apps/x509.c: Add -copy_extensions option, used when transforming x509 <-> req
[openssl.git] / apps / x509.c
1 /*
2  * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include "apps.h"
14 #include "progs.h"
15 #include <openssl/bio.h>
16 #include <openssl/asn1.h>
17 #include <openssl/err.h>
18 #include <openssl/bn.h>
19 #include <openssl/evp.h>
20 #include <openssl/x509.h>
21 #include <openssl/x509v3.h>
22 #include <openssl/objects.h>
23 #include <openssl/pem.h>
24 #include <openssl/rsa.h>
25 #ifndef OPENSSL_NO_DSA
26 # include <openssl/dsa.h>
27 #endif
28
29 #undef POSTFIX
30 #define POSTFIX ".srl"
31 #define DEFAULT_DAYS    30 /* default cert validity period in days */
32 #define UNSET_DAYS      -2 /* -1 is used for testing expiration checks */
33 #define EXT_COPY_UNSET     -1
34
35 static int callb(int ok, X509_STORE_CTX *ctx);
36 static int sign(X509 *x, EVP_PKEY *pkey, X509 *issuer,
37                 STACK_OF(OPENSSL_STRING) *sigopts,
38                 int days, int clrext,
39                 const EVP_MD *digest, CONF *conf, const char *section,
40                 int preserve_dates);
41 static int x509_certify(X509_STORE *ctx, const char *CAfile,
42                         const EVP_MD *digest,
43                         X509 *x, X509 *xca, EVP_PKEY *pkey,
44                         STACK_OF(OPENSSL_STRING) *sigopts,
45                         const char *serialfile, int create,
46                         int days, int clrext, CONF *conf, const char *section,
47                         ASN1_INTEGER *sno, int preserve_dates);
48 static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt);
49 static int print_x509v3_exts(BIO *bio, X509 *x, const char *ext_names);
50
51 typedef enum OPTION_choice {
52     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
53     OPT_INFORM, OPT_OUTFORM, OPT_KEYFORM, OPT_REQ, OPT_CAFORM,
54     OPT_CAKEYFORM, OPT_VFYOPT, OPT_SIGOPT, OPT_DAYS, OPT_PASSIN, OPT_EXTFILE,
55     OPT_EXTENSIONS, OPT_IN, OPT_OUT, OPT_SIGNKEY, OPT_CA, OPT_CAKEY,
56     OPT_CASERIAL, OPT_SET_SERIAL, OPT_NEW, OPT_FORCE_PUBKEY, OPT_SUBJ,
57     OPT_ADDTRUST, OPT_ADDREJECT, OPT_SETALIAS, OPT_CERTOPT, OPT_NAMEOPT,
58     OPT_EMAIL, OPT_OCSP_URI, OPT_SERIAL, OPT_NEXT_SERIAL,
59     OPT_MODULUS, OPT_PUBKEY, OPT_X509TOREQ, OPT_TEXT, OPT_HASH,
60     OPT_ISSUER_HASH, OPT_SUBJECT, OPT_ISSUER, OPT_FINGERPRINT, OPT_DATES,
61     OPT_PURPOSE, OPT_STARTDATE, OPT_ENDDATE, OPT_CHECKEND, OPT_CHECKHOST,
62     OPT_CHECKEMAIL, OPT_CHECKIP, OPT_NOOUT, OPT_TRUSTOUT, OPT_CLRTRUST,
63     OPT_CLRREJECT, OPT_ALIAS, OPT_CACREATESERIAL, OPT_CLREXT, OPT_OCSPID,
64     OPT_SUBJECT_HASH_OLD, OPT_ISSUER_HASH_OLD, OPT_COPY_EXTENSIONS,
65     OPT_BADSIG, OPT_MD, OPT_ENGINE, OPT_NOCERT, OPT_PRESERVE_DATES,
66     OPT_R_ENUM, OPT_PROV_ENUM, OPT_EXT
67 } OPTION_CHOICE;
68
69 const OPTIONS x509_options[] = {
70     OPT_SECTION("General"),
71     {"help", OPT_HELP, '-', "Display this summary"},
72
73     {"in", OPT_IN, '<',
74      "Certificate input (default stdin), or CSR input file with -req"},
75     {"passin", OPT_PASSIN, 's', "Private key and cert file pass-phrase source"},
76     {"new", OPT_NEW, '-', "Generate a certificate from scratch"},
77     {"x509toreq", OPT_X509TOREQ, '-',
78      "Output a certification request (rather than a certificate)"},
79     {"req", OPT_REQ, '-', "Input is a CSR file (rather than a certificate)"},
80     {"copy_extensions", OPT_COPY_EXTENSIONS, 's',
81      "copy extensions when converting from CSR to x509 or vice versa"},
82     {"inform", OPT_INFORM, 'f',
83      "CSR input file format (DER or PEM) - default PEM"},
84     {"vfyopt", OPT_VFYOPT, 's', "CSR verification parameter in n:v form"},
85     {"signkey", OPT_SIGNKEY, 's',
86      "Key used to self-sign certificate or cert request"},
87     {"keyform", OPT_KEYFORM, 'E',
88      "Key input format (ENGINE, other values ignored)"},
89     {"out", OPT_OUT, '>', "Output file - default stdout"},
90     {"outform", OPT_OUTFORM, 'f',
91      "Output format (DER or PEM) - default PEM"},
92     {"nocert", OPT_NOCERT, '-',
93      "No cert output (except for requested printing)"},
94     {"noout", OPT_NOOUT, '-', "No output (except for requested printing)"},
95
96     OPT_SECTION("Certificate printing"),
97     {"text", OPT_TEXT, '-', "Print the certificate in text form"},
98     {"certopt", OPT_CERTOPT, 's', "Various certificate text printing options"},
99     {"fingerprint", OPT_FINGERPRINT, '-', "Print the certificate fingerprint"},
100     {"alias", OPT_ALIAS, '-', "Print certificate alias"},
101     {"serial", OPT_SERIAL, '-', "Print serial number value"},
102     {"startdate", OPT_STARTDATE, '-', "Print the notBefore field"},
103     {"enddate", OPT_ENDDATE, '-', "Print the notAfter field"},
104     {"dates", OPT_DATES, '-', "Print both notBefore and notAfter fields"},
105     {"subject", OPT_SUBJECT, '-', "Print subject DN"},
106     {"issuer", OPT_ISSUER, '-', "Print issuer DN"},
107     {"nameopt", OPT_NAMEOPT, 's',
108      "Certificate subject/issuer name printing options"},
109     {"email", OPT_EMAIL, '-', "Print email address(es)"},
110     {"hash", OPT_HASH, '-', "Synonym for -subject_hash (for backward compat)"},
111     {"subject_hash", OPT_HASH, '-', "Print subject hash value"},
112 #ifndef OPENSSL_NO_MD5
113     {"subject_hash_old", OPT_SUBJECT_HASH_OLD, '-',
114      "Print old-style (MD5) subject hash value"},
115 #endif
116     {"issuer_hash", OPT_ISSUER_HASH, '-', "Print issuer hash value"},
117 #ifndef OPENSSL_NO_MD5
118     {"issuer_hash_old", OPT_ISSUER_HASH_OLD, '-',
119      "Print old-style (MD5) issuer hash value"},
120 #endif
121     {"ext", OPT_EXT, 's', "Print the specified X509V3 extensions"},
122     {"ocspid", OPT_OCSPID, '-',
123      "Print OCSP hash values for the subject name and public key"},
124     {"ocsp_uri", OPT_OCSP_URI, '-', "Print OCSP Responder URL(s)"},
125     {"purpose", OPT_PURPOSE, '-', "Print out certificate purposes"},
126     {"pubkey", OPT_PUBKEY, '-', "Print the public key in PEM format"},
127     {"modulus", OPT_MODULUS, '-', "Print the RSA key modulus"},
128
129     OPT_SECTION("Certificate checking"),
130     {"checkend", OPT_CHECKEND, 'M',
131      "Check whether cert expires in the next arg seconds"},
132     {OPT_MORE_STR, 1, 1, "Exit 1 (failure) if so, 0 if not"},
133     {"checkhost", OPT_CHECKHOST, 's', "Check certificate matches host"},
134     {"checkemail", OPT_CHECKEMAIL, 's', "Check certificate matches email"},
135     {"checkip", OPT_CHECKIP, 's', "Check certificate matches ipaddr"},
136
137     OPT_SECTION("Certificate output"),
138     {"set_serial", OPT_SET_SERIAL, 's',
139      "Serial number to use, overrides -CAserial"},
140     {"next_serial", OPT_NEXT_SERIAL, '-',
141      "Increment current certificate serial number"},
142     {"days", OPT_DAYS, 'n',
143      "Number of days until newly generated certificate expires - default 30"},
144     {"preserve_dates", OPT_PRESERVE_DATES, '-',
145      "Preserve existing validity dates"},
146     {"subj", OPT_SUBJ, 's', "Set or override certificate subject (and issuer)"},
147     {"force_pubkey", OPT_FORCE_PUBKEY, '<',
148      "Place the given key in new certificate"},
149     {"clrext", OPT_CLREXT, '-', "Clear all extensions when producing a certificate "},
150     {"extfile", OPT_EXTFILE, '<', "Config file with X509V3 extensions to add"},
151     {"extensions", OPT_EXTENSIONS, 's',
152      "Section of extfile to use - default: unnamed section"},
153     {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"},
154     {"badsig", OPT_BADSIG, '-',
155      "Corrupt last byte of certificate signature (for test)"},
156     {"", OPT_MD, '-', "Any supported digest, used for signing and printing"},
157
158     OPT_SECTION("Micro-CA"),
159     {"CA", OPT_CA, '<',
160      "Use the given CA certificate, conflicts with -signkey"},
161     {"CAform", OPT_CAFORM, 'F', "CA cert format (PEM/DER/P12); has no effect"},
162     {"CAkey", OPT_CAKEY, 's', "The corresponding CA key; default is -CA arg"},
163     {"CAkeyform", OPT_CAKEYFORM, 'E',
164      "CA key format (ENGINE, other values ignored)"},
165     {"CAserial", OPT_CASERIAL, 's',
166      "File that keeps track of CA-generated serial number"},
167     {"CAcreateserial", OPT_CACREATESERIAL, '-',
168      "Create CA serial number file if it does not exist"},
169
170     OPT_SECTION("Certificate trust output"),
171     {"trustout", OPT_TRUSTOUT, '-', "Mark certificate PEM output as trusted"},
172     {"setalias", OPT_SETALIAS, 's', "Set certificate alias (nickname)"},
173     {"clrtrust", OPT_CLRTRUST, '-', "Clear all trusted purposes"},
174     {"addtrust", OPT_ADDTRUST, 's', "Trust certificate for a given purpose"},
175     {"clrreject", OPT_CLRREJECT, '-',
176      "Clears all the prohibited or rejected uses of the certificate"},
177     {"addreject", OPT_ADDREJECT, 's',
178      "Reject certificate for a given purpose"},
179
180     OPT_R_OPTIONS,
181 #ifndef OPENSSL_NO_ENGINE
182     {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
183 #endif
184     OPT_PROV_OPTIONS,
185     {NULL}
186 };
187
188 int x509_main(int argc, char **argv)
189 {
190     ASN1_INTEGER *sno = NULL;
191     ASN1_OBJECT *objtmp = NULL;
192     BIO *out = NULL;
193     CONF *extconf = NULL;
194     int ext_copy = EXT_COPY_UNSET;
195     EVP_PKEY *signkey = NULL, *CAkey = NULL, *pubkey = NULL;
196     int newcert = 0;
197     char *subj = NULL;
198     X509_NAME *fsubj = NULL;
199     const unsigned long chtype = MBSTRING_ASC;
200     const int multirdn = 1;
201     STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL;
202     STACK_OF(OPENSSL_STRING) *sigopts = NULL, *vfyopts = NULL;
203     X509 *x = NULL, *xca = NULL;
204     X509_REQ *req = NULL, *rq = NULL;
205     X509_STORE *ctx = NULL;
206     const EVP_MD *digest = NULL;
207     char *CAkeyfile = NULL, *CAserial = NULL, *pubkeyfile = NULL, *alias = NULL;
208     char *checkhost = NULL, *checkemail = NULL, *checkip = NULL;
209     char *ext_names = NULL;
210     char *extsect = NULL, *extfile = NULL, *passin = NULL, *passinarg = NULL;
211     char *infile = NULL, *outfile = NULL, *signkeyfile = NULL, *CAfile = NULL;
212     char *prog;
213     int days = UNSET_DAYS; /* not explicitly set */
214     int x509toreq = 0, modulus = 0, print_pubkey = 0, pprint = 0;
215     int CAformat = FORMAT_PEM, CAkeyformat = FORMAT_PEM;
216     int fingerprint = 0, reqfile = 0, checkend = 0;
217     int informat = FORMAT_PEM, outformat = FORMAT_PEM, keyformat = FORMAT_PEM;
218     int next_serial = 0, subject_hash = 0, issuer_hash = 0, ocspid = 0;
219     int noout = 0, CA_createserial = 0, email = 0;
220     int ocsp_uri = 0, trustout = 0, clrtrust = 0, clrreject = 0, aliasout = 0;
221     int ret = 1, i, num = 0, badsig = 0, clrext = 0, nocert = 0;
222     int text = 0, serial = 0, subject = 0, issuer = 0, startdate = 0, ext = 0;
223     int enddate = 0;
224     time_t checkoffset = 0;
225     unsigned long certflag = 0;
226     int preserve_dates = 0;
227     OPTION_CHOICE o;
228     ENGINE *e = NULL;
229 #ifndef OPENSSL_NO_MD5
230     int subject_hash_old = 0, issuer_hash_old = 0;
231 #endif
232
233     ctx = X509_STORE_new();
234     if (ctx == NULL)
235         goto end;
236     X509_STORE_set_verify_cb(ctx, callb);
237
238     prog = opt_init(argc, argv, x509_options);
239     while ((o = opt_next()) != OPT_EOF) {
240         switch (o) {
241         case OPT_EOF:
242         case OPT_ERR:
243  opthelp:
244             BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
245             goto end;
246         case OPT_HELP:
247             opt_help(x509_options);
248             ret = 0;
249             goto end;
250         case OPT_INFORM:
251             if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat))
252                 goto opthelp;
253             break;
254         case OPT_IN:
255             infile = opt_arg();
256             break;
257         case OPT_OUTFORM:
258             if (!opt_format(opt_arg(), OPT_FMT_ANY, &outformat))
259                 goto opthelp;
260             break;
261         case OPT_KEYFORM:
262             if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyformat))
263                 goto opthelp;
264             break;
265         case OPT_CAFORM:
266             if (!opt_format(opt_arg(), OPT_FMT_ANY, &CAformat))
267                 goto opthelp;
268             break;
269         case OPT_CAKEYFORM:
270             if (!opt_format(opt_arg(), OPT_FMT_ANY, &CAkeyformat))
271                 goto opthelp;
272             break;
273         case OPT_OUT:
274             outfile = opt_arg();
275             break;
276         case OPT_REQ:
277             reqfile = 1;
278             break;
279         case OPT_COPY_EXTENSIONS:
280             if (!set_ext_copy(&ext_copy, opt_arg())) {
281                 BIO_printf(bio_err,
282                            "Invalid extension copy option: %s\n", opt_arg());
283                 goto end;
284             }
285             break;
286
287         case OPT_SIGOPT:
288             if (!sigopts)
289                 sigopts = sk_OPENSSL_STRING_new_null();
290             if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, opt_arg()))
291                 goto opthelp;
292             break;
293         case OPT_VFYOPT:
294             if (!vfyopts)
295                 vfyopts = sk_OPENSSL_STRING_new_null();
296             if (!vfyopts || !sk_OPENSSL_STRING_push(vfyopts, opt_arg()))
297                 goto opthelp;
298             break;
299         case OPT_DAYS:
300             days = atoi(opt_arg());
301             if (days < -1) {
302                 BIO_printf(bio_err, "%s: -days parameter arg must be >= -1\n",
303                            prog);
304                 goto end;
305             }
306             break;
307         case OPT_PASSIN:
308             passinarg = opt_arg();
309             break;
310         case OPT_EXTFILE:
311             extfile = opt_arg();
312             break;
313         case OPT_R_CASES:
314             if (!opt_rand(o))
315                 goto end;
316             break;
317         case OPT_PROV_CASES:
318             if (!opt_provider(o))
319                 goto end;
320             break;
321         case OPT_EXTENSIONS:
322             extsect = opt_arg();
323             break;
324         case OPT_SIGNKEY:
325             signkeyfile = opt_arg();
326             break;
327         case OPT_CA:
328             CAfile = opt_arg();
329             break;
330         case OPT_CAKEY:
331             CAkeyfile = opt_arg();
332             break;
333         case OPT_CASERIAL:
334             CAserial = opt_arg();
335             break;
336         case OPT_SET_SERIAL:
337             if (sno != NULL) {
338                 BIO_printf(bio_err, "Serial number supplied twice\n");
339                 goto opthelp;
340             }
341             if ((sno = s2i_ASN1_INTEGER(NULL, opt_arg())) == NULL)
342                 goto opthelp;
343             break;
344         case OPT_NEW:
345             newcert = 1;
346             break;
347         case OPT_FORCE_PUBKEY:
348             pubkeyfile = opt_arg();
349             break;
350         case OPT_SUBJ:
351             subj = opt_arg();
352             break;
353         case OPT_ADDTRUST:
354             if ((objtmp = OBJ_txt2obj(opt_arg(), 0)) == NULL) {
355                 BIO_printf(bio_err,
356                            "%s: Invalid trust object value %s\n",
357                            prog, opt_arg());
358                 goto opthelp;
359             }
360             if (trust == NULL && (trust = sk_ASN1_OBJECT_new_null()) == NULL)
361                 goto end;
362             sk_ASN1_OBJECT_push(trust, objtmp);
363             objtmp = NULL;
364             trustout = 1;
365             break;
366         case OPT_ADDREJECT:
367             if ((objtmp = OBJ_txt2obj(opt_arg(), 0)) == NULL) {
368                 BIO_printf(bio_err,
369                            "%s: Invalid reject object value %s\n",
370                            prog, opt_arg());
371                 goto opthelp;
372             }
373             if (reject == NULL
374                 && (reject = sk_ASN1_OBJECT_new_null()) == NULL)
375                 goto end;
376             sk_ASN1_OBJECT_push(reject, objtmp);
377             objtmp = NULL;
378             trustout = 1;
379             break;
380         case OPT_SETALIAS:
381             alias = opt_arg();
382             trustout = 1;
383             break;
384         case OPT_CERTOPT:
385             if (!set_cert_ex(&certflag, opt_arg()))
386                 goto opthelp;
387             break;
388         case OPT_NAMEOPT:
389             if (!set_nameopt(opt_arg()))
390                 goto opthelp;
391             break;
392         case OPT_ENGINE:
393             e = setup_engine(opt_arg(), 0);
394             break;
395         case OPT_EMAIL:
396             email = ++num;
397             break;
398         case OPT_OCSP_URI:
399             ocsp_uri = ++num;
400             break;
401         case OPT_SERIAL:
402             serial = ++num;
403             break;
404         case OPT_NEXT_SERIAL:
405             next_serial = ++num;
406             break;
407         case OPT_MODULUS:
408             modulus = ++num;
409             break;
410         case OPT_PUBKEY:
411             print_pubkey = ++num;
412             break;
413         case OPT_X509TOREQ:
414             x509toreq = 1;
415             break;
416         case OPT_TEXT:
417             text = ++num;
418             break;
419         case OPT_SUBJECT:
420             subject = ++num;
421             break;
422         case OPT_ISSUER:
423             issuer = ++num;
424             break;
425         case OPT_FINGERPRINT:
426             fingerprint = ++num;
427             break;
428         case OPT_HASH:
429             subject_hash = ++num;
430             break;
431         case OPT_ISSUER_HASH:
432             issuer_hash = ++num;
433             break;
434         case OPT_PURPOSE:
435             pprint = ++num;
436             break;
437         case OPT_STARTDATE:
438             startdate = ++num;
439             break;
440         case OPT_ENDDATE:
441             enddate = ++num;
442             break;
443         case OPT_NOOUT:
444             noout = ++num;
445             break;
446         case OPT_EXT:
447             ext = ++num;
448             ext_names = opt_arg();
449             break;
450         case OPT_NOCERT:
451             nocert = 1;
452             break;
453         case OPT_TRUSTOUT:
454             trustout = 1;
455             break;
456         case OPT_CLRTRUST:
457             clrtrust = ++num;
458             break;
459         case OPT_CLRREJECT:
460             clrreject = ++num;
461             break;
462         case OPT_ALIAS:
463             aliasout = ++num;
464             break;
465         case OPT_CACREATESERIAL:
466             CA_createserial = ++num;
467             break;
468         case OPT_CLREXT:
469             clrext = 1;
470             break;
471         case OPT_OCSPID:
472             ocspid = ++num;
473             break;
474         case OPT_BADSIG:
475             badsig = 1;
476             break;
477 #ifndef OPENSSL_NO_MD5
478         case OPT_SUBJECT_HASH_OLD:
479             subject_hash_old = ++num;
480             break;
481         case OPT_ISSUER_HASH_OLD:
482             issuer_hash_old = ++num;
483             break;
484 #else
485         case OPT_SUBJECT_HASH_OLD:
486         case OPT_ISSUER_HASH_OLD:
487             break;
488 #endif
489         case OPT_DATES:
490             startdate = ++num;
491             enddate = ++num;
492             break;
493         case OPT_CHECKEND:
494             checkend = 1;
495             {
496                 intmax_t temp = 0;
497                 if (!opt_imax(opt_arg(), &temp))
498                     goto opthelp;
499                 checkoffset = (time_t)temp;
500                 if ((intmax_t)checkoffset != temp) {
501                     BIO_printf(bio_err, "%s: Checkend time out of range %s\n",
502                                prog, opt_arg());
503                     goto opthelp;
504                 }
505             }
506             break;
507         case OPT_CHECKHOST:
508             checkhost = opt_arg();
509             break;
510         case OPT_CHECKEMAIL:
511             checkemail = opt_arg();
512             break;
513         case OPT_CHECKIP:
514             checkip = opt_arg();
515             break;
516         case OPT_PRESERVE_DATES:
517             preserve_dates = 1;
518             break;
519         case OPT_MD:
520             if (!opt_md(opt_unknown(), &digest))
521                 goto opthelp;
522         }
523     }
524
525     /* No extra arguments. */
526     argc = opt_num_rest();
527     if (argc != 0)
528         goto opthelp;
529
530     if (preserve_dates && days != UNSET_DAYS) {
531         BIO_printf(bio_err, "Cannot use -preserve_dates with -days option\n");
532         goto end;
533     }
534     if (days == UNSET_DAYS)
535         days = DEFAULT_DAYS;
536
537     if (!app_passwd(passinarg, NULL, &passin, NULL)) {
538         BIO_printf(bio_err, "Error getting password\n");
539         goto end;
540     }
541
542     if (!X509_STORE_set_default_paths_ex(ctx, app_get0_libctx(),
543                                          app_get0_propq()))
544         goto end;
545
546     if (newcert && infile != NULL) {
547         BIO_printf(bio_err, "The -in option cannot be used with -new\n");
548         goto end;
549     }
550     if (newcert && reqfile) {
551         BIO_printf(bio_err,
552                    "The -req option cannot be used with -new\n");
553         goto end;
554     }
555     if (signkeyfile != NULL) {
556         signkey = load_key(signkeyfile, keyformat, 0, passin, e, "private key");
557         if (signkey == NULL)
558             goto end;
559     }
560     if (pubkeyfile != NULL) {
561         if ((pubkey = load_pubkey(pubkeyfile, keyformat, 0, NULL, e,
562                                   "explicitly set public key")) == NULL)
563             goto end;
564     }
565
566     if (newcert) {
567         if (subj == NULL) {
568             BIO_printf(bio_err,
569                        "The -new option requires a subject to be set using -subj\n");
570             goto end;
571         }
572         if (signkeyfile == NULL && pubkeyfile == NULL) {
573             BIO_printf(bio_err,
574                        "The -new option without -signkey requires using -force_pubkey\n");
575             goto end;
576         }
577     }
578     if (subj != NULL
579             && (fsubj = parse_name(subj, chtype, multirdn, "subject")) == NULL)
580         goto end;
581
582     if (CAkeyfile == NULL)
583         CAkeyfile = CAfile;
584     if (CAfile != NULL) {
585         if (signkeyfile != NULL) {
586             BIO_printf(bio_err, "Cannot use both -signkey and -CA option\n");
587             goto end;
588         }
589     } else if (CAkeyfile != NULL) {
590         BIO_printf(bio_err,
591                    "Warning: ignoring -CAkey option since no -CA option is given\n");
592     }
593
594     if (extfile == NULL) {
595         if (extsect != NULL)
596             BIO_printf(bio_err,
597                        "Warning: ignoring -extensions option without -extfile\n");
598     } else {
599         X509V3_CTX ctx2;
600
601         if ((extconf = app_load_config(extfile)) == NULL)
602             goto end;
603         if (extsect == NULL) {
604             extsect = NCONF_get_string(extconf, "default", "extensions");
605             if (extsect == NULL) {
606                 ERR_clear_error();
607                 extsect = "default";
608             }
609         }
610         X509V3_set_ctx_test(&ctx2);
611         X509V3_set_nconf(&ctx2, extconf);
612         if (!X509V3_EXT_add_nconf(extconf, &ctx2, extsect, NULL)) {
613             BIO_printf(bio_err,
614                        "Error checking extension section %s\n", extsect);
615             goto end;
616         }
617     }
618
619     if (reqfile) {
620         EVP_PKEY *pkey;
621
622         req = load_csr(infile, informat, "certificate request input");
623         if (req == NULL)
624             goto end;
625
626         if ((pkey = X509_REQ_get0_pubkey(req)) == NULL) {
627             BIO_printf(bio_err, "Error unpacking public key\n");
628             goto end;
629         }
630         i = do_X509_REQ_verify(req, pkey, vfyopts);
631         if (i < 0) {
632             BIO_printf(bio_err,
633                        "Error while verifying certificate request self-signature\n");
634             goto end;
635         }
636         if (i == 0) {
637             BIO_printf(bio_err,
638                        "Certificate request self-signature did not match the contents\n");
639             goto end;
640         } else {
641             BIO_printf(bio_err, "Certificate request self-signature ok\n");
642         }
643
644         print_name(bio_err, "subject=", X509_REQ_get_subject_name(req),
645                    get_nameopt());
646     } else if (!x509toreq && ext_copy != EXT_COPY_UNSET) {
647         BIO_printf(bio_err, "Ignoring -copy_extensions since neither -x509toreq nor -req is given\n");
648     }
649
650     if (reqfile || newcert) {
651         if (preserve_dates)
652             BIO_printf(bio_err,
653                        "Warning: ignoring -preserve_dates option with -req or -new\n");
654         preserve_dates = 0;
655         if (signkeyfile == NULL && CAkeyfile == NULL) {
656             BIO_printf(bio_err,
657                        "We need a private key to sign with, use -signkey or -CAkey or -CA with private key\n");
658             goto end;
659         }
660         if ((x = X509_new_ex(app_get0_libctx(), app_get0_propq())) == NULL)
661             goto end;
662         if (sno == NULL) {
663             sno = ASN1_INTEGER_new();
664             if (sno == NULL || !rand_serial(NULL, sno))
665                 goto end;
666             if (!X509_set_serialNumber(x, sno))
667                 goto end;
668             ASN1_INTEGER_free(sno);
669             sno = NULL;
670         } else if (!X509_set_serialNumber(x, sno)) {
671             goto end;
672         }
673         if (req != NULL) {
674             if (ext_copy == EXT_COPY_UNSET) {
675                 BIO_printf(bio_err,
676                            "Warning: ignoring any extensions in the request since -copy_extensions is not given\n");
677             } else if (clrext && ext_copy != EXT_COPY_NONE) {
678                 BIO_printf(bio_err, "Must not use -clrext together with -copy_extensions\n");
679                 goto end;
680             } else if (!copy_extensions(x, req, ext_copy)) {
681                 BIO_printf(bio_err, "Error copying extensions from request\n");
682                 goto end;
683             }
684         }
685     } else {
686         x = load_cert_pass(infile, 1, passin, "certificate");
687         if (x == NULL)
688             goto end;
689     }
690     if ((fsubj != NULL || req != NULL)
691         && !X509_set_subject_name(x, fsubj != NULL ? fsubj :
692                                   X509_REQ_get_subject_name(req)))
693         goto end;
694     if ((pubkey != NULL || signkey != NULL || req != NULL)
695         && !X509_set_pubkey(x, pubkey != NULL ? pubkey :
696                             signkey != NULL ? signkey :
697                             X509_REQ_get0_pubkey(req)))
698         goto end;
699
700     if (CAfile != NULL) {
701         xca = load_cert_pass(CAfile, 1, passin, "CA certificate");
702         if (xca == NULL)
703             goto end;
704     }
705
706     out = bio_open_default(outfile, 'w', outformat);
707     if (out == NULL)
708         goto end;
709
710     if (!noout || text || next_serial)
711         OBJ_create("2.99999.3", "SET.ex3", "SET x509v3 extension 3");
712     /* TODO: why is this strange object created (and no error checked)? */
713
714     if (alias)
715         X509_alias_set1(x, (unsigned char *)alias, -1);
716
717     if (clrtrust)
718         X509_trust_clear(x);
719     if (clrreject)
720         X509_reject_clear(x);
721
722     if (trust != NULL) {
723         for (i = 0; i < sk_ASN1_OBJECT_num(trust); i++) {
724             objtmp = sk_ASN1_OBJECT_value(trust, i);
725             X509_add1_trust_object(x, objtmp);
726         }
727         objtmp = NULL;
728     }
729
730     if (reject != NULL) {
731         for (i = 0; i < sk_ASN1_OBJECT_num(reject); i++) {
732             objtmp = sk_ASN1_OBJECT_value(reject, i);
733             X509_add1_reject_object(x, objtmp);
734         }
735         objtmp = NULL;
736     }
737
738     if (x509toreq) { /* also works but makes little sense together with -req */
739         const STACK_OF(X509_EXTENSION) *exts;
740
741         if (signkey == NULL) {
742             BIO_printf(bio_err, "Must specify request key using -signkey\n");
743             goto end;
744         }
745         if (clrext)
746             BIO_printf(bio_err,
747                        "Warning: the -clrext option is ignored when producing a request\n");
748
749         if ((rq = X509_to_X509_REQ(x, NULL, NULL)) == NULL)
750             goto end;
751         exts = X509_get0_extensions(x);
752         if (sk_X509_EXTENSION_num(exts /* may be NULL */) > 0) {
753             if (ext_copy == EXT_COPY_UNSET) {
754                 BIO_printf(bio_err,
755                            "Warning: ignoring extensions in the certificate since -copy_extensions is not given\n");
756             } else if (ext_copy != EXT_COPY_NONE
757                        && !X509_REQ_add_extensions(rq, exts)) {
758                 BIO_printf(bio_err,
759                            "Error copying extensions from certificate\n");
760                 goto end;
761             }
762         }
763         if (!X509_REQ_sign(rq, signkey, digest))
764             goto end;
765         if (!noout) {
766             if (outformat == FORMAT_ASN1) {
767                 X509_REQ_print_ex(out, rq, get_nameopt(), X509_FLAG_COMPAT);
768                 i = i2d_X509_bio(out, x);
769             } else {
770                 i = PEM_write_bio_X509_REQ(out, rq);
771             }
772             if (!i) {
773                 BIO_printf(bio_err,
774                            "Unable to write certificate request\n");
775                 goto end;
776             }
777         }
778         noout = 1;
779     } else if (signkey != NULL) {
780         if (!sign(x, signkey, x /* self-issuing */, sigopts, days, clrext,
781                   digest, extconf, extsect, preserve_dates))
782             goto end;
783     } else if (CAfile != NULL) {
784         if (!reqfile && !newcert) { /* certificate should be self-signed */
785             X509_STORE_CTX *xsc = X509_STORE_CTX_new();
786
787             if (xsc == NULL || !X509_STORE_CTX_init(xsc, ctx, x, NULL)) {
788                 BIO_printf(bio_err, "Error initialising X509 store\n");
789                 X509_STORE_CTX_free(xsc);
790                 goto end;
791             }
792             X509_STORE_CTX_set_cert(xsc, x);
793             X509_STORE_CTX_set_flags(xsc, X509_V_FLAG_CHECK_SS_SIGNATURE);
794             i = X509_verify_cert(xsc);
795             X509_STORE_CTX_free(xsc);
796             if (i <= 0)
797                 goto end;
798         }
799         if ((CAkey = load_key(CAkeyfile, CAkeyformat,
800                               0, passin, e, "CA private key")) == NULL)
801             goto end;
802         if (!x509_certify(ctx, CAfile, digest, x, xca, CAkey, sigopts,
803                           CAserial, CA_createserial, days, clrext,
804                           extconf, extsect, sno, preserve_dates))
805             goto end;
806     }
807     if (badsig) {
808         const ASN1_BIT_STRING *signature;
809
810         X509_get0_signature(&signature, NULL, x);
811         corrupt_signature(signature);
812     }
813
814     if (num) { /* TODO remove this needless guard and extra indentation below */
815         /* Process print options in the given order, as indicated by index i */
816         for (i = 1; i <= num; i++) {
817             if (issuer == i) {
818                 print_name(out, "issuer=", X509_get_issuer_name(x),
819                            get_nameopt());
820             } else if (subject == i) {
821                 print_name(out, "subject=",
822                            X509_get_subject_name(x), get_nameopt());
823             } else if (serial == i) {
824                 BIO_printf(out, "serial=");
825                 i2a_ASN1_INTEGER(out, X509_get0_serialNumber(x));
826                 BIO_printf(out, "\n");
827             } else if (next_serial == i) {
828                 ASN1_INTEGER *ser = X509_get_serialNumber(x);
829                 BIGNUM *bnser = ASN1_INTEGER_to_BN(ser, NULL);
830
831                 if (!bnser)
832                     goto end;
833                 if (!BN_add_word(bnser, 1))
834                     goto end;
835                 ser = BN_to_ASN1_INTEGER(bnser, NULL);
836                 if (!ser)
837                     goto end;
838                 BN_free(bnser);
839                 i2a_ASN1_INTEGER(out, ser);
840                 ASN1_INTEGER_free(ser);
841                 BIO_puts(out, "\n");
842             } else if (email == i || ocsp_uri == i) {
843                 STACK_OF(OPENSSL_STRING) *emlst;
844                 int j;
845
846                 if (email == i)
847                     emlst = X509_get1_email(x);
848                 else
849                     emlst = X509_get1_ocsp(x);
850                 for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++)
851                     BIO_printf(out, "%s\n",
852                                sk_OPENSSL_STRING_value(emlst, j));
853                 X509_email_free(emlst);
854             } else if (aliasout == i) {
855                 unsigned char *alstr;
856
857                 alstr = X509_alias_get0(x, NULL);
858                 if (alstr)
859                     BIO_printf(out, "%s\n", alstr);
860                 else
861                     BIO_puts(out, "<No Alias>\n");
862             } else if (subject_hash == i) {
863                 BIO_printf(out, "%08lx\n", X509_subject_name_hash(x));
864 #ifndef OPENSSL_NO_MD5
865             } else if (subject_hash_old == i) {
866                 BIO_printf(out, "%08lx\n", X509_subject_name_hash_old(x));
867 #endif
868             } else if (issuer_hash == i) {
869                 BIO_printf(out, "%08lx\n", X509_issuer_name_hash(x));
870 #ifndef OPENSSL_NO_MD5
871             } else if (issuer_hash_old == i) {
872                 BIO_printf(out, "%08lx\n", X509_issuer_name_hash_old(x));
873 #endif
874             } else if (pprint == i) {
875                 X509_PURPOSE *ptmp;
876                 int j;
877
878                 BIO_printf(out, "Certificate purposes:\n");
879                 for (j = 0; j < X509_PURPOSE_get_count(); j++) {
880                     ptmp = X509_PURPOSE_get0(j);
881                     purpose_print(out, x, ptmp);
882                 }
883             } else if (modulus == i) {
884                 EVP_PKEY *pkey;
885
886                 pkey = X509_get0_pubkey(x);
887                 if (pkey == NULL) {
888                     BIO_printf(bio_err,
889                                "Modulus unavailable: cannot get key\n");
890                     goto end;
891                 }
892                 BIO_printf(out, "Modulus=");
893                 if (EVP_PKEY_is_a(pkey, "RSA")) {
894                     BIGNUM *n;
895
896                     /* Every RSA key has an 'n' */
897                     EVP_PKEY_get_bn_param(pkey, "n", &n);
898                     BN_print(out, n);
899                     BN_free(n);
900                 } else if (EVP_PKEY_is_a(pkey, "DSA")) {
901                     BIGNUM *dsapub;
902
903                     /* Every DSA key has an 'pub' */
904                     EVP_PKEY_get_bn_param(pkey, "pub", &dsapub);
905                     BN_print(out, dsapub);
906                     BN_free(dsapub);
907                 } else {
908                     BIO_printf(out, "No modulus for this public key type");
909                 }
910                 BIO_printf(out, "\n");
911             } else if (print_pubkey == i) {
912                 EVP_PKEY *pkey;
913
914                 pkey = X509_get0_pubkey(x);
915                 if (pkey == NULL) {
916                     BIO_printf(bio_err, "Error getting public key\n");
917                     goto end;
918                 }
919                 PEM_write_bio_PUBKEY(out, pkey);
920             } else if (text == i) {
921                 X509_print_ex(out, x, get_nameopt(), certflag);
922             } else if (startdate == i) {
923                 BIO_puts(out, "notBefore=");
924                 ASN1_TIME_print(out, X509_get0_notBefore(x));
925                 BIO_puts(out, "\n");
926             } else if (enddate == i) {
927                 BIO_puts(out, "notAfter=");
928                 ASN1_TIME_print(out, X509_get0_notAfter(x));
929                 BIO_puts(out, "\n");
930             } else if (fingerprint == i) {
931                 int j;
932                 unsigned int n;
933                 unsigned char md[EVP_MAX_MD_SIZE];
934                 const EVP_MD *fdig = digest;
935
936                 if (fdig == NULL)
937                     fdig = EVP_sha1();
938
939                 if (!X509_digest(x, fdig, md, &n)) {
940                     BIO_printf(bio_err, "Out of memory\n");
941                     goto end;
942                 }
943                 BIO_printf(out, "%s Fingerprint=",
944                            OBJ_nid2sn(EVP_MD_type(fdig)));
945                 for (j = 0; j < (int)n; j++) {
946                     BIO_printf(out, "%02X%c", md[j], (j + 1 == (int)n)
947                                ? '\n' : ':');
948                 }
949             } else if (ocspid == i) {
950                 X509_ocspid_print(out, x);
951             } else if (ext == i) {
952                 print_x509v3_exts(out, x, ext_names);
953             }
954         }
955     }
956
957     if (checkend) {
958         time_t tcheck = time(NULL) + checkoffset;
959
960         if (X509_cmp_time(X509_get0_notAfter(x), &tcheck) < 0) {
961             BIO_printf(out, "Certificate will expire\n");
962             ret = 1;
963         } else {
964             BIO_printf(out, "Certificate will not expire\n");
965             ret = 0;
966         }
967         goto end;
968     }
969
970     print_cert_checks(out, x, checkhost, checkemail, checkip);
971
972     if (noout || nocert) {
973         ret = 0;
974         goto end;
975     }
976
977     if (outformat == FORMAT_ASN1) {
978         i = i2d_X509_bio(out, x);
979     } else if (outformat == FORMAT_PEM) {
980         if (trustout)
981             i = PEM_write_bio_X509_AUX(out, x);
982         else
983             i = PEM_write_bio_X509(out, x);
984     } else {
985         BIO_printf(bio_err, "Bad output format specified for outfile\n");
986         goto end;
987     }
988     if (!i) {
989         BIO_printf(bio_err, "Unable to write certificate\n");
990         goto end;
991     }
992     ret = 0;
993
994  end:
995     if (ret != 0)
996         ERR_print_errors(bio_err);
997     NCONF_free(extconf);
998     BIO_free_all(out);
999     X509_STORE_free(ctx);
1000     X509_NAME_free(fsubj);
1001     X509_REQ_free(req);
1002     X509_free(x);
1003     X509_free(xca);
1004     EVP_PKEY_free(signkey);
1005     EVP_PKEY_free(CAkey);
1006     EVP_PKEY_free(pubkey);
1007     sk_OPENSSL_STRING_free(sigopts);
1008     sk_OPENSSL_STRING_free(vfyopts);
1009     X509_REQ_free(rq);
1010     ASN1_INTEGER_free(sno);
1011     sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free);
1012     sk_ASN1_OBJECT_pop_free(reject, ASN1_OBJECT_free);
1013     ASN1_OBJECT_free(objtmp);
1014     release_engine(e);
1015     clear_free(passin);
1016     return ret;
1017 }
1018
1019 static ASN1_INTEGER *x509_load_serial(const char *CAfile,
1020                                       const char *serialfile, int create)
1021 {
1022     char *buf = NULL;
1023     ASN1_INTEGER *bs = NULL;
1024     BIGNUM *serial = NULL;
1025
1026     if (serialfile == NULL) {
1027         const char *p = strrchr(CAfile, '.');
1028         size_t len = p != NULL ? (size_t)(p - CAfile) : strlen(CAfile);
1029
1030         buf = app_malloc(len + sizeof(POSTFIX), "serial# buffer");
1031         memcpy(buf, CAfile, len);
1032         memcpy(buf + len, POSTFIX, sizeof(POSTFIX));
1033         serialfile = buf;
1034     }
1035
1036     serial = load_serial(serialfile, create, NULL);
1037     if (serial == NULL)
1038         goto end;
1039
1040     if (!BN_add_word(serial, 1)) {
1041         BIO_printf(bio_err, "Serial number increment failure\n");
1042         goto end;
1043     }
1044
1045     if (!save_serial(serialfile, NULL, serial, &bs))
1046         goto end;
1047
1048  end:
1049     OPENSSL_free(buf);
1050     BN_free(serial);
1051     return bs;
1052 }
1053
1054 static int x509_certify(X509_STORE *ctx, const char *CAfile,
1055                         const EVP_MD *digest,
1056                         X509 *x, X509 *xca, EVP_PKEY *pkey,
1057                         STACK_OF(OPENSSL_STRING) *sigopts,
1058                         const char *serialfile, int create,
1059                         int days, int clrext, CONF *conf, const char *section,
1060                         ASN1_INTEGER *sno, int preserve_dates)
1061 {
1062     int ret = 0;
1063     ASN1_INTEGER *bs = NULL;
1064
1065     if (!X509_check_private_key(xca, pkey)) {
1066         BIO_printf(bio_err,
1067                    "CA certificate and CA private key do not match\n");
1068         goto end;
1069     }
1070
1071     if (sno)
1072         bs = sno;
1073     else if ((bs = x509_load_serial(CAfile, serialfile, create)) == NULL)
1074         goto end;
1075     if (!X509_set_serialNumber(x, bs))
1076         goto end;
1077
1078     if (!sign(x, pkey, xca, sigopts, days, clrext, digest,
1079               conf, section, preserve_dates))
1080         goto end;
1081
1082     ret = 1;
1083  end:
1084     if (!sno)
1085         ASN1_INTEGER_free(bs);
1086     return ret;
1087 }
1088
1089 static int callb(int ok, X509_STORE_CTX *ctx)
1090 {
1091     int err;
1092     X509 *err_cert;
1093
1094     /*
1095      * It is ok to use a self-signed certificate. This case will catch both
1096      * the initial ok == 0 and the final ok == 1 calls to this function.
1097      */
1098     err = X509_STORE_CTX_get_error(ctx);
1099     if (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT)
1100         return 1;
1101
1102     /*
1103      * BAD we should have gotten an error.  Normally if everything worked
1104      * X509_STORE_CTX_get_error(ctx) will still be set to
1105      * DEPTH_ZERO_SELF_....
1106      */
1107     if (ok) {
1108         BIO_printf(bio_err,
1109                    "Error with certificate to be certified - should be self-signed\n");
1110         return 0;
1111     } else {
1112         err_cert = X509_STORE_CTX_get_current_cert(ctx);
1113         print_name(bio_err, NULL, X509_get_subject_name(err_cert), 0);
1114         BIO_printf(bio_err,
1115                    "Error with certificate - error %d at depth %d\n%s\n", err,
1116                    X509_STORE_CTX_get_error_depth(ctx),
1117                    X509_verify_cert_error_string(err));
1118         return 1;
1119     }
1120 }
1121
1122 static int sign(X509 *x, EVP_PKEY *pkey, X509 *issuer,
1123                 STACK_OF(OPENSSL_STRING) *sigopts,
1124                 int days, int clrext,
1125                 const EVP_MD *digest, CONF *conf, const char *section,
1126                 int preserve_dates)
1127 {
1128     X509V3_CTX ext_ctx;
1129
1130     if (!X509_set_issuer_name(x, X509_get_subject_name(issuer)))
1131         return 0;
1132
1133     if (!preserve_dates && !set_cert_times(x, NULL, NULL, days))
1134         return 0;
1135
1136     if (clrext) {
1137         while (X509_get_ext_count(x) > 0)
1138             X509_delete_ext(x, 0);
1139     }
1140
1141     X509V3_set_ctx(&ext_ctx, issuer, x, NULL, NULL, X509V3_CTX_REPLACE);
1142     if (issuer == x
1143         /* prepare the correct AKID of self-issued, possibly self-signed cert */
1144             && !X509V3_set_issuer_pkey(&ext_ctx, pkey))
1145         return 0;
1146
1147     if (conf != NULL) {
1148         X509V3_set_nconf(&ext_ctx, conf);
1149         if (!X509V3_EXT_add_nconf(conf, &ext_ctx, section, x)) {
1150             BIO_printf(bio_err,
1151                        "Error adding extensions from section %s\n", section);
1152             return 0;
1153         }
1154     }
1155     return do_X509_sign(x, pkey, digest, sigopts, &ext_ctx);
1156 }
1157
1158 static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt)
1159 {
1160     int id, i, idret;
1161     const char *pname;
1162     id = X509_PURPOSE_get_id(pt);
1163     pname = X509_PURPOSE_get0_name(pt);
1164     for (i = 0; i < 2; i++) {
1165         idret = X509_check_purpose(cert, id, i);
1166         BIO_printf(bio, "%s%s : ", pname, i ? " CA" : "");
1167         if (idret == 1)
1168             BIO_printf(bio, "Yes\n");
1169         else if (idret == 0)
1170             BIO_printf(bio, "No\n");
1171         else
1172             BIO_printf(bio, "Yes (WARNING code=%d)\n", idret);
1173     }
1174     return 1;
1175 }
1176
1177 static int parse_ext_names(char *names, const char **result)
1178 {
1179     char *p, *q;
1180     int cnt = 0, len = 0;
1181
1182     p = q = names;
1183     len = strlen(names);
1184
1185     while (q - names <= len) {
1186         if (*q != ',' && *q != '\0') {
1187             q++;
1188             continue;
1189         }
1190         if (p != q) {
1191             /* found */
1192             if (result != NULL) {
1193                 result[cnt] = p;
1194                 *q = '\0';
1195             }
1196             cnt++;
1197         }
1198         p = ++q;
1199     }
1200
1201     return cnt;
1202 }
1203
1204 static int print_x509v3_exts(BIO *bio, X509 *x, const char *ext_names)
1205 {
1206     const STACK_OF(X509_EXTENSION) *exts = NULL;
1207     STACK_OF(X509_EXTENSION) *exts2 = NULL;
1208     X509_EXTENSION *ext = NULL;
1209     ASN1_OBJECT *obj;
1210     int i, j, ret = 0, num, nn = 0;
1211     const char *sn, **names = NULL;
1212     char *tmp_ext_names = NULL;
1213
1214     exts = X509_get0_extensions(x);
1215     if ((num = sk_X509_EXTENSION_num(exts)) <= 0) {
1216         BIO_printf(bio_err, "No extensions in certificate\n");
1217         ret = 1;
1218         goto end;
1219     }
1220
1221     /* parse comma separated ext name string */
1222     if ((tmp_ext_names = OPENSSL_strdup(ext_names)) == NULL)
1223         goto end;
1224     if ((nn = parse_ext_names(tmp_ext_names, NULL)) == 0) {
1225         BIO_printf(bio, "Invalid extension names: %s\n", ext_names);
1226         goto end;
1227     }
1228     if ((names = OPENSSL_malloc(sizeof(char *) * nn)) == NULL)
1229         goto end;
1230     parse_ext_names(tmp_ext_names, names);
1231
1232     for (i = 0; i < num; i++) {
1233         ext = sk_X509_EXTENSION_value(exts, i);
1234
1235         /* check if this ext is what we want */
1236         obj = X509_EXTENSION_get_object(ext);
1237         sn = OBJ_nid2sn(OBJ_obj2nid(obj));
1238         if (sn == NULL || strcmp(sn, "UNDEF") == 0)
1239             continue;
1240
1241         for (j = 0; j < nn; j++) {
1242             if (strcmp(sn, names[j]) == 0) {
1243                 /* push the extension into a new stack */
1244                 if (exts2 == NULL
1245                     && (exts2 = sk_X509_EXTENSION_new_null()) == NULL)
1246                     goto end;
1247                 if (!sk_X509_EXTENSION_push(exts2, ext))
1248                     goto end;
1249             }
1250         }
1251     }
1252
1253     if (!sk_X509_EXTENSION_num(exts2)) {
1254         BIO_printf(bio, "No extensions matched with %s\n", ext_names);
1255         ret = 1;
1256         goto end;
1257     }
1258
1259     ret = X509V3_extensions_print(bio, NULL, exts2, 0, 0);
1260  end:
1261     sk_X509_EXTENSION_free(exts2);
1262     OPENSSL_free(names);
1263     OPENSSL_free(tmp_ext_names);
1264     return ret;
1265 }