v3_purp.c revision 296465
1/* v3_purp.c */
2/*
3 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
4 * 2001.
5 */
6/* ====================================================================
7 * Copyright (c) 1999-2004 The OpenSSL Project.  All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in
18 *    the documentation and/or other materials provided with the
19 *    distribution.
20 *
21 * 3. All advertising materials mentioning features or use of this
22 *    software must display the following acknowledgment:
23 *    "This product includes software developed by the OpenSSL Project
24 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25 *
26 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27 *    endorse or promote products derived from this software without
28 *    prior written permission. For written permission, please contact
29 *    licensing@OpenSSL.org.
30 *
31 * 5. Products derived from this software may not be called "OpenSSL"
32 *    nor may "OpenSSL" appear in their names without prior written
33 *    permission of the OpenSSL Project.
34 *
35 * 6. Redistributions of any form whatsoever must retain the following
36 *    acknowledgment:
37 *    "This product includes software developed by the OpenSSL Project
38 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39 *
40 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51 * OF THE POSSIBILITY OF SUCH DAMAGE.
52 * ====================================================================
53 *
54 * This product includes cryptographic software written by Eric Young
55 * (eay@cryptsoft.com).  This product includes software written by Tim
56 * Hudson (tjh@cryptsoft.com).
57 *
58 */
59
60#include <stdio.h>
61#include "cryptlib.h"
62#include <openssl/x509v3.h>
63#include <openssl/x509_vfy.h>
64
65static void x509v3_cache_extensions(X509 *x);
66
67static int check_ssl_ca(const X509 *x);
68static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x,
69                                    int ca);
70static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x,
71                                    int ca);
72static int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x,
73                                       int ca);
74static int purpose_smime(const X509 *x, int ca);
75static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x,
76                                    int ca);
77static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x,
78                                       int ca);
79static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x,
80                                  int ca);
81static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca);
82static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca);
83
84static int xp_cmp(const X509_PURPOSE *const *a, const X509_PURPOSE *const *b);
85static void xptable_free(X509_PURPOSE *p);
86
87static X509_PURPOSE xstandard[] = {
88    {X509_PURPOSE_SSL_CLIENT, X509_TRUST_SSL_CLIENT, 0,
89     check_purpose_ssl_client, "SSL client", "sslclient", NULL},
90    {X509_PURPOSE_SSL_SERVER, X509_TRUST_SSL_SERVER, 0,
91     check_purpose_ssl_server, "SSL server", "sslserver", NULL},
92    {X509_PURPOSE_NS_SSL_SERVER, X509_TRUST_SSL_SERVER, 0,
93     check_purpose_ns_ssl_server, "Netscape SSL server", "nssslserver", NULL},
94    {X509_PURPOSE_SMIME_SIGN, X509_TRUST_EMAIL, 0, check_purpose_smime_sign,
95     "S/MIME signing", "smimesign", NULL},
96    {X509_PURPOSE_SMIME_ENCRYPT, X509_TRUST_EMAIL, 0,
97     check_purpose_smime_encrypt, "S/MIME encryption", "smimeencrypt", NULL},
98    {X509_PURPOSE_CRL_SIGN, X509_TRUST_COMPAT, 0, check_purpose_crl_sign,
99     "CRL signing", "crlsign", NULL},
100    {X509_PURPOSE_ANY, X509_TRUST_DEFAULT, 0, no_check, "Any Purpose", "any",
101     NULL},
102    {X509_PURPOSE_OCSP_HELPER, X509_TRUST_COMPAT, 0, ocsp_helper,
103     "OCSP helper", "ocsphelper", NULL},
104};
105
106#define X509_PURPOSE_COUNT (sizeof(xstandard)/sizeof(X509_PURPOSE))
107
108IMPLEMENT_STACK_OF(X509_PURPOSE)
109
110static STACK_OF(X509_PURPOSE) *xptable = NULL;
111
112static int xp_cmp(const X509_PURPOSE *const *a, const X509_PURPOSE *const *b)
113{
114    return (*a)->purpose - (*b)->purpose;
115}
116
117/*
118 * As much as I'd like to make X509_check_purpose use a "const" X509* I
119 * really can't because it does recalculate hashes and do other non-const
120 * things.
121 */
122int X509_check_purpose(X509 *x, int id, int ca)
123{
124    int idx;
125    const X509_PURPOSE *pt;
126    if (!(x->ex_flags & EXFLAG_SET)) {
127        CRYPTO_w_lock(CRYPTO_LOCK_X509);
128        x509v3_cache_extensions(x);
129        CRYPTO_w_unlock(CRYPTO_LOCK_X509);
130    }
131    if (id == -1)
132        return 1;
133    idx = X509_PURPOSE_get_by_id(id);
134    if (idx == -1)
135        return -1;
136    pt = X509_PURPOSE_get0(idx);
137    return pt->check_purpose(pt, x, ca);
138}
139
140int X509_PURPOSE_set(int *p, int purpose)
141{
142    if (X509_PURPOSE_get_by_id(purpose) == -1) {
143        X509V3err(X509V3_F_X509_PURPOSE_SET, X509V3_R_INVALID_PURPOSE);
144        return 0;
145    }
146    *p = purpose;
147    return 1;
148}
149
150int X509_PURPOSE_get_count(void)
151{
152    if (!xptable)
153        return X509_PURPOSE_COUNT;
154    return sk_X509_PURPOSE_num(xptable) + X509_PURPOSE_COUNT;
155}
156
157X509_PURPOSE *X509_PURPOSE_get0(int idx)
158{
159    if (idx < 0)
160        return NULL;
161    if (idx < (int)X509_PURPOSE_COUNT)
162        return xstandard + idx;
163    return sk_X509_PURPOSE_value(xptable, idx - X509_PURPOSE_COUNT);
164}
165
166int X509_PURPOSE_get_by_sname(char *sname)
167{
168    int i;
169    X509_PURPOSE *xptmp;
170    for (i = 0; i < X509_PURPOSE_get_count(); i++) {
171        xptmp = X509_PURPOSE_get0(i);
172        if (!strcmp(xptmp->sname, sname))
173            return i;
174    }
175    return -1;
176}
177
178int X509_PURPOSE_get_by_id(int purpose)
179{
180    X509_PURPOSE tmp;
181    int idx;
182    if ((purpose >= X509_PURPOSE_MIN) && (purpose <= X509_PURPOSE_MAX))
183        return purpose - X509_PURPOSE_MIN;
184    tmp.purpose = purpose;
185    if (!xptable)
186        return -1;
187    idx = sk_X509_PURPOSE_find(xptable, &tmp);
188    if (idx == -1)
189        return -1;
190    return idx + X509_PURPOSE_COUNT;
191}
192
193int X509_PURPOSE_add(int id, int trust, int flags,
194                     int (*ck) (const X509_PURPOSE *, const X509 *, int),
195                     char *name, char *sname, void *arg)
196{
197    int idx;
198    X509_PURPOSE *ptmp;
199    /*
200     * This is set according to what we change: application can't set it
201     */
202    flags &= ~X509_PURPOSE_DYNAMIC;
203    /* This will always be set for application modified trust entries */
204    flags |= X509_PURPOSE_DYNAMIC_NAME;
205    /* Get existing entry if any */
206    idx = X509_PURPOSE_get_by_id(id);
207    /* Need a new entry */
208    if (idx == -1) {
209        if (!(ptmp = OPENSSL_malloc(sizeof(X509_PURPOSE)))) {
210            X509V3err(X509V3_F_X509_PURPOSE_ADD, ERR_R_MALLOC_FAILURE);
211            return 0;
212        }
213        ptmp->flags = X509_PURPOSE_DYNAMIC;
214    } else
215        ptmp = X509_PURPOSE_get0(idx);
216
217    /* OPENSSL_free existing name if dynamic */
218    if (ptmp->flags & X509_PURPOSE_DYNAMIC_NAME) {
219        OPENSSL_free(ptmp->name);
220        OPENSSL_free(ptmp->sname);
221    }
222    /* dup supplied name */
223    ptmp->name = BUF_strdup(name);
224    ptmp->sname = BUF_strdup(sname);
225    if (!ptmp->name || !ptmp->sname) {
226        X509V3err(X509V3_F_X509_PURPOSE_ADD, ERR_R_MALLOC_FAILURE);
227        return 0;
228    }
229    /* Keep the dynamic flag of existing entry */
230    ptmp->flags &= X509_PURPOSE_DYNAMIC;
231    /* Set all other flags */
232    ptmp->flags |= flags;
233
234    ptmp->purpose = id;
235    ptmp->trust = trust;
236    ptmp->check_purpose = ck;
237    ptmp->usr_data = arg;
238
239    /* If its a new entry manage the dynamic table */
240    if (idx == -1) {
241        if (!xptable && !(xptable = sk_X509_PURPOSE_new(xp_cmp))) {
242            X509V3err(X509V3_F_X509_PURPOSE_ADD, ERR_R_MALLOC_FAILURE);
243            return 0;
244        }
245        if (!sk_X509_PURPOSE_push(xptable, ptmp)) {
246            X509V3err(X509V3_F_X509_PURPOSE_ADD, ERR_R_MALLOC_FAILURE);
247            return 0;
248        }
249    }
250    return 1;
251}
252
253static void xptable_free(X509_PURPOSE *p)
254{
255    if (!p)
256        return;
257    if (p->flags & X509_PURPOSE_DYNAMIC) {
258        if (p->flags & X509_PURPOSE_DYNAMIC_NAME) {
259            OPENSSL_free(p->name);
260            OPENSSL_free(p->sname);
261        }
262        OPENSSL_free(p);
263    }
264}
265
266void X509_PURPOSE_cleanup(void)
267{
268    unsigned int i;
269    sk_X509_PURPOSE_pop_free(xptable, xptable_free);
270    for (i = 0; i < X509_PURPOSE_COUNT; i++)
271        xptable_free(xstandard + i);
272    xptable = NULL;
273}
274
275int X509_PURPOSE_get_id(X509_PURPOSE *xp)
276{
277    return xp->purpose;
278}
279
280char *X509_PURPOSE_get0_name(X509_PURPOSE *xp)
281{
282    return xp->name;
283}
284
285char *X509_PURPOSE_get0_sname(X509_PURPOSE *xp)
286{
287    return xp->sname;
288}
289
290int X509_PURPOSE_get_trust(X509_PURPOSE *xp)
291{
292    return xp->trust;
293}
294
295static int nid_cmp(int *a, int *b)
296{
297    return *a - *b;
298}
299
300int X509_supported_extension(X509_EXTENSION *ex)
301{
302    /*
303     * This table is a list of the NIDs of supported extensions: that is
304     * those which are used by the verify process. If an extension is
305     * critical and doesn't appear in this list then the verify process will
306     * normally reject the certificate. The list must be kept in numerical
307     * order because it will be searched using bsearch.
308     */
309
310    static int supported_nids[] = {
311        NID_netscape_cert_type, /* 71 */
312        NID_key_usage,          /* 83 */
313        NID_subject_alt_name,   /* 85 */
314        NID_basic_constraints,  /* 87 */
315        NID_certificate_policies, /* 89 */
316        NID_ext_key_usage,      /* 126 */
317#ifndef OPENSSL_NO_RFC3779
318        NID_sbgp_ipAddrBlock,   /* 290 */
319        NID_sbgp_autonomousSysNum, /* 291 */
320#endif
321        NID_policy_constraints, /* 401 */
322        NID_proxyCertInfo,      /* 661 */
323        NID_inhibit_any_policy  /* 748 */
324    };
325
326    int ex_nid;
327
328    ex_nid = OBJ_obj2nid(X509_EXTENSION_get_object(ex));
329
330    if (ex_nid == NID_undef)
331        return 0;
332
333    if (OBJ_bsearch((char *)&ex_nid, (char *)supported_nids,
334                    sizeof(supported_nids) / sizeof(int), sizeof(int),
335                    (int (*)(const void *, const void *))nid_cmp))
336        return 1;
337    return 0;
338}
339
340static void x509v3_cache_extensions(X509 *x)
341{
342    BASIC_CONSTRAINTS *bs;
343    PROXY_CERT_INFO_EXTENSION *pci;
344    ASN1_BIT_STRING *usage;
345    ASN1_BIT_STRING *ns;
346    EXTENDED_KEY_USAGE *extusage;
347    X509_EXTENSION *ex;
348
349    int i;
350    if (x->ex_flags & EXFLAG_SET)
351        return;
352#ifndef OPENSSL_NO_SHA
353    X509_digest(x, EVP_sha1(), x->sha1_hash, NULL);
354#endif
355    /* Does subject name match issuer ? */
356    if (!X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x)))
357        x->ex_flags |= EXFLAG_SI;
358    /* V1 should mean no extensions ... */
359    if (!X509_get_version(x))
360        x->ex_flags |= EXFLAG_V1;
361    /* Handle basic constraints */
362    if ((bs = X509_get_ext_d2i(x, NID_basic_constraints, NULL, NULL))) {
363        if (bs->ca)
364            x->ex_flags |= EXFLAG_CA;
365        if (bs->pathlen) {
366            if ((bs->pathlen->type == V_ASN1_NEG_INTEGER)
367                || !bs->ca) {
368                x->ex_flags |= EXFLAG_INVALID;
369                x->ex_pathlen = 0;
370            } else
371                x->ex_pathlen = ASN1_INTEGER_get(bs->pathlen);
372        } else
373            x->ex_pathlen = -1;
374        BASIC_CONSTRAINTS_free(bs);
375        x->ex_flags |= EXFLAG_BCONS;
376    }
377    /* Handle proxy certificates */
378    if ((pci = X509_get_ext_d2i(x, NID_proxyCertInfo, NULL, NULL))) {
379        if (x->ex_flags & EXFLAG_CA
380            || X509_get_ext_by_NID(x, NID_subject_alt_name, 0) >= 0
381            || X509_get_ext_by_NID(x, NID_issuer_alt_name, 0) >= 0) {
382            x->ex_flags |= EXFLAG_INVALID;
383        }
384        if (pci->pcPathLengthConstraint) {
385            x->ex_pcpathlen = ASN1_INTEGER_get(pci->pcPathLengthConstraint);
386        } else
387            x->ex_pcpathlen = -1;
388        PROXY_CERT_INFO_EXTENSION_free(pci);
389        x->ex_flags |= EXFLAG_PROXY;
390    }
391    /* Handle key usage */
392    if ((usage = X509_get_ext_d2i(x, NID_key_usage, NULL, NULL))) {
393        if (usage->length > 0) {
394            x->ex_kusage = usage->data[0];
395            if (usage->length > 1)
396                x->ex_kusage |= usage->data[1] << 8;
397        } else
398            x->ex_kusage = 0;
399        x->ex_flags |= EXFLAG_KUSAGE;
400        ASN1_BIT_STRING_free(usage);
401    }
402    x->ex_xkusage = 0;
403    if ((extusage = X509_get_ext_d2i(x, NID_ext_key_usage, NULL, NULL))) {
404        x->ex_flags |= EXFLAG_XKUSAGE;
405        for (i = 0; i < sk_ASN1_OBJECT_num(extusage); i++) {
406            switch (OBJ_obj2nid(sk_ASN1_OBJECT_value(extusage, i))) {
407            case NID_server_auth:
408                x->ex_xkusage |= XKU_SSL_SERVER;
409                break;
410
411            case NID_client_auth:
412                x->ex_xkusage |= XKU_SSL_CLIENT;
413                break;
414
415            case NID_email_protect:
416                x->ex_xkusage |= XKU_SMIME;
417                break;
418
419            case NID_code_sign:
420                x->ex_xkusage |= XKU_CODE_SIGN;
421                break;
422
423            case NID_ms_sgc:
424            case NID_ns_sgc:
425                x->ex_xkusage |= XKU_SGC;
426                break;
427
428            case NID_OCSP_sign:
429                x->ex_xkusage |= XKU_OCSP_SIGN;
430                break;
431
432            case NID_time_stamp:
433                x->ex_xkusage |= XKU_TIMESTAMP;
434                break;
435
436            case NID_dvcs:
437                x->ex_xkusage |= XKU_DVCS;
438                break;
439            }
440        }
441        sk_ASN1_OBJECT_pop_free(extusage, ASN1_OBJECT_free);
442    }
443
444    if ((ns = X509_get_ext_d2i(x, NID_netscape_cert_type, NULL, NULL))) {
445        if (ns->length > 0)
446            x->ex_nscert = ns->data[0];
447        else
448            x->ex_nscert = 0;
449        x->ex_flags |= EXFLAG_NSCERT;
450        ASN1_BIT_STRING_free(ns);
451    }
452    x->skid = X509_get_ext_d2i(x, NID_subject_key_identifier, NULL, NULL);
453    x->akid = X509_get_ext_d2i(x, NID_authority_key_identifier, NULL, NULL);
454#ifndef OPENSSL_NO_RFC3779
455    x->rfc3779_addr = X509_get_ext_d2i(x, NID_sbgp_ipAddrBlock, NULL, NULL);
456    x->rfc3779_asid = X509_get_ext_d2i(x, NID_sbgp_autonomousSysNum,
457                                       NULL, NULL);
458#endif
459    for (i = 0; i < X509_get_ext_count(x); i++) {
460        ex = X509_get_ext(x, i);
461        if (!X509_EXTENSION_get_critical(ex))
462            continue;
463        if (!X509_supported_extension(ex)) {
464            x->ex_flags |= EXFLAG_CRITICAL;
465            break;
466        }
467    }
468    x->ex_flags |= EXFLAG_SET;
469}
470
471/*-
472 * CA checks common to all purposes
473 * return codes:
474 * 0 not a CA
475 * 1 is a CA
476 * 2 basicConstraints absent so "maybe" a CA
477 * 3 basicConstraints absent but self signed V1.
478 * 4 basicConstraints absent but keyUsage present and keyCertSign asserted.
479 */
480
481#define V1_ROOT (EXFLAG_V1|EXFLAG_SS)
482#define ku_reject(x, usage) \
483        (((x)->ex_flags & EXFLAG_KUSAGE) && !((x)->ex_kusage & (usage)))
484#define xku_reject(x, usage) \
485        (((x)->ex_flags & EXFLAG_XKUSAGE) && !((x)->ex_xkusage & (usage)))
486#define ns_reject(x, usage) \
487        (((x)->ex_flags & EXFLAG_NSCERT) && !((x)->ex_nscert & (usage)))
488
489static int check_ca(const X509 *x)
490{
491    /* keyUsage if present should allow cert signing */
492    if (ku_reject(x, KU_KEY_CERT_SIGN))
493        return 0;
494    if (x->ex_flags & EXFLAG_BCONS) {
495        if (x->ex_flags & EXFLAG_CA)
496            return 1;
497        /* If basicConstraints says not a CA then say so */
498        else
499            return 0;
500    } else {
501        /* we support V1 roots for...  uh, I don't really know why. */
502        if ((x->ex_flags & V1_ROOT) == V1_ROOT)
503            return 3;
504        /*
505         * If key usage present it must have certSign so tolerate it
506         */
507        else if (x->ex_flags & EXFLAG_KUSAGE)
508            return 4;
509        /* Older certificates could have Netscape-specific CA types */
510        else if (x->ex_flags & EXFLAG_NSCERT && x->ex_nscert & NS_ANY_CA)
511            return 5;
512        /* can this still be regarded a CA certificate?  I doubt it */
513        return 0;
514    }
515}
516
517int X509_check_ca(X509 *x)
518{
519    if (!(x->ex_flags & EXFLAG_SET)) {
520        CRYPTO_w_lock(CRYPTO_LOCK_X509);
521        x509v3_cache_extensions(x);
522        CRYPTO_w_unlock(CRYPTO_LOCK_X509);
523    }
524
525    return check_ca(x);
526}
527
528/* Check SSL CA: common checks for SSL client and server */
529static int check_ssl_ca(const X509 *x)
530{
531    int ca_ret;
532    ca_ret = check_ca(x);
533    if (!ca_ret)
534        return 0;
535    /* check nsCertType if present */
536    if (ca_ret != 5 || x->ex_nscert & NS_SSL_CA)
537        return ca_ret;
538    else
539        return 0;
540}
541
542static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x,
543                                    int ca)
544{
545    if (xku_reject(x, XKU_SSL_CLIENT))
546        return 0;
547    if (ca)
548        return check_ssl_ca(x);
549    /* We need to do digital signatures with it */
550    if (ku_reject(x, KU_DIGITAL_SIGNATURE))
551        return 0;
552    /* nsCertType if present should allow SSL client use */
553    if (ns_reject(x, NS_SSL_CLIENT))
554        return 0;
555    return 1;
556}
557
558static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x,
559                                    int ca)
560{
561    if (xku_reject(x, XKU_SSL_SERVER | XKU_SGC))
562        return 0;
563    if (ca)
564        return check_ssl_ca(x);
565
566    if (ns_reject(x, NS_SSL_SERVER))
567        return 0;
568    /* Now as for keyUsage: we'll at least need to sign OR encipher */
569    if (ku_reject(x, KU_DIGITAL_SIGNATURE | KU_KEY_ENCIPHERMENT))
570        return 0;
571
572    return 1;
573
574}
575
576static int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x,
577                                       int ca)
578{
579    int ret;
580    ret = check_purpose_ssl_server(xp, x, ca);
581    if (!ret || ca)
582        return ret;
583    /* We need to encipher or Netscape complains */
584    if (ku_reject(x, KU_KEY_ENCIPHERMENT))
585        return 0;
586    return ret;
587}
588
589/* common S/MIME checks */
590static int purpose_smime(const X509 *x, int ca)
591{
592    if (xku_reject(x, XKU_SMIME))
593        return 0;
594    if (ca) {
595        int ca_ret;
596        ca_ret = check_ca(x);
597        if (!ca_ret)
598            return 0;
599        /* check nsCertType if present */
600        if (ca_ret != 5 || x->ex_nscert & NS_SMIME_CA)
601            return ca_ret;
602        else
603            return 0;
604    }
605    if (x->ex_flags & EXFLAG_NSCERT) {
606        if (x->ex_nscert & NS_SMIME)
607            return 1;
608        /* Workaround for some buggy certificates */
609        if (x->ex_nscert & NS_SSL_CLIENT)
610            return 2;
611        return 0;
612    }
613    return 1;
614}
615
616static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x,
617                                    int ca)
618{
619    int ret;
620    ret = purpose_smime(x, ca);
621    if (!ret || ca)
622        return ret;
623    if (ku_reject(x, KU_DIGITAL_SIGNATURE | KU_NON_REPUDIATION))
624        return 0;
625    return ret;
626}
627
628static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x,
629                                       int ca)
630{
631    int ret;
632    ret = purpose_smime(x, ca);
633    if (!ret || ca)
634        return ret;
635    if (ku_reject(x, KU_KEY_ENCIPHERMENT))
636        return 0;
637    return ret;
638}
639
640static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x,
641                                  int ca)
642{
643    if (ca) {
644        int ca_ret;
645        if ((ca_ret = check_ca(x)) != 2)
646            return ca_ret;
647        else
648            return 0;
649    }
650    if (ku_reject(x, KU_CRL_SIGN))
651        return 0;
652    return 1;
653}
654
655/*
656 * OCSP helper: this is *not* a full OCSP check. It just checks that each CA
657 * is valid. Additional checks must be made on the chain.
658 */
659
660static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca)
661{
662    /*
663     * Must be a valid CA.  Should we really support the "I don't know" value
664     * (2)?
665     */
666    if (ca)
667        return check_ca(x);
668    /* leaf certificate is checked in OCSP_verify() */
669    return 1;
670}
671
672static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca)
673{
674    return 1;
675}
676
677/*-
678 * Various checks to see if one certificate issued the second.
679 * This can be used to prune a set of possible issuer certificates
680 * which have been looked up using some simple method such as by
681 * subject name.
682 * These are:
683 * 1. Check issuer_name(subject) == subject_name(issuer)
684 * 2. If akid(subject) exists check it matches issuer
685 * 3. If key_usage(issuer) exists check it supports certificate signing
686 * returns 0 for OK, positive for reason for mismatch, reasons match
687 * codes for X509_verify_cert()
688 */
689
690int X509_check_issued(X509 *issuer, X509 *subject)
691{
692    if (X509_NAME_cmp(X509_get_subject_name(issuer),
693                      X509_get_issuer_name(subject)))
694        return X509_V_ERR_SUBJECT_ISSUER_MISMATCH;
695    x509v3_cache_extensions(issuer);
696    x509v3_cache_extensions(subject);
697    if (subject->akid) {
698        /* Check key ids (if present) */
699        if (subject->akid->keyid && issuer->skid &&
700            ASN1_OCTET_STRING_cmp(subject->akid->keyid, issuer->skid))
701            return X509_V_ERR_AKID_SKID_MISMATCH;
702        /* Check serial number */
703        if (subject->akid->serial &&
704            ASN1_INTEGER_cmp(X509_get_serialNumber(issuer),
705                             subject->akid->serial))
706            return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH;
707        /* Check issuer name */
708        if (subject->akid->issuer) {
709            /*
710             * Ugh, for some peculiar reason AKID includes SEQUENCE OF
711             * GeneralName. So look for a DirName. There may be more than one
712             * but we only take any notice of the first.
713             */
714            GENERAL_NAMES *gens;
715            GENERAL_NAME *gen;
716            X509_NAME *nm = NULL;
717            int i;
718            gens = subject->akid->issuer;
719            for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
720                gen = sk_GENERAL_NAME_value(gens, i);
721                if (gen->type == GEN_DIRNAME) {
722                    nm = gen->d.dirn;
723                    break;
724                }
725            }
726            if (nm && X509_NAME_cmp(nm, X509_get_issuer_name(issuer)))
727                return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH;
728        }
729    }
730    if (subject->ex_flags & EXFLAG_PROXY) {
731        if (ku_reject(issuer, KU_DIGITAL_SIGNATURE))
732            return X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE;
733    } else if (ku_reject(issuer, KU_KEY_CERT_SIGN))
734        return X509_V_ERR_KEYUSAGE_NO_CERTSIGN;
735    return X509_V_OK;
736}
737