Extend all the loading functions to take an engine pointer, a pass
[openssl.git] / apps / req.c
1 /* apps/req.c */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
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>
63 #ifdef OPENSSL_NO_STDIO
64 #define APPS_WIN16
65 #endif
66 #include "apps.h"
67 #include <openssl/bio.h>
68 #include <openssl/evp.h>
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>
76 #include <openssl/engine.h>
77
78 #define SECTION         "req"
79
80 #define BITS            "default_bits"
81 #define KEYFILE         "default_keyfile"
82 #define PROMPT          "prompt"
83 #define DISTINGUISHED_NAME      "distinguished_name"
84 #define ATTRIBUTES      "attributes"
85 #define V3_EXTENSIONS   "x509_extensions"
86 #define REQ_EXTENSIONS  "req_extensions"
87 #define STRING_MASK     "string_mask"
88
89 #define DEFAULT_KEY_LENGTH      512
90 #define MIN_KEY_LENGTH          384
91
92 #undef PROG
93 #define PROG    req_main
94
95 /* -inform arg  - input format - default PEM (DER or PEM)
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).
105  * -keyform arg - key file format.
106  * -rand file(s) - load the file(s) into the PRNG.
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
114 static int make_REQ(X509_REQ *req,EVP_PKEY *pkey,char *dn,int attribs);
115 static int build_subject(X509_REQ *req, char *subj);
116 static 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);
119 static int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *sk,
120                                 STACK_OF(CONF_VALUE) *attr, int attribs);
121 static int add_attribute_object(X509_REQ *req, char *text,
122                                 char *def, char *value, int nid, int min,
123                                 int max);
124 static int add_DN_object(X509_NAME *n, char *text, char *def, char *value,
125         int nid,int min,int max);
126 #ifndef OPENSSL_NO_RSA
127 static void MS_CALLBACK req_cb(int p,int n,void *arg);
128 #endif
129 static int req_check_len(int len,int min,int max);
130 static int check_end(char *str, char *end);
131 #ifndef MONOLITH
132 static char *default_config_file=NULL;
133 static LHASH *config=NULL;
134 #endif
135 static LHASH *req_conf=NULL;
136 static int batch=0;
137
138 #define TYPE_RSA        1
139 #define TYPE_DSA        2
140 #define TYPE_DH         3
141
142 int MAIN(int, char **);
143
144 int MAIN(int argc, char **argv)
145         {
146         ENGINE *e = NULL;
147 #ifndef OPENSSL_NO_DSA
148         DSA *dsa_params=NULL;
149 #endif
150         unsigned long nmflag = 0;
151         int ex=1,x509=0,days=30;
152         X509 *x509ss=NULL;
153         X509_REQ *req=NULL;
154         EVP_PKEY *pkey=NULL;
155         int i,badops=0,newreq=0,newkey= -1,verbose=0,pkey_type=TYPE_RSA;
156         BIO *in=NULL,*out=NULL;
157         int informat,outformat,verify=0,noout=0,text=0,keyform=FORMAT_PEM;
158         int nodes=0,kludge=0,newhdr=0,subject=0;
159         char *infile,*outfile,*prog,*keyfile=NULL,*template=NULL,*keyout=NULL;
160         char *engine=NULL;
161         char *extensions = NULL;
162         char *req_exts = NULL;
163         const EVP_CIPHER *cipher=NULL;
164         ASN1_INTEGER *serial = NULL;
165         int modulus=0;
166         char *inrand=NULL;
167         char *passargin = NULL, *passargout = NULL;
168         char *passin = NULL, *passout = NULL;
169         char *p;
170         char *subj = NULL;
171         const EVP_MD *md_alg=NULL,*digest=EVP_md5();
172 #ifndef MONOLITH
173         MS_STATIC char config_name[256];
174 #endif
175
176         req_conf = NULL;
177 #ifndef OPENSSL_NO_DES
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)
184                         BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
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                         }
206                 else if (strcmp(*argv,"-engine") == 0)
207                         {
208                         if (--argc < 1) goto bad;
209                         engine= *(++argv);
210                         }
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                         {
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                         }
245                 else if (strcmp(*argv,"-passin") == 0)
246                         {
247                         if (--argc < 1) goto bad;
248                         passargin= *(++argv);
249                         }
250                 else if (strcmp(*argv,"-passout") == 0)
251                         {
252                         if (--argc < 1) goto bad;
253                         passargout= *(++argv);
254                         }
255                 else if (strcmp(*argv,"-rand") == 0)
256                         {
257                         if (--argc < 1) goto bad;
258                         inrand= *(++argv);
259                         }
260                 else if (strcmp(*argv,"-newkey") == 0)
261                         {
262                         int is_numeric;
263
264                         if (--argc < 1) goto bad;
265                         p= *(++argv);
266                         is_numeric = p[0] >= '0' && p[0] <= '9';
267                         if (strncmp("rsa:",p,4) == 0 || is_numeric)
268                                 {
269                                 pkey_type=TYPE_RSA;
270                                 if(!is_numeric)
271                                     p+=4;
272                                 newkey= atoi(p);
273                                 }
274                         else
275 #ifndef OPENSSL_NO_DSA
276                                 if (strncmp("dsa:",p,4) == 0)
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                                         }
288                                 if ((dsa_params=PEM_read_bio_DSAparams(in,NULL,NULL,NULL)) == NULL)
289                                         {
290                                         ERR_clear_error();
291                                         (void)BIO_reset(in);
292                                         if ((xtmp=PEM_read_bio_X509(in,NULL,NULL,NULL)) == NULL)
293                                                 {
294                                                 BIO_printf(bio_err,"unable to load DSA parameters from file\n");
295                                                 goto end;
296                                                 }
297
298                                         dtmp=X509_get_pubkey(xtmp);
299                                         if (dtmp->type == EVP_PKEY_DSA)
300                                                 dsa_params=DSAparams_dup(dtmp->pkey.dsa);
301                                         EVP_PKEY_free(dtmp);
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                                                 }
308                                         }
309                                 BIO_free(in);
310                                 newkey=BN_num_bits(dsa_params->p);
311                                 in=NULL;
312                                 }
313                         else 
314 #endif
315 #ifndef OPENSSL_NO_DH
316                                 if (strncmp("dh:",p,4) == 0)
317                                 {
318                                 pkey_type=TYPE_DH;
319                                 p+=3;
320                                 }
321                         else
322 #endif
323                                 pkey_type=TYPE_RSA;
324
325                         newreq=1;
326                         }
327                 else if (strcmp(*argv,"-batch") == 0)
328                         batch=1;
329                 else if (strcmp(*argv,"-newhdr") == 0)
330                         newhdr=1;
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;
339                 else if (strcmp(*argv,"-verbose") == 0)
340                         verbose=1;
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;
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;
356                 else if (strcmp(*argv,"-subj") == 0)
357                         {
358                         if (--argc < 1) goto bad;
359                         subj= *(++argv);
360                         }
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                         }
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                         }
373                 else if ((md_alg=EVP_get_digestbyname(&((*argv)[1]))) != NULL)
374                         {
375                         /* ok */
376                         digest=md_alg;
377                         }
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                         }
388                 else
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                 {
400 bad:
401                 BIO_printf(bio_err,"%s [options] <infile >outfile\n",prog);
402                 BIO_printf(bio_err,"where options  are\n");
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");
405                 BIO_printf(bio_err," -in arg        input file\n");
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");
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");
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");
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");
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");
423                 BIO_printf(bio_err," -[digest]      Digest to sign with (md5, sha1, md2, mdc2)\n");
424                 BIO_printf(bio_err," -config file   request template file.\n");
425                 BIO_printf(bio_err," -subj arg      set or modify request subject\n");
426                 BIO_printf(bio_err," -new           new request.\n");
427                 BIO_printf(bio_err," -batch         do not ask anything during request generation\n");
428                 BIO_printf(bio_err," -x509          output a x509 structure instead of a cert. req.\n");
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");
431                 BIO_printf(bio_err," -newhdr        output \"NEW\" in the header lines\n");
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");
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");
436                 goto end;
437                 }
438
439         ERR_load_crypto_strings();
440         if(!app_passwd(bio_err, passargin, passargout, &passin, &passout)) {
441                 BIO_printf(bio_err, "Error getting passwords\n");
442                 goto end;
443         }
444
445 #ifndef MONOLITH /* else this has happened in openssl.c (global `config') */
446         /* Lets load up our environment a little */
447         p=getenv("OPENSSL_CONF");
448         if (p == NULL)
449                 p=getenv("SSLEAY_CONF");
450         if (p == NULL)
451                 {
452                 strcpy(config_name,X509_get_default_cert_area());
453 #ifndef OPENSSL_SYS_VMS
454                 strcat(config_name,"/");
455 #endif
456                 strcat(config_name,OPENSSL_CONF);
457                 p=config_name;
458                 }
459         default_config_file=p;
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
486         if (req_conf != NULL)
487                 {
488                 p=CONF_get_string(req_conf,NULL,"oid_file");
489                 if (p == NULL)
490                         ERR_clear_error();
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                 }
510         if(!add_oid_section(bio_err, req_conf)) goto end;
511
512         if (md_alg == NULL)
513                 {
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                         }
522                 }
523
524         if (!extensions)
525                 {
526                 extensions = CONF_get_string(req_conf, SECTION, V3_EXTENSIONS);
527                 if (!extensions)
528                         ERR_clear_error();
529                 }
530         if (extensions) {
531                 /* Check syntax of file */
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)) {
536                         BIO_printf(bio_err,
537                          "Error Loading extension section %s\n", extensions);
538                         goto end;
539                 }
540         }
541
542         if(!passin)
543                 {
544                 passin = CONF_get_string(req_conf, SECTION, "input_password");
545                 if (!passin)
546                         ERR_clear_error();
547                 }
548         
549         if(!passout)
550                 {
551                 passout = CONF_get_string(req_conf, SECTION, "output_password");
552                 if (!passout)
553                         ERR_clear_error();
554                 }
555
556         p = CONF_get_string(req_conf, SECTION, STRING_MASK);
557         if (!p)
558                 ERR_clear_error();
559
560         if(p && !ASN1_STRING_set_default_mask_asc(p)) {
561                 BIO_printf(bio_err, "Invalid global string mask setting %s\n", p);
562                 goto end;
563         }
564
565         if(!req_exts)
566                 {
567                 req_exts = CONF_get_string(req_conf, SECTION, REQ_EXTENSIONS);
568                 if (!req_exts)
569                         ERR_clear_error();
570                 }
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
584         in=BIO_new(BIO_s_file());
585         out=BIO_new(BIO_s_file());
586         if ((in == NULL) || (out == NULL))
587                 goto end;
588
589         if (engine != NULL)
590                 {
591                 if((e = ENGINE_by_id(engine)) == NULL)
592                         {
593                         BIO_printf(bio_err,"invalid engine \"%s\"\n",
594                                 engine);
595                         goto end;
596                         }
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                 }
606
607         if (keyfile != NULL)
608                 {
609                 pkey = load_key(bio_err, keyfile, keyform, NULL, e,
610                         "Private Key");
611                 if (!pkey)
612                         {
613                         /* load_key() has already printed an appropriate
614                            message */
615                         goto end;
616                         }
617                 if (EVP_PKEY_type(pkey->type) == EVP_PKEY_DSA)
618                         {
619                         char *randfile = CONF_get_string(req_conf,SECTION,"RANDFILE");
620                         if (randfile == NULL)
621                                 ERR_clear_error();
622                         app_RAND_load_file(randfile, bio_err, 0);
623                         }
624                 }
625
626         if (newreq && (pkey == NULL))
627                 {
628                 char *randfile = CONF_get_string(req_conf,SECTION,"RANDFILE");
629                 if (randfile == NULL)
630                         ERR_clear_error();
631                 app_RAND_load_file(randfile, bio_err, 0);
632                 if (inrand)
633                         app_RAND_load_files(inrand);
634         
635                 if (newkey <= 0)
636                         {
637                         newkey=(int)CONF_get_number(req_conf,SECTION,BITS);
638                         if (newkey <= 0)
639                                 newkey=DEFAULT_KEY_LENGTH;
640                         }
641
642                 if (newkey < MIN_KEY_LENGTH)
643                         {
644                         BIO_printf(bio_err,"private key length is too short,\n");
645                         BIO_printf(bio_err,"it needs to be at least %d bits, not %d\n",MIN_KEY_LENGTH,newkey);
646                         goto end;
647                         }
648                 BIO_printf(bio_err,"Generating a %d bit %s private key\n",
649                         newkey,(pkey_type == TYPE_RSA)?"RSA":"DSA");
650
651                 if ((pkey=EVP_PKEY_new()) == NULL) goto end;
652
653 #ifndef OPENSSL_NO_RSA
654                 if (pkey_type == TYPE_RSA)
655                         {
656                         if (!EVP_PKEY_assign_RSA(pkey,
657                                 RSA_generate_key(newkey,0x10001,
658                                         req_cb,bio_err)))
659                                 goto end;
660                         }
661                 else
662 #endif
663 #ifndef OPENSSL_NO_DSA
664                         if (pkey_type == TYPE_DSA)
665                         {
666                         if (!DSA_generate_key(dsa_params)) goto end;
667                         if (!EVP_PKEY_assign_DSA(pkey,dsa_params)) goto end;
668                         dsa_params=NULL;
669                         }
670 #endif
671
672                 app_RAND_write_file(randfile, bio_err);
673
674                 if (pkey == NULL) goto end;
675
676                 if (keyout == NULL)
677                         {
678                         keyout=CONF_get_string(req_conf,SECTION,KEYFILE);
679                         if (keyout == NULL)
680                                 ERR_clear_error();
681                         }
682                 
683                 if (keyout == NULL)
684                         {
685                         BIO_printf(bio_err,"writing new private key to stdout\n");
686                         BIO_set_fp(out,stdout,BIO_NOCLOSE);
687 #ifdef OPENSSL_SYS_VMS
688                         {
689                         BIO *tmpbio = BIO_new(BIO_f_linebuffer());
690                         out = BIO_push(tmpbio, out);
691                         }
692 #endif
693                         }
694                 else
695                         {
696                         BIO_printf(bio_err,"writing new private key to '%s'\n",keyout);
697                         if (BIO_write_filename(out,keyout) <= 0)
698                                 {
699                                 perror(keyout);
700                                 goto end;
701                                 }
702                         }
703
704                 p=CONF_get_string(req_conf,SECTION,"encrypt_rsa_key");
705                 if (p == NULL)
706                         {
707                         ERR_clear_error();
708                         p=CONF_get_string(req_conf,SECTION,"encrypt_key");
709                         if (p == NULL)
710                                 ERR_clear_error();
711                         }
712                 if ((p != NULL) && (strcmp(p,"no") == 0))
713                         cipher=NULL;
714                 if (nodes) cipher=NULL;
715                 
716                 i=0;
717 loop:
718                 if (!PEM_write_bio_PrivateKey(out,pkey,cipher,
719                         NULL,0,NULL,passout))
720                         {
721                         if ((ERR_GET_REASON(ERR_peek_error()) ==
722                                 PEM_R_PROBLEMS_GETTING_PASSWORD) && (i < 3))
723                                 {
724                                 ERR_clear_error();
725                                 i++;
726                                 goto loop;
727                                 }
728                         goto end;
729                         }
730                 BIO_printf(bio_err,"-----\n");
731                 }
732
733         if (!newreq)
734                 {
735                 /* Since we are using a pre-existing certificate
736                  * request, the kludge 'format' info should not be
737                  * changed. */
738                 kludge= -1;
739                 if (infile == NULL)
740                         BIO_set_fp(in,stdin,BIO_NOCLOSE);
741                 else
742                         {
743                         if (BIO_read_filename(in,infile) <= 0)
744                                 {
745                                 perror(infile);
746                                 goto end;
747                                 }
748                         }
749
750                 if      (informat == FORMAT_ASN1)
751                         req=d2i_X509_REQ_bio(in,NULL);
752                 else if (informat == FORMAT_PEM)
753                         req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL);
754                 else
755                         {
756                         BIO_printf(bio_err,"bad input format specified for X509 request\n");
757                         goto end;
758                         }
759                 if (req == NULL)
760                         {
761                         BIO_printf(bio_err,"unable to load X509 request\n");
762                         goto end;
763                         }
764                 }
765
766         if (newreq || x509)
767                 {
768                 if (pkey == NULL)
769                         {
770                         BIO_printf(bio_err,"you need to specify a private key\n");
771                         goto end;
772                         }
773 #ifndef OPENSSL_NO_DSA
774                 if (pkey->type == EVP_PKEY_DSA)
775                         digest=EVP_dss1();
776 #endif
777                 if (req == NULL)
778                         {
779                         req=X509_REQ_new();
780                         if (req == NULL)
781                                 {
782                                 goto end;
783                                 }
784
785                         i=make_REQ(req,pkey,subj,!x509);
786                         subj=NULL; /* done processing '-subj' option */
787                         if ((kludge > 0) && !sk_X509_ATTRIBUTE_num(req->req_info->attributes))
788                                 {
789                                 sk_X509_ATTRIBUTE_free(req->req_info->attributes);
790                                 req->req_info->attributes = NULL;
791                                 }
792                         if (!i)
793                                 {
794                                 BIO_printf(bio_err,"problems making Certificate Request\n");
795                                 goto end;
796                                 }
797                         }
798                 if (x509)
799                         {
800                         EVP_PKEY *tmppkey;
801                         X509V3_CTX ext_ctx;
802                         if ((x509ss=X509_new()) == NULL) goto end;
803
804                         /* Set version to V3 */
805                         if(!X509_set_version(x509ss, 2)) goto end;
806                         if (serial)
807                                 X509_set_serialNumber(x509ss, serial);
808                         else
809                                 ASN1_INTEGER_set(X509_get_serialNumber(x509ss),0L);
810
811                         X509_set_issuer_name(x509ss,
812                                 X509_REQ_get_subject_name(req));
813                         X509_gmtime_adj(X509_get_notBefore(x509ss),0);
814                         X509_gmtime_adj(X509_get_notAfter(x509ss),
815                                 (long)60*60*24*days);
816                         X509_set_subject_name(x509ss,
817                                 X509_REQ_get_subject_name(req));
818                         tmppkey = X509_REQ_get_pubkey(req);
819                         X509_set_pubkey(x509ss,tmppkey);
820                         EVP_PKEY_free(tmppkey);
821
822                         /* Set up V3 context struct */
823
824                         X509V3_set_ctx(&ext_ctx, x509ss, x509ss, NULL, NULL, 0);
825                         X509V3_set_conf_lhash(&ext_ctx, req_conf);
826
827                         /* Add extensions */
828                         if(extensions && !X509V3_EXT_add_conf(req_conf, 
829                                         &ext_ctx, extensions, x509ss))
830                                 {
831                                 BIO_printf(bio_err,
832                                         "Error Loading extension section %s\n",
833                                         extensions);
834                                 goto end;
835                                 }
836                         
837                         if (!(i=X509_sign(x509ss,pkey,digest)))
838                                 goto end;
839                         }
840                 else
841                         {
842                         X509V3_CTX ext_ctx;
843
844                         /* Set up V3 context struct */
845
846                         X509V3_set_ctx(&ext_ctx, NULL, NULL, req, NULL, 0);
847                         X509V3_set_conf_lhash(&ext_ctx, req_conf);
848
849                         /* Add extensions */
850                         if(req_exts && !X509V3_EXT_REQ_add_conf(req_conf, 
851                                         &ext_ctx, req_exts, req))
852                                 {
853                                 BIO_printf(bio_err,
854                                         "Error Loading extension section %s\n",
855                                         req_exts);
856                                 goto end;
857                                 }
858                         if (!(i=X509_REQ_sign(req,pkey,digest)))
859                                 goto end;
860                         }
861                 }
862
863         if (subj && x509)
864                 {
865                 BIO_printf(bio_err, "Cannot modifiy certificate subject\n");
866                 goto end;
867                 }
868
869         if (subj && !x509)
870                 {
871                 if (verbose)
872                         {
873                         BIO_printf(bio_err, "Modifying Request's Subject\n");
874                         print_name(bio_err, "old subject=", X509_REQ_get_subject_name(req), nmflag);
875                         }
876
877                 if (build_subject(req, subj) == 0)
878                         {
879                         BIO_printf(bio_err, "ERROR: cannot modify subject\n");
880                         ex=1;
881                         goto end;
882                         }
883
884                 req->req_info->enc.modified = 1;
885
886                 if (verbose)
887                         {
888                         print_name(bio_err, "new subject=", X509_REQ_get_subject_name(req), nmflag);
889                         }
890                 }
891
892         if (verify && !x509)
893                 {
894                 int tmp=0;
895
896                 if (pkey == NULL)
897                         {
898                         pkey=X509_REQ_get_pubkey(req);
899                         tmp=1;
900                         if (pkey == NULL) goto end;
901                         }
902
903                 i=X509_REQ_verify(req,pkey);
904                 if (tmp) {
905                         EVP_PKEY_free(pkey);
906                         pkey=NULL;
907                 }
908
909                 if (i < 0)
910                         {
911                         goto end;
912                         }
913                 else if (i == 0)
914                         {
915                         BIO_printf(bio_err,"verify failure\n");
916                         }
917                 else /* if (i > 0) */
918                         BIO_printf(bio_err,"verify OK\n");
919                 }
920
921         if (noout && !text && !modulus && !subject)
922                 {
923                 ex=0;
924                 goto end;
925                 }
926
927         if (outfile == NULL)
928                 {
929                 BIO_set_fp(out,stdout,BIO_NOCLOSE);
930 #ifdef OPENSSL_SYS_VMS
931                 {
932                 BIO *tmpbio = BIO_new(BIO_f_linebuffer());
933                 out = BIO_push(tmpbio, out);
934                 }
935 #endif
936                 }
937         else
938                 {
939                 if ((keyout != NULL) && (strcmp(outfile,keyout) == 0))
940                         i=(int)BIO_append_filename(out,outfile);
941                 else
942                         i=(int)BIO_write_filename(out,outfile);
943                 if (!i)
944                         {
945                         perror(outfile);
946                         goto end;
947                         }
948                 }
949
950         if (text)
951                 {
952                 if (x509)
953                         X509_print(out,x509ss);
954                 else    
955                         X509_REQ_print(out,req);
956                 }
957
958         if(subject) 
959                 {
960                 if(x509)
961                         print_name(out, "subject=", X509_get_subject_name(x509ss), nmflag);
962                 else
963                         print_name(out, "subject=", X509_REQ_get_subject_name(req), nmflag);
964                 }
965
966         if (modulus)
967                 {
968                 EVP_PKEY *pubkey;
969
970                 if (x509)
971                         pubkey=X509_get_pubkey(x509ss);
972                 else
973                         pubkey=X509_REQ_get_pubkey(req);
974                 if (pubkey == NULL)
975                         {
976                         fprintf(stdout,"Modulus=unavailable\n");
977                         goto end; 
978                         }
979                 fprintf(stdout,"Modulus=");
980 #ifndef OPENSSL_NO_RSA
981                 if (pubkey->type == EVP_PKEY_RSA)
982                         BN_print(out,pubkey->pkey.rsa->n);
983                 else
984 #endif
985                         fprintf(stdout,"Wrong Algorithm type");
986                 fprintf(stdout,"\n");
987                 }
988
989         if (!noout && !x509)
990                 {
991                 if      (outformat == FORMAT_ASN1)
992                         i=i2d_X509_REQ_bio(out,req);
993                 else if (outformat == FORMAT_PEM) {
994                         if(newhdr) i=PEM_write_bio_X509_REQ_NEW(out,req);
995                         else i=PEM_write_bio_X509_REQ(out,req);
996                 } else {
997                         BIO_printf(bio_err,"bad output format specified for outfile\n");
998                         goto end;
999                         }
1000                 if (!i)
1001                         {
1002                         BIO_printf(bio_err,"unable to write X509 request\n");
1003                         goto end;
1004                         }
1005                 }
1006         if (!noout && x509 && (x509ss != NULL))
1007                 {
1008                 if      (outformat == FORMAT_ASN1)
1009                         i=i2d_X509_bio(out,x509ss);
1010                 else if (outformat == FORMAT_PEM)
1011                         i=PEM_write_bio_X509(out,x509ss);
1012                 else    {
1013                         BIO_printf(bio_err,"bad output format specified for outfile\n");
1014                         goto end;
1015                         }
1016                 if (!i)
1017                         {
1018                         BIO_printf(bio_err,"unable to write X509 certificate\n");
1019                         goto end;
1020                         }
1021                 }
1022         ex=0;
1023 end:
1024         if (ex)
1025                 {
1026                 ERR_print_errors(bio_err);
1027                 }
1028         if ((req_conf != NULL) && (req_conf != config)) CONF_free(req_conf);
1029         BIO_free(in);
1030         BIO_free_all(out);
1031         EVP_PKEY_free(pkey);
1032         X509_REQ_free(req);
1033         X509_free(x509ss);
1034         ASN1_INTEGER_free(serial);
1035         if(passargin && passin) OPENSSL_free(passin);
1036         if(passargout && passout) OPENSSL_free(passout);
1037         OBJ_cleanup();
1038 #ifndef OPENSSL_NO_DSA
1039         if (dsa_params != NULL) DSA_free(dsa_params);
1040 #endif
1041         EXIT(ex);
1042         }
1043
1044 static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, char *subj, int attribs)
1045         {
1046         int ret=0,i;
1047         char no_prompt = 0;
1048         STACK_OF(CONF_VALUE) *dn_sk, *attr_sk = NULL;
1049         char *tmp, *dn_sect,*attr_sect;
1050
1051         tmp=CONF_get_string(req_conf,SECTION,PROMPT);
1052         if (tmp == NULL)
1053                 ERR_clear_error();
1054         if((tmp != NULL) && !strcmp(tmp, "no")) no_prompt = 1;
1055
1056         dn_sect=CONF_get_string(req_conf,SECTION,DISTINGUISHED_NAME);
1057         if (dn_sect == NULL)
1058                 {
1059                 BIO_printf(bio_err,"unable to find '%s' in config\n",
1060                         DISTINGUISHED_NAME);
1061                 goto err;
1062                 }
1063         dn_sk=CONF_get_section(req_conf,dn_sect);
1064         if (dn_sk == NULL)
1065                 {
1066                 BIO_printf(bio_err,"unable to get '%s' section\n",dn_sect);
1067                 goto err;
1068                 }
1069
1070         attr_sect=CONF_get_string(req_conf,SECTION,ATTRIBUTES);
1071         if (attr_sect == NULL)
1072                 {
1073                 ERR_clear_error();              
1074                 attr_sk=NULL;
1075                 }
1076         else
1077                 {
1078                 attr_sk=CONF_get_section(req_conf,attr_sect);
1079                 if (attr_sk == NULL)
1080                         {
1081                         BIO_printf(bio_err,"unable to get '%s' section\n",attr_sect);
1082                         goto err;
1083                         }
1084                 }
1085
1086         /* setup version number */
1087         if (!X509_REQ_set_version(req,0L)) goto err; /* version 1 */
1088
1089         if (no_prompt) 
1090                 i = auto_info(req, dn_sk, attr_sk, attribs);
1091         else 
1092                 {
1093                 if (subj)
1094                         i = build_subject(req, subj);
1095                 else
1096                         i = prompt_info(req, dn_sk, dn_sect, attr_sk, attr_sect, attribs);
1097                 }
1098         if(!i) goto err;
1099
1100         X509_REQ_set_pubkey(req,pkey);
1101
1102         ret=1;
1103 err:
1104         return(ret);
1105         }
1106
1107 static int build_subject(X509_REQ *req, char *subject)
1108         {
1109         X509_NAME *n = NULL;
1110
1111         int i, nid, ne_num=0;
1112
1113         char *ne_name = NULL;
1114         char *ne_value = NULL;
1115
1116         char *tmp = NULL;
1117         char *p[2];
1118
1119         char *str_list[256];
1120        
1121         p[0] = ",/";
1122         p[1] = "=";
1123
1124         n = X509_NAME_new();
1125
1126         tmp = strtok(subject, p[0]);
1127         while((tmp != NULL) && (ne_num < (sizeof str_list/sizeof *str_list)))
1128                 {
1129                 char *token = tmp;
1130
1131                 while (token[0] == ' ')
1132                         token++;
1133                 str_list[ne_num] = token;
1134
1135                 tmp = strtok(NULL, p[0]);
1136                 ne_num++;
1137                 }
1138
1139         for(i = 0; i < ne_num; i++)
1140                 {
1141                 ne_name  = strtok(str_list[i], p[1]);
1142                 ne_value = strtok(NULL, p[1]);
1143
1144                 if ((nid=OBJ_txt2nid(ne_name)) == NID_undef)
1145                         {
1146                         BIO_printf(bio_err, "Subject Attribute %s has no known NID, skipped\n", ne_name);
1147                         continue;
1148                         }
1149
1150                 if (ne_value == NULL)
1151                         {
1152                         BIO_printf(bio_err, "No value provided for Subject Attribute %s, skipped\n", ne_name);
1153                         continue;
1154                         }
1155
1156                 if (!X509_NAME_add_entry_by_NID(n, nid, MBSTRING_ASC, (unsigned char*)ne_value, -1,-1,0))
1157                         {
1158                         X509_NAME_free(n);
1159                         return 0;
1160                         }
1161                 }
1162
1163         if (!X509_REQ_set_subject_name(req, n))
1164                 return 0;
1165         X509_NAME_free(n);
1166         return 1;
1167 }
1168
1169
1170 static int prompt_info(X509_REQ *req,
1171                 STACK_OF(CONF_VALUE) *dn_sk, char *dn_sect,
1172                 STACK_OF(CONF_VALUE) *attr_sk, char *attr_sect, int attribs)
1173         {
1174         int i;
1175         char *p,*q;
1176         char buf[100];
1177         int nid,min,max;
1178         char *type,*def,*value;
1179         CONF_VALUE *v;
1180         X509_NAME *subj;
1181         subj = X509_REQ_get_subject_name(req);
1182
1183         if(!batch)
1184                 {
1185                 BIO_printf(bio_err,"You are about to be asked to enter information that will be incorporated\n");
1186                 BIO_printf(bio_err,"into your certificate request.\n");
1187                 BIO_printf(bio_err,"What you are about to enter is what is called a Distinguished Name or a DN.\n");
1188                 BIO_printf(bio_err,"There are quite a few fields but you can leave some blank\n");
1189                 BIO_printf(bio_err,"For some fields there will be a default value,\n");
1190                 BIO_printf(bio_err,"If you enter '.', the field will be left blank.\n");
1191                 BIO_printf(bio_err,"-----\n");
1192                 }
1193
1194
1195         if (sk_CONF_VALUE_num(dn_sk))
1196                 {
1197                 i= -1;
1198 start:          for (;;)
1199                         {
1200                         i++;
1201                         if (sk_CONF_VALUE_num(dn_sk) <= i) break;
1202
1203                         v=sk_CONF_VALUE_value(dn_sk,i);
1204                         p=q=NULL;
1205                         type=v->name;
1206                         if(!check_end(type,"_min") || !check_end(type,"_max") ||
1207                                 !check_end(type,"_default") ||
1208                                          !check_end(type,"_value")) continue;
1209                         /* Skip past any leading X. X: X, etc to allow for
1210                          * multiple instances 
1211                          */
1212                         for(p = v->name; *p ; p++) 
1213                                 if ((*p == ':') || (*p == ',') ||
1214                                                          (*p == '.')) {
1215                                         p++;
1216                                         if(*p) type = p;
1217                                         break;
1218                                 }
1219                         /* If OBJ not recognised ignore it */
1220                         if ((nid=OBJ_txt2nid(type)) == NID_undef) goto start;
1221                         sprintf(buf,"%s_default",v->name);
1222                         if ((def=CONF_get_string(req_conf,dn_sect,buf)) == NULL)
1223                                 {
1224                                 ERR_clear_error();
1225                                 def="";
1226                                 }
1227                                 
1228                         sprintf(buf,"%s_value",v->name);
1229                         if ((value=CONF_get_string(req_conf,dn_sect,buf)) == NULL)
1230                                 {
1231                                 ERR_clear_error();
1232                                 value=NULL;
1233                                 }
1234
1235                         sprintf(buf,"%s_min",v->name);
1236                         min=(int)CONF_get_number(req_conf,dn_sect,buf);
1237
1238                         sprintf(buf,"%s_max",v->name);
1239                         max=(int)CONF_get_number(req_conf,dn_sect,buf);
1240
1241                         if (!add_DN_object(subj,v->value,def,value,nid,
1242                                 min,max))
1243                                 return 0;
1244                         }
1245                 if (X509_NAME_entry_count(subj) == 0)
1246                         {
1247                         BIO_printf(bio_err,"error, no objects specified in config file\n");
1248                         return 0;
1249                         }
1250
1251                 if (attribs)
1252                         {
1253                         if ((attr_sk != NULL) && (sk_CONF_VALUE_num(attr_sk) > 0) && (!batch))
1254                                 {
1255                                 BIO_printf(bio_err,"\nPlease enter the following 'extra' attributes\n");
1256                                 BIO_printf(bio_err,"to be sent with your certificate request\n");
1257                                 }
1258
1259                         i= -1;
1260 start2:                 for (;;)
1261                                 {
1262                                 i++;
1263                                 if ((attr_sk == NULL) ||
1264                                             (sk_CONF_VALUE_num(attr_sk) <= i))
1265                                         break;
1266
1267                                 v=sk_CONF_VALUE_value(attr_sk,i);
1268                                 type=v->name;
1269                                 if ((nid=OBJ_txt2nid(type)) == NID_undef)
1270                                         goto start2;
1271
1272                                 sprintf(buf,"%s_default",type);
1273                                 if ((def=CONF_get_string(req_conf,attr_sect,buf))
1274                                         == NULL)
1275                                         {
1276                                         ERR_clear_error();
1277                                         def="";
1278                                         }
1279                                 
1280                                 
1281                                 sprintf(buf,"%s_value",type);
1282                                 if ((value=CONF_get_string(req_conf,attr_sect,buf))
1283                                         == NULL)
1284                                         {
1285                                         ERR_clear_error();
1286                                         value=NULL;
1287                                         }
1288
1289                                 sprintf(buf,"%s_min",type);
1290                                 min=(int)CONF_get_number(req_conf,attr_sect,buf);
1291
1292                                 sprintf(buf,"%s_max",type);
1293                                 max=(int)CONF_get_number(req_conf,attr_sect,buf);
1294
1295                                 if (!add_attribute_object(req,
1296                                         v->value,def,value,nid,min,max))
1297                                         return 0;
1298                                 }
1299                         }
1300                 }
1301         else
1302                 {
1303                 BIO_printf(bio_err,"No template, please set one up.\n");
1304                 return 0;
1305                 }
1306
1307         return 1;
1308
1309         }
1310
1311 static int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *dn_sk,
1312                         STACK_OF(CONF_VALUE) *attr_sk, int attribs)
1313         {
1314         int i;
1315         char *p,*q;
1316         char *type;
1317         CONF_VALUE *v;
1318         X509_NAME *subj;
1319
1320         subj = X509_REQ_get_subject_name(req);
1321
1322         for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++)
1323                 {
1324                 v=sk_CONF_VALUE_value(dn_sk,i);
1325                 p=q=NULL;
1326                 type=v->name;
1327                 /* Skip past any leading X. X: X, etc to allow for
1328                  * multiple instances 
1329                  */
1330                 for(p = v->name; *p ; p++) 
1331 #ifndef CHARSET_EBCDIC
1332                         if ((*p == ':') || (*p == ',') || (*p == '.')) {
1333 #else
1334                         if ((*p == os_toascii[':']) || (*p == os_toascii[',']) || (*p == os_toascii['.'])) {
1335 #endif
1336                                 p++;
1337                                 if(*p) type = p;
1338                                 break;
1339                         }
1340                 if (!X509_NAME_add_entry_by_txt(subj,type, MBSTRING_ASC,
1341                                 (unsigned char *) v->value,-1,-1,0)) return 0;
1342
1343                 }
1344
1345                 if (!X509_NAME_entry_count(subj))
1346                         {
1347                         BIO_printf(bio_err,"error, no objects specified in config file\n");
1348                         return 0;
1349                         }
1350                 if (attribs)
1351                         {
1352                         for (i = 0; i < sk_CONF_VALUE_num(attr_sk); i++)
1353                                 {
1354                                 v=sk_CONF_VALUE_value(attr_sk,i);
1355                                 if(!X509_REQ_add1_attr_by_txt(req, v->name, MBSTRING_ASC,
1356                                         (unsigned char *)v->value, -1)) return 0;
1357                                 }
1358                         }
1359         return 1;
1360         }
1361
1362
1363 static int add_DN_object(X509_NAME *n, char *text, char *def, char *value,
1364              int nid, int min, int max)
1365         {
1366         int i,ret=0;
1367         MS_STATIC char buf[1024];
1368 start:
1369         if (!batch) BIO_printf(bio_err,"%s [%s]:",text,def);
1370         (void)BIO_flush(bio_err);
1371         if(value != NULL)
1372                 {
1373                 strcpy(buf,value);
1374                 strcat(buf,"\n");
1375                 BIO_printf(bio_err,"%s\n",value);
1376                 }
1377         else
1378                 {
1379                 buf[0]='\0';
1380                 if (!batch)
1381                         {
1382                         fgets(buf,1024,stdin);
1383                         }
1384                 else
1385                         {
1386                         buf[0] = '\n';
1387                         buf[1] = '\0';
1388                         }
1389                 }
1390
1391         if (buf[0] == '\0') return(0);
1392         else if (buf[0] == '\n')
1393                 {
1394                 if ((def == NULL) || (def[0] == '\0'))
1395                         return(1);
1396                 strcpy(buf,def);
1397                 strcat(buf,"\n");
1398                 }
1399         else if ((buf[0] == '.') && (buf[1] == '\n')) return(1);
1400
1401         i=strlen(buf);
1402         if (buf[i-1] != '\n')
1403                 {
1404                 BIO_printf(bio_err,"weird input :-(\n");
1405                 return(0);
1406                 }
1407         buf[--i]='\0';
1408 #ifdef CHARSET_EBCDIC
1409         ebcdic2ascii(buf, buf, i);
1410 #endif
1411         if(!req_check_len(i, min, max)) goto start;
1412         if (!X509_NAME_add_entry_by_NID(n,nid, MBSTRING_ASC,
1413                                 (unsigned char *) buf, -1,-1,0)) goto err;
1414         ret=1;
1415 err:
1416         return(ret);
1417         }
1418
1419 static int add_attribute_object(X509_REQ *req, char *text,
1420                                 char *def, char *value, int nid, int min,
1421                                 int max)
1422         {
1423         int i;
1424         static char buf[1024];
1425
1426 start:
1427         if (!batch) BIO_printf(bio_err,"%s [%s]:",text,def);
1428         (void)BIO_flush(bio_err);
1429         if (value != NULL)
1430                 {
1431                 strcpy(buf,value);
1432                 strcat(buf,"\n");
1433                 BIO_printf(bio_err,"%s\n",value);
1434                 }
1435         else
1436                 {
1437                 buf[0]='\0';
1438                 if (!batch)
1439                         {
1440                         fgets(buf,1024,stdin);
1441                         }
1442                 else
1443                         {
1444                         buf[0] = '\n';
1445                         buf[1] = '\0';
1446                         }
1447                 }
1448
1449         if (buf[0] == '\0') return(0);
1450         else if (buf[0] == '\n')
1451                 {
1452                 if ((def == NULL) || (def[0] == '\0'))
1453                         return(1);
1454                 strcpy(buf,def);
1455                 strcat(buf,"\n");
1456                 }
1457         else if ((buf[0] == '.') && (buf[1] == '\n')) return(1);
1458
1459         i=strlen(buf);
1460         if (buf[i-1] != '\n')
1461                 {
1462                 BIO_printf(bio_err,"weird input :-(\n");
1463                 return(0);
1464                 }
1465         buf[--i]='\0';
1466 #ifdef CHARSET_EBCDIC
1467         ebcdic2ascii(buf, buf, i);
1468 #endif
1469         if(!req_check_len(i, min, max)) goto start;
1470
1471         if(!X509_REQ_add1_attr_by_NID(req, nid, MBSTRING_ASC,
1472                                         (unsigned char *)buf, -1)) {
1473                 BIO_printf(bio_err, "Error adding attribute\n");
1474                 ERR_print_errors(bio_err);
1475                 goto err;
1476         }
1477
1478         return(1);
1479 err:
1480         return(0);
1481         }
1482
1483 #ifndef OPENSSL_NO_RSA
1484 static void MS_CALLBACK req_cb(int p, int n, void *arg)
1485         {
1486         char c='*';
1487
1488         if (p == 0) c='.';
1489         if (p == 1) c='+';
1490         if (p == 2) c='*';
1491         if (p == 3) c='\n';
1492         BIO_write((BIO *)arg,&c,1);
1493         (void)BIO_flush((BIO *)arg);
1494 #ifdef LINT
1495         p=n;
1496 #endif
1497         }
1498 #endif
1499
1500 static int req_check_len(int len, int min, int max)
1501         {
1502         if (len < min)
1503                 {
1504                 BIO_printf(bio_err,"string is too short, it needs to be at least %d bytes long\n",min);
1505                 return(0);
1506                 }
1507         if ((max != 0) && (len > max))
1508                 {
1509                 BIO_printf(bio_err,"string is too long, it needs to be less than  %d bytes long\n",max);
1510                 return(0);
1511                 }
1512         return(1);
1513         }
1514
1515 /* Check if the end of a string matches 'end' */
1516 static int check_end(char *str, char *end)
1517 {
1518         int elen, slen; 
1519         char *tmp;
1520         elen = strlen(end);
1521         slen = strlen(str);
1522         if(elen > slen) return 1;
1523         tmp = str + slen - elen;
1524         return strcmp(tmp, end);
1525 }