summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/x509/privkey_pkcs8.c23
-rw-r--r--src/Makefile.am9
-rw-r--r--src/certtool-gaa.c789
-rw-r--r--src/certtool-gaa.h37
-rw-r--r--src/certtool.c400
-rw-r--r--src/certtool.gaa21
-rw-r--r--src/common.c4
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;