c6e88ba4e1ca26b15ea6bf991ee2eb3e45788216
[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 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,int attribs);
115 static int prompt_info(X509_REQ *req,
116                 STACK_OF(CONF_VALUE) *dn_sk, char *dn_sect,
117                 STACK_OF(CONF_VALUE) *attr_sk, char *attr_sect, int attribs);
118 static int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *sk,
119                                 STACK_OF(CONF_VALUE) *attr, int attribs);
120 static int add_attribute_object(X509_REQ *req, char *text,
121                                 char *def, char *value, int nid, int min,
122                                 int max);
123 static int add_DN_object(X509_NAME *n, char *text, char *def, char *value,
124         int nid,int min,int max);
125 #ifndef NO_RSA
126 static void MS_CALLBACK req_cb(int p,int n,void *arg);
127 #endif
128 static int req_check_len(int len,int min,int max);
129 static int check_end(char *str, char *end);
130 #ifndef MONOLITH
131 static char *default_config_file=NULL;
132 static LHASH *config=NULL;
133 #endif
134 static LHASH *req_conf=NULL;
135
136 #define TYPE_RSA        1
137 #define TYPE_DSA        2
138 #define TYPE_DH         3
139
140 int MAIN(int, char **);
141
142 int MAIN(int argc, char **argv)
143         {
144         ENGINE *e = NULL;
145 #ifndef NO_DSA
146         DSA *dsa_params=NULL;
147 #endif
148         unsigned long nmflag = 0;
149         int ex=1,x509=0,days=30;
150         X509 *x509ss=NULL;
151         X509_REQ *req=NULL;
152         EVP_PKEY *pkey=NULL;
153         int i,badops=0,newreq=0,newkey= -1,pkey_type=TYPE_RSA;
154         BIO *in=NULL,*out=NULL;
155         int informat,outformat,verify=0,noout=0,text=0,keyform=FORMAT_PEM;
156         int nodes=0,kludge=0,newhdr=0,subject=0;
157         char *infile,*outfile,*prog,*keyfile=NULL,*template=NULL,*keyout=NULL;
158         char *engine=NULL;
159         char *extensions = NULL;
160         char *req_exts = NULL;
161         EVP_CIPHER *cipher=NULL;
162         ASN1_INTEGER *serial = NULL;
163         int modulus=0;
164         char *inrand=NULL;
165         char *passargin = NULL, *passargout = NULL;
166         char *passin = NULL, *passout = NULL;
167         char *p;
168         const EVP_MD *md_alg=NULL,*digest=EVP_md5();
169 #ifndef MONOLITH
170         MS_STATIC char config_name[256];
171 #endif
172
173         req_conf = NULL;
174 #ifndef NO_DES
175         cipher=EVP_des_ede3_cbc();
176 #endif
177         apps_startup();
178
179         if (bio_err == NULL)
180                 if ((bio_err=BIO_new(BIO_s_file())) != NULL)
181                         BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
182
183         infile=NULL;
184         outfile=NULL;
185         informat=FORMAT_PEM;
186         outformat=FORMAT_PEM;
187
188         prog=argv[0];
189         argc--;
190         argv++;
191         while (argc >= 1)
192                 {
193                 if      (strcmp(*argv,"-inform") == 0)
194                         {
195                         if (--argc < 1) goto bad;
196                         informat=str2fmt(*(++argv));
197                         }
198                 else if (strcmp(*argv,"-outform") == 0)
199                         {
200                         if (--argc < 1) goto bad;
201                         outformat=str2fmt(*(++argv));
202                         }
203                 else if (strcmp(*argv,"-engine") == 0)
204                         {
205                         if (--argc < 1) goto bad;
206                         engine= *(++argv);
207                         }
208                 else if (strcmp(*argv,"-key") == 0)
209                         {
210                         if (--argc < 1) goto bad;
211                         keyfile= *(++argv);
212                         }
213                 else if (strcmp(*argv,"-new") == 0)
214                         {
215                         newreq=1;
216                         }
217                 else if (strcmp(*argv,"-config") == 0)
218                         {       
219                         if (--argc < 1) goto bad;
220                         template= *(++argv);
221                         }
222                 else if (strcmp(*argv,"-keyform") == 0)
223                         {
224                         if (--argc < 1) goto bad;
225                         keyform=str2fmt(*(++argv));
226                         }
227                 else if (strcmp(*argv,"-in") == 0)
228                         {
229                         if (--argc < 1) goto bad;
230                         infile= *(++argv);
231                         }
232                 else if (strcmp(*argv,"-out") == 0)
233                         {
234                         if (--argc < 1) goto bad;
235                         outfile= *(++argv);
236                         }
237                 else if (strcmp(*argv,"-keyout") == 0)
238                         {
239                         if (--argc < 1) goto bad;
240                         keyout= *(++argv);
241                         }
242                 else if (strcmp(*argv,"-passin") == 0)
243                         {
244                         if (--argc < 1) goto bad;
245                         passargin= *(++argv);
246                         }
247                 else if (strcmp(*argv,"-passout") == 0)
248                         {
249                         if (--argc < 1) goto bad;
250                         passargout= *(++argv);
251                         }
252                 else if (strcmp(*argv,"-rand") == 0)
253                         {
254                         if (--argc < 1) goto bad;
255                         inrand= *(++argv);
256                         }
257                 else if (strcmp(*argv,"-newkey") == 0)
258                         {
259                         int is_numeric;
260
261                         if (--argc < 1) goto bad;
262                         p= *(++argv);
263                         is_numeric = p[0] >= '0' && p[0] <= '9';
264                         if (strncmp("rsa:",p,4) == 0 || is_numeric)
265                                 {
266                                 pkey_type=TYPE_RSA;
267                                 if(!is_numeric)
268                                     p+=4;
269                                 newkey= atoi(p);
270                                 }
271                         else
272 #ifndef NO_DSA
273                                 if (strncmp("dsa:",p,4) == 0)
274                                 {
275                                 X509 *xtmp=NULL;
276                                 EVP_PKEY *dtmp;
277
278                                 pkey_type=TYPE_DSA;
279                                 p+=4;
280                                 if ((in=BIO_new_file(p,"r")) == NULL)
281                                         {
282                                         perror(p);
283                                         goto end;
284                                         }
285                                 if ((dsa_params=PEM_read_bio_DSAparams(in,NULL,NULL,NULL)) == NULL)
286                                         {
287                                         ERR_clear_error();
288                                         (void)BIO_reset(in);
289                                         if ((xtmp=PEM_read_bio_X509(in,NULL,NULL,NULL)) == NULL)
290                                                 {
291                                                 BIO_printf(bio_err,"unable to load DSA parameters from file\n");
292                                                 goto end;
293                                                 }
294
295                                         dtmp=X509_get_pubkey(xtmp);
296                                         if (dtmp->type == EVP_PKEY_DSA)
297                                                 dsa_params=DSAparams_dup(dtmp->pkey.dsa);
298                                         EVP_PKEY_free(dtmp);
299                                         X509_free(xtmp);
300                                         if (dsa_params == NULL)
301                                                 {
302                                                 BIO_printf(bio_err,"Certificate does not contain DSA parameters\n");
303                                                 goto end;
304                                                 }
305                                         }
306                                 BIO_free(in);
307                                 newkey=BN_num_bits(dsa_params->p);
308                                 in=NULL;
309                                 }
310                         else 
311 #endif
312 #ifndef NO_DH
313                                 if (strncmp("dh:",p,4) == 0)
314                                 {
315                                 pkey_type=TYPE_DH;
316                                 p+=3;
317                                 }
318                         else
319 #endif
320                                 pkey_type=TYPE_RSA;
321
322                         newreq=1;
323                         }
324                 else if (strcmp(*argv,"-newhdr") == 0)
325                         newhdr=1;
326                 else if (strcmp(*argv,"-modulus") == 0)
327                         modulus=1;
328                 else if (strcmp(*argv,"-verify") == 0)
329                         verify=1;
330                 else if (strcmp(*argv,"-nodes") == 0)
331                         nodes=1;
332                 else if (strcmp(*argv,"-noout") == 0)
333                         noout=1;
334                 else if (strcmp(*argv,"-nameopt") == 0)
335                         {
336                         if (--argc < 1) goto bad;
337                         if (!set_name_ex(&nmflag, *(++argv))) goto bad;
338                         }
339                 else if (strcmp(*argv,"-subject") == 0)
340                         subject=1;
341                 else if (strcmp(*argv,"-text") == 0)
342                         text=1;
343                 else if (strcmp(*argv,"-x509") == 0)
344                         x509=1;
345                 else if (strcmp(*argv,"-asn1-kludge") == 0)
346                         kludge=1;
347                 else if (strcmp(*argv,"-no-asn1-kludge") == 0)
348                         kludge=0;
349                 else if (strcmp(*argv,"-days") == 0)
350                         {
351                         if (--argc < 1) goto bad;
352                         days= atoi(*(++argv));
353                         if (days == 0) days=30;
354                         }
355                 else if (strcmp(*argv,"-set_serial") == 0)
356                         {
357                         if (--argc < 1) goto bad;
358                         serial = s2i_ASN1_INTEGER(NULL, *(++argv));
359                         if (!serial) goto bad;
360                         }
361                 else if ((md_alg=EVP_get_digestbyname(&((*argv)[1]))) != NULL)
362                         {
363                         /* ok */
364                         digest=md_alg;
365                         }
366                 else if (strcmp(*argv,"-extensions") == 0)
367                         {
368                         if (--argc < 1) goto bad;
369                         extensions = *(++argv);
370                         }
371                 else if (strcmp(*argv,"-reqexts") == 0)
372                         {
373                         if (--argc < 1) goto bad;
374                         req_exts = *(++argv);
375                         }
376                 else
377                         {
378                         BIO_printf(bio_err,"unknown option %s\n",*argv);
379                         badops=1;
380                         break;
381                         }
382                 argc--;
383                 argv++;
384                 }
385
386         if (badops)
387                 {
388 bad:
389                 BIO_printf(bio_err,"%s [options] <infile >outfile\n",prog);
390                 BIO_printf(bio_err,"where options  are\n");
391                 BIO_printf(bio_err," -inform arg    input format - DER or PEM\n");
392                 BIO_printf(bio_err," -outform arg   output format - DER or PEM\n");
393                 BIO_printf(bio_err," -in arg        input file\n");
394                 BIO_printf(bio_err," -out arg       output file\n");
395                 BIO_printf(bio_err," -text          text form of request\n");
396                 BIO_printf(bio_err," -noout         do not output REQ\n");
397                 BIO_printf(bio_err," -verify        verify signature on REQ\n");
398                 BIO_printf(bio_err," -modulus       RSA modulus\n");
399                 BIO_printf(bio_err," -nodes         don't encrypt the output key\n");
400                 BIO_printf(bio_err," -engine e      use engine e, possibly a hardware device.\n");
401                 BIO_printf(bio_err," -key file  use the private key contained in file\n");
402                 BIO_printf(bio_err," -keyform arg   key file format\n");
403                 BIO_printf(bio_err," -keyout arg    file to send the key to\n");
404                 BIO_printf(bio_err," -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
405                 BIO_printf(bio_err,"                load the file (or the files in the directory) into\n");
406                 BIO_printf(bio_err,"                the random number generator\n");
407                 BIO_printf(bio_err," -newkey rsa:bits generate a new RSA key of 'bits' in size\n");
408                 BIO_printf(bio_err," -newkey dsa:file generate a new DSA key, parameters taken from CA in 'file'\n");
409
410                 BIO_printf(bio_err," -[digest]      Digest to sign with (md5, sha1, md2, mdc2)\n");
411                 BIO_printf(bio_err," -config file   request template file.\n");
412                 BIO_printf(bio_err," -new           new request.\n");
413                 BIO_printf(bio_err," -x509          output a x509 structure instead of a cert. req.\n");
414                 BIO_printf(bio_err," -days          number of days a certificate generated by -x509 is valid for.\n");
415                 BIO_printf(bio_err," -set_serial    serial number to use for a certificate generated by -x509.\n");
416                 BIO_printf(bio_err," -newhdr        output \"NEW\" in the header lines\n");
417                 BIO_printf(bio_err," -asn1-kludge   Output the 'request' in a format that is wrong but some CA's\n");
418                 BIO_printf(bio_err,"                have been reported as requiring\n");
419                 BIO_printf(bio_err," -extensions .. specify certificate extension section (override value in config file)\n");
420                 BIO_printf(bio_err," -reqexts ..    specify request extension section (override value in config file)\n");
421                 goto end;
422                 }
423
424         ERR_load_crypto_strings();
425         if(!app_passwd(bio_err, passargin, passargout, &passin, &passout)) {
426                 BIO_printf(bio_err, "Error getting passwords\n");
427                 goto end;
428         }
429
430 #ifndef MONOLITH /* else this has happened in openssl.c (global `config') */
431         /* Lets load up our environment a little */
432         p=getenv("OPENSSL_CONF");
433         if (p == NULL)
434                 p=getenv("SSLEAY_CONF");
435         if (p == NULL)
436                 {
437                 strcpy(config_name,X509_get_default_cert_area());
438 #ifndef VMS
439                 strcat(config_name,"/");
440 #endif
441                 strcat(config_name,OPENSSL_CONF);
442                 p=config_name;
443                 }
444         default_config_file=p;
445         config=CONF_load(config,p,NULL);
446 #endif
447
448         if (template != NULL)
449                 {
450                 long errline;
451
452                 BIO_printf(bio_err,"Using configuration from %s\n",template);
453                 req_conf=CONF_load(NULL,template,&errline);
454                 if (req_conf == NULL)
455                         {
456                         BIO_printf(bio_err,"error on line %ld of %s\n",errline,template);
457                         goto end;
458                         }
459                 }
460         else
461                 {
462                 req_conf=config;
463                 BIO_printf(bio_err,"Using configuration from %s\n",
464                         default_config_file);
465                 if (req_conf == NULL)
466                         {
467                         BIO_printf(bio_err,"Unable to load config info\n");
468                         }
469                 }
470
471         if (req_conf != NULL)
472                 {
473                 p=CONF_get_string(req_conf,NULL,"oid_file");
474                 if (p == NULL)
475                         ERR_clear_error();
476                 if (p != NULL)
477                         {
478                         BIO *oid_bio;
479
480                         oid_bio=BIO_new_file(p,"r");
481                         if (oid_bio == NULL) 
482                                 {
483                                 /*
484                                 BIO_printf(bio_err,"problems opening %s for extra oid's\n",p);
485                                 ERR_print_errors(bio_err);
486                                 */
487                                 }
488                         else
489                                 {
490                                 OBJ_create_objects(oid_bio);
491                                 BIO_free(oid_bio);
492                                 }
493                         }
494                 }
495         if(!add_oid_section(bio_err, req_conf)) goto end;
496
497         if (md_alg == NULL)
498                 {
499                 p=CONF_get_string(req_conf,SECTION,"default_md");
500                 if (p == NULL)
501                         ERR_clear_error();
502                 if (p != NULL)
503                         {
504                         if ((md_alg=EVP_get_digestbyname(p)) != NULL)
505                                 digest=md_alg;
506                         }
507                 }
508
509         if (!extensions)
510                 {
511                 extensions = CONF_get_string(req_conf, SECTION, V3_EXTENSIONS);
512                 if (!extensions)
513                         ERR_clear_error();
514                 }
515         if (extensions) {
516                 /* Check syntax of file */
517                 X509V3_CTX ctx;
518                 X509V3_set_ctx_test(&ctx);
519                 X509V3_set_conf_lhash(&ctx, req_conf);
520                 if(!X509V3_EXT_add_conf(req_conf, &ctx, extensions, NULL)) {
521                         BIO_printf(bio_err,
522                          "Error Loading extension section %s\n", extensions);
523                         goto end;
524                 }
525         }
526
527         if(!passin)
528                 {
529                 passin = CONF_get_string(req_conf, SECTION, "input_password");
530                 if (!passin)
531                         ERR_clear_error();
532                 }
533         
534         if(!passout)
535                 {
536                 passout = CONF_get_string(req_conf, SECTION, "output_password");
537                 if (!passout)
538                         ERR_clear_error();
539                 }
540
541         p = CONF_get_string(req_conf, SECTION, STRING_MASK);
542         if (!p)
543                 ERR_clear_error();
544
545         if(p && !ASN1_STRING_set_default_mask_asc(p)) {
546                 BIO_printf(bio_err, "Invalid global string mask setting %s\n", p);
547                 goto end;
548         }
549
550         if(!req_exts)
551                 {
552                 req_exts = CONF_get_string(req_conf, SECTION, REQ_EXTENSIONS);
553                 if (!req_exts)
554                         ERR_clear_error();
555                 }
556         if(req_exts) {
557                 /* Check syntax of file */
558                 X509V3_CTX ctx;
559                 X509V3_set_ctx_test(&ctx);
560                 X509V3_set_conf_lhash(&ctx, req_conf);
561                 if(!X509V3_EXT_add_conf(req_conf, &ctx, req_exts, NULL)) {
562                         BIO_printf(bio_err,
563                          "Error Loading request extension section %s\n",
564                                                                 req_exts);
565                         goto end;
566                 }
567         }
568
569         in=BIO_new(BIO_s_file());
570         out=BIO_new(BIO_s_file());
571         if ((in == NULL) || (out == NULL))
572                 goto end;
573
574         if (engine != NULL)
575                 {
576                 if((e = ENGINE_by_id(engine)) == NULL)
577                         {
578                         BIO_printf(bio_err,"invalid engine \"%s\"\n",
579                                 engine);
580                         goto end;
581                         }
582                 if(!ENGINE_set_default(e, ENGINE_METHOD_ALL))
583                         {
584                         BIO_printf(bio_err,"can't use that engine\n");
585                         goto end;
586                         }
587                 BIO_printf(bio_err,"engine \"%s\" set.\n", engine);
588                 /* Free our "structural" reference. */
589                 ENGINE_free(e);
590                 }
591
592         if (keyfile != NULL)
593                 {
594                 if (keyform == FORMAT_ENGINE)
595                         {
596                         if (!e)
597                                 {
598                                 BIO_printf(bio_err,"no engine specified\n");
599                                 goto end;
600                                 }
601                         pkey = ENGINE_load_private_key(e, keyfile, NULL);
602                         }
603                 else
604                         {
605                         if (BIO_read_filename(in,keyfile) <= 0)
606                                 {
607                                 perror(keyfile);
608                                 goto end;
609                                 }
610
611                         if (keyform == FORMAT_ASN1)
612                                 pkey=d2i_PrivateKey_bio(in,NULL);
613                         else if (keyform == FORMAT_PEM)
614                                 {
615                                 pkey=PEM_read_bio_PrivateKey(in,NULL,NULL,
616                                         passin);
617                                 }
618                         else
619                                 {
620                                 BIO_printf(bio_err,"bad input format specified for X509 request\n");
621                                 goto end;
622                                 }
623                         }
624
625                 if (pkey == NULL)
626                         {
627                         BIO_printf(bio_err,"unable to load Private key\n");
628                         goto end;
629                         }
630                 if (EVP_PKEY_type(pkey->type) == EVP_PKEY_DSA)
631                         {
632                         char *randfile = CONF_get_string(req_conf,SECTION,"RANDFILE");
633                         if (randfile == NULL)
634                                 ERR_clear_error();
635                         app_RAND_load_file(randfile, bio_err, 0);
636                         }
637                 }
638
639         if (newreq && (pkey == NULL))
640                 {
641                 char *randfile = CONF_get_string(req_conf,SECTION,"RANDFILE");
642                 if (randfile == NULL)
643                         ERR_clear_error();
644                 app_RAND_load_file(randfile, bio_err, 0);
645                 if (inrand)
646                         app_RAND_load_files(inrand);
647         
648                 if (newkey <= 0)
649                         {
650                         newkey=(int)CONF_get_number(req_conf,SECTION,BITS);
651                         if (newkey <= 0)
652                                 newkey=DEFAULT_KEY_LENGTH;
653                         }
654
655                 if (newkey < MIN_KEY_LENGTH)
656                         {
657                         BIO_printf(bio_err,"private key length is too short,\n");
658                         BIO_printf(bio_err,"it needs to be at least %d bits, not %d\n",MIN_KEY_LENGTH,newkey);
659                         goto end;
660                         }
661                 BIO_printf(bio_err,"Generating a %d bit %s private key\n",
662                         newkey,(pkey_type == TYPE_RSA)?"RSA":"DSA");
663
664                 if ((pkey=EVP_PKEY_new()) == NULL) goto end;
665
666 #ifndef NO_RSA
667                 if (pkey_type == TYPE_RSA)
668                         {
669                         if (!EVP_PKEY_assign_RSA(pkey,
670                                 RSA_generate_key(newkey,0x10001,
671                                         req_cb,bio_err)))
672                                 goto end;
673                         }
674                 else
675 #endif
676 #ifndef NO_DSA
677                         if (pkey_type == TYPE_DSA)
678                         {
679                         if (!DSA_generate_key(dsa_params)) goto end;
680                         if (!EVP_PKEY_assign_DSA(pkey,dsa_params)) goto end;
681                         dsa_params=NULL;
682                         }
683 #endif
684
685                 app_RAND_write_file(randfile, bio_err);
686
687                 if (pkey == NULL) goto end;
688
689                 if (keyout == NULL)
690                         {
691                         keyout=CONF_get_string(req_conf,SECTION,KEYFILE);
692                         if (keyout == NULL)
693                                 ERR_clear_error();
694                         }
695                 
696                 if (keyout == NULL)
697                         {
698                         BIO_printf(bio_err,"writing new private key to stdout\n");
699                         BIO_set_fp(out,stdout,BIO_NOCLOSE);
700 #ifdef VMS
701                         {
702                         BIO *tmpbio = BIO_new(BIO_f_linebuffer());
703                         out = BIO_push(tmpbio, out);
704                         }
705 #endif
706                         }
707                 else
708                         {
709                         BIO_printf(bio_err,"writing new private key to '%s'\n",keyout);
710                         if (BIO_write_filename(out,keyout) <= 0)
711                                 {
712                                 perror(keyout);
713                                 goto end;
714                                 }
715                         }
716
717                 p=CONF_get_string(req_conf,SECTION,"encrypt_rsa_key");
718                 if (p == NULL)
719                         {
720                         ERR_clear_error();
721                         p=CONF_get_string(req_conf,SECTION,"encrypt_key");
722                         if (p == NULL)
723                                 ERR_clear_error();
724                         }
725                 if ((p != NULL) && (strcmp(p,"no") == 0))
726                         cipher=NULL;
727                 if (nodes) cipher=NULL;
728                 
729                 i=0;
730 loop:
731                 if (!PEM_write_bio_PrivateKey(out,pkey,cipher,
732                         NULL,0,NULL,passout))
733                         {
734                         if ((ERR_GET_REASON(ERR_peek_error()) ==
735                                 PEM_R_PROBLEMS_GETTING_PASSWORD) && (i < 3))
736                                 {
737                                 ERR_clear_error();
738                                 i++;
739                                 goto loop;
740                                 }
741                         goto end;
742                         }
743                 BIO_printf(bio_err,"-----\n");
744                 }
745
746         if (!newreq)
747                 {
748                 /* Since we are using a pre-existing certificate
749                  * request, the kludge 'format' info should not be
750                  * changed. */
751                 kludge= -1;
752                 if (infile == NULL)
753                         BIO_set_fp(in,stdin,BIO_NOCLOSE);
754                 else
755                         {
756                         if (BIO_read_filename(in,infile) <= 0)
757                                 {
758                                 perror(infile);
759                                 goto end;
760                                 }
761                         }
762
763                 if      (informat == FORMAT_ASN1)
764                         req=d2i_X509_REQ_bio(in,NULL);
765                 else if (informat == FORMAT_PEM)
766                         req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL);
767                 else
768                         {
769                         BIO_printf(bio_err,"bad input format specified for X509 request\n");
770                         goto end;
771                         }
772                 if (req == NULL)
773                         {
774                         BIO_printf(bio_err,"unable to load X509 request\n");
775                         goto end;
776                         }
777                 }
778
779         if (newreq || x509)
780                 {
781                 if (pkey == NULL)
782                         {
783                         BIO_printf(bio_err,"you need to specify a private key\n");
784                         goto end;
785                         }
786 #ifndef NO_DSA
787                 if (pkey->type == EVP_PKEY_DSA)
788                         digest=EVP_dss1();
789 #endif
790                 if (req == NULL)
791                         {
792                         req=X509_REQ_new();
793                         if (req == NULL)
794                                 {
795                                 goto end;
796                                 }
797
798                         i=make_REQ(req,pkey,!x509);
799                         if ((kludge > 0) && !sk_X509_ATTRIBUTE_num(req->req_info->attributes))
800                                 {
801                                 sk_X509_ATTRIBUTE_free(req->req_info->attributes);
802                                 req->req_info->attributes = NULL;
803                                 }
804                         if (!i)
805                                 {
806                                 BIO_printf(bio_err,"problems making Certificate Request\n");
807                                 goto end;
808                                 }
809                         }
810                 if (x509)
811                         {
812                         EVP_PKEY *tmppkey;
813                         X509V3_CTX ext_ctx;
814                         if ((x509ss=X509_new()) == NULL) goto end;
815
816                         /* Set version to V3 */
817                         if(!X509_set_version(x509ss, 2)) goto end;
818                         if (serial)
819                                 X509_set_serialNumber(x509ss, serial);
820                         else
821                                 ASN1_INTEGER_set(X509_get_serialNumber(x509ss),0L);
822
823                         X509_set_issuer_name(x509ss,
824                                 X509_REQ_get_subject_name(req));
825                         X509_gmtime_adj(X509_get_notBefore(x509ss),0);
826                         X509_gmtime_adj(X509_get_notAfter(x509ss),
827                                 (long)60*60*24*days);
828                         X509_set_subject_name(x509ss,
829                                 X509_REQ_get_subject_name(req));
830                         tmppkey = X509_REQ_get_pubkey(req);
831                         X509_set_pubkey(x509ss,tmppkey);
832                         EVP_PKEY_free(tmppkey);
833
834                         /* Set up V3 context struct */
835
836                         X509V3_set_ctx(&ext_ctx, x509ss, x509ss, NULL, NULL, 0);
837                         X509V3_set_conf_lhash(&ext_ctx, req_conf);
838
839                         /* Add extensions */
840                         if(extensions && !X509V3_EXT_add_conf(req_conf, 
841                                         &ext_ctx, extensions, x509ss))
842                             {
843                             BIO_printf(bio_err,
844                                        "Error Loading extension section %s\n",
845                                        extensions);
846                             goto end;
847                             }
848
849                         if (!(i=X509_sign(x509ss,pkey,digest)))
850                                 goto end;
851                         }
852                 else
853                         {
854                         X509V3_CTX ext_ctx;
855
856                         /* Set up V3 context struct */
857
858                         X509V3_set_ctx(&ext_ctx, NULL, NULL, req, NULL, 0);
859                         X509V3_set_conf_lhash(&ext_ctx, req_conf);
860
861                         /* Add extensions */
862                         if(req_exts && !X509V3_EXT_REQ_add_conf(req_conf, 
863                                         &ext_ctx, req_exts, req))
864                             {
865                             BIO_printf(bio_err,
866                                        "Error Loading extension section %s\n",
867                                        req_exts);
868                             goto end;
869                             }
870                         if (!(i=X509_REQ_sign(req,pkey,digest)))
871                                 goto end;
872                         }
873                 }
874
875         if (verify && !x509)
876                 {
877                 int tmp=0;
878
879                 if (pkey == NULL)
880                         {
881                         pkey=X509_REQ_get_pubkey(req);
882                         tmp=1;
883                         if (pkey == NULL) goto end;
884                         }
885
886                 i=X509_REQ_verify(req,pkey);
887                 if (tmp) {
888                         EVP_PKEY_free(pkey);
889                         pkey=NULL;
890                 }
891
892                 if (i < 0)
893                         {
894                         goto end;
895                         }
896                 else if (i == 0)
897                         {
898                         BIO_printf(bio_err,"verify failure\n");
899                         }
900                 else /* if (i > 0) */
901                         BIO_printf(bio_err,"verify OK\n");
902                 }
903
904         if (noout && !text && !modulus && !subject)
905                 {
906                 ex=0;
907                 goto end;
908                 }
909
910         if (outfile == NULL)
911                 {
912                 BIO_set_fp(out,stdout,BIO_NOCLOSE);
913 #ifdef VMS
914                 {
915                 BIO *tmpbio = BIO_new(BIO_f_linebuffer());
916                 out = BIO_push(tmpbio, out);
917                 }
918 #endif
919                 }
920         else
921                 {
922                 if ((keyout != NULL) && (strcmp(outfile,keyout) == 0))
923                         i=(int)BIO_append_filename(out,outfile);
924                 else
925                         i=(int)BIO_write_filename(out,outfile);
926                 if (!i)
927                         {
928                         perror(outfile);
929                         goto end;
930                         }
931                 }
932
933         if (text)
934                 {
935                 if (x509)
936                         X509_print(out,x509ss);
937                 else    
938                         X509_REQ_print(out,req);
939                 }
940
941         if(subject) 
942                 {
943                 if(x509)
944                         print_name(out, "subject=", X509_get_subject_name(x509ss), nmflag);
945                 else
946                         print_name(out, "subject=", X509_REQ_get_subject_name(req), nmflag);
947                 }
948
949         if (modulus)
950                 {
951                 EVP_PKEY *pubkey;
952
953                 if (x509)
954                         pubkey=X509_get_pubkey(x509ss);
955                 else
956                         pubkey=X509_REQ_get_pubkey(req);
957                 if (pubkey == NULL)
958                         {
959                         fprintf(stdout,"Modulus=unavailable\n");
960                         goto end; 
961                         }
962                 fprintf(stdout,"Modulus=");
963 #ifndef NO_RSA
964                 if (pubkey->type == EVP_PKEY_RSA)
965                         BN_print(out,pubkey->pkey.rsa->n);
966                 else
967 #endif
968                         fprintf(stdout,"Wrong Algorithm type");
969                 fprintf(stdout,"\n");
970                 }
971
972         if (!noout && !x509)
973                 {
974                 if      (outformat == FORMAT_ASN1)
975                         i=i2d_X509_REQ_bio(out,req);
976                 else if (outformat == FORMAT_PEM) {
977                         if(newhdr) i=PEM_write_bio_X509_REQ_NEW(out,req);
978                         else i=PEM_write_bio_X509_REQ(out,req);
979                 } else {
980                         BIO_printf(bio_err,"bad output format specified for outfile\n");
981                         goto end;
982                         }
983                 if (!i)
984                         {
985                         BIO_printf(bio_err,"unable to write X509 request\n");
986                         goto end;
987                         }
988                 }
989         if (!noout && x509 && (x509ss != NULL))
990                 {
991                 if      (outformat == FORMAT_ASN1)
992                         i=i2d_X509_bio(out,x509ss);
993                 else if (outformat == FORMAT_PEM)
994                         i=PEM_write_bio_X509(out,x509ss);
995                 else    {
996                         BIO_printf(bio_err,"bad output format specified for outfile\n");
997                         goto end;
998                         }
999                 if (!i)
1000                         {
1001                         BIO_printf(bio_err,"unable to write X509 certificate\n");
1002                         goto end;
1003                         }
1004                 }
1005         ex=0;
1006 end:
1007         if (ex)
1008                 {
1009                 ERR_print_errors(bio_err);
1010                 }
1011         if ((req_conf != NULL) && (req_conf != config)) CONF_free(req_conf);
1012         BIO_free(in);
1013         BIO_free_all(out);
1014         EVP_PKEY_free(pkey);
1015         X509_REQ_free(req);
1016         X509_free(x509ss);
1017         ASN1_INTEGER_free(serial);
1018         if(passargin && passin) OPENSSL_free(passin);
1019         if(passargout && passout) OPENSSL_free(passout);
1020         OBJ_cleanup();
1021 #ifndef NO_DSA
1022         if (dsa_params != NULL) DSA_free(dsa_params);
1023 #endif
1024         EXIT(ex);
1025         }
1026
1027 static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, int attribs)
1028         {
1029         int ret=0,i;
1030         char no_prompt = 0;
1031         STACK_OF(CONF_VALUE) *dn_sk, *attr_sk = NULL;
1032         char *tmp, *dn_sect,*attr_sect;
1033
1034         tmp=CONF_get_string(req_conf,SECTION,PROMPT);
1035         if (tmp == NULL)
1036                 ERR_clear_error();
1037         if((tmp != NULL) && !strcmp(tmp, "no")) no_prompt = 1;
1038
1039         dn_sect=CONF_get_string(req_conf,SECTION,DISTINGUISHED_NAME);
1040         if (dn_sect == NULL)
1041                 {
1042                 BIO_printf(bio_err,"unable to find '%s' in config\n",
1043                         DISTINGUISHED_NAME);
1044                 goto err;
1045                 }
1046         dn_sk=CONF_get_section(req_conf,dn_sect);
1047         if (dn_sk == NULL)
1048                 {
1049                 BIO_printf(bio_err,"unable to get '%s' section\n",dn_sect);
1050                 goto err;
1051                 }
1052
1053         attr_sect=CONF_get_string(req_conf,SECTION,ATTRIBUTES);
1054         if (attr_sect == NULL)
1055                 {
1056                 ERR_clear_error();              
1057                 attr_sk=NULL;
1058                 }
1059         else
1060                 {
1061                 attr_sk=CONF_get_section(req_conf,attr_sect);
1062                 if (attr_sk == NULL)
1063                         {
1064                         BIO_printf(bio_err,"unable to get '%s' section\n",attr_sect);
1065                         goto err;
1066                         }
1067                 }
1068
1069         /* setup version number */
1070         if (!X509_REQ_set_version(req,0L)) goto err; /* version 1 */
1071
1072         if(no_prompt) i = auto_info(req, dn_sk, attr_sk, attribs);
1073         else i = prompt_info(req, dn_sk, dn_sect, attr_sk, attr_sect, attribs);
1074         if(!i) goto err;
1075
1076         X509_REQ_set_pubkey(req,pkey);
1077
1078         ret=1;
1079 err:
1080         return(ret);
1081         }
1082
1083
1084 static int prompt_info(X509_REQ *req,
1085                 STACK_OF(CONF_VALUE) *dn_sk, char *dn_sect,
1086                 STACK_OF(CONF_VALUE) *attr_sk, char *attr_sect, int attribs)
1087         {
1088         int i;
1089         char *p,*q;
1090         char buf[100];
1091         int nid,min,max;
1092         char *type,*def,*value;
1093         CONF_VALUE *v;
1094         X509_NAME *subj;
1095         subj = X509_REQ_get_subject_name(req);
1096         BIO_printf(bio_err,"You are about to be asked to enter information that will be incorporated\n");
1097         BIO_printf(bio_err,"into your certificate request.\n");
1098         BIO_printf(bio_err,"What you are about to enter is what is called a Distinguished Name or a DN.\n");
1099         BIO_printf(bio_err,"There are quite a few fields but you can leave some blank\n");
1100         BIO_printf(bio_err,"For some fields there will be a default value,\n");
1101         BIO_printf(bio_err,"If you enter '.', the field will be left blank.\n");
1102         BIO_printf(bio_err,"-----\n");
1103
1104
1105         if (sk_CONF_VALUE_num(dn_sk))
1106                 {
1107                 i= -1;
1108 start:          for (;;)
1109                         {
1110                         i++;
1111                         if (sk_CONF_VALUE_num(dn_sk) <= i) break;
1112
1113                         v=sk_CONF_VALUE_value(dn_sk,i);
1114                         p=q=NULL;
1115                         type=v->name;
1116                         if(!check_end(type,"_min") || !check_end(type,"_max") ||
1117                                 !check_end(type,"_default") ||
1118                                          !check_end(type,"_value")) continue;
1119                         /* Skip past any leading X. X: X, etc to allow for
1120                          * multiple instances 
1121                          */
1122                         for(p = v->name; *p ; p++) 
1123                                 if ((*p == ':') || (*p == ',') ||
1124                                                          (*p == '.')) {
1125                                         p++;
1126                                         if(*p) type = p;
1127                                         break;
1128                                 }
1129                         /* If OBJ not recognised ignore it */
1130                         if ((nid=OBJ_txt2nid(type)) == NID_undef) goto start;
1131                         sprintf(buf,"%s_default",v->name);
1132                         if ((def=CONF_get_string(req_conf,dn_sect,buf)) == NULL)
1133                                 {
1134                                 ERR_clear_error();
1135                                 def="";
1136                                 }
1137                                 
1138                         sprintf(buf,"%s_value",v->name);
1139                         if ((value=CONF_get_string(req_conf,dn_sect,buf)) == NULL)
1140                                 {
1141                                 ERR_clear_error();
1142                                 value=NULL;
1143                                 }
1144
1145                         sprintf(buf,"%s_min",v->name);
1146                         min=(int)CONF_get_number(req_conf,dn_sect,buf);
1147
1148                         sprintf(buf,"%s_max",v->name);
1149                         max=(int)CONF_get_number(req_conf,dn_sect,buf);
1150
1151                         if (!add_DN_object(subj,v->value,def,value,nid,
1152                                 min,max))
1153                                 return 0;
1154                         }
1155                 if (X509_NAME_entry_count(subj) == 0)
1156                         {
1157                         BIO_printf(bio_err,"error, no objects specified in config file\n");
1158                         return 0;
1159                         }
1160
1161                 if (attribs)
1162                         {
1163                         if ((attr_sk != NULL) && (sk_CONF_VALUE_num(attr_sk) > 0))
1164                                 {
1165                                 BIO_printf(bio_err,"\nPlease enter the following 'extra' attributes\n");
1166                                 BIO_printf(bio_err,"to be sent with your certificate request\n");
1167                                 }
1168
1169                         i= -1;
1170 start2:                 for (;;)
1171                                 {
1172                                 i++;
1173                                 if ((attr_sk == NULL) ||
1174                                             (sk_CONF_VALUE_num(attr_sk) <= i))
1175                                         break;
1176
1177                                 v=sk_CONF_VALUE_value(attr_sk,i);
1178                                 type=v->name;
1179                                 if ((nid=OBJ_txt2nid(type)) == NID_undef)
1180                                         goto start2;
1181
1182                                 sprintf(buf,"%s_default",type);
1183                                 if ((def=CONF_get_string(req_conf,attr_sect,buf))
1184                                         == NULL)
1185                                         {
1186                                         ERR_clear_error();
1187                                         def="";
1188                                         }
1189                                 
1190                                 
1191                                 sprintf(buf,"%s_value",type);
1192                                 if ((value=CONF_get_string(req_conf,attr_sect,buf))
1193                                         == NULL)
1194                                         {
1195                                         ERR_clear_error();
1196                                         value=NULL;
1197                                         }
1198
1199                                 sprintf(buf,"%s_min",type);
1200                                 min=(int)CONF_get_number(req_conf,attr_sect,buf);
1201
1202                                 sprintf(buf,"%s_max",type);
1203                                 max=(int)CONF_get_number(req_conf,attr_sect,buf);
1204
1205                                 if (!add_attribute_object(req,
1206                                         v->value,def,value,nid,min,max))
1207                                         return 0;
1208                                 }
1209                         }
1210                 }
1211         else
1212                 {
1213                 BIO_printf(bio_err,"No template, please set one up.\n");
1214                 return 0;
1215                 }
1216
1217         return 1;
1218
1219         }
1220
1221 static int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *dn_sk,
1222                         STACK_OF(CONF_VALUE) *attr_sk, int attribs)
1223         {
1224         int i;
1225         char *p,*q;
1226         char *type;
1227         CONF_VALUE *v;
1228         X509_NAME *subj;
1229
1230         subj = X509_REQ_get_subject_name(req);
1231
1232         for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++)
1233                 {
1234                 v=sk_CONF_VALUE_value(dn_sk,i);
1235                 p=q=NULL;
1236                 type=v->name;
1237                 /* Skip past any leading X. X: X, etc to allow for
1238                  * multiple instances 
1239                  */
1240                 for(p = v->name; *p ; p++) 
1241 #ifndef CHARSET_EBCDIC
1242                         if ((*p == ':') || (*p == ',') || (*p == '.')) {
1243 #else
1244                         if ((*p == os_toascii[':']) || (*p == os_toascii[',']) || (*p == os_toascii['.'])) {
1245 #endif
1246                                 p++;
1247                                 if(*p) type = p;
1248                                 break;
1249                         }
1250                 if (!X509_NAME_add_entry_by_txt(subj,type, MBSTRING_ASC,
1251                                 (unsigned char *) v->value,-1,-1,0)) return 0;
1252
1253                 }
1254
1255                 if (!X509_NAME_entry_count(subj))
1256                         {
1257                         BIO_printf(bio_err,"error, no objects specified in config file\n");
1258                         return 0;
1259                         }
1260                 if (attribs)
1261                         {
1262                         for (i = 0; i < sk_CONF_VALUE_num(attr_sk); i++)
1263                                 {
1264                                 v=sk_CONF_VALUE_value(attr_sk,i);
1265                                 if(!X509_REQ_add1_attr_by_txt(req, v->name, MBSTRING_ASC,
1266                                         (unsigned char *)v->value, -1)) return 0;
1267                                 }
1268                         }
1269         return 1;
1270         }
1271
1272
1273 static int add_DN_object(X509_NAME *n, char *text, char *def, char *value,
1274              int nid, int min, int max)
1275         {
1276         int i,ret=0;
1277         MS_STATIC char buf[1024];
1278 start:
1279         BIO_printf(bio_err,"%s [%s]:",text,def);
1280         (void)BIO_flush(bio_err);
1281         if (value != NULL)
1282                 {
1283                 strcpy(buf,value);
1284                 strcat(buf,"\n");
1285                 BIO_printf(bio_err,"%s\n",value);
1286                 }
1287         else
1288                 {
1289                 buf[0]='\0';
1290                 fgets(buf,1024,stdin);
1291                 }
1292
1293         if (buf[0] == '\0') return(0);
1294         else if (buf[0] == '\n')
1295                 {
1296                 if ((def == NULL) || (def[0] == '\0'))
1297                         return(1);
1298                 strcpy(buf,def);
1299                 strcat(buf,"\n");
1300                 }
1301         else if ((buf[0] == '.') && (buf[1] == '\n')) return(1);
1302
1303         i=strlen(buf);
1304         if (buf[i-1] != '\n')
1305                 {
1306                 BIO_printf(bio_err,"weird input :-(\n");
1307                 return(0);
1308                 }
1309         buf[--i]='\0';
1310
1311 #ifdef CHARSET_EBCDIC
1312         ebcdic2ascii(buf, buf, i);
1313 #endif
1314         if(!req_check_len(i, min, max)) goto start;
1315         if (!X509_NAME_add_entry_by_NID(n,nid, MBSTRING_ASC,
1316                                 (unsigned char *) buf, -1,-1,0)) goto err;
1317         ret=1;
1318 err:
1319         return(ret);
1320         }
1321
1322 static int add_attribute_object(X509_REQ *req, char *text,
1323                                 char *def, char *value, int nid, int min,
1324                                 int max)
1325         {
1326         int i;
1327         static char buf[1024];
1328
1329 start:
1330         BIO_printf(bio_err,"%s [%s]:",text,def);
1331         (void)BIO_flush(bio_err);
1332         if (value != NULL)
1333                 {
1334                 strcpy(buf,value);
1335                 strcat(buf,"\n");
1336                 BIO_printf(bio_err,"%s\n",value);
1337                 }
1338         else
1339                 {
1340                 buf[0]='\0';
1341                 fgets(buf,1024,stdin);
1342                 }
1343
1344         if (buf[0] == '\0') return(0);
1345         else if (buf[0] == '\n')
1346                 {
1347                 if ((def == NULL) || (def[0] == '\0'))
1348                         return(1);
1349                 strcpy(buf,def);
1350                 strcat(buf,"\n");
1351                 }
1352         else if ((buf[0] == '.') && (buf[1] == '\n')) return(1);
1353
1354         i=strlen(buf);
1355         if (buf[i-1] != '\n')
1356                 {
1357                 BIO_printf(bio_err,"weird input :-(\n");
1358                 return(0);
1359                 }
1360         buf[--i]='\0';
1361 #ifdef CHARSET_EBCDIC
1362         ebcdic2ascii(buf, buf, i);
1363 #endif
1364         if(!req_check_len(i, min, max)) goto start;
1365
1366         if(!X509_REQ_add1_attr_by_NID(req, nid, MBSTRING_ASC,
1367                                         (unsigned char *)buf, -1)) {
1368                 BIO_printf(bio_err, "Error adding attribute\n");
1369                 ERR_print_errors(bio_err);
1370                 goto err;
1371         }
1372
1373         return(1);
1374 err:
1375         return(0);
1376         }
1377
1378 #ifndef NO_RSA
1379 static void MS_CALLBACK req_cb(int p, int n, void *arg)
1380         {
1381         char c='*';
1382
1383         if (p == 0) c='.';
1384         if (p == 1) c='+';
1385         if (p == 2) c='*';
1386         if (p == 3) c='\n';
1387         BIO_write((BIO *)arg,&c,1);
1388         (void)BIO_flush((BIO *)arg);
1389 #ifdef LINT
1390         p=n;
1391 #endif
1392         }
1393 #endif
1394
1395 static int req_check_len(int len, int min, int max)
1396         {
1397         if (len < min)
1398                 {
1399                 BIO_printf(bio_err,"string is too short, it needs to be at least %d bytes long\n",min);
1400                 return(0);
1401                 }
1402         if ((max != 0) && (len > max))
1403                 {
1404                 BIO_printf(bio_err,"string is too long, it needs to be less than  %d bytes long\n",max);
1405                 return(0);
1406                 }
1407         return(1);
1408         }
1409
1410 /* Check if the end of a string matches 'end' */
1411 static int check_end(char *str, char *end)
1412 {
1413         int elen, slen; 
1414         char *tmp;
1415         elen = strlen(end);
1416         slen = strlen(str);
1417         if(elen > slen) return 1;
1418         tmp = str + slen - elen;
1419         return strcmp(tmp, end);
1420 }