x509.c revision 306195
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
90static 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
159static int MS_CALLBACK callb(int ok, X509_STORE_CTX *ctx);
160static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext,
161                const EVP_MD *digest, CONF *conf, char *section);
162static 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);
167static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt);
168static int reqfile = 0;
169#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
170static int force_version = 2;
171#endif
172
173int MAIN(int, char **);
174
175int 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
1049static 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
1095static 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    if (upkey == NULL)  {
1109        BIO_printf(bio_err, "Error obtaining CA X509 public key\n");
1110        goto end;
1111    }
1112    EVP_PKEY_copy_parameters(upkey, pkey);
1113    EVP_PKEY_free(upkey);
1114
1115    if (!X509_STORE_CTX_init(&xsc, ctx, x, NULL)) {
1116        BIO_printf(bio_err, "Error initialising X509 store\n");
1117        goto end;
1118    }
1119    if (sno)
1120        bs = sno;
1121    else if (!(bs = x509_load_serial(CAfile, serialfile, create)))
1122        goto end;
1123
1124/*      if (!X509_STORE_add_cert(ctx,x)) goto end;*/
1125
1126    /*
1127     * NOTE: this certificate can/should be self signed, unless it was a
1128     * certificate request in which case it is not.
1129     */
1130    X509_STORE_CTX_set_cert(&xsc, x);
1131    X509_STORE_CTX_set_flags(&xsc, X509_V_FLAG_CHECK_SS_SIGNATURE);
1132    if (!reqfile && X509_verify_cert(&xsc) <= 0)
1133        goto end;
1134
1135    if (!X509_check_private_key(xca, pkey)) {
1136        BIO_printf(bio_err,
1137                   "CA certificate and CA private key do not match\n");
1138        goto end;
1139    }
1140
1141    if (!X509_set_issuer_name(x, X509_get_subject_name(xca)))
1142        goto end;
1143    if (!X509_set_serialNumber(x, bs))
1144        goto end;
1145
1146    if (X509_gmtime_adj(X509_get_notBefore(x), 0L) == NULL)
1147        goto end;
1148
1149    /* hardwired expired */
1150    if (X509_time_adj_ex(X509_get_notAfter(x), days, 0, NULL) == NULL)
1151        goto end;
1152
1153    if (clrext) {
1154        while (X509_get_ext_count(x) > 0)
1155            X509_delete_ext(x, 0);
1156    }
1157
1158    if (conf) {
1159        X509V3_CTX ctx2;
1160#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
1161        X509_set_version(x, force_version);
1162#else
1163        X509_set_version(x, 2); /* version 3 certificate */
1164#endif
1165        X509V3_set_ctx(&ctx2, xca, x, NULL, NULL, 0);
1166        X509V3_set_nconf(&ctx2, conf);
1167        if (!X509V3_EXT_add_nconf(conf, &ctx2, section, x))
1168            goto end;
1169    }
1170
1171    if (!do_X509_sign(bio_err, x, pkey, digest, sigopts))
1172        goto end;
1173    ret = 1;
1174 end:
1175    X509_STORE_CTX_cleanup(&xsc);
1176    if (!ret)
1177        ERR_print_errors(bio_err);
1178    if (!sno)
1179        ASN1_INTEGER_free(bs);
1180    return ret;
1181}
1182
1183static int MS_CALLBACK callb(int ok, X509_STORE_CTX *ctx)
1184{
1185    int err;
1186    X509 *err_cert;
1187
1188    /*
1189     * it is ok to use a self signed certificate This case will catch both
1190     * the initial ok == 0 and the final ok == 1 calls to this function
1191     */
1192    err = X509_STORE_CTX_get_error(ctx);
1193    if (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT)
1194        return 1;
1195
1196    /*
1197     * BAD we should have gotten an error.  Normally if everything worked
1198     * X509_STORE_CTX_get_error(ctx) will still be set to
1199     * DEPTH_ZERO_SELF_....
1200     */
1201    if (ok) {
1202        BIO_printf(bio_err,
1203                   "error with certificate to be certified - should be self signed\n");
1204        return 0;
1205    } else {
1206        err_cert = X509_STORE_CTX_get_current_cert(ctx);
1207        print_name(bio_err, NULL, X509_get_subject_name(err_cert), 0);
1208        BIO_printf(bio_err,
1209                   "error with certificate - error %d at depth %d\n%s\n", err,
1210                   X509_STORE_CTX_get_error_depth(ctx),
1211                   X509_verify_cert_error_string(err));
1212        return 1;
1213    }
1214}
1215
1216/* self sign */
1217static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext,
1218                const EVP_MD *digest, CONF *conf, char *section)
1219{
1220
1221    EVP_PKEY *pktmp;
1222
1223    pktmp = X509_get_pubkey(x);
1224    if (pktmp == NULL)
1225        goto err;
1226    EVP_PKEY_copy_parameters(pktmp, pkey);
1227    EVP_PKEY_save_parameters(pktmp, 1);
1228    EVP_PKEY_free(pktmp);
1229
1230    if (!X509_set_issuer_name(x, X509_get_subject_name(x)))
1231        goto err;
1232    if (X509_gmtime_adj(X509_get_notBefore(x), 0) == NULL)
1233        goto err;
1234
1235    if (X509_time_adj_ex(X509_get_notAfter(x), days, 0, NULL) == NULL)
1236        goto err;
1237
1238    if (!X509_set_pubkey(x, pkey))
1239        goto err;
1240    if (clrext) {
1241        while (X509_get_ext_count(x) > 0)
1242            X509_delete_ext(x, 0);
1243    }
1244    if (conf) {
1245        X509V3_CTX ctx;
1246#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
1247        X509_set_version(x, force_version);
1248#else
1249        X509_set_version(x, 2); /* version 3 certificate */
1250#endif
1251        X509V3_set_ctx(&ctx, x, x, NULL, NULL, 0);
1252        X509V3_set_nconf(&ctx, conf);
1253        if (!X509V3_EXT_add_nconf(conf, &ctx, section, x))
1254            goto err;
1255    }
1256    if (!X509_sign(x, pkey, digest))
1257        goto err;
1258    return 1;
1259 err:
1260    ERR_print_errors(bio_err);
1261    return 0;
1262}
1263
1264static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt)
1265{
1266    int id, i, idret;
1267    char *pname;
1268    id = X509_PURPOSE_get_id(pt);
1269    pname = X509_PURPOSE_get0_name(pt);
1270    for (i = 0; i < 2; i++) {
1271        idret = X509_check_purpose(cert, id, i);
1272        BIO_printf(bio, "%s%s : ", pname, i ? " CA" : "");
1273        if (idret == 1)
1274            BIO_printf(bio, "Yes\n");
1275        else if (idret == 0)
1276            BIO_printf(bio, "No\n");
1277        else
1278            BIO_printf(bio, "Yes (WARNING code=%d)\n", idret);
1279    }
1280    return 1;
1281}
1282