2 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Free Software Foundation
4 * This file is part of GNUTLS.
6 * GNUTLS is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GNUTLS is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include <certtool-cfg.h>
26 #include <gnutls/x509.h>
32 /* Gnulib portability files. */
38 typedef struct _cfg_ctx
46 char *challenge_password
;
53 char *crl_dist_points
;
55 char *pkcs12_key_name
;
68 int time_stamping_key
;
70 char *proxy_policy_language
;
78 memset (&cfg
, 0, sizeof (cfg
));
84 template_parse (const char *template)
86 /* libcfg+ parsing context */
89 /* Parsing return code */
92 /* Option variables */
95 struct cfg_option options
[] = {
96 {NULL
, '\0', "organization", CFG_STR
, (void *) &cfg
.organization
,
98 {NULL
, '\0', "unit", CFG_STR
, (void *) &cfg
.unit
, 0},
99 {NULL
, '\0', "locality", CFG_STR
, (void *) &cfg
.locality
, 0},
100 {NULL
, '\0', "state", CFG_STR
, (void *) &cfg
.state
, 0},
101 {NULL
, '\0', "cn", CFG_STR
, (void *) &cfg
.cn
, 0},
102 {NULL
, '\0', "uid", CFG_STR
, (void *) &cfg
.uid
, 0},
103 {NULL
, '\0', "challenge_password", CFG_STR
,
104 (void *) &cfg
.challenge_password
, 0},
105 {NULL
, '\0', "password", CFG_STR
, (void *) &cfg
.password
, 0},
106 {NULL
, '\0', "pkcs9_email", CFG_STR
, (void *) &cfg
.pkcs9_email
, 0},
107 {NULL
, '\0', "country", CFG_STR
, (void *) &cfg
.country
, 0},
108 {NULL
, '\0', "dns_name", CFG_STR
, (void *) &cfg
.dns_name
, 0},
109 {NULL
, '\0', "ip_address", CFG_STR
, (void *) &cfg
.ip_addr
, 0},
110 {NULL
, '\0', "email", CFG_STR
, (void *) &cfg
.email
, 0},
112 {NULL
, '\0', "dn_oid", CFG_STR
+ CFG_MULTI_SEPARATED
,
113 (void *) &cfg
.dn_oid
, 0},
115 {NULL
, '\0', "crl_dist_points", CFG_STR
,
116 (void *) &cfg
.crl_dist_points
, 0},
117 {NULL
, '\0', "pkcs12_key_name", CFG_STR
,
118 (void *) &cfg
.pkcs12_key_name
, 0},
120 {NULL
, '\0', "serial", CFG_INT
, (void *) &cfg
.serial
, 0},
121 {NULL
, '\0', "expiration_days", CFG_INT
,
122 (void *) &cfg
.expiration_days
, 0},
124 {NULL
, '\0', "crl_next_update", CFG_INT
,
125 (void *) &cfg
.crl_next_update
, 0},
127 {NULL
, '\0', "ca", CFG_BOOL
, (void *) &cfg
.ca
, 0},
128 {NULL
, '\0', "path_len", CFG_INT
, (void *) &cfg
.path_len
, 0},
129 {NULL
, '\0', "tls_www_client", CFG_BOOL
,
130 (void *) &cfg
.tls_www_client
, 0},
131 {NULL
, '\0', "tls_www_server", CFG_BOOL
,
132 (void *) &cfg
.tls_www_server
, 0},
133 {NULL
, '\0', "signing_key", CFG_BOOL
, (void *) &cfg
.signing_key
,
135 {NULL
, '\0', "encryption_key", CFG_BOOL
,
136 (void *) &cfg
.encryption_key
, 0},
137 {NULL
, '\0', "cert_signing_key", CFG_BOOL
,
138 (void *) &cfg
.cert_sign_key
, 0},
139 {NULL
, '\0', "crl_signing_key", CFG_BOOL
,
140 (void *) &cfg
.crl_sign_key
, 0},
141 {NULL
, '\0', "code_signing_key", CFG_BOOL
,
142 (void *) &cfg
.code_sign_key
, 0},
143 {NULL
, '\0', "ocsp_signing_key", CFG_BOOL
,
144 (void *) &cfg
.ocsp_sign_key
, 0},
145 {NULL
, '\0', "time_stamping_key", CFG_BOOL
,
146 (void *) &cfg
.time_stamping_key
, 0},
147 {NULL
, '\0', "proxy_policy_language", CFG_STR
,
148 (void *) &cfg
.proxy_policy_language
, 0},
152 /* Creating context */
153 con
= cfg_get_context (options
);
156 puts ("Not enough memory");
160 cfg_set_cfgfile_context (con
, 0, -1, (char *) template);
162 /* Parsing command line */
163 ret
= cfg_parse (con
);
167 printf ("error parsing command line: %s: ", template);
168 cfg_fprint_error (con
, stdout
);
170 exit (ret
< 0 ? -ret
: ret
);
177 read_crt_set (gnutls_x509_crt_t crt
, const char *input_str
, const char *oid
)
182 fputs (input_str
, stderr
);
183 fgets (input
, sizeof (input
), stdin
);
185 if (strlen (input
) == 1) /* only newline */
189 gnutls_x509_crt_set_dn_by_oid (crt
, oid
, 0, input
, strlen (input
) - 1);
192 fprintf (stderr
, "set_dn: %s\n", gnutls_strerror (ret
));
198 read_crq_set (gnutls_x509_crq_t crq
, const char *input_str
, const char *oid
)
203 fputs (input_str
, stderr
);
204 fgets (input
, sizeof (input
), stdin
);
206 if (strlen (input
) == 1) /* only newline */
210 gnutls_x509_crq_set_dn_by_oid (crq
, oid
, 0, input
, strlen (input
) - 1);
213 fprintf (stderr
, "set_dn: %s\n", gnutls_strerror (ret
));
218 /* The input_str should contain %d or %u to print the default.
221 read_int_with_default (const char *input_str
, int def
)
227 printf(input_str
, def
);
230 l
= strtol (in
, &endptr
, 0);
234 fprintf (stderr
, "Trailing garbage ignored: `%s'\n", endptr
);
239 if (l
<= INT_MIN
|| l
>= INT_MAX
)
241 fprintf (stderr
, "Integer out of range: `%s'\n", in
);
255 read_int (const char *input_str
)
257 return read_int_with_default (input_str
, 0);
261 read_str (const char *input_str
)
263 static char input
[128];
266 fputs (input_str
, stderr
);
267 if (fgets (input
, sizeof (input
), stdin
) == NULL
)
270 len
= strlen (input
);
271 if ((len
> 0) && (input
[len
- 1] == '\n'))
282 read_yesno (const char *input_str
)
286 fputs (input_str
, stderr
);
287 fgets (input
, sizeof (input
), stdin
);
289 if (strlen (input
) == 1) /* only newline */
292 if (input
[0] == 'y' || input
[0] == 'Y')
299 /* Wrapper functions for non-interactive mode.
307 return getpass ("Enter password: ");
311 get_confirmed_pass (bool empty_ok
)
317 const char *pass
= NULL
;
323 printf ("Password missmatch, try again.\n");
328 pass
= getpass ("Enter password: ");
329 copy
= strdup (pass
);
330 pass
= getpass ("Confirm password: ");
332 while (strcmp (pass
, copy
) != 0 && !(empty_ok
&& *pass
== '\0'));
341 get_challenge_pass (void)
344 return cfg
.challenge_password
;
346 return getpass ("Enter a challenge password: ");
350 get_crl_dist_point_url (void)
353 return cfg
.crl_dist_points
;
355 return read_str ("Enter the URI of the CRL distribution point: ");
359 get_country_crt_set (gnutls_x509_crt_t crt
)
368 gnutls_x509_crt_set_dn_by_oid (crt
,
369 GNUTLS_OID_X520_COUNTRY_NAME
, 0,
370 cfg
.country
, strlen (cfg
.country
));
373 fprintf (stderr
, "set_dn: %s\n", gnutls_strerror (ret
));
379 read_crt_set (crt
, "Country name (2 chars): ",
380 GNUTLS_OID_X520_COUNTRY_NAME
);
386 get_organization_crt_set (gnutls_x509_crt_t crt
)
392 if (!cfg
.organization
)
396 gnutls_x509_crt_set_dn_by_oid (crt
,
397 GNUTLS_OID_X520_ORGANIZATION_NAME
,
399 strlen (cfg
.organization
));
402 fprintf (stderr
, "set_dn: %s\n", gnutls_strerror (ret
));
408 read_crt_set (crt
, "Organization name: ",
409 GNUTLS_OID_X520_ORGANIZATION_NAME
);
415 get_unit_crt_set (gnutls_x509_crt_t crt
)
425 gnutls_x509_crt_set_dn_by_oid (crt
,
426 GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME
,
427 0, cfg
.unit
, strlen (cfg
.unit
));
430 fprintf (stderr
, "set_dn: %s\n", gnutls_strerror (ret
));
436 read_crt_set (crt
, "Organizational unit name: ",
437 GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME
);
443 get_state_crt_set (gnutls_x509_crt_t crt
)
452 gnutls_x509_crt_set_dn_by_oid (crt
,
453 GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME
,
454 0, cfg
.state
, strlen (cfg
.state
));
457 fprintf (stderr
, "set_dn: %s\n", gnutls_strerror (ret
));
463 read_crt_set (crt
, "State or province name: ",
464 GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME
);
470 get_locality_crt_set (gnutls_x509_crt_t crt
)
479 gnutls_x509_crt_set_dn_by_oid (crt
,
480 GNUTLS_OID_X520_LOCALITY_NAME
, 0,
481 cfg
.locality
, strlen (cfg
.locality
));
484 fprintf (stderr
, "set_dn: %s\n", gnutls_strerror (ret
));
490 read_crt_set (crt
, "Locality name: ", GNUTLS_OID_X520_LOCALITY_NAME
);
496 get_cn_crt_set (gnutls_x509_crt_t crt
)
505 gnutls_x509_crt_set_dn_by_oid (crt
, GNUTLS_OID_X520_COMMON_NAME
,
506 0, cfg
.cn
, strlen (cfg
.cn
));
509 fprintf (stderr
, "set_dn: %s\n", gnutls_strerror (ret
));
515 read_crt_set (crt
, "Common name: ", GNUTLS_OID_X520_COMMON_NAME
);
521 get_uid_crt_set (gnutls_x509_crt_t crt
)
529 ret
= gnutls_x509_crt_set_dn_by_oid (crt
, GNUTLS_OID_LDAP_UID
, 0,
530 cfg
.uid
, strlen (cfg
.uid
));
533 fprintf (stderr
, "set_dn: %s\n", gnutls_strerror (ret
));
539 read_crt_set (crt
, "UID: ", GNUTLS_OID_LDAP_UID
);
545 get_oid_crt_set (gnutls_x509_crt_t crt
)
553 for (i
= 0; cfg
.dn_oid
[i
] != NULL
; i
+= 2)
555 if (cfg
.dn_oid
[i
+ 1] == NULL
)
557 fprintf (stderr
, "dn_oid: %s does not have an argument.\n",
561 ret
= gnutls_x509_crt_set_dn_by_oid (crt
, cfg
.dn_oid
[i
], 0,
563 strlen (cfg
.dn_oid
[i
+ 1]));
567 fprintf (stderr
, "set_dn_oid: %s\n", gnutls_strerror (ret
));
577 get_pkcs9_email_crt_set (gnutls_x509_crt_t crt
)
583 if (!cfg
.pkcs9_email
)
585 ret
= gnutls_x509_crt_set_dn_by_oid (crt
, GNUTLS_OID_PKCS9_EMAIL
, 0,
587 strlen (cfg
.pkcs9_email
));
590 fprintf (stderr
, "set_dn: %s\n", gnutls_strerror (ret
));
596 read_crt_set (crt
, "E-mail: ", GNUTLS_OID_PKCS9_EMAIL
);
604 int default_serial
= time (NULL
);
609 return default_serial
;
614 return read_int_with_default
615 ("Enter the certificate's serial number in decimal (default: %u): ", default_serial
);
626 if (cfg
.expiration_days
<= 0)
629 return cfg
.expiration_days
;
635 days
= read_int ("The certificate will expire in (days): ");
652 read_yesno ("Does the certificate belong to an authority? (y/N): ");
665 return read_int_with_default
666 ("Path length constraint (decimal, %d for no constraint): ", -1);
671 get_pkcs12_key_name (void)
677 if (!cfg
.pkcs12_key_name
)
679 return cfg
.pkcs12_key_name
;
685 name
= read_str ("Enter a name for the key: ");
687 while (name
== NULL
);
693 get_tls_client_status (void)
697 return cfg
.tls_www_client
;
701 return read_yesno ("Is this a TLS web client certificate? (y/N): ");
706 get_tls_server_status (void)
710 return cfg
.tls_www_server
;
715 read_yesno ("Is this also a TLS web server certificate? (y/N): ");
729 read_str ("Enter the dnsName of the subject of the certificate: ");
743 read_str ("Enter the IP address of the subject of the certificate: ");
757 read_str ("Enter the e-mail of the subject of the certificate: ");
762 get_sign_status (int server
)
768 return cfg
.signing_key
;
774 "Will the certificate be used for signing (DHE and RSA-EXPORT ciphersuites)? (y/N): ";
777 "Will the certificate be used for signing (required for TLS)? (y/N): ";
778 return read_yesno (msg
);
783 get_encrypt_status (int server
)
789 return cfg
.encryption_key
;
795 "Will the certificate be used for encryption (RSA ciphersuites)? (y/N): ";
798 "Will the certificate be used for encryption (not required for TLS)? (y/N): ";
799 return read_yesno (msg
);
804 get_cert_sign_status (void)
808 return cfg
.cert_sign_key
;
814 ("Will the certificate be used to sign other certificates? (y/N): ");
819 get_crl_sign_status (void)
823 return cfg
.crl_sign_key
;
828 read_yesno ("Will the certificate be used to sign CRLs? (y/N): ");
833 get_code_sign_status (void)
837 return cfg
.code_sign_key
;
842 read_yesno ("Will the certificate be used to sign code? (y/N): ");
847 get_ocsp_sign_status (void)
851 return cfg
.ocsp_sign_key
;
857 ("Will the certificate be used to sign OCSP requests? (y/N): ");
862 get_time_stamp_status (void)
866 return cfg
.time_stamping_key
;
872 ("Will the certificate be used for time stamping? (y/N): ");
877 get_crl_next_update (void)
883 if (cfg
.crl_next_update
<= 0)
886 return cfg
.crl_next_update
;
892 days
= read_int ("The next CRL will be issued in (days): ");
900 get_proxy_policy (char **policy
, size_t *policylen
)
906 ret
= cfg
.proxy_policy_language
;
908 ret
= "1.3.6.1.5.5.7.21.1";
914 ret
= read_str ("Enter the OID of the proxy policy language: ");
922 if (strcmp (ret
, "1.3.6.1.5.5.7.21.1") != 0 &&
923 strcmp (ret
, "1.3.6.1.5.5.7.21.2") != 0)
925 fprintf (stderr
, "Reading non-standard proxy policy not supported.\n");
934 get_country_crq_set (gnutls_x509_crq_t crq
)
943 gnutls_x509_crq_set_dn_by_oid (crq
,
944 GNUTLS_OID_X520_COUNTRY_NAME
, 0,
945 cfg
.country
, strlen (cfg
.country
));
948 fprintf (stderr
, "set_dn: %s\n", gnutls_strerror (ret
));
954 read_crq_set (crq
, "Country name (2 chars): ",
955 GNUTLS_OID_X520_COUNTRY_NAME
);
961 get_organization_crq_set (gnutls_x509_crq_t crq
)
967 if (!cfg
.organization
)
971 gnutls_x509_crq_set_dn_by_oid (crq
,
972 GNUTLS_OID_X520_ORGANIZATION_NAME
,
974 strlen (cfg
.organization
));
977 fprintf (stderr
, "set_dn: %s\n", gnutls_strerror (ret
));
983 read_crq_set (crq
, "Organization name: ",
984 GNUTLS_OID_X520_ORGANIZATION_NAME
);
990 get_unit_crq_set (gnutls_x509_crq_t crq
)
1000 gnutls_x509_crq_set_dn_by_oid (crq
,
1001 GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME
,
1002 0, cfg
.unit
, strlen (cfg
.unit
));
1005 fprintf (stderr
, "set_dn: %s\n", gnutls_strerror (ret
));
1011 read_crq_set (crq
, "Organizational unit name: ",
1012 GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME
);
1018 get_state_crq_set (gnutls_x509_crq_t crq
)
1027 gnutls_x509_crq_set_dn_by_oid (crq
,
1028 GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME
,
1029 0, cfg
.state
, strlen (cfg
.state
));
1032 fprintf (stderr
, "set_dn: %s\n", gnutls_strerror (ret
));
1038 read_crq_set (crq
, "State or province name: ",
1039 GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME
);
1045 get_locality_crq_set (gnutls_x509_crq_t crq
)
1054 gnutls_x509_crq_set_dn_by_oid (crq
,
1055 GNUTLS_OID_X520_LOCALITY_NAME
, 0,
1056 cfg
.locality
, strlen (cfg
.locality
));
1059 fprintf (stderr
, "set_dn: %s\n", gnutls_strerror (ret
));
1065 read_crq_set (crq
, "Locality name: ", GNUTLS_OID_X520_LOCALITY_NAME
);
1071 get_cn_crq_set (gnutls_x509_crq_t crq
)
1080 gnutls_x509_crq_set_dn_by_oid (crq
, GNUTLS_OID_X520_COMMON_NAME
,
1081 0, cfg
.cn
, strlen (cfg
.cn
));
1084 fprintf (stderr
, "set_dn: %s\n", gnutls_strerror (ret
));
1090 read_crq_set (crq
, "Common name: ", GNUTLS_OID_X520_COMMON_NAME
);
1096 get_uid_crq_set (gnutls_x509_crq_t crq
)
1104 ret
= gnutls_x509_crq_set_dn_by_oid (crq
, GNUTLS_OID_LDAP_UID
, 0,
1105 cfg
.uid
, strlen (cfg
.uid
));
1108 fprintf (stderr
, "set_dn: %s\n", gnutls_strerror (ret
));
1114 read_crq_set (crq
, "UID: ", GNUTLS_OID_LDAP_UID
);
1120 get_oid_crq_set (gnutls_x509_crq_t crq
)
1128 for (i
= 0; cfg
.dn_oid
[i
] != NULL
; i
+= 2)
1130 if (cfg
.dn_oid
[i
+ 1] == NULL
)
1132 fprintf (stderr
, "dn_oid: %s does not have an argument.\n",
1136 ret
= gnutls_x509_crq_set_dn_by_oid (crq
, cfg
.dn_oid
[i
], 0,
1138 strlen (cfg
.dn_oid
[i
+ 1]));
1142 fprintf (stderr
, "set_dn_oid: %s\n", gnutls_strerror (ret
));