]> CyberLeo.Net >> Repos - FreeBSD/releng/9.3.git/blob - crypto/openssl/crypto/x509v3/v3_purp.c
Fix multiple OpenSSL vulnerabilities.
[FreeBSD/releng/9.3.git] / crypto / openssl / crypto / x509v3 / v3_purp.c
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
65 static void x509v3_cache_extensions(X509 *x);
66
67 static int check_ssl_ca(const X509 *x);
68 static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x,
69                                     int ca);
70 static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x,
71                                     int ca);
72 static int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x,
73                                        int ca);
74 static int purpose_smime(const X509 *x, int ca);
75 static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x,
76                                     int ca);
77 static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x,
78                                        int ca);
79 static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x,
80                                   int ca);
81 static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca);
82 static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca);
83
84 static int xp_cmp(const X509_PURPOSE *const *a, const X509_PURPOSE *const *b);
85 static void xptable_free(X509_PURPOSE *p);
86
87 static 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
108 IMPLEMENT_STACK_OF(X509_PURPOSE)
109
110 static STACK_OF(X509_PURPOSE) *xptable = NULL;
111
112 static 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  */
122 int 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
140 int 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
150 int 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
157 X509_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
166 int 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
178 int 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
193 int 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
253 static 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
266 void 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
275 int X509_PURPOSE_get_id(X509_PURPOSE *xp)
276 {
277     return xp->purpose;
278 }
279
280 char *X509_PURPOSE_get0_name(X509_PURPOSE *xp)
281 {
282     return xp->name;
283 }
284
285 char *X509_PURPOSE_get0_sname(X509_PURPOSE *xp)
286 {
287     return xp->sname;
288 }
289
290 int X509_PURPOSE_get_trust(X509_PURPOSE *xp)
291 {
292     return xp->trust;
293 }
294
295 static int nid_cmp(int *a, int *b)
296 {
297     return *a - *b;
298 }
299
300 int 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
340 static 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
489 static 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
517 int 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 */
529 static 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
542 static 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
558 static 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
576 static 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 */
590 static 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
616 static 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
628 static 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
640 static 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
660 static 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
672 static 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
690 int 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 }