xref: /freebsd/crypto/openssl/apps/x509.c (revision d356ca0c3ffa363d5bfbc237b44f53b3f88fd415)
1 /* apps/x509.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 <assert.h>
60 #include <stdio.h>
61 #include <stdlib.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/asn1.h>
69 #include <openssl/err.h>
70 #include <openssl/bn.h>
71 #include <openssl/evp.h>
72 #include <openssl/x509.h>
73 #include <openssl/x509v3.h>
74 #include <openssl/objects.h>
75 #include <openssl/pem.h>
76 #ifndef OPENSSL_NO_RSA
77 # include <openssl/rsa.h>
78 #endif
79 #ifndef OPENSSL_NO_DSA
80 # include <openssl/dsa.h>
81 #endif
82 
83 #undef PROG
84 #define PROG x509_main
85 
86 #undef POSTFIX
87 #define POSTFIX ".srl"
88 #define DEF_DAYS        30
89 
90 static const char *x509_usage[] = {
91     "usage: x509 args\n",
92     " -inform arg     - input format - default PEM (one of DER, NET or PEM)\n",
93     " -outform arg    - output format - default PEM (one of DER, NET or PEM)\n",
94     " -keyform arg    - private key format - default PEM\n",
95     " -CAform arg     - CA format - default PEM\n",
96     " -CAkeyform arg  - CA key format - default PEM\n",
97     " -in arg         - input file - default stdin\n",
98     " -out arg        - output file - default stdout\n",
99     " -passin arg     - private key password source\n",
100     " -serial         - print serial number value\n",
101     " -subject_hash   - print subject hash value\n",
102 #ifndef OPENSSL_NO_MD5
103     " -subject_hash_old   - print old-style (MD5) subject hash value\n",
104 #endif
105     " -issuer_hash    - print issuer hash value\n",
106 #ifndef OPENSSL_NO_MD5
107     " -issuer_hash_old    - print old-style (MD5) issuer hash value\n",
108 #endif
109     " -hash           - synonym for -subject_hash\n",
110     " -subject        - print subject DN\n",
111     " -issuer         - print issuer DN\n",
112     " -email          - print email address(es)\n",
113     " -startdate      - notBefore field\n",
114     " -enddate        - notAfter field\n",
115     " -purpose        - print out certificate purposes\n",
116     " -dates          - both Before and After dates\n",
117     " -modulus        - print the RSA key modulus\n",
118     " -pubkey         - output the public key\n",
119     " -fingerprint    - print the certificate fingerprint\n",
120     " -alias          - output certificate alias\n",
121     " -noout          - no certificate output\n",
122     " -ocspid         - print OCSP hash values for the subject name and public key\n",
123     " -ocsp_uri       - print OCSP Responder URL(s)\n",
124     " -trustout       - output a \"trusted\" certificate\n",
125     " -clrtrust       - clear all trusted purposes\n",
126     " -clrreject      - clear all rejected purposes\n",
127     " -addtrust arg   - trust certificate for a given purpose\n",
128     " -addreject arg  - reject certificate for a given purpose\n",
129     " -setalias arg   - set certificate alias\n",
130     " -days arg       - How long till expiry of a signed certificate - def 30 days\n",
131     " -checkend arg   - check whether the cert expires in the next arg seconds\n",
132     "                   exit 1 if so, 0 if not\n",
133     " -signkey arg    - self sign cert with arg\n",
134     " -x509toreq      - output a certification request object\n",
135     " -req            - input is a certificate request, sign and output.\n",
136     " -CA arg         - set the CA certificate, must be PEM format.\n",
137     " -CAkey arg      - set the CA key, must be PEM format\n",
138     "                   missing, it is assumed to be in the CA file.\n",
139     " -CAcreateserial - create serial number file if it does not exist\n",
140     " -CAserial arg   - serial file\n",
141     " -set_serial     - serial number to use\n",
142     " -text           - print the certificate in text form\n",
143     " -C              - print out C code forms\n",
144     " -md2/-md5/-sha1/-mdc2 - digest to use\n",
145     " -extfile        - configuration file with X509V3 extensions to add\n",
146     " -extensions     - section from config file with X509V3 extensions to add\n",
147     " -clrext         - delete extensions before signing and input certificate\n",
148     " -nameopt arg    - various certificate name options\n",
149 #ifndef OPENSSL_NO_ENGINE
150     " -engine e       - use engine e, possibly a hardware device.\n",
151 #endif
152     " -certopt arg    - various certificate text options\n",
153     " -checkhost host - check certificate matches \"host\"\n",
154     " -checkemail email - check certificate matches \"email\"\n",
155     " -checkip ipaddr - check certificate matches \"ipaddr\"\n",
156     NULL
157 };
158 
159 static int MS_CALLBACK callb(int ok, X509_STORE_CTX *ctx);
160 static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext,
161                 const EVP_MD *digest, CONF *conf, char *section);
162 static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
163                         X509 *x, X509 *xca, EVP_PKEY *pkey,
164                         STACK_OF(OPENSSL_STRING) *sigopts, char *serial,
165                         int create, int days, int clrext, CONF *conf,
166                         char *section, ASN1_INTEGER *sno);
167 static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt);
168 static int reqfile = 0;
169 #ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
170 static int force_version = 2;
171 #endif
172 
173 int MAIN(int, char **);
174 
175 int MAIN(int argc, char **argv)
176 {
177     ENGINE *e = NULL;
178     int ret = 1;
179     X509_REQ *req = NULL;
180     X509 *x = NULL, *xca = NULL;
181     ASN1_OBJECT *objtmp;
182     STACK_OF(OPENSSL_STRING) *sigopts = NULL;
183     EVP_PKEY *Upkey = NULL, *CApkey = NULL, *fkey = NULL;
184     ASN1_INTEGER *sno = NULL;
185     int i, num, badops = 0, badsig = 0;
186     BIO *out = NULL;
187     BIO *STDout = NULL;
188     STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL;
189     int informat, outformat, keyformat, CAformat, CAkeyformat;
190     char *infile = NULL, *outfile = NULL, *keyfile = NULL, *CAfile = NULL;
191     char *CAkeyfile = NULL, *CAserial = NULL;
192     char *fkeyfile = NULL;
193     char *alias = NULL;
194     int text = 0, serial = 0, subject = 0, issuer = 0, startdate =
195         0, enddate = 0;
196     int next_serial = 0;
197     int subject_hash = 0, issuer_hash = 0, ocspid = 0;
198 #ifndef OPENSSL_NO_MD5
199     int subject_hash_old = 0, issuer_hash_old = 0;
200 #endif
201     int noout = 0, sign_flag = 0, CA_flag = 0, CA_createserial = 0, email = 0;
202     int ocsp_uri = 0;
203     int trustout = 0, clrtrust = 0, clrreject = 0, aliasout = 0, clrext = 0;
204     int C = 0;
205     int x509req = 0, days = DEF_DAYS, modulus = 0, pubkey = 0;
206     int pprint = 0;
207     const char **pp;
208     X509_STORE *ctx = NULL;
209     X509_REQ *rq = NULL;
210     int fingerprint = 0;
211     char buf[256];
212     const EVP_MD *md_alg, *digest = NULL;
213     CONF *extconf = NULL;
214     char *extsect = NULL, *extfile = NULL, *passin = NULL, *passargin = NULL;
215     int need_rand = 0;
216     int checkend = 0, checkoffset = 0;
217     unsigned long nmflag = 0, certflag = 0;
218     char *checkhost = NULL;
219     char *checkemail = NULL;
220     char *checkip = NULL;
221 #ifndef OPENSSL_NO_ENGINE
222     char *engine = NULL;
223 #endif
224 
225     reqfile = 0;
226 
227     apps_startup();
228 
229     if (bio_err == NULL)
230         bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
231 
232     if (!load_config(bio_err, NULL))
233         goto end;
234     STDout = BIO_new_fp(stdout, BIO_NOCLOSE);
235 #ifdef OPENSSL_SYS_VMS
236     {
237         BIO *tmpbio = BIO_new(BIO_f_linebuffer());
238         STDout = BIO_push(tmpbio, STDout);
239     }
240 #endif
241 
242     informat = FORMAT_PEM;
243     outformat = FORMAT_PEM;
244     keyformat = FORMAT_PEM;
245     CAformat = FORMAT_PEM;
246     CAkeyformat = FORMAT_PEM;
247 
248     ctx = X509_STORE_new();
249     if (ctx == NULL)
250         goto end;
251     X509_STORE_set_verify_cb(ctx, callb);
252 
253     argc--;
254     argv++;
255     num = 0;
256     while (argc >= 1) {
257         if (strcmp(*argv, "-inform") == 0) {
258             if (--argc < 1)
259                 goto bad;
260             informat = str2fmt(*(++argv));
261         } else if (strcmp(*argv, "-outform") == 0) {
262             if (--argc < 1)
263                 goto bad;
264             outformat = str2fmt(*(++argv));
265         } else if (strcmp(*argv, "-keyform") == 0) {
266             if (--argc < 1)
267                 goto bad;
268             keyformat = str2fmt(*(++argv));
269         } else if (strcmp(*argv, "-req") == 0) {
270             reqfile = 1;
271             need_rand = 1;
272         } else if (strcmp(*argv, "-CAform") == 0) {
273             if (--argc < 1)
274                 goto bad;
275             CAformat = str2fmt(*(++argv));
276         } else if (strcmp(*argv, "-CAkeyform") == 0) {
277             if (--argc < 1)
278                 goto bad;
279             CAkeyformat = str2fmt(*(++argv));
280         } else if (strcmp(*argv, "-sigopt") == 0) {
281             if (--argc < 1)
282                 goto bad;
283             if (!sigopts)
284                 sigopts = sk_OPENSSL_STRING_new_null();
285             if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, *(++argv)))
286                 goto bad;
287         }
288 #ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
289         else if (strcmp(*argv, "-force_version") == 0) {
290             if (--argc < 1)
291                 goto bad;
292             force_version = atoi(*(++argv)) - 1;
293         }
294 #endif
295         else if (strcmp(*argv, "-days") == 0) {
296             if (--argc < 1)
297                 goto bad;
298             days = atoi(*(++argv));
299             if (days == 0) {
300                 BIO_printf(bio_err, "bad number of days\n");
301                 goto bad;
302             }
303         } else if (strcmp(*argv, "-passin") == 0) {
304             if (--argc < 1)
305                 goto bad;
306             passargin = *(++argv);
307         } else if (strcmp(*argv, "-extfile") == 0) {
308             if (--argc < 1)
309                 goto bad;
310             extfile = *(++argv);
311         } else if (strcmp(*argv, "-extensions") == 0) {
312             if (--argc < 1)
313                 goto bad;
314             extsect = *(++argv);
315         } else if (strcmp(*argv, "-in") == 0) {
316             if (--argc < 1)
317                 goto bad;
318             infile = *(++argv);
319         } else if (strcmp(*argv, "-out") == 0) {
320             if (--argc < 1)
321                 goto bad;
322             outfile = *(++argv);
323         } else if (strcmp(*argv, "-signkey") == 0) {
324             if (--argc < 1)
325                 goto bad;
326             keyfile = *(++argv);
327             sign_flag = ++num;
328             need_rand = 1;
329         } else if (strcmp(*argv, "-CA") == 0) {
330             if (--argc < 1)
331                 goto bad;
332             CAfile = *(++argv);
333             CA_flag = ++num;
334             need_rand = 1;
335         } else if (strcmp(*argv, "-CAkey") == 0) {
336             if (--argc < 1)
337                 goto bad;
338             CAkeyfile = *(++argv);
339         } else if (strcmp(*argv, "-CAserial") == 0) {
340             if (--argc < 1)
341                 goto bad;
342             CAserial = *(++argv);
343         } else if (strcmp(*argv, "-set_serial") == 0) {
344             if (--argc < 1)
345                 goto bad;
346             if (!(sno = s2i_ASN1_INTEGER(NULL, *(++argv))))
347                 goto bad;
348         } else if (strcmp(*argv, "-force_pubkey") == 0) {
349             if (--argc < 1)
350                 goto bad;
351             fkeyfile = *(++argv);
352         } else if (strcmp(*argv, "-addtrust") == 0) {
353             if (--argc < 1)
354                 goto bad;
355             if (!(objtmp = OBJ_txt2obj(*(++argv), 0))) {
356                 BIO_printf(bio_err, "Invalid trust object value %s\n", *argv);
357                 goto bad;
358             }
359             if (!trust)
360                 trust = sk_ASN1_OBJECT_new_null();
361             sk_ASN1_OBJECT_push(trust, objtmp);
362             trustout = 1;
363         } else if (strcmp(*argv, "-addreject") == 0) {
364             if (--argc < 1)
365                 goto bad;
366             if (!(objtmp = OBJ_txt2obj(*(++argv), 0))) {
367                 BIO_printf(bio_err,
368                            "Invalid reject object value %s\n", *argv);
369                 goto bad;
370             }
371             if (!reject)
372                 reject = sk_ASN1_OBJECT_new_null();
373             sk_ASN1_OBJECT_push(reject, objtmp);
374             trustout = 1;
375         } else if (strcmp(*argv, "-setalias") == 0) {
376             if (--argc < 1)
377                 goto bad;
378             alias = *(++argv);
379             trustout = 1;
380         } else if (strcmp(*argv, "-certopt") == 0) {
381             if (--argc < 1)
382                 goto bad;
383             if (!set_cert_ex(&certflag, *(++argv)))
384                 goto bad;
385         } else if (strcmp(*argv, "-nameopt") == 0) {
386             if (--argc < 1)
387                 goto bad;
388             if (!set_name_ex(&nmflag, *(++argv)))
389                 goto bad;
390         }
391 #ifndef OPENSSL_NO_ENGINE
392         else if (strcmp(*argv, "-engine") == 0) {
393             if (--argc < 1)
394                 goto bad;
395             engine = *(++argv);
396         }
397 #endif
398         else if (strcmp(*argv, "-C") == 0)
399             C = ++num;
400         else if (strcmp(*argv, "-email") == 0)
401             email = ++num;
402         else if (strcmp(*argv, "-ocsp_uri") == 0)
403             ocsp_uri = ++num;
404         else if (strcmp(*argv, "-serial") == 0)
405             serial = ++num;
406         else if (strcmp(*argv, "-next_serial") == 0)
407             next_serial = ++num;
408         else if (strcmp(*argv, "-modulus") == 0)
409             modulus = ++num;
410         else if (strcmp(*argv, "-pubkey") == 0)
411             pubkey = ++num;
412         else if (strcmp(*argv, "-x509toreq") == 0)
413             x509req = ++num;
414         else if (strcmp(*argv, "-text") == 0)
415             text = ++num;
416         else if (strcmp(*argv, "-hash") == 0
417                  || strcmp(*argv, "-subject_hash") == 0)
418             subject_hash = ++num;
419 #ifndef OPENSSL_NO_MD5
420         else if (strcmp(*argv, "-subject_hash_old") == 0)
421             subject_hash_old = ++num;
422 #endif
423         else if (strcmp(*argv, "-issuer_hash") == 0)
424             issuer_hash = ++num;
425 #ifndef OPENSSL_NO_MD5
426         else if (strcmp(*argv, "-issuer_hash_old") == 0)
427             issuer_hash_old = ++num;
428 #endif
429         else if (strcmp(*argv, "-subject") == 0)
430             subject = ++num;
431         else if (strcmp(*argv, "-issuer") == 0)
432             issuer = ++num;
433         else if (strcmp(*argv, "-fingerprint") == 0)
434             fingerprint = ++num;
435         else if (strcmp(*argv, "-dates") == 0) {
436             startdate = ++num;
437             enddate = ++num;
438         } else if (strcmp(*argv, "-purpose") == 0)
439             pprint = ++num;
440         else if (strcmp(*argv, "-startdate") == 0)
441             startdate = ++num;
442         else if (strcmp(*argv, "-enddate") == 0)
443             enddate = ++num;
444         else if (strcmp(*argv, "-checkend") == 0) {
445             if (--argc < 1)
446                 goto bad;
447             checkoffset = atoi(*(++argv));
448             checkend = 1;
449         } else if (strcmp(*argv, "-checkhost") == 0) {
450             if (--argc < 1)
451                 goto bad;
452             checkhost = *(++argv);
453         } else if (strcmp(*argv, "-checkemail") == 0) {
454             if (--argc < 1)
455                 goto bad;
456             checkemail = *(++argv);
457         } else if (strcmp(*argv, "-checkip") == 0) {
458             if (--argc < 1)
459                 goto bad;
460             checkip = *(++argv);
461         } else if (strcmp(*argv, "-noout") == 0)
462             noout = ++num;
463         else if (strcmp(*argv, "-trustout") == 0)
464             trustout = 1;
465         else if (strcmp(*argv, "-clrtrust") == 0)
466             clrtrust = ++num;
467         else if (strcmp(*argv, "-clrreject") == 0)
468             clrreject = ++num;
469         else if (strcmp(*argv, "-alias") == 0)
470             aliasout = ++num;
471         else if (strcmp(*argv, "-CAcreateserial") == 0)
472             CA_createserial = ++num;
473         else if (strcmp(*argv, "-clrext") == 0)
474             clrext = 1;
475 #if 1                           /* stay backwards-compatible with 0.9.5; this
476                                  * should go away soon */
477         else if (strcmp(*argv, "-crlext") == 0) {
478             BIO_printf(bio_err, "use -clrext instead of -crlext\n");
479             clrext = 1;
480         }
481 #endif
482         else if (strcmp(*argv, "-ocspid") == 0)
483             ocspid = ++num;
484         else if (strcmp(*argv, "-badsig") == 0)
485             badsig = 1;
486         else if ((md_alg = EVP_get_digestbyname(*argv + 1))) {
487             /* ok */
488             digest = md_alg;
489         } else {
490             BIO_printf(bio_err, "unknown option %s\n", *argv);
491             badops = 1;
492             break;
493         }
494         argc--;
495         argv++;
496     }
497 
498     if (badops) {
499  bad:
500         for (pp = x509_usage; (*pp != NULL); pp++)
501             BIO_printf(bio_err, "%s", *pp);
502         goto end;
503     }
504 #ifndef OPENSSL_NO_ENGINE
505     e = setup_engine(bio_err, engine, 0);
506 #endif
507 
508     if (need_rand)
509         app_RAND_load_file(NULL, bio_err, 0);
510 
511     ERR_load_crypto_strings();
512 
513     if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) {
514         BIO_printf(bio_err, "Error getting password\n");
515         goto end;
516     }
517 
518     if (!X509_STORE_set_default_paths(ctx)) {
519         ERR_print_errors(bio_err);
520         goto end;
521     }
522 
523     if (fkeyfile) {
524         fkey = load_pubkey(bio_err, fkeyfile, keyformat, 0,
525                            NULL, e, "Forced key");
526         if (fkey == NULL)
527             goto end;
528     }
529 
530     if ((CAkeyfile == NULL) && (CA_flag) && (CAformat == FORMAT_PEM)) {
531         CAkeyfile = CAfile;
532     } else if ((CA_flag) && (CAkeyfile == NULL)) {
533         BIO_printf(bio_err,
534                    "need to specify a CAkey if using the CA command\n");
535         goto end;
536     }
537 
538     if (extfile) {
539         long errorline = -1;
540         X509V3_CTX ctx2;
541         extconf = NCONF_new(NULL);
542         if (!NCONF_load(extconf, extfile, &errorline)) {
543             if (errorline <= 0)
544                 BIO_printf(bio_err,
545                            "error loading the config file '%s'\n", extfile);
546             else
547                 BIO_printf(bio_err,
548                            "error on line %ld of config file '%s'\n",
549                            errorline, extfile);
550             goto end;
551         }
552         if (!extsect) {
553             extsect = NCONF_get_string(extconf, "default", "extensions");
554             if (!extsect) {
555                 ERR_clear_error();
556                 extsect = "default";
557             }
558         }
559         X509V3_set_ctx_test(&ctx2);
560         X509V3_set_nconf(&ctx2, extconf);
561         if (!X509V3_EXT_add_nconf(extconf, &ctx2, extsect, NULL)) {
562             BIO_printf(bio_err,
563                        "Error Loading extension section %s\n", extsect);
564             ERR_print_errors(bio_err);
565             goto end;
566         }
567     }
568 
569     if (reqfile) {
570         EVP_PKEY *pkey;
571         BIO *in;
572 
573         if (!sign_flag && !CA_flag) {
574             BIO_printf(bio_err, "We need a private key to sign with\n");
575             goto end;
576         }
577         in = BIO_new(BIO_s_file());
578         if (in == NULL) {
579             ERR_print_errors(bio_err);
580             goto end;
581         }
582 
583         if (infile == NULL)
584             BIO_set_fp(in, stdin, BIO_NOCLOSE | BIO_FP_TEXT);
585         else {
586             if (BIO_read_filename(in, infile) <= 0) {
587                 perror(infile);
588                 BIO_free(in);
589                 goto end;
590             }
591         }
592         req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL);
593         BIO_free(in);
594 
595         if (req == NULL) {
596             ERR_print_errors(bio_err);
597             goto end;
598         }
599 
600         if ((req->req_info == NULL) ||
601             (req->req_info->pubkey == NULL) ||
602             (req->req_info->pubkey->public_key == NULL) ||
603             (req->req_info->pubkey->public_key->data == NULL)) {
604             BIO_printf(bio_err,
605                        "The certificate request appears to corrupted\n");
606             BIO_printf(bio_err, "It does not contain a public key\n");
607             goto end;
608         }
609         if ((pkey = X509_REQ_get_pubkey(req)) == NULL) {
610             BIO_printf(bio_err, "error unpacking public key\n");
611             goto end;
612         }
613         i = X509_REQ_verify(req, pkey);
614         EVP_PKEY_free(pkey);
615         if (i < 0) {
616             BIO_printf(bio_err, "Signature verification error\n");
617             ERR_print_errors(bio_err);
618             goto end;
619         }
620         if (i == 0) {
621             BIO_printf(bio_err,
622                        "Signature did not match the certificate request\n");
623             goto end;
624         } else
625             BIO_printf(bio_err, "Signature ok\n");
626 
627         print_name(bio_err, "subject=", X509_REQ_get_subject_name(req),
628                    nmflag);
629 
630         if ((x = X509_new()) == NULL)
631             goto end;
632 
633         if (sno == NULL) {
634             sno = ASN1_INTEGER_new();
635             if (!sno || !rand_serial(NULL, sno))
636                 goto end;
637             if (!X509_set_serialNumber(x, sno))
638                 goto end;
639             ASN1_INTEGER_free(sno);
640             sno = NULL;
641         } else if (!X509_set_serialNumber(x, sno))
642             goto end;
643 
644         if (!X509_set_issuer_name(x, req->req_info->subject))
645             goto end;
646         if (!X509_set_subject_name(x, req->req_info->subject))
647             goto end;
648 
649         X509_gmtime_adj(X509_get_notBefore(x), 0);
650         X509_time_adj_ex(X509_get_notAfter(x), days, 0, NULL);
651         if (fkey)
652             X509_set_pubkey(x, fkey);
653         else {
654             pkey = X509_REQ_get_pubkey(req);
655             X509_set_pubkey(x, pkey);
656             EVP_PKEY_free(pkey);
657         }
658     } else
659         x = load_cert(bio_err, infile, informat, NULL, e, "Certificate");
660 
661     if (x == NULL)
662         goto end;
663     if (CA_flag) {
664         xca = load_cert(bio_err, CAfile, CAformat, NULL, e, "CA Certificate");
665         if (xca == NULL)
666             goto end;
667     }
668 
669     if (!noout || text || next_serial) {
670         OBJ_create("2.99999.3", "SET.ex3", "SET x509v3 extension 3");
671 
672         out = BIO_new(BIO_s_file());
673         if (out == NULL) {
674             ERR_print_errors(bio_err);
675             goto end;
676         }
677         if (outfile == NULL) {
678             BIO_set_fp(out, stdout, BIO_NOCLOSE);
679 #ifdef OPENSSL_SYS_VMS
680             {
681                 BIO *tmpbio = BIO_new(BIO_f_linebuffer());
682                 out = BIO_push(tmpbio, out);
683             }
684 #endif
685         } else {
686             if (BIO_write_filename(out, outfile) <= 0) {
687                 perror(outfile);
688                 goto end;
689             }
690         }
691     }
692 
693     if (alias)
694         X509_alias_set1(x, (unsigned char *)alias, -1);
695 
696     if (clrtrust)
697         X509_trust_clear(x);
698     if (clrreject)
699         X509_reject_clear(x);
700 
701     if (trust) {
702         for (i = 0; i < sk_ASN1_OBJECT_num(trust); i++) {
703             objtmp = sk_ASN1_OBJECT_value(trust, i);
704             X509_add1_trust_object(x, objtmp);
705         }
706     }
707 
708     if (reject) {
709         for (i = 0; i < sk_ASN1_OBJECT_num(reject); i++) {
710             objtmp = sk_ASN1_OBJECT_value(reject, i);
711             X509_add1_reject_object(x, objtmp);
712         }
713     }
714 
715     if (num) {
716         for (i = 1; i <= num; i++) {
717             if (issuer == i) {
718                 print_name(STDout, "issuer= ",
719                            X509_get_issuer_name(x), nmflag);
720             } else if (subject == i) {
721                 print_name(STDout, "subject= ",
722                            X509_get_subject_name(x), nmflag);
723             } else if (serial == i) {
724                 BIO_printf(STDout, "serial=");
725                 i2a_ASN1_INTEGER(STDout, X509_get_serialNumber(x));
726                 BIO_printf(STDout, "\n");
727             } else if (next_serial == i) {
728                 BIGNUM *bnser;
729                 ASN1_INTEGER *ser;
730                 ser = X509_get_serialNumber(x);
731                 bnser = ASN1_INTEGER_to_BN(ser, NULL);
732                 if (!bnser)
733                     goto end;
734                 if (!BN_add_word(bnser, 1))
735                     goto end;
736                 ser = BN_to_ASN1_INTEGER(bnser, NULL);
737                 if (!ser)
738                     goto end;
739                 BN_free(bnser);
740                 i2a_ASN1_INTEGER(out, ser);
741                 ASN1_INTEGER_free(ser);
742                 BIO_puts(out, "\n");
743             } else if ((email == i) || (ocsp_uri == i)) {
744                 int j;
745                 STACK_OF(OPENSSL_STRING) *emlst;
746                 if (email == i)
747                     emlst = X509_get1_email(x);
748                 else
749                     emlst = X509_get1_ocsp(x);
750                 for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++)
751                     BIO_printf(STDout, "%s\n",
752                                sk_OPENSSL_STRING_value(emlst, j));
753                 X509_email_free(emlst);
754             } else if (aliasout == i) {
755                 unsigned char *alstr;
756                 alstr = X509_alias_get0(x, NULL);
757                 if (alstr)
758                     BIO_printf(STDout, "%s\n", alstr);
759                 else
760                     BIO_puts(STDout, "<No Alias>\n");
761             } else if (subject_hash == i) {
762                 BIO_printf(STDout, "%08lx\n", X509_subject_name_hash(x));
763             }
764 #ifndef OPENSSL_NO_MD5
765             else if (subject_hash_old == i) {
766                 BIO_printf(STDout, "%08lx\n", X509_subject_name_hash_old(x));
767             }
768 #endif
769             else if (issuer_hash == i) {
770                 BIO_printf(STDout, "%08lx\n", X509_issuer_name_hash(x));
771             }
772 #ifndef OPENSSL_NO_MD5
773             else if (issuer_hash_old == i) {
774                 BIO_printf(STDout, "%08lx\n", X509_issuer_name_hash_old(x));
775             }
776 #endif
777             else if (pprint == i) {
778                 X509_PURPOSE *ptmp;
779                 int j;
780                 BIO_printf(STDout, "Certificate purposes:\n");
781                 for (j = 0; j < X509_PURPOSE_get_count(); j++) {
782                     ptmp = X509_PURPOSE_get0(j);
783                     purpose_print(STDout, x, ptmp);
784                 }
785             } else if (modulus == i) {
786                 EVP_PKEY *pkey;
787 
788                 pkey = X509_get_pubkey(x);
789                 if (pkey == NULL) {
790                     BIO_printf(bio_err, "Modulus=unavailable\n");
791                     ERR_print_errors(bio_err);
792                     goto end;
793                 }
794                 BIO_printf(STDout, "Modulus=");
795 #ifndef OPENSSL_NO_RSA
796                 if (pkey->type == EVP_PKEY_RSA)
797                     BN_print(STDout, pkey->pkey.rsa->n);
798                 else
799 #endif
800 #ifndef OPENSSL_NO_DSA
801                 if (pkey->type == EVP_PKEY_DSA)
802                     BN_print(STDout, pkey->pkey.dsa->pub_key);
803                 else
804 #endif
805                     BIO_printf(STDout, "Wrong Algorithm type");
806                 BIO_printf(STDout, "\n");
807                 EVP_PKEY_free(pkey);
808             } else if (pubkey == i) {
809                 EVP_PKEY *pkey;
810 
811                 pkey = X509_get_pubkey(x);
812                 if (pkey == NULL) {
813                     BIO_printf(bio_err, "Error getting public key\n");
814                     ERR_print_errors(bio_err);
815                     goto end;
816                 }
817                 PEM_write_bio_PUBKEY(STDout, pkey);
818                 EVP_PKEY_free(pkey);
819             } else if (C == i) {
820                 unsigned char *d;
821                 char *m;
822                 int y, z;
823 
824                 X509_NAME_oneline(X509_get_subject_name(x), buf, sizeof buf);
825                 BIO_printf(STDout, "/* subject:%s */\n", buf);
826                 m = X509_NAME_oneline(X509_get_issuer_name(x), buf,
827                                       sizeof buf);
828                 BIO_printf(STDout, "/* issuer :%s */\n", buf);
829 
830                 z = i2d_X509(x, NULL);
831                 m = OPENSSL_malloc(z);
832                 if (!m) {
833                     BIO_printf(bio_err, "Out of memory\n");
834                     ERR_print_errors(bio_err);
835                     goto end;
836                 }
837 
838                 d = (unsigned char *)m;
839                 z = i2d_X509_NAME(X509_get_subject_name(x), &d);
840                 BIO_printf(STDout, "unsigned char XXX_subject_name[%d]={\n",
841                            z);
842                 d = (unsigned char *)m;
843                 for (y = 0; y < z; y++) {
844                     BIO_printf(STDout, "0x%02X,", d[y]);
845                     if ((y & 0x0f) == 0x0f)
846                         BIO_printf(STDout, "\n");
847                 }
848                 if (y % 16 != 0)
849                     BIO_printf(STDout, "\n");
850                 BIO_printf(STDout, "};\n");
851 
852                 z = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &d);
853                 BIO_printf(STDout, "unsigned char XXX_public_key[%d]={\n", z);
854                 d = (unsigned char *)m;
855                 for (y = 0; y < z; y++) {
856                     BIO_printf(STDout, "0x%02X,", d[y]);
857                     if ((y & 0x0f) == 0x0f)
858                         BIO_printf(STDout, "\n");
859                 }
860                 if (y % 16 != 0)
861                     BIO_printf(STDout, "\n");
862                 BIO_printf(STDout, "};\n");
863 
864                 z = i2d_X509(x, &d);
865                 BIO_printf(STDout, "unsigned char XXX_certificate[%d]={\n",
866                            z);
867                 d = (unsigned char *)m;
868                 for (y = 0; y < z; y++) {
869                     BIO_printf(STDout, "0x%02X,", d[y]);
870                     if ((y & 0x0f) == 0x0f)
871                         BIO_printf(STDout, "\n");
872                 }
873                 if (y % 16 != 0)
874                     BIO_printf(STDout, "\n");
875                 BIO_printf(STDout, "};\n");
876 
877                 OPENSSL_free(m);
878             } else if (text == i) {
879                 X509_print_ex(STDout, x, nmflag, certflag);
880             } else if (startdate == i) {
881                 BIO_puts(STDout, "notBefore=");
882                 ASN1_TIME_print(STDout, X509_get_notBefore(x));
883                 BIO_puts(STDout, "\n");
884             } else if (enddate == i) {
885                 BIO_puts(STDout, "notAfter=");
886                 ASN1_TIME_print(STDout, X509_get_notAfter(x));
887                 BIO_puts(STDout, "\n");
888             } else if (fingerprint == i) {
889                 int j;
890                 unsigned int n;
891                 unsigned char md[EVP_MAX_MD_SIZE];
892                 const EVP_MD *fdig = digest;
893 
894                 if (!fdig)
895                     fdig = EVP_sha1();
896 
897                 if (!X509_digest(x, fdig, md, &n)) {
898                     BIO_printf(bio_err, "out of memory\n");
899                     goto end;
900                 }
901                 BIO_printf(STDout, "%s Fingerprint=",
902                            OBJ_nid2sn(EVP_MD_type(fdig)));
903                 for (j = 0; j < (int)n; j++) {
904                     BIO_printf(STDout, "%02X%c", md[j], (j + 1 == (int)n)
905                                ? '\n' : ':');
906                 }
907             }
908 
909             /* should be in the library */
910             else if ((sign_flag == i) && (x509req == 0)) {
911                 BIO_printf(bio_err, "Getting Private key\n");
912                 if (Upkey == NULL) {
913                     Upkey = load_key(bio_err,
914                                      keyfile, keyformat, 0,
915                                      passin, e, "Private key");
916                     if (Upkey == NULL)
917                         goto end;
918                 }
919 
920                 assert(need_rand);
921                 if (!sign(x, Upkey, days, clrext, digest, extconf, extsect))
922                     goto end;
923             } else if (CA_flag == i) {
924                 BIO_printf(bio_err, "Getting CA Private Key\n");
925                 if (CAkeyfile != NULL) {
926                     CApkey = load_key(bio_err,
927                                       CAkeyfile, CAkeyformat,
928                                       0, passin, e, "CA Private Key");
929                     if (CApkey == NULL)
930                         goto end;
931                 }
932 
933                 assert(need_rand);
934                 if (!x509_certify(ctx, CAfile, digest, x, xca,
935                                   CApkey, sigopts,
936                                   CAserial, CA_createserial, days, clrext,
937                                   extconf, extsect, sno))
938                     goto end;
939             } else if (x509req == i) {
940                 EVP_PKEY *pk;
941 
942                 BIO_printf(bio_err, "Getting request Private Key\n");
943                 if (keyfile == NULL) {
944                     BIO_printf(bio_err, "no request key file specified\n");
945                     goto end;
946                 } else {
947                     pk = load_key(bio_err,
948                                   keyfile, keyformat, 0,
949                                   passin, e, "request key");
950                     if (pk == NULL)
951                         goto end;
952                 }
953 
954                 BIO_printf(bio_err, "Generating certificate request\n");
955 
956                 rq = X509_to_X509_REQ(x, pk, digest);
957                 EVP_PKEY_free(pk);
958                 if (rq == NULL) {
959                     ERR_print_errors(bio_err);
960                     goto end;
961                 }
962                 if (!noout) {
963                     X509_REQ_print(out, rq);
964                     PEM_write_bio_X509_REQ(out, rq);
965                 }
966                 noout = 1;
967             } else if (ocspid == i) {
968                 X509_ocspid_print(out, x);
969             }
970         }
971     }
972 
973     if (checkend) {
974         time_t tcheck = time(NULL) + checkoffset;
975 
976         if (X509_cmp_time(X509_get_notAfter(x), &tcheck) < 0) {
977             BIO_printf(out, "Certificate will expire\n");
978             ret = 1;
979         } else {
980             BIO_printf(out, "Certificate will not expire\n");
981             ret = 0;
982         }
983         goto end;
984     }
985 
986     print_cert_checks(STDout, x, checkhost, checkemail, checkip);
987 
988     if (noout) {
989         ret = 0;
990         goto end;
991     }
992 
993     if (badsig)
994         x->signature->data[x->signature->length - 1] ^= 0x1;
995 
996     if (outformat == FORMAT_ASN1)
997         i = i2d_X509_bio(out, x);
998     else if (outformat == FORMAT_PEM) {
999         if (trustout)
1000             i = PEM_write_bio_X509_AUX(out, x);
1001         else
1002             i = PEM_write_bio_X509(out, x);
1003     } else if (outformat == FORMAT_NETSCAPE) {
1004         NETSCAPE_X509 nx;
1005         ASN1_OCTET_STRING hdr;
1006 
1007         hdr.data = (unsigned char *)NETSCAPE_CERT_HDR;
1008         hdr.length = strlen(NETSCAPE_CERT_HDR);
1009         nx.header = &hdr;
1010         nx.cert = x;
1011 
1012         i = ASN1_item_i2d_bio(ASN1_ITEM_rptr(NETSCAPE_X509), out, &nx);
1013     } else {
1014         BIO_printf(bio_err, "bad output format specified for outfile\n");
1015         goto end;
1016     }
1017     if (!i) {
1018         BIO_printf(bio_err, "unable to write certificate\n");
1019         ERR_print_errors(bio_err);
1020         goto end;
1021     }
1022     ret = 0;
1023  end:
1024     if (need_rand)
1025         app_RAND_write_file(NULL, bio_err);
1026     OBJ_cleanup();
1027     NCONF_free(extconf);
1028     BIO_free_all(out);
1029     BIO_free_all(STDout);
1030     X509_STORE_free(ctx);
1031     X509_REQ_free(req);
1032     X509_free(x);
1033     X509_free(xca);
1034     EVP_PKEY_free(Upkey);
1035     EVP_PKEY_free(CApkey);
1036     EVP_PKEY_free(fkey);
1037     if (sigopts)
1038         sk_OPENSSL_STRING_free(sigopts);
1039     X509_REQ_free(rq);
1040     ASN1_INTEGER_free(sno);
1041     sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free);
1042     sk_ASN1_OBJECT_pop_free(reject, ASN1_OBJECT_free);
1043     if (passin)
1044         OPENSSL_free(passin);
1045     apps_shutdown();
1046     OPENSSL_EXIT(ret);
1047 }
1048 
1049 static ASN1_INTEGER *x509_load_serial(char *CAfile, char *serialfile,
1050                                       int create)
1051 {
1052     char *buf = NULL, *p;
1053     ASN1_INTEGER *bs = NULL;
1054     BIGNUM *serial = NULL;
1055     size_t len;
1056 
1057     len = ((serialfile == NULL)
1058            ? (strlen(CAfile) + strlen(POSTFIX) + 1)
1059            : (strlen(serialfile))) + 1;
1060     buf = OPENSSL_malloc(len);
1061     if (buf == NULL) {
1062         BIO_printf(bio_err, "out of mem\n");
1063         goto end;
1064     }
1065     if (serialfile == NULL) {
1066         BUF_strlcpy(buf, CAfile, len);
1067         for (p = buf; *p; p++)
1068             if (*p == '.') {
1069                 *p = '\0';
1070                 break;
1071             }
1072         BUF_strlcat(buf, POSTFIX, len);
1073     } else
1074         BUF_strlcpy(buf, serialfile, len);
1075 
1076     serial = load_serial(buf, create, NULL);
1077     if (serial == NULL)
1078         goto end;
1079 
1080     if (!BN_add_word(serial, 1)) {
1081         BIO_printf(bio_err, "add_word failure\n");
1082         goto end;
1083     }
1084 
1085     if (!save_serial(buf, NULL, serial, &bs))
1086         goto end;
1087 
1088  end:
1089     if (buf)
1090         OPENSSL_free(buf);
1091     BN_free(serial);
1092     return bs;
1093 }
1094 
1095 static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
1096                         X509 *x, X509 *xca, EVP_PKEY *pkey,
1097                         STACK_OF(OPENSSL_STRING) *sigopts,
1098                         char *serialfile, int create,
1099                         int days, int clrext, CONF *conf, char *section,
1100                         ASN1_INTEGER *sno)
1101 {
1102     int ret = 0;
1103     ASN1_INTEGER *bs = NULL;
1104     X509_STORE_CTX xsc;
1105     EVP_PKEY *upkey;
1106 
1107     upkey = X509_get_pubkey(xca);
1108     EVP_PKEY_copy_parameters(upkey, pkey);
1109     EVP_PKEY_free(upkey);
1110 
1111     if (!X509_STORE_CTX_init(&xsc, ctx, x, NULL)) {
1112         BIO_printf(bio_err, "Error initialising X509 store\n");
1113         goto end;
1114     }
1115     if (sno)
1116         bs = sno;
1117     else if (!(bs = x509_load_serial(CAfile, serialfile, create)))
1118         goto end;
1119 
1120 /*      if (!X509_STORE_add_cert(ctx,x)) goto end;*/
1121 
1122     /*
1123      * NOTE: this certificate can/should be self signed, unless it was a
1124      * certificate request in which case it is not.
1125      */
1126     X509_STORE_CTX_set_cert(&xsc, x);
1127     X509_STORE_CTX_set_flags(&xsc, X509_V_FLAG_CHECK_SS_SIGNATURE);
1128     if (!reqfile && X509_verify_cert(&xsc) <= 0)
1129         goto end;
1130 
1131     if (!X509_check_private_key(xca, pkey)) {
1132         BIO_printf(bio_err,
1133                    "CA certificate and CA private key do not match\n");
1134         goto end;
1135     }
1136 
1137     if (!X509_set_issuer_name(x, X509_get_subject_name(xca)))
1138         goto end;
1139     if (!X509_set_serialNumber(x, bs))
1140         goto end;
1141 
1142     if (X509_gmtime_adj(X509_get_notBefore(x), 0L) == NULL)
1143         goto end;
1144 
1145     /* hardwired expired */
1146     if (X509_time_adj_ex(X509_get_notAfter(x), days, 0, NULL) == NULL)
1147         goto end;
1148 
1149     if (clrext) {
1150         while (X509_get_ext_count(x) > 0)
1151             X509_delete_ext(x, 0);
1152     }
1153 
1154     if (conf) {
1155         X509V3_CTX ctx2;
1156 #ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
1157         X509_set_version(x, force_version);
1158 #else
1159         X509_set_version(x, 2); /* version 3 certificate */
1160 #endif
1161         X509V3_set_ctx(&ctx2, xca, x, NULL, NULL, 0);
1162         X509V3_set_nconf(&ctx2, conf);
1163         if (!X509V3_EXT_add_nconf(conf, &ctx2, section, x))
1164             goto end;
1165     }
1166 
1167     if (!do_X509_sign(bio_err, x, pkey, digest, sigopts))
1168         goto end;
1169     ret = 1;
1170  end:
1171     X509_STORE_CTX_cleanup(&xsc);
1172     if (!ret)
1173         ERR_print_errors(bio_err);
1174     if (!sno)
1175         ASN1_INTEGER_free(bs);
1176     return ret;
1177 }
1178 
1179 static int MS_CALLBACK callb(int ok, X509_STORE_CTX *ctx)
1180 {
1181     int err;
1182     X509 *err_cert;
1183 
1184     /*
1185      * it is ok to use a self signed certificate This case will catch both
1186      * the initial ok == 0 and the final ok == 1 calls to this function
1187      */
1188     err = X509_STORE_CTX_get_error(ctx);
1189     if (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT)
1190         return 1;
1191 
1192     /*
1193      * BAD we should have gotten an error.  Normally if everything worked
1194      * X509_STORE_CTX_get_error(ctx) will still be set to
1195      * DEPTH_ZERO_SELF_....
1196      */
1197     if (ok) {
1198         BIO_printf(bio_err,
1199                    "error with certificate to be certified - should be self signed\n");
1200         return 0;
1201     } else {
1202         err_cert = X509_STORE_CTX_get_current_cert(ctx);
1203         print_name(bio_err, NULL, X509_get_subject_name(err_cert), 0);
1204         BIO_printf(bio_err,
1205                    "error with certificate - error %d at depth %d\n%s\n", err,
1206                    X509_STORE_CTX_get_error_depth(ctx),
1207                    X509_verify_cert_error_string(err));
1208         return 1;
1209     }
1210 }
1211 
1212 /* self sign */
1213 static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext,
1214                 const EVP_MD *digest, CONF *conf, char *section)
1215 {
1216 
1217     EVP_PKEY *pktmp;
1218 
1219     pktmp = X509_get_pubkey(x);
1220     EVP_PKEY_copy_parameters(pktmp, pkey);
1221     EVP_PKEY_save_parameters(pktmp, 1);
1222     EVP_PKEY_free(pktmp);
1223 
1224     if (!X509_set_issuer_name(x, X509_get_subject_name(x)))
1225         goto err;
1226     if (X509_gmtime_adj(X509_get_notBefore(x), 0) == NULL)
1227         goto err;
1228 
1229     if (X509_time_adj_ex(X509_get_notAfter(x), days, 0, NULL) == NULL)
1230         goto err;
1231 
1232     if (!X509_set_pubkey(x, pkey))
1233         goto err;
1234     if (clrext) {
1235         while (X509_get_ext_count(x) > 0)
1236             X509_delete_ext(x, 0);
1237     }
1238     if (conf) {
1239         X509V3_CTX ctx;
1240 #ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
1241         X509_set_version(x, force_version);
1242 #else
1243         X509_set_version(x, 2); /* version 3 certificate */
1244 #endif
1245         X509V3_set_ctx(&ctx, x, x, NULL, NULL, 0);
1246         X509V3_set_nconf(&ctx, conf);
1247         if (!X509V3_EXT_add_nconf(conf, &ctx, section, x))
1248             goto err;
1249     }
1250     if (!X509_sign(x, pkey, digest))
1251         goto err;
1252     return 1;
1253  err:
1254     ERR_print_errors(bio_err);
1255     return 0;
1256 }
1257 
1258 static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt)
1259 {
1260     int id, i, idret;
1261     char *pname;
1262     id = X509_PURPOSE_get_id(pt);
1263     pname = X509_PURPOSE_get0_name(pt);
1264     for (i = 0; i < 2; i++) {
1265         idret = X509_check_purpose(cert, id, i);
1266         BIO_printf(bio, "%s%s : ", pname, i ? " CA" : "");
1267         if (idret == 1)
1268             BIO_printf(bio, "Yes\n");
1269         else if (idret == 0)
1270             BIO_printf(bio, "No\n");
1271         else
1272             BIO_printf(bio, "Yes (WARNING code=%d)\n", idret);
1273     }
1274     return 1;
1275 }
1276