]> git.ipfire.org Git - thirdparty/openssl.git/blame - apps/req.c
A wish was expressed.
[thirdparty/openssl.git] / apps / req.c
CommitLineData
d02b48c6 1/* apps/req.c */
58964a49 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
d02b48c6
RE
3 * All rights reserved.
4 *
5 * This package is an SSL implementation written
6 * by Eric Young (eay@cryptsoft.com).
7 * The implementation was written so as to conform with Netscapes SSL.
8 *
9 * This library is free for commercial and non-commercial use as long as
10 * the following conditions are aheared to. The following conditions
11 * apply to all code found in this distribution, be it the RC4, RSA,
12 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
13 * included with this distribution is covered by the same copyright terms
14 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15 *
16 * Copyright remains Eric Young's, and as such any Copyright notices in
17 * the code are not to be removed.
18 * If this package is used in a product, Eric Young should be given attribution
19 * as the author of the parts of the library used.
20 * This can be in the form of a textual message at program startup or
21 * in documentation (online or textual) provided with the package.
22 *
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
25 * are met:
26 * 1. Redistributions of source code must retain the copyright
27 * notice, this list of conditions and the following disclaimer.
28 * 2. Redistributions in binary form must reproduce the above copyright
29 * notice, this list of conditions and the following disclaimer in the
30 * documentation and/or other materials provided with the distribution.
31 * 3. All advertising materials mentioning features or use of this software
32 * must display the following acknowledgement:
33 * "This product includes cryptographic software written by
34 * Eric Young (eay@cryptsoft.com)"
35 * The word 'cryptographic' can be left out if the rouines from the library
36 * being used are not cryptographic related :-).
37 * 4. If you include any Windows specific code (or a derivative thereof) from
38 * the apps directory (application code) you must include an acknowledgement:
39 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40 *
41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 * SUCH DAMAGE.
52 *
53 * The licence and distribution terms for any publically available version or
54 * derivative of this code cannot be changed. i.e. this code cannot simply be
55 * copied and put under another distribution licence
56 * [including the GNU Public Licence.]
57 */
58
59#include <stdio.h>
60#include <stdlib.h>
61#include <time.h>
62#include <string.h>
cf1b7d96 63#ifdef OPENSSL_NO_STDIO
d02b48c6
RE
64#define APPS_WIN16
65#endif
66#include "apps.h"
ec577822
BM
67#include <openssl/bio.h>
68#include <openssl/evp.h>
ec577822
BM
69#include <openssl/conf.h>
70#include <openssl/err.h>
71#include <openssl/asn1.h>
72#include <openssl/x509.h>
73#include <openssl/x509v3.h>
74#include <openssl/objects.h>
75#include <openssl/pem.h>
5270e702 76#include <openssl/engine.h>
d02b48c6
RE
77
78#define SECTION "req"
79
80#define BITS "default_bits"
81#define KEYFILE "default_keyfile"
b38f9f66 82#define PROMPT "prompt"
d02b48c6
RE
83#define DISTINGUISHED_NAME "distinguished_name"
84#define ATTRIBUTES "attributes"
f317aa4c 85#define V3_EXTENSIONS "x509_extensions"
c79b16e1 86#define REQ_EXTENSIONS "req_extensions"
b38f9f66 87#define STRING_MASK "string_mask"
d02b48c6
RE
88
89#define DEFAULT_KEY_LENGTH 512
90#define MIN_KEY_LENGTH 384
91
92#undef PROG
93#define PROG req_main
94
25f923dd 95/* -inform arg - input format - default PEM (DER or PEM)
d02b48c6
RE
96 * -outform arg - output format - default PEM
97 * -in arg - input file - default stdin
98 * -out arg - output file - default stdout
99 * -verify - check request signature
100 * -noout - don't print stuff out.
101 * -text - print out human readable text.
102 * -nodes - no des encryption
103 * -config file - Load configuration file.
104 * -key file - make a request using key in file (or use it for verification).
a44f26d5 105 * -keyform arg - key file format.
2a98f417 106 * -rand file(s) - load the file(s) into the PRNG.
d02b48c6
RE
107 * -newkey - make a key and a request.
108 * -modulus - print RSA modulus.
109 * -x509 - output a self signed X509 structure instead.
110 * -asn1-kludge - output new certificate request in a format that some CA's
111 * require. This format is wrong
112 */
113
bad40585
BM
114static int make_REQ(X509_REQ *req,EVP_PKEY *pkey,char *dn,int attribs);
115static int build_subject(X509_REQ *req, char *subj);
b38f9f66
DSH
116static int prompt_info(X509_REQ *req,
117 STACK_OF(CONF_VALUE) *dn_sk, char *dn_sect,
118 STACK_OF(CONF_VALUE) *attr_sk, char *attr_sect, int attribs);
119static int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *sk,
120 STACK_OF(CONF_VALUE) *attr, int attribs);
6e6bc352 121static int add_attribute_object(X509_REQ *req, char *text,
d500de16
BL
122 char *def, char *value, int nid, int min,
123 int max);
d02b48c6
RE
124static int add_DN_object(X509_NAME *n, char *text, char *def, char *value,
125 int nid,int min,int max);
cf1b7d96 126#ifndef OPENSSL_NO_RSA
b4f76582 127static void MS_CALLBACK req_cb(int p,int n,void *arg);
752d706a 128#endif
6e6bc352 129static int req_check_len(int len,int min,int max);
a43aa73e 130static int check_end(char *str, char *end);
d02b48c6
RE
131#ifndef MONOLITH
132static char *default_config_file=NULL;
133static LHASH *config=NULL;
134#endif
135static LHASH *req_conf=NULL;
bad40585 136static int batch=0;
d02b48c6
RE
137
138#define TYPE_RSA 1
139#define TYPE_DSA 2
140#define TYPE_DH 3
141
667ac4ec
RE
142int MAIN(int, char **);
143
6b691a5c 144int MAIN(int argc, char **argv)
d02b48c6 145 {
5270e702 146 ENGINE *e = NULL;
cf1b7d96 147#ifndef OPENSSL_NO_DSA
d02b48c6 148 DSA *dsa_params=NULL;
58964a49 149#endif
d0c98589 150 unsigned long nmflag = 0;
d02b48c6
RE
151 int ex=1,x509=0,days=30;
152 X509 *x509ss=NULL;
153 X509_REQ *req=NULL;
154 EVP_PKEY *pkey=NULL;
bad40585 155 int i,badops=0,newreq=0,newkey= -1,verbose=0,pkey_type=TYPE_RSA;
d02b48c6
RE
156 BIO *in=NULL,*out=NULL;
157 int informat,outformat,verify=0,noout=0,text=0,keyform=FORMAT_PEM;
d0c98589 158 int nodes=0,kludge=0,newhdr=0,subject=0;
d02b48c6 159 char *infile,*outfile,*prog,*keyfile=NULL,*template=NULL,*keyout=NULL;
5270e702 160 char *engine=NULL;
f317aa4c 161 char *extensions = NULL;
c79b16e1 162 char *req_exts = NULL;
13588350 163 const EVP_CIPHER *cipher=NULL;
acba75c5 164 ASN1_INTEGER *serial = NULL;
d02b48c6 165 int modulus=0;
f365611c 166 char *inrand=NULL;
a3fe382e 167 char *passargin = NULL, *passargout = NULL;
36217a94 168 char *passin = NULL, *passout = NULL;
d02b48c6 169 char *p;
bad40585 170 char *subj = NULL;
e778802f 171 const EVP_MD *md_alg=NULL,*digest=EVP_md5();
d02b48c6
RE
172#ifndef MONOLITH
173 MS_STATIC char config_name[256];
174#endif
175
b74ba295 176 req_conf = NULL;
cf1b7d96 177#ifndef OPENSSL_NO_DES
d02b48c6
RE
178 cipher=EVP_des_ede3_cbc();
179#endif
180 apps_startup();
181
182 if (bio_err == NULL)
183 if ((bio_err=BIO_new(BIO_s_file())) != NULL)
58964a49 184 BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
d02b48c6
RE
185
186 infile=NULL;
187 outfile=NULL;
188 informat=FORMAT_PEM;
189 outformat=FORMAT_PEM;
190
191 prog=argv[0];
192 argc--;
193 argv++;
194 while (argc >= 1)
195 {
196 if (strcmp(*argv,"-inform") == 0)
197 {
198 if (--argc < 1) goto bad;
199 informat=str2fmt(*(++argv));
200 }
201 else if (strcmp(*argv,"-outform") == 0)
202 {
203 if (--argc < 1) goto bad;
204 outformat=str2fmt(*(++argv));
205 }
5270e702
RL
206 else if (strcmp(*argv,"-engine") == 0)
207 {
208 if (--argc < 1) goto bad;
209 engine= *(++argv);
210 }
d02b48c6
RE
211 else if (strcmp(*argv,"-key") == 0)
212 {
213 if (--argc < 1) goto bad;
214 keyfile= *(++argv);
215 }
216 else if (strcmp(*argv,"-new") == 0)
217 {
d02b48c6
RE
218 newreq=1;
219 }
220 else if (strcmp(*argv,"-config") == 0)
221 {
222 if (--argc < 1) goto bad;
223 template= *(++argv);
224 }
225 else if (strcmp(*argv,"-keyform") == 0)
226 {
227 if (--argc < 1) goto bad;
228 keyform=str2fmt(*(++argv));
229 }
230 else if (strcmp(*argv,"-in") == 0)
231 {
232 if (--argc < 1) goto bad;
233 infile= *(++argv);
234 }
235 else if (strcmp(*argv,"-out") == 0)
236 {
237 if (--argc < 1) goto bad;
238 outfile= *(++argv);
239 }
240 else if (strcmp(*argv,"-keyout") == 0)
241 {
242 if (--argc < 1) goto bad;
243 keyout= *(++argv);
244 }
36217a94
DSH
245 else if (strcmp(*argv,"-passin") == 0)
246 {
247 if (--argc < 1) goto bad;
a3fe382e 248 passargin= *(++argv);
36217a94
DSH
249 }
250 else if (strcmp(*argv,"-passout") == 0)
251 {
252 if (--argc < 1) goto bad;
a3fe382e 253 passargout= *(++argv);
36217a94 254 }
ac57d15b
RL
255 else if (strcmp(*argv,"-rand") == 0)
256 {
257 if (--argc < 1) goto bad;
258 inrand= *(++argv);
259 }
d02b48c6
RE
260 else if (strcmp(*argv,"-newkey") == 0)
261 {
bc4deee0
BL
262 int is_numeric;
263
d02b48c6
RE
264 if (--argc < 1) goto bad;
265 p= *(++argv);
bc4deee0
BL
266 is_numeric = p[0] >= '0' && p[0] <= '9';
267 if (strncmp("rsa:",p,4) == 0 || is_numeric)
d02b48c6
RE
268 {
269 pkey_type=TYPE_RSA;
bc4deee0
BL
270 if(!is_numeric)
271 p+=4;
d02b48c6
RE
272 newkey= atoi(p);
273 }
58964a49 274 else
cf1b7d96 275#ifndef OPENSSL_NO_DSA
58964a49 276 if (strncmp("dsa:",p,4) == 0)
d02b48c6
RE
277 {
278 X509 *xtmp=NULL;
279 EVP_PKEY *dtmp;
280
281 pkey_type=TYPE_DSA;
282 p+=4;
283 if ((in=BIO_new_file(p,"r")) == NULL)
284 {
285 perror(p);
286 goto end;
287 }
74678cc2 288 if ((dsa_params=PEM_read_bio_DSAparams(in,NULL,NULL,NULL)) == NULL)
d02b48c6
RE
289 {
290 ERR_clear_error();
d58d092b 291 (void)BIO_reset(in);
74678cc2 292 if ((xtmp=PEM_read_bio_X509(in,NULL,NULL,NULL)) == NULL)
d02b48c6
RE
293 {
294 BIO_printf(bio_err,"unable to load DSA parameters from file\n");
295 goto end;
296 }
58964a49 297
d02b48c6
RE
298 dtmp=X509_get_pubkey(xtmp);
299 if (dtmp->type == EVP_PKEY_DSA)
300 dsa_params=DSAparams_dup(dtmp->pkey.dsa);
1756d405 301 EVP_PKEY_free(dtmp);
d02b48c6
RE
302 X509_free(xtmp);
303 if (dsa_params == NULL)
304 {
305 BIO_printf(bio_err,"Certificate does not contain DSA parameters\n");
306 goto end;
307 }
d02b48c6
RE
308 }
309 BIO_free(in);
310 newkey=BN_num_bits(dsa_params->p);
311 in=NULL;
312 }
58964a49
RE
313 else
314#endif
cf1b7d96 315#ifndef OPENSSL_NO_DH
58964a49 316 if (strncmp("dh:",p,4) == 0)
d02b48c6
RE
317 {
318 pkey_type=TYPE_DH;
319 p+=3;
320 }
321 else
58964a49 322#endif
d02b48c6
RE
323 pkey_type=TYPE_RSA;
324
325 newreq=1;
326 }
bad40585
BM
327 else if (strcmp(*argv,"-batch") == 0)
328 batch=1;
8a208cba
DSH
329 else if (strcmp(*argv,"-newhdr") == 0)
330 newhdr=1;
d02b48c6
RE
331 else if (strcmp(*argv,"-modulus") == 0)
332 modulus=1;
333 else if (strcmp(*argv,"-verify") == 0)
334 verify=1;
335 else if (strcmp(*argv,"-nodes") == 0)
336 nodes=1;
337 else if (strcmp(*argv,"-noout") == 0)
338 noout=1;
bad40585
BM
339 else if (strcmp(*argv,"-verbose") == 0)
340 verbose=1;
d0c98589
DSH
341 else if (strcmp(*argv,"-nameopt") == 0)
342 {
343 if (--argc < 1) goto bad;
344 if (!set_name_ex(&nmflag, *(++argv))) goto bad;
345 }
346 else if (strcmp(*argv,"-subject") == 0)
347 subject=1;
d02b48c6
RE
348 else if (strcmp(*argv,"-text") == 0)
349 text=1;
350 else if (strcmp(*argv,"-x509") == 0)
351 x509=1;
352 else if (strcmp(*argv,"-asn1-kludge") == 0)
353 kludge=1;
354 else if (strcmp(*argv,"-no-asn1-kludge") == 0)
355 kludge=0;
bad40585
BM
356 else if (strcmp(*argv,"-subj") == 0)
357 {
358 if (--argc < 1) goto bad;
359 subj= *(++argv);
360 }
d02b48c6
RE
361 else if (strcmp(*argv,"-days") == 0)
362 {
363 if (--argc < 1) goto bad;
364 days= atoi(*(++argv));
365 if (days == 0) days=30;
366 }
acba75c5
DSH
367 else if (strcmp(*argv,"-set_serial") == 0)
368 {
369 if (--argc < 1) goto bad;
370 serial = s2i_ASN1_INTEGER(NULL, *(++argv));
371 if (!serial) goto bad;
372 }
d02b48c6
RE
373 else if ((md_alg=EVP_get_digestbyname(&((*argv)[1]))) != NULL)
374 {
375 /* ok */
376 digest=md_alg;
377 }
87a25f90
DSH
378 else if (strcmp(*argv,"-extensions") == 0)
379 {
380 if (--argc < 1) goto bad;
381 extensions = *(++argv);
382 }
383 else if (strcmp(*argv,"-reqexts") == 0)
384 {
385 if (--argc < 1) goto bad;
386 req_exts = *(++argv);
387 }
d02b48c6 388 else
d02b48c6
RE
389 {
390 BIO_printf(bio_err,"unknown option %s\n",*argv);
391 badops=1;
392 break;
393 }
394 argc--;
395 argv++;
396 }
397
398 if (badops)
399 {
400bad:
401 BIO_printf(bio_err,"%s [options] <infile >outfile\n",prog);
402 BIO_printf(bio_err,"where options are\n");
25f923dd
DSH
403 BIO_printf(bio_err," -inform arg input format - DER or PEM\n");
404 BIO_printf(bio_err," -outform arg output format - DER or PEM\n");
9fe84296 405 BIO_printf(bio_err," -in arg input file\n");
d02b48c6
RE
406 BIO_printf(bio_err," -out arg output file\n");
407 BIO_printf(bio_err," -text text form of request\n");
408 BIO_printf(bio_err," -noout do not output REQ\n");
409 BIO_printf(bio_err," -verify verify signature on REQ\n");
410 BIO_printf(bio_err," -modulus RSA modulus\n");
411 BIO_printf(bio_err," -nodes don't encrypt the output key\n");
bad40585
BM
412 BIO_printf(bio_err," -engine e use engine e, possibly a hardware device\n");
413 BIO_printf(bio_err," -subject output the request's subject\n");
414 BIO_printf(bio_err," -passin private key password source\n");
415 BIO_printf(bio_err," -key file use the private key contained in file\n");
d02b48c6
RE
416 BIO_printf(bio_err," -keyform arg key file format\n");
417 BIO_printf(bio_err," -keyout arg file to send the key to\n");
2a98f417
RL
418 BIO_printf(bio_err," -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
419 BIO_printf(bio_err," load the file (or the files in the directory) into\n");
420 BIO_printf(bio_err," the random number generator\n");
d02b48c6
RE
421 BIO_printf(bio_err," -newkey rsa:bits generate a new RSA key of 'bits' in size\n");
422 BIO_printf(bio_err," -newkey dsa:file generate a new DSA key, parameters taken from CA in 'file'\n");
d02b48c6 423 BIO_printf(bio_err," -[digest] Digest to sign with (md5, sha1, md2, mdc2)\n");
d1f4c83c 424 BIO_printf(bio_err," -config file request template file.\n");
bad40585 425 BIO_printf(bio_err," -subj arg set or modify request subject\n");
d02b48c6 426 BIO_printf(bio_err," -new new request.\n");
bad40585 427 BIO_printf(bio_err," -batch do not ask anything during request generation\n");
d02b48c6 428 BIO_printf(bio_err," -x509 output a x509 structure instead of a cert. req.\n");
acba75c5
DSH
429 BIO_printf(bio_err," -days number of days a certificate generated by -x509 is valid for.\n");
430 BIO_printf(bio_err," -set_serial serial number to use for a certificate generated by -x509.\n");
8a208cba 431 BIO_printf(bio_err," -newhdr output \"NEW\" in the header lines\n");
d02b48c6
RE
432 BIO_printf(bio_err," -asn1-kludge Output the 'request' in a format that is wrong but some CA's\n");
433 BIO_printf(bio_err," have been reported as requiring\n");
87a25f90
DSH
434 BIO_printf(bio_err," -extensions .. specify certificate extension section (override value in config file)\n");
435 BIO_printf(bio_err," -reqexts .. specify request extension section (override value in config file)\n");
d02b48c6
RE
436 goto end;
437 }
438
439 ERR_load_crypto_strings();
a3fe382e
DSH
440 if(!app_passwd(bio_err, passargin, passargout, &passin, &passout)) {
441 BIO_printf(bio_err, "Error getting passwords\n");
442 goto end;
443 }
d02b48c6 444
3db1f2d5 445#ifndef MONOLITH /* else this has happened in openssl.c (global `config') */
d02b48c6 446 /* Lets load up our environment a little */
06d5b162
RE
447 p=getenv("OPENSSL_CONF");
448 if (p == NULL)
449 p=getenv("SSLEAY_CONF");
d02b48c6
RE
450 if (p == NULL)
451 {
452 strcpy(config_name,X509_get_default_cert_area());
bc36ee62 453#ifndef OPENSSL_SYS_VMS
7af62c3c 454 strcat(config_name,"/");
7d7d2cbc 455#endif
06d5b162 456 strcat(config_name,OPENSSL_CONF);
d02b48c6
RE
457 p=config_name;
458 }
3db1f2d5 459 default_config_file=p;
d02b48c6
RE
460 config=CONF_load(config,p,NULL);
461#endif
462
463 if (template != NULL)
464 {
465 long errline;
466
467 BIO_printf(bio_err,"Using configuration from %s\n",template);
468 req_conf=CONF_load(NULL,template,&errline);
469 if (req_conf == NULL)
470 {
471 BIO_printf(bio_err,"error on line %ld of %s\n",errline,template);
472 goto end;
473 }
474 }
475 else
476 {
477 req_conf=config;
478 BIO_printf(bio_err,"Using configuration from %s\n",
479 default_config_file);
480 if (req_conf == NULL)
481 {
482 BIO_printf(bio_err,"Unable to load config info\n");
483 }
484 }
485
dfeab068
RE
486 if (req_conf != NULL)
487 {
488 p=CONF_get_string(req_conf,NULL,"oid_file");
2c0d1012
BM
489 if (p == NULL)
490 ERR_clear_error();
dfeab068
RE
491 if (p != NULL)
492 {
493 BIO *oid_bio;
494
495 oid_bio=BIO_new_file(p,"r");
496 if (oid_bio == NULL)
497 {
498 /*
499 BIO_printf(bio_err,"problems opening %s for extra oid's\n",p);
500 ERR_print_errors(bio_err);
501 */
502 }
503 else
504 {
505 OBJ_create_objects(oid_bio);
506 BIO_free(oid_bio);
507 }
508 }
509 }
2c0d1012 510 if(!add_oid_section(bio_err, req_conf)) goto end;
dfeab068 511
2c0d1012 512 if (md_alg == NULL)
d02b48c6 513 {
2c0d1012
BM
514 p=CONF_get_string(req_conf,SECTION,"default_md");
515 if (p == NULL)
516 ERR_clear_error();
517 if (p != NULL)
518 {
519 if ((md_alg=EVP_get_digestbyname(p)) != NULL)
520 digest=md_alg;
521 }
d02b48c6
RE
522 }
523
2c0d1012
BM
524 if (!extensions)
525 {
87a25f90 526 extensions = CONF_get_string(req_conf, SECTION, V3_EXTENSIONS);
2c0d1012
BM
527 if (!extensions)
528 ERR_clear_error();
529 }
530 if (extensions) {
1756d405 531 /* Check syntax of file */
41b731f2
DSH
532 X509V3_CTX ctx;
533 X509V3_set_ctx_test(&ctx);
534 X509V3_set_conf_lhash(&ctx, req_conf);
535 if(!X509V3_EXT_add_conf(req_conf, &ctx, extensions, NULL)) {
1756d405
DSH
536 BIO_printf(bio_err,
537 "Error Loading extension section %s\n", extensions);
538 goto end;
539 }
540 }
f317aa4c 541
36217a94 542 if(!passin)
2c0d1012 543 {
36217a94 544 passin = CONF_get_string(req_conf, SECTION, "input_password");
2c0d1012
BM
545 if (!passin)
546 ERR_clear_error();
547 }
548
36217a94 549 if(!passout)
2c0d1012 550 {
36217a94 551 passout = CONF_get_string(req_conf, SECTION, "output_password");
2c0d1012
BM
552 if (!passout)
553 ERR_clear_error();
554 }
36217a94 555
b38f9f66 556 p = CONF_get_string(req_conf, SECTION, STRING_MASK);
2c0d1012
BM
557 if (!p)
558 ERR_clear_error();
74400f73
DSH
559
560 if(p && !ASN1_STRING_set_default_mask_asc(p)) {
d2b6c3f3 561 BIO_printf(bio_err, "Invalid global string mask setting %s\n", p);
74400f73
DSH
562 goto end;
563 }
564
87a25f90 565 if(!req_exts)
2c0d1012 566 {
87a25f90 567 req_exts = CONF_get_string(req_conf, SECTION, REQ_EXTENSIONS);
2c0d1012
BM
568 if (!req_exts)
569 ERR_clear_error();
570 }
c79b16e1
DSH
571 if(req_exts) {
572 /* Check syntax of file */
573 X509V3_CTX ctx;
574 X509V3_set_ctx_test(&ctx);
575 X509V3_set_conf_lhash(&ctx, req_conf);
576 if(!X509V3_EXT_add_conf(req_conf, &ctx, req_exts, NULL)) {
577 BIO_printf(bio_err,
578 "Error Loading request extension section %s\n",
579 req_exts);
580 goto end;
581 }
582 }
583
d02b48c6
RE
584 in=BIO_new(BIO_s_file());
585 out=BIO_new(BIO_s_file());
586 if ((in == NULL) || (out == NULL))
587 goto end;
588
5270e702 589 if (engine != NULL)
d02b48c6 590 {
5270e702 591 if((e = ENGINE_by_id(engine)) == NULL)
d02b48c6 592 {
5270e702
RL
593 BIO_printf(bio_err,"invalid engine \"%s\"\n",
594 engine);
d02b48c6
RE
595 goto end;
596 }
5270e702
RL
597 if(!ENGINE_set_default(e, ENGINE_METHOD_ALL))
598 {
599 BIO_printf(bio_err,"can't use that engine\n");
600 goto end;
601 }
602 BIO_printf(bio_err,"engine \"%s\" set.\n", engine);
603 /* Free our "structural" reference. */
604 ENGINE_free(e);
605 }
d02b48c6 606
5270e702
RL
607 if (keyfile != NULL)
608 {
609 if (keyform == FORMAT_ENGINE)
36217a94 610 {
5270e702
RL
611 if (!e)
612 {
613 BIO_printf(bio_err,"no engine specified\n");
614 goto end;
615 }
616 pkey = ENGINE_load_private_key(e, keyfile, NULL);
36217a94 617 }
d02b48c6
RE
618 else
619 {
5270e702
RL
620 if (BIO_read_filename(in,keyfile) <= 0)
621 {
622 perror(keyfile);
623 goto end;
624 }
625
626 if (keyform == FORMAT_ASN1)
627 pkey=d2i_PrivateKey_bio(in,NULL);
628 else if (keyform == FORMAT_PEM)
629 {
630 pkey=PEM_read_bio_PrivateKey(in,NULL,NULL,
631 passin);
632 }
633 else
634 {
635 BIO_printf(bio_err,"bad input format specified for X509 request\n");
636 goto end;
637 }
d02b48c6
RE
638 }
639
640 if (pkey == NULL)
641 {
642 BIO_printf(bio_err,"unable to load Private key\n");
643 goto end;
644 }
bad40585 645 if (EVP_PKEY_type(pkey->type) == EVP_PKEY_DSA)
fd13f0ee
DSH
646 {
647 char *randfile = CONF_get_string(req_conf,SECTION,"RANDFILE");
2c0d1012
BM
648 if (randfile == NULL)
649 ERR_clear_error();
fd13f0ee 650 app_RAND_load_file(randfile, bio_err, 0);
bad40585 651 }
d02b48c6
RE
652 }
653
654 if (newreq && (pkey == NULL))
655 {
ff4e9d91 656 char *randfile = CONF_get_string(req_conf,SECTION,"RANDFILE");
2c0d1012
BM
657 if (randfile == NULL)
658 ERR_clear_error();
a31011e8 659 app_RAND_load_file(randfile, bio_err, 0);
ff4e9d91
RL
660 if (inrand)
661 app_RAND_load_files(inrand);
f365611c 662
d02b48c6
RE
663 if (newkey <= 0)
664 {
665 newkey=(int)CONF_get_number(req_conf,SECTION,BITS);
666 if (newkey <= 0)
667 newkey=DEFAULT_KEY_LENGTH;
668 }
669
670 if (newkey < MIN_KEY_LENGTH)
671 {
672 BIO_printf(bio_err,"private key length is too short,\n");
673 BIO_printf(bio_err,"it needs to be at least %d bits, not %d\n",MIN_KEY_LENGTH,newkey);
674 goto end;
675 }
676 BIO_printf(bio_err,"Generating a %d bit %s private key\n",
677 newkey,(pkey_type == TYPE_RSA)?"RSA":"DSA");
678
679 if ((pkey=EVP_PKEY_new()) == NULL) goto end;
680
cf1b7d96 681#ifndef OPENSSL_NO_RSA
d02b48c6
RE
682 if (pkey_type == TYPE_RSA)
683 {
684 if (!EVP_PKEY_assign_RSA(pkey,
58964a49 685 RSA_generate_key(newkey,0x10001,
b4f76582 686 req_cb,bio_err)))
d02b48c6
RE
687 goto end;
688 }
689 else
690#endif
cf1b7d96 691#ifndef OPENSSL_NO_DSA
d02b48c6
RE
692 if (pkey_type == TYPE_DSA)
693 {
694 if (!DSA_generate_key(dsa_params)) goto end;
695 if (!EVP_PKEY_assign_DSA(pkey,dsa_params)) goto end;
696 dsa_params=NULL;
697 }
698#endif
699
a31011e8 700 app_RAND_write_file(randfile, bio_err);
d02b48c6
RE
701
702 if (pkey == NULL) goto end;
703
704 if (keyout == NULL)
2c0d1012 705 {
d02b48c6 706 keyout=CONF_get_string(req_conf,SECTION,KEYFILE);
2c0d1012
BM
707 if (keyout == NULL)
708 ERR_clear_error();
709 }
710
d02b48c6
RE
711 if (keyout == NULL)
712 {
713 BIO_printf(bio_err,"writing new private key to stdout\n");
714 BIO_set_fp(out,stdout,BIO_NOCLOSE);
bc36ee62 715#ifdef OPENSSL_SYS_VMS
645749ef
RL
716 {
717 BIO *tmpbio = BIO_new(BIO_f_linebuffer());
718 out = BIO_push(tmpbio, out);
719 }
720#endif
d02b48c6
RE
721 }
722 else
723 {
724 BIO_printf(bio_err,"writing new private key to '%s'\n",keyout);
725 if (BIO_write_filename(out,keyout) <= 0)
726 {
727 perror(keyout);
728 goto end;
729 }
730 }
731
732 p=CONF_get_string(req_conf,SECTION,"encrypt_rsa_key");
733 if (p == NULL)
2c0d1012
BM
734 {
735 ERR_clear_error();
d02b48c6 736 p=CONF_get_string(req_conf,SECTION,"encrypt_key");
2c0d1012
BM
737 if (p == NULL)
738 ERR_clear_error();
739 }
d02b48c6
RE
740 if ((p != NULL) && (strcmp(p,"no") == 0))
741 cipher=NULL;
742 if (nodes) cipher=NULL;
743
744 i=0;
745loop:
746 if (!PEM_write_bio_PrivateKey(out,pkey,cipher,
a3fe382e 747 NULL,0,NULL,passout))
d02b48c6
RE
748 {
749 if ((ERR_GET_REASON(ERR_peek_error()) ==
750 PEM_R_PROBLEMS_GETTING_PASSWORD) && (i < 3))
751 {
752 ERR_clear_error();
753 i++;
754 goto loop;
755 }
756 goto end;
757 }
758 BIO_printf(bio_err,"-----\n");
759 }
760
761 if (!newreq)
762 {
763 /* Since we are using a pre-existing certificate
764 * request, the kludge 'format' info should not be
765 * changed. */
766 kludge= -1;
767 if (infile == NULL)
768 BIO_set_fp(in,stdin,BIO_NOCLOSE);
769 else
770 {
771 if (BIO_read_filename(in,infile) <= 0)
772 {
773 perror(infile);
774 goto end;
775 }
776 }
777
778 if (informat == FORMAT_ASN1)
779 req=d2i_X509_REQ_bio(in,NULL);
780 else if (informat == FORMAT_PEM)
74678cc2 781 req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL);
d02b48c6
RE
782 else
783 {
784 BIO_printf(bio_err,"bad input format specified for X509 request\n");
785 goto end;
786 }
787 if (req == NULL)
788 {
789 BIO_printf(bio_err,"unable to load X509 request\n");
790 goto end;
791 }
792 }
793
794 if (newreq || x509)
795 {
d02b48c6
RE
796 if (pkey == NULL)
797 {
798 BIO_printf(bio_err,"you need to specify a private key\n");
799 goto end;
800 }
cf1b7d96 801#ifndef OPENSSL_NO_DSA
69a03c17
BM
802 if (pkey->type == EVP_PKEY_DSA)
803 digest=EVP_dss1();
804#endif
d02b48c6
RE
805 if (req == NULL)
806 {
807 req=X509_REQ_new();
808 if (req == NULL)
809 {
810 goto end;
811 }
812
bad40585
BM
813 i=make_REQ(req,pkey,subj,!x509);
814 subj=NULL; /* done processing '-subj' option */
9d6b1ce6
DSH
815 if ((kludge > 0) && !sk_X509_ATTRIBUTE_num(req->req_info->attributes))
816 {
817 sk_X509_ATTRIBUTE_free(req->req_info->attributes);
818 req->req_info->attributes = NULL;
819 }
d02b48c6
RE
820 if (!i)
821 {
822 BIO_printf(bio_err,"problems making Certificate Request\n");
823 goto end;
824 }
825 }
826 if (x509)
827 {
10061c7c 828 EVP_PKEY *tmppkey;
f317aa4c 829 X509V3_CTX ext_ctx;
d02b48c6
RE
830 if ((x509ss=X509_new()) == NULL) goto end;
831
f317aa4c
DSH
832 /* Set version to V3 */
833 if(!X509_set_version(x509ss, 2)) goto end;
acba75c5
DSH
834 if (serial)
835 X509_set_serialNumber(x509ss, serial);
836 else
837 ASN1_INTEGER_set(X509_get_serialNumber(x509ss),0L);
d02b48c6
RE
838
839 X509_set_issuer_name(x509ss,
840 X509_REQ_get_subject_name(req));
841 X509_gmtime_adj(X509_get_notBefore(x509ss),0);
842 X509_gmtime_adj(X509_get_notAfter(x509ss),
843 (long)60*60*24*days);
844 X509_set_subject_name(x509ss,
845 X509_REQ_get_subject_name(req));
10061c7c
DSH
846 tmppkey = X509_REQ_get_pubkey(req);
847 X509_set_pubkey(x509ss,tmppkey);
848 EVP_PKEY_free(tmppkey);
d02b48c6 849
f317aa4c
DSH
850 /* Set up V3 context struct */
851
1d48dd00
DSH
852 X509V3_set_ctx(&ext_ctx, x509ss, x509ss, NULL, NULL, 0);
853 X509V3_set_conf_lhash(&ext_ctx, req_conf);
f317aa4c
DSH
854
855 /* Add extensions */
856 if(extensions && !X509V3_EXT_add_conf(req_conf,
9f7646da 857 &ext_ctx, extensions, x509ss))
bad40585
BM
858 {
859 BIO_printf(bio_err,
860 "Error Loading extension section %s\n",
861 extensions);
862 goto end;
863 }
864
d02b48c6
RE
865 if (!(i=X509_sign(x509ss,pkey,digest)))
866 goto end;
867 }
868 else
869 {
c79b16e1
DSH
870 X509V3_CTX ext_ctx;
871
872 /* Set up V3 context struct */
873
874 X509V3_set_ctx(&ext_ctx, NULL, NULL, req, NULL, 0);
875 X509V3_set_conf_lhash(&ext_ctx, req_conf);
876
877 /* Add extensions */
878 if(req_exts && !X509V3_EXT_REQ_add_conf(req_conf,
879 &ext_ctx, req_exts, req))
bad40585
BM
880 {
881 BIO_printf(bio_err,
882 "Error Loading extension section %s\n",
883 req_exts);
884 goto end;
885 }
d02b48c6
RE
886 if (!(i=X509_REQ_sign(req,pkey,digest)))
887 goto end;
888 }
889 }
890
bad40585
BM
891 if (subj && x509)
892 {
893 BIO_printf(bio_err, "Cannot modifiy certificate subject\n");
894 goto end;
895 }
896
897 if (subj && !x509)
898 {
899 if (verbose)
900 {
901 BIO_printf(bio_err, "Modifying Request's Subject\n");
902 print_name(bio_err, "old subject=", X509_REQ_get_subject_name(req), nmflag);
903 }
904
905 if (build_subject(req, subj) == 0)
906 {
907 BIO_printf(bio_err, "ERROR: cannot modify subject\n");
908 ex=1;
909 goto end;
910 }
911
912 req->req_info->enc.modified = 1;
913
914 if (verbose)
915 {
916 print_name(bio_err, "new subject=", X509_REQ_get_subject_name(req), nmflag);
917 }
918 }
919
d02b48c6
RE
920 if (verify && !x509)
921 {
922 int tmp=0;
923
924 if (pkey == NULL)
925 {
926 pkey=X509_REQ_get_pubkey(req);
927 tmp=1;
928 if (pkey == NULL) goto end;
929 }
930
931 i=X509_REQ_verify(req,pkey);
cfcf6453
DSH
932 if (tmp) {
933 EVP_PKEY_free(pkey);
934 pkey=NULL;
935 }
d02b48c6
RE
936
937 if (i < 0)
938 {
939 goto end;
940 }
941 else if (i == 0)
942 {
943 BIO_printf(bio_err,"verify failure\n");
944 }
945 else /* if (i > 0) */
946 BIO_printf(bio_err,"verify OK\n");
947 }
948
d0c98589 949 if (noout && !text && !modulus && !subject)
d02b48c6
RE
950 {
951 ex=0;
952 goto end;
953 }
954
955 if (outfile == NULL)
645749ef 956 {
d02b48c6 957 BIO_set_fp(out,stdout,BIO_NOCLOSE);
bc36ee62 958#ifdef OPENSSL_SYS_VMS
645749ef
RL
959 {
960 BIO *tmpbio = BIO_new(BIO_f_linebuffer());
961 out = BIO_push(tmpbio, out);
962 }
963#endif
964 }
d02b48c6
RE
965 else
966 {
967 if ((keyout != NULL) && (strcmp(outfile,keyout) == 0))
968 i=(int)BIO_append_filename(out,outfile);
969 else
970 i=(int)BIO_write_filename(out,outfile);
971 if (!i)
972 {
973 perror(outfile);
974 goto end;
975 }
976 }
977
978 if (text)
979 {
980 if (x509)
981 X509_print(out,x509ss);
982 else
983 X509_REQ_print(out,req);
984 }
985
d0c98589
DSH
986 if(subject)
987 {
988 if(x509)
989 print_name(out, "subject=", X509_get_subject_name(x509ss), nmflag);
990 else
991 print_name(out, "subject=", X509_REQ_get_subject_name(req), nmflag);
992 }
993
d02b48c6
RE
994 if (modulus)
995 {
996 EVP_PKEY *pubkey;
997
998 if (x509)
999 pubkey=X509_get_pubkey(x509ss);
1000 else
1001 pubkey=X509_REQ_get_pubkey(req);
1002 if (pubkey == NULL)
1003 {
1004 fprintf(stdout,"Modulus=unavailable\n");
1005 goto end;
1006 }
1007 fprintf(stdout,"Modulus=");
cf1b7d96 1008#ifndef OPENSSL_NO_RSA
d02b48c6
RE
1009 if (pubkey->type == EVP_PKEY_RSA)
1010 BN_print(out,pubkey->pkey.rsa->n);
1011 else
13e91dd3 1012#endif
d02b48c6
RE
1013 fprintf(stdout,"Wrong Algorithm type");
1014 fprintf(stdout,"\n");
1015 }
1016
1017 if (!noout && !x509)
1018 {
1019 if (outformat == FORMAT_ASN1)
1020 i=i2d_X509_REQ_bio(out,req);
8a208cba
DSH
1021 else if (outformat == FORMAT_PEM) {
1022 if(newhdr) i=PEM_write_bio_X509_REQ_NEW(out,req);
1023 else i=PEM_write_bio_X509_REQ(out,req);
1024 } else {
d02b48c6
RE
1025 BIO_printf(bio_err,"bad output format specified for outfile\n");
1026 goto end;
1027 }
1028 if (!i)
1029 {
1030 BIO_printf(bio_err,"unable to write X509 request\n");
1031 goto end;
1032 }
1033 }
1034 if (!noout && x509 && (x509ss != NULL))
1035 {
1036 if (outformat == FORMAT_ASN1)
1037 i=i2d_X509_bio(out,x509ss);
1038 else if (outformat == FORMAT_PEM)
1039 i=PEM_write_bio_X509(out,x509ss);
1040 else {
1041 BIO_printf(bio_err,"bad output format specified for outfile\n");
1042 goto end;
1043 }
1044 if (!i)
1045 {
1046 BIO_printf(bio_err,"unable to write X509 certificate\n");
1047 goto end;
1048 }
1049 }
1050 ex=0;
1051end:
1052 if (ex)
1053 {
1054 ERR_print_errors(bio_err);
1055 }
1056 if ((req_conf != NULL) && (req_conf != config)) CONF_free(req_conf);
a43aa73e 1057 BIO_free(in);
645749ef 1058 BIO_free_all(out);
a43aa73e
DSH
1059 EVP_PKEY_free(pkey);
1060 X509_REQ_free(req);
1061 X509_free(x509ss);
acba75c5 1062 ASN1_INTEGER_free(serial);
26a3a48d
RL
1063 if(passargin && passin) OPENSSL_free(passin);
1064 if(passargout && passout) OPENSSL_free(passout);
a43aa73e 1065 OBJ_cleanup();
cf1b7d96 1066#ifndef OPENSSL_NO_DSA
d02b48c6 1067 if (dsa_params != NULL) DSA_free(dsa_params);
58964a49 1068#endif
d02b48c6
RE
1069 EXIT(ex);
1070 }
1071
bad40585 1072static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, char *subj, int attribs)
d02b48c6 1073 {
a43aa73e 1074 int ret=0,i;
b38f9f66
DSH
1075 char no_prompt = 0;
1076 STACK_OF(CONF_VALUE) *dn_sk, *attr_sk = NULL;
1077 char *tmp, *dn_sect,*attr_sect;
1078
1079 tmp=CONF_get_string(req_conf,SECTION,PROMPT);
2c0d1012
BM
1080 if (tmp == NULL)
1081 ERR_clear_error();
b38f9f66
DSH
1082 if((tmp != NULL) && !strcmp(tmp, "no")) no_prompt = 1;
1083
1084 dn_sect=CONF_get_string(req_conf,SECTION,DISTINGUISHED_NAME);
1085 if (dn_sect == NULL)
d02b48c6
RE
1086 {
1087 BIO_printf(bio_err,"unable to find '%s' in config\n",
1088 DISTINGUISHED_NAME);
1089 goto err;
1090 }
b38f9f66
DSH
1091 dn_sk=CONF_get_section(req_conf,dn_sect);
1092 if (dn_sk == NULL)
d02b48c6 1093 {
b38f9f66 1094 BIO_printf(bio_err,"unable to get '%s' section\n",dn_sect);
d02b48c6
RE
1095 goto err;
1096 }
1097
b38f9f66
DSH
1098 attr_sect=CONF_get_string(req_conf,SECTION,ATTRIBUTES);
1099 if (attr_sect == NULL)
2c0d1012
BM
1100 {
1101 ERR_clear_error();
b38f9f66 1102 attr_sk=NULL;
2c0d1012 1103 }
d02b48c6
RE
1104 else
1105 {
b38f9f66
DSH
1106 attr_sk=CONF_get_section(req_conf,attr_sect);
1107 if (attr_sk == NULL)
d02b48c6 1108 {
b38f9f66 1109 BIO_printf(bio_err,"unable to get '%s' section\n",attr_sect);
d02b48c6
RE
1110 goto err;
1111 }
1112 }
1113
74400f73 1114 /* setup version number */
b38f9f66 1115 if (!X509_REQ_set_version(req,0L)) goto err; /* version 1 */
74400f73 1116
bad40585
BM
1117 if (no_prompt)
1118 i = auto_info(req, dn_sk, attr_sk, attribs);
1119 else
1120 {
1121 if (subj)
1122 i = build_subject(req, subj);
1123 else
1124 i = prompt_info(req, dn_sk, dn_sect, attr_sk, attr_sect, attribs);
1125 }
b38f9f66 1126 if(!i) goto err;
d02b48c6 1127
d02b48c6
RE
1128 X509_REQ_set_pubkey(req,pkey);
1129
1130 ret=1;
1131err:
1132 return(ret);
1133 }
1134
bad40585
BM
1135static int build_subject(X509_REQ *req, char *subject)
1136 {
1137 X509_NAME *n = NULL;
1138
1139 int i, nid, ne_num=0;
1140
1141 char *ne_name = NULL;
1142 char *ne_value = NULL;
1143
1144 char *tmp = NULL;
1145 char *p[2];
1146
1147 char *str_list[256];
1148
1149 p[0] = ",/";
1150 p[1] = "=";
1151
1152 n = X509_NAME_new();
1153
1154 tmp = strtok(subject, p[0]);
1155 while((tmp != NULL) && (ne_num < (sizeof str_list/sizeof *str_list)))
1156 {
1157 char *token = tmp;
1158
1159 while (token[0] == ' ')
1160 token++;
1161 str_list[ne_num] = token;
1162
1163 tmp = strtok(NULL, p[0]);
1164 ne_num++;
1165 }
1166
1167 for(i = 0; i < ne_num; i++)
1168 {
1169 ne_name = strtok(str_list[i], p[1]);
1170 ne_value = strtok(NULL, p[1]);
1171
1172 if ((nid=OBJ_txt2nid(ne_name)) == NID_undef)
1173 {
1174 BIO_printf(bio_err, "Subject Attribute %s has no known NID, skipped\n", ne_name);
1175 continue;
1176 }
1177
1178 if (ne_value == NULL)
1179 {
1180 BIO_printf(bio_err, "No value provided for Subject Attribute %s, skipped\n", ne_name);
1181 continue;
1182 }
1183
1184 if (!X509_NAME_add_entry_by_NID(n, nid, MBSTRING_ASC, (unsigned char*)ne_value, -1,-1,0))
1185 {
1186 X509_NAME_free(n);
1187 return 0;
1188 }
1189 }
1190
1191 if (!X509_REQ_set_subject_name(req, n))
1192 return 0;
1193 X509_NAME_free(n);
1194 return 1;
1195}
1196
b38f9f66
DSH
1197
1198static int prompt_info(X509_REQ *req,
1199 STACK_OF(CONF_VALUE) *dn_sk, char *dn_sect,
1200 STACK_OF(CONF_VALUE) *attr_sk, char *attr_sect, int attribs)
1201 {
1202 int i;
1203 char *p,*q;
1204 char buf[100];
1205 int nid,min,max;
1206 char *type,*def,*value;
1207 CONF_VALUE *v;
1208 X509_NAME *subj;
1209 subj = X509_REQ_get_subject_name(req);
bad40585
BM
1210
1211 if(!batch)
1212 {
1213 BIO_printf(bio_err,"You are about to be asked to enter information that will be incorporated\n");
1214 BIO_printf(bio_err,"into your certificate request.\n");
1215 BIO_printf(bio_err,"What you are about to enter is what is called a Distinguished Name or a DN.\n");
1216 BIO_printf(bio_err,"There are quite a few fields but you can leave some blank\n");
1217 BIO_printf(bio_err,"For some fields there will be a default value,\n");
1218 BIO_printf(bio_err,"If you enter '.', the field will be left blank.\n");
1219 BIO_printf(bio_err,"-----\n");
1220 }
b38f9f66
DSH
1221
1222
1223 if (sk_CONF_VALUE_num(dn_sk))
1224 {
1225 i= -1;
1226start: for (;;)
1227 {
1228 i++;
1229 if (sk_CONF_VALUE_num(dn_sk) <= i) break;
1230
1231 v=sk_CONF_VALUE_value(dn_sk,i);
1232 p=q=NULL;
1233 type=v->name;
1234 if(!check_end(type,"_min") || !check_end(type,"_max") ||
1235 !check_end(type,"_default") ||
1236 !check_end(type,"_value")) continue;
1237 /* Skip past any leading X. X: X, etc to allow for
1238 * multiple instances
1239 */
1240 for(p = v->name; *p ; p++)
1241 if ((*p == ':') || (*p == ',') ||
1242 (*p == '.')) {
1243 p++;
1244 if(*p) type = p;
1245 break;
1246 }
1247 /* If OBJ not recognised ignore it */
1248 if ((nid=OBJ_txt2nid(type)) == NID_undef) goto start;
1249 sprintf(buf,"%s_default",v->name);
1250 if ((def=CONF_get_string(req_conf,dn_sect,buf)) == NULL)
2c0d1012
BM
1251 {
1252 ERR_clear_error();
b38f9f66 1253 def="";
2c0d1012 1254 }
b38f9f66
DSH
1255
1256 sprintf(buf,"%s_value",v->name);
1257 if ((value=CONF_get_string(req_conf,dn_sect,buf)) == NULL)
2c0d1012
BM
1258 {
1259 ERR_clear_error();
b38f9f66 1260 value=NULL;
2c0d1012 1261 }
b38f9f66
DSH
1262
1263 sprintf(buf,"%s_min",v->name);
1264 min=(int)CONF_get_number(req_conf,dn_sect,buf);
1265
1266 sprintf(buf,"%s_max",v->name);
1267 max=(int)CONF_get_number(req_conf,dn_sect,buf);
1268
1269 if (!add_DN_object(subj,v->value,def,value,nid,
1270 min,max))
1271 return 0;
1272 }
1273 if (X509_NAME_entry_count(subj) == 0)
1274 {
1275 BIO_printf(bio_err,"error, no objects specified in config file\n");
1276 return 0;
1277 }
1278
1279 if (attribs)
1280 {
bad40585 1281 if ((attr_sk != NULL) && (sk_CONF_VALUE_num(attr_sk) > 0) && (!batch))
b38f9f66
DSH
1282 {
1283 BIO_printf(bio_err,"\nPlease enter the following 'extra' attributes\n");
1284 BIO_printf(bio_err,"to be sent with your certificate request\n");
1285 }
1286
1287 i= -1;
1288start2: for (;;)
1289 {
1290 i++;
1291 if ((attr_sk == NULL) ||
1292 (sk_CONF_VALUE_num(attr_sk) <= i))
1293 break;
1294
1295 v=sk_CONF_VALUE_value(attr_sk,i);
1296 type=v->name;
1297 if ((nid=OBJ_txt2nid(type)) == NID_undef)
1298 goto start2;
1299
1300 sprintf(buf,"%s_default",type);
1301 if ((def=CONF_get_string(req_conf,attr_sect,buf))
1302 == NULL)
2c0d1012
BM
1303 {
1304 ERR_clear_error();
b38f9f66 1305 def="";
2c0d1012
BM
1306 }
1307
b38f9f66
DSH
1308
1309 sprintf(buf,"%s_value",type);
1310 if ((value=CONF_get_string(req_conf,attr_sect,buf))
1311 == NULL)
2c0d1012
BM
1312 {
1313 ERR_clear_error();
b38f9f66 1314 value=NULL;
2c0d1012 1315 }
b38f9f66
DSH
1316
1317 sprintf(buf,"%s_min",type);
1318 min=(int)CONF_get_number(req_conf,attr_sect,buf);
1319
1320 sprintf(buf,"%s_max",type);
1321 max=(int)CONF_get_number(req_conf,attr_sect,buf);
1322
6e6bc352 1323 if (!add_attribute_object(req,
b38f9f66
DSH
1324 v->value,def,value,nid,min,max))
1325 return 0;
1326 }
1327 }
1328 }
1329 else
1330 {
1331 BIO_printf(bio_err,"No template, please set one up.\n");
1332 return 0;
1333 }
1334
1335 return 1;
1336
1337 }
1338
1339static int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *dn_sk,
1340 STACK_OF(CONF_VALUE) *attr_sk, int attribs)
1341 {
1342 int i;
1343 char *p,*q;
1344 char *type;
1345 CONF_VALUE *v;
1346 X509_NAME *subj;
1347
1348 subj = X509_REQ_get_subject_name(req);
1349
1350 for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++)
1351 {
1352 v=sk_CONF_VALUE_value(dn_sk,i);
1353 p=q=NULL;
1354 type=v->name;
1355 /* Skip past any leading X. X: X, etc to allow for
1356 * multiple instances
1357 */
1358 for(p = v->name; *p ; p++)
97d8e82c 1359#ifndef CHARSET_EBCDIC
b38f9f66 1360 if ((*p == ':') || (*p == ',') || (*p == '.')) {
97d8e82c
RL
1361#else
1362 if ((*p == os_toascii[':']) || (*p == os_toascii[',']) || (*p == os_toascii['.'])) {
1363#endif
b38f9f66
DSH
1364 p++;
1365 if(*p) type = p;
1366 break;
1367 }
1368 if (!X509_NAME_add_entry_by_txt(subj,type, MBSTRING_ASC,
1369 (unsigned char *) v->value,-1,-1,0)) return 0;
1370
1371 }
1372
1373 if (!X509_NAME_entry_count(subj))
1374 {
1375 BIO_printf(bio_err,"error, no objects specified in config file\n");
1376 return 0;
1377 }
b38f9f66
DSH
1378 if (attribs)
1379 {
6e6bc352 1380 for (i = 0; i < sk_CONF_VALUE_num(attr_sk); i++)
b38f9f66 1381 {
b38f9f66 1382 v=sk_CONF_VALUE_value(attr_sk,i);
c7cb16a8 1383 if(!X509_REQ_add1_attr_by_txt(req, v->name, MBSTRING_ASC,
6e6bc352 1384 (unsigned char *)v->value, -1)) return 0;
b38f9f66
DSH
1385 }
1386 }
b38f9f66
DSH
1387 return 1;
1388 }
1389
1390
6b691a5c
UM
1391static int add_DN_object(X509_NAME *n, char *text, char *def, char *value,
1392 int nid, int min, int max)
d02b48c6 1393 {
74400f73 1394 int i,ret=0;
d02b48c6 1395 MS_STATIC char buf[1024];
6e6bc352 1396start:
bad40585 1397 if (!batch) BIO_printf(bio_err,"%s [%s]:",text,def);
d58d092b 1398 (void)BIO_flush(bio_err);
bad40585 1399 if(value != NULL)
d02b48c6
RE
1400 {
1401 strcpy(buf,value);
1402 strcat(buf,"\n");
1403 BIO_printf(bio_err,"%s\n",value);
1404 }
1405 else
1406 {
1407 buf[0]='\0';
bad40585
BM
1408 if (!batch)
1409 {
1410 fgets(buf,1024,stdin);
1411 }
1412 else
1413 {
1414 buf[0] = '\n';
1415 buf[1] = '\0';
1416 }
d02b48c6
RE
1417 }
1418
1419 if (buf[0] == '\0') return(0);
1420 else if (buf[0] == '\n')
1421 {
1422 if ((def == NULL) || (def[0] == '\0'))
1423 return(1);
1424 strcpy(buf,def);
1425 strcat(buf,"\n");
1426 }
1427 else if ((buf[0] == '.') && (buf[1] == '\n')) return(1);
1428
1429 i=strlen(buf);
1430 if (buf[i-1] != '\n')
1431 {
1432 BIO_printf(bio_err,"weird input :-(\n");
1433 return(0);
1434 }
1435 buf[--i]='\0';
a53955d8
UM
1436#ifdef CHARSET_EBCDIC
1437 ebcdic2ascii(buf, buf, i);
1438#endif
6e6bc352 1439 if(!req_check_len(i, min, max)) goto start;
74400f73
DSH
1440 if (!X509_NAME_add_entry_by_NID(n,nid, MBSTRING_ASC,
1441 (unsigned char *) buf, -1,-1,0)) goto err;
d02b48c6
RE
1442 ret=1;
1443err:
d02b48c6
RE
1444 return(ret);
1445 }
1446
6e6bc352 1447static int add_attribute_object(X509_REQ *req, char *text,
d500de16
BL
1448 char *def, char *value, int nid, int min,
1449 int max)
d02b48c6 1450 {
6e6bc352 1451 int i;
d02b48c6 1452 static char buf[1024];
d02b48c6
RE
1453
1454start:
bad40585 1455 if (!batch) BIO_printf(bio_err,"%s [%s]:",text,def);
d58d092b 1456 (void)BIO_flush(bio_err);
d02b48c6
RE
1457 if (value != NULL)
1458 {
1459 strcpy(buf,value);
1460 strcat(buf,"\n");
1461 BIO_printf(bio_err,"%s\n",value);
1462 }
1463 else
1464 {
1465 buf[0]='\0';
bad40585
BM
1466 if (!batch)
1467 {
1468 fgets(buf,1024,stdin);
1469 }
1470 else
1471 {
1472 buf[0] = '\n';
1473 buf[1] = '\0';
1474 }
d02b48c6
RE
1475 }
1476
1477 if (buf[0] == '\0') return(0);
1478 else if (buf[0] == '\n')
1479 {
1480 if ((def == NULL) || (def[0] == '\0'))
1481 return(1);
1482 strcpy(buf,def);
1483 strcat(buf,"\n");
1484 }
1485 else if ((buf[0] == '.') && (buf[1] == '\n')) return(1);
1486
1487 i=strlen(buf);
1488 if (buf[i-1] != '\n')
1489 {
1490 BIO_printf(bio_err,"weird input :-(\n");
1491 return(0);
1492 }
1493 buf[--i]='\0';
97d8e82c
RL
1494#ifdef CHARSET_EBCDIC
1495 ebcdic2ascii(buf, buf, i);
1496#endif
6e6bc352 1497 if(!req_check_len(i, min, max)) goto start;
d02b48c6 1498
c7cb16a8 1499 if(!X509_REQ_add1_attr_by_NID(req, nid, MBSTRING_ASC,
6e6bc352
DSH
1500 (unsigned char *)buf, -1)) {
1501 BIO_printf(bio_err, "Error adding attribute\n");
1502 ERR_print_errors(bio_err);
d02b48c6 1503 goto err;
6e6bc352 1504 }
d02b48c6 1505
d02b48c6
RE
1506 return(1);
1507err:
d02b48c6
RE
1508 return(0);
1509 }
1510
cf1b7d96 1511#ifndef OPENSSL_NO_RSA
b4f76582 1512static void MS_CALLBACK req_cb(int p, int n, void *arg)
d02b48c6
RE
1513 {
1514 char c='*';
1515
1516 if (p == 0) c='.';
1517 if (p == 1) c='+';
1518 if (p == 2) c='*';
1519 if (p == 3) c='\n';
58964a49 1520 BIO_write((BIO *)arg,&c,1);
d58d092b 1521 (void)BIO_flush((BIO *)arg);
d02b48c6
RE
1522#ifdef LINT
1523 p=n;
1524#endif
1525 }
752d706a 1526#endif
d02b48c6 1527
6e6bc352 1528static int req_check_len(int len, int min, int max)
d02b48c6 1529 {
d02b48c6
RE
1530 if (len < min)
1531 {
1532 BIO_printf(bio_err,"string is too short, it needs to be at least %d bytes long\n",min);
1533 return(0);
1534 }
1535 if ((max != 0) && (len > max))
1536 {
1537 BIO_printf(bio_err,"string is too long, it needs to be less than %d bytes long\n",max);
1538 return(0);
1539 }
1540 return(1);
1541 }
a43aa73e
DSH
1542
1543/* Check if the end of a string matches 'end' */
6b691a5c 1544static int check_end(char *str, char *end)
a43aa73e
DSH
1545{
1546 int elen, slen;
1547 char *tmp;
1548 elen = strlen(end);
1549 slen = strlen(str);
1550 if(elen > slen) return 1;
1551 tmp = str + slen - elen;
a43aa73e
DSH
1552 return strcmp(tmp, end);
1553}