diff options
author | Andrew Bartlett <abartlet@samba.org> | 2007-07-03 08:00:08 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 14:58:59 -0500 |
commit | ec0035c9b8e0690f3bc21f3de089c39eae660916 (patch) | |
tree | 183dddce1bc0704f0c137df03e611d255fb68e11 /source4/heimdal/lib/hx509 | |
parent | 74b35321dc043188386d0305508b5276a5290d0d (diff) | |
download | samba-ec0035c9b8e0690f3bc21f3de089c39eae660916.tar.gz samba-ec0035c9b8e0690f3bc21f3de089c39eae660916.tar.bz2 samba-ec0035c9b8e0690f3bc21f3de089c39eae660916.zip |
r23678: Update to current lorikeet-heimdal (-r 767), which should fix the
panics on hosts without /dev/random.
Andrew Bartlett
(This used to be commit 14a4ddb131993fec72316f7e8e371638749e6f1f)
Diffstat (limited to 'source4/heimdal/lib/hx509')
-rw-r--r-- | source4/heimdal/lib/hx509/cert.c | 186 | ||||
-rw-r--r-- | source4/heimdal/lib/hx509/cms.c | 79 | ||||
-rw-r--r-- | source4/heimdal/lib/hx509/crypto.c | 66 | ||||
-rw-r--r-- | source4/heimdal/lib/hx509/file.c | 240 | ||||
-rw-r--r-- | source4/heimdal/lib/hx509/hx509-private.h | 42 | ||||
-rw-r--r-- | source4/heimdal/lib/hx509/hx509-protos.h | 57 | ||||
-rw-r--r-- | source4/heimdal/lib/hx509/hx509.h | 19 | ||||
-rw-r--r-- | source4/heimdal/lib/hx509/hx_locl.h | 6 | ||||
-rw-r--r-- | source4/heimdal/lib/hx509/keyset.c | 23 | ||||
-rw-r--r-- | source4/heimdal/lib/hx509/ks_file.c | 418 | ||||
-rw-r--r-- | source4/heimdal/lib/hx509/ks_keychain.c | 129 | ||||
-rw-r--r-- | source4/heimdal/lib/hx509/ks_p11.c | 15 | ||||
-rw-r--r-- | source4/heimdal/lib/hx509/ks_p12.c | 16 | ||||
-rw-r--r-- | source4/heimdal/lib/hx509/req.c | 110 | ||||
-rw-r--r-- | source4/heimdal/lib/hx509/revoke.c | 19 |
15 files changed, 977 insertions, 448 deletions
diff --git a/source4/heimdal/lib/hx509/cert.c b/source4/heimdal/lib/hx509/cert.c index 27b17a0204..caf163f8e4 100644 --- a/source4/heimdal/lib/hx509/cert.c +++ b/source4/heimdal/lib/hx509/cert.c @@ -32,7 +32,7 @@ */ #include "hx_locl.h" -RCSID("$Id: cert.c 20915 2007-06-05 03:58:56Z lha $"); +RCSID("$Id: cert.c 21294 2007-06-25 14:37:15Z lha $"); #include "crypto-headers.h" #include <rtbl.h> @@ -43,6 +43,7 @@ struct hx509_verify_ctx_data { #define HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE 2 #define HX509_VERIFY_CTX_F_REQUIRE_RFC3280 4 #define HX509_VERIFY_CTX_F_CHECK_TRUST_ANCHORS 8 +#define HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS 16 time_t time_now; unsigned int max_depth; #define HX509_VERIFY_MAX_DEPTH 30 @@ -51,6 +52,7 @@ struct hx509_verify_ctx_data { #define REQUIRE_RFC3280(ctx) ((ctx)->flags & HX509_VERIFY_CTX_F_REQUIRE_RFC3280) #define CHECK_TA(ctx) ((ctx)->flags & HX509_VERIFY_CTX_F_CHECK_TRUST_ANCHORS) +#define ALLOW_DEF_TA(ctx) (((ctx)->flags & HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS) == 0) struct _hx509_cert_attrs { size_t len; @@ -80,22 +82,6 @@ typedef struct hx509_name_constraints { * */ -void -_hx509_abort(const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - vprintf(fmt, ap); - va_end(ap); - printf("\n"); - fflush(stdout); - abort(); -} - -/* - * - */ - int hx509_context_init(hx509_context *context) { @@ -227,7 +213,34 @@ hx509_cert_init(hx509_context context, const Certificate *c, hx509_cert *cert) if (ret) { free((*cert)->data); free(*cert); + *cert = NULL; + } + return ret; +} + +int +hx509_cert_init_data(hx509_context context, + const void *ptr, + size_t len, + hx509_cert *cert) +{ + Certificate t; + size_t size; + int ret; + + ret = decode_Certificate(ptr, len, &t, &size); + if (ret) { + hx509_set_error_string(context, 0, ret, "Failed to decode certificate"); + return ret; + } + if (size != len) { + hx509_set_error_string(context, 0, HX509_EXTRA_DATA_AFTER_STRUCTURE, + "Extra data after certificate"); + return HX509_EXTRA_DATA_AFTER_STRUCTURE; } + + ret = hx509_cert_init(context, &t, cert); + free_Certificate(&t); return ret; } @@ -291,10 +304,10 @@ hx509_cert hx509_cert_ref(hx509_cert cert) { if (cert->ref <= 0) - _hx509_abort("refcount <= 0"); + _hx509_abort("cert refcount <= 0"); cert->ref++; if (cert->ref == 0) - _hx509_abort("refcount == 0"); + _hx509_abort("cert refcount == 0"); return cert; } @@ -342,6 +355,12 @@ hx509_verify_set_time(hx509_verify_ctx ctx, time_t t) } void +hx509_verify_set_max_depth(hx509_verify_ctx ctx, unsigned int max_depth) +{ + ctx->max_depth = max_depth; +} + +void hx509_verify_set_proxy_certificate(hx509_verify_ctx ctx, int boolean) { if (boolean) @@ -359,6 +378,15 @@ hx509_verify_set_strict_rfc3280_verification(hx509_verify_ctx ctx, int boolean) ctx->flags &= ~HX509_VERIFY_CTX_F_REQUIRE_RFC3280; } +void +hx509_verify_ctx_f_allow_default_trustanchors(hx509_verify_ctx ctx, int boolean) +{ + if (boolean) + ctx->flags &= ~HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS; + else + ctx->flags |= HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS; +} + static const Extension * find_extension(const Certificate *cert, const heim_oid *oid, int *idx) { @@ -1295,13 +1323,15 @@ match_general_name(const GeneralName *c, const GeneralName *n, int *match) return 0; } case choice_GeneralName_dNSName: { - size_t len1, len2; + size_t lenc, lenn; - len1 = strlen(c->u.dNSName); - len2 = strlen(n->u.dNSName); - if (len1 > len2) + lenc = strlen(c->u.dNSName); + lenn = strlen(n->u.dNSName); + if (lenc > lenn) return HX509_NAME_CONSTRAINT_ERROR; - if (strcasecmp(&n->u.dNSName[len2 - len1], c->u.dNSName) != 0) + if (strcasecmp(&n->u.dNSName[lenn - lenc], c->u.dNSName) != 0) + return HX509_NAME_CONSTRAINT_ERROR; + if (lenc != lenn && n->u.dNSName[lenn - lenc - 1] != '.') return HX509_NAME_CONSTRAINT_ERROR; *match = 1; return 0; @@ -1488,15 +1518,15 @@ hx509_verify_path(hx509_context context, /* * */ - ret = hx509_certs_init(context, "MEMORY:trust-anchors", 0, NULL, &anchors); - if (ret) - goto out; - ret = hx509_certs_merge(context, anchors, ctx->trust_anchors); - if (ret) - goto out; - ret = hx509_certs_merge(context, anchors, context->default_trust_anchors); - if (ret) - goto out; + if (ctx->trust_anchors) + anchors = _hx509_certs_ref(ctx->trust_anchors); + else if (context->default_trust_anchors && ALLOW_DEF_TA(ctx)) + anchors = _hx509_certs_ref(context->default_trust_anchors); + else { + ret = hx509_certs_init(context, "MEMORY:no-TA", 0, NULL, &anchors); + if (ret) + goto out; + } /* * Calculate the path from the certificate user presented to the @@ -1843,17 +1873,82 @@ hx509_verify_signature(hx509_context context, return _hx509_verify_signature(context, signer->data, alg, data, sig); } +#define HX509_VHN_F_ALLOW_NO_MATCH 1 + int hx509_verify_hostname(hx509_context context, const hx509_cert cert, - int require_match, + int flags, + hx509_hostname_type type, const char *hostname, const struct sockaddr *sa, /* XXX krb5_socklen_t */ int sa_size) { + GeneralNames san; + int ret, i, j; + if (sa && sa_size <= 0) return EINVAL; - return 0; + + memset(&san, 0, sizeof(san)); + + i = 0; + do { + ret = find_extension_subject_alt_name(cert->data, &i, &san); + if (ret == HX509_EXTENSION_NOT_FOUND) { + ret = 0; + break; + } else if (ret != 0) + break; + + for (j = 0; j < san.len; j++) { + switch (san.val[j].element) { + case choice_GeneralName_dNSName: + if (strcasecmp(san.val[j].u.dNSName, hostname) == 0) { + free_GeneralNames(&san); + return 0; + } + break; + default: + break; + } + } + free_GeneralNames(&san); + } while (1); + + { + Name *name = &cert->data->tbsCertificate.subject; + + /* match if first component is a CN= */ + if (name->u.rdnSequence.len > 0 + && name->u.rdnSequence.val[0].len == 1 + && der_heim_oid_cmp(&name->u.rdnSequence.val[0].val[0].type, + oid_id_at_commonName()) == 0) + { + DirectoryString *ds = &name->u.rdnSequence.val[0].val[0].value; + + switch (ds->element) { + case choice_DirectoryString_printableString: + if (strcasecmp(ds->u.printableString, hostname) == 0) + return 0; + break; + case choice_DirectoryString_ia5String: + if (strcasecmp(ds->u.ia5String, hostname) == 0) + return 0; + break; + case choice_DirectoryString_utf8String: + if (strcasecmp(ds->u.utf8String, hostname) == 0) + return 0; + default: + break; + } + } + } + + if ((flags & HX509_VHN_F_ALLOW_NO_MATCH) == 0) + ret = HX509_NAME_CONSTRAINT_ERROR; + + return ret; } int @@ -2434,3 +2529,24 @@ hx509_cert_binary(hx509_context context, hx509_cert c, heim_octet_string *os) return ret; } + +/* + * Last to avoid lost __attribute__s due to #undef. + */ + +#undef __attribute__ +#define __attribute__(X) + +void +_hx509_abort(const char *fmt, ...) + __attribute__ ((noreturn, format (printf, 1, 2))) +{ + va_list ap; + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + printf("\n"); + fflush(stdout); + abort(); +} + diff --git a/source4/heimdal/lib/hx509/cms.c b/source4/heimdal/lib/hx509/cms.c index 29ca80e194..30f364060d 100644 --- a/source4/heimdal/lib/hx509/cms.c +++ b/source4/heimdal/lib/hx509/cms.c @@ -32,7 +32,7 @@ */ #include "hx_locl.h" -RCSID("$Id: cms.c 20937 2007-06-06 20:50:55Z lha $"); +RCSID("$Id: cms.c 21319 2007-06-25 19:46:52Z lha $"); #define ALLOC(X, N) (X) = calloc((N), sizeof(*(X))) #define ALLOC_SEQ(X, N) do { (X)->len = (N); ALLOC((X)->val, (N)); } while(0) @@ -115,24 +115,42 @@ hx509_cms_unwrap_ContentInfo(const heim_octet_string *in, return 0; } +#define CMS_ID_SKI 0 +#define CMS_ID_NAME 1 + static int -fill_CMSIdentifier(const hx509_cert cert, CMSIdentifier *id) +fill_CMSIdentifier(const hx509_cert cert, + int type, + CMSIdentifier *id) { - hx509_name name; int ret; - id->element = choice_CMSIdentifier_issuerAndSerialNumber; - ret = hx509_cert_get_issuer(cert, &name); - if (ret) - return ret; - ret = copy_Name(&name->der_name, - &id->u.issuerAndSerialNumber.issuer); - hx509_name_free(&name); - if (ret) - return ret; + switch (type) { + case CMS_ID_SKI: + id->element = choice_CMSIdentifier_subjectKeyIdentifier; + ret = _hx509_find_extension_subject_key_id(_hx509_get_cert(cert), + &id->u.subjectKeyIdentifier); + if (ret == 0) + break; + /* FALL THOUGH */ + case CMS_ID_NAME: { + hx509_name name; - ret = hx509_cert_get_serialnumber(cert, - &id->u.issuerAndSerialNumber.serialNumber); + id->element = choice_CMSIdentifier_issuerAndSerialNumber; + ret = hx509_cert_get_issuer(cert, &name); + if (ret) + return ret; + ret = hx509_name_to_Name(name, &id->u.issuerAndSerialNumber.issuer); + hx509_name_free(&name); + if (ret) + return ret; + + ret = hx509_cert_get_serialnumber(cert, &id->u.issuerAndSerialNumber.serialNumber); + break; + } + default: + _hx509_abort("CMS fill identifier with unknown type"); + } return ret; } @@ -467,6 +485,13 @@ hx509_cms_envelope_1(hx509_context context, goto out; } + ret = hx509_crypto_random_iv(crypto, &ivec); + if (ret) { + hx509_set_error_string(context, 0, ret, + "Failed to create a random iv"); + goto out; + } + ret = hx509_crypto_encrypt(crypto, data, length, @@ -518,7 +543,7 @@ hx509_cms_envelope_1(hx509_context context, ri = &ed.recipientInfos.val[0]; ri->version = 0; - ret = fill_CMSIdentifier(cert, &ri->rid); + ret = fill_CMSIdentifier(cert, CMS_ID_SKI, &ri->rid); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to set CMS identifier info " @@ -585,22 +610,12 @@ any_to_certs(hx509_context context, const SignedData *sd, hx509_certs certs) return 0; for (i = 0; i < sd->certificates->len; i++) { - Certificate cert; hx509_cert c; - const void *p = sd->certificates->val[i].data; - size_t size, length = sd->certificates->val[i].length; - - ret = decode_Certificate(p, length, &cert, &size); - if (ret) { - hx509_set_error_string(context, 0, ret, - "Failed to decode certificate %d " - "in SignedData.certificates", i); - return ret; - } - - ret = hx509_cert_init(context, &cert, &c); - free_Certificate(&cert); + ret = hx509_cert_init_data(context, + sd->certificates->val[i].data, + sd->certificates->val[i].length, + &c); if (ret) return ret; ret = hx509_certs_add(context, certs, c); @@ -951,6 +966,7 @@ hx509_cms_create_signed_1(hx509_context context, int ret; size_t size; hx509_path path; + int cmsidflag = CMS_ID_SKI; memset(&sd, 0, sizeof(sd)); memset(&name, 0, sizeof(name)); @@ -960,6 +976,9 @@ hx509_cms_create_signed_1(hx509_context context, content.data = rk_UNCONST(data); content.length = length; + if (flags & HX509_CMS_SIGATURE_ID_NAME) + cmsidflag = CMS_ID_NAME; + if (_hx509_cert_private_key(cert) == NULL) { hx509_set_error_string(context, 0, HX509_PRIVATE_KEY_MISSING, "Private key missing for signing"); @@ -1014,7 +1033,7 @@ hx509_cms_create_signed_1(hx509_context context, signer_info->version = 1; - ret = fill_CMSIdentifier(cert, &signer_info->sid); + ret = fill_CMSIdentifier(cert, cmsidflag, &signer_info->sid); if (ret) { hx509_clear_error_string(context); goto out; diff --git a/source4/heimdal/lib/hx509/crypto.c b/source4/heimdal/lib/hx509/crypto.c index 96d9693cc2..d86300bd58 100644 --- a/source4/heimdal/lib/hx509/crypto.c +++ b/source4/heimdal/lib/hx509/crypto.c @@ -32,7 +32,7 @@ */ #include "hx_locl.h" -RCSID("$Id: crypto.c 20939 2007-06-06 20:53:02Z lha $"); +RCSID("$Id: crypto.c 21318 2007-06-25 19:46:32Z lha $"); struct hx509_crypto; @@ -362,6 +362,7 @@ rsa_create_signature(hx509_context context, sig->length = RSA_size(signer->private_key.rsa); sig->data = malloc(sig->length); if (sig->data == NULL) { + der_free_octet_string(&indata); hx509_set_error_string(context, 0, ENOMEM, "out of memory"); return ENOMEM; } @@ -1761,15 +1762,17 @@ CMSRC2CBCParam_set(hx509_context context, const heim_octet_string *param, p->maximum_effective_key = 128; break; default: + free(p); free_CMSRC2CBCParameter(&rc2param); return HX509_CRYPTO_SIG_INVALID_FORMAT; } if (ivec) ret = der_copy_octet_string(&rc2param.iv, ivec); free_CMSRC2CBCParameter(&rc2param); - if (ret) + if (ret) { + free(p); hx509_clear_error_string(context); - else + } else crypto->param = p; return ret; @@ -2009,10 +2012,29 @@ hx509_crypto_get_params(hx509_context context, } int +hx509_crypto_random_iv(hx509_crypto crypto, heim_octet_string *ivec) +{ + ivec->length = EVP_CIPHER_iv_length(crypto->c); + ivec->data = malloc(ivec->length); + if (ivec->data == NULL) { + ivec->length = 0; + return ENOMEM; + } + + if (RAND_bytes(ivec->data, ivec->length) <= 0) { + free(ivec->data); + ivec->data = NULL; + ivec->length = 0; + return HX509_CRYPTO_INTERNAL_ERROR; + } + return 0; +} + +int hx509_crypto_encrypt(hx509_crypto crypto, const void *data, const size_t length, - heim_octet_string *ivec, + const heim_octet_string *ivec, heim_octet_string **ciphertext) { EVP_CIPHER_CTX evp; @@ -2021,19 +2043,9 @@ hx509_crypto_encrypt(hx509_crypto crypto, *ciphertext = NULL; - EVP_CIPHER_CTX_init(&evp); - - ivec->length = EVP_CIPHER_iv_length(crypto->c); - ivec->data = malloc(ivec->length); - if (ivec->data == NULL) { - ret = ENOMEM; - goto out; - } + assert(EVP_CIPHER_iv_length(crypto->c) == ivec->length); - if (RAND_bytes(ivec->data, ivec->length) <= 0) { - ret = HX509_CRYPTO_INTERNAL_ERROR; - goto out; - } + EVP_CIPHER_CTX_init(&evp); ret = EVP_CipherInit_ex(&evp, crypto->c, NULL, crypto->key.data, ivec->data, 1); @@ -2082,10 +2094,6 @@ hx509_crypto_encrypt(hx509_crypto crypto, out: if (ret) { - if (ivec->data) { - free(ivec->data); - memset(ivec, 0, sizeof(*ivec)); - } if (*ciphertext) { if ((*ciphertext)->data) { free((*ciphertext)->data); @@ -2286,6 +2294,24 @@ find_string2key(const heim_oid *oid, return NULL; } +/* + * + */ + +int +_hx509_pbe_encrypt(hx509_context context, + hx509_lock lock, + const AlgorithmIdentifier *ai, + const heim_octet_string *content, + heim_octet_string *econtent) +{ + hx509_clear_error_string(context); + return EINVAL; +} + +/* + * + */ int _hx509_pbe_decrypt(hx509_context context, diff --git a/source4/heimdal/lib/hx509/file.c b/source4/heimdal/lib/hx509/file.c index 1152af2423..b076b74f44 100644 --- a/source4/heimdal/lib/hx509/file.c +++ b/source4/heimdal/lib/hx509/file.c @@ -134,3 +134,243 @@ _hx509_write_file(const char *fn, const void *data, size_t length) return 0; } + +/* + * + */ + +static void +header(FILE *f, const char *type, const char *str) +{ + fprintf(f, "-----%s %s-----\n", type, str); +} + +int +hx509_pem_write(hx509_context context, const char *type, + hx509_pem_header *headers, FILE *f, + const void *data, size_t size) +{ + const char *p = data; + size_t length; + char *line; + +#define ENCODE_LINE_LENGTH 54 + + header(f, "BEGIN", type); + + while (headers) { + fprintf(f, "%s: %s\n%s", + headers->header, headers->value, + headers->next ? "" : "\n"); + headers = headers->next; + } + + while (size > 0) { + ssize_t l; + + length = size; + if (length > ENCODE_LINE_LENGTH) + length = ENCODE_LINE_LENGTH; + + l = base64_encode(p, length, &line); + if (l < 0) { + hx509_set_error_string(context, 0, ENOMEM, + "malloc - out of memory"); + return ENOMEM; + } + size -= length; + fprintf(f, "%s\n", line); + p += length; + free(line); + } + + header(f, "END", type); + + return 0; +} + +/* + * + */ + +int +hx509_pem_add_header(hx509_pem_header **headers, + const char *header, const char *value) +{ + hx509_pem_header *h; + + h = calloc(1, sizeof(*h)); + if (h == NULL) + return ENOMEM; + h->header = strdup(header); + if (h->header == NULL) { + free(h); + return ENOMEM; + } + h->value = strdup(value); + if (h->value == NULL) { + free(h->header); + free(h); + return ENOMEM; + } + + h->next = *headers; + *headers = h; + + return 0; +} + +void +hx509_pem_free_header(hx509_pem_header *headers) +{ + hx509_pem_header *h; + while (headers) { + h = headers; + headers = headers->next; + free(h->header); + free(h->value); + free(h); + } +} + +/* + * + */ + +const char * +hx509_pem_find_header(const hx509_pem_header *h, const char *header) +{ + while(h) { + if (strcmp(header, h->header) == 0) + return h->value; + h = h->next; + } + return NULL; +} + + +/* + * + */ + +int +hx509_pem_read(hx509_context context, + FILE *f, + hx509_pem_read_func func, + void *ctx) +{ + hx509_pem_header *headers = NULL; + char *type = NULL; + void *data = NULL; + size_t len = 0; + char buf[1024]; + int ret = HX509_PARSING_KEY_FAILED; + + enum { BEFORE, SEARCHHEADER, INHEADER, INDATA, DONE } where; + + where = BEFORE; + + while (fgets(buf, sizeof(buf), f) != NULL) { + char *p; + int i; + + i = strcspn(buf, "\n"); + if (buf[i] == '\n') { + buf[i] = '\0'; + if (i > 0) + i--; + } + if (buf[i] == '\r') { + buf[i] = '\0'; + if (i > 0) + i--; + } + + switch (where) { + case BEFORE: + if (strncmp("-----BEGIN ", buf, 11) == 0) { + type = strdup(buf + 11); + if (type == NULL) + break; + p = strchr(type, '-'); + if (p) + *p = '\0'; + where = SEARCHHEADER; + } + break; + case SEARCHHEADER: + p = strchr(buf, ':'); + if (p == NULL) { + where = INDATA; + goto indata; + } + /* FALLTHOUGH */ + case INHEADER: + if (buf[0] == '\0') { + where = INDATA; + break; + } + p = strchr(buf, ':'); + if (p) { + *p++ = '\0'; + while (isspace((int)*p)) + p++; + ret = hx509_pem_add_header(&headers, buf, p); + if (ret) + abort(); + } + break; + case INDATA: + indata: + + if (strncmp("-----END ", buf, 9) == 0) { + where = DONE; + break; + } + + p = emalloc(i); + i = base64_decode(buf, p); + if (i < 0) { + free(p); + goto out; + } + + data = erealloc(data, len + i); + memcpy(((char *)data) + len, p, i); + free(p); + len += i; + break; + case DONE: + abort(); + } + + if (where == DONE) { + ret = (*func)(context, type, headers, data, len, ctx); + out: + free(data); + data = NULL; + len = 0; + free(type); + type = NULL; + where = BEFORE; + hx509_pem_free_header(headers); + headers = NULL; + if (ret) + break; + } + } + + if (where != BEFORE) { + hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED, + "File ends before end of PEM end tag"); + ret = HX509_PARSING_KEY_FAILED; + } + if (data) + free(data); + if (type) + free(type); + if (headers) + hx509_pem_free_header(headers); + + return ret; +} diff --git a/source4/heimdal/lib/hx509/hx509-private.h b/source4/heimdal/lib/hx509/hx509-private.h index 2763df957f..451c3c89f2 100644 --- a/source4/heimdal/lib/hx509/hx509-private.h +++ b/source4/heimdal/lib/hx509/hx509-private.h @@ -4,6 +4,10 @@ #include <stdarg.h> +#if !defined(__GNUC__) && !defined(__attribute__) +#define __attribute__(x) +#endif + int _hx509_Certificate_cmp ( const Certificate */*p*/, @@ -20,7 +24,8 @@ _hx509_Time2time_t (const Time */*t*/); void _hx509_abort ( const char */*fmt*/, - ...); + ...) + __attribute__ ((noreturn, format (printf, 1, 2))); int _hx509_calculate_path ( @@ -104,6 +109,9 @@ _hx509_certs_keys_get ( hx509_certs /*certs*/, hx509_private_key **/*keys*/); +hx509_certs +_hx509_certs_ref (hx509_certs /*certs*/); + int _hx509_check_key_usage ( hx509_context /*context*/, @@ -306,6 +314,14 @@ _hx509_pbe_decrypt ( const heim_octet_string */*econtent*/, heim_octet_string */*content*/); +int +_hx509_pbe_encrypt ( + hx509_context /*context*/, + hx509_lock /*lock*/, + const AlgorithmIdentifier */*ai*/, + const heim_octet_string */*content*/, + heim_octet_string */*econtent*/); + void _hx509_pi_printf ( int (*/*func*/)(void *, const char *), @@ -407,11 +423,35 @@ void _hx509_request_free (hx509_request */*req*/); int +_hx509_request_get_SubjectPublicKeyInfo ( + hx509_context /*context*/, + hx509_request /*req*/, + SubjectPublicKeyInfo */*key*/); + +int +_hx509_request_get_name ( + hx509_context /*context*/, + hx509_request /*req*/, + hx509_name */*name*/); + +int _hx509_request_init ( hx509_context /*context*/, hx509_request */*req*/); int +_hx509_request_parse ( + hx509_context /*context*/, + const char */*path*/, + hx509_request */*req*/); + +int +_hx509_request_print ( + hx509_context /*context*/, + hx509_request /*req*/, + FILE */*f*/); + +int _hx509_request_set_SubjectPublicKeyInfo ( hx509_context /*context*/, hx509_request /*req*/, diff --git a/source4/heimdal/lib/hx509/hx509-protos.h b/source4/heimdal/lib/hx509/hx509-protos.h index ab312cdbdf..71fb29d59d 100644 --- a/source4/heimdal/lib/hx509/hx509-protos.h +++ b/source4/heimdal/lib/hx509/hx509-protos.h @@ -237,6 +237,13 @@ hx509_cert_init ( hx509_cert */*cert*/); int +hx509_cert_init_data ( + hx509_context /*context*/, + const void */*ptr*/, + size_t /*len*/, + hx509_cert */*cert*/); + +int hx509_cert_keyusage_print ( hx509_context /*context*/, hx509_cert /*c*/, @@ -479,7 +486,7 @@ hx509_crypto_encrypt ( hx509_crypto /*crypto*/, const void */*data*/, const size_t /*length*/, - heim_octet_string */*ivec*/, + const heim_octet_string */*ivec*/, heim_octet_string **/*ciphertext*/); const heim_oid * @@ -508,6 +515,11 @@ const char * hx509_crypto_provider (hx509_crypto /*crypto*/); int +hx509_crypto_random_iv ( + hx509_crypto /*crypto*/, + heim_octet_string */*ivec*/); + +int hx509_crypto_select ( const hx509_context /*context*/, int /*type*/, @@ -740,6 +752,36 @@ hx509_peer_info_set_cms_algs ( const AlgorithmIdentifier */*val*/, size_t /*len*/); +int +hx509_pem_add_header ( + hx509_pem_header **/*headers*/, + const char */*header*/, + const char */*value*/); + +const char * +hx509_pem_find_header ( + const hx509_pem_header */*h*/, + const char */*header*/); + +void +hx509_pem_free_header (hx509_pem_header */*headers*/); + +int +hx509_pem_read ( + hx509_context /*context*/, + FILE */*f*/, + hx509_pem_read_func /*func*/, + void */*ctx*/); + +int +hx509_pem_write ( + hx509_context /*context*/, + const char */*type*/, + hx509_pem_header */*headers*/, + FILE */*f*/, + const void */*data*/, + size_t /*size*/); + void hx509_print_func ( hx509_vprint_func /*func*/, @@ -931,13 +973,19 @@ hx509_verify_attach_revoke ( hx509_revoke_ctx /*revoke_ctx*/); void +hx509_verify_ctx_f_allow_default_trustanchors ( + hx509_verify_ctx /*ctx*/, + int /*boolean*/); + +void hx509_verify_destroy_ctx (hx509_verify_ctx /*ctx*/); int hx509_verify_hostname ( hx509_context /*context*/, const hx509_cert /*cert*/, - int /*require_match*/, + int /*flags*/, + hx509_hostname_type /*type*/, const char */*hostname*/, const struct sockaddr */*sa*/, int /*sa_size*/); @@ -955,6 +1003,11 @@ hx509_verify_path ( hx509_certs /*pool*/); void +hx509_verify_set_max_depth ( + hx509_verify_ctx /*ctx*/, + unsigned int /*max_depth*/); + +void hx509_verify_set_proxy_certificate ( hx509_verify_ctx /*ctx*/, int /*boolean*/); diff --git a/source4/heimdal/lib/hx509/hx509.h b/source4/heimdal/lib/hx509/hx509.h index 664c12e045..2f22cedfbc 100644 --- a/source4/heimdal/lib/hx509/hx509.h +++ b/source4/heimdal/lib/hx509/hx509.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: hx509.h 20798 2007-06-02 03:28:55Z lha $ */ +/* $Id: hx509.h 21310 2007-06-25 18:26:06Z lha $ */ typedef struct hx509_cert_attribute_data *hx509_cert_attribute; typedef struct hx509_cert_data *hx509_cert; @@ -84,6 +84,16 @@ typedef struct hx509_octet_string_list { heim_octet_string *val; } hx509_octet_string_list; +typedef struct hx509_pem_header { + struct hx509_pem_header *next; + char *header; + char *value; +} hx509_pem_header; + +typedef int +(*hx509_pem_read_func)(hx509_context, const char *, const hx509_pem_header *, + const void *, size_t, void *ctx); + /* * Options passed to hx509_query_match_option. */ @@ -122,5 +132,12 @@ typedef enum { /* flags hx509_cms_create_signed* */ #define HX509_CMS_SIGATURE_DETACHED 1 +#define HX509_CMS_SIGATURE_ID_NAME 2 + +/* hx509_verify_hostname nametype */ +typedef enum { + HX509_HN_HOSTNAME = 0, + HX509_HN_DNSSRV +} hx509_hostname_type; #include <hx509-protos.h> diff --git a/source4/heimdal/lib/hx509/hx_locl.h b/source4/heimdal/lib/hx509/hx_locl.h index bfbee0943e..145bfcc006 100644 --- a/source4/heimdal/lib/hx509/hx_locl.h +++ b/source4/heimdal/lib/hx509/hx_locl.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: hx_locl.h 20930 2007-06-06 00:23:42Z lha $ */ +/* $Id: hx_locl.h 21083 2007-06-13 02:11:19Z lha $ */ #ifdef HAVE_CONFIG_H #include <config.h> @@ -194,6 +194,6 @@ extern const AlgorithmIdentifier * _hx509_crypto_default_secret_alg; * Configurable options */ -#if 0 /* fdef __APPLE__*/ -#define HX509_DEFAULT_ANCHORS "KEYCHAIN:system" +#ifdef __APPLE__ +#define HX509_DEFAULT_ANCHORS "KEYCHAIN:system-anchors" #endif diff --git a/source4/heimdal/lib/hx509/keyset.c b/source4/heimdal/lib/hx509/keyset.c index 475835b9b0..7da5705a80 100644 --- a/source4/heimdal/lib/hx509/keyset.c +++ b/source4/heimdal/lib/hx509/keyset.c @@ -32,9 +32,10 @@ */ #include "hx_locl.h" -RCSID("$Id: keyset.c 20911 2007-06-05 03:41:17Z lha $"); +RCSID("$Id: keyset.c 21140 2007-06-18 21:24:19Z lha $"); struct hx509_certs_data { + int ref; struct hx509_keyset_ops *ops; void *ops_data; }; @@ -99,18 +100,20 @@ hx509_certs_init(hx509_context context, } ops = _hx509_ks_type(context, type); - free(type); if (ops == NULL) { hx509_set_error_string(context, 0, ENOENT, "Keyset type %s is not supported", type); + free(type); return ENOENT; } + free(type); c = calloc(1, sizeof(*c)); if (c == NULL) { hx509_clear_error_string(context); return ENOMEM; } c->ops = ops; + c->ref = 1; ret = (*ops->init)(context, c, &c->ops_data, flags, residue, lock); if (ret) { @@ -140,10 +143,26 @@ hx509_certs_store(hx509_context context, } +hx509_certs +_hx509_certs_ref(hx509_certs certs) +{ + if (certs->ref <= 0) + _hx509_abort("certs refcount <= 0"); + certs->ref++; + if (certs->ref == 0) + _hx509_abort("certs refcount == 0"); + return certs; +} + void hx509_certs_free(hx509_certs *certs) { if (*certs) { + if ((*certs)->ref <= 0) + _hx509_abort("refcount <= 0"); + if (--(*certs)->ref > 0) + return; + (*(*certs)->ops->free)(*certs, (*certs)->ops_data); free(*certs); *certs = NULL; diff --git a/source4/heimdal/lib/hx509/ks_file.c b/source4/heimdal/lib/hx509/ks_file.c index f9a3580880..269afd03b1 100644 --- a/source4/heimdal/lib/hx509/ks_file.c +++ b/source4/heimdal/lib/hx509/ks_file.c @@ -32,68 +32,16 @@ */ #include "hx_locl.h" -RCSID("$Id: ks_file.c 20776 2007-06-01 22:02:01Z lha $"); +RCSID("$Id: ks_file.c 21314 2007-06-25 18:45:07Z lha $"); + +typedef enum { USE_PEM, USE_DER } outformat; struct ks_file { hx509_certs certs; char *fn; + outformat format; }; -struct header { - char *header; - char *value; - struct header *next; -}; - -static int -add_headers(struct header **headers, const char *header, const char *value) -{ - struct header *h; - h = calloc(1, sizeof(*h)); - if (h == NULL) - return ENOMEM; - h->header = strdup(header); - if (h->header == NULL) { - free(h); - return ENOMEM; - } - h->value = strdup(value); - if (h->value == NULL) { - free(h->header); - free(h); - return ENOMEM; - } - - h->next = *headers; - *headers = h; - - return 0; -} - -static void -free_headers(struct header *headers) -{ - struct header *h; - while (headers) { - h = headers; - headers = headers->next; - free(h->header); - free(h->value); - free(h); - } -} - -static const char * -find_header(const struct header *headers, const char *header) -{ - while(headers) { - if (strcmp(header, headers->header) == 0) - return headers->value; - headers = headers->next; - } - return NULL; -} - /* * */ @@ -101,24 +49,13 @@ find_header(const struct header *headers, const char *header) static int parse_certificate(hx509_context context, const char *fn, struct hx509_collector *c, - const struct header *headers, + const hx509_pem_header *headers, const void *data, size_t len) { hx509_cert cert; - Certificate t; - size_t size; int ret; - ret = decode_Certificate(data, len, &t, &size); - if (ret) { - hx509_set_error_string(context, 0, ret, - "Failed to parse certificate in %s", - fn); - return ret; - } - - ret = hx509_cert_init(context, &t, &cert); - free_Certificate(&t); + ret = hx509_cert_init_data(context, data, len, &cert); if (ret) return ret; @@ -195,13 +132,13 @@ out: static int parse_rsa_private_key(hx509_context context, const char *fn, struct hx509_collector *c, - const struct header *headers, + const hx509_pem_header *headers, const void *data, size_t len) { int ret = 0; const char *enc; - enc = find_header(headers, "Proc-Type"); + enc = hx509_pem_find_header(headers, "Proc-Type"); if (enc) { const char *dek; char *type, *iv; @@ -229,7 +166,7 @@ parse_rsa_private_key(hx509_context context, const char *fn, return HX509_PARSING_KEY_FAILED; } - dek = find_header(headers, "DEK-Info"); + dek = hx509_pem_find_header(headers, "DEK-Info"); if (dek == NULL) { hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED, "Encrypted RSA missing DEK-Info"); @@ -243,8 +180,14 @@ parse_rsa_private_key(hx509_context context, const char *fn, } iv = strchr(type, ','); - if (iv) - *iv++ = '\0'; + if (iv == NULL) { + free(type); + hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED, + "IV missing"); + return HX509_PARSING_KEY_FAILED; + } + + *iv++ = '\0'; size = strlen(iv); ivdata = malloc(size); @@ -339,7 +282,7 @@ parse_rsa_private_key(hx509_context context, const char *fn, struct pem_formats { const char *name; int (*func)(hx509_context, const char *, struct hx509_collector *, - const struct header *, const void *, size_t); + const hx509_pem_header *, const void *, size_t); } formats[] = { { "CERTIFICATE", parse_certificate }, { "RSA PRIVATE KEY", parse_rsa_private_key } @@ -347,152 +290,27 @@ struct pem_formats { static int -parse_pem_file(hx509_context context, - const char *fn, - struct hx509_collector *c, - int *found_data) +pem_func(hx509_context context, const char *type, + const hx509_pem_header *header, + const void *data, size_t len, void *ctx) { - struct header *headers = NULL; - char *type = NULL; - void *data = NULL; - size_t len = 0; - char buf[1024]; - int ret; - FILE *f; - - - enum { BEFORE, SEARCHHEADER, INHEADER, INDATA, DONE } where; - - where = BEFORE; - *found_data = 0; + struct hx509_collector *c = ctx; + int ret, j; - if ((f = fopen(fn, "r")) == NULL) { - hx509_set_error_string(context, 0, ENOENT, - "Failed to open PEM file \"%s\": %s", - fn, strerror(errno)); - return ENOENT; - } - ret = 0; - - while (fgets(buf, sizeof(buf), f) != NULL) { - char *p; - int i; - - i = strcspn(buf, "\n"); - if (buf[i] == '\n') { - buf[i] = '\0'; - if (i > 0) - i--; - } - if (buf[i] == '\r') { - buf[i] = '\0'; - if (i > 0) - i--; - } - - switch (where) { - case BEFORE: - if (strncmp("-----BEGIN ", buf, 11) == 0) { - type = strdup(buf + 11); - if (type == NULL) - break; - p = strchr(type, '-'); - if (p) - *p = '\0'; - *found_data = 1; - where = SEARCHHEADER; - } + for (j = 0; j < sizeof(formats)/sizeof(formats[0]); j++) { + const char *q = formats[j].name; + if (strcasecmp(type, q) == 0) { + ret = (*formats[j].func)(context, NULL, c, header, data, len); break; - case SEARCHHEADER: - p = strchr(buf, ':'); - if (p == NULL) { - where = INDATA; - goto indata; - } - /* FALLTHOUGH */ - case INHEADER: - if (buf[0] == '\0') { - where = INDATA; - break; - } - p = strchr(buf, ':'); - if (p) { - *p++ = '\0'; - while (isspace((int)*p)) - p++; - add_headers(&headers, buf, p); - } - break; - case INDATA: - indata: - - if (strncmp("-----END ", buf, 9) == 0) { - where = DONE; - break; - } - - p = emalloc(i); - i = base64_decode(buf, p); - if (i < 0) { - free(p); - goto out; - } - - data = erealloc(data, len + i); - memcpy(((char *)data) + len, p, i); - free(p); - len += i; - break; - case DONE: - abort(); - } - - if (where == DONE) { - int j; - - for (j = 0; j < sizeof(formats)/sizeof(formats[0]); j++) { - const char *q = formats[j].name; - if (strcasecmp(type, q) == 0) { - ret = (*formats[j].func)(context, fn, c, - headers, data, len); - break; - } - } - if (j == sizeof(formats)/sizeof(formats[0])) { - ret = HX509_UNSUPPORTED_OPERATION; - hx509_set_error_string(context, 0, ret, - "Found no matching PEM format for %s", - type); - } - out: - free(data); - data = NULL; - len = 0; - free(type); - type = NULL; - where = BEFORE; - free_headers(headers); - headers = NULL; - if (ret) - break; } } - - fclose(f); - - if (where != BEFORE) { - hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED, - "File ends before end of PEM end tag"); - ret = HX509_PARSING_KEY_FAILED; + if (j == sizeof(formats)/sizeof(formats[0])) { + ret = HX509_UNSUPPORTED_OPERATION; + hx509_set_error_string(context, 0, ret, + "Found no matching PEM format for %s", type); + return ret; } - if (data) - free(data); - if (type) - free(type); - if (headers) - free_headers(headers); - - return ret; + return 0; } /* @@ -500,9 +318,9 @@ parse_pem_file(hx509_context context, */ static int -file_init(hx509_context context, - hx509_certs certs, void **data, int flags, - const char *residue, hx509_lock lock) +file_init_common(hx509_context context, + hx509_certs certs, void **data, int flags, + const char *residue, hx509_lock lock, outformat format) { char *p, *pnext; struct ks_file *f = NULL; @@ -520,6 +338,7 @@ file_init(hx509_context context, hx509_clear_error_string(context); return ENOMEM; } + f->format = format; f->fn = strdup(residue); if (f->fn == NULL) { @@ -547,17 +366,26 @@ file_init(hx509_context context, goto out; for (p = f->fn; p != NULL; p = pnext) { - int found_data; + FILE *f; pnext = strchr(p, ','); if (pnext) *pnext++ = '\0'; - ret = parse_pem_file(context, p, c, &found_data); - if (ret) + + if ((f = fopen(p, "r")) == NULL) { + ret = ENOENT; + hx509_set_error_string(context, 0, ret, + "Failed to open PEM file \"%s\": %s", + p, strerror(errno)); goto out; + } - if (!found_data) { + ret = hx509_pem_read(context, f, pem_func, c); + fclose(f); + if (ret != 0 && ret != HX509_PARSING_KEY_FAILED) + goto out; + else if (ret == HX509_PARSING_KEY_FAILED) { size_t length; void *ptr; int i; @@ -606,75 +434,40 @@ out: } static int -file_free(hx509_certs certs, void *data) +file_init_pem(hx509_context context, + hx509_certs certs, void **data, int flags, + const char *residue, hx509_lock lock) { - struct ks_file *f = data; - hx509_certs_free(&f->certs); - free(f->fn); - free(f); - return 0; + return file_init_common(context, certs, data, flags, residue, lock, USE_PEM); } -static void -pem_header(FILE *f, const char *type, const char *str) +static int +file_init_der(hx509_context context, + hx509_certs certs, void **data, int flags, + const char *residue, hx509_lock lock) { - fprintf(f, "-----%s %s-----\n", type, str); + return file_init_common(context, certs, data, flags, residue, lock, USE_DER); } static int -dump_pem_file(hx509_context context, const char *header, - FILE *f, const void *data, size_t size) +file_free(hx509_certs certs, void *data) { - const char *p = data; - size_t length; - char *line; - -#define ENCODE_LINE_LENGTH 54 - - pem_header(f, "BEGIN", header); - - while (size > 0) { - ssize_t l; - - length = size; - if (length > ENCODE_LINE_LENGTH) - length = ENCODE_LINE_LENGTH; - - l = base64_encode(p, length, &line); - if (l < 0) { - hx509_set_error_string(context, 0, ENOMEM, - "malloc - out of memory"); - return ENOMEM; - } - size -= length; - fprintf(f, "%s\n", line); - p += length; - free(line); - } - - pem_header(f, "END", header); - + struct ks_file *f = data; + hx509_certs_free(&f->certs); + free(f->fn); + free(f); return 0; } -static int -store_private_key(hx509_context context, FILE *f, hx509_private_key key) -{ - heim_octet_string data; - int ret; - - ret = _hx509_private_key_export(context, key, &data); - if (ret == 0) - dump_pem_file(context, _hx509_private_pem_name(key), f, - data.data, data.length); - free(data.data); - return ret; -} +struct store_ctx { + FILE *f; + outformat format; +}; static int store_func(hx509_context context, void *ctx, hx509_cert c) { - FILE *f = (FILE *)ctx; + struct store_ctx *sc = ctx; heim_octet_string data; int ret; @@ -682,11 +475,26 @@ store_func(hx509_context context, void *ctx, hx509_cert c) if (ret) return ret; - dump_pem_file(context, "CERTIFICATE", f, data.data, data.length); - free(data.data); - - if (_hx509_cert_private_key_exportable(c)) - store_private_key(context, f, _hx509_cert_private_key(c)); + switch (sc->format) { + case USE_DER: + fwrite(data.data, data.length, 1, sc->f); + free(data.data); + break; + case USE_PEM: + hx509_pem_write(context, "CERTIFICATE", NULL, sc->f, + data.data, data.length); + free(data.data); + if (_hx509_cert_private_key_exportable(c)) { + hx509_private_key key = _hx509_cert_private_key(c); + ret = _hx509_private_key_export(context, key, &data); + if (ret) + break; + hx509_pem_write(context, _hx509_private_pem_name(key), NULL, sc->f, + data.data, data.length); + free(data.data); + } + break; + } return 0; } @@ -696,18 +504,19 @@ file_store(hx509_context context, hx509_certs certs, void *data, int flags, hx509_lock lock) { struct ks_file *f = data; - FILE *fh; + struct store_ctx sc; int ret; - fh = fopen(f->fn, "w"); - if (fh == NULL) { + sc.f = fopen(f->fn, "w"); + if (sc.f == NULL) { hx509_set_error_string(context, 0, ENOENT, "Failed to open file %s for writing"); return ENOENT; } + sc.format = f->format; - ret = hx509_certs_iter(context, f->certs, store_func, fh); - fclose(fh); + ret = hx509_certs_iter(context, f->certs, store_func, &sc); + fclose(sc.f); return ret; } @@ -767,7 +576,7 @@ file_addkey(hx509_context context, static struct hx509_keyset_ops keyset_file = { "FILE", 0, - file_init, + file_init_pem, file_store, file_free, file_add, @@ -780,8 +589,43 @@ static struct hx509_keyset_ops keyset_file = { file_addkey }; +static struct hx509_keyset_ops keyset_pemfile = { + "PEM-FILE", + 0, + file_init_pem, + file_store, + file_free, + file_add, + NULL, + file_iter_start, + file_iter, + file_iter_end, + NULL, + file_getkeys, + file_addkey +}; + +static struct hx509_keyset_ops keyset_derfile = { + "DER-FILE", + 0, + file_init_der, + file_store, + file_free, + file_add, + NULL, + file_iter_start, + file_iter, + file_iter_end, + NULL, + file_getkeys, + file_addkey +}; + + void _hx509_ks_file_register(hx509_context context) { _hx509_ks_register(context, &keyset_file); + _hx509_ks_register(context, &keyset_pemfile); + _hx509_ks_register(context, &keyset_derfile); } diff --git a/source4/heimdal/lib/hx509/ks_keychain.c b/source4/heimdal/lib/hx509/ks_keychain.c index 2f0f72cd14..33c4d6774b 100644 --- a/source4/heimdal/lib/hx509/ks_keychain.c +++ b/source4/heimdal/lib/hx509/ks_keychain.c @@ -32,7 +32,7 @@ */ #include "hx_locl.h" -RCSID("$Id: ks_keychain.c 20945 2007-06-06 22:17:17Z lha $"); +RCSID("$Id: ks_keychain.c 21097 2007-06-16 07:00:49Z lha $"); #ifdef HAVE_FRAMEWORK_SECURITY @@ -254,6 +254,7 @@ set_private_key(hx509_context context, */ struct ks_keychain { + int anchors; SecKeychainRef keychain; }; @@ -263,7 +264,6 @@ keychain_init(hx509_context context, const char *residue, hx509_lock lock) { struct ks_keychain *ctx; - OSStatus ret; ctx = calloc(1, sizeof(*ctx)); if (ctx == NULL) { @@ -272,13 +272,20 @@ keychain_init(hx509_context context, } if (residue) { - if (strcasecmp(residue, "system") == 0) - residue = "/System/Library/Keychains/X509Anchors"; - - ret = SecKeychainOpen(residue, &ctx->keychain); - if (ret != noErr) { + if (strcasecmp(residue, "system-anchors") == 0) { + ctx->anchors = 1; + } else if (strncasecmp(residue, "FILE:", 5) == 0) { + OSStatus ret; + + ret = SecKeychainOpen(residue + 5, &ctx->keychain); + if (ret != noErr) { + hx509_set_error_string(context, 0, ENOENT, + "Failed to open %s", residue); + return ENOENT; + } + } else { hx509_set_error_string(context, 0, ENOENT, - "Failed to open %s", residue); + "Unknown subtype %s", residue); return ENOENT; } } @@ -307,6 +314,8 @@ keychain_free(hx509_certs certs, void *data) */ struct iter { + hx509_certs certs; + void *cursor; SecKeychainSearchRef searchRef; }; @@ -316,7 +325,6 @@ keychain_iter_start(hx509_context context, { struct ks_keychain *ctx = data; struct iter *iter; - OSStatus ret; iter = calloc(1, sizeof(*iter)); if (iter == NULL) { @@ -324,15 +332,66 @@ keychain_iter_start(hx509_context context, return ENOMEM; } - ret = SecKeychainSearchCreateFromAttributes(ctx->keychain, - kSecCertificateItemClass, - NULL, - &iter->searchRef); - if (ret) { - free(iter); - hx509_set_error_string(context, 0, ret, - "Failed to start search for attributes"); - return ENOMEM; + if (ctx->anchors) { + CFArrayRef anchors; + int ret; + int i; + + ret = hx509_certs_init(context, "MEMORY:ks-file-create", + 0, NULL, &iter->certs); + if (ret) { + free(iter); + return ret; + } + + ret = SecTrustCopyAnchorCertificates(&anchors); + if (ret != 0) { + hx509_certs_free(&iter->certs); + free(iter); + hx509_set_error_string(context, 0, ENOMEM, + "Can't get trust anchors from Keychain"); + return ENOMEM; + } + for (i = 0; i < CFArrayGetCount(anchors); i++) { + SecCertificateRef cr; + hx509_cert cert; + CSSM_DATA cssm; + + cr = (SecCertificateRef)CFArrayGetValueAtIndex(anchors, i); + + SecCertificateGetData(cr, &cssm); + + ret = hx509_cert_init_data(context, cssm.Data, cssm.Length, &cert); + if (ret) + continue; + + ret = hx509_certs_add(context, iter->certs, cert); + hx509_cert_free(cert); + } + CFRelease(anchors); + } + + if (iter->certs) { + int ret; + ret = hx509_certs_start_seq(context, iter->certs, &iter->cursor); + if (ret) { + hx509_certs_free(&iter->certs); + free(iter); + return ret; + } + } else { + OSStatus ret; + + ret = SecKeychainSearchCreateFromAttributes(ctx->keychain, + kSecCertificateItemClass, + NULL, + &iter->searchRef); + if (ret) { + free(iter); + hx509_set_error_string(context, 0, ret, + "Failed to start search for attributes"); + return ENOMEM; + } } *cursor = iter; @@ -349,15 +408,16 @@ keychain_iter(hx509_context context, { SecKeychainAttributeList *attrs = NULL; SecKeychainAttributeInfo attrInfo; - uint32 attrFormat = 0; + uint32 attrFormat[1] = { 0 }; SecKeychainItemRef itemRef; - SecItemAttr item; + SecItemAttr item[1]; struct iter *iter = cursor; - Certificate t; OSStatus ret; UInt32 len; void *ptr = NULL; - size_t size; + + if (iter->certs) + return hx509_certs_next_cert(context, iter->certs, iter->cursor, cert); *cert = NULL; @@ -371,26 +431,18 @@ keychain_iter(hx509_context context, * Pick out certificate and matching "keyid" */ - item = kSecPublicKeyHashItemAttr; + item[0] = kSecPublicKeyHashItemAttr; attrInfo.count = 1; - attrInfo.tag = &item; - attrInfo.format = &attrFormat; + attrInfo.tag = item; + attrInfo.format = attrFormat; ret = SecKeychainItemCopyAttributesAndData(itemRef, &attrInfo, NULL, &attrs, &len, &ptr); if (ret) return EINVAL; - - ret = decode_Certificate(ptr, len, &t, &size); - CFRelease(itemRef); - if (ret) { - hx509_set_error_string(context, 0, ret, "Failed to parse certificate"); - goto out; - } - ret = hx509_cert_init(context, &t, cert); - free_Certificate(&t); + ret = hx509_cert_init_data(context, ptr, len, cert); if (ret) goto out; @@ -449,7 +501,14 @@ keychain_iter_end(hx509_context context, { struct iter *iter = cursor; - CFRelease(iter->searchRef); + if (iter->certs) { + int ret; + ret = hx509_certs_end_seq(context, iter->certs, iter->cursor); + hx509_certs_free(&iter->certs); + } else { + CFRelease(iter->searchRef); + } + memset(iter, 0, sizeof(*iter)); free(iter); return 0; diff --git a/source4/heimdal/lib/hx509/ks_p11.c b/source4/heimdal/lib/hx509/ks_p11.c index 90c716213f..b899005b33 100644 --- a/source4/heimdal/lib/hx509/ks_p11.c +++ b/source4/heimdal/lib/hx509/ks_p11.c @@ -32,7 +32,7 @@ */ #include "hx_locl.h" -RCSID("$Id: ks_p11.c 20920 2007-06-05 05:47:06Z lha $"); +RCSID("$Id: ks_p11.c 21085 2007-06-13 06:39:53Z lha $"); #ifdef HAVE_DLFCN_H #include <dlfcn.h> #endif @@ -682,7 +682,6 @@ collect_cert(hx509_context context, { struct hx509_collector *collector = ptr; hx509_cert cert; - Certificate t; int ret; if ((CK_LONG)query[0].ulValueLen == -1 || @@ -691,16 +690,8 @@ collect_cert(hx509_context context, return 0; } - - ret = decode_Certificate(query[1].pValue, query[1].ulValueLen, - &t, NULL); - if (ret) { - hx509_clear_error_string(context); - return 0; - } - - ret = hx509_cert_init(context, &t, &cert); - free_Certificate(&t); + ret = hx509_cert_init_data(context, query[1].pValue, + query[1].ulValueLen, &cert); if (ret) return ret; diff --git a/source4/heimdal/lib/hx509/ks_p12.c b/source4/heimdal/lib/hx509/ks_p12.c index 5fddbd07de..12756e6c07 100644 --- a/source4/heimdal/lib/hx509/ks_p12.c +++ b/source4/heimdal/lib/hx509/ks_p12.c @@ -32,7 +32,7 @@ */ #include "hx_locl.h" -RCSID("$Id: ks_p12.c 20909 2007-06-05 03:09:13Z lha $"); +RCSID("$Id: ks_p12.c 21146 2007-06-18 21:37:25Z lha $"); struct ks_pkcs12 { hx509_certs certs; @@ -90,7 +90,7 @@ keyBag_parser(hx509_context context, &ki.privateKeyAlgorithm, NULL, &ki.privateKey, - &attr->attrValues); + os); free_PKCS8PrivateKeyInfo(&ki); return 0; } @@ -132,7 +132,6 @@ certBag_parser(hx509_context context, const PKCS12_Attributes *attrs) { heim_octet_string os; - Certificate t; hx509_cert cert; PKCS12_CertBag cb; int ret; @@ -154,16 +153,11 @@ certBag_parser(hx509_context context, if (ret) return ret; - ret = decode_Certificate(os.data, os.length, &t, NULL); + ret = hx509_cert_init_data(context, os.data, os.length, &cert); der_free_octet_string(&os); if (ret) return ret; - ret = hx509_cert_init(context, &t, &cert); - free_Certificate(&t); - if (ret) - return ret; - ret = _hx509_collector_certs_add(context, c, cert); if (ret) { hx509_cert_free(cert); @@ -437,7 +431,9 @@ p12_init(hx509_context context, out: _hx509_collector_free(c); - if (ret) { + if (ret && p12) { + if (p12->fn) + free(p12->fn); if (p12->certs) hx509_certs_free(&p12->certs); free(p12); diff --git a/source4/heimdal/lib/hx509/req.c b/source4/heimdal/lib/hx509/req.c index 34e3a4ea27..d7a85e1cec 100644 --- a/source4/heimdal/lib/hx509/req.c +++ b/source4/heimdal/lib/hx509/req.c @@ -33,7 +33,7 @@ #include "hx_locl.h" #include <pkcs10_asn1.h> -RCSID("$Id: req.c 20934 2007-06-06 15:30:02Z lha $"); +RCSID("$Id: req.c 21344 2007-06-26 14:22:34Z lha $"); struct hx509_request_data { hx509_name name; @@ -85,6 +85,18 @@ _hx509_request_set_name(hx509_context context, } int +_hx509_request_get_name(hx509_context context, + hx509_request req, + hx509_name *name) +{ + if (req->name == NULL) { + hx509_set_error_string(context, 0, EINVAL, "Request have no name"); + return EINVAL; + } + return hx509_name_copy(context, req->name, name); +} + +int _hx509_request_set_SubjectPublicKeyInfo(hx509_context context, hx509_request req, const SubjectPublicKeyInfo *key) @@ -94,6 +106,14 @@ _hx509_request_set_SubjectPublicKeyInfo(hx509_context context, } int +_hx509_request_get_SubjectPublicKeyInfo(hx509_context context, + hx509_request req, + SubjectPublicKeyInfo *key) +{ + return copy_SubjectPublicKeyInfo(&req->key, key); +} + +int _hx509_request_add_eku(hx509_context context, hx509_request req, const heim_oid *oid) @@ -215,3 +235,91 @@ out: return ret; } + +int +_hx509_request_parse(hx509_context context, + const char *path, + hx509_request *req) +{ + CertificationRequest r; + CertificationRequestInfo *rinfo; + hx509_name subject; + size_t len, size; + void *p; + int ret; + + if (strncmp(path, "PKCS10:", 7) != 0) { + hx509_set_error_string(context, 0, HX509_UNSUPPORTED_OPERATION, + "unsupport type in %s", path); + return HX509_UNSUPPORTED_OPERATION; + } + path += 7; + + /* XXX PEM request */ + + ret = _hx509_map_file(path, &p, &len, NULL); + if (ret) { + hx509_set_error_string(context, 0, ret, "Failed to map file %s", path); + return ret; + } + + ret = decode_CertificationRequest(p, len, &r, &size); + _hx509_unmap_file(p, len); + if (ret) { + hx509_set_error_string(context, 0, ret, "Failed to decode %s", path); + return ret; + } + + ret = _hx509_request_init(context, req); + if (ret) { + free_CertificationRequest(&r); + return ret; + } + + rinfo = &r.certificationRequestInfo; + + ret = _hx509_request_set_SubjectPublicKeyInfo(context, *req, + &rinfo->subjectPKInfo); + if (ret) { + free_CertificationRequest(&r); + _hx509_request_free(req); + return ret; + } + + ret = _hx509_name_from_Name(&rinfo->subject, &subject); + if (ret) { + free_CertificationRequest(&r); + _hx509_request_free(req); + return ret; + } + ret = _hx509_request_set_name(context, *req, subject); + hx509_name_free(&subject); + free_CertificationRequest(&r); + if (ret) { + _hx509_request_free(req); + return ret; + } + + return 0; +} + + +int +_hx509_request_print(hx509_context context, hx509_request req, FILE *f) +{ + int ret; + + if (req->name) { + char *subject; + ret = hx509_name_to_string(req->name, &subject); + if (ret) { + hx509_set_error_string(context, 0, ret, "Failed to print name"); + return ret; + } + fprintf(f, "name: %s\n", subject); + free(subject); + } + + return 0; +} + diff --git a/source4/heimdal/lib/hx509/revoke.c b/source4/heimdal/lib/hx509/revoke.c index 0d477945c8..ddcb17ee38 100644 --- a/source4/heimdal/lib/hx509/revoke.c +++ b/source4/heimdal/lib/hx509/revoke.c @@ -32,7 +32,7 @@ */ #include "hx_locl.h" -RCSID("$Id: revoke.c 20871 2007-06-03 21:22:51Z lha $"); +RCSID("$Id: revoke.c 21153 2007-06-18 21:55:46Z lha $"); struct revoke_crl { char *path; @@ -572,10 +572,10 @@ hx509_revoke_verify(hx509_context context, continue; } - for (i = 0; i < ocsp->ocsp.tbsResponseData.responses.len; i++) { + for (j = 0; j < ocsp->ocsp.tbsResponseData.responses.len; j++) { heim_octet_string os; - ret = der_heim_integer_cmp(&ocsp->ocsp.tbsResponseData.responses.val[i].certID.serialNumber, + ret = der_heim_integer_cmp(&ocsp->ocsp.tbsResponseData.responses.val[j].certID.serialNumber, &c->tbsCertificate.serialNumber); if (ret != 0) continue; @@ -594,13 +594,13 @@ hx509_revoke_verify(hx509_context context, ret = _hx509_verify_signature(context, NULL, - &ocsp->ocsp.tbsResponseData.responses.val[i].certID.hashAlgorithm, + &ocsp->ocsp.tbsResponseData.responses.val[j].certID.hashAlgorithm, &os, - &ocsp->ocsp.tbsResponseData.responses.val[i].certID.issuerKeyHash); + &ocsp->ocsp.tbsResponseData.responses.val[j].certID.issuerKeyHash); if (ret != 0) continue; - switch (ocsp->ocsp.tbsResponseData.responses.val[i].certStatus.element) { + switch (ocsp->ocsp.tbsResponseData.responses.val[j].certStatus.element) { case choice_OCSPCertStatus_good: break; case choice_OCSPCertStatus_revoked: @@ -609,13 +609,13 @@ hx509_revoke_verify(hx509_context context, } /* don't allow the update to be in the future */ - if (ocsp->ocsp.tbsResponseData.responses.val[i].thisUpdate > + if (ocsp->ocsp.tbsResponseData.responses.val[j].thisUpdate > now + context->ocsp_time_diff) continue; /* don't allow the next updte to be in the past */ - if (ocsp->ocsp.tbsResponseData.responses.val[i].nextUpdate) { - if (*ocsp->ocsp.tbsResponseData.responses.val[i].nextUpdate < now) + if (ocsp->ocsp.tbsResponseData.responses.val[j].nextUpdate) { + if (*ocsp->ocsp.tbsResponseData.responses.val[j].nextUpdate < now) continue; } else /* Should force a refetch, but can we ? */; @@ -1077,6 +1077,7 @@ hx509_crl_alloc(hx509_context context, hx509_crl *crl) if (ret) { free(*crl); *crl = NULL; + return ret; } (*crl)->expire = 0; return ret; |