diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 2004-04-15 18:39:31 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 2004-04-15 18:39:31 +0000 |
commit | b1ac98abf9e700f03d5aa5f97c06dab605d6da06 (patch) | |
tree | c08a9624b4a539b85c5650bcf09528d13eb2d039 /sbin/isakmpd/x509.c | |
parent | aeca45bc7d867b71e9600c7108674fae5db8ff9c (diff) |
partial move to KNF. More to come. This has happened because there
are a raft of source code auditors who are willing to help improve this
code only if this is done, and hey, isakmpd does need our standard
auditing process. ok ho hshoexer
Diffstat (limited to 'sbin/isakmpd/x509.c')
-rw-r--r-- | sbin/isakmpd/x509.c | 2383 |
1 files changed, 1109 insertions, 1274 deletions
diff --git a/sbin/isakmpd/x509.c b/sbin/isakmpd/x509.c index be0f7a88bae..dda7dda0197 100644 --- a/sbin/isakmpd/x509.c +++ b/sbin/isakmpd/x509.c @@ -1,5 +1,5 @@ -/* $OpenBSD: x509.c,v 1.87 2004/04/07 22:45:49 ho Exp $ */ -/* $EOM: x509.c,v 1.54 2001/01/16 18:42:16 ho Exp $ */ +/* $OpenBSD: x509.c,v 1.88 2004/04/15 18:39:26 deraadt Exp $ */ +/* $EOM: x509.c,v 1.54 2001/01/16 18:42:16 ho Exp $ */ /* * Copyright (c) 1998, 1999 Niels Provos. All rights reserved. @@ -47,7 +47,7 @@ #ifdef USE_POLICY #include <regex.h> #include <keynote.h> -#endif /* USE_POLICY */ +#endif /* USE_POLICY */ #include "sysdep.h" @@ -65,10 +65,10 @@ #include "util.h" #include "x509.h" -static u_int16_t x509_hash (u_int8_t *, size_t); -static void x509_hash_init (void); -static X509 *x509_hash_find (u_int8_t *, size_t); -static int x509_hash_enter (X509 *); +static u_int16_t x509_hash(u_int8_t *, size_t); +static void x509_hash_init(void); +static X509 *x509_hash_find(u_int8_t *, size_t); +static int x509_hash_enter(X509 *); /* * X509_STOREs do not support subjectAltNames, so we have to build @@ -87,15 +87,16 @@ static X509_STORE *x509_cas = 0; #define INITIAL_BUCKET_BITS 6 struct x509_hash { - LIST_ENTRY (x509_hash) link; + LIST_ENTRY(x509_hash) link; - X509 *cert; + X509 *cert; }; -static LIST_HEAD (x509_list, x509_hash) *x509_tab = 0; +static +LIST_HEAD(x509_list, x509_hash) * x509_tab = 0; /* Works both as a maximum index and a mask. */ -static int bucket_mask; + static int bucket_mask; #ifdef USE_POLICY /* @@ -104,1128 +105,996 @@ static int bucket_mask; * XXX RSA-specific. */ int -x509_generate_kn (int id, X509 *cert) +x509_generate_kn(int id, X509 *cert) { - char *fmt = "Authorizer: \"rsa-hex:%s\"\nLicensees: \"rsa-hex:%s\"\n" - "Conditions: %s >= \"%s\" && %s <= \"%s\";\n"; - char *ikey, *skey, *buf, isname[256], subname[256]; - char *fmt2 = "Authorizer: \"DN:%s\"\nLicensees: \"DN:%s\"\n" - "Conditions: %s >= \"%s\" && %s <= \"%s\";\n"; - X509_NAME *issuer, *subject; - struct keynote_deckey dc; - X509_STORE_CTX csc; - X509_OBJECT obj; - X509 *icert; - RSA *key; - time_t tt; - char before[15], after[15]; - ASN1_TIME *tm; - char *timecomp, *timecomp2; - int i, buf_len; - - LOG_DBG ((LOG_POLICY, 90, + char *fmt = "Authorizer: \"rsa-hex:%s\"\nLicensees: \"rsa-hex:%s\"\n" + "Conditions: %s >= \"%s\" && %s <= \"%s\";\n"; + char *ikey, *skey, *buf, isname[256], subname[256]; + char *fmt2 = "Authorizer: \"DN:%s\"\nLicensees: \"DN:%s\"\n" + "Conditions: %s >= \"%s\" && %s <= \"%s\";\n"; + X509_NAME *issuer, *subject; + struct keynote_deckey dc; + X509_STORE_CTX csc; + X509_OBJECT obj; + X509 *icert; + RSA *key; + time_t tt; + char before[15], after[15], *timecomp, *timecomp2; + ASN1_TIME *tm; + int i, buf_len; + + LOG_DBG((LOG_POLICY, 90, "x509_generate_kn: generating KeyNote policy for certificate %p", cert)); - issuer = X509_get_issuer_name (cert); - subject = X509_get_subject_name (cert); - - /* Missing or self-signed, ignore cert but don't report failure. */ - if (!issuer || !subject || !X509_name_cmp (issuer, subject)) - return 1; - - if (!x509_cert_get_key (cert, &key)) - { - LOG_DBG ((LOG_POLICY, 30, - "x509_generate_kn: failed to get public key from cert")); - return 0; - } - - dc.dec_algorithm = KEYNOTE_ALGORITHM_RSA; - dc.dec_key = key; - ikey = kn_encode_key (&dc, INTERNAL_ENC_PKCS1, ENCODING_HEX, - KEYNOTE_PUBLIC_KEY); - if (keynote_errno == ERROR_MEMORY) - { - log_print ("x509_generate_kn: failed to get memory for public key"); - RSA_free (key); - LOG_DBG ((LOG_POLICY, 30, "x509_generate_kn: cannot get subject key")); - return 0; - } - if (!ikey) - { - RSA_free (key); - LOG_DBG ((LOG_POLICY, 30, "x509_generate_kn: cannot get subject key")); - return 0; - } - RSA_free (key); - - /* Now find issuer's certificate so we can get the public key. */ - X509_STORE_CTX_init (&csc, x509_cas, cert, NULL); - if (X509_STORE_get_by_subject (&csc, X509_LU_X509, issuer, &obj) != - X509_LU_X509) - { - X509_STORE_CTX_cleanup (&csc); - X509_STORE_CTX_init (&csc, x509_certs, cert, NULL); - if (X509_STORE_get_by_subject (&csc, X509_LU_X509, issuer, &obj) != - X509_LU_X509) - { - X509_STORE_CTX_cleanup (&csc); - LOG_DBG ((LOG_POLICY, 30, - "x509_generate_kn: no certificate found for issuer")); - return 0; + issuer = X509_get_issuer_name(cert); + subject = X509_get_subject_name(cert); + + /* Missing or self-signed, ignore cert but don't report failure. */ + if (!issuer || !subject || !X509_name_cmp(issuer, subject)) + return 1; + + if (!x509_cert_get_key(cert, &key)) { + LOG_DBG((LOG_POLICY, 30, + "x509_generate_kn: failed to get public key from cert")); + return 0; } - } - - X509_STORE_CTX_cleanup (&csc); - icert = obj.data.x509; - - if (icert == NULL) - { - LOG_DBG ((LOG_POLICY, 30, "x509_generate_kn: " - "missing certificates, cannot construct X509 chain")); - free (ikey); - return 0; - } - - if (!x509_cert_get_key (icert, &key)) - { - LOG_DBG ((LOG_POLICY, 30, - "x509_generate_kn: failed to get public key from cert")); - free (ikey); - return 0; - } - - X509_OBJECT_free_contents (&obj); - - dc.dec_algorithm = KEYNOTE_ALGORITHM_RSA; - dc.dec_key = key; - skey = kn_encode_key (&dc, INTERNAL_ENC_PKCS1, ENCODING_HEX, - KEYNOTE_PUBLIC_KEY); - if (keynote_errno == ERROR_MEMORY) - { - log_error ("x509_generate_kn: failed to get memory for public key"); - free (ikey); - RSA_free (key); - LOG_DBG ((LOG_POLICY, 30, "x509_generate_kn: cannot get issuer key")); - return 0; - } - - if (!skey) - { - free (ikey); - RSA_free (key); - LOG_DBG ((LOG_POLICY, 30, "x509_generate_kn: cannot get issuer key")); - return 0; - } - RSA_free (key); - - buf_len = strlen (fmt) + strlen (ikey) + strlen (skey) + 56; - buf = calloc (buf_len, sizeof (char)); - buf_len *= sizeof (char); - if (!buf) - { - log_error ("x509_generate_kn: " - "failed to allocate memory for KeyNote credential"); - free (ikey); - free (skey); - return 0; - } - - if (((tm = X509_get_notBefore (cert)) == NULL) || - (tm->type != V_ASN1_UTCTIME && tm->type != V_ASN1_GENERALIZEDTIME)) - { - tt = time (0); - strftime (before, 14, "%Y%m%d%H%M%S", localtime (&tt)); - timecomp = "LocalTimeOfDay"; - } - else - { - if (tm->data[tm->length - 1] == 'Z') - { - timecomp = "GMTTimeOfDay"; - i = tm->length - 2; + dc.dec_algorithm = KEYNOTE_ALGORITHM_RSA; + dc.dec_key = key; + ikey = kn_encode_key(&dc, INTERNAL_ENC_PKCS1, ENCODING_HEX, + KEYNOTE_PUBLIC_KEY); + if (keynote_errno == ERROR_MEMORY) { + log_print("x509_generate_kn: failed to get memory for public key"); + RSA_free(key); + LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: cannot get subject key")); + return 0; } - else - { - timecomp = "LocalTimeOfDay"; - i = tm->length - 1; + if (!ikey) { + RSA_free(key); + LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: cannot get subject key")); + return 0; } - - for (; i >= 0; i--) - { - if (tm->data[i] < '0' || tm->data[i] > '9') - { - LOG_DBG ((LOG_POLICY, 30, "x509_generate_kn: invalid data in " - "NotValidBefore time field")); - free (ikey); - free (skey); - free (buf); - return 0; - } + RSA_free(key); + + /* Now find issuer's certificate so we can get the public key. */ + X509_STORE_CTX_init(&csc, x509_cas, cert, NULL); + if (X509_STORE_get_by_subject(&csc, X509_LU_X509, issuer, &obj) != + X509_LU_X509) { + X509_STORE_CTX_cleanup(&csc); + X509_STORE_CTX_init(&csc, x509_certs, cert, NULL); + if (X509_STORE_get_by_subject(&csc, X509_LU_X509, issuer, &obj) != + X509_LU_X509) { + X509_STORE_CTX_cleanup(&csc); + LOG_DBG((LOG_POLICY, 30, + "x509_generate_kn: no certificate found for issuer")); + return 0; + } } - - if (tm->type == V_ASN1_UTCTIME) - { - if ((tm->length < 10) || (tm->length > 13)) - { - LOG_DBG ((LOG_POLICY, 30, "x509_generate_kn: invalid length " - "of NotValidBefore time field (%d)", tm->length)); - free (ikey); - free (skey); - free (buf); - return 0; - } - - /* Validity checks. */ - if ((tm->data[2] != '0' && tm->data[2] != '1') - || (tm->data[2] == '0' && tm->data[3] == '0') - || (tm->data[2] == '1' && tm->data[3] > '2') - || (tm->data[4] > '3') - || (tm->data[4] == '0' && tm->data[5] == '0') - || (tm->data[4] == '3' && tm->data[5] > '1') - || (tm->data[6] > '2') - || (tm->data[6] == '2' && tm->data[7] > '3') - || (tm->data[8] > '5')) - { - LOG_DBG ((LOG_POLICY, 30, "x509_generate_kn: invalid value in " - "NotValidBefore time field")); - free (ikey); - free (skey); - free (buf); - return 0; - } - - /* Stupid UTC tricks. */ - if (tm->data[0] < '5') - snprintf (before, sizeof before, "20%s", tm->data); - else - snprintf (before, sizeof before, "19%s", tm->data); + X509_STORE_CTX_cleanup(&csc); + icert = obj.data.x509; + + if (icert == NULL) { + LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: " + "missing certificates, cannot construct X509 chain")); + free(ikey); + return 0; } - else - { /* V_ASN1_GENERICTIME */ - if ((tm->length < 12) || (tm->length > 15)) - { - LOG_DBG ((LOG_POLICY, 30, "x509_generate_kn: invalid length of " - "NotValidBefore time field (%d)", tm->length)); - free (ikey); - free (skey); - free (buf); - return 0; - } - - /* Validity checks. */ - if ((tm->data[4] != '0' && tm->data[4] != '1') - || (tm->data[4] == '0' && tm->data[5] == '0') - || (tm->data[4] == '1' && tm->data[5] > '2') - || (tm->data[6] > '3') - || (tm->data[6] == '0' && tm->data[7] == '0') - || (tm->data[6] == '3' && tm->data[7] > '1') - || (tm->data[8] > '2') - || (tm->data[8] == '2' && tm->data[9] > '3') - || (tm->data[10] > '5')) - { - LOG_DBG ((LOG_POLICY, 30, "x509_generate_kn: invalid value in " - "NotValidBefore time field")); - free (ikey); - free (skey); - free (buf); - return 0; - } - - snprintf (before, sizeof before, "%s", tm->data); + if (!x509_cert_get_key(icert, &key)) { + LOG_DBG((LOG_POLICY, 30, + "x509_generate_kn: failed to get public key from cert")); + free(ikey); + return 0; } - - /* Fix missing seconds. */ - if (tm->length < 12) - { - before[12] = '0'; - before[13] = '0'; + X509_OBJECT_free_contents(&obj); + + dc.dec_algorithm = KEYNOTE_ALGORITHM_RSA; + dc.dec_key = key; + skey = kn_encode_key(&dc, INTERNAL_ENC_PKCS1, ENCODING_HEX, + KEYNOTE_PUBLIC_KEY); + if (keynote_errno == ERROR_MEMORY) { + log_error("x509_generate_kn: failed to get memory for public key"); + free(ikey); + RSA_free(key); + LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: cannot get issuer key")); + return 0; } - - /* This will overwrite trailing 'Z'. */ - before[14] = '\0'; - } - - tm = X509_get_notAfter (cert); - if (tm == NULL - && (tm->type != V_ASN1_UTCTIME && tm->type != V_ASN1_GENERALIZEDTIME)) - { - tt = time (0); - strftime (after, 14, "%Y%m%d%H%M%S", localtime (&tt)); - timecomp2 = "LocalTimeOfDay"; - } - else - { - if (tm->data[tm->length - 1] == 'Z') - { - timecomp2 = "GMTTimeOfDay"; - i = tm->length - 2; + if (!skey) { + free(ikey); + RSA_free(key); + LOG_DBG((LOG_POLICY, 30, "x509_generate_kn: cannot get issuer key")); + return 0; } - else - { - timecomp2 = "LocalTimeOfDay"; - i = tm->length - 1; + RSA_free(key); + + buf_len = strlen(fmt) + strlen(ikey) + strlen(skey) + 56; + buf = calloc(buf_len, sizeof(char)); + buf_len *= sizeof(char); + if (!buf) { + log_error("x509_generate_kn: " + "failed to allocate memory for KeyNote credential"); + free(ikey); + free(skey); + return 0; } - - for (; i >= 0; i--) - { - if (tm->data[i] < '0' || tm->data[i] > '9') - { - LOG_DBG ((LOG_POLICY, 30, "x509_generate_kn: invalid data in " - "NotValidAfter time field")); - free (ikey); - free (skey); - free (buf); - return 0; - } + if (((tm = X509_get_notBefore(cert)) == NULL) || + (tm->type != V_ASN1_UTCTIME && tm->type != V_ASN1_GENERALIZEDTIME)) { + tt = time(0); + strftime(before, 14, "%Y%m%d%H%M%S", localtime(&tt)); + timecomp = "LocalTimeOfDay"; + } else { + if (tm->data[tm->length - 1] == 'Z') { + timecomp = "GMTTimeOfDay"; + i = tm->length - 2; + } else { + timecomp = "LocalTimeOfDay"; + i = tm->length - 1; + } + + for (; i >= 0; i--) { + if (tm->data[i] < '0' || tm->data[i] > '9') { + LOG_DBG((LOG_POLICY, 30, + "x509_generate_kn: invalid data in " + "NotValidBefore time field")); + free(ikey); + free(skey); + free(buf); + return 0; + } + } + + if (tm->type == V_ASN1_UTCTIME) { + if ((tm->length < 10) || (tm->length > 13)) { + LOG_DBG((LOG_POLICY, 30, + "x509_generate_kn: invalid length " + "of NotValidBefore time field (%d)", tm->length)); + free(ikey); + free(skey); + free(buf); + return 0; + } + /* Validity checks. */ + if ((tm->data[2] != '0' && tm->data[2] != '1') || + (tm->data[2] == '0' && tm->data[3] == '0') || + (tm->data[2] == '1' && tm->data[3] > '2') || + (tm->data[4] > '3') || + (tm->data[4] == '0' && tm->data[5] == '0') || + (tm->data[4] == '3' && tm->data[5] > '1') || + (tm->data[6] > '2') || + (tm->data[6] == '2' && tm->data[7] > '3') || + (tm->data[8] > '5')) { + LOG_DBG((LOG_POLICY, 30, + "x509_generate_kn: invalid value in " + "NotValidBefore time field")); + free(ikey); + free(skey); + free(buf); + return 0; + } + /* Stupid UTC tricks. */ + if (tm->data[0] < '5') + snprintf(before, sizeof before, "20%s", tm->data); + else + snprintf(before, sizeof before, "19%s", tm->data); + } else { /* V_ASN1_GENERICTIME */ + if ((tm->length < 12) || (tm->length > 15)) { + LOG_DBG((LOG_POLICY, 30, + "x509_generate_kn: invalid length of " + "NotValidBefore time field (%d)", tm->length)); + free(ikey); + free(skey); + free(buf); + return 0; + } + /* Validity checks. */ + if ((tm->data[4] != '0' && tm->data[4] != '1') || + (tm->data[4] == '0' && tm->data[5] == '0') || + (tm->data[4] == '1' && tm->data[5] > '2') || + (tm->data[6] > '3') || + (tm->data[6] == '0' && tm->data[7] == '0') || + (tm->data[6] == '3' && tm->data[7] > '1') || + (tm->data[8] > '2') || + (tm->data[8] == '2' && tm->data[9] > '3') || + (tm->data[10] > '5')) { + LOG_DBG((LOG_POLICY, 30, + "x509_generate_kn: invalid value in " + "NotValidBefore time field")); + free(ikey); + free(skey); + free(buf); + return 0; + } + snprintf(before, sizeof before, "%s", tm->data); + } + + /* Fix missing seconds. */ + if (tm->length < 12) { + before[12] = '0'; + before[13] = '0'; + } + /* This will overwrite trailing 'Z'. */ + before[14] = '\0'; } - if (tm->type == V_ASN1_UTCTIME) - { - if ((tm->length < 10) || (tm->length > 13)) - { - LOG_DBG ((LOG_POLICY, 30, "x509_generate_kn: invalid length of " - "NotValidAfter time field (%d)", tm->length)); - free (ikey); - free (skey); - free (buf); - return 0; - } - - /* Validity checks. */ - if ((tm->data[2] != '0' && tm->data[2] != '1') - || (tm->data[2] == '0' && tm->data[3] == '0') - || (tm->data[2] == '1' && tm->data[3] > '2') - || (tm->data[4] > '3') - || (tm->data[4] == '0' && tm->data[5] == '0') - || (tm->data[4] == '3' && tm->data[5] > '1') - || (tm->data[6] > '2') - || (tm->data[6] == '2' && tm->data[7] > '3') - || (tm->data[8] > '5')) - { - LOG_DBG ((LOG_POLICY, 30, "x509_generate_kn: invalid value in " - "NotValidAfter time field")); - free (ikey); - free (skey); - free (buf); - return 0; - } - - /* Stupid UTC tricks. */ - if (tm->data[0] < '5') - snprintf (after, sizeof after, "20%s", tm->data); - else - snprintf (after, sizeof after, "19%s", tm->data); + tm = X509_get_notAfter(cert); + if (tm == NULL && + (tm->type != V_ASN1_UTCTIME && tm->type != V_ASN1_GENERALIZEDTIME)) { + tt = time(0); + strftime(after, 14, "%Y%m%d%H%M%S", localtime(&tt)); + timecomp2 = "LocalTimeOfDay"; + } else { + if (tm->data[tm->length - 1] == 'Z') { + timecomp2 = "GMTTimeOfDay"; + i = tm->length - 2; + } else { + timecomp2 = "LocalTimeOfDay"; + i = tm->length - 1; + } + + for (; i >= 0; i--) { + if (tm->data[i] < '0' || tm->data[i] > '9') { + LOG_DBG((LOG_POLICY, 30, + "x509_generate_kn: invalid data in " + "NotValidAfter time field")); + free(ikey); + free(skey); + free(buf); + return 0; + } + } + + if (tm->type == V_ASN1_UTCTIME) { + if ((tm->length < 10) || (tm->length > 13)) { + LOG_DBG((LOG_POLICY, 30, + "x509_generate_kn: invalid length of " + "NotValidAfter time field (%d)", tm->length)); + free(ikey); + free(skey); + free(buf); + return 0; + } + /* Validity checks. */ + if ((tm->data[2] != '0' && tm->data[2] != '1') || + (tm->data[2] == '0' && tm->data[3] == '0') || + (tm->data[2] == '1' && tm->data[3] > '2') || + (tm->data[4] > '3') || + (tm->data[4] == '0' && tm->data[5] == '0') || + (tm->data[4] == '3' && tm->data[5] > '1') || + (tm->data[6] > '2') || + (tm->data[6] == '2' && tm->data[7] > '3') || + (tm->data[8] > '5')) { + LOG_DBG((LOG_POLICY, 30, + "x509_generate_kn: invalid value in " + "NotValidAfter time field")); + free(ikey); + free(skey); + free(buf); + return 0; + } + /* Stupid UTC tricks. */ + if (tm->data[0] < '5') + snprintf(after, sizeof after, "20%s", tm->data); + else + snprintf(after, sizeof after, "19%s", tm->data); + } else { /* V_ASN1_GENERICTIME */ + if ((tm->length < 12) || (tm->length > 15)) { + LOG_DBG((LOG_POLICY, 30, + "x509_generate_kn: invalid length of " + "NotValidAfter time field (%d)", tm->length)); + free(ikey); + free(skey); + free(buf); + return 0; + } + /* Validity checks. */ + if ((tm->data[4] != '0' && tm->data[4] != '1') || + (tm->data[4] == '0' && tm->data[5] == '0') || + (tm->data[4] == '1' && tm->data[5] > '2') || + (tm->data[6] > '3') || + (tm->data[6] == '0' && tm->data[7] == '0') || + (tm->data[6] == '3' && tm->data[7] > '1') || + (tm->data[8] > '2') || + (tm->data[8] == '2' && tm->data[9] > '3') || + (tm->data[10] > '5')) { + LOG_DBG((LOG_POLICY, 30, + "x509_generate_kn: invalid value in " + "NotValidAfter time field")); + free(ikey); + free(skey); + free(buf); + return 0; + } + snprintf(after, sizeof after, "%s", tm->data); + } + + /* Fix missing seconds. */ + if (tm->length < 12) { + after[12] = '0'; + after[13] = '0'; + } + after[14] = '\0'; /* This will overwrite trailing 'Z' */ } - else - { /* V_ASN1_GENERICTIME */ - if ((tm->length < 12) || (tm->length > 15)) - { - LOG_DBG ((LOG_POLICY, 30, "x509_generate_kn: invalid length of " - "NotValidAfter time field (%d)", tm->length)); - free (ikey); - free (skey); - free (buf); - return 0; - } - - /* Validity checks. */ - if ((tm->data[4] != '0' && tm->data[4] != '1') - || (tm->data[4] == '0' && tm->data[5] == '0') - || (tm->data[4] == '1' && tm->data[5] > '2') - || (tm->data[6] > '3') - || (tm->data[6] == '0' && tm->data[7] == '0') - || (tm->data[6] == '3' && tm->data[7] > '1') - || (tm->data[8] > '2') - || (tm->data[8] == '2' && tm->data[9] > '3') - || (tm->data[10] > '5')) - { - LOG_DBG ((LOG_POLICY, 30, "x509_generate_kn: invalid value in " - "NotValidAfter time field")); - free (ikey); - free (skey); - free (buf); - return 0; - } - - snprintf (after, sizeof after, "%s", tm->data); - } - - /* Fix missing seconds. */ - if (tm->length < 12) - { - after[12] = '0'; - after[13] = '0'; + + snprintf(buf, buf_len, fmt, skey, ikey, timecomp, before, timecomp2, after); + free(ikey); + free(skey); + + if (kn_add_assertion(id, buf, strlen(buf), ASSERT_FLAG_LOCAL) == -1) { + LOG_DBG((LOG_POLICY, 30, + "x509_generate_kn: failed to add new KeyNote credential")); + free(buf); + return 0; } + /* We could print the assertion here, but log_print() truncates... */ + LOG_DBG((LOG_POLICY, 60, "x509_generate_kn: added credential")); - after[14] = '\0'; /* This will overwrite trailing 'Z' */ - } - - snprintf (buf, buf_len, fmt, skey, ikey, timecomp, before, timecomp2, after); - free (ikey); - free (skey); - - if (kn_add_assertion (id, buf, strlen (buf), ASSERT_FLAG_LOCAL) == -1) - { - LOG_DBG ((LOG_POLICY, 30, - "x509_generate_kn: failed to add new KeyNote credential")); - free (buf); - return 0; - } - - /* We could print the assertion here, but log_print() truncates... */ - LOG_DBG ((LOG_POLICY, 60, "x509_generate_kn: added credential")); - - free (buf); - - if (!X509_NAME_oneline (issuer, isname, 256)) - { - LOG_DBG ((LOG_POLICY, 50, - "x509_generate_kn: X509_NAME_oneline (issuer, ...) failed")); - return 0; - } - - if (!X509_NAME_oneline (subject, subname, 256)) - { - LOG_DBG ((LOG_POLICY, 50, - "x509_generate_kn: X509_NAME_oneline (subject, ...) failed")); - return 0; - } - - buf_len = strlen (fmt2) + strlen (isname) + strlen (subname) + 56; - buf = malloc (buf_len); - if (!buf) - { - log_error ("x509_generate_kn: malloc (%d) failed", buf_len); - return 0; - } - - snprintf (buf, buf_len, fmt2, isname, subname, timecomp, before, timecomp2, - after); + free(buf); - if (kn_add_assertion (id, buf, strlen (buf), ASSERT_FLAG_LOCAL) == -1) - { - LOG_DBG ((LOG_POLICY, 30, - "x509_generate_kn: failed to add new KeyNote credential")); - free (buf); - return 0; - } + if (!X509_NAME_oneline(issuer, isname, 256)) { + LOG_DBG((LOG_POLICY, 50, + "x509_generate_kn: X509_NAME_oneline (issuer, ...) failed")); + return 0; + } + if (!X509_NAME_oneline(subject, subname, 256)) { + LOG_DBG((LOG_POLICY, 50, + "x509_generate_kn: X509_NAME_oneline (subject, ...) failed")); + return 0; + } + buf_len = strlen(fmt2) + strlen(isname) + strlen(subname) + 56; + buf = malloc(buf_len); + if (!buf) { + log_error("x509_generate_kn: malloc (%d) failed", buf_len); + return 0; + } + snprintf(buf, buf_len, fmt2, isname, subname, timecomp, before, timecomp2, + after); - LOG_DBG ((LOG_POLICY, 80, "x509_generate_kn: added credential:\n%s", buf)); + if (kn_add_assertion(id, buf, strlen(buf), ASSERT_FLAG_LOCAL) == -1) { + LOG_DBG((LOG_POLICY, 30, + "x509_generate_kn: failed to add new KeyNote credential")); + free(buf); + return 0; + } + LOG_DBG((LOG_POLICY, 80, "x509_generate_kn: added credential:\n%s", buf)); - free (buf); - return 1; + free(buf); + return 1; } -#endif /* USE_POLICY */ +#endif /* USE_POLICY */ static u_int16_t -x509_hash (u_int8_t *id, size_t len) +x509_hash(u_int8_t *id, size_t len) { - size_t i; - u_int16_t bucket = 0; - - /* XXX We might resize if we are crossing a certain threshold. */ - for (i = 4; i < (len & ~1); i += 2) - { - /* Doing it this way avoids alignment problems. */ - bucket ^= (id[i] + 1) * (id[i + 1] + 257); - } - /* Hash in the last character of odd length IDs too. */ - if (i < len) - bucket ^= (id[i] + 1) * (id[i] + 257); - - bucket &= bucket_mask; - - return bucket; + u_int16_t bucket = 0; + size_t i; + + /* XXX We might resize if we are crossing a certain threshold. */ + for (i = 4; i < (len & ~1); i += 2) { + /* Doing it this way avoids alignment problems. */ + bucket ^= (id[i] + 1) * (id[i + 1] + 257); + } + /* Hash in the last character of odd length IDs too. */ + if (i < len) + bucket ^= (id[i] + 1) * (id[i] + 257); + + bucket &= bucket_mask; + return bucket; } static void -x509_hash_init (void) +x509_hash_init(void) { - struct x509_hash *certh; - int i; - - bucket_mask = (1 << INITIAL_BUCKET_BITS) - 1; - - /* If reinitializing, free existing entries. */ - if (x509_tab) - { - for (i = 0; i <= bucket_mask; i++) - for (certh = LIST_FIRST (&x509_tab[i]); certh; - certh = LIST_FIRST (&x509_tab[i])) - { - LIST_REMOVE (certh, link); - free (certh); - } - - free (x509_tab); - } - - x509_tab = malloc ((bucket_mask + 1) * sizeof (struct x509_list)); - if (!x509_tab) - log_fatal ("x509_hash_init: malloc (%lu) failed", - (bucket_mask + 1) * (unsigned long)sizeof (struct x509_list)); - for (i = 0; i <= bucket_mask; i++) - { - LIST_INIT (&x509_tab[i]); - } + struct x509_hash *certh; + int i; + + bucket_mask = (1 << INITIAL_BUCKET_BITS) - 1; + + /* If reinitializing, free existing entries. */ + if (x509_tab) { + for (i = 0; i <= bucket_mask; i++) + for (certh = LIST_FIRST(&x509_tab[i]); certh; + certh = LIST_FIRST(&x509_tab[i])) { + LIST_REMOVE(certh, link); + free(certh); + } + free(x509_tab); + } + x509_tab = malloc((bucket_mask + 1) * sizeof(struct x509_list)); + if (!x509_tab) + log_fatal("x509_hash_init: malloc (%lu) failed", + (bucket_mask + 1) * (unsigned long) sizeof(struct x509_list)); + for (i = 0; i <= bucket_mask; i++) { + LIST_INIT(&x509_tab[i]); + } } /* Lookup a certificate by an ID blob. */ static X509 * -x509_hash_find (u_int8_t *id, size_t len) +x509_hash_find(u_int8_t *id, size_t len) { - struct x509_hash *cert; - u_int8_t **cid; - u_int32_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_subjects (cert->cert, &n, &cid, &clen)) - continue; - - id_found = 0; - for (i = 0; i < n; i++) - { - LOG_DBG_BUF ((LOG_CRYPTO, 70, "cert_cmp", id, len)); - LOG_DBG_BUF ((LOG_CRYPTO, 70, "cert_cmp", cid[i], clen[i])); - /* XXX This identity predicate needs to be understood. */ - if (clen[i] == len && id[0] == cid[i][0] - && memcmp (id + 4, cid[i] + 4, len - 4) == 0) - { - id_found++; - break; - } + struct x509_hash *cert; + u_int8_t **cid; + u_int32_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_subjects(cert->cert, &n, &cid, &clen)) + continue; + + id_found = 0; + for (i = 0; i < n; i++) { + LOG_DBG_BUF((LOG_CRYPTO, 70, "cert_cmp", id, len)); + LOG_DBG_BUF((LOG_CRYPTO, 70, "cert_cmp", cid[i], clen[i])); + /* + * XXX This identity predicate needs to be + * understood. + */ + if (clen[i] == len && id[0] == cid[i][0] && + memcmp(id + 4, cid[i] + 4, len - 4) == 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)); + return cert->cert; } - cert_free_subjects (n, cid, clen); - if (!id_found) - continue; - LOG_DBG ((LOG_CRYPTO, 70, "x509_hash_find: return X509 %p", - cert->cert)); - return cert->cert; - } - - LOG_DBG ((LOG_CRYPTO, 70, "x509_hash_find: no certificate matched query")); - return 0; + LOG_DBG((LOG_CRYPTO, 70, "x509_hash_find: no certificate matched query")); + return 0; } static int -x509_hash_enter (X509 *cert) +x509_hash_enter(X509 *cert) { - u_int16_t bucket = 0; - u_int8_t **id; - u_int32_t *len; - struct x509_hash *certh; - int n, i; - - if (!x509_cert_get_subjects (cert, &n, &id, &len)) - { - log_print ("x509_hash_enter: cannot retrieve subjects"); - return 0; - } - - for (i = 0; i < n; i++) - { - certh = calloc (1, sizeof *certh); - if (!certh) - { - cert_free_subjects (n, id, len); - log_error ("x509_hash_enter: calloc (1, %lu) failed", - (unsigned long)sizeof *certh); - return 0; - } - - certh->cert = cert; - - 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); - - return 1; + u_int16_t bucket = 0; + u_int8_t **id; + u_int32_t *len; + struct x509_hash *certh; + int n, i; + + if (!x509_cert_get_subjects(cert, &n, &id, &len)) { + log_print("x509_hash_enter: cannot retrieve subjects"); + return 0; + } + for (i = 0; i < n; i++) { + certh = calloc(1, sizeof *certh); + if (!certh) { + cert_free_subjects(n, id, len); + log_error("x509_hash_enter: calloc (1, %lu) failed", + (unsigned long) sizeof *certh); + return 0; + } + certh->cert = cert; + + 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); + + return 1; } /* X509 Certificate Handling functions. */ int -x509_read_from_dir (X509_STORE *ctx, char *name, int hash) +x509_read_from_dir(X509_STORE *ctx, char *name, int hash) { - struct dirent *file; + struct dirent *file; #if defined (USE_PRIVSEP) - struct monitor_dirents *dir; - FILE *certfp; + struct monitor_dirents *dir; + FILE *certfp; #else - DIR *dir; - BIO *certh; + DIR *dir; + BIO *certh; #endif - X509 *cert; - char fullname[PATH_MAX]; - int off, size; + X509 *cert; + char fullname[PATH_MAX]; + int off, size; - if (strlen (name) >= sizeof fullname - 1) - { - log_print ("x509_read_from_dir: directory name too long"); - return 0; - } + if (strlen(name) >= sizeof fullname - 1) { + log_print("x509_read_from_dir: directory name too long"); + return 0; + } + LOG_DBG((LOG_CRYPTO, 40, "x509_read_from_dir: reading certs from %s", + name)); + + dir = monitor_opendir(name); + if (!dir) { + LOG_DBG((LOG_CRYPTO, 10, + "x509_read_from_dir: opendir (\"%s\") failed: " + "%s", name, strerror(errno))); + return 0; + } + strlcpy(fullname, name, sizeof fullname); + off = strlen(fullname); + size = sizeof fullname - off; - LOG_DBG ((LOG_CRYPTO, 40, "x509_read_from_dir: reading certs from %s", - name)); + while ((file = monitor_readdir(dir)) != NULL) { + strlcpy(fullname + off, file->d_name, size); - dir = monitor_opendir (name); - if (!dir) - { - LOG_DBG ((LOG_CRYPTO, 10, "x509_read_from_dir: opendir (\"%s\") failed: " - "%s", name, strerror (errno))); - return 0; - } - - strlcpy (fullname, name, sizeof fullname); - off = strlen (fullname); - size = sizeof fullname - off; - - while ((file = monitor_readdir (dir)) != NULL) - { - strlcpy (fullname + off, file->d_name, size); - - if (file->d_type != DT_UNKNOWN) - { - if (file->d_type != DT_REG && file->d_type != DT_LNK) - continue; - } - else - { - struct stat sb; - - if (monitor_stat (fullname, &sb) == -1 || !(sb.st_mode & S_IFREG)) - continue; - } - - LOG_DBG ((LOG_CRYPTO, 60, "x509_read_from_dir: reading certificate %s", - file->d_name)); + if (file->d_type != DT_UNKNOWN) { + if (file->d_type != DT_REG && file->d_type != DT_LNK) + continue; + } else { + struct stat sb; -#if defined (USE_PRIVSEP) - certfp = monitor_fopen (fullname, "r"); - if (!certfp) - { - log_error ("x509_read_from_dir: monitor_fopen (\"%s\", \"r\") failed", - fullname); - continue; - } + if (monitor_stat(fullname, &sb) == -1 || + !(sb.st_mode & S_IFREG)) + continue; + } + + LOG_DBG((LOG_CRYPTO, 60, "x509_read_from_dir: reading certificate %s", + file->d_name)); +#if defined (USE_PRIVSEP) + certfp = monitor_fopen(fullname, "r"); + if (!certfp) { + log_error("x509_read_from_dir: monitor_fopen " + "(\"%s\", \"r\") failed", + fullname); + continue; + } #if SSLEAY_VERSION_NUMBER >= 0x00904100L - cert = PEM_read_X509 (certfp, NULL, NULL, NULL); + cert = PEM_read_X509(certfp, NULL, NULL, NULL); #else - cert = PEM_read_X509 (certfp, NULL, NULL); + cert = PEM_read_X509(certfp, NULL, NULL); #endif - fclose (certfp); + fclose(certfp); #else - certh = BIO_new (BIO_s_file ()); - if (!certh) - { - log_error ("x509_read_from_dir: BIO_new (BIO_s_file ()) failed"); - continue; - } - - if (BIO_read_filename (certh, fullname) == -1) - { - BIO_free (certh); - log_error ("x509_read_from_dir: " - "BIO_read_filename (certh, \"%s\") failed", - fullname); - continue; - } - + certh = BIO_new(BIO_s_file()); + if (!certh) { + log_error("x509_read_from_dir: BIO_new (BIO_s_file ()) failed"); + continue; + } + if (BIO_read_filename(certh, fullname) == -1) { + BIO_free(certh); + log_error("x509_read_from_dir: " + "BIO_read_filename (certh, \"%s\") failed", + fullname); + continue; + } #if SSLEAY_VERSION_NUMBER >= 0x00904100L - cert = PEM_read_bio_X509 (certh, NULL, NULL, NULL); + cert = PEM_read_bio_X509(certh, NULL, NULL, NULL); #else - cert = PEM_read_bio_X509 (certh, NULL, NULL); + cert = PEM_read_bio_X509(certh, NULL, NULL); #endif - BIO_free (certh); -#endif /* USE_PRIVSEP */ - if (cert == NULL) - { - log_print ("x509_read_from_dir: PEM_read_bio_X509 failed for %s", - file->d_name); - continue; - } - - if (!X509_STORE_add_cert (ctx, cert)) - { - /* - * This is actually expected if we have several certificates only - * differing in subjectAltName, which is not an something that is - * strange. Consider multi-homed machines. - */ - LOG_DBG ((LOG_CRYPTO, 50, - "x509_read_from_dir: X509_STORE_add_cert failed for %s", - file->d_name)); + BIO_free(certh); +#endif /* USE_PRIVSEP */ + if (cert == NULL) { + log_print("x509_read_from_dir: PEM_read_bio_X509 failed for %s", + file->d_name); + continue; + } + if (!X509_STORE_add_cert(ctx, cert)) { + /* + * This is actually expected if we have several + * certificates only differing in subjectAltName, which + * is not an something that is strange. Consider + * multi-homed machines. + */ + LOG_DBG((LOG_CRYPTO, 50, + "x509_read_from_dir: X509_STORE_add_cert failed for %s", + file->d_name)); + } + if (hash) + if (!x509_hash_enter(cert)) + log_print("x509_read_from_dir: x509_hash_enter " + "(%s) failed", + file->d_name); } - if (hash) - if (!x509_hash_enter (cert)) - log_print ("x509_read_from_dir: x509_hash_enter (%s) failed", - file->d_name); - } - - monitor_closedir (dir); + monitor_closedir(dir); - return 1; + return 1; } /* XXX share code with x509_read_from_dir() ? */ int -x509_read_crls_from_dir (X509_STORE *ctx, char *name) +x509_read_crls_from_dir(X509_STORE *ctx, char *name) { #if OPENSSL_VERSION_NUMBER >= 0x00907000L - struct dirent *file; + struct dirent *file; #if defined (USE_PRIVSEP) - struct monitor_dirents *dir; - FILE *crlfp; + struct monitor_dirents *dir; + FILE *crlfp; #else - DIR *dir; - BIO *crlh; + DIR *dir; + BIO *crlh; #endif - X509_CRL *crl; - char fullname[PATH_MAX]; - int off, size; + X509_CRL *crl; + char fullname[PATH_MAX]; + int off, size; - if (strlen (name) >= sizeof fullname - 1) - { - log_print ("x509_read_crls_from_dir: directory name too long"); - return 0; - } - - LOG_DBG ((LOG_CRYPTO, 40, "x509_read_crls_from_dir: reading CRLs from %s", + if (strlen(name) >= sizeof fullname - 1) { + log_print("x509_read_crls_from_dir: directory name too long"); + return 0; + } + LOG_DBG((LOG_CRYPTO, 40, "x509_read_crls_from_dir: reading CRLs from %s", name)); - dir = monitor_opendir (name); - if (!dir) - { - LOG_DBG ((LOG_CRYPTO, 10, "x509_read_crls_from_dir: opendir (\"%s\") " - "failed: %s", name, strerror (errno))); - return 0; - } - - strlcpy (fullname, name, sizeof fullname); - off = strlen (fullname); - size = sizeof fullname - off; - - while ((file = monitor_readdir (dir)) != NULL) - { - strlcpy (fullname + off, file->d_name, size); - - if (file->d_type != DT_UNKNOWN) - { - if (file->d_type != DT_REG && file->d_type != DT_LNK) - continue; - } - else - { - struct stat sb; - - if (monitor_stat (fullname, &sb) == -1 || !(sb.st_mode & S_IFREG)) - continue; - } - - LOG_DBG ((LOG_CRYPTO, 60, "x509_read_crls_from_dir: reading CRL %s", - file->d_name)); - -#if defined (USE_PRIVSEP) - crlfp = monitor_fopen (fullname, "r"); - if (!crlfp) - { - log_error ("x509_read_crls_from_dir: monitor_fopen (\"%s\", \"r\") " - "failed", fullname); - continue; + dir = monitor_opendir(name); + if (!dir) { + LOG_DBG((LOG_CRYPTO, 10, "x509_read_crls_from_dir: opendir (\"%s\") " + "failed: %s", name, strerror(errno))); + return 0; } + strlcpy(fullname, name, sizeof fullname); + off = strlen(fullname); + size = sizeof fullname - off; - crl = PEM_read_X509_CRL (crlfp, NULL, NULL, NULL); - fclose (crlfp); -#else - crlh = BIO_new (BIO_s_file ()); - if (!crlh) - { - log_error ("x509_read_crls_from_dir: " - "BIO_new (BIO_s_file ()) failed"); - continue; - } + while ((file = monitor_readdir(dir)) != NULL) { + strlcpy(fullname + off, file->d_name, size); - if (BIO_read_filename (crlh, fullname) == -1) - { - BIO_free (crlh); - log_error ("x509_read_crls_from_dir: " - "BIO_read_filename (crlh, \"%s\") failed", fullname); - continue; - } + if (file->d_type != DT_UNKNOWN) { + if (file->d_type != DT_REG && file->d_type != DT_LNK) + continue; + } else { + struct stat sb; - crl = PEM_read_bio_X509_CRL (crlh, NULL, NULL, NULL); + if (monitor_stat(fullname, &sb) == -1 || !(sb.st_mode & S_IFREG)) + continue; + } - BIO_free (crlh); -#endif /* USE_PRIVSEP */ - if (crl == NULL) - { - log_print ("x509_read_crls_from_dir: " - "PEM_read_bio_X509_CRL failed for %s", file->d_name); - continue; - } + LOG_DBG((LOG_CRYPTO, 60, "x509_read_crls_from_dir: reading CRL %s", + file->d_name)); - if (!X509_STORE_add_crl (ctx, crl)) - { - LOG_DBG ((LOG_CRYPTO, 50, "x509_read_crls_from_dir: " - "X509_STORE_add_crl failed for %s", file->d_name)); - continue; +#if defined (USE_PRIVSEP) + crlfp = monitor_fopen(fullname, "r"); + if (!crlfp) { + log_error("x509_read_crls_from_dir: monitor_fopen " + "(\"%s\", \"r\") failed", fullname); + continue; + } + crl = PEM_read_X509_CRL(crlfp, NULL, NULL, NULL); + fclose(crlfp); +#else + crlh = BIO_new(BIO_s_file()); + if (!crlh) { + log_error("x509_read_crls_from_dir: " + "BIO_new (BIO_s_file ()) failed"); + continue; + } + if (BIO_read_filename(crlh, fullname) == -1) { + BIO_free(crlh); + log_error("x509_read_crls_from_dir: " + "BIO_read_filename (crlh, \"%s\") failed", fullname); + continue; + } + crl = PEM_read_bio_X509_CRL(crlh, NULL, NULL, NULL); + + BIO_free(crlh); +#endif /* USE_PRIVSEP */ + if (crl == NULL) { + log_print("x509_read_crls_from_dir: " + "PEM_read_bio_X509_CRL failed for %s", file->d_name); + continue; + } + if (!X509_STORE_add_crl(ctx, crl)) { + LOG_DBG((LOG_CRYPTO, 50, "x509_read_crls_from_dir: " + "X509_STORE_add_crl failed for %s", file->d_name)); + continue; + } + /* + * XXX This is to make x509_cert_validate set this (and another) flag + * XXX when validating certificates. Currently, OpenSSL defaults to + * XXX reject an otherwise valid certificate (chain) if these flags + * XXX are set but there are no CRLs to check. The current workaround + * XXX is to only set the flags if we actually loaded some CRL data. + */ + X509_STORE_set_flags(ctx, X509_V_FLAG_CRL_CHECK); } - /* - * XXX This is to make x509_cert_validate set this (and another) flag - * XXX when validating certificates. Currently, OpenSSL defaults to - * XXX reject an otherwise valid certificate (chain) if these flags - * XXX are set but there are no CRLs to check. The current workaround - * XXX is to only set the flags if we actually loaded some CRL data. - */ - X509_STORE_set_flags (ctx, X509_V_FLAG_CRL_CHECK); - } - - monitor_closedir (dir); -#endif /* OPENSSL_VERSION_NUMBER >= 0x00907000L */ + monitor_closedir(dir); +#endif /* OPENSSL_VERSION_NUMBER >= 0x00907000L */ - return 1; + return 1; } /* Initialize our databases and load our own certificates. */ int -x509_cert_init (void) +x509_cert_init(void) { - char *dirname; - - x509_hash_init (); - - /* Process CA certificates we will trust. */ - dirname = conf_get_str ("X509-certificates", "CA-directory"); - if (!dirname) - { - log_print ("x509_cert_init: no CA-directory"); - return 0; - } - - /* Free if already initialized. */ - if (x509_cas) - X509_STORE_free (x509_cas); - - x509_cas = X509_STORE_new (); - if (!x509_cas) - { - log_print ("x509_cert_init: creating new X509_STORE failed"); - return 0; - } - - if (!x509_read_from_dir (x509_cas, dirname, 0)) - { - log_print ("x509_cert_init: x509_read_from_dir failed"); - return 0; - } - - /* Process client certificates we will accept. */ - dirname = conf_get_str ("X509-certificates", "Cert-directory"); - if (!dirname) - { - log_print ("x509_cert_init: no Cert-directory"); - return 0; - } - - /* Free if already initialized. */ - if (x509_certs) - X509_STORE_free (x509_certs); - - x509_certs = X509_STORE_new (); - if (!x509_certs) - { - log_print ("x509_cert_init: creating new X509_STORE failed"); - return 0; - } - - if (!x509_read_from_dir (x509_certs, dirname, 1)) - { - log_print ("x509_cert_init: x509_read_from_dir failed"); - return 0; - } - - return 1; + char *dirname; + + x509_hash_init(); + + /* Process CA certificates we will trust. */ + dirname = conf_get_str("X509-certificates", "CA-directory"); + if (!dirname) { + log_print("x509_cert_init: no CA-directory"); + return 0; + } + /* Free if already initialized. */ + if (x509_cas) + X509_STORE_free(x509_cas); + + x509_cas = X509_STORE_new(); + if (!x509_cas) { + log_print("x509_cert_init: creating new X509_STORE failed"); + return 0; + } + if (!x509_read_from_dir(x509_cas, dirname, 0)) { + log_print("x509_cert_init: x509_read_from_dir failed"); + return 0; + } + /* Process client certificates we will accept. */ + dirname = conf_get_str("X509-certificates", "Cert-directory"); + if (!dirname) { + log_print("x509_cert_init: no Cert-directory"); + return 0; + } + /* Free if already initialized. */ + if (x509_certs) + X509_STORE_free(x509_certs); + + x509_certs = X509_STORE_new(); + if (!x509_certs) { + log_print("x509_cert_init: creating new X509_STORE failed"); + return 0; + } + if (!x509_read_from_dir(x509_certs, dirname, 1)) { + log_print("x509_cert_init: x509_read_from_dir failed"); + return 0; + } + return 1; } int -x509_crl_init (void) +x509_crl_init(void) { - /* - * XXX I'm not sure if the method to use CRLs in certificate validation - * is valid for OpenSSL versions prior to 0.9.7. For now, simply do not - * support it. - */ + /* + * XXX I'm not sure if the method to use CRLs in certificate validation + * is valid for OpenSSL versions prior to 0.9.7. For now, simply do not + * support it. + */ #if OPENSSL_VERSION_NUMBER >= 0x00907000L - char *dirname; - dirname = conf_get_str ("X509-certificates", "CRL-directory"); - if (!dirname) - { - log_print ("x509_crl_init: no CRL-directory"); - return 0; - } - - if (!x509_read_crls_from_dir (x509_cas, dirname)) - { - LOG_DBG ((LOG_MISC, 10, "x509_crl_init: x509_read_crls_from_dir failed")); - return 0; - } + char *dirname; + dirname = conf_get_str("X509-certificates", "CRL-directory"); + if (!dirname) { + log_print("x509_crl_init: no CRL-directory"); + return 0; + } + if (!x509_read_crls_from_dir(x509_cas, dirname)) { + LOG_DBG((LOG_MISC, 10, + "x509_crl_init: x509_read_crls_from_dir failed")); + return 0; + } #else - LOG_DBG ((LOG_CRYPTO, 10, "x509_crl_init: CRL support only " + LOG_DBG((LOG_CRYPTO, 10, "x509_crl_init: CRL support only " "with OpenSSL v0.9.7 or later")); #endif - return 1; + return 1; } void * -x509_cert_get (u_int8_t *asn, u_int32_t len) +x509_cert_get(u_int8_t *asn, u_int32_t len) { - return x509_from_asn (asn, len); + return x509_from_asn(asn, len); } int -x509_cert_validate (void *scert) +x509_cert_validate(void *scert) { - X509_STORE_CTX csc; - X509_NAME *issuer, *subject; - X509 *cert = (X509 *)scert; - EVP_PKEY *key; - int res, err; - - /* - * Validate the peer certificate by checking with the CA certificates we - * trust. - */ - X509_STORE_CTX_init (&csc, x509_cas, cert, NULL); + X509_STORE_CTX csc; + X509_NAME *issuer, *subject; + X509 *cert = (X509 *) scert; + EVP_PKEY *key; + int res, err; + + /* + * Validate the peer certificate by checking with the CA certificates we + * trust. + */ + X509_STORE_CTX_init(&csc, x509_cas, cert, NULL); #if OPENSSL_VERSION_NUMBER >= 0x00907000L - /* XXX See comment in x509_read_crls_from_dir. */ - if (x509_cas->flags & X509_V_FLAG_CRL_CHECK) - { - X509_STORE_CTX_set_flags (&csc, X509_V_FLAG_CRL_CHECK); - X509_STORE_CTX_set_flags (&csc, X509_V_FLAG_CRL_CHECK_ALL); - } + /* XXX See comment in x509_read_crls_from_dir. */ + if (x509_cas->flags & X509_V_FLAG_CRL_CHECK) { + X509_STORE_CTX_set_flags(&csc, X509_V_FLAG_CRL_CHECK); + X509_STORE_CTX_set_flags(&csc, X509_V_FLAG_CRL_CHECK_ALL); + } #endif - res = X509_verify_cert (&csc); - err = csc.error; - X509_STORE_CTX_cleanup (&csc); - - /* Return if validation succeeded or self-signed certs are not accepted. */ - if (res) - return 1; - else if (!conf_get_str ("X509-certificates", "Accept-self-signed")) - { - if (err) - log_print ("x509_cert_validate: %.100s", - X509_verify_cert_error_string (err)); - return res; - } - - issuer = X509_get_issuer_name (cert); - subject = X509_get_subject_name (cert); - - if (!issuer || !subject || X509_name_cmp (issuer, subject)) - return 0; - - key = X509_get_pubkey (cert); - if (!key) - { - log_print ("x509_cert_validate: could not get public key from " - "self-signed cert"); - return 0; - } - - if (X509_verify (cert, key) == -1) - { - log_print ("x509_cert_validate: self-signed cert is bad"); - return 0; - } - - return 1; + res = X509_verify_cert(&csc); + err = csc.error; + X509_STORE_CTX_cleanup(&csc); + + /* + * Return if validation succeeded or self-signed certs are not + * accepted. + */ + if (res) + return 1; + else if (!conf_get_str("X509-certificates", "Accept-self-signed")) { + if (err) + log_print("x509_cert_validate: %.100s", + X509_verify_cert_error_string(err)); + return res; + } + issuer = X509_get_issuer_name(cert); + subject = X509_get_subject_name(cert); + + if (!issuer || !subject || X509_name_cmp(issuer, subject)) + return 0; + + key = X509_get_pubkey(cert); + if (!key) { + log_print("x509_cert_validate: could not get public key from " + "self-signed cert"); + return 0; + } + if (X509_verify(cert, key) == -1) { + log_print("x509_cert_validate: self-signed cert is bad"); + return 0; + } + return 1; } int -x509_cert_insert (int id, void *scert) +x509_cert_insert(int id, void *scert) { - X509 *cert; - int res; - - cert = X509_dup ((X509 *)scert); - if (!cert) - { - log_print ("x509_cert_insert: X509_dup failed"); - return 0; - } + X509 *cert; + int res; + cert = X509_dup((X509 *) scert); + if (!cert) { + log_print("x509_cert_insert: X509_dup failed"); + return 0; + } #ifdef USE_POLICY - if (x509_generate_kn (id, cert) == 0) - { - LOG_DBG ((LOG_POLICY, 50, - "x509_cert_insert: x509_generate_kn failed")); - X509_free (cert); - return 0; - } -#endif /* USE_POLICY */ - - res = x509_hash_enter (cert); - if (!res) - X509_free (cert); - - return res; + if (x509_generate_kn(id, cert) == 0) { + LOG_DBG((LOG_POLICY, 50, + "x509_cert_insert: x509_generate_kn failed")); + X509_free(cert); + return 0; + } +#endif /* USE_POLICY */ + + res = x509_hash_enter(cert); + if (!res) + X509_free(cert); + + return res; } static struct x509_hash * -x509_hash_lookup (X509 *cert) +x509_hash_lookup(X509 *cert) { - int i; - struct x509_hash *certh; - - for (i = 0; i <= bucket_mask; i++) - for (certh = LIST_FIRST (&x509_tab[i]); certh; - certh = LIST_NEXT (certh, link)) - if (certh->cert == cert) - return certh; - return 0; + int i; + struct x509_hash *certh; + + for (i = 0; i <= bucket_mask; i++) + for (certh = LIST_FIRST(&x509_tab[i]); certh; + certh = LIST_NEXT(certh, link)) + if (certh->cert == cert) + return certh; + return 0; } void -x509_cert_free (void *cert) +x509_cert_free(void *cert) { - struct x509_hash *certh = x509_hash_lookup ((X509 *)cert); + struct x509_hash *certh = x509_hash_lookup((X509 *) cert); - if (certh) - LIST_REMOVE (certh, link); - X509_free ((X509 *)cert); + if (certh) + LIST_REMOVE(certh, link); + X509_free((X509 *) cert); } /* Validate the BER Encoding of a RDNSequence in the CERT_REQ payload. */ int -x509_certreq_validate (u_int8_t *asn, u_int32_t len) +x509_certreq_validate(u_int8_t *asn, u_int32_t len) { - int res = 1; + int res = 1; #if 0 - struct norm_type name = SEQOF ("issuer", RDNSequence); - - if (!asn_template_clone (&name, 1) - || (asn = asn_decode_sequence (asn, len, &name)) == 0) - { - log_print ("x509_certreq_validate: can not decode 'acceptable CA' info"); - res = 0; - } - asn_free (&name); + struct norm_type name = SEQOF("issuer", RDNSequence); + + if (!asn_template_clone(&name, 1) || + (asn = asn_decode_sequence(asn, len, &name)) == 0) { + log_print("x509_certreq_validate: can not decode 'acceptable CA' info"); + res = 0; + } + asn_free(&name); #endif - /* XXX - not supported directly in SSL - later. */ + /* XXX - not supported directly in SSL - later. */ - return res; + return res; } /* Decode the BER Encoding of a RDNSequence in the CERT_REQ payload. */ void * -x509_certreq_decode (u_int8_t *asn, u_int32_t len) +x509_certreq_decode(u_int8_t *asn, u_int32_t len) { #if 0 - /* XXX This needs to be done later. */ - struct norm_type aca = SEQOF ("aca", RDNSequence); - struct norm_type *tmp; - struct x509_aca naca, *ret; - - if (!asn_template_clone (&aca, 1) - || (asn = asn_decode_sequence (asn, len, &aca)) == 0) - { - log_print ("x509_certreq_decode: can not decode 'acceptable CA' info"); - goto fail; - } - memset (&naca, 0, sizeof (naca)); - - tmp = asn_decompose ("aca.RelativeDistinguishedName.AttributeValueAssertion", - &aca); - if (!tmp) - goto fail; - x509_get_attribval (tmp, &naca.name1); - - tmp = asn_decompose ("aca.RelativeDistinguishedName[1]" - ".AttributeValueAssertion", &aca); - if (tmp) - x509_get_attribval (tmp, &naca.name2); - - asn_free (&aca); - - ret = malloc (sizeof (struct x509_aca)); - if (ret) - memcpy (ret, &naca, sizeof (struct x509_aca)); - else - { - log_error ("x509_certreq_decode: malloc (%lu) failed", - (unsigned long)sizeof (struct x509_aca)); - x509_free_aca (&aca); - } - - return ret; - - fail: - asn_free (&aca); + /* XXX This needs to be done later. */ + struct norm_type aca = SEQOF("aca", RDNSequence); + struct norm_type *tmp; + struct x509_aca naca, *ret; + + if (!asn_template_clone(&aca, 1) || + (asn = asn_decode_sequence(asn, len, &aca)) == 0) { + log_print("x509_certreq_decode: can not decode 'acceptable CA' info"); + goto fail; + } + memset(&naca, 0, sizeof(naca)); + + tmp = asn_decompose("aca.RelativeDistinguishedName.AttributeValueAssertion", + &aca); + if (!tmp) + goto fail; + x509_get_attribval(tmp, &naca.name1); + + tmp = asn_decompose("aca.RelativeDistinguishedName[1]" + ".AttributeValueAssertion", &aca); + if (tmp) + x509_get_attribval(tmp, &naca.name2); + + asn_free(&aca); + + ret = malloc(sizeof(struct x509_aca)); + if (ret) + memcpy(ret, &naca, sizeof(struct x509_aca)); + else { + log_error("x509_certreq_decode: malloc (%lu) failed", + (unsigned long) sizeof(struct x509_aca)); + x509_free_aca(&aca); + } + + return ret; + +fail: + asn_free(&aca); #endif - return 0; + return 0; } void -x509_free_aca (void *blob) +x509_free_aca(void *blob) { - struct x509_aca *aca = blob; + struct x509_aca *aca = blob; - if (aca->name1.type) - free (aca->name1.type); - if (aca->name1.val) - free (aca->name1.val); + if (aca->name1.type) + free(aca->name1.type); + if (aca->name1.val) + free(aca->name1.val); - if (aca->name2.type) - free (aca->name2.type); - if (aca->name2.val) - free (aca->name2.val); + if (aca->name2.type) + free(aca->name2.type); + if (aca->name2.val) + free(aca->name2.val); } X509 * -x509_from_asn (u_char *asn, u_int len) +x509_from_asn(u_char *asn, u_int len) { - BIO *certh; - X509 *scert = 0; - - certh = BIO_new (BIO_s_mem ()); - if (!certh) - { - log_error ("x509_from_asn: BIO_new (BIO_s_mem ()) failed"); - return 0; - } - - if (BIO_write (certh, asn, len) == -1) - { - log_error ("x509_from_asn: BIO_write failed\n"); - goto end; - } - - scert = d2i_X509_bio (certh, NULL); - if (!scert) - { - log_print ("x509_from_asn: d2i_X509_bio failed\n"); - goto end; - } - - end: - BIO_free (certh); - return scert; + BIO *certh; + X509 *scert = 0; + + certh = BIO_new(BIO_s_mem()); + if (!certh) { + log_error("x509_from_asn: BIO_new (BIO_s_mem ()) failed"); + return 0; + } + if (BIO_write(certh, asn, len) == -1) { + log_error("x509_from_asn: BIO_write failed\n"); + goto end; + } + scert = d2i_X509_bio(certh, NULL); + if (!scert) { + log_print("x509_from_asn: d2i_X509_bio failed\n"); + goto end; + } +end: + BIO_free(certh); + return scert; } /* @@ -1233,338 +1102,304 @@ x509_from_asn (u_char *asn, u_int len) * XXX We don't check if the certificate we find is from an accepted CA. */ int -x509_cert_obtain (u_int8_t *id, size_t id_len, void *data, u_int8_t **cert, - u_int32_t *certlen) +x509_cert_obtain(u_int8_t *id, size_t id_len, void *data, u_int8_t **cert, + u_int32_t *certlen) { - struct x509_aca *aca = data; - X509 *scert; - - if (aca) - LOG_DBG ((LOG_CRYPTO, 60, - "x509_cert_obtain: acceptable certificate authorities here")); - - /* We need our ID to find a certificate. */ - if (!id) - { - log_print ("x509_cert_obtain: ID is missing"); - return 0; - } - - scert = x509_hash_find (id, id_len); - if (!scert) - return 0; - - x509_serialize (scert, cert, certlen); - if (!*cert) - return 0; - return 1; + struct x509_aca *aca = data; + X509 *scert; + + if (aca) + LOG_DBG((LOG_CRYPTO, 60, + "x509_cert_obtain: acceptable certificate authorities here")); + + /* We need our ID to find a certificate. */ + if (!id) { + log_print("x509_cert_obtain: ID is missing"); + return 0; + } + scert = x509_hash_find(id, id_len); + if (!scert) + return 0; + + x509_serialize(scert, cert, certlen); + if (!*cert) + return 0; + return 1; } /* Returns a pointer to the subjectAltName information of X509 certificate. */ int -x509_cert_subjectaltname (X509 *scert, u_int8_t **altname, u_int32_t *len) +x509_cert_subjectaltname(X509 *scert, u_int8_t **altname, u_int32_t *len) { - X509_EXTENSION *subjectaltname; - u_int8_t *sandata; - int extpos; - int santype, sanlen; - - extpos = X509_get_ext_by_NID (scert, NID_subject_alt_name, -1); - if (extpos == -1) - { - log_print ("x509_cert_subjectaltname: " - "certificate does not contain subjectAltName"); - return 0; - } - - subjectaltname = X509_get_ext (scert, extpos); - - if (!subjectaltname || !subjectaltname->value - || !subjectaltname->value->data || subjectaltname->value->length < 4) - { - log_print ("x509_cert_subjectaltname: invalid subjectaltname extension"); - return 0; - } - - /* SSL does not handle unknown ASN stuff well, do it by hand. */ - sandata = subjectaltname->value->data; - santype = sandata[2] & 0x3f; - sanlen = sandata[3]; - sandata += 4; - - if (sanlen + 4 != subjectaltname->value->length) - { - log_print ("x509_cert_subjectaltname: subjectaltname invalid length"); - return 0; - } - - *len = sanlen; - *altname = sandata; - - return santype; + X509_EXTENSION *subjectaltname; + u_int8_t *sandata; + int extpos; + int santype, sanlen; + + extpos = X509_get_ext_by_NID(scert, NID_subject_alt_name, -1); + if (extpos == -1) { + log_print("x509_cert_subjectaltname: " + "certificate does not contain subjectAltName"); + return 0; + } + subjectaltname = X509_get_ext(scert, extpos); + + if (!subjectaltname || !subjectaltname->value || + !subjectaltname->value->data || subjectaltname->value->length < 4) { + log_print("x509_cert_subjectaltname: invalid subjectaltname extension"); + return 0; + } + /* SSL does not handle unknown ASN stuff well, do it by hand. */ + sandata = subjectaltname->value->data; + santype = sandata[2] & 0x3f; + sanlen = sandata[3]; + sandata += 4; + + if (sanlen + 4 != subjectaltname->value->length) { + log_print("x509_cert_subjectaltname: subjectaltname invalid length"); + return 0; + } + *len = sanlen; + *altname = sandata; + return santype; } int -x509_cert_get_subjects (void *scert, int *cnt, 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; - u_int8_t *buf = 0; - unsigned char *ubuf; - int i; - - *id = 0; - *id_len = 0; - - /* - * XXX There can be a collection of subjectAltNames, but for now - * I only return the subjectName and a single subjectAltName, if present. - */ - type = x509_cert_subjectaltname (cert, &altname, &altlen); - if (!type) - { - *cnt = 1; - altlen = 0; - } - else - *cnt = 2; - - *id = calloc (*cnt, sizeof **id); - if (!*id) - { - log_print ("x509_cert_get_subject: malloc (%lu) failed", - *cnt * (unsigned long)sizeof **id); - goto fail; - } - - *id_len = malloc (*cnt * sizeof **id_len); - if (!*id_len) - { - log_print ("x509_cert_get_subject: malloc (%lu) failed", - *cnt * (unsigned long)sizeof **id_len); - goto fail; - } - - /* Stash the subjectName into the first slot. */ - subject = X509_get_subject_name (cert); - if (!subject) - goto fail; - - (*id_len)[0] = - ISAKMP_ID_DATA_OFF + 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; - i2d_X509_NAME (subject, &ubuf); - - if (altlen) - { - /* Stash the subjectAltName into the second slot. */ - 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; + X509 *cert = scert; + X509_NAME *subject; + int type; + u_int8_t *altname; + u_int32_t altlen; + u_int8_t *buf = 0; + unsigned char *ubuf; + int i; + + *id = 0; + *id_len = 0; + + /* + * XXX There can be a collection of subjectAltNames, but for now + * I only return the subjectName and a single subjectAltName, if present. + */ + type = x509_cert_subjectaltname(cert, &altname, &altlen); + if (!type) { + *cnt = 1; + altlen = 0; + } else + *cnt = 2; + + *id = calloc(*cnt, sizeof **id); + if (!*id) { + log_print("x509_cert_get_subject: malloc (%lu) failed", + *cnt * (unsigned long) sizeof **id); + goto fail; } - - switch (type) - { - case X509v3_DNS_NAME: - SET_ISAKMP_ID_TYPE (buf, IPSEC_ID_FQDN); - break; - - case X509v3_RFC_NAME: - SET_ISAKMP_ID_TYPE (buf, IPSEC_ID_USER_FQDN); - break; - - 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 IPaddress length %d ", altlen); - goto fail; - } - break; + *id_len = malloc(*cnt * sizeof **id_len); + if (!*id_len) { + log_print("x509_cert_get_subject: malloc (%lu) failed", + *cnt * (unsigned long) sizeof **id_len); + goto fail; } - - 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)[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; + /* Stash the subjectName into the first slot. */ + subject = X509_get_subject_name(cert); + if (!subject) + goto fail; + + (*id_len)[0] = + ISAKMP_ID_DATA_OFF + 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; + i2d_X509_NAME(subject, &ubuf); + + if (altlen) { + /* Stash the subjectAltName into the second slot. */ + 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: + SET_ISAKMP_ID_TYPE(buf, IPSEC_ID_FQDN); + break; + + case X509v3_RFC_NAME: + SET_ISAKMP_ID_TYPE(buf, IPSEC_ID_USER_FQDN); + break; + + 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 IPaddress length %d ", + altlen); + goto fail; + } + 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); + + (*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; } - 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; + 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) +x509_cert_get_key(void *scert, void *keyp) { - X509 *cert = scert; - EVP_PKEY *key; + X509 *cert = scert; + EVP_PKEY *key; - key = X509_get_pubkey (cert); + key = X509_get_pubkey(cert); - /* Check if we got the right key type. */ - if (key->type != EVP_PKEY_RSA) - { - log_print ("x509_cert_get_key: public key is not a RSA key"); - X509_free (cert); - return 0; - } - - *(RSA **)keyp = RSAPublicKey_dup (key->pkey.rsa); + /* Check if we got the right key type. */ + if (key->type != EVP_PKEY_RSA) { + log_print("x509_cert_get_key: public key is not a RSA key"); + X509_free(cert); + return 0; + } + *(RSA **) keyp = RSAPublicKey_dup(key->pkey.rsa); - return *(RSA **)keyp == NULL ? 0 : 1; + return *(RSA **) keyp == NULL ? 0 : 1; } void * -x509_cert_dup (void *scert) +x509_cert_dup(void *scert) { - return X509_dup (scert); + return X509_dup(scert); } void -x509_serialize (void *scert, u_int8_t **data, u_int32_t *datalen) +x509_serialize(void *scert, u_int8_t **data, u_int32_t *datalen) { - u_int8_t *p; - - *datalen = i2d_X509 ((X509 *) scert, NULL); - *data = p = malloc (*datalen); - if (!p) - { - log_error ("x509_serialize: malloc (%d) failed", *datalen); - return; - } + u_int8_t *p; - *datalen = i2d_X509 ((X509 *)scert, &p); + *datalen = i2d_X509((X509 *) scert, NULL); + *data = p = malloc(*datalen); + if (!p) { + log_error("x509_serialize: malloc (%d) failed", *datalen); + return; + } + *datalen = i2d_X509((X509 *) scert, &p); } /* From cert to printable */ char * -x509_printable (void *cert) +x509_printable(void *cert) { - char *s; - u_int8_t *data; - u_int32_t datalen, i; - - x509_serialize (cert, &data, &datalen); - if (!data) - return 0; - - s = malloc (datalen * 2 + 1); - if (!s) - { - free (data); - log_error ("x509_printable: malloc (%d) failed", datalen * 2 + 1); - return 0; - } - - for (i = 0; i < datalen; i++) - snprintf (s + (2 * i), 2 * (datalen - i) + 1, "%02x", data[i]); - free (data); - return s; + char *s; + u_int8_t *data; + u_int32_t datalen, i; + + x509_serialize(cert, &data, &datalen); + if (!data) + return 0; + + s = malloc(datalen * 2 + 1); + if (!s) { + free(data); + log_error("x509_printable: malloc (%d) failed", datalen * 2 + 1); + return 0; + } + for (i = 0; i < datalen; i++) + snprintf(s + (2 * i), 2 * (datalen - i) + 1, "%02x", data[i]); + free(data); + return s; } /* From printable to cert */ void * -x509_from_printable (char *cert) +x509_from_printable(char *cert) { - u_int8_t *buf; - int plen, ret; - void *foo; - - plen = (strlen (cert) + 1) / 2; - buf = malloc (plen); - if (!buf) - { - log_error ("x509_from_printable: malloc (%d) failed", plen); - return 0; - } - - ret = hex2raw (cert, buf, plen); - if (ret == -1) - { - free (buf); - log_print ("x509_from_printable: badly formatted cert"); - return 0; - } - - foo = x509_cert_get (buf, plen); - free (buf); - if (!foo) - log_print ("x509_from_printable: could not retrieve certificate"); - return foo; + u_int8_t *buf; + int plen, ret; + void *foo; + + plen = (strlen(cert) + 1) / 2; + buf = malloc(plen); + if (!buf) { + log_error("x509_from_printable: malloc (%d) failed", plen); + return 0; + } + ret = hex2raw(cert, buf, plen); + if (ret == -1) { + free(buf); + log_print("x509_from_printable: badly formatted cert"); + return 0; + } + foo = x509_cert_get(buf, plen); + free(buf); + if (!foo) + log_print("x509_from_printable: could not retrieve certificate"); + return foo; } char * -x509_DN_string (u_int8_t *asn1, size_t sz) +x509_DN_string(u_int8_t *asn1, size_t sz) { - X509_NAME *name; - u_int8_t *p = asn1; - /* XXX Just a guess at a maximum length. */ - char buf[256]; - - name = d2i_X509_NAME (NULL, &p, sz); - if (!name) - { - log_print ("x509_DN_string: d2i_X509_NAME failed"); - return 0; - } - if (!X509_NAME_oneline (name, buf, sizeof buf - 1)) - { - log_print ("x509_DN_string: X509_NAME_oneline failed"); - X509_NAME_free (name); - return 0; - } - X509_NAME_free (name); - buf[sizeof buf - 1] = '\0'; - return strdup (buf); + X509_NAME *name; + u_int8_t *p = asn1; + /* XXX Just a guess at a maximum length. */ + char buf[256]; + + name = d2i_X509_NAME(NULL, &p, sz); + if (!name) { + log_print("x509_DN_string: d2i_X509_NAME failed"); + return 0; + } + if (!X509_NAME_oneline(name, buf, sizeof buf - 1)) { + log_print("x509_DN_string: X509_NAME_oneline failed"); + X509_NAME_free(name); + return 0; + } + X509_NAME_free(name); + buf[sizeof buf - 1] = '\0'; + return strdup(buf); } -#endif /* USE_X509 */ +#endif /* USE_X509 */ |