summaryrefslogtreecommitdiff
path: root/source4/heimdal/lib/hx509
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2007-07-03 08:00:08 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 14:58:59 -0500
commitec0035c9b8e0690f3bc21f3de089c39eae660916 (patch)
tree183dddce1bc0704f0c137df03e611d255fb68e11 /source4/heimdal/lib/hx509
parent74b35321dc043188386d0305508b5276a5290d0d (diff)
downloadsamba-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.c186
-rw-r--r--source4/heimdal/lib/hx509/cms.c79
-rw-r--r--source4/heimdal/lib/hx509/crypto.c66
-rw-r--r--source4/heimdal/lib/hx509/file.c240
-rw-r--r--source4/heimdal/lib/hx509/hx509-private.h42
-rw-r--r--source4/heimdal/lib/hx509/hx509-protos.h57
-rw-r--r--source4/heimdal/lib/hx509/hx509.h19
-rw-r--r--source4/heimdal/lib/hx509/hx_locl.h6
-rw-r--r--source4/heimdal/lib/hx509/keyset.c23
-rw-r--r--source4/heimdal/lib/hx509/ks_file.c418
-rw-r--r--source4/heimdal/lib/hx509/ks_keychain.c129
-rw-r--r--source4/heimdal/lib/hx509/ks_p11.c15
-rw-r--r--source4/heimdal/lib/hx509/ks_p12.c16
-rw-r--r--source4/heimdal/lib/hx509/req.c110
-rw-r--r--source4/heimdal/lib/hx509/revoke.c19
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;