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