diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2003-10-25 18:32:20 +0000 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2003-10-25 18:32:20 +0000 |
commit | 219136f6e6317bb955ecf50ee4c6a10c691e0693 (patch) | |
tree | 67cf491f2cf7e55a40b32720ae366244319d695e | |
parent | 0fba2d908da6d0df821991ea5fdbeeda0f4ff089 (diff) | |
download | gnutls-219136f6e6317bb955ecf50ee4c6a10c691e0693.tar.gz |
Added a certtool primitive command line utility
-rw-r--r-- | lib/x509/privkey_pkcs8.c | 23 | ||||
-rw-r--r-- | src/Makefile.am | 9 | ||||
-rw-r--r-- | src/certtool-gaa.c | 789 | ||||
-rw-r--r-- | src/certtool-gaa.h | 37 | ||||
-rw-r--r-- | src/certtool.c | 400 | ||||
-rw-r--r-- | src/certtool.gaa | 21 | ||||
-rw-r--r-- | src/common.c | 4 |
7 files changed, 1266 insertions, 17 deletions
diff --git a/lib/x509/privkey_pkcs8.c b/lib/x509/privkey_pkcs8.c index c2c2e9cd32..0d373cc1f8 100644 --- a/lib/x509/privkey_pkcs8.c +++ b/lib/x509/privkey_pkcs8.c @@ -424,8 +424,18 @@ int gnutls_x509_privkey_export_pkcs8(gnutls_x509_privkey key, schema = PBES2; - if (!(flags & GNUTLS_PKCS8_PLAIN) || password == NULL) { + if ((flags & GNUTLS_PKCS8_PLAIN) || password == NULL) + { + _gnutls_free_datum(&tmp); + + ret = + _gnutls_x509_export_int(pkey_info, format, + PEM_UNENCRYPTED_PKCS8, + *output_data_size, output_data, + output_data_size); + asn1_delete_structure(&pkey_info); + } else { asn1_delete_structure(&pkey_info); /* we don't need it */ ret = encode_to_pkcs8_key(schema, &tmp, password, &pkcs8_asn); @@ -442,17 +452,6 @@ int gnutls_x509_privkey_export_pkcs8(gnutls_x509_privkey key, output_data_size); asn1_delete_structure(&pkcs8_asn); - - } else { - _gnutls_free_datum(&tmp); - - ret = - _gnutls_x509_export_int(pkey_info, format, - PEM_UNENCRYPTED_PKCS8, - *output_data_size, output_data, - output_data_size); - - asn1_delete_structure(&pkey_info); } return ret; diff --git a/src/Makefile.am b/src/Makefile.am index a5fd2e7393..7be501984f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,11 +1,11 @@ EXTRA_DIST = common.h prime.gaa crypt.gaa crypt-gaa.h README.srpcrypt prime-gaa.h \ README cli.gaa cli-gaa.h serv-gaa.h serv.gaa tls_test.gaa \ - tls_test-gaa.h tests.h gnutls-http-serv list.h + tls_test-gaa.h tests.h gnutls-http-serv list.h certtool-gaa.h SUBDIRS = srp x509 openpgp INCLUDES = -I../lib -I../libtasn1/lib -I../includes -bin_PROGRAMS = gnutls-serv gnutls-cli gnutls-srpcrypt gnutls-cli-debug +bin_PROGRAMS = gnutls-serv gnutls-cli gnutls-srpcrypt gnutls-cli-debug certtool gnutls_serv_SOURCES = serv-gaa.c serv.c common.c gnutls_serv_LDADD = ../lib/libgnutls.la ../libextra/libgnutls-extra.la $(LIBGCRYPT_LIBS) $(LIBOPENCDK_LIBS) $(SERV_LIBS) gnutls_srpcrypt_SOURCES = crypt-gaa.c crypt.c @@ -14,7 +14,8 @@ gnutls_cli_SOURCES = cli-gaa.c cli.c common.c gnutls_cli_LDADD = ../lib/libgnutls.la ../libextra/libgnutls-extra.la $(LIBGCRYPT_LIBS) $(LIBOPENCDK_LIBS) gnutls_cli_debug_SOURCES = tls_test-gaa.c tls_test.c tests.c common.c gnutls_cli_debug_LDADD = ../lib/libgnutls.la ../libextra/libgnutls-extra.la $(LIBGCRYPT_LIBS) $(LIBOPENCDK_LIBS) - +certtool_SOURCES = certtool-gaa.c certtool.c +certtool_LDADD = ../lib/libgnutls.la $(LIBGCRYPT_LIBS) noinst_PROGRAMS = prime retcodes @@ -28,6 +29,8 @@ crypt-gaa.c: crypt.gaa -gaa crypt.gaa -o crypt-gaa.c -i crypt-gaa.h prime-gaa.c: prime.gaa -gaa prime.gaa -o prime-gaa.c -i prime-gaa.h +certtool-gaa.c: certtool.gaa + -gaa certtool.gaa -o certtool-gaa.c -i certtool-gaa.h cli-gaa.c: cli.gaa -gaa cli.gaa -o cli-gaa.c -i cli-gaa.h tls_test-gaa.c: tls_test.gaa diff --git a/src/certtool-gaa.c b/src/certtool-gaa.c new file mode 100644 index 0000000000..c08a70accb --- /dev/null +++ b/src/certtool-gaa.c @@ -0,0 +1,789 @@ +/* File generated by GAA 1.6.2 + */ +#define GAA_NO_WIN32 +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#ifndef GAA_NO_WIN32 +#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(WINDOWS) +#define GAA_WIN32 +#endif +#endif + +void* gaa_malloc( size_t size) { +void* ret; + ret = malloc(size); + if (ret==NULL) { + fprintf(stderr, "gaa: could not allocate memory"); + exit(1); + } + return ret; +} + +void __gaa_helpsingle(char short_name, char *name, + char *arg_desc, char *opt_help) +{ + int col1, col3, col4, tabsize = 3, curr; + int i; + + col1 = 5; /* Default values */ + col3 = 30; + col4 = 70; + + curr = 0; + for(i = 0; i < col1; i++) + { + printf(" "); + curr++; + } + if(short_name) + { + if(name && *name) + { + printf("-%c, ", short_name); + curr += 4; + } + else + { + printf("-%c ", short_name); + curr += 3; + } + } + if(name && *name) + { + printf("--%s ", name); + curr += 3 + strlen(name); + } + if(arg_desc && *arg_desc) + { + printf("%s ", arg_desc); + curr += 1 + strlen(arg_desc); + } + if(curr >= col3) + { + printf("\n"); + curr = 0; + } + if(opt_help) /* let's print the option's help body */ + { + const char *str = opt_help; + while(*str) + { + while(curr < col3) + { + printf(" "); + curr++; + } + switch(*str) + { + case '\n': + printf("\n"); + curr = 0; + break; + case '\t': + do + { + printf(" "); + curr++; + } + while((curr - col3) % tabsize != 0 && curr < col4); + case ' ': + if(*str == ' ') + { + curr++; + printf(" "); + } + for(i = 1; str[i] && str[i] != ' ' && str[i] != '\n' + && str[i] != '\t'; i++); + if(curr + i - 1 >= col4) + curr = col4; + break; + default: + printf("%c", *str); + curr++; + } + if(curr >= col4) + { + printf("\n"); + curr = 0; + } + str++; + } + } + printf("\n"); +} + +void gaa_help(void) +{ + printf("Certtool help\nUsage : certtool [options]\n"); + __gaa_helpsingle('s', "generate-self-signed", "", "Generate a self-signed certificate."); + __gaa_helpsingle('p', "generate-privkey", "", "Generate a private key."); + __gaa_helpsingle('i', "cert-info", "", "Print information on a certificate."); + __gaa_helpsingle('8', "pkcs8", "", "Use PKCS #8 format for private keys."); + __gaa_helpsingle(0, "bits", "BITS ", "specify the number of bits for key generation."); + __gaa_helpsingle('h', "help", "", "shows this help text"); + __gaa_helpsingle('v', "version", "", "shows the program version"); + +#line 100 "gaa.skel" +} +/* Copy of C area */ + +#line 104 "gaa.skel" +/* GAA HEADER */ +#ifndef GAA_HEADER_POKY +#define GAA_HEADER_POKY + +typedef struct _gaainfo gaainfo; + +struct _gaainfo +{ +#line 13 "certtool.gaa" + int bits; +#line 10 "certtool.gaa" + int pkcs8; +#line 3 "certtool.gaa" + int action; + +#line 114 "gaa.skel" +}; + +#ifdef __cplusplus +extern "C" +{ +#endif + + int gaa(int argc, char *argv[], gaainfo *gaaval); + + void gaa_help(void); + + int gaa_file(char *name, gaainfo *gaaval); + +#ifdef __cplusplus +} +#endif + + +#endif + +#line 135 "gaa.skel" + +/* C declarations */ + +#define GAAERROR(x) \ +{ \ +gaa_error = 1; \ +return x; \ +} + +char *gaa_current_option; +int gaa_error = 0; + +/* Generated by gaa */ + +#include <string.h> +#include <stdlib.h> + + +#define GAA_OK -1 + +#define GAA_ERROR_NOMATCH 0 +#define GAA_ERROR_NOTENOUGH_ARGS 1 +#define GAA_ERROR_INVALID_ARG 2 +#define GAA_ERROR_UNKNOWN 3 + +#define GAA_NOT_AN_OPTION 0 +#define GAA_WORD_OPTION 1 +#define GAA_LETTER_OPTION 2 +#define GAA_MULTIPLE_OPTION 3 + +#define GAA_REST 0 +#define GAA_NB_OPTION 7 +#define GAAOPTID_version 1 +#define GAAOPTID_help 2 +#define GAAOPTID_bits 3 +#define GAAOPTID_pkcs8 4 +#define GAAOPTID_cert_info 5 +#define GAAOPTID_generate_privkey 6 +#define GAAOPTID_generate_self_signed 7 + +#line 168 "gaa.skel" + +#define GAA_CHECK1STR(a,b) \ +if(a[0] == str[0]) \ +{ \ + gaa_current_option = a; \ + return b; \ +} + +#define GAA_CHECKSTR(a,b) \ +if(strcmp(a,str) == 0) \ +{ \ + gaa_current_option = a; \ + return b; \ +} + +#define GAA_TESTMOREARGS \ +if(!OK) \ +{ \ +while((gaa_last_non_option != gaa_index) && (gaa_arg_used[gaa_index] == 1)) \ + gaa_index++; \ +if(gaa_last_non_option == gaa_index) \ + return GAA_ERROR_NOTENOUGH_ARGS; \ +} + +#define GAA_TESTMOREOPTIONALARGS \ +if(!OK) \ +{ \ +while((gaa_last_non_option != gaa_index) && (gaa_arg_used[gaa_index] == 1)) \ + gaa_index++; \ +if(gaa_last_non_option == gaa_index) \ + OK = 1; \ +} + +#define GAA_FILL_2ARGS(target, func) \ +target = func(GAAargv[gaa_index]); \ +gaa_arg_used[gaa_index] = 1; \ +if(gaa_error == 1) \ +{ \ + gaa_error = 0; \ + return GAA_ERROR_INVALID_ARG; \ +} + + + +#define GAA_FILL(target, func, num) \ +if(!OK) \ +{ \ +target = func(GAAargv[gaa_index]); \ +gaa_arg_used[gaa_index] = 1; \ +if(gaa_error == 1) \ +{ \ + gaa_error = 0; \ + return GAA_ERROR_INVALID_ARG; \ +} \ +num = 1; \ +} \ +else \ +{ \ +num = 0; \ +} + +#define GAA_LIST_FILL(target, func, type ,num) \ +if(!OK) \ +{ \ +num = 0; \ +target = NULL; \ +if ( gaa_last_non_option - gaa_index > 0) \ + target = gaa_malloc((gaa_last_non_option - gaa_index) * sizeof(type));\ +for(; gaa_index < gaa_last_non_option; gaa_index++) \ +{ \ + if(gaa_arg_used[gaa_index] == 0) \ + { \ + GAA_FILL_2ARGS(target[num], func); \ + num++; \ + } \ +} \ +if(num == 0) \ + return GAA_ERROR_NOTENOUGH_ARGS; \ +} + +#define GAA_OPTIONALLIST_FILL(target, func, type ,num) \ +if(!OK) \ +{ \ +num = 0; \ +target = NULL; \ +if ( gaa_last_non_option - gaa_index > 0) \ + target = gaa_malloc((gaa_last_non_option - gaa_index) * sizeof(type));\ +for(; gaa_index < gaa_last_non_option; gaa_index++) \ +{ \ + if(gaa_arg_used[gaa_index] == 0) \ + { \ + GAA_FILL_2ARGS(target[num], func); \ + num++; \ + } \ +} \ +} + +#define GAA_OBLIGAT(str) \ +k = 0; \ +for(i = 0; i < strlen(str); i++) \ +{ \ + j = gaa_get_option_num(str + i, GAA_LETTER_OPTION); \ + if(j == GAA_ERROR_NOMATCH) \ + { \ + printf("Error: invalid 'obligat' set\n"); \ + exit(-1); \ + } \ + if(opt_list[j] == 1) \ + k = 1; \ +} \ +if(k == 0) \ +{ \ + if(strlen(str) == 1) \ + printf("You must give the -%s option\n", str); \ + else \ + printf("You must give at least one option of '%s'\n", str); \ + return 0; \ +} + +#define GAA_INCOMP(str) \ +k = 0; \ +for(i = 0; i < strlen(str); i++) \ +{ \ + j = gaa_get_option_num(str + i, GAA_LETTER_OPTION); \ + if(j == GAA_ERROR_NOMATCH) \ + { \ + printf("Error: invalid 'obligat' set\n"); \ + exit(-1); \ + } \ + if(opt_list[j] == 1) \ + k++; \ +} \ +if(k > 1) \ +{ \ + printf("The options '%s' are incompatible\n", str); \ + return 0; \ +} + + +char **GAAargv; +int GAAargc; +char *gaa_arg_used; +int gaa_processing_file = 0; +int inited = 0; + +int gaa_getint(char *arg) +{ + int tmp; + char a; + if(sscanf(arg, "%d%c", &tmp, &a) != 1) + { + printf("Option %s: '%s' isn't an integer\n", gaa_current_option, arg); + GAAERROR(-1); + } + return tmp; +} + +char gaa_getchar(char *arg) +{ + if(strlen(arg) != 1) + { + printf("Option %s: '%s' isn't an character\n", gaa_current_option, arg); + GAAERROR(-1); + } + return arg[0]; +} + +char* gaa_getstr(char *arg) +{ + return arg; +} +float gaa_getfloat(char *arg) +{ + float tmp; + char a; + if(sscanf(arg, "%f%c", &tmp, &a) != 1) + { + printf("Option %s: '%s' isn't a float number\n", gaa_current_option, arg); + GAAERROR(-1); + } + return tmp; +} +/* option structures */ + +struct GAAOPTION_bits +{ + int arg1; + int size1; +}; + +#line 349 "gaa.skel" +int gaa_is_an_argument(char *str) +{ +#ifdef GAA_WIN32 + if(str[0] == '/' && str[1] != 0) + return GAA_MULTIPLE_OPTION; +#endif + if(str[0] != '-') + return GAA_NOT_AN_OPTION; + if(str[1] == 0) + return GAA_NOT_AN_OPTION; + if(str[1] == '-') + { + if(str[2] != 0) + return GAA_WORD_OPTION; + else + return GAA_NOT_AN_OPTION; + } + if(str[2] == 0) + return GAA_LETTER_OPTION; + else + return GAA_MULTIPLE_OPTION; +} + +int gaa_get_option_num(char *str, int status) +{ + switch(status) + { + case GAA_LETTER_OPTION: + GAA_CHECK1STR("", GAAOPTID_bits); + case GAA_MULTIPLE_OPTION: +#line 375 "gaa.skel" + GAA_CHECK1STR("v", GAAOPTID_version); + GAA_CHECK1STR("h", GAAOPTID_help); + GAA_CHECK1STR("8", GAAOPTID_pkcs8); + GAA_CHECK1STR("i", GAAOPTID_cert_info); + GAA_CHECK1STR("p", GAAOPTID_generate_privkey); + GAA_CHECK1STR("s", GAAOPTID_generate_self_signed); + +#line 277 "gaa.skel" + break; + case GAA_WORD_OPTION: + GAA_CHECKSTR("version", GAAOPTID_version); + GAA_CHECKSTR("help", GAAOPTID_help); + GAA_CHECKSTR("bits", GAAOPTID_bits); + GAA_CHECKSTR("pkcs8", GAAOPTID_pkcs8); + GAA_CHECKSTR("cert-info", GAAOPTID_cert_info); + GAA_CHECKSTR("generate-privkey", GAAOPTID_generate_privkey); + GAA_CHECKSTR("generate-self-signed", GAAOPTID_generate_self_signed); + +#line 281 "gaa.skel" + break; + default: break; + } + return GAA_ERROR_NOMATCH; +} + +int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) +{ + int OK = 0; + int gaa_last_non_option; + struct GAAOPTION_bits GAATMP_bits; + +#line 393 "gaa.skel" +#ifdef GAA_REST_EXISTS + struct GAAREST GAAREST_tmp; +#endif + + opt_list[gaa_num] = 1; + + for(gaa_last_non_option = gaa_index; + (gaa_last_non_option != GAAargc) && (gaa_is_an_argument(GAAargv[gaa_last_non_option]) == GAA_NOT_AN_OPTION); + gaa_last_non_option++); + + if(gaa_num == GAA_REST) + { + gaa_index = 1; + gaa_last_non_option = GAAargc; + } + + switch(gaa_num) + { + case GAAOPTID_version: + OK = 0; +#line 18 "certtool.gaa" +{ certtool_version(); exit(0); ;}; + + return GAA_OK; + break; + case GAAOPTID_help: + OK = 0; +#line 16 "certtool.gaa" +{ gaa_help(); exit(0); ;}; + + return GAA_OK; + break; + case GAAOPTID_bits: + OK = 0; + GAA_TESTMOREARGS; + GAA_FILL(GAATMP_bits.arg1, gaa_getint, GAATMP_bits.size1); + gaa_index++; +#line 14 "certtool.gaa" +{ gaaval->bits = GAATMP_bits.arg1 ;}; + + return GAA_OK; + break; + case GAAOPTID_pkcs8: + OK = 0; +#line 11 "certtool.gaa" +{ gaaval->pkcs8=1 ;}; + + return GAA_OK; + break; + case GAAOPTID_cert_info: + OK = 0; +#line 8 "certtool.gaa" +{ gaaval->action = 2; ;}; + + return GAA_OK; + break; + case GAAOPTID_generate_privkey: + OK = 0; +#line 6 "certtool.gaa" +{ gaaval->action=1; ;}; + + return GAA_OK; + break; + case GAAOPTID_generate_self_signed: + OK = 0; +#line 4 "certtool.gaa" +{ gaaval->action=0; ;}; + + return GAA_OK; + break; + +#line 413 "gaa.skel" + default: break; + } + return GAA_ERROR_UNKNOWN; +} + +int gaa(int argc, char **argv, gaainfo *gaaval) +{ + int tmp1, tmp2; + int i, j; + char *opt_list; + + GAAargv = argv; + GAAargc = argc; + + opt_list = (char*) gaa_malloc(GAA_NB_OPTION + 1); + + for(i = 0; i < GAA_NB_OPTION + 1; i++) + opt_list[i] = 0; + /* initialization */ + if(inited == 0) + { + +#line 20 "certtool.gaa" +{ gaaval->bits = 1024; gaaval->pkcs8 = 0;;}; + + } + inited = 1; +#line 438 "gaa.skel" + gaa_arg_used = NULL; + + if (argc > 0) { + gaa_arg_used = gaa_malloc(argc * sizeof(char)); + } + + for(i = 1; i < argc; i++) + gaa_arg_used[i] = 0; + for(i = 1; i < argc; i++) + { + if(gaa_arg_used[i] == 0) + { + j = 0; + tmp1 = gaa_is_an_argument(GAAargv[i]); + switch(tmp1) + { + case GAA_WORD_OPTION: + j++; + case GAA_LETTER_OPTION: + j++; + tmp2 = gaa_get_option_num(argv[i]+j, tmp1); + if(tmp2 == GAA_ERROR_NOMATCH) + { + printf("Invalid option '%s'\n", argv[i]+j); + return 0; + } + switch(gaa_try(tmp2, i+1, gaaval, opt_list)) + { + case GAA_ERROR_NOTENOUGH_ARGS: + printf("'%s': not enough arguments\n",gaa_current_option); + return 0; + case GAA_ERROR_INVALID_ARG: + printf("Invalid arguments\n"); + return 0; + case GAA_OK: + break; + default: + printf("Unknown error\n"); + } + gaa_arg_used[i] = 1; + break; + case GAA_MULTIPLE_OPTION: + for(j = 1; j < strlen(argv[i]); j++) + { + tmp2 = gaa_get_option_num(argv[i]+j, tmp1); + if(tmp2 == GAA_ERROR_NOMATCH) + { + printf("Invalid option '%c'\n", *(argv[i]+j)); + return 0; + } + switch(gaa_try(tmp2, i+1, gaaval, opt_list)) + { + case GAA_ERROR_NOTENOUGH_ARGS: + printf("'%s': not enough arguments\n",gaa_current_option); + return 0; + case GAA_ERROR_INVALID_ARG: + printf("Invalid arguments\n"); + return 0; + case GAA_OK: + break; + default: + printf("Unknown error\n"); + } + } + gaa_arg_used[i] = 1; + break; + default: break; + } + } + } +if(gaa_processing_file == 0) +{ + +#line 507 "gaa.skel" +#ifdef GAA_REST_EXISTS + switch(gaa_try(GAA_REST, 1, gaaval, opt_list)) + { + case GAA_ERROR_NOTENOUGH_ARGS: + printf("Rest: not enough arguments\n"); + return 0; + case GAA_ERROR_INVALID_ARG: + printf("Invalid arguments\n"); + return 0; + case GAA_OK: + break; + default: + printf("Unknown error\n"); + } +#endif +} + for(i = 1; i < argc; i++) + { + if(gaa_arg_used[i] == 0) + { + printf("Too many arguments\n"); + return 0; + } + } + free(gaa_arg_used); + free(opt_list); + return -1; +} + +struct gaastrnode +{ + char *str; + struct gaastrnode *next; +}; + +typedef struct gaastrnode gaa_str_node; + +int gaa_internal_get_next_str(FILE *file, gaa_str_node *tmp_str, int argc) +{ + int pos_ini; + char a; + int i = 0, len = 0, newline = 0; + + if(argc == 1) { + newline = 1; + len = 2; + } + + if(fscanf(file,"%c", &a) != 1) return 0; + + while(a == ' ' || a == 9 || a == '\n') + { + if(a == '\n') + { + newline=1; + len = 2; + } + if(fscanf(file,"%c", &a) != 1) return 0; + } + + pos_ini = ftell(file) - 1; + + while(a != ' ' && a != 9 && a != '\n') + { + + len++; + if(fscanf(file,"%c", &a) != 1) a = ' '; + } + + len += 1; + tmp_str->str = gaa_malloc((len) * sizeof(char)); + + if(newline == 1) + { + tmp_str->str[0] = '-'; + tmp_str->str[1] = '-'; + i = 2; + } + else + { + i = 0; + } + + fseek(file,pos_ini, SEEK_SET); + do + { + if(fscanf(file, "%c", &a) != 1) + { + i+=2; + break; + } + tmp_str->str[i] = a; + i++; + } + while(a != ' ' && a != 9 && a != '\n' && i < len); + + tmp_str->str[i - 1] = 0; + + fseek(file,- 1, SEEK_CUR); +/* printf("%d\n", ftell(file)); */ + + return -1; +} + +int gaa_file(char *name, gaainfo *gaaval) +{ + gaa_str_node *first_str, **tmp_str, *tmp_str2; + int rval, i; + char **argv; + int argc = 0; + FILE *file; + + gaa_processing_file = 1; + + if((file = fopen(name, "r")) == NULL) + { + printf("Couldn't open '%s' configuration file for reading\n", name); + return 0; + } + + tmp_str = &first_str; + do + { + argc++; + *tmp_str = gaa_malloc(sizeof(gaa_str_node)); + + (*tmp_str)->str = NULL; + (*tmp_str)->next = NULL; + + rval = gaa_internal_get_next_str(file, *tmp_str, argc); + tmp_str = &((*tmp_str)->next); + } + while(rval == -1); + + if(rval == 1) + return 0; + + argv = gaa_malloc((1 + argc) * sizeof(char*)); + + tmp_str2 = first_str; + argv[0] = "cfg"; + for(i = 1; i < argc; i++) + { + argv[i] = tmp_str2->str; + tmp_str2 = tmp_str2->next; + } + + rval = gaa(argc, argv, gaaval); + gaa_processing_file = 0; + return rval; +} diff --git a/src/certtool-gaa.h b/src/certtool-gaa.h new file mode 100644 index 0000000000..e4aba13d70 --- /dev/null +++ b/src/certtool-gaa.h @@ -0,0 +1,37 @@ + +#line 104 "gaa.skel" +/* GAA HEADER */ +#ifndef GAA_HEADER_POKY +#define GAA_HEADER_POKY + +typedef struct _gaainfo gaainfo; + +struct _gaainfo +{ +#line 13 "certtool.gaa" + int bits; +#line 10 "certtool.gaa" + int pkcs8; +#line 3 "certtool.gaa" + int action; + +#line 114 "gaa.skel" +}; + +#ifdef __cplusplus +extern "C" +{ +#endif + + int gaa(int argc, char *argv[], gaainfo *gaaval); + + void gaa_help(void); + + int gaa_file(char *name, gaainfo *gaaval); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/src/certtool.c b/src/certtool.c new file mode 100644 index 0000000000..b38b3063af --- /dev/null +++ b/src/certtool.c @@ -0,0 +1,400 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <gnutls/gnutls.h> +#include <gnutls/x509.h> +#include <time.h> +#include "certtool-gaa.h" + +void certificate_info( void); +static void gaa_parser(int argc, char **argv); +void generate_self_signed( void); +static gaainfo info; + +static unsigned char buffer[10*1024]; +static const int buffer_size = sizeof(buffer); + +static void tls_log_func( int level, const char* str) +{ + fprintf(stderr, "|<%d>| %s", level, str); +} + +int main(int argc, char** argv) +{ + gnutls_global_init(); + gnutls_global_set_log_function( tls_log_func); + gnutls_global_set_log_level(2); + + gaa_parser(argc, argv); + + return 0; +} + + + +static void read_set( gnutls_x509_crt crt, const char* input_str, const char* oid) +{ +char input[128]; +int ret; + + fputs( input_str, stderr); + fgets( input, sizeof(input), stdin); + + if (strlen(input)==1) /* only newline */ return; + + ret = gnutls_x509_crt_set_dn_by_oid(crt, oid, input, strlen(input)-1); + if (ret < 0) { + fprintf(stderr, "set_dn: %s\n", gnutls_strerror(ret)); + exit(1); + } +} + +static int read_int( const char* input_str) +{ +char input[128]; + + fputs( input_str, stderr); + fgets( input, sizeof(input), stdin); + + if (strlen(input)==1) /* only newline */ return 0; + + return atoi(input); +} + +static const char* read_str( const char* input_str) +{ +static char input[128]; + + fputs( input_str, stderr); + fgets( input, sizeof(input), stdin); + + input[strlen(input)-1] = 0; + + if (strlen(input)==0) return NULL; + + return input; +} + +static int read_yesno( const char* input_str) +{ +char input[128]; + + fputs( input_str, stderr); + fgets( input, sizeof(input), stdin); + + if (strlen(input)==1) /* only newline */ return 0; + + if (input[0] == 'y' || input[0] == 'Y') return 1; + + return 0; +} + +static gnutls_x509_privkey generate_private_key_int( void) +{ +gnutls_x509_privkey key; +int ret; + + ret = gnutls_x509_privkey_init(&key); + if (ret < 0) { + fprintf(stderr, "privkey_init: %s\n", gnutls_strerror(ret)); + exit(1); + } + + fprintf(stderr, "Generating a %d bit RSA private key...\n", info.bits); + ret = gnutls_x509_privkey_generate( key, GNUTLS_PK_RSA, info.bits, 0); + if (ret < 0) { + fprintf(stderr, "privkey_generate: %s\n", gnutls_strerror(ret)); + exit(1); + } + + return key; + +} + +static void print_private_key( gnutls_x509_privkey key) +{ +int size, ret; + + if (!info.pkcs8) { + size = sizeof(buffer); + ret = gnutls_x509_privkey_export( key, GNUTLS_X509_FMT_PEM, buffer, &size); + if (ret < 0) { + fprintf(stderr, "privkey_export: %s\n", gnutls_strerror(ret)); + exit(1); + } + } else { + size = sizeof(buffer); + ret = gnutls_x509_privkey_export_pkcs8( key, GNUTLS_X509_FMT_PEM, NULL, GNUTLS_PKCS8_PLAIN, buffer, &size); + if (ret < 0) { + fprintf(stderr, "privkey_export_pkcs8: %s\n", gnutls_strerror(ret)); + exit(1); + } + } + + printf("Private key: \n%s\n", buffer); +} + +void generate_private_key( void) +{ +gnutls_x509_privkey key; + + key = generate_private_key_int(); + + print_private_key( key); + + gnutls_x509_privkey_deinit(key); +} + + +void generate_self_signed( void) +{ + gnutls_x509_crt crt; + gnutls_x509_privkey key; + int size, serial; + int days, result, ca_status; + const char* str; + + size = gnutls_x509_crt_init(&crt); + if (size < 0) { + fprintf(stderr, "crt_init: %s\n", gnutls_strerror(size)); + exit(1); + } + + key = generate_private_key_int(); + + fprintf(stderr, "Please enter the details of the certificate's distinguished name. " + "Just press enter to ignore a field.\n"); + + read_set( crt, "Country name (2 chars): ", GNUTLS_OID_X520_COUNTRY_NAME); + read_set( crt, "Organization name: ", GNUTLS_OID_X520_ORGANIZATION_NAME); + read_set( crt, "Organizational unit name: ", GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME); + read_set( crt, "Locality name: ", GNUTLS_OID_X520_LOCALITY_NAME); + read_set( crt, "State or province name: ", GNUTLS_OID_X520_LOCALITY_NAME); + read_set( crt, "Common name: ", GNUTLS_OID_X520_COMMON_NAME); + + fprintf(stderr, "This field should not be used in new certificates.\n"); + read_set( crt, "E-mail: ", GNUTLS_OID_PKCS9_EMAIL); + + size = gnutls_x509_crt_set_version( crt, 2); + if (size < 0) { + fprintf(stderr, "set_version: %s\n", gnutls_strerror(size)); + exit(1); + } + + serial = read_int( "Enter the certificate's serial number: "); + buffer[2] = serial & 0xff; + buffer[1] = (serial >> 8) & 0xff; + buffer[0] = (serial >> 16) & 0xff; + + result = gnutls_x509_crt_set_serial( crt, buffer, 3); + if (result < 0) { + fprintf(stderr, "serial: %s\n", gnutls_strerror(result)); + exit(1); + } + + + size = gnutls_x509_crt_set_key( crt, key); + if (size < 0) { + fprintf(stderr, "set_key: %s\n", gnutls_strerror(size)); + exit(1); + } + + fprintf(stderr, "\n\nActivation/Expiration time.\n"); + gnutls_x509_crt_set_activation_time( crt, time(NULL)); + + do { + days = read_int( "The generated certificate will expire in (days): "); + } while( days==0); + + result = gnutls_x509_crt_set_expiration_time( crt, time(NULL)+days*24*60*60); + if (result < 0) { + fprintf(stderr, "serial: %s\n", gnutls_strerror(result)); + exit(1); + } + + + fprintf(stderr, "\n\nExtensions.\n"); + + ca_status = read_yesno( "Does the certificate belong to an authority? (Y/N): "); + + result = gnutls_x509_crt_set_ca_status( crt, ca_status); + if (result < 0) { + fprintf(stderr, "ca_status: %s\n", gnutls_strerror(result)); + exit(1); + } + + result = read_yesno( "Is this a server certificate? (Y/N): "); + if (result != 0) { + str = read_str( "Enter the dnsName of the subject of the certificate: "); + if (str != NULL) { + result = gnutls_x509_crt_set_subject_alternative_name( crt, GNUTLS_SAN_DNSNAME, str); + if (result < 0) { + fprintf(stderr, "subject_alt_name: %s\n", gnutls_strerror(result)); + exit(1); + } + } + } else { + + str = read_str( "Enter the e-mail of the subject of the certificate: "); + + if (str != NULL) { + result = gnutls_x509_crt_set_subject_alternative_name( crt, GNUTLS_SAN_RFC822NAME, str); + if (result < 0) { + fprintf(stderr, "subject_alt_name: %s\n", gnutls_strerror(result)); + exit(1); + } + } + } + + fprintf(stderr, "\n\nSigning certificate...\n"); + + result = gnutls_x509_crt_sign( crt, crt, key); + if (result < 0) { + fprintf(stderr, "crt_sign: %s\n", gnutls_strerror(result)); + exit(1); + } + + print_private_key( key); + + + size = sizeof(buffer); + result = gnutls_x509_crt_export( crt, GNUTLS_X509_FMT_PEM, buffer, &size); + if (result < 0) { + fprintf(stderr, "crt_export: %s\n", gnutls_strerror(result)); + exit(1); + } + + printf("Certificate: \n%s", buffer); + + + gnutls_x509_crt_deinit(crt); + gnutls_x509_privkey_deinit(key); + +} + +void gaa_parser(int argc, char **argv) +{ + if (gaa(argc, argv, &info) != -1) { + fprintf(stderr, + "Error in the arguments. Use the --help or -h parameters to get more information.\n"); + exit(1); + } + + switch( info.action) { + case 0: + generate_self_signed(); + return; + case 1: + generate_private_key(); + return; + case 2: + certificate_info(); + return; + } +} + +void certtool_version(void) +{ + fprintf(stderr, "certtool, "); + fprintf(stderr, "version %s. Libgnutls %s.\n", LIBGNUTLS_VERSION, + gnutls_check_version(NULL)); +} + +void certificate_info( void) +{ + gnutls_x509_crt crt; + int size, ret, i; + time_t tim; + gnutls_datum pem; + char serial[40]; + size_t serial_size = sizeof(serial), dn_size; + char printable[256]; + char *print; + char dn[256]; + + size = fread( buffer, 1, sizeof(buffer)-1, stdin); + buffer[size] = 0; + + gnutls_x509_crt_init(&crt); + + pem.data = buffer; + pem.size = size; + + ret = gnutls_x509_crt_import(crt, &pem, GNUTLS_X509_FMT_PEM); + if (ret < 0) { + fprintf(stderr, "Decoding error: %s\n", gnutls_strerror(ret)); + exit(1); + } + + printf("Version: %d\n", gnutls_x509_crt_get_version(crt)); + + /* serial number + */ + if (gnutls_x509_crt_get_serial(crt, serial, &serial_size) >= 0) { + print = printable; + for (i = 0; i < serial_size; i++) { + sprintf(print, "%.2x ", + (unsigned char) serial[i]); + print += 3; + } + printf("Serial Number: %s\n", printable); + } + + /* Issuer + */ + dn_size = sizeof(dn); + + ret = gnutls_x509_crt_get_issuer_dn(crt, dn, &dn_size); + if (ret >= 0) + printf("Issuer: %s\n", dn); + + printf("Signature Algorithm: "); + ret = gnutls_x509_crt_get_signature_algorithm(crt); + switch(ret) { + case GNUTLS_PK_RSA: + printf("RSA\n"); + break; + case GNUTLS_PK_DSA: + printf("DSA\n"); + break; + default: + printf("UNKNOWN\n"); + break; + } + + /* Validity + */ + printf("Validity\n"); + + tim = gnutls_x509_crt_get_activation_time(crt); + printf("\tNot Before: %s", ctime(&tim)); + + tim = gnutls_x509_crt_get_expiration_time(crt); + printf("\tNot After: %s", ctime(&tim)); + + /* Subject + */ + dn_size = sizeof(dn); + ret = gnutls_x509_crt_get_dn(crt, dn, &dn_size); + if (ret >= 0) + printf("Subject: %s\n", dn); + + /* Public key algorithm + */ + printf("Subject Public Key Info:\n"); + ret = gnutls_x509_crt_get_pk_algorithm(crt, NULL); + printf("\tPublic Key Algorithm: "); + + switch(ret) { + case GNUTLS_PK_RSA: + printf("RSA\n"); + break; + case GNUTLS_PK_DSA: + printf("DSA\n"); + break; + default: + printf("UNKNOWN\n"); + break; + } + +} diff --git a/src/certtool.gaa b/src/certtool.gaa new file mode 100644 index 0000000000..1e7ba7651f --- /dev/null +++ b/src/certtool.gaa @@ -0,0 +1,21 @@ +helpnode "Certtool help\nUsage : certtool [options]" + +#int action; +option (s, generate-self-signed) { $action=0; } "Generate a self-signed certificate." + +option (p, generate-privkey) { $action=1; } "Generate a private key." + +option (i, cert-info) { $action = 2; } "Print information on a certificate." + +#int pkcs8; +option (8, pkcs8) { $pkcs8=1 } "Use PKCS #8 format for private keys." + +#int bits; +option (bits) INT "BITS" { $bits = $1 } "specify the number of bits for key generation." + +option (h, help) { gaa_help(); exit(0); } "shows this help text" + +option (v, version) { certtool_version(); exit(0); } "shows the program version" + +init { $bits = 1024; $pkcs8 = 0;} + diff --git a/src/common.c b/src/common.c index 70e42f9a0a..38544bcb79 100644 --- a/src/common.c +++ b/src/common.c @@ -38,10 +38,10 @@ void print_x509_info(gnutls_session session, const char* hostname) char digest[20]; char serial[40]; char dn[256]; - int dn_size; + size_t dn_size; size_t digest_size = sizeof(digest); int i, j; - int serial_size = sizeof(serial); + size_t serial_size = sizeof(serial); char printable[256]; char *print; int bits, algo; |