diff options
author | Niklas Hallqvist <niklas@cvs.openbsd.org> | 2000-10-07 07:00:35 +0000 |
---|---|---|
committer | Niklas Hallqvist <niklas@cvs.openbsd.org> | 2000-10-07 07:00:35 +0000 |
commit | 60046455c5367d063936733b0f78a78c2c0fcdc2 (patch) | |
tree | 2c3da6df15f2f99118e713dc3c9d509366e82429 | |
parent | dc768b3fb17c19383e55cdcea891752427321593 (diff) |
Merge with EOM 1.43
author: niklas
Multiple subject name matching, makes certificate interop with PGPnet at least
partly working. Added some error checking.
author: provos
style as pointed out by the code style pedant.
author: ho
Compile without USE_KEYNOTE/USE_POLICY.
-rw-r--r-- | sbin/isakmpd/x509.c | 248 |
1 files changed, 160 insertions, 88 deletions
diff --git a/sbin/isakmpd/x509.c b/sbin/isakmpd/x509.c index 38dfe318573..09ad1643e72 100644 --- a/sbin/isakmpd/x509.c +++ b/sbin/isakmpd/x509.c @@ -1,5 +1,5 @@ -/* $OpenBSD: x509.c,v 1.28 2000/06/08 20:51:21 niklas Exp $ */ -/* $EOM: x509.c,v 1.40 2000/05/21 04:24:54 angelos Exp $ */ +/* $OpenBSD: x509.c,v 1.29 2000/10/07 07:00:34 niklas Exp $ */ +/* $EOM: x509.c,v 1.43 2000/09/28 12:53:27 niklas Exp $ */ /* * Copyright (c) 1998, 1999 Niels Provos. All rights reserved. @@ -56,6 +56,7 @@ #include "sysdep.h" +#include "cert.h" #include "conf.h" #include "dyn.h" #include "exchange.h" @@ -165,7 +166,7 @@ x509_generate_kn (X509 *cert) { log_print ("x509_generate_kn: " "missing certificates, cannot construct X509 chain"); - free(ikey); + free (ikey); return 0; } @@ -220,8 +221,18 @@ x509_generate_kn (X509 *cert) } free (buf); - LC (X509_NAME_oneline, (issuer, isname, 256)); - LC (X509_NAME_oneline, (subject, subname, 256)); + if (!LC (X509_NAME_oneline, (issuer, isname, 256))) + { + log_print ("x509_generate_kn: X509_NAME_oneline (issuer, ...) failed"); + return 0; + } + + if (!LC (X509_NAME_oneline, (subject, subname, 256))) + { + log_print ("x509_generate_kn: X509_NAME_oneline (subject, ...) failed"); + return 0; + } + buf = malloc (strlen (fmt2) + strlen (isname) + strlen (subname)); if (!buf) @@ -338,7 +349,7 @@ x509_hash_init () free (certh); } - free(x509_tab); + free (x509_tab); } x509_tab = malloc ((bucket_mask + 1) * sizeof (struct x509_list)); @@ -356,21 +367,26 @@ X509 * x509_hash_find (u_int8_t *id, size_t len) { struct x509_hash *cert; - u_int8_t *cid; - size_t clen; + u_int8_t **cid; + size_t *clen; + int n, i, id_found; for (cert = LIST_FIRST (&x509_tab[x509_hash (id, len)]); cert; cert = LIST_NEXT (cert, link)) { - if (!x509_cert_get_subject (cert->cert, &cid, &clen)) + if (!x509_cert_get_subjects (cert->cert, &n, &cid, &clen)) continue; - if (clen != len || memcmp (id, cid, len) != 0) - { - free (cid); - continue; - } - free (cid); + id_found = 0; + for (i = 0; i < n; i++) + if (clen[i] == len && memcmp (id, cid[i], len) == 0) + { + id_found++; + break; + } + cert_free_subjects (n, cid, clen); + if (!id_found) + continue; LOG_DBG ((LOG_CRYPTO, 70, "x509_hash_find: return X509 %p", cert->cert)); @@ -385,20 +401,21 @@ int x509_hash_enter (X509 *cert) { u_int16_t bucket = 0; - u_int8_t *id; - u_int32_t len; + u_int8_t **id; + u_int32_t *len; struct x509_hash *certh; + int n, i; - if (!x509_cert_get_subject (cert, &id, &len)) + if (!x509_cert_get_subjects (cert, &n, &id, &len)) { - log_print ("x509_hash_enter: can not retrieve subjectAltName"); + log_print ("x509_hash_enter: can not retrieve subjects"); return 0; } certh = malloc (sizeof *certh); if (!certh) { - free (id); + cert_free_subjects (n, id, len); log_error ("x509_hash_enter: malloc (%d) failed", sizeof *certh); return 0; } @@ -406,12 +423,16 @@ x509_hash_enter (X509 *cert) certh->cert = cert; - bucket = x509_hash (id, len); - free (id); + for (i = 0; i < n; i++) + { + bucket = x509_hash (id[i], len[i]); + + LIST_INSERT_HEAD (&x509_tab[bucket], certh, link); + LOG_DBG ((LOG_CRYPTO, 70, "x509_hash_enter: cert %p added to bucket %d", + cert, bucket)); + } + cert_free_subjects (n, id, len); - LIST_INSERT_HEAD (&x509_tab[bucket], certh, link); - LOG_DBG ((LOG_CRYPTO, 70, "x509_hash_enter: cert %p added to bucket %d", - cert, bucket)); return 1; } @@ -530,7 +551,9 @@ int x509_cert_init (void) { char *dirname; +#if defined(USE_KEYNOTE) || defined(USE_POLICY) int i; +#endif x509_hash_init (); @@ -842,7 +865,7 @@ x509_check_subjectaltname (u_char *id, u_int id_len, X509 *scert) switch (idtype) { case IPSEC_ID_IPV4_ADDR: - if (type == X509v3_IPV4_ADDR) + if (type == X509v3_IP_ADDR) ret = 1; break; case IPSEC_ID_FQDN: @@ -969,88 +992,137 @@ x509_cert_subjectaltname (X509 *scert, u_int8_t **altname, u_int32_t *len) } int -x509_cert_get_subject (void *scert, u_int8_t **id, u_int32_t *id_len) +x509_cert_get_subjects (void *scert, int *cnt, u_int8_t ***id, + u_int32_t **id_len) { X509 *cert = scert; + X509_NAME *subject; int type; u_int8_t *altname; u_int32_t altlen; + char *buf = 0; + unsigned char *ubuf; + int i; + + *id = 0; + *id_len = 0; + + /* + * XXX I *think* the subjectAltName can be a collection, but for now + * I only return the subjectName and a single subjectAltName. + */ + *cnt = 2; + + *id = calloc(*cnt, sizeof **id); + if (!*id) + { + log_print ("x509_cert_get_subject: malloc (%d) failed", + *cnt * sizeof **id); + goto fail; + } + + *id_len = malloc(*cnt * sizeof **id_len); + if (!*id_len) + { + log_print ("x509_cert_get_subject: malloc (%d) failed", + *cnt * sizeof **id_len); + goto fail; + } + + /* Stash the subjectName into the first slot. */ + subject = LC (X509_get_subject_name, (cert)); + if (!subject) + goto fail; + + + (*id_len)[0] = + ISAKMP_ID_DATA_OFF + LC (i2d_X509_NAME, (subject, NULL)) - ISAKMP_GEN_SZ; + (*id)[0] = malloc ((*id_len)[0]); + if (!(*id)[0]) + { + log_print ("x509_cert_get_subject: malloc (%d) failed", (*id_len)[0]); + goto fail; + } + SET_ISAKMP_ID_TYPE ((*id)[0] - ISAKMP_GEN_SZ, IPSEC_ID_DER_ASN1_DN); + ubuf = (*id)[0] + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ; + LC (i2d_X509_NAME, (subject, &ubuf)); + /* Stash the subjectAltName into the second slot. */ type = x509_cert_subjectaltname (cert, &altname, &altlen); + if (!type) + goto fail; + + buf = malloc (altlen + ISAKMP_ID_DATA_OFF); + if (!buf) + { + log_print ("x509_cert_get_subject: malloc (%d) failed", + altlen + ISAKMP_ID_DATA_OFF); + goto fail; + } switch (type) { case X509v3_DNS_NAME: - case X509v3_RFC_NAME: - { - char *buf; - - buf = malloc (altlen + ISAKMP_ID_DATA_OFF); - if (!buf) - { - log_print ("x509_cert_get_subject: malloc (%d) failed", - altlen + ISAKMP_ID_DATA_OFF); - return 0; - } - - if (type == X509v3_DNS_NAME) - SET_ISAKMP_ID_TYPE (buf, IPSEC_ID_FQDN); - else - SET_ISAKMP_ID_TYPE (buf, IPSEC_ID_USER_FQDN); + SET_ISAKMP_ID_TYPE (buf, IPSEC_ID_FQDN); + break; - SET_IPSEC_ID_PROTO (buf + ISAKMP_ID_DOI_DATA_OFF, 0); - SET_IPSEC_ID_PORT (buf + ISAKMP_ID_DOI_DATA_OFF, 0); - memcpy (buf + ISAKMP_ID_DATA_OFF, altname, altlen); + case X509v3_RFC_NAME: + SET_ISAKMP_ID_TYPE (buf, IPSEC_ID_USER_FQDN); + break; - *id_len = ISAKMP_ID_DATA_OFF + altlen - ISAKMP_GEN_SZ; - *id = malloc (*id_len); - if (!*id) - { - log_print ("x509_cert_get_subject: malloc (%d) failed", *id_len); - free (buf); - return 0; - } - memcpy (*id, buf + ISAKMP_GEN_SZ, *id_len); - free (buf); - } + case X509v3_IP_ADDR: + /* + * XXX I dislike the numeric constants, but I don't know what we + * should use otherwise. + */ + switch (altlen) + { + case 4: + SET_ISAKMP_ID_TYPE (buf, IPSEC_ID_IPV4_ADDR); + break; + + case 16: + SET_ISAKMP_ID_TYPE (buf, IPSEC_ID_IPV6_ADDR); + break; + + default: + log_print ("x509_cert_get_subject: " + "invalid subjectAltName iPAdress length %d ", altlen); + goto fail; + } break; - - case X509v3_IPV4_ADDR: - { - char buf[ISAKMP_ID_DATA_OFF + 4]; - - /* XXX sizeof IPV4_ADDR, how any better? */ - if (altlen != 4) - { - log_print ("x509_cert_get_subject: length != IP4addr: %d", - altlen); - return 0; - } + } - SET_ISAKMP_ID_TYPE (buf, IPSEC_ID_IPV4_ADDR); - SET_IPSEC_ID_PROTO (buf + ISAKMP_ID_DOI_DATA_OFF, 0); - SET_IPSEC_ID_PORT (buf + ISAKMP_ID_DOI_DATA_OFF, 0); - memcpy (buf + ISAKMP_ID_DATA_OFF, altname, altlen); + SET_IPSEC_ID_PROTO (buf + ISAKMP_ID_DOI_DATA_OFF, 0); + SET_IPSEC_ID_PORT (buf + ISAKMP_ID_DOI_DATA_OFF, 0); + memcpy (buf + ISAKMP_ID_DATA_OFF, altname, altlen); - *id_len = ISAKMP_ID_DATA_OFF + 4 - ISAKMP_GEN_SZ; - *id = malloc (*id_len); - if (!*id) - { - log_print ("x509_cert_get_subject: malloc (%d) failed", *id_len); - return 0; - } - memcpy (*id, buf + ISAKMP_GEN_SZ, *id_len); - } - break; - default: - log_print ("x509_cert_get_subject: unsupported subjectAltName type: %d", - type); - return 0; + (*id_len)[1] = ISAKMP_ID_DATA_OFF + altlen - ISAKMP_GEN_SZ; + (*id)[1] = malloc ((*id_len)[1]); + if (!(*id)[1]) + { + log_print ("x509_cert_get_subject: malloc (%d) failed", (*id_len)[1]); + goto fail; } + memcpy ((*id)[1], buf + ISAKMP_GEN_SZ, (*id_len)[1]); + free (buf); + buf = 0; return 1; -} + fail: + for (i = 0; i < *cnt; i++) + if ((*id)[i]) + free ((*id)[i]); + if (*id) + free (*id); + if (*id_len) + free (*id_len); + if (buf) + free (buf); + return 0; +} + int x509_cert_get_key (void *scert, void *keyp) { |