summaryrefslogtreecommitdiff
path: root/source4/heimdal/lib/hx509
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2007-06-13 05:44:24 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 14:53:18 -0500
commit91adebe749beb0dc23cacaea316cb2b724776aad (patch)
tree133d480f5b23b99fcf1149861136103dc4525cb1 /source4/heimdal/lib/hx509
parentf7110d928afd61cee203d07fd85968af993a327f (diff)
downloadsamba-91adebe749beb0dc23cacaea316cb2b724776aad.tar.gz
samba-91adebe749beb0dc23cacaea316cb2b724776aad.tar.bz2
samba-91adebe749beb0dc23cacaea316cb2b724776aad.zip
r23456: Update Samba4 to current lorikeet-heimdal.
Andrew Bartlett (This used to be commit ae0f81ab235c72cceb120bcdeb051a483cf3cc4f)
Diffstat (limited to 'source4/heimdal/lib/hx509')
-rw-r--r--source4/heimdal/lib/hx509/ca.c331
-rw-r--r--source4/heimdal/lib/hx509/cert.c236
-rw-r--r--source4/heimdal/lib/hx509/cms.c191
-rw-r--r--source4/heimdal/lib/hx509/collector.c21
-rw-r--r--source4/heimdal/lib/hx509/crmf.asn12
-rw-r--r--source4/heimdal/lib/hx509/crypto.c316
-rw-r--r--source4/heimdal/lib/hx509/env.c111
-rw-r--r--source4/heimdal/lib/hx509/error.c17
-rw-r--r--source4/heimdal/lib/hx509/file.c21
-rw-r--r--source4/heimdal/lib/hx509/hx509-private.h65
-rw-r--r--source4/heimdal/lib/hx509/hx509-protos.h168
-rw-r--r--source4/heimdal/lib/hx509/hx509.h17
-rw-r--r--source4/heimdal/lib/hx509/hx509_err.et5
-rw-r--r--source4/heimdal/lib/hx509/hx_locl.h21
-rw-r--r--source4/heimdal/lib/hx509/keyset.c16
-rw-r--r--source4/heimdal/lib/hx509/ks_dir.c2
-rw-r--r--source4/heimdal/lib/hx509/ks_file.c15
-rw-r--r--source4/heimdal/lib/hx509/ks_keychain.c487
-rw-r--r--source4/heimdal/lib/hx509/ks_mem.c3
-rw-r--r--source4/heimdal/lib/hx509/ks_null.c8
-rw-r--r--source4/heimdal/lib/hx509/ks_p11.c27
-rw-r--r--source4/heimdal/lib/hx509/ks_p12.c45
-rw-r--r--source4/heimdal/lib/hx509/lock.c2
-rw-r--r--source4/heimdal/lib/hx509/name.c240
-rw-r--r--source4/heimdal/lib/hx509/ocsp.asn12
-rw-r--r--source4/heimdal/lib/hx509/peer.c8
-rw-r--r--source4/heimdal/lib/hx509/pkcs10.asn12
-rw-r--r--source4/heimdal/lib/hx509/print.c401
-rw-r--r--source4/heimdal/lib/hx509/req.c4
-rw-r--r--source4/heimdal/lib/hx509/revoke.c265
-rw-r--r--source4/heimdal/lib/hx509/test_name.c44
31 files changed, 2728 insertions, 365 deletions
diff --git a/source4/heimdal/lib/hx509/ca.c b/source4/heimdal/lib/hx509/ca.c
index 1a5b4947be..0e48269aa4 100644
--- a/source4/heimdal/lib/hx509/ca.c
+++ b/source4/heimdal/lib/hx509/ca.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 Kungliga Tekniska Högskolan
+ * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -33,7 +33,7 @@
#include "hx_locl.h"
#include <pkinit_asn1.h>
-RCSID("$Id: ca.c,v 1.12 2007/01/05 18:40:46 lha Exp $");
+RCSID("$Id: ca.c 20904 2007-06-05 01:58:45Z lha $");
struct hx509_ca_tbs {
hx509_name subject;
@@ -47,10 +47,12 @@ struct hx509_ca_tbs {
unsigned int ca:1;
unsigned int key:1;
unsigned int serial:1;
+ unsigned int domaincontroller:1;
} flags;
time_t notBefore;
time_t notAfter;
int pathLenConstraint; /* both for CA and Proxy */
+ CRLDistributionPoints crldp;
};
int
@@ -66,6 +68,8 @@ hx509_ca_tbs_init(hx509_context context, hx509_ca_tbs *tbs)
(*tbs)->eku.len = 0;
(*tbs)->eku.val = NULL;
(*tbs)->pathLenConstraint = 0;
+ (*tbs)->crldp.len = 0;
+ (*tbs)->crldp.val = NULL;
return 0;
}
@@ -80,6 +84,7 @@ hx509_ca_tbs_free(hx509_ca_tbs *tbs)
free_GeneralNames(&(*tbs)->san);
free_ExtKeyUsage(&(*tbs)->eku);
der_free_heim_integer(&(*tbs)->serial);
+ free_CRLDistributionPoints(&(*tbs)->crldp);
hx509_name_free(&(*tbs)->subject);
@@ -114,6 +119,89 @@ hx509_ca_tbs_set_notAfter_lifetime(hx509_context context,
return hx509_ca_tbs_set_notAfter(context, tbs, time(NULL) + delta);
}
+static const struct units templatebits[] = {
+ { "ExtendedKeyUsage", HX509_CA_TEMPLATE_EKU },
+ { "KeyUsage", HX509_CA_TEMPLATE_KU },
+ { "SPKI", HX509_CA_TEMPLATE_SPKI },
+ { "notAfter", HX509_CA_TEMPLATE_NOTAFTER },
+ { "notBefore", HX509_CA_TEMPLATE_NOTBEFORE },
+ { "serial", HX509_CA_TEMPLATE_SERIAL },
+ { "subject", HX509_CA_TEMPLATE_SUBJECT },
+ { NULL, 0 }
+};
+
+const struct units *
+hx509_ca_tbs_template_units(void)
+{
+ return templatebits;
+}
+
+int
+hx509_ca_tbs_set_template(hx509_context context,
+ hx509_ca_tbs tbs,
+ int flags,
+ hx509_cert cert)
+{
+ int ret;
+
+ if (flags & HX509_CA_TEMPLATE_SUBJECT) {
+ if (tbs->subject)
+ hx509_name_free(&tbs->subject);
+ ret = hx509_cert_get_subject(cert, &tbs->subject);
+ if (ret) {
+ hx509_set_error_string(context, 0, ret,
+ "Failed to get subject from template");
+ return ret;
+ }
+ }
+ if (flags & HX509_CA_TEMPLATE_SERIAL) {
+ der_free_heim_integer(&tbs->serial);
+ ret = hx509_cert_get_serialnumber(cert, &tbs->serial);
+ tbs->flags.serial = !ret;
+ if (ret) {
+ hx509_set_error_string(context, 0, ret,
+ "Failed to copy serial number");
+ return ret;
+ }
+ }
+ if (flags & HX509_CA_TEMPLATE_NOTBEFORE)
+ tbs->notBefore = hx509_cert_get_notBefore(cert);
+ if (flags & HX509_CA_TEMPLATE_NOTAFTER)
+ tbs->notAfter = hx509_cert_get_notAfter(cert);
+ if (flags & HX509_CA_TEMPLATE_SPKI) {
+ free_SubjectPublicKeyInfo(&tbs->spki);
+ ret = hx509_cert_get_SPKI(cert, &tbs->spki);
+ tbs->flags.key = !ret;
+ if (ret) {
+ hx509_set_error_string(context, 0, ret, "Failed to copy SPKI");
+ return ret;
+ }
+ }
+ if (flags & HX509_CA_TEMPLATE_KU) {
+ KeyUsage ku;
+ ret = _hx509_cert_get_keyusage(context, cert, &ku);
+ if (ret)
+ return ret;
+ tbs->key_usage = KeyUsage2int(ku);
+ }
+ if (flags & HX509_CA_TEMPLATE_EKU) {
+ ExtKeyUsage eku;
+ int i;
+ ret = _hx509_cert_get_eku(context, cert, &eku);
+ if (ret)
+ return ret;
+ for (i = 0; i < eku.len; i++) {
+ ret = hx509_ca_tbs_add_eku(context, tbs, &eku.val[i]);
+ if (ret) {
+ free_ExtKeyUsage(&eku);
+ return ret;
+ }
+ }
+ free_ExtKeyUsage(&eku);
+ }
+ return 0;
+}
+
int
hx509_ca_tbs_set_ca(hx509_context context,
hx509_ca_tbs tbs,
@@ -136,6 +224,14 @@ hx509_ca_tbs_set_proxy(hx509_context context,
int
+hx509_ca_tbs_set_domaincontroller(hx509_context context,
+ hx509_ca_tbs tbs)
+{
+ tbs->flags.domaincontroller = 1;
+ return 0;
+}
+
+int
hx509_ca_tbs_set_spki(hx509_context context,
hx509_ca_tbs tbs,
const SubjectPublicKeyInfo *spki)
@@ -160,25 +256,123 @@ hx509_ca_tbs_set_serialnumber(hx509_context context,
}
int
-hx509_ca_tbs_add_eku(hx509_context contex,
+hx509_ca_tbs_add_eku(hx509_context context,
hx509_ca_tbs tbs,
const heim_oid *oid)
{
void *ptr;
int ret;
+ unsigned i;
+
+ /* search for duplicates */
+ for (i = 0; i < tbs->eku.len; i++) {
+ if (der_heim_oid_cmp(oid, &tbs->eku.val[i]) == 0)
+ return 0;
+ }
ptr = realloc(tbs->eku.val, sizeof(tbs->eku.val[0]) * (tbs->eku.len + 1));
- if (ptr == NULL)
+ if (ptr == NULL) {
+ hx509_set_error_string(context, 0, ENOMEM, "out of memory");
return ENOMEM;
+ }
tbs->eku.val = ptr;
ret = der_copy_oid(oid, &tbs->eku.val[tbs->eku.len]);
- if (ret)
+ if (ret) {
+ hx509_set_error_string(context, 0, ret, "out of memory");
return ret;
+ }
tbs->eku.len += 1;
return 0;
}
int
+hx509_ca_tbs_add_crl_dp_uri(hx509_context context,
+ hx509_ca_tbs tbs,
+ const char *uri,
+ hx509_name issuername)
+{
+ DistributionPoint dp;
+ int ret;
+
+ memset(&dp, 0, sizeof(dp));
+
+ dp.distributionPoint = ecalloc(1, sizeof(*dp.distributionPoint));
+
+ {
+ DistributionPointName name;
+ GeneralName gn;
+ size_t size;
+
+ name.element = choice_DistributionPointName_fullName;
+ name.u.fullName.len = 1;
+ name.u.fullName.val = &gn;
+
+ gn.element = choice_GeneralName_uniformResourceIdentifier;
+ gn.u.uniformResourceIdentifier = rk_UNCONST(uri);
+
+ ASN1_MALLOC_ENCODE(DistributionPointName,
+ dp.distributionPoint->data,
+ dp.distributionPoint->length,
+ &name, &size, ret);
+ if (ret) {
+ hx509_set_error_string(context, 0, ret,
+ "Failed to encoded DistributionPointName");
+ goto out;
+ }
+ if (dp.distributionPoint->length != size)
+ _hx509_abort("internal ASN.1 encoder error");
+ }
+
+ if (issuername) {
+#if 1
+ hx509_set_error_string(context, 0, EINVAL,
+ "CRLDistributionPoints.name.issuername not yet supported");
+ return EINVAL;
+#else
+ GeneralNames *crlissuer;
+ GeneralName gn;
+ Name n;
+
+ crlissuer = calloc(1, sizeof(*crlissuer));
+ if (crlissuer == NULL) {
+ return ENOMEM;
+ }
+ memset(&gn, 0, sizeof(gn));
+
+ gn.element = choice_GeneralName_directoryName;
+ ret = hx509_name_to_Name(issuername, &n);
+ if (ret) {
+ hx509_set_error_string(context, 0, ret, "out of memory");
+ goto out;
+ }
+
+ gn.u.directoryName.element = n.element;
+ gn.u.directoryName.u.rdnSequence = n.u.rdnSequence;
+
+ ret = add_GeneralNames(&crlissuer, &gn);
+ free_Name(&n);
+ if (ret) {
+ hx509_set_error_string(context, 0, ret, "out of memory");
+ goto out;
+ }
+
+ dp.cRLIssuer = &crlissuer;
+#endif
+ }
+
+ ret = add_CRLDistributionPoints(&tbs->crldp, &dp);
+ if (ret) {
+ hx509_set_error_string(context, 0, ret, "out of memory");
+ goto out;
+ }
+
+out:
+ free_DistributionPoint(&dp);
+
+ return ret;
+}
+
+int
hx509_ca_tbs_add_san_otherName(hx509_context context,
hx509_ca_tbs tbs,
const heim_oid *oid,
@@ -282,6 +476,58 @@ out:
return ret;
}
+/*
+ *
+ */
+
+static int
+add_utf8_san(hx509_context context,
+ hx509_ca_tbs tbs,
+ const heim_oid *oid,
+ const char *string)
+{
+ const PKIXXmppAddr ustring = (const PKIXXmppAddr)string;
+ heim_octet_string os;
+ size_t size;
+ int ret;
+
+ os.length = 0;
+ os.data = NULL;
+
+ ASN1_MALLOC_ENCODE(PKIXXmppAddr, os.data, os.length, &ustring, &size, ret);
+ if (ret) {
+ hx509_set_error_string(context, 0, ret, "Out of memory");
+ goto out;
+ }
+ if (size != os.length)
+ _hx509_abort("internal ASN.1 encoder error");
+
+ ret = hx509_ca_tbs_add_san_otherName(context,
+ tbs,
+ oid,
+ &os);
+ free(os.data);
+out:
+ return ret;
+}
+
+int
+hx509_ca_tbs_add_san_ms_upn(hx509_context context,
+ hx509_ca_tbs tbs,
+ const char *principal)
+{
+ return add_utf8_san(context, tbs, oid_id_pkinit_ms_san(), principal);
+}
+
+int
+hx509_ca_tbs_add_san_jid(hx509_context context,
+ hx509_ca_tbs tbs,
+ const char *jid)
+{
+ return add_utf8_san(context, tbs, oid_id_pkix_on_xmppAddr(), jid);
+}
+
+
int
hx509_ca_tbs_add_san_hostname(hx509_context context,
hx509_ca_tbs tbs,
@@ -321,6 +567,14 @@ hx509_ca_tbs_set_subject(hx509_context context,
return hx509_name_copy(context, subject, &tbs->subject);
}
+int
+hx509_ca_tbs_subject_expand(hx509_context context,
+ hx509_ca_tbs tbs,
+ hx509_env env)
+{
+ return hx509_name_expand(context, tbs->subject, env);
+}
+
static int
add_extension(hx509_context context,
TBSCertificate *tbsc,
@@ -410,7 +664,7 @@ ca_sign(hx509_context context,
time_t notAfter;
unsigned key_usage;
- sigalg = hx509_signature_rsa_with_sha1();
+ sigalg = _hx509_crypto_default_sig_alg;
memset(&c, 0, sizeof(c));
@@ -439,6 +693,7 @@ ca_sign(hx509_context context,
KeyUsage ku;
memset(&ku, 0, sizeof(ku));
ku.keyCertSign = 1;
+ ku.cRLSign = 1;
key_usage |= KeyUsage2int(ku);
}
@@ -453,16 +708,25 @@ ca_sign(hx509_context context,
hx509_set_error_string(context, 0, ret, "No public key set");
return ret;
}
- if (tbs->subject == NULL && !tbs->flags.proxy) {
- ret = EINVAL;
- hx509_set_error_string(context, 0, ret, "No subject name set");
- return ret;
+ /*
+ * Don't put restrictions on proxy certificate's subject name, it
+ * will be generated below.
+ */
+ if (!tbs->flags.proxy) {
+ if (tbs->subject == NULL) {
+ hx509_set_error_string(context, 0, EINVAL, "No subject name set");
+ return EINVAL;
+ }
+ if (hx509_name_is_null_p(tbs->subject) && tbs->san.len == 0) {
+ hx509_set_error_string(context, 0, EINVAL,
+ "NULL subject and no SubjectAltNames");
+ return EINVAL;
+ }
}
if (tbs->flags.ca && tbs->flags.proxy) {
- ret = EINVAL;
- hx509_set_error_string(context, 0, ret, "Can't be proxy and CA "
+ hx509_set_error_string(context, 0, EINVAL, "Can't be proxy and CA "
"at the same time");
- return ret;
+ return EINVAL;
}
if (tbs->flags.proxy) {
if (tbs->san.len > 0) {
@@ -549,6 +813,22 @@ ca_sign(hx509_context context,
goto out;
}
+ /* Add the text BMP string Domaincontroller to the cert */
+ if (tbs->flags.domaincontroller) {
+ data.data = rk_UNCONST("\x1e\x20\x00\x44\x00\x6f\x00\x6d"
+ "\x00\x61\x00\x69\x00\x6e\x00\x43"
+ "\x00\x6f\x00\x6e\x00\x74\x00\x72"
+ "\x00\x6f\x00\x6c\x00\x6c\x00\x65"
+ "\x00\x72");
+ data.length = 34;
+
+ ret = add_extension(context, tbsc, 0,
+ oid_id_ms_cert_enroll_domaincontroller(),
+ &data);
+ if (ret)
+ goto out;
+ }
+
/* add KeyUsage */
{
KeyUsage ku;
@@ -561,7 +841,7 @@ ca_sign(hx509_context context,
}
if (size != data.length)
_hx509_abort("internal ASN.1 encoder error");
- ret = add_extension(context, tbsc, 1,
+ ret = add_extension(context, tbsc, 1,
oid_id_x509_ce_keyUsage(), &data);
free(data.data);
if (ret)
@@ -678,7 +958,8 @@ ca_sign(hx509_context context,
}
if (size != data.length)
_hx509_abort("internal ASN.1 encoder error");
- ret = add_extension(context, tbsc, 0,
+ /* Critical if this is a CA */
+ ret = add_extension(context, tbsc, tbs->flags.ca,
oid_id_x509_ce_basicConstraints(),
&data);
free(data.data);
@@ -728,6 +1009,23 @@ ca_sign(hx509_context context,
goto out;
}
+ if (tbs->crldp.len) {
+
+ ASN1_MALLOC_ENCODE(CRLDistributionPoints, data.data, data.length,
+ &tbs->crldp, &size, ret);
+ if (ret) {
+ hx509_set_error_string(context, 0, ret, "Out of memory");
+ goto out;
+ }
+ if (size != data.length)
+ _hx509_abort("internal ASN.1 encoder error");
+ ret = add_extension(context, tbsc, FALSE,
+ oid_id_x509_ce_cRLDistributionPoints(),
+ &data);
+ free(data.data);
+ if (ret)
+ goto out;
+ }
ASN1_MALLOC_ENCODE(TBSCertificate, data.data, data.length,tbsc, &size, ret);
if (ret) {
@@ -772,11 +1070,13 @@ get_AuthorityKeyIdentifier(hx509_context context,
if (ret == 0) {
ai->keyIdentifier = calloc(1, sizeof(*ai->keyIdentifier));
if (ai->keyIdentifier == NULL) {
+ free_SubjectKeyIdentifier(&si);
ret = ENOMEM;
hx509_set_error_string(context, 0, ret, "Out of memory");
goto out;
}
ret = der_copy_octet_string(&si, ai->keyIdentifier);
+ free_SubjectKeyIdentifier(&si);
if (ret) {
hx509_set_error_string(context, 0, ret, "Out of memory");
goto out;
@@ -818,6 +1118,7 @@ get_AuthorityKeyIdentifier(hx509_context context,
goto out;
}
+ memset(&gn, 0, sizeof(gn));
gn.element = choice_GeneralName_directoryName;
gn.u.directoryName.element =
choice_GeneralName_directoryName_rdnSequence;
diff --git a/source4/heimdal/lib/hx509/cert.c b/source4/heimdal/lib/hx509/cert.c
index f84c61a798..27b17a0204 100644
--- a/source4/heimdal/lib/hx509/cert.c
+++ b/source4/heimdal/lib/hx509/cert.c
@@ -32,8 +32,9 @@
*/
#include "hx_locl.h"
-RCSID("$Id: cert.c,v 1.82 2007/01/09 10:52:03 lha Exp $");
+RCSID("$Id: cert.c 20915 2007-06-05 03:58:56Z lha $");
#include "crypto-headers.h"
+#include <rtbl.h>
struct hx509_verify_ctx_data {
hx509_certs trust_anchors;
@@ -102,11 +103,13 @@ hx509_context_init(hx509_context *context)
if (*context == NULL)
return ENOMEM;
+ _hx509_ks_null_register(*context);
_hx509_ks_mem_register(*context);
_hx509_ks_file_register(*context);
_hx509_ks_pkcs12_register(*context);
_hx509_ks_pkcs11_register(*context);
_hx509_ks_dir_register(*context);
+ _hx509_ks_keychain_register(*context);
ENGINE_add_conf_module();
OpenSSL_add_all_algorithms();
@@ -116,6 +119,11 @@ hx509_context_init(hx509_context *context)
initialize_hx_error_table_r(&(*context)->et_list);
initialize_asn1_error_table_r(&(*context)->et_list);
+#ifdef HX509_DEFAULT_ANCHORS
+ (void)hx509_certs_init(*context, HX509_DEFAULT_ANCHORS, 0,
+ NULL, &(*context)->default_trust_anchors);
+#endif
+
return 0;
}
@@ -138,6 +146,9 @@ hx509_context_free(hx509_context *context)
}
(*context)->ks_num_ops = 0;
free_error_table ((*context)->et_list);
+ if ((*context)->querystat)
+ free((*context)->querystat);
+ memset(*context, 0, sizeof(**context));
free(*context);
*context = NULL;
}
@@ -836,7 +847,7 @@ find_parent(hx509_context context,
hx509_set_error_string(context, 0, HX509_ISSUER_NOT_FOUND,
"Failed to find issuer for "
- "certificate with subject: %s", str);
+ "certificate with subject: '%s'", str);
free(str);
}
return HX509_ISSUER_NOT_FOUND;
@@ -847,7 +858,9 @@ find_parent(hx509_context context,
*/
static int
-is_proxy_cert(hx509_context context, const Certificate *cert, ProxyCertInfo *rinfo)
+is_proxy_cert(hx509_context context,
+ const Certificate *cert,
+ ProxyCertInfo *rinfo)
{
ProxyCertInfo info;
const Extension *e;
@@ -876,7 +889,9 @@ is_proxy_cert(hx509_context context, const Certificate *cert, ProxyCertInfo *rin
hx509_clear_error_string(context);
return HX509_EXTRA_DATA_AFTER_STRUCTURE;
}
- if (rinfo)
+ if (rinfo == NULL)
+ free_ProxyCertInfo(&info);
+ else
*rinfo = info;
return 0;
@@ -969,8 +984,10 @@ _hx509_calculate_path(hx509_context context,
current = parent;
if (path->len > max_depth) {
+ hx509_cert_free(current);
hx509_set_error_string(context, 0, HX509_PATH_TOO_LONG,
- "Path too long while bulding certificate chain");
+ "Path too long while bulding "
+ "certificate chain");
return HX509_PATH_TOO_LONG;
}
}
@@ -1065,6 +1082,25 @@ hx509_cert_get_serialnumber(hx509_cert p, heim_integer *i)
return der_copy_heim_integer(&p->data->tbsCertificate.serialNumber, i);
}
+time_t
+hx509_cert_get_notBefore(hx509_cert p)
+{
+ return _hx509_Time2time_t(&p->data->tbsCertificate.validity.notBefore);
+}
+
+time_t
+hx509_cert_get_notAfter(hx509_cert p)
+{
+ return _hx509_Time2time_t(&p->data->tbsCertificate.validity.notAfter);
+}
+
+int
+hx509_cert_get_SPKI(hx509_cert p, SubjectPublicKeyInfo *spki)
+{
+ return copy_SubjectPublicKeyInfo(&p->data->tbsCertificate.subjectPublicKeyInfo,
+ spki);
+}
+
hx509_private_key
_hx509_cert_private_key(hx509_cert p)
{
@@ -1349,7 +1385,7 @@ match_tree(const GeneralSubtrees *t, const Certificate *c, int *match)
{
GeneralName certname;
-
+ memset(&certname, 0, sizeof(certname));
certname.element = choice_GeneralName_directoryName;
certname.u.directoryName.element =
c->tbsCertificate.subject.element;
@@ -1435,6 +1471,7 @@ hx509_verify_path(hx509_context context,
int ret, i, proxy_cert_depth;
enum certtype type;
Name proxy_issuer;
+ hx509_certs anchors = NULL;
memset(&proxy_issuer, 0, sizeof(proxy_issuer));
@@ -1449,11 +1486,24 @@ hx509_verify_path(hx509_context context,
ctx->time_now = time(NULL);
/*
+ *
+ */
+ 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;
+
+ /*
* Calculate the path from the certificate user presented to the
* to an anchor.
*/
ret = _hx509_calculate_path(context, 0, ctx->time_now,
- ctx->trust_anchors, ctx->max_depth,
+ anchors, ctx->max_depth,
cert, pool, &path);
if (ret)
goto out;
@@ -1775,6 +1825,7 @@ hx509_verify_path(hx509_context context,
}
out:
+ hx509_certs_free(&anchors);
free_Name(&proxy_issuer);
free_name_constraints(&nc);
_hx509_path_free(&path);
@@ -2030,6 +2081,8 @@ _hx509_query_match_cert(hx509_context context, const hx509_query *q, hx509_cert
{
Certificate *c = _hx509_get_cert(cert);
+ _hx509_query_statistic(context, 1, q);
+
if ((q->match & HX509_QUERY_FIND_ISSUER_CERT) &&
_hx509_cert_is_parent_cmp(q->subject, c, 0) != 0)
return 0;
@@ -2154,6 +2207,139 @@ _hx509_query_match_cert(hx509_context context, const hx509_query *q, hx509_cert
return 1;
}
+void
+hx509_query_statistic_file(hx509_context context, const char *fn)
+{
+ if (context->querystat)
+ free(context->querystat);
+ context->querystat = strdup(fn);
+}
+
+void
+_hx509_query_statistic(hx509_context context, int type, const hx509_query *q)
+{
+ FILE *f;
+ if (context->querystat == NULL)
+ return;
+ f = fopen(context->querystat, "a");
+ if (f == NULL)
+ return;
+ fprintf(f, "%d %d\n", type, q->match);
+ fclose(f);
+}
+
+static const char *statname[] = {
+ "find issuer cert",
+ "match serialnumber",
+ "match issuer name",
+ "match subject name",
+ "match subject key id",
+ "match issuer id",
+ "private key",
+ "ku encipherment",
+ "ku digitalsignature",
+ "ku keycertsign",
+ "ku crlsign",
+ "ku nonrepudiation",
+ "ku keyagreement",
+ "ku dataencipherment",
+ "anchor",
+ "match certificate",
+ "match local key id",
+ "no match path",
+ "match friendly name",
+ "match function",
+ "match key hash sha1",
+ "match time"
+};
+
+struct stat_el {
+ unsigned long stats;
+ unsigned int index;
+};
+
+
+static int
+stat_sort(const void *a, const void *b)
+{
+ const struct stat_el *ae = a;
+ const struct stat_el *be = b;
+ return be->stats - ae->stats;
+}
+
+void
+hx509_query_unparse_stats(hx509_context context, int printtype, FILE *out)
+{
+ rtbl_t t;
+ FILE *f;
+ int type, mask, i, num;
+ unsigned long multiqueries = 0, totalqueries = 0;
+ struct stat_el stats[32];
+
+ if (context->querystat == NULL)
+ return;
+ f = fopen(context->querystat, "r");
+ if (f == NULL) {
+ fprintf(out, "No statistic file %s: %s.\n",
+ context->querystat, strerror(errno));
+ return;
+ }
+
+ for (i = 0; i < sizeof(stats)/sizeof(stats[0]); i++) {
+ stats[i].index = i;
+ stats[i].stats = 0;
+ }
+
+ while (fscanf(f, "%d %d\n", &type, &mask) == 2) {
+ if (type != printtype)
+ continue;
+ num = i = 0;
+ while (mask && i < sizeof(stats)/sizeof(stats[0])) {
+ if (mask & 1) {
+ stats[i].stats++;
+ num++;
+ }
+ mask = mask >>1 ;
+ i++;
+ }
+ if (num > 1)
+ multiqueries++;
+ totalqueries++;
+ }
+ fclose(f);
+
+ qsort(stats, sizeof(stats)/sizeof(stats[0]), sizeof(stats[0]), stat_sort);
+
+ t = rtbl_create();
+ if (t == NULL)
+ errx(1, "out of memory");
+
+ rtbl_set_separator (t, " ");
+
+ rtbl_add_column_by_id (t, 0, "Name", 0);
+ rtbl_add_column_by_id (t, 1, "Counter", 0);
+
+
+ for (i = 0; i < sizeof(stats)/sizeof(stats[0]); i++) {
+ char str[10];
+
+ if (stats[i].index < sizeof(statname)/sizeof(statname[0]))
+ rtbl_add_column_entry_by_id (t, 0, statname[stats[i].index]);
+ else {
+ snprintf(str, sizeof(str), "%d", stats[i].index);
+ rtbl_add_column_entry_by_id (t, 0, str);
+ }
+ snprintf(str, sizeof(str), "%lu", stats[i].stats);
+ rtbl_add_column_entry_by_id (t, 1, str);
+ }
+
+ rtbl_format(t, out);
+ rtbl_destroy(t);
+
+ fprintf(out, "\nQueries: multi %lu total %lu\n",
+ multiqueries, totalqueries);
+}
+
int
hx509_cert_check_eku(hx509_context context, hx509_cert cert,
const heim_oid *eku, int allow_any_eku)
@@ -2212,3 +2398,39 @@ _hx509_cert_get_keyusage(hx509_context context,
return ret;
return 0;
}
+
+int
+_hx509_cert_get_eku(hx509_context context,
+ hx509_cert cert,
+ ExtKeyUsage *e)
+{
+ int ret;
+
+ memset(e, 0, sizeof(*e));
+
+ ret = find_extension_eku(_hx509_get_cert(cert), e);
+ if (ret && ret != HX509_EXTENSION_NOT_FOUND) {
+ hx509_clear_error_string(context);
+ return ret;
+ }
+ return 0;
+}
+
+int
+hx509_cert_binary(hx509_context context, hx509_cert c, heim_octet_string *os)
+{
+ size_t size;
+ int ret;
+
+ os->data = NULL;
+ os->length = 0;
+
+ ASN1_MALLOC_ENCODE(Certificate, os->data, os->length,
+ _hx509_get_cert(c), &size, ret);
+ if (ret)
+ return ret;
+ if (os->length != size)
+ _hx509_abort("internal ASN.1 encoder error");
+
+ return ret;
+}
diff --git a/source4/heimdal/lib/hx509/cms.c b/source4/heimdal/lib/hx509/cms.c
index 4ed70b8f84..29ca80e194 100644
--- a/source4/heimdal/lib/hx509/cms.c
+++ b/source4/heimdal/lib/hx509/cms.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 - 2006 Kungliga Tekniska Högskolan
+ * Copyright (c) 2003 - 2007 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -32,7 +32,7 @@
*/
#include "hx_locl.h"
-RCSID("$Id: cms.c,v 1.48 2007/01/08 18:45:03 lha Exp $");
+RCSID("$Id: cms.c 20937 2007-06-06 20:50:55Z 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)
@@ -302,6 +302,11 @@ hx509_cms_unenvelope(hx509_context context,
goto out;
}
enccontent = encryptedContent;
+ } else if (encryptedContent != NULL) {
+ ret = HX509_CMS_NO_DATA_AVAILABLE;
+ hx509_set_error_string(context, 0, ret,
+ "Both internal and external encrypted data");
+ goto out;
}
cert = NULL;
@@ -423,6 +428,7 @@ out:
int
hx509_cms_envelope_1(hx509_context context,
+ int flags,
hx509_cert cert,
const void *data,
size_t length,
@@ -621,6 +627,7 @@ hx509_cms_verify_signed(hx509_context context,
hx509_verify_ctx ctx,
const void *data,
size_t length,
+ const heim_octet_string *signedContent,
hx509_certs store,
heim_oid *contentType,
heim_octet_string *content,
@@ -648,12 +655,20 @@ hx509_cms_verify_signed(hx509_context context,
goto out;
}
- if (sd.encapContentInfo.eContent == NULL) {
+ if (sd.encapContentInfo.eContent == NULL && signedContent == NULL) {
ret = HX509_CMS_NO_DATA_AVAILABLE;
hx509_set_error_string(context, 0, ret,
"No content data in SignedData");
goto out;
}
+ if (sd.encapContentInfo.eContent && signedContent) {
+ ret = HX509_CMS_NO_DATA_AVAILABLE;
+ hx509_set_error_string(context, 0, ret,
+ "Both external and internal SignedData");
+ goto out;
+ }
+ if (sd.encapContentInfo.eContent)
+ signedContent = sd.encapContentInfo.eContent;
ret = hx509_certs_init(context, "MEMORY:cms-cert-buffer",
0, NULL, &certs);
@@ -739,7 +754,7 @@ hx509_cms_verify_signed(hx509_context context,
ret = _hx509_verify_signature(context,
NULL,
&signer_info->digestAlgorithm,
- sd.encapContentInfo.eContent,
+ signedContent,
&os);
der_free_octet_string(&os);
if (ret) {
@@ -801,7 +816,7 @@ hx509_cms_verify_signed(hx509_context context,
_hx509_abort("internal ASN.1 encoder error");
} else {
- signed_data = sd.encapContentInfo.eContent;
+ signed_data = rk_UNCONST(signedContent);
match_oid = oid_id_pkcs7_data();
}
@@ -824,7 +839,7 @@ hx509_cms_verify_signed(hx509_context context,
"Failed to verify sigature in "
"CMS SignedData");
}
- if (signed_data != sd.encapContentInfo.eContent) {
+ if (signed_data != signedContent) {
der_free_octet_string(signed_data);
free(signed_data);
}
@@ -861,14 +876,14 @@ hx509_cms_verify_signed(hx509_context context,
goto out;
}
- content->data = malloc(sd.encapContentInfo.eContent->length);
+ content->data = malloc(signedContent->length);
if (content->data == NULL) {
hx509_clear_error_string(context);
ret = ENOMEM;
goto out;
}
- content->length = sd.encapContentInfo.eContent->length;
- memcpy(content->data,sd.encapContentInfo.eContent->data,content->length);
+ content->length = signedContent->length;
+ memcpy(content->data, signedContent->data, content->length);
out:
free_SignedData(&sd);
@@ -884,38 +899,6 @@ out:
return ret;
}
-int
-_hx509_set_digest_alg(DigestAlgorithmIdentifier *id,
- const heim_oid *oid,
- void *param, size_t length)
-{
- int ret;
- if (param) {
- id->parameters = malloc(sizeof(*id->parameters));
- if (id->parameters == NULL)
- return ENOMEM;
- id->parameters->data = malloc(length);
- if (id->parameters->data == NULL) {
- free(id->parameters);
- id->parameters = NULL;
- return ENOMEM;
- }
- memcpy(id->parameters->data, param, length);
- id->parameters->length = length;
- } else
- id->parameters = NULL;
- ret = der_copy_oid(oid, &id->algorithm);
- if (ret) {
- if (id->parameters) {
- free(id->parameters->data);
- free(id->parameters);
- id->parameters = NULL;
- }
- return ret;
- }
- return 0;
-}
-
static int
add_one_attribute(Attribute **attr,
unsigned int *len,
@@ -950,6 +933,7 @@ add_one_attribute(Attribute **attr,
int
hx509_cms_create_signed_1(hx509_context context,
+ int flags,
const heim_oid *eContentType,
const void *data, size_t length,
const AlgorithmIdentifier *digest_alg,
@@ -962,7 +946,7 @@ hx509_cms_create_signed_1(hx509_context context,
AlgorithmIdentifier digest;
hx509_name name;
SignerInfo *signer_info;
- heim_octet_string buf;
+ heim_octet_string buf, content, sigdata = { 0, NULL };
SignedData sd;
int ret;
size_t size;
@@ -973,6 +957,9 @@ hx509_cms_create_signed_1(hx509_context context,
memset(&path, 0, sizeof(path));
memset(&digest, 0, sizeof(digest));
+ content.data = rk_UNCONST(data);
+ content.length = length;
+
if (_hx509_cert_private_key(cert) == NULL) {
hx509_set_error_string(context, 0, HX509_PRIVATE_KEY_MISSING,
"Private key missing for signing");
@@ -992,22 +979,29 @@ hx509_cms_create_signed_1(hx509_context context,
sd.version = CMSVersion_v3;
+ if (eContentType == NULL)
+ eContentType = oid_id_pkcs7_data();
+
der_copy_oid(eContentType, &sd.encapContentInfo.eContentType);
- ALLOC(sd.encapContentInfo.eContent, 1);
- if (sd.encapContentInfo.eContent == NULL) {
- hx509_clear_error_string(context);
- ret = ENOMEM;
- goto out;
- }
- sd.encapContentInfo.eContent->data = malloc(length);
- if (sd.encapContentInfo.eContent->data == NULL) {
- hx509_clear_error_string(context);
- ret = ENOMEM;
- goto out;
+ /* */
+ if ((flags & HX509_CMS_SIGATURE_DETACHED) == 0) {
+ ALLOC(sd.encapContentInfo.eContent, 1);
+ if (sd.encapContentInfo.eContent == NULL) {
+ hx509_clear_error_string(context);
+ ret = ENOMEM;
+ goto out;
+ }
+
+ sd.encapContentInfo.eContent->data = malloc(length);
+ if (sd.encapContentInfo.eContent->data == NULL) {
+ hx509_clear_error_string(context);
+ ret = ENOMEM;
+ goto out;
+ }
+ memcpy(sd.encapContentInfo.eContent->data, data, length);
+ sd.encapContentInfo.eContent->length = length;
}
- memcpy(sd.encapContentInfo.eContent->data, data, length);
- sd.encapContentInfo.eContent->length = length;
ALLOC_SEQ(&sd.signerInfos, 1);
if (sd.signerInfos.val == NULL) {
@@ -1029,39 +1023,43 @@ hx509_cms_create_signed_1(hx509_context context,
signer_info->signedAttrs = NULL;
signer_info->unsignedAttrs = NULL;
- ALLOC(signer_info->signedAttrs, 1);
- if (signer_info->signedAttrs == NULL) {
- ret = ENOMEM;
+
+ ret = copy_AlgorithmIdentifier(&digest, &signer_info->digestAlgorithm);
+ if (ret) {
+ hx509_clear_error_string(context);
goto out;
}
- {
- heim_octet_string data;
+ /*
+ * If its not pkcs7-data send signedAttributes
+ */
- ret = copy_AlgorithmIdentifier(&digest, &signer_info->digestAlgorithm);
- if (ret) {
- hx509_clear_error_string(context);
+ if (der_heim_oid_cmp(eContentType, oid_id_pkcs7_data()) != 0) {
+ CMSAttributes sa;
+ heim_octet_string sig;
+
+ ALLOC(signer_info->signedAttrs, 1);
+ if (signer_info->signedAttrs == NULL) {
+ ret = ENOMEM;
goto out;
}
ret = _hx509_create_signature(context,
NULL,
&digest,
- sd.encapContentInfo.eContent,
+ &content,
NULL,
- &data);
- if (ret) {
- hx509_clear_error_string(context);
+ &sig);
+ if (ret)
goto out;
- }
ASN1_MALLOC_ENCODE(MessageDigest,
buf.data,
buf.length,
- &data,
+ &sig,
&size,
ret);
- der_free_octet_string(&data);
+ der_free_octet_string(&sig);
if (ret) {
hx509_clear_error_string(context);
goto out;
@@ -1078,9 +1076,6 @@ hx509_cms_create_signed_1(hx509_context context,
goto out;
}
- }
-
- if (der_heim_oid_cmp(eContentType, oid_id_pkcs7_data()) != 0) {
ASN1_MALLOC_ENCODE(ContentType,
buf.data,
@@ -1101,19 +1096,13 @@ hx509_cms_create_signed_1(hx509_context context,
hx509_clear_error_string(context);
goto out;
}
- }
-
- {
- CMSAttributes sa;
- heim_octet_string os;
-
sa.val = signer_info->signedAttrs->val;
sa.len = signer_info->signedAttrs->len;
ASN1_MALLOC_ENCODE(CMSAttributes,
- os.data,
- os.length,
+ sigdata.data,
+ sigdata.length,
&sa,
&size,
ret);
@@ -1121,21 +1110,32 @@ hx509_cms_create_signed_1(hx509_context context,
hx509_clear_error_string(context);
goto out;
}
- if (size != os.length)
+ if (size != sigdata.length)
_hx509_abort("internal ASN.1 encoder error");
-
+ } else {
+ sigdata.data = content.data;
+ sigdata.length = content.length;
+ }
+
+
+ {
+ AlgorithmIdentifier sigalg;
+
+ ret = hx509_crypto_select(context, HX509_SELECT_PUBLIC_SIG,
+ _hx509_cert_private_key(cert), peer,
+ &sigalg);
+ if (ret)
+ goto out;
+
ret = _hx509_create_signature(context,
_hx509_cert_private_key(cert),
- hx509_signature_rsa_with_sha1(),
- &os,
+ &sigalg,
+ &sigdata,
&signer_info->signatureAlgorithm,
&signer_info->signature);
-
- der_free_octet_string(&os);
- if (ret) {
- hx509_clear_error_string(context);
+ free_AlgorithmIdentifier(&sigalg);
+ if (ret)
goto out;
- }
}
ALLOC_SEQ(&sd.digestAlgorithms, 1);
@@ -1184,17 +1184,12 @@ hx509_cms_create_signed_1(hx509_context context,
}
for (i = 0; i < path.len; i++) {
- ASN1_MALLOC_ENCODE(Certificate,
- sd.certificates->val[i].data,
- sd.certificates->val[i].length,
- _hx509_get_cert(path.val[i]),
- &size, ret);
+ ret = hx509_cert_binary(context, path.val[i],
+ &sd.certificates->val[i]);
if (ret) {
hx509_clear_error_string(context);
goto out;
}
- if (sd.certificates->val[i].length != size)
- _hx509_abort("internal ASN.1 encoder error");
}
}
@@ -1209,6 +1204,8 @@ hx509_cms_create_signed_1(hx509_context context,
_hx509_abort("internal ASN.1 encoder error");
out:
+ if (sigdata.data != content.data)
+ der_free_octet_string(&sigdata);
free_AlgorithmIdentifier(&digest);
_hx509_path_free(&path);
free_SignedData(&sd);
diff --git a/source4/heimdal/lib/hx509/collector.c b/source4/heimdal/lib/hx509/collector.c
index ec172f46f4..8b6ffcb945 100644
--- a/source4/heimdal/lib/hx509/collector.c
+++ b/source4/heimdal/lib/hx509/collector.c
@@ -32,7 +32,7 @@
*/
#include "hx_locl.h"
-RCSID("$Id: collector.c,v 1.16 2007/01/09 10:52:04 lha Exp $");
+RCSID("$Id: collector.c 20778 2007-06-01 22:04:13Z lha $");
struct private_key {
AlgorithmIdentifier alg;
@@ -51,22 +51,26 @@ struct hx509_collector {
};
-struct hx509_collector *
-_hx509_collector_alloc(hx509_context context, hx509_lock lock)
+int
+_hx509_collector_alloc(hx509_context context, hx509_lock lock, struct hx509_collector **collector)
{
struct hx509_collector *c;
int ret;
+ *collector = NULL;
+
c = calloc(1, sizeof(*c));
- if (c == NULL)
- return NULL;
+ if (c == NULL) {
+ hx509_set_error_string(context, 0, ENOMEM, "out of memory");
+ return ENOMEM;
+ }
c->lock = lock;
ret = hx509_certs_init(context, "MEMORY:collector-unenvelop-cert",
0,NULL, &c->unenvelop_certs);
if (ret) {
free(c);
- return NULL;
+ return ret;
}
c->val.data = NULL;
c->val.len = 0;
@@ -75,10 +79,11 @@ _hx509_collector_alloc(hx509_context context, hx509_lock lock)
if (ret) {
hx509_certs_free(&c->unenvelop_certs);
free(c);
- return NULL;
+ return ret;
}
- return c;
+ *collector = c;
+ return 0;
}
hx509_lock
diff --git a/source4/heimdal/lib/hx509/crmf.asn1 b/source4/heimdal/lib/hx509/crmf.asn1
index 4f02b26872..97ade264ae 100644
--- a/source4/heimdal/lib/hx509/crmf.asn1
+++ b/source4/heimdal/lib/hx509/crmf.asn1
@@ -1,4 +1,4 @@
--- $Id: crmf.asn1,v 1.1 2006/04/18 13:05:21 lha Exp $
+-- $Id: crmf.asn1 17102 2006-04-18 13:05:21Z lha $
PKCS10 DEFINITIONS ::=
BEGIN
diff --git a/source4/heimdal/lib/hx509/crypto.c b/source4/heimdal/lib/hx509/crypto.c
index dac0a8160b..96d9693cc2 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,v 1.63 2007/01/09 10:52:05 lha Exp $");
+RCSID("$Id: crypto.c 20939 2007-06-06 20:53:02Z lha $");
struct hx509_crypto;
@@ -42,6 +42,11 @@ enum crypto_op_type {
COT_SIGN
};
+struct hx509_generate_private_context {
+ const heim_oid *key_oid;
+ int isCA;
+ unsigned long num_bits;
+};
struct hx509_private_key_ops {
const char *pemtype;
@@ -56,8 +61,9 @@ struct hx509_private_key_ops {
const void *data,
size_t len,
hx509_private_key private_key);
- int (*generate_private_key)(hx509_context context,
- hx509_private_key private_key);
+ int (*generate_private_key)(hx509_context,
+ struct hx509_generate_private_context *,
+ hx509_private_key);
int (*handle_alg)(const hx509_private_key,
const AlgorithmIdentifier *,
enum crypto_op_type);
@@ -96,7 +102,7 @@ struct hx509_private_key {
*/
struct signature_alg {
- char *name;
+ const char *name;
const heim_oid *(*sig_oid)(void);
const AlgorithmIdentifier *(*sig_alg)(void);
const heim_oid *(*key_oid)(void);
@@ -107,8 +113,7 @@ struct signature_alg {
#define SIG_DIGEST 0x100
#define SIG_PUBLIC_SIG 0x200
-#define SIG_PUBLIC_ENC 0x400
-#define SIG_SECRET 0x800
+#define SIG_SECRET 0x400
int (*verify_signature)(hx509_context context,
const struct signature_alg *,
@@ -123,9 +128,6 @@ struct signature_alg {
const heim_octet_string *,
AlgorithmIdentifier *,
heim_octet_string *);
- int (*private_key2SPKI)(hx509_context,
- hx509_private_key,
- SubjectPublicKeyInfo *);
};
/*
@@ -142,6 +144,46 @@ heim_int2BN(const heim_integer *i)
return bn;
}
+/*
+ *
+ */
+
+static int
+set_digest_alg(DigestAlgorithmIdentifier *id,
+ const heim_oid *oid,
+ const void *param, size_t length)
+{
+ int ret;
+ if (param) {
+ id->parameters = malloc(sizeof(*id->parameters));
+ if (id->parameters == NULL)
+ return ENOMEM;
+ id->parameters->data = malloc(length);
+ if (id->parameters->data == NULL) {
+ free(id->parameters);
+ id->parameters = NULL;
+ return ENOMEM;
+ }
+ memcpy(id->parameters->data, param, length);
+ id->parameters->length = length;
+ } else
+ id->parameters = NULL;
+ ret = der_copy_oid(oid, &id->algorithm);
+ if (ret) {
+ if (id->parameters) {
+ free(id->parameters->data);
+ free(id->parameters);
+ id->parameters = NULL;
+ }
+ return ret;
+ }
+ return 0;
+}
+
+/*
+ *
+ */
+
static int
rsa_verify_signature(hx509_context context,
const struct signature_alg *sig_alg,
@@ -280,12 +322,13 @@ rsa_create_signature(hx509_context context,
digest_alg = hx509_signature_md5();
} else if (der_heim_oid_cmp(sig_oid, oid_id_dsa_with_sha1()) == 0) {
digest_alg = hx509_signature_sha1();
+ } else if (der_heim_oid_cmp(sig_oid, oid_id_pkcs1_rsaEncryption()) == 0) {
+ digest_alg = hx509_signature_sha1();
} else
return HX509_ALG_NOT_SUPP;
if (signatureAlgorithm) {
- ret = _hx509_set_digest_alg(signatureAlgorithm,
- sig_oid, "\x05\x00", 2);
+ ret = set_digest_alg(signatureAlgorithm, sig_oid, "\x05\x00", 2);
if (ret) {
hx509_clear_error_string(context);
return ret;
@@ -380,9 +423,8 @@ rsa_private_key2SPKI(hx509_context context,
}
spki->subjectPublicKey.length = len * 8;
- ret = _hx509_set_digest_alg(&spki->algorithm,
- oid_id_pkcs1_rsaEncryption(),
- "\x05\x00", 2);
+ ret = set_digest_alg(&spki->algorithm,oid_id_pkcs1_rsaEncryption(),
+ "\x05\x00", 2);
if (ret) {
hx509_set_error_string(context, 0, ret, "malloc - out of memory");
free(spki->subjectPublicKey.data);
@@ -400,17 +442,13 @@ rsa_private_key2SPKI(hx509_context context,
}
static int
-cb_func(int a, int b, BN_GENCB *c)
+rsa_generate_private_key(hx509_context context,
+ struct hx509_generate_private_context *ctx,
+ hx509_private_key private_key)
{
- return 1;
-}
-
-static int
-rsa_generate_private_key(hx509_context context, hx509_private_key private_key)
-{
- BN_GENCB cb;
BIGNUM *e;
int ret;
+ unsigned long bits;
static const int default_rsa_e = 65537;
static const int default_rsa_bits = 1024;
@@ -425,9 +463,14 @@ rsa_generate_private_key(hx509_context context, hx509_private_key private_key)
e = BN_new();
BN_set_word(e, default_rsa_e);
- BN_GENCB_set(&cb, cb_func, NULL);
- ret = RSA_generate_key_ex(private_key->private_key.rsa,
- default_rsa_bits, e, &cb);
+ bits = default_rsa_bits;
+
+ if (ctx->num_bits)
+ bits = ctx->num_bits;
+ else if (ctx->isCA)
+ bits *= 2;
+
+ ret = RSA_generate_key_ex(private_key->private_key.rsa, bits, e, NULL);
BN_free(e);
if (ret != 1) {
hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
@@ -642,8 +685,8 @@ sha256_create_signature(hx509_context context,
if (signatureAlgorithm) {
int ret;
- ret = _hx509_set_digest_alg(signatureAlgorithm,
- (*sig_alg->sig_oid)(), "\x05\x00", 2);
+ ret = set_digest_alg(signatureAlgorithm, (*sig_alg->sig_oid)(),
+ "\x05\x00", 2);
if (ret)
return ret;
}
@@ -708,8 +751,8 @@ sha1_create_signature(hx509_context context,
if (signatureAlgorithm) {
int ret;
- ret = _hx509_set_digest_alg(signatureAlgorithm,
- (*sig_alg->sig_oid)(), "\x05\x00", 2);
+ ret = set_digest_alg(signatureAlgorithm, (*sig_alg->sig_oid)(),
+ "\x05\x00", 2);
if (ret)
return ret;
}
@@ -789,7 +832,7 @@ md2_verify_signature(hx509_context context,
return 0;
}
-static struct signature_alg pkcs1_rsa_sha1_alg = {
+static const struct signature_alg pkcs1_rsa_sha1_alg = {
"rsa",
oid_id_pkcs1_rsaEncryption,
hx509_signature_rsa_with_sha1,
@@ -797,11 +840,10 @@ static struct signature_alg pkcs1_rsa_sha1_alg = {
NULL,
PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG,
rsa_verify_signature,
- rsa_create_signature,
- rsa_private_key2SPKI
+ rsa_create_signature
};
-static struct signature_alg rsa_with_sha256_alg = {
+static const struct signature_alg rsa_with_sha256_alg = {
"rsa-with-sha256",
oid_id_pkcs1_sha256WithRSAEncryption,
hx509_signature_rsa_with_sha256,
@@ -809,11 +851,10 @@ static struct signature_alg rsa_with_sha256_alg = {
oid_id_sha256,
PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG,
rsa_verify_signature,
- rsa_create_signature,
- rsa_private_key2SPKI
+ rsa_create_signature
};
-static struct signature_alg rsa_with_sha1_alg = {
+static const struct signature_alg rsa_with_sha1_alg = {
"rsa-with-sha1",
oid_id_pkcs1_sha1WithRSAEncryption,
hx509_signature_rsa_with_sha1,
@@ -821,11 +862,10 @@ static struct signature_alg rsa_with_sha1_alg = {
oid_id_secsig_sha_1,
PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG,
rsa_verify_signature,
- rsa_create_signature,
- rsa_private_key2SPKI
+ rsa_create_signature
};
-static struct signature_alg rsa_with_md5_alg = {
+static const struct signature_alg rsa_with_md5_alg = {
"rsa-with-md5",
oid_id_pkcs1_md5WithRSAEncryption,
hx509_signature_rsa_with_md5,
@@ -833,11 +873,10 @@ static struct signature_alg rsa_with_md5_alg = {
oid_id_rsa_digest_md5,
PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG,
rsa_verify_signature,
- rsa_create_signature,
- rsa_private_key2SPKI
+ rsa_create_signature
};
-static struct signature_alg rsa_with_md2_alg = {
+static const struct signature_alg rsa_with_md2_alg = {
"rsa-with-md2",
oid_id_pkcs1_md2WithRSAEncryption,
hx509_signature_rsa_with_md2,
@@ -845,11 +884,10 @@ static struct signature_alg rsa_with_md2_alg = {
oid_id_rsa_digest_md2,
PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG,
rsa_verify_signature,
- rsa_create_signature,
- rsa_private_key2SPKI
+ rsa_create_signature
};
-static struct signature_alg dsa_sha1_alg = {
+static const struct signature_alg dsa_sha1_alg = {
"dsa-with-sha1",
oid_id_dsa_with_sha1,
NULL,
@@ -860,7 +898,7 @@ static struct signature_alg dsa_sha1_alg = {
/* create_signature */ NULL,
};
-static struct signature_alg sha256_alg = {
+static const struct signature_alg sha256_alg = {
"sha-256",
oid_id_sha256,
hx509_signature_sha256,
@@ -871,7 +909,7 @@ static struct signature_alg sha256_alg = {
sha256_create_signature
};
-static struct signature_alg sha1_alg = {
+static const struct signature_alg sha1_alg = {
"sha1",
oid_id_secsig_sha_1,
hx509_signature_sha1,
@@ -882,7 +920,7 @@ static struct signature_alg sha1_alg = {
sha1_create_signature
};
-static struct signature_alg md5_alg = {
+static const struct signature_alg md5_alg = {
"rsa-md5",
oid_id_rsa_digest_md5,
hx509_signature_md5,
@@ -892,7 +930,7 @@ static struct signature_alg md5_alg = {
md5_verify_signature
};
-static struct signature_alg md2_alg = {
+static const struct signature_alg md2_alg = {
"rsa-md2",
oid_id_rsa_digest_md2,
hx509_signature_md2,
@@ -907,12 +945,13 @@ static struct signature_alg md2_alg = {
* compatible" type (type is RSA, DSA, none, etc)
*/
-static struct signature_alg *sig_algs[] = {
+static const struct signature_alg *sig_algs[] = {
&rsa_with_sha256_alg,
&rsa_with_sha1_alg,
&pkcs1_rsa_sha1_alg,
&rsa_with_md5_alg,
&rsa_with_md2_alg,
+ &pkcs1_rsa_sha1_alg,
&dsa_sha1_alg,
&sha256_alg,
&sha1_alg,
@@ -1235,8 +1274,56 @@ _hx509_private_key2SPKI(hx509_context context,
}
int
+_hx509_generate_private_key_init(hx509_context context,
+ const heim_oid *oid,
+ struct hx509_generate_private_context **ctx)
+{
+ *ctx = NULL;
+
+ if (der_heim_oid_cmp(oid, oid_id_pkcs1_rsaEncryption()) != 0) {
+ hx509_set_error_string(context, 0, EINVAL,
+ "private key not an RSA key");
+ return EINVAL;
+ }
+
+ *ctx = calloc(1, sizeof(**ctx));
+ if (*ctx == NULL) {
+ hx509_set_error_string(context, 0, ENOMEM, "out of memory");
+ return ENOMEM;
+ }
+ (*ctx)->key_oid = oid;
+
+ return 0;
+}
+
+int
+_hx509_generate_private_key_is_ca(hx509_context context,
+ struct hx509_generate_private_context *ctx)
+{
+ ctx->isCA = 1;
+ return 0;
+}
+
+int
+_hx509_generate_private_key_bits(hx509_context context,
+ struct hx509_generate_private_context *ctx,
+ unsigned long bits)
+{
+ ctx->num_bits = bits;
+ return 0;
+}
+
+
+void
+_hx509_generate_private_key_free(struct hx509_generate_private_context **ctx)
+{
+ free(*ctx);
+ *ctx = NULL;
+}
+
+int
_hx509_generate_private_key(hx509_context context,
- const heim_oid *key_oid,
+ struct hx509_generate_private_context *ctx,
hx509_private_key *private_key)
{
struct hx509_private_key_ops *ops;
@@ -1244,7 +1331,7 @@ _hx509_generate_private_key(hx509_context context,
*private_key = NULL;
- ops = find_private_alg(key_oid);
+ ops = find_private_alg(ctx->key_oid);
if (ops == NULL) {
hx509_clear_error_string(context);
return HX509_SIG_ALG_NO_SUPPORTED;
@@ -1256,7 +1343,7 @@ _hx509_generate_private_key(hx509_context context,
return ret;
}
- ret = (*ops->generate_private_key)(context, *private_key);
+ ret = (*ops->generate_private_key)(context, ctx, *private_key);
if (ret)
_hx509_private_key_free(private_key);
@@ -1268,21 +1355,21 @@ _hx509_generate_private_key(hx509_context context,
*
*/
-static const heim_octet_string null_entry_oid = { 2, "\x05\x00" };
+static const heim_octet_string null_entry_oid = { 2, rk_UNCONST("\x05\x00") };
-static const unsigned sha512_oid_tree[] = { 2, 16, 840, 1, 101, 3, 4, 3 };
+static const unsigned sha512_oid_tree[] = { 2, 16, 840, 1, 101, 3, 4, 2, 3 };
const AlgorithmIdentifier _hx509_signature_sha512_data = {
- { 8, rk_UNCONST(sha512_oid_tree) }, rk_UNCONST(&null_entry_oid)
+ { 9, rk_UNCONST(sha512_oid_tree) }, rk_UNCONST(&null_entry_oid)
};
-static const unsigned sha384_oid_tree[] = { 2, 16, 840, 1, 101, 3, 4, 2 };
+static const unsigned sha384_oid_tree[] = { 2, 16, 840, 1, 101, 3, 4, 2, 2 };
const AlgorithmIdentifier _hx509_signature_sha384_data = {
- { 8, rk_UNCONST(sha384_oid_tree) }, rk_UNCONST(&null_entry_oid)
+ { 9, rk_UNCONST(sha384_oid_tree) }, rk_UNCONST(&null_entry_oid)
};
static const unsigned sha256_oid_tree[] = { 2, 16, 840, 1, 101, 3, 4, 2, 1 };
const AlgorithmIdentifier _hx509_signature_sha256_data = {
- { 8, rk_UNCONST(sha256_oid_tree) }, rk_UNCONST(&null_entry_oid)
+ { 9, rk_UNCONST(sha256_oid_tree) }, rk_UNCONST(&null_entry_oid)
};
static const unsigned sha1_oid_tree[] = { 1, 3, 14, 3, 2, 26 };
@@ -1335,6 +1422,20 @@ const AlgorithmIdentifier _hx509_signature_rsa_data = {
{ 7, rk_UNCONST(rsa_oid) }, NULL
};
+static const unsigned des_rsdi_ede3_cbc_oid[] ={ 1, 2, 840, 113549, 3, 7 };
+const AlgorithmIdentifier _hx509_des_rsdi_ede3_cbc_oid = {
+ { 6, rk_UNCONST(des_rsdi_ede3_cbc_oid) }, NULL
+};
+
+static const unsigned aes128_cbc_oid[] ={ 2, 16, 840, 1, 101, 3, 4, 1, 2 };
+const AlgorithmIdentifier _hx509_crypto_aes128_cbc_data = {
+ { 9, rk_UNCONST(aes128_cbc_oid) }, NULL
+};
+
+static const unsigned aes256_cbc_oid[] ={ 2, 16, 840, 1, 101, 3, 4, 1, 42 };
+const AlgorithmIdentifier _hx509_crypto_aes256_cbc_data = {
+ { 9, rk_UNCONST(aes256_cbc_oid) }, NULL
+};
const AlgorithmIdentifier *
hx509_signature_sha512(void)
@@ -1388,6 +1489,33 @@ const AlgorithmIdentifier *
hx509_signature_rsa(void)
{ return &_hx509_signature_rsa_data; }
+const AlgorithmIdentifier *
+hx509_crypto_des_rsdi_ede3_cbc(void)
+{ return &_hx509_des_rsdi_ede3_cbc_oid; }
+
+const AlgorithmIdentifier *
+hx509_crypto_aes128_cbc(void)
+{ return &_hx509_crypto_aes128_cbc_data; }
+
+const AlgorithmIdentifier *
+hx509_crypto_aes256_cbc(void)
+{ return &_hx509_crypto_aes256_cbc_data; }
+
+/*
+ *
+ */
+
+const AlgorithmIdentifier * _hx509_crypto_default_sig_alg =
+ &_hx509_signature_rsa_with_sha1_data;
+const AlgorithmIdentifier * _hx509_crypto_default_digest_alg =
+ &_hx509_signature_sha1_data;
+const AlgorithmIdentifier * _hx509_crypto_default_secret_alg =
+ &_hx509_crypto_aes128_cbc_data;
+
+/*
+ *
+ */
+
int
_hx509_private_key_init(hx509_private_key *key,
hx509_private_key_ops *ops,
@@ -1487,6 +1615,7 @@ _hx509_private_key_export(hx509_context context,
struct hx509cipher {
const char *name;
const heim_oid *(*oid_func)(void);
+ const AlgorithmIdentifier *(*ai_func)(void);
const EVP_CIPHER *(*evp_func)(void);
int (*get_params)(hx509_context, const hx509_crypto,
const heim_octet_string *, heim_octet_string *);
@@ -1654,6 +1783,7 @@ static const struct hx509cipher ciphers[] = {
{
"rc2-cbc",
oid_id_pkcs3_rc2_cbc,
+ NULL,
EVP_rc2_cbc,
CMSRC2CBCParam_get,
CMSRC2CBCParam_set
@@ -1661,6 +1791,7 @@ static const struct hx509cipher ciphers[] = {
{
"rc2-cbc",
oid_id_rsadsi_rc2_cbc,
+ NULL,
EVP_rc2_cbc,
CMSRC2CBCParam_get,
CMSRC2CBCParam_set
@@ -1668,6 +1799,7 @@ static const struct hx509cipher ciphers[] = {
{
"rc2-40-cbc",
oid_private_rc2_40,
+ NULL,
EVP_rc2_40_cbc,
CMSRC2CBCParam_get,
CMSRC2CBCParam_set
@@ -1675,6 +1807,7 @@ static const struct hx509cipher ciphers[] = {
{
"des-ede3-cbc",
oid_id_pkcs3_des_ede3_cbc,
+ NULL,
EVP_des_ede3_cbc,
CMSCBCParam_get,
CMSCBCParam_set
@@ -1682,6 +1815,7 @@ static const struct hx509cipher ciphers[] = {
{
"des-ede3-cbc",
oid_id_rsadsi_des_ede3_cbc,
+ hx509_crypto_des_rsdi_ede3_cbc,
EVP_des_ede3_cbc,
CMSCBCParam_get,
CMSCBCParam_set
@@ -1689,6 +1823,7 @@ static const struct hx509cipher ciphers[] = {
{
"aes-128-cbc",
oid_id_aes_128_cbc,
+ hx509_crypto_aes128_cbc,
EVP_aes_128_cbc,
CMSCBCParam_get,
CMSCBCParam_set
@@ -1696,6 +1831,7 @@ static const struct hx509cipher ciphers[] = {
{
"aes-192-cbc",
oid_id_aes_192_cbc,
+ NULL,
EVP_aes_192_cbc,
CMSCBCParam_get,
CMSCBCParam_set
@@ -1703,6 +1839,7 @@ static const struct hx509cipher ciphers[] = {
{
"aes-256-cbc",
oid_id_aes_256_cbc,
+ hx509_crypto_aes256_cbc,
EVP_aes_256_cbc,
CMSCBCParam_get,
CMSCBCParam_set
@@ -2060,11 +2197,13 @@ PBE_string2key(hx509_context context,
const EVP_MD *md)
{
PKCS12_PBEParams p12params;
- int passwordlen = strlen(password);
+ int passwordlen;
hx509_crypto c;
int iter, saltlen, ret;
unsigned char *salt;
+ passwordlen = password ? strlen(password) : 0;
+
if (parameters == NULL)
return HX509_ALG_NOT_SUPP;
@@ -2081,10 +2220,6 @@ PBE_string2key(hx509_context context,
salt = p12params.salt.data;
saltlen = p12params.salt.length;
- /* XXX It needs to be here, but why ? */
- if (passwordlen == 0)
- password = NULL;
-
if (!PKCS12_key_gen (password, passwordlen, salt, saltlen,
PKCS12_KEY_ID, iter, key->length, key->data, md)) {
ret = HX509_CRYPTO_INTERNAL_ERROR;
@@ -2205,8 +2340,10 @@ _hx509_pbe_decrypt(hx509_context context,
if (i < pw->len)
password = pw->val[i];
- else
+ else if (i < pw->len + 1)
password = "";
+ else
+ password = NULL;
ret = (*s2k)(context, password, ai->parameters, &crypto,
&key, &iv, enc_oid, md);
@@ -2314,7 +2451,6 @@ hx509_crypto_select(const hx509_context context,
hx509_peer_info peer,
AlgorithmIdentifier *selected)
{
- const heim_oid *keytype = NULL;
const AlgorithmIdentifier *def;
size_t i, j;
int ret, bits;
@@ -2323,20 +2459,25 @@ hx509_crypto_select(const hx509_context context,
if (type == HX509_SELECT_DIGEST) {
bits = SIG_DIGEST;
- def = hx509_signature_sha1();
+ def = _hx509_crypto_default_digest_alg;
} else if (type == HX509_SELECT_PUBLIC_SIG) {
bits = SIG_PUBLIC_SIG;
/* XXX depend on `source´ and `peer´ */
- def = hx509_signature_rsa_with_sha1();
+ def = _hx509_crypto_default_sig_alg;
+ } else if (type == HX509_SELECT_SECRET_ENC) {
+ bits = SIG_SECRET;
+ def = _hx509_crypto_default_secret_alg;
} else {
hx509_set_error_string(context, 0, EINVAL,
"Unknown type %d of selection", type);
return EINVAL;
}
- keytype = find_keytype(source);
-
if (peer) {
+ const heim_oid *keytype = NULL;
+
+ keytype = find_keytype(source);
+
for (i = 0; i < peer->len; i++) {
for (j = 0; sig_algs[j]; j++) {
if ((sig_algs[j]->flags & bits) != bits)
@@ -2354,6 +2495,19 @@ hx509_crypto_select(const hx509_context context,
hx509_clear_error_string(context);
return ret;
}
+ if (bits & SIG_SECRET) {
+ const struct hx509cipher *cipher;
+
+ cipher = find_cipher_by_oid(&peer->val[i].algorithm);
+ if (cipher == NULL)
+ continue;
+ if (cipher->ai_func == NULL)
+ continue;
+ ret = copy_AlgorithmIdentifier(cipher->ai_func(), selected);
+ if (ret)
+ hx509_clear_error_string(context);
+ return ret;
+ }
}
}
@@ -2379,7 +2533,7 @@ hx509_crypto_available(hx509_context context,
*val = NULL;
if (type == HX509_SELECT_ALL) {
- bits = SIG_DIGEST | SIG_PUBLIC_SIG;
+ bits = SIG_DIGEST | SIG_PUBLIC_SIG | SIG_SECRET;
} else if (type == HX509_SELECT_DIGEST) {
bits = SIG_DIGEST;
} else if (type == HX509_SELECT_PUBLIC_SIG) {
@@ -2415,6 +2569,26 @@ hx509_crypto_available(hx509_context context,
len++;
}
+ /* Add AES */
+ if (bits & SIG_SECRET) {
+
+ for (i = 0; i < sizeof(ciphers)/sizeof(ciphers[0]); i++) {
+
+ if (ciphers[i].ai_func == NULL)
+ continue;
+
+ ptr = realloc(*val, sizeof(**val) * (len + 1));
+ if (ptr == NULL)
+ goto out;
+ *val = ptr;
+
+ ret = copy_AlgorithmIdentifier((ciphers[i].ai_func)(), &(*val)[len]);
+ if (ret)
+ goto out;
+ len++;
+ }
+ }
+
*plen = len;
return 0;
diff --git a/source4/heimdal/lib/hx509/env.c b/source4/heimdal/lib/hx509/env.c
new file mode 100644
index 0000000000..4cb2f9f4b1
--- /dev/null
+++ b/source4/heimdal/lib/hx509/env.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2007 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "hx_locl.h"
+RCSID("$Id: env.c 19878 2007-01-13 00:58:39Z lha $");
+
+struct hx509_env {
+ struct {
+ char *key;
+ char *value;
+ } *val;
+ size_t len;
+};
+
+int
+hx509_env_init(hx509_context context, hx509_env *env)
+{
+ *env = calloc(1, sizeof(**env));
+ if (*env == NULL) {
+ hx509_set_error_string(context, 0, ENOMEM, "out of memory");
+ return ENOMEM;
+ }
+ return 0;
+}
+
+int
+hx509_env_add(hx509_context context, hx509_env env,
+ const char *key, const char *value)
+{
+ void *ptr;
+
+ ptr = realloc(env->val, sizeof(env->val[0]) * (env->len + 1));
+ if (ptr == NULL) {
+ hx509_set_error_string(context, 0, ENOMEM, "out of memory");
+ return ENOMEM;
+ }
+ env->val = ptr;
+ env->val[env->len].key = strdup(key);
+ if (env->val[env->len].key == NULL) {
+ hx509_set_error_string(context, 0, ENOMEM, "out of memory");
+ return ENOMEM;
+ }
+ env->val[env->len].value = strdup(value);
+ if (env->val[env->len].value == NULL) {
+ free(env->val[env->len].key);
+ hx509_set_error_string(context, 0, ENOMEM, "out of memory");
+ return ENOMEM;
+ }
+ env->len++;
+ return 0;
+}
+
+const char *
+hx509_env_lfind(hx509_context context, hx509_env env,
+ const char *key, size_t len)
+{
+ size_t i;
+
+ for (i = 0; i < env->len; i++) {
+ char *s = env->val[i].key;
+ if (strncmp(key, s, len) == 0 && s[len] == '\0')
+ return env->val[i].value;
+ }
+ return NULL;
+}
+
+
+void
+hx509_env_free(hx509_env *env)
+{
+ size_t i;
+
+ for (i = 0; i < (*env)->len; i++) {
+ free((*env)->val[i].key);
+ free((*env)->val[i].value);
+ }
+ free((*env)->val);
+ free(*env);
+ *env = NULL;
+}
+
diff --git a/source4/heimdal/lib/hx509/error.c b/source4/heimdal/lib/hx509/error.c
index 770b71981a..9f3a014873 100644
--- a/source4/heimdal/lib/hx509/error.c
+++ b/source4/heimdal/lib/hx509/error.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 Kungliga Tekniska Högskolan
+ * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -32,7 +32,7 @@
*/
#include "hx_locl.h"
-RCSID("$Id: error.c,v 1.4 2006/11/16 15:08:09 lha Exp $");
+RCSID("$Id: error.c 20912 2007-06-05 03:53:52Z lha $");
struct hx509_error_data {
hx509_error next;
@@ -87,7 +87,8 @@ hx509_set_error_stringv(hx509_context context, int flags, int code,
}
void
-hx509_set_error_string(hx509_context context, int flags, int code, const char *fmt, ...)
+hx509_set_error_string(hx509_context context, int flags, int code,
+ const char *fmt, ...)
{
va_list ap;
@@ -100,9 +101,9 @@ char *
hx509_get_error_string(hx509_context context, int error_code)
{
struct rk_strpool *p = NULL;
- hx509_error msg;
+ hx509_error msg = context->error;
- if (context->error == NULL) {
+ if (msg == NULL || msg->code != error_code) {
const char *cstr;
char *str;
@@ -125,10 +126,12 @@ hx509_get_error_string(hx509_context context, int error_code)
}
void
-hx509_err(hx509_context context, int exit_code, int error_code, char *fmt, ...)
+hx509_err(hx509_context context, int exit_code,
+ int error_code, const char *fmt, ...)
{
va_list ap;
- char *msg, *str;
+ const char *msg;
+ char *str;
va_start(ap, fmt);
vasprintf(&str, fmt, ap);
diff --git a/source4/heimdal/lib/hx509/file.c b/source4/heimdal/lib/hx509/file.c
index 39497fc3a9..1152af2423 100644
--- a/source4/heimdal/lib/hx509/file.c
+++ b/source4/heimdal/lib/hx509/file.c
@@ -35,6 +35,27 @@
RCSID("$ID$");
int
+_hx509_map_file_os(const char *fn, heim_octet_string *os, struct stat *rsb)
+{
+ size_t length;
+ void *data;
+ int ret;
+
+ ret = _hx509_map_file(fn, &data, &length, rsb);
+
+ os->data = data;
+ os->length = length;
+
+ return ret;
+}
+
+void
+_hx509_unmap_file_os(heim_octet_string *os)
+{
+ _hx509_unmap_file(os->data, os->length);
+}
+
+int
_hx509_map_file(const char *fn, void **data, size_t *length, struct stat *rsb)
{
struct stat sb;
diff --git a/source4/heimdal/lib/hx509/hx509-private.h b/source4/heimdal/lib/hx509/hx509-private.h
index 2db3f4f932..2763df957f 100644
--- a/source4/heimdal/lib/hx509/hx509-private.h
+++ b/source4/heimdal/lib/hx509/hx509-private.h
@@ -39,6 +39,12 @@ _hx509_cert_assign_key (
hx509_private_key /*private_key*/);
int
+_hx509_cert_get_eku (
+ hx509_context /*context*/,
+ hx509_cert /*cert*/,
+ ExtKeyUsage */*e*/);
+
+int
_hx509_cert_get_keyusage (
hx509_context /*context*/,
hx509_cert /*c*/,
@@ -105,10 +111,11 @@ _hx509_check_key_usage (
unsigned /*flags*/,
int /*req_present*/);
-struct hx509_collector *
+int
_hx509_collector_alloc (
hx509_context /*context*/,
- hx509_lock /*lock*/);
+ hx509_lock /*lock*/,
+ struct hx509_collector **/*collector*/);
int
_hx509_collector_certs_add (
@@ -169,9 +176,29 @@ _hx509_find_extension_subject_key_id (
int
_hx509_generate_private_key (
hx509_context /*context*/,
- const heim_oid */*key_oid*/,
+ struct hx509_generate_private_context */*ctx*/,
hx509_private_key */*private_key*/);
+int
+_hx509_generate_private_key_bits (
+ hx509_context /*context*/,
+ struct hx509_generate_private_context */*ctx*/,
+ unsigned long /*bits*/);
+
+void
+_hx509_generate_private_key_free (struct hx509_generate_private_context **/*ctx*/);
+
+int
+_hx509_generate_private_key_init (
+ hx509_context /*context*/,
+ const heim_oid */*oid*/,
+ struct hx509_generate_private_context **/*ctx*/);
+
+int
+_hx509_generate_private_key_is_ca (
+ hx509_context /*context*/,
+ struct hx509_generate_private_context */*ctx*/);
+
Certificate *
_hx509_get_cert (hx509_cert /*cert*/);
@@ -182,9 +209,15 @@ void
_hx509_ks_file_register (hx509_context /*context*/);
void
+_hx509_ks_keychain_register (hx509_context /*context*/);
+
+void
_hx509_ks_mem_register (hx509_context /*context*/);
void
+_hx509_ks_null_register (hx509_context /*context*/);
+
+void
_hx509_ks_pkcs11_register (hx509_context /*context*/);
void
@@ -215,6 +248,12 @@ _hx509_map_file (
struct stat */*rsb*/);
int
+_hx509_map_file_os (
+ const char */*fn*/,
+ heim_octet_string */*os*/,
+ struct stat */*rsb*/);
+
+int
_hx509_match_keys (
hx509_cert /*c*/,
hx509_private_key /*private_key*/);
@@ -269,9 +308,9 @@ _hx509_pbe_decrypt (
void
_hx509_pi_printf (
- int (*/*func*/)(void *, char *),
+ int (*/*func*/)(void *, const char *),
void */*ctx*/,
- char */*fmt*/,
+ const char */*fmt*/,
...);
int
@@ -340,6 +379,12 @@ _hx509_query_match_cert (
const hx509_query */*q*/,
hx509_cert /*cert*/);
+void
+_hx509_query_statistic (
+ hx509_context /*context*/,
+ int /*type*/,
+ const hx509_query */*q*/);
+
int
_hx509_request_add_dns_name (
hx509_context /*context*/,
@@ -392,18 +437,14 @@ _hx509_set_cert_attribute (
const heim_oid */*oid*/,
const heim_octet_string */*attr*/);
-int
-_hx509_set_digest_alg (
- DigestAlgorithmIdentifier */*id*/,
- const heim_oid */*oid*/,
- void */*param*/,
- size_t /*length*/);
-
void
_hx509_unmap_file (
void */*data*/,
size_t /*len*/);
+void
+_hx509_unmap_file_os (heim_octet_string */*os*/);
+
int
_hx509_unparse_Name (
const Name */*aname*/,
diff --git a/source4/heimdal/lib/hx509/hx509-protos.h b/source4/heimdal/lib/hx509/hx509-protos.h
index 4fcab70ff8..ab312cdbdf 100644
--- a/source4/heimdal/lib/hx509/hx509-protos.h
+++ b/source4/heimdal/lib/hx509/hx509-protos.h
@@ -8,6 +8,14 @@
extern "C" {
#endif
+#ifndef HX509_LIB_FUNCTION
+#if defined(_WIN32)
+#define HX509_LIB_FUNCTION _stdcall
+#else
+#define HX509_LIB_FUNCTION
+#endif
+#endif
+
void
hx509_bitstring_print (
const heim_bit_string */*b*/,
@@ -29,8 +37,15 @@ hx509_ca_sign_self (
hx509_cert */*certificate*/);
int
+hx509_ca_tbs_add_crl_dp_uri (
+ hx509_context /*context*/,
+ hx509_ca_tbs /*tbs*/,
+ const char */*uri*/,
+ hx509_name /*issuername*/);
+
+int
hx509_ca_tbs_add_eku (
- hx509_context /*contex*/,
+ hx509_context /*context*/,
hx509_ca_tbs /*tbs*/,
const heim_oid */*oid*/);
@@ -41,6 +56,18 @@ hx509_ca_tbs_add_san_hostname (
const char */*dnsname*/);
int
+hx509_ca_tbs_add_san_jid (
+ hx509_context /*context*/,
+ hx509_ca_tbs /*tbs*/,
+ const char */*jid*/);
+
+int
+hx509_ca_tbs_add_san_ms_upn (
+ hx509_context /*context*/,
+ hx509_ca_tbs /*tbs*/,
+ const char */*principal*/);
+
+int
hx509_ca_tbs_add_san_otherName (
hx509_context /*context*/,
hx509_ca_tbs /*tbs*/,
@@ -74,6 +101,11 @@ hx509_ca_tbs_set_ca (
int /*pathLenConstraint*/);
int
+hx509_ca_tbs_set_domaincontroller (
+ hx509_context /*context*/,
+ hx509_ca_tbs /*tbs*/);
+
+int
hx509_ca_tbs_set_notAfter (
hx509_context /*context*/,
hx509_ca_tbs /*tbs*/,
@@ -116,6 +148,28 @@ hx509_ca_tbs_set_subject (
hx509_name /*subject*/);
int
+hx509_ca_tbs_set_template (
+ hx509_context /*context*/,
+ hx509_ca_tbs /*tbs*/,
+ int /*flags*/,
+ hx509_cert /*cert*/);
+
+int
+hx509_ca_tbs_subject_expand (
+ hx509_context /*context*/,
+ hx509_ca_tbs /*tbs*/,
+ hx509_env /*env*/);
+
+const struct units *
+hx509_ca_tbs_template_units (void);
+
+int
+hx509_cert_binary (
+ hx509_context /*context*/,
+ hx509_cert /*c*/,
+ heim_octet_string */*os*/);
+
+int
hx509_cert_check_eku (
hx509_context /*context*/,
hx509_cert /*cert*/,
@@ -136,6 +190,11 @@ hx509_cert_find_subjectAltName_otherName (
void
hx509_cert_free (hx509_cert /*cert*/);
+int
+hx509_cert_get_SPKI (
+ hx509_cert /*p*/,
+ SubjectPublicKeyInfo */*spki*/);
+
hx509_cert_attribute
hx509_cert_get_attribute (
hx509_cert /*cert*/,
@@ -155,6 +214,12 @@ hx509_cert_get_issuer (
hx509_cert /*p*/,
hx509_name */*name*/);
+time_t
+hx509_cert_get_notAfter (hx509_cert /*p*/);
+
+time_t
+hx509_cert_get_notBefore (hx509_cert /*p*/);
+
int
hx509_cert_get_serialnumber (
hx509_cert /*p*/,
@@ -218,7 +283,7 @@ int
hx509_certs_info (
hx509_context /*context*/,
hx509_certs /*certs*/,
- int (*/*func*/)(void *, char *),
+ int (*/*func*/)(void *, const char *),
void */*ctx*/);
int
@@ -274,6 +339,7 @@ hx509_clear_error_string (hx509_context /*context*/);
int
hx509_cms_create_signed_1 (
hx509_context /*context*/,
+ int /*flags*/,
const heim_oid */*eContentType*/,
const void */*data*/,
size_t /*length*/,
@@ -296,6 +362,7 @@ hx509_cms_decrypt_encrypted (
int
hx509_cms_envelope_1 (
hx509_context /*context*/,
+ int /*flags*/,
hx509_cert /*cert*/,
const void */*data*/,
size_t /*length*/,
@@ -327,6 +394,7 @@ hx509_cms_verify_signed (
hx509_verify_ctx /*ctx*/,
const void */*data*/,
size_t /*length*/,
+ const heim_octet_string */*signedContent*/,
hx509_certs /*store*/,
heim_oid */*contentType*/,
heim_octet_string */*content*/,
@@ -350,6 +418,41 @@ hx509_context_set_missing_revoke (
int /*flag*/);
int
+hx509_crl_add_revoked_certs (
+ hx509_context /*context*/,
+ hx509_crl /*crl*/,
+ hx509_certs /*certs*/);
+
+int
+hx509_crl_alloc (
+ hx509_context /*context*/,
+ hx509_crl */*crl*/);
+
+void
+hx509_crl_free (
+ hx509_context /*context*/,
+ hx509_crl */*crl*/);
+
+int
+hx509_crl_lifetime (
+ hx509_context /*context*/,
+ hx509_crl /*crl*/,
+ int /*delta*/);
+
+int
+hx509_crl_sign (
+ hx509_context /*context*/,
+ hx509_cert /*signer*/,
+ hx509_crl /*crl*/,
+ heim_octet_string */*os*/);
+
+const AlgorithmIdentifier *
+hx509_crypto_aes128_cbc (void);
+
+const AlgorithmIdentifier *
+hx509_crypto_aes256_cbc (void);
+
+int
hx509_crypto_available (
hx509_context /*context*/,
int /*type*/,
@@ -365,6 +468,9 @@ hx509_crypto_decrypt (
heim_octet_string */*ivec*/,
heim_octet_string */*clear*/);
+const AlgorithmIdentifier *
+hx509_crypto_des_rsdi_ede3_cbc (void);
+
void
hx509_crypto_destroy (hx509_crypto /*crypto*/);
@@ -432,17 +538,44 @@ hx509_crypto_set_random_key (
hx509_crypto /*crypto*/,
heim_octet_string */*key*/);
+int
+hx509_env_add (
+ hx509_context /*context*/,
+ hx509_env /*env*/,
+ const char */*key*/,
+ const char */*value*/);
+
+void
+hx509_env_free (hx509_env */*env*/);
+
+int
+hx509_env_init (
+ hx509_context /*context*/,
+ hx509_env */*env*/);
+
+const char *
+hx509_env_lfind (
+ hx509_context /*context*/,
+ hx509_env /*env*/,
+ const char */*key*/,
+ size_t /*len*/);
+
void
hx509_err (
hx509_context /*context*/,
int /*exit_code*/,
int /*error_code*/,
- char */*fmt*/,
+ const char */*fmt*/,
...);
void
hx509_free_octet_string_list (hx509_octet_string_list */*list*/);
+int
+hx509_general_name_unparse (
+ GeneralName */*name*/,
+ char **/*str*/);
+
char *
hx509_get_error_string (
hx509_context /*context*/,
@@ -507,11 +640,22 @@ hx509_lock_set_prompter (
void */*data*/);
int
+hx509_name_cmp (
+ hx509_name /*n1*/,
+ hx509_name /*n2*/);
+
+int
hx509_name_copy (
hx509_context /*context*/,
const hx509_name /*from*/,
hx509_name */*to*/);
+int
+hx509_name_expand (
+ hx509_context /*context*/,
+ hx509_name /*name*/,
+ hx509_env /*env*/);
+
void
hx509_name_free (hx509_name */*name*/);
@@ -519,6 +663,11 @@ int
hx509_name_is_null_p (const hx509_name /*name*/);
int
+hx509_name_normalize (
+ hx509_context /*context*/,
+ hx509_name /*name*/);
+
+int
hx509_name_to_Name (
const hx509_name /*from*/,
Name */*to*/);
@@ -576,7 +725,7 @@ hx509_peer_info_alloc (
hx509_context /*context*/,
hx509_peer_info */*peer*/);
-int
+void
hx509_peer_info_free (hx509_peer_info /*peer*/);
int
@@ -639,6 +788,17 @@ hx509_query_match_option (
hx509_query */*q*/,
hx509_query_option /*option*/);
+void
+hx509_query_statistic_file (
+ hx509_context /*context*/,
+ const char */*fn*/);
+
+void
+hx509_query_unparse_stats (
+ hx509_context /*context*/,
+ int /*printtype*/,
+ FILE */*out*/);
+
int
hx509_revoke_add_crl (
hx509_context /*context*/,
diff --git a/source4/heimdal/lib/hx509/hx509.h b/source4/heimdal/lib/hx509/hx509.h
index 70f29ea92d..664c12e045 100644
--- a/source4/heimdal/lib/hx509/hx509.h
+++ b/source4/heimdal/lib/hx509/hx509.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-/* $Id: hx509.h,v 1.16 2007/01/09 10:52:05 lha Exp $ */
+/* $Id: hx509.h 20798 2007-06-02 03:28:55Z lha $ */
typedef struct hx509_cert_attribute_data *hx509_cert_attribute;
typedef struct hx509_cert_data *hx509_cert;
@@ -50,6 +50,8 @@ typedef struct hx509_request_data *hx509_request;
typedef struct hx509_error_data *hx509_error;
typedef struct hx509_peer_info *hx509_peer_info;
typedef struct hx509_ca_tbs *hx509_ca_tbs;
+typedef struct hx509_env *hx509_env;
+typedef struct hx509_crl *hx509_crl;
typedef void (*hx509_vprint_func)(void *, const char *, va_list);
@@ -107,5 +109,18 @@ typedef enum {
#define HX509_SELECT_DIGEST 1
#define HX509_SELECT_PUBLIC_SIG 2
#define HX509_SELECT_PUBLIC_ENC 3
+#define HX509_SELECT_SECRET_ENC 4
+
+/* flags to hx509_ca_tbs_set_template */
+#define HX509_CA_TEMPLATE_SUBJECT 1
+#define HX509_CA_TEMPLATE_SERIAL 2
+#define HX509_CA_TEMPLATE_NOTBEFORE 4
+#define HX509_CA_TEMPLATE_NOTAFTER 8
+#define HX509_CA_TEMPLATE_SPKI 16
+#define HX509_CA_TEMPLATE_KU 32
+#define HX509_CA_TEMPLATE_EKU 64
+
+/* flags hx509_cms_create_signed* */
+#define HX509_CMS_SIGATURE_DETACHED 1
#include <hx509-protos.h>
diff --git a/source4/heimdal/lib/hx509/hx509_err.et b/source4/heimdal/lib/hx509/hx509_err.et
index 54ec177e47..90f3b3d907 100644
--- a/source4/heimdal/lib/hx509/hx509_err.et
+++ b/source4/heimdal/lib/hx509/hx509_err.et
@@ -3,7 +3,7 @@
#
# This might look like a com_err file, but is not
#
-id "$Id: hx509_err.et,v 1.19 2006/12/30 23:05:39 lha Exp $"
+id "$Id: hx509_err.et 20807 2007-06-03 03:11:20Z lha $"
error_table hx
prefix HX509
@@ -76,7 +76,8 @@ error_code CRL_CERT_REVOKED, "Certificate is included in CRL"
error_code REVOKE_STATUS_MISSING, "No revoke status found for certificates"
error_code CRL_UNKNOWN_EXTENSION, "Unknown extension"
error_code REVOKE_WRONG_DATA, "Got wrong CRL/OCSP data from server"
-error_code REVOKE_NOT_SAME_PARENT, "Doesn't have same parent as other certificaes"
+error_code REVOKE_NOT_SAME_PARENT, "Doesn't have same parent as other certificates"
+error_code CERT_NOT_IN_OCSP, "Certificates not in OCSP reply"
# misc error
index 108
diff --git a/source4/heimdal/lib/hx509/hx_locl.h b/source4/heimdal/lib/hx509/hx_locl.h
index 78d158f8b1..bfbee0943e 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,v 1.30 2007/01/09 10:52:06 lha Exp $ */
+/* $Id: hx_locl.h 20930 2007-06-06 00:23:42Z lha $ */
#ifdef HAVE_CONFIG_H
#include <config.h>
@@ -71,6 +71,7 @@
struct hx509_keyset_ops;
struct hx509_collector;
+struct hx509_generate_private_context;
typedef struct hx509_path hx509_path;
#include <hx509.h>
@@ -144,7 +145,7 @@ struct hx509_query_data {
};
struct hx509_keyset_ops {
- char *name;
+ const char *name;
int flags;
int (*init)(hx509_context, hx509_certs, void **,
int, const char *, hx509_lock);
@@ -157,7 +158,7 @@ struct hx509_keyset_ops {
int (*iter)(hx509_context, hx509_certs, void *, void *, hx509_cert *);
int (*iter_end)(hx509_context, hx509_certs, void *, void *);
int (*printinfo)(hx509_context, hx509_certs,
- void *, int (*)(void *, char *), void *);
+ void *, int (*)(void *, const char *), void *);
int (*getkeys)(hx509_context, hx509_certs, void *, hx509_private_key **);
int (*addkey)(hx509_context, hx509_certs, void *, hx509_private_key);
};
@@ -178,7 +179,21 @@ struct hx509_context_data {
#define HX509_DEFAULT_OCSP_TIME_DIFF (5*60)
hx509_error error;
struct et_list *et_list;
+ char *querystat;
+ hx509_certs default_trust_anchors;
};
/* _hx509_calculate_path flag field */
#define HX509_CALCULATE_PATH_NO_ANCHOR 1
+
+extern const AlgorithmIdentifier * _hx509_crypto_default_sig_alg;
+extern const AlgorithmIdentifier * _hx509_crypto_default_digest_alg;
+extern const AlgorithmIdentifier * _hx509_crypto_default_secret_alg;
+
+/*
+ * Configurable options
+ */
+
+#if 0 /* fdef __APPLE__*/
+#define HX509_DEFAULT_ANCHORS "KEYCHAIN:system"
+#endif
diff --git a/source4/heimdal/lib/hx509/keyset.c b/source4/heimdal/lib/hx509/keyset.c
index c3d5ee210c..475835b9b0 100644
--- a/source4/heimdal/lib/hx509/keyset.c
+++ b/source4/heimdal/lib/hx509/keyset.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004 - 2006 Kungliga Tekniska Högskolan
+ * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -32,7 +32,7 @@
*/
#include "hx_locl.h"
-RCSID("$Id: keyset.c,v 1.18 2007/01/09 10:52:07 lha Exp $");
+RCSID("$Id: keyset.c 20911 2007-06-05 03:41:17Z lha $");
struct hx509_certs_data {
struct hx509_keyset_ops *ops;
@@ -276,6 +276,8 @@ hx509_certs_find(hx509_context context,
*r = NULL;
+ _hx509_query_statistic(context, 0, q);
+
if (certs->ops->query)
return (*certs->ops->query)(context, certs, certs->ops_data, q, r);
@@ -317,6 +319,8 @@ certs_merge_func(hx509_context context, void *ctx, hx509_cert c)
int
hx509_certs_merge(hx509_context context, hx509_certs to, hx509_certs from)
{
+ if (from == NULL)
+ return 0;
return hx509_certs_iter(context, from, certs_merge_func, to);
}
@@ -358,7 +362,7 @@ hx509_get_one_cert(hx509_context context, hx509_certs certs, hx509_cert *c)
}
static int
-certs_info_stdio(void *ctx, char *str)
+certs_info_stdio(void *ctx, const char *str)
{
FILE *f = ctx;
fprintf(f, "%s\n", str);
@@ -368,7 +372,7 @@ certs_info_stdio(void *ctx, char *str)
int
hx509_certs_info(hx509_context context,
hx509_certs certs,
- int (*func)(void *, char *),
+ int (*func)(void *, const char *),
void *ctx)
{
if (func == NULL) {
@@ -385,8 +389,8 @@ hx509_certs_info(hx509_context context,
}
void
-_hx509_pi_printf(int (*func)(void *, char *), void *ctx,
- char *fmt, ...)
+_hx509_pi_printf(int (*func)(void *, const char *), void *ctx,
+ const char *fmt, ...)
{
va_list ap;
char *str;
diff --git a/source4/heimdal/lib/hx509/ks_dir.c b/source4/heimdal/lib/hx509/ks_dir.c
index 01dcf5795b..a0bc875e5b 100644
--- a/source4/heimdal/lib/hx509/ks_dir.c
+++ b/source4/heimdal/lib/hx509/ks_dir.c
@@ -32,7 +32,7 @@
*/
#include "hx_locl.h"
-RCSID("$Id: ks_dir.c,v 1.7 2007/01/09 10:52:08 lha Exp $");
+RCSID("$Id: ks_dir.c 19778 2007-01-09 10:52:13Z lha $");
#include <dirent.h>
/*
diff --git a/source4/heimdal/lib/hx509/ks_file.c b/source4/heimdal/lib/hx509/ks_file.c
index db0f475129..f9a3580880 100644
--- a/source4/heimdal/lib/hx509/ks_file.c
+++ b/source4/heimdal/lib/hx509/ks_file.c
@@ -32,7 +32,7 @@
*/
#include "hx_locl.h"
-RCSID("$Id: ks_file.c,v 1.31 2007/01/09 10:52:08 lha Exp $");
+RCSID("$Id: ks_file.c 20776 2007-06-01 22:02:01Z lha $");
struct ks_file {
hx509_certs certs;
@@ -542,12 +542,9 @@ file_init(hx509_context context,
return 0;
}
- c = _hx509_collector_alloc(context, lock);
- if (c == NULL) {
- ret = ENOMEM;
- hx509_set_error_string(context, 0, ret, "out of memory");
+ ret = _hx509_collector_alloc(context, lock, &c);
+ if (ret)
goto out;
- }
for (p = f->fn; p != NULL; p = pnext) {
int found_data;
@@ -678,16 +675,12 @@ static int
store_func(hx509_context context, void *ctx, hx509_cert c)
{
FILE *f = (FILE *)ctx;
- size_t size;
heim_octet_string data;
int ret;
- ASN1_MALLOC_ENCODE(Certificate, data.data, data.length,
- _hx509_get_cert(c), &size, ret);
+ ret = hx509_cert_binary(context, c, &data);
if (ret)
return ret;
- if (data.length != size)
- _hx509_abort("internal ASN.1 encoder error");
dump_pem_file(context, "CERTIFICATE", f, data.data, data.length);
free(data.data);
diff --git a/source4/heimdal/lib/hx509/ks_keychain.c b/source4/heimdal/lib/hx509/ks_keychain.c
new file mode 100644
index 0000000000..2f0f72cd14
--- /dev/null
+++ b/source4/heimdal/lib/hx509/ks_keychain.c
@@ -0,0 +1,487 @@
+/*
+ * Copyright (c) 2007 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "hx_locl.h"
+RCSID("$Id: ks_keychain.c 20945 2007-06-06 22:17:17Z lha $");
+
+#ifdef HAVE_FRAMEWORK_SECURITY
+
+#include <Security/Security.h>
+
+/* Missing function decls */
+OSStatus SecKeyGetCSPHandle(SecKeyRef, CSSM_CSP_HANDLE *);
+OSStatus SecKeyGetCredentials(SecKeyRef, CSSM_ACL_AUTHORIZATION_TAG,
+ int, const CSSM_ACCESS_CREDENTIALS **);
+#define kSecCredentialTypeDefault 0
+
+
+static int
+getAttribute(SecKeychainItemRef itemRef, SecItemAttr item,
+ SecKeychainAttributeList **attrs)
+{
+ SecKeychainAttributeInfo attrInfo;
+ uint32 attrFormat = 0;
+ OSStatus ret;
+
+ *attrs = NULL;
+
+ attrInfo.count = 1;
+ attrInfo.tag = &item;
+ attrInfo.format = &attrFormat;
+
+ ret = SecKeychainItemCopyAttributesAndData(itemRef, &attrInfo, NULL,
+ attrs, NULL, NULL);
+ if (ret)
+ return EINVAL;
+ return 0;
+}
+
+
+/*
+ *
+ */
+
+struct kc_rsa {
+ SecKeychainItemRef item;
+ size_t keysize;
+};
+
+
+static int
+kc_rsa_public_encrypt(int flen,
+ const unsigned char *from,
+ unsigned char *to,
+ RSA *rsa,
+ int padding)
+{
+ return -1;
+}
+
+static int
+kc_rsa_public_decrypt(int flen,
+ const unsigned char *from,
+ unsigned char *to,
+ RSA *rsa,
+ int padding)
+{
+ return -1;
+}
+
+
+static int
+kc_rsa_private_encrypt(int flen,
+ const unsigned char *from,
+ unsigned char *to,
+ RSA *rsa,
+ int padding)
+{
+ struct kc_rsa *kc = RSA_get_app_data(rsa);
+
+ CSSM_RETURN cret;
+ OSStatus ret;
+ const CSSM_ACCESS_CREDENTIALS *creds;
+ SecKeyRef privKeyRef = (SecKeyRef)kc->item;
+ CSSM_CSP_HANDLE cspHandle;
+ const CSSM_KEY *cssmKey;
+ CSSM_CC_HANDLE sigHandle = 0;
+ CSSM_DATA sig, in;
+ int fret = 0;
+
+
+ cret = SecKeyGetCSSMKey(privKeyRef, &cssmKey);
+ if(cret) abort();
+
+ cret = SecKeyGetCSPHandle(privKeyRef, &cspHandle);
+ if(cret) abort();
+
+ ret = SecKeyGetCredentials(privKeyRef, CSSM_ACL_AUTHORIZATION_SIGN,
+ kSecCredentialTypeDefault, &creds);
+ if(ret) abort();
+
+ ret = CSSM_CSP_CreateSignatureContext(cspHandle, CSSM_ALGID_RSA,
+ creds, cssmKey, &sigHandle);
+ if(ret) abort();
+
+ in.Data = (uint8 *)from;
+ in.Length = flen;
+
+ sig.Data = (uint8 *)to;
+ sig.Length = kc->keysize;
+
+ cret = CSSM_SignData(sigHandle, &in, 1, CSSM_ALGID_NONE, &sig);
+ if(cret) {
+ /* cssmErrorString(cret); */
+ fret = -1;
+ } else
+ fret = sig.Length;
+
+ if(sigHandle)
+ CSSM_DeleteContext(sigHandle);
+
+ return fret;
+}
+
+static int
+kc_rsa_private_decrypt(int flen, const unsigned char *from, unsigned char *to,
+ RSA * rsa, int padding)
+{
+ return -1;
+}
+
+static int
+kc_rsa_init(RSA *rsa)
+{
+ return 1;
+}
+
+static int
+kc_rsa_finish(RSA *rsa)
+{
+ struct kc_rsa *kc_rsa = RSA_get_app_data(rsa);
+ CFRelease(kc_rsa->item);
+ memset(kc_rsa, 0, sizeof(*kc_rsa));
+ free(kc_rsa);
+ return 1;
+}
+
+static const RSA_METHOD kc_rsa_pkcs1_method = {
+ "hx509 Keychain PKCS#1 RSA",
+ kc_rsa_public_encrypt,
+ kc_rsa_public_decrypt,
+ kc_rsa_private_encrypt,
+ kc_rsa_private_decrypt,
+ NULL,
+ NULL,
+ kc_rsa_init,
+ kc_rsa_finish,
+ 0,
+ NULL,
+ NULL,
+ NULL
+};
+
+static int
+set_private_key(hx509_context context,
+ SecKeychainItemRef itemRef,
+ hx509_cert cert)
+{
+ struct kc_rsa *kc;
+ hx509_private_key key;
+ RSA *rsa;
+ int ret;
+
+ ret = _hx509_private_key_init(&key, NULL, NULL);
+ if (ret)
+ return ret;
+
+ kc = calloc(1, sizeof(*kc));
+ if (kc == NULL)
+ _hx509_abort("out of memory");
+
+ kc->item = itemRef;
+
+ rsa = RSA_new();
+ if (rsa == NULL)
+ _hx509_abort("out of memory");
+
+ /* Argh, fake modulus since OpenSSL API is on crack */
+ {
+ SecKeychainAttributeList *attrs = NULL;
+ uint32_t size;
+ void *data;
+
+ rsa->n = BN_new();
+ if (rsa->n == NULL) abort();
+
+ ret = getAttribute(itemRef, kSecKeyKeySizeInBits, &attrs);
+ if (ret) abort();
+
+ size = *(uint32_t *)attrs->attr[0].data;
+ SecKeychainItemFreeAttributesAndData(attrs, NULL);
+
+ kc->keysize = (size + 7) / 8;
+
+ data = malloc(kc->keysize);
+ memset(data, 0xe0, kc->keysize);
+ BN_bin2bn(data, kc->keysize, rsa->n);
+ free(data);
+ }
+ rsa->e = NULL;
+
+ RSA_set_method(rsa, &kc_rsa_pkcs1_method);
+ ret = RSA_set_app_data(rsa, kc);
+ if (ret != 1)
+ _hx509_abort("RSA_set_app_data");
+
+ _hx509_private_key_assign_rsa(key, rsa);
+ _hx509_cert_assign_key(cert, key);
+
+ return 0;
+}
+
+/*
+ *
+ */
+
+struct ks_keychain {
+ SecKeychainRef keychain;
+};
+
+static int
+keychain_init(hx509_context context,
+ hx509_certs certs, void **data, int flags,
+ const char *residue, hx509_lock lock)
+{
+ struct ks_keychain *ctx;
+ OSStatus ret;
+
+ ctx = calloc(1, sizeof(*ctx));
+ if (ctx == NULL) {
+ hx509_clear_error_string(context);
+ return ENOMEM;
+ }
+
+ if (residue) {
+ if (strcasecmp(residue, "system") == 0)
+ residue = "/System/Library/Keychains/X509Anchors";
+
+ ret = SecKeychainOpen(residue, &ctx->keychain);
+ if (ret != noErr) {
+ hx509_set_error_string(context, 0, ENOENT,
+ "Failed to open %s", residue);
+ return ENOENT;
+ }
+ }
+
+ *data = ctx;
+ return 0;
+}
+
+/*
+ *
+ */
+
+static int
+keychain_free(hx509_certs certs, void *data)
+{
+ struct ks_keychain *ctx = data;
+ if (ctx->keychain)
+ CFRelease(ctx->keychain);
+ memset(ctx, 0, sizeof(*ctx));
+ free(ctx);
+ return 0;
+}
+
+/*
+ *
+ */
+
+struct iter {
+ SecKeychainSearchRef searchRef;
+};
+
+static int
+keychain_iter_start(hx509_context context,
+ hx509_certs certs, void *data, void **cursor)
+{
+ struct ks_keychain *ctx = data;
+ struct iter *iter;
+ OSStatus ret;
+
+ iter = calloc(1, sizeof(*iter));
+ if (iter == NULL) {
+ hx509_set_error_string(context, 0, ENOMEM, "out of memory");
+ 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;
+ }
+
+ *cursor = iter;
+ return 0;
+}
+
+/*
+ *
+ */
+
+static int
+keychain_iter(hx509_context context,
+ hx509_certs certs, void *data, void *cursor, hx509_cert *cert)
+{
+ SecKeychainAttributeList *attrs = NULL;
+ SecKeychainAttributeInfo attrInfo;
+ uint32 attrFormat = 0;
+ SecKeychainItemRef itemRef;
+ SecItemAttr item;
+ struct iter *iter = cursor;
+ Certificate t;
+ OSStatus ret;
+ UInt32 len;
+ void *ptr = NULL;
+ size_t size;
+
+ *cert = NULL;
+
+ ret = SecKeychainSearchCopyNext(iter->searchRef, &itemRef);
+ if (ret == errSecItemNotFound)
+ return 0;
+ else if (ret != 0)
+ return EINVAL;
+
+ /*
+ * Pick out certificate and matching "keyid"
+ */
+
+ item = kSecPublicKeyHashItemAttr;
+
+ attrInfo.count = 1;
+ 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);
+ if (ret)
+ goto out;
+
+ /*
+ * Find related private key if there is one by looking at
+ * kSecPublicKeyHashItemAttr == kSecKeyLabel
+ */
+ {
+ SecKeychainSearchRef search;
+ SecKeychainAttribute attrKeyid;
+ SecKeychainAttributeList attrList;
+
+ attrKeyid.tag = kSecKeyLabel;
+ attrKeyid.length = attrs->attr[0].length;
+ attrKeyid.data = attrs->attr[0].data;
+
+ attrList.count = 1;
+ attrList.attr = &attrKeyid;
+
+ ret = SecKeychainSearchCreateFromAttributes(NULL,
+ CSSM_DL_DB_RECORD_PRIVATE_KEY,
+ &attrList,
+ &search);
+ if (ret) {
+ ret = 0;
+ goto out;
+ }
+
+ ret = SecKeychainSearchCopyNext(search, &itemRef);
+ CFRelease(search);
+ if (ret == errSecItemNotFound) {
+ ret = 0;
+ goto out;
+ } else if (ret) {
+ ret = EINVAL;
+ goto out;
+ }
+ set_private_key(context, itemRef, *cert);
+ }
+
+out:
+ SecKeychainItemFreeAttributesAndData(attrs, ptr);
+
+ return ret;
+}
+
+/*
+ *
+ */
+
+static int
+keychain_iter_end(hx509_context context,
+ hx509_certs certs,
+ void *data,
+ void *cursor)
+{
+ struct iter *iter = cursor;
+
+ CFRelease(iter->searchRef);
+ memset(iter, 0, sizeof(*iter));
+ free(iter);
+ return 0;
+}
+
+/*
+ *
+ */
+
+struct hx509_keyset_ops keyset_keychain = {
+ "KEYCHAIN",
+ 0,
+ keychain_init,
+ NULL,
+ keychain_free,
+ NULL,
+ NULL,
+ keychain_iter_start,
+ keychain_iter,
+ keychain_iter_end
+};
+
+#endif /* HAVE_FRAMEWORK_SECURITY */
+
+/*
+ *
+ */
+
+void
+_hx509_ks_keychain_register(hx509_context context)
+{
+#ifdef HAVE_FRAMEWORK_SECURITY
+ _hx509_ks_register(context, &keyset_keychain);
+#endif
+}
diff --git a/source4/heimdal/lib/hx509/ks_mem.c b/source4/heimdal/lib/hx509/ks_mem.c
index dd7b7166bc..efa19eb19c 100644
--- a/source4/heimdal/lib/hx509/ks_mem.c
+++ b/source4/heimdal/lib/hx509/ks_mem.c
@@ -80,6 +80,7 @@ mem_free(hx509_certs certs, void *data)
free(mem->certs.val);
for (i = 0; mem->keys && mem->keys[i]; i++)
_hx509_private_key_free(&mem->keys[i]);
+ free(mem->keys);
free(mem->name);
free(mem);
@@ -162,7 +163,7 @@ mem_getkeys(hx509_context context,
for (i = 0; mem->keys && mem->keys[i]; i++)
;
- *keys = calloc(i, sizeof(**keys));
+ *keys = calloc(i + 1, sizeof(**keys));
for (i = 0; mem->keys && mem->keys[i]; i++) {
(*keys)[i] = _hx509_private_key_ref(mem->keys[i]);
if ((*keys)[i] == NULL) {
diff --git a/source4/heimdal/lib/hx509/ks_null.c b/source4/heimdal/lib/hx509/ks_null.c
index 1e6c2ea3fb..3be259fc60 100644
--- a/source4/heimdal/lib/hx509/ks_null.c
+++ b/source4/heimdal/lib/hx509/ks_null.c
@@ -32,7 +32,7 @@
*/
#include "hx_locl.h"
-RCSID("$Id: ks_null.c,v 1.5 2007/01/09 10:52:10 lha Exp $");
+RCSID("$Id: ks_null.c 20901 2007-06-04 23:14:08Z lha $");
static int
@@ -90,3 +90,9 @@ struct hx509_keyset_ops keyset_null = {
null_iter,
null_iter_end
};
+
+void
+_hx509_ks_null_register(hx509_context context)
+{
+ _hx509_ks_register(context, &keyset_null);
+}
diff --git a/source4/heimdal/lib/hx509/ks_p11.c b/source4/heimdal/lib/hx509/ks_p11.c
index b103264b7a..90c716213f 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,v 1.45 2007/01/09 19:43:35 lha Exp $");
+RCSID("$Id: ks_p11.c 20920 2007-06-05 05:47:06Z lha $");
#ifdef HAVE_DLFCN_H
#include <dlfcn.h>
#endif
@@ -214,7 +214,7 @@ p11_rsa_finish(RSA *rsa)
return 1;
}
-static const RSA_METHOD rsa_pkcs1_method = {
+static const RSA_METHOD p11_rsa_pkcs1_method = {
"hx509 PKCS11 PKCS#1 RSA",
p11_rsa_public_encrypt,
p11_rsa_public_decrypt,
@@ -644,7 +644,7 @@ collect_private_key(hx509_context context,
if (p->refcount == 0)
_hx509_abort("pkcs11 refcount to high");
- RSA_set_method(rsa, &rsa_pkcs1_method);
+ RSA_set_method(rsa, &p11_rsa_pkcs1_method);
ret = RSA_set_app_data(rsa, p11rsa);
if (ret != 1)
_hx509_abort("RSA_set_app_data");
@@ -766,11 +766,9 @@ p11_list_keys(hx509_context context,
if (lock == NULL)
lock = _hx509_empty_lock;
- collector = _hx509_collector_alloc(context, lock);
- if (collector == NULL) {
- hx509_set_error_string(context, 0, ENOMEM, "out of memory");
- return ENOMEM;
- }
+ ret = _hx509_collector_alloc(context, lock, &collector);
+ if (ret)
+ return ret;
key_class = CKO_PRIVATE_KEY;
ret = iterate_entries(context, p, slot, session,
@@ -1113,7 +1111,7 @@ static int
p11_printinfo(hx509_context context,
hx509_certs certs,
void *data,
- int (*func)(void *, char *),
+ int (*func)(void *, const char *),
void *ctx)
{
struct p11_module *p = data;
@@ -1140,6 +1138,17 @@ p11_printinfo(hx509_context context,
MECHNAME(CKM_RSA_X_509, "rsa-x-509");
MECHNAME(CKM_MD5_RSA_PKCS, "md5-rsa-pkcs");
MECHNAME(CKM_SHA1_RSA_PKCS, "sha1-rsa-pkcs");
+ MECHNAME(CKM_RIPEMD160_RSA_PKCS, "ripemd160-rsa-pkcs");
+ MECHNAME(CKM_RSA_PKCS_OAEP, "rsa-pkcs-oaep");
+ MECHNAME(CKM_SHA_1, "sha1");
+ MECHNAME(CKM_MD5, "md5");
+ MECHNAME(CKM_MD2, "md2");
+ MECHNAME(CKM_RIPEMD160, "ripemd-160");
+ MECHNAME(CKM_DES_ECB, "des-ecb");
+ MECHNAME(CKM_DES_CBC, "des-cbc");
+ MECHNAME(CKM_AES_ECB, "aes-ecb");
+ MECHNAME(CKM_AES_CBC, "aes-cbc");
+ MECHNAME(CKM_DH_PKCS_PARAMETER_GEN, "dh-pkcs-parameter-gen");
default:
snprintf(unknownname, sizeof(unknownname),
"unknown-mech-%lu",
diff --git a/source4/heimdal/lib/hx509/ks_p12.c b/source4/heimdal/lib/hx509/ks_p12.c
index 69dba802e5..5fddbd07de 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,v 1.18 2007/01/09 10:52:11 lha Exp $");
+RCSID("$Id: ks_p12.c 20909 2007-06-05 03:09:13Z lha $");
struct ks_pkcs12 {
hx509_certs certs;
@@ -341,39 +341,45 @@ p12_init(hx509_context context,
if (lock == NULL)
lock = _hx509_empty_lock;
- c = _hx509_collector_alloc(context, lock);
- if (c == NULL)
- return ENOMEM;
+ ret = _hx509_collector_alloc(context, lock, &c);
+ if (ret)
+ return ret;
p12 = calloc(1, sizeof(*p12));
if (p12 == NULL) {
ret = ENOMEM;
+ hx509_set_error_string(context, 0, ret, "out of memory");
goto out;
}
p12->fn = strdup(residue);
if (p12->fn == NULL) {
ret = ENOMEM;
+ hx509_set_error_string(context, 0, ret, "out of memory");
goto out;
}
if (flags & HX509_CERTS_CREATE) {
- ret = hx509_certs_init(context, "MEMORY:ks-file-create",
+ ret = hx509_certs_init(context, "MEMORY:ks-file-create",
0, lock, &p12->certs);
- if (ret)
- goto out;
- *data = p12;
- return 0;
+ if (ret == 0)
+ *data = p12;
+ goto out;
}
ret = _hx509_map_file(residue, &buf, &len, NULL);
- if (ret)
+ if (ret) {
+ hx509_clear_error_string(context);
goto out;
+ }
ret = decode_PKCS12_PFX(buf, len, &pfx, NULL);
_hx509_unmap_file(buf, len);
- if (ret)
+ if (ret) {
+ hx509_set_error_string(context, 0, ret,
+ "Failed to decode the PFX in %s", residue);
goto out;
+ }
if (der_heim_oid_cmp(&pfx.authSafe.contentType, oid_id_pkcs7_data()) != 0) {
free_PKCS12_PFX(&pfx);
@@ -452,15 +458,20 @@ addBag(hx509_context context,
ptr = realloc(as->val, sizeof(as->val[0]) * (as->len + 1));
if (ptr == NULL) {
- hx509_set_error_string(context, 0, ENOMEM, "malloc out of memory");
+ hx509_set_error_string(context, 0, ENOMEM, "out of memory");
return ENOMEM;
}
as->val = ptr;
ret = der_copy_oid(oid, &as->val[as->len].contentType);
+ if (ret) {
+ hx509_set_error_string(context, 0, ret, "out of memory");
+ return ret;
+ }
as->val[as->len].content = calloc(1, sizeof(*as->val[0].content));
if (as->val[as->len].content == NULL) {
+ der_free_oid(&as->val[as->len].contentType);
hx509_set_error_string(context, 0, ENOMEM, "malloc out of memory");
return ENOMEM;
}
@@ -488,11 +499,11 @@ store_func(hx509_context context, void *ctx, hx509_cert c)
os.data = NULL;
os.length = 0;
- ASN1_MALLOC_ENCODE(Certificate, os.data, os.length,
- _hx509_get_cert(c), &size, ret);
+ ret = hx509_cert_binary(context, c, &os);
if (ret)
- goto out;
- ASN1_MALLOC_ENCODE(PKCS12_OctetString,
+ return ret;
+
+ ASN1_MALLOC_ENCODE(PKCS12_OctetString,
cb.certValue.data,cb.certValue.length,
&os, &size, ret);
free(os.data);
@@ -505,7 +516,7 @@ store_func(hx509_context context, void *ctx, hx509_cert c)
}
ASN1_MALLOC_ENCODE(PKCS12_CertBag, os.data, os.length,
&cb, &size, ret);
- free(cb.certValue.data);
+ free_PKCS12_CertBag(&cb);
if (ret)
goto out;
diff --git a/source4/heimdal/lib/hx509/lock.c b/source4/heimdal/lib/hx509/lock.c
index 95fc0aa26d..de326f2e2d 100644
--- a/source4/heimdal/lib/hx509/lock.c
+++ b/source4/heimdal/lib/hx509/lock.c
@@ -32,7 +32,7 @@
*/
#include "hx_locl.h"
-RCSID("$Id: lock.c,v 1.13 2006/10/14 09:41:05 lha Exp $");
+RCSID("$Id: lock.c 18452 2006-10-14 09:41:05Z lha $");
struct hx509_lock_data {
struct _hx509_password password;
diff --git a/source4/heimdal/lib/hx509/name.c b/source4/heimdal/lib/hx509/name.c
index 92e9e6f974..5198633b1e 100644
--- a/source4/heimdal/lib/hx509/name.c
+++ b/source4/heimdal/lib/hx509/name.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004 - 2006 Kungliga Tekniska Högskolan
+ * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -32,7 +32,7 @@
*/
#include "hx_locl.h"
-RCSID("$Id: name.c,v 1.33 2006/12/30 23:04:11 lha Exp $");
+RCSID("$Id: name.c 20891 2007-06-04 22:51:41Z lha $");
/*
* name parsing from rfc2253
@@ -41,7 +41,7 @@ RCSID("$Id: name.c,v 1.33 2006/12/30 23:04:11 lha Exp $");
*/
static const struct {
- char *n;
+ const char *n;
const heim_oid *(*o)(void);
} no[] = {
{ "C", oid_id_at_countryName },
@@ -51,6 +51,7 @@ static const struct {
{ "O", oid_id_at_organizationName },
{ "OU", oid_id_at_organizationalUnitName },
{ "S", oid_id_at_stateOrProvinceName },
+ { "STREET", oid_id_at_streetAddress },
{ "UID", oid_id_Userid },
{ "emailAddress", oid_id_pkcs9_emailAddress },
{ "serialNumber", oid_id_at_serialNumber }
@@ -81,25 +82,27 @@ quote_string(const char *f, size_t len, size_t *rlen)
to[j++] = from[i];
} else {
int l = snprintf(&to[j], tolen - j - 1,
- "#%02x", (unsigned int)from[i]);
+ "#%02x", (unsigned char)from[i]);
j += l;
}
}
to[j] = '\0';
+ assert(j < tolen);
*rlen = j;
return to;
}
static int
-append_string(char **str, size_t *total_len, char *ss, size_t len, int quote)
+append_string(char **str, size_t *total_len, const char *ss,
+ size_t len, int quote)
{
char *s, *qs;
if (quote)
qs = quote_string(ss, len, &len);
else
- qs = ss;
+ qs = rk_UNCONST(ss);
s = realloc(*str, len + *total_len + 1);
if (s == NULL)
@@ -181,10 +184,10 @@ _hx509_Name_to_string(const Name *n, char **str)
ss = ds->u.ia5String;
break;
case choice_DirectoryString_printableString:
- ss = ds->u.ia5String;
+ ss = ds->u.printableString;
break;
case choice_DirectoryString_utf8String:
- ss = ds->u.ia5String;
+ ss = ds->u.utf8String;
break;
case choice_DirectoryString_bmpString: {
uint16_t *bmp = ds->u.bmpString.data;
@@ -200,11 +203,25 @@ _hx509_Name_to_string(const Name *n, char **str)
break;
}
case choice_DirectoryString_teletexString:
- ss = "teletex-string"; /* XXX */
+ ss = malloc(ds->u.teletexString.length + 1);
+ if (ss == NULL)
+ _hx509_abort("allocation failure"); /* XXX */
+ memcpy(ss, ds->u.teletexString.data, ds->u.teletexString.length);
+ ss[ds->u.teletexString.length] = '\0';
break;
- case choice_DirectoryString_universalString:
- ss = "universalString"; /* XXX */
+ case choice_DirectoryString_universalString: {
+ uint32_t *uni = ds->u.universalString.data;
+ size_t unilen = ds->u.universalString.length;
+ size_t k;
+
+ ss = malloc(unilen + 1);
+ if (ss == NULL)
+ _hx509_abort("allocation failure"); /* XXX */
+ for (k = 0; k < unilen; k++)
+ ss[k] = uni[k] & 0xff; /* XXX */
+ ss[k] = '\0';
break;
+ }
default:
_hx509_abort("unknown directory type: %d", ds->element);
exit(1);
@@ -214,8 +231,12 @@ _hx509_Name_to_string(const Name *n, char **str)
append_string(str, &total_len, "=", 1, 0);
len = strlen(ss);
append_string(str, &total_len, ss, len, 1);
- if (ds->element == choice_DirectoryString_bmpString)
+ if (ds->element == choice_DirectoryString_universalString ||
+ ds->element == choice_DirectoryString_bmpString ||
+ ds->element == choice_DirectoryString_teletexString)
+ {
free(ss);
+ }
if (j + 1 < n->u.rdnSequence.val[i].len)
append_string(str, &total_len, "+", 1, 0);
}
@@ -299,6 +320,13 @@ _hx509_name_cmp(const Name *n1, const Name *n2)
}
int
+hx509_name_cmp(hx509_name n1, hx509_name n2)
+{
+ return _hx509_name_cmp(&n1->der_name, &n2->der_name);
+}
+
+
+int
_hx509_name_from_Name(const Name *n, hx509_name *name)
{
int ret;
@@ -487,6 +515,106 @@ hx509_name_to_Name(const hx509_name from, Name *to)
return copy_Name(&from->der_name, to);
}
+int
+hx509_name_normalize(hx509_context context, hx509_name name)
+{
+ return 0;
+}
+
+int
+hx509_name_expand(hx509_context context,
+ hx509_name name,
+ hx509_env env)
+{
+ Name *n = &name->der_name;
+ int i, j;
+
+ if (env == NULL)
+ return 0;
+
+ if (n->element != choice_Name_rdnSequence) {
+ hx509_set_error_string(context, 0, EINVAL, "RDN not of supported type");
+ return EINVAL;
+ }
+
+ for (i = 0 ; i < n->u.rdnSequence.len; i++) {
+ for (j = 0; j < n->u.rdnSequence.val[i].len; j++) {
+ /*
+ THIS SHOULD REALLY BE:
+ COMP = n->u.rdnSequence.val[i].val[j];
+ normalize COMP to utf8
+ check if there are variables
+ expand variables
+ convert back to orignal format, store in COMP
+ free normalized utf8 string
+ */
+ DirectoryString *ds = &n->u.rdnSequence.val[i].val[j].value;
+ char *p, *p2;
+ struct rk_strpool *strpool = NULL;
+
+ if (ds->element != choice_DirectoryString_utf8String) {
+ hx509_set_error_string(context, 0, EINVAL, "unsupported type");
+ return EINVAL;
+ }
+ p = strstr(ds->u.utf8String, "${");
+ if (p) {
+ strpool = rk_strpoolprintf(strpool, "%.*s",
+ (int)(p - ds->u.utf8String),
+ ds->u.utf8String);
+ if (strpool == NULL) {
+ hx509_set_error_string(context, 0, ENOMEM, "out of memory");
+ return ENOMEM;
+ }
+ }
+ while (p != NULL) {
+ /* expand variables */
+ const char *value;
+ p2 = strchr(p, '}');
+ if (p2 == NULL) {
+ hx509_set_error_string(context, 0, EINVAL, "missing }");
+ rk_strpoolfree(strpool);
+ return EINVAL;
+ }
+ p += 2;
+ value = hx509_env_lfind(context, env, p, p2 - p);
+ if (value == NULL) {
+ hx509_set_error_string(context, 0, EINVAL,
+ "variable %.*s missing",
+ (int)(p2 - p), p);
+ rk_strpoolfree(strpool);
+ return EINVAL;
+ }
+ strpool = rk_strpoolprintf(strpool, "%s", value);
+ if (strpool == NULL) {
+ hx509_set_error_string(context, 0, ENOMEM, "out of memory");
+ return ENOMEM;
+ }
+ p2++;
+
+ p = strstr(p2, "${");
+ if (p)
+ strpool = rk_strpoolprintf(strpool, "%.*s",
+ (int)(p - p2), p2);
+ else
+ strpool = rk_strpoolprintf(strpool, "%s", p2);
+ if (strpool == NULL) {
+ hx509_set_error_string(context, 0, ENOMEM, "out of memory");
+ return ENOMEM;
+ }
+ }
+ if (strpool) {
+ free(ds->u.utf8String);
+ ds->u.utf8String = rk_strpoolcollect(strpool);
+ if (ds->u.utf8String == NULL) {
+ hx509_set_error_string(context, 0, ENOMEM, "out of memory");
+ return ENOMEM;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
void
hx509_name_free(hx509_name *name)
@@ -548,3 +676,91 @@ hx509_name_is_null_p(const hx509_name name)
{
return name->der_name.u.rdnSequence.len == 0;
}
+
+int
+hx509_general_name_unparse(GeneralName *name, char **str)
+{
+ struct rk_strpool *strpool = NULL;
+
+ *str = NULL;
+
+ switch (name->element) {
+ case choice_GeneralName_otherName: {
+ char *str;
+ hx509_oid_sprint(&name->u.otherName.type_id, &str);
+ if (str == NULL)
+ return ENOMEM;
+ strpool = rk_strpoolprintf(strpool, "otherName: %s", str);
+ free(str);
+ break;
+ }
+ case choice_GeneralName_rfc822Name:
+ strpool = rk_strpoolprintf(strpool, "rfc822Name: %s\n",
+ name->u.rfc822Name);
+ break;
+ case choice_GeneralName_dNSName:
+ strpool = rk_strpoolprintf(strpool, "dNSName: %s\n",
+ name->u.dNSName);
+ break;
+ case choice_GeneralName_directoryName: {
+ Name dir;
+ char *s;
+ int ret;
+ memset(&dir, 0, sizeof(dir));
+ dir.element = name->u.directoryName.element;
+ dir.u.rdnSequence = name->u.directoryName.u.rdnSequence;
+ ret = _hx509_unparse_Name(&dir, &s);
+ if (ret)
+ return ret;
+ strpool = rk_strpoolprintf(strpool, "directoryName: %s", s);
+ free(s);
+ break;
+ }
+ case choice_GeneralName_uniformResourceIdentifier:
+ strpool = rk_strpoolprintf(strpool, "URI: %s",
+ name->u.uniformResourceIdentifier);
+ break;
+ case choice_GeneralName_iPAddress: {
+ unsigned char *a = name->u.iPAddress.data;
+
+ strpool = rk_strpoolprintf(strpool, "IPAddress: ");
+ if (strpool == NULL)
+ break;
+ if (name->u.iPAddress.length == 4)
+ strpool = rk_strpoolprintf(strpool, "%d.%d.%d.%d",
+ a[0], a[1], a[2], a[3]);
+ else if (name->u.iPAddress.length == 16)
+ strpool = rk_strpoolprintf(strpool,
+ "%02X:%02X:%02X:%02X:"
+ "%02X:%02X:%02X:%02X:"
+ "%02X:%02X:%02X:%02X:"
+ "%02X:%02X:%02X:%02X",
+ a[0], a[1], a[2], a[3],
+ a[4], a[5], a[6], a[7],
+ a[8], a[9], a[10], a[11],
+ a[12], a[13], a[14], a[15]);
+ else
+ strpool = rk_strpoolprintf(strpool,
+ "unknown IP address of length %lu",
+ (unsigned long)name->u.iPAddress.length);
+ break;
+ }
+ case choice_GeneralName_registeredID: {
+ char *str;
+ hx509_oid_sprint(&name->u.registeredID, &str);
+ if (str == NULL)
+ return ENOMEM;
+ strpool = rk_strpoolprintf(strpool, "registeredID: %s", str);
+ free(str);
+ break;
+ }
+ default:
+ return EINVAL;
+ }
+ if (strpool == NULL)
+ return ENOMEM;
+
+ *str = rk_strpoolcollect(strpool);
+
+ return 0;
+}
diff --git a/source4/heimdal/lib/hx509/ocsp.asn1 b/source4/heimdal/lib/hx509/ocsp.asn1
index 62a2750b96..d8ecd66ccf 100644
--- a/source4/heimdal/lib/hx509/ocsp.asn1
+++ b/source4/heimdal/lib/hx509/ocsp.asn1
@@ -1,5 +1,5 @@
-- From rfc2560
--- $Id: ocsp.asn1,v 1.4 2006/12/30 12:38:44 lha Exp $
+-- $Id: ocsp.asn1 19576 2006-12-30 12:40:43Z lha $
OCSP DEFINITIONS EXPLICIT TAGS::=
BEGIN
diff --git a/source4/heimdal/lib/hx509/peer.c b/source4/heimdal/lib/hx509/peer.c
index f82f2877f6..eccedf1043 100644
--- a/source4/heimdal/lib/hx509/peer.c
+++ b/source4/heimdal/lib/hx509/peer.c
@@ -32,7 +32,7 @@
*/
#include "hx_locl.h"
-RCSID("$Id: peer.c,v 1.1 2006/11/26 15:49:01 lha Exp $");
+RCSID("$Id: peer.c 20938 2007-06-06 20:51:34Z lha $");
int
hx509_peer_info_alloc(hx509_context context, hx509_peer_info *peer)
@@ -59,14 +59,16 @@ free_cms_alg(hx509_peer_info peer)
}
}
-int
+void
hx509_peer_info_free(hx509_peer_info peer)
{
+ if (peer == NULL)
+ return;
if (peer->cert)
hx509_cert_free(peer->cert);
free_cms_alg(peer);
memset(peer, 0, sizeof(*peer));
- return 0;
+ free(peer);
}
int
diff --git a/source4/heimdal/lib/hx509/pkcs10.asn1 b/source4/heimdal/lib/hx509/pkcs10.asn1
index c33fd36cb2..518fe3bfa3 100644
--- a/source4/heimdal/lib/hx509/pkcs10.asn1
+++ b/source4/heimdal/lib/hx509/pkcs10.asn1
@@ -1,4 +1,4 @@
--- $Id: pkcs10.asn1,v 1.1 2006/04/01 09:46:57 lha Exp $
+-- $Id: pkcs10.asn1 16918 2006-04-01 09:46:57Z lha $
PKCS10 DEFINITIONS ::=
BEGIN
diff --git a/source4/heimdal/lib/hx509/print.c b/source4/heimdal/lib/hx509/print.c
index 802ac12b4e..dc9d4cfa58 100644
--- a/source4/heimdal/lib/hx509/print.c
+++ b/source4/heimdal/lib/hx509/print.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004 - 2006 Kungliga Tekniska Högskolan
+ * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -32,7 +32,7 @@
*/
#include "hx_locl.h"
-RCSID("$Id: print.c,v 1.15 2006/12/07 20:37:57 lha Exp $");
+RCSID("$Id: print.c 20908 2007-06-05 02:59:33Z lha $");
struct hx509_validate_ctx_data {
@@ -41,6 +41,18 @@ struct hx509_validate_ctx_data {
void *ctx;
};
+struct cert_status {
+ unsigned int selfsigned:1;
+ unsigned int isca:1;
+ unsigned int isproxy:1;
+ unsigned int haveSAN:1;
+ unsigned int haveIAN:1;
+ unsigned int haveSKI:1;
+ unsigned int haveAKI:1;
+ unsigned int haveCRLDP:1;
+};
+
+
/*
*
*/
@@ -155,10 +167,16 @@ validate_print(hx509_validate_ctx ctx, int flags, const char *fmt, ...)
va_end(va);
}
+/*
+ * Dont Care, SHOULD critical, SHOULD NOT critical, MUST critical,
+ * MUST NOT critical
+ */
enum critical_flag { D_C = 0, S_C, S_N_C, M_C, M_N_C };
static int
-check_Null(hx509_validate_ctx ctx, enum critical_flag cf, const Extension *e)
+check_Null(hx509_validate_ctx ctx,
+ struct cert_status *status,
+ enum critical_flag cf, const Extension *e)
{
switch(cf) {
case D_C:
@@ -191,13 +209,96 @@ check_Null(hx509_validate_ctx ctx, enum critical_flag cf, const Extension *e)
static int
check_subjectKeyIdentifier(hx509_validate_ctx ctx,
+ struct cert_status *status,
enum critical_flag cf,
const Extension *e)
{
- check_Null(ctx, cf, e);
+ SubjectKeyIdentifier si;
+ size_t size;
+ int ret;
+
+ status->haveSKI = 1;
+ check_Null(ctx, status, cf, e);
+
+ ret = decode_SubjectKeyIdentifier(e->extnValue.data,
+ e->extnValue.length,
+ &si, &size);
+ if (ret) {
+ validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
+ "Decoding SubjectKeyIdentifier failed: %d", ret);
+ return 1;
+ }
+ if (size != e->extnValue.length) {
+ validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
+ "Decoding SKI ahve extra bits on the end");
+ return 1;
+ }
+ if (si.length == 0)
+ validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
+ "SKI is too short (0 bytes)");
+ if (si.length > 20)
+ validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
+ "SKI is too long");
+
+ {
+ char *id;
+ hex_encode(si.data, si.length, &id);
+ if (id) {
+ validate_print(ctx, HX509_VALIDATE_F_VERBOSE,
+ "\tsubject key id: %s\n", id);
+ free(id);
+ }
+ }
+
+ free_SubjectKeyIdentifier(&si);
+
+ return 0;
+}
+
+static int
+check_authorityKeyIdentifier(hx509_validate_ctx ctx,
+ struct cert_status *status,
+ enum critical_flag cf,
+ const Extension *e)
+{
+ AuthorityKeyIdentifier ai;
+ size_t size;
+ int ret;
+
+ status->haveAKI = 1;
+ check_Null(ctx, status, cf, e);
+
+ status->haveSKI = 1;
+ check_Null(ctx, status, cf, e);
+
+ ret = decode_AuthorityKeyIdentifier(e->extnValue.data,
+ e->extnValue.length,
+ &ai, &size);
+ if (ret) {
+ validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
+ "Decoding AuthorityKeyIdentifier failed: %d", ret);
+ return 1;
+ }
+ if (size != e->extnValue.length) {
+ validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
+ "Decoding SKI ahve extra bits on the end");
+ return 1;
+ }
+
+ if (ai.keyIdentifier) {
+ char *id;
+ hex_encode(ai.keyIdentifier->data, ai.keyIdentifier->length, &id);
+ if (id) {
+ validate_print(ctx, HX509_VALIDATE_F_VERBOSE,
+ "\tauthority key id: %s\n", id);
+ free(id);
+ }
+ }
+
return 0;
}
+
static int
check_pkinit_san(hx509_validate_ctx ctx, heim_any *a)
{
@@ -206,15 +307,16 @@ check_pkinit_san(hx509_validate_ctx ctx, heim_any *a)
size_t size;
int ret;
- ret = decode_KRB5PrincipalName(a->data, a->length,
- &kn, &size);
+ ret = decode_KRB5PrincipalName(a->data, a->length, &kn, &size);
if (ret) {
- printf("Decoding kerberos name in SAN failed: %d", ret);
+ validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
+ "Decoding kerberos name in SAN failed: %d", ret);
return 1;
}
if (size != a->length) {
- printf("Decoding kerberos name have extra bits on the end");
+ validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
+ "Decoding kerberos name have extra bits on the end");
return 1;
}
@@ -233,22 +335,117 @@ check_pkinit_san(hx509_validate_ctx ctx, heim_any *a)
}
static int
-check_dnssrv_san(hx509_validate_ctx ctx, heim_any *a)
+check_utf8_string_san(hx509_validate_ctx ctx, heim_any *a)
{
+ PKIXXmppAddr jid;
+ size_t size;
+ int ret;
+
+ ret = decode_PKIXXmppAddr(a->data, a->length, &jid, &size);
+ if (ret) {
+ validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
+ "Decoding JID in SAN failed: %d", ret);
+ return 1;
+ }
+
+ validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "%s", jid);
+ free_PKIXXmppAddr(&jid);
+
return 0;
}
+static int
+check_altnull(hx509_validate_ctx ctx, heim_any *a)
+{
+ return 0;
+}
+
+static int
+check_CRLDistributionPoints(hx509_validate_ctx ctx,
+ struct cert_status *status,
+ enum critical_flag cf,
+ const Extension *e)
+{
+ CRLDistributionPoints dp;
+ size_t size;
+ int ret, i;
+
+ check_Null(ctx, status, cf, e);
+
+ ret = decode_CRLDistributionPoints(e->extnValue.data,
+ e->extnValue.length,
+ &dp, &size);
+ if (ret) {
+ validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
+ "Decoding CRL Distribution Points failed: %d\n", ret);
+ return 1;
+ }
+
+ validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "CRL Distribution Points:\n");
+ for (i = 0 ; i < dp.len; i++) {
+ if (dp.val[i].distributionPoint) {
+ DistributionPointName dpname;
+ heim_any *data = dp.val[i].distributionPoint;
+ int j;
+
+ ret = decode_DistributionPointName(data->data, data->length,
+ &dpname, NULL);
+ if (ret) {
+ validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
+ "Failed to parse CRL Distribution Point Name: %d\n", ret);
+ continue;
+ }
+
+ switch (dpname.element) {
+ case choice_DistributionPointName_fullName:
+ validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "Fullname:\n");
+
+ for (j = 0 ; j < dpname.u.fullName.len; j++) {
+ char *s;
+ GeneralName *name = &dpname.u.fullName.val[j];
+
+ ret = hx509_general_name_unparse(name, &s);
+ if (ret == 0 && s != NULL) {
+ validate_print(ctx, HX509_VALIDATE_F_VERBOSE, " %s\n", s);
+ free(s);
+ }
+ }
+ break;
+ case choice_DistributionPointName_nameRelativeToCRLIssuer:
+ validate_print(ctx, HX509_VALIDATE_F_VERBOSE,
+ "Unknown nameRelativeToCRLIssuer");
+ break;
+ default:
+ validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
+ "Unknown DistributionPointName");
+ break;
+ }
+ free_DistributionPointName(&dpname);
+ }
+ }
+ free_CRLDistributionPoints(&dp);
+
+ status->haveCRLDP = 1;
+
+ return 0;
+}
+
+
struct {
const char *name;
const heim_oid *(*oid)(void);
int (*func)(hx509_validate_ctx, heim_any *);
} check_altname[] = {
{ "pk-init", oid_id_pkinit_san, check_pkinit_san },
- { "dns-srv", oid_id_pkix_on_dnsSRV, check_dnssrv_san }
+ { "jabber", oid_id_pkix_on_xmppAddr, check_utf8_string_san },
+ { "dns-srv", oid_id_pkix_on_dnsSRV, check_altnull },
+ { "card-id", oid_id_uspkicommon_card_id, check_altnull },
+ { "Microsoft NT-PRINCIPAL-NAME", oid_id_pkinit_ms_san, check_utf8_string_san }
};
static int
check_altName(hx509_validate_ctx ctx,
+ struct cert_status *status,
const char *name,
enum critical_flag cf,
const Extension *e)
@@ -257,20 +454,24 @@ check_altName(hx509_validate_ctx ctx,
size_t size;
int ret, i;
- check_Null(ctx, cf, e);
+ check_Null(ctx, status, cf, e);
if (e->extnValue.length == 0) {
- printf("%sAltName empty, not allowed", name);
+ validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
+ "%sAltName empty, not allowed", name);
return 1;
}
ret = decode_GeneralNames(e->extnValue.data, e->extnValue.length,
&gn, &size);
if (ret) {
- printf("\tret = %d while decoding %s GeneralNames\n", ret, name);
+ validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
+ "\tret = %d while decoding %s GeneralNames\n",
+ ret, name);
return 1;
}
if (gn.len == 0) {
- printf("%sAltName generalName empty, not allowed", name);
+ validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
+ "%sAltName generalName empty, not allowed\n", name);
return 1;
}
@@ -278,7 +479,9 @@ check_altName(hx509_validate_ctx ctx,
switch (gn.val[i].element) {
case choice_GeneralName_otherName: {
unsigned j;
- validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "%sAltName otherName ", name);
+
+ validate_print(ctx, HX509_VALIDATE_F_VERBOSE,
+ "%sAltName otherName ", name);
for (j = 0; j < sizeof(check_altname)/sizeof(check_altname[0]); j++) {
if (der_heim_oid_cmp((*check_altname[j].oid)(),
@@ -298,41 +501,18 @@ check_altName(hx509_validate_ctx ctx,
validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "\n");
break;
}
- case choice_GeneralName_rfc822Name:
- validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "rfc822Name: %s\n",
- gn.val[i].u.rfc822Name);
- break;
- case choice_GeneralName_dNSName:
- validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "dNSName: %s\n",
- gn.val[i].u.dNSName);
- break;
- case choice_GeneralName_directoryName: {
- Name dir;
+ default: {
char *s;
- dir.element = gn.val[i].u.directoryName.element;
- dir.u.rdnSequence = gn.val[i].u.directoryName.u.rdnSequence;
- ret = _hx509_unparse_Name(&dir, &s);
+ ret = hx509_general_name_unparse(&gn.val[i], &s);
if (ret) {
- printf("unable to parse %sAltName directoryName\n", name);
+ validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
+ "ret = %d unparsing GeneralName\n", ret);
return 1;
}
- validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "directoryName: %s\n", s);
+ validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "%s\n", s);
free(s);
break;
}
- case choice_GeneralName_uniformResourceIdentifier:
- validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "uri: %s\n",
- gn.val[i].u.uniformResourceIdentifier);
- break;
- case choice_GeneralName_iPAddress:
- validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "ip address\n");
- break;
- case choice_GeneralName_registeredID:
- validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "registered id: ");
- hx509_oid_print(&gn.val[i].u.registeredID,
- validate_vprint, ctx);
- validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "\n");
- break;
}
}
@@ -343,23 +523,28 @@ check_altName(hx509_validate_ctx ctx,
static int
check_subjectAltName(hx509_validate_ctx ctx,
+ struct cert_status *status,
enum critical_flag cf,
const Extension *e)
{
- return check_altName(ctx, "subject", cf, e);
+ status->haveSAN = 1;
+ return check_altName(ctx, status, "subject", cf, e);
}
static int
check_issuerAltName(hx509_validate_ctx ctx,
+ struct cert_status *status,
enum critical_flag cf,
const Extension *e)
{
- return check_altName(ctx, "issuer", cf, e);
+ status->haveIAN = 1;
+ return check_altName(ctx, status, "issuer", cf, e);
}
static int
check_basicConstraints(hx509_validate_ctx ctx,
+ struct cert_status *status,
enum critical_flag cf,
const Extension *e)
{
@@ -367,7 +552,7 @@ check_basicConstraints(hx509_validate_ctx ctx,
size_t size;
int ret;
- check_Null(ctx, cf, e);
+ check_Null(ctx, status, cf, e);
ret = decode_BasicConstraints(e->extnValue.data, e->extnValue.length,
&b, &size);
@@ -384,6 +569,30 @@ check_basicConstraints(hx509_validate_ctx ctx,
validate_print(ctx, HX509_VALIDATE_F_VERBOSE,
"\tpathLenConstraint: %d\n", *b.pathLenConstraint);
+ if (b.cA) {
+ if (*b.cA) {
+ if (!e->critical)
+ validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
+ "Is a CA and not BasicConstraints CRITICAL\n");
+ status->isca = 1;
+ }
+ else
+ validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
+ "cA is FALSE, not allowed to be\n");
+ }
+ free_BasicConstraints(&b);
+
+ return 0;
+}
+
+static int
+check_proxyCertInfo(hx509_validate_ctx ctx,
+ struct cert_status *status,
+ enum critical_flag cf,
+ const Extension *e)
+{
+ status->isproxy = 1;
+
return 0;
}
@@ -391,6 +600,7 @@ struct {
const char *name;
const heim_oid *(*oid)(void);
int (*func)(hx509_validate_ctx ctx,
+ struct cert_status *status,
enum critical_flag cf,
const Extension *);
enum critical_flag cf;
@@ -401,7 +611,7 @@ struct {
{ ext(keyUsage, Null), S_C },
{ ext(subjectAltName, subjectAltName), M_N_C },
{ ext(issuerAltName, issuerAltName), S_N_C },
- { ext(basicConstraints, basicConstraints), M_C },
+ { ext(basicConstraints, basicConstraints), D_C },
{ ext(cRLNumber, Null), M_N_C },
{ ext(cRLReason, Null), M_N_C },
{ ext(holdInstructionCode, Null), M_N_C },
@@ -410,14 +620,20 @@ struct {
{ ext(issuingDistributionPoint, Null), M_C },
{ ext(certificateIssuer, Null), M_C },
{ ext(nameConstraints, Null), M_C },
- { ext(cRLDistributionPoints, Null), S_N_C },
+ { ext(cRLDistributionPoints, CRLDistributionPoints), S_N_C },
{ ext(certificatePolicies, Null) },
{ ext(policyMappings, Null), M_N_C },
- { ext(authorityKeyIdentifier, Null), M_N_C },
+ { ext(authorityKeyIdentifier, authorityKeyIdentifier), M_N_C },
{ ext(policyConstraints, Null), D_C },
{ ext(extKeyUsage, Null), D_C },
{ ext(freshestCRL, Null), M_N_C },
{ ext(inhibitAnyPolicy, Null), M_C },
+ { "proxyCertInfo", oid_id_pe_proxyCertInfo,
+ check_proxyCertInfo, M_C },
+ { "US Fed PKI - PIV Interim", oid_id_uspkicommon_piv_interim,
+ check_Null, D_C },
+ { "Netscape cert comment", oid_id_netscape_cert_comment,
+ check_Null, D_C },
{ NULL }
};
@@ -459,31 +675,45 @@ hx509_validate_cert(hx509_context context,
{
Certificate *c = _hx509_get_cert(cert);
TBSCertificate *t = &c->tbsCertificate;
- hx509_name name;
+ hx509_name issuer, subject;
char *str;
+ struct cert_status status;
+ int ret;
+
+ memset(&status, 0, sizeof(status));
if (_hx509_cert_get_version(c) != 3)
validate_print(ctx, HX509_VALIDATE_F_VERBOSE,
"Not version 3 certificate\n");
- if (t->version && *t->version < 2 && t->extensions)
+ if ((t->version == NULL || *t->version < 2) && t->extensions)
validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
"Not version 3 certificate with extensions\n");
- _hx509_name_from_Name(&t->subject, &name);
- hx509_name_to_string(name, &str);
- hx509_name_free(&name);
+ if (_hx509_cert_get_version(c) >= 3 && t->extensions == NULL)
+ validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
+ "Version 3 certificate without extensions\n");
+
+ ret = hx509_cert_get_subject(cert, &subject);
+ if (ret) abort();
+ hx509_name_to_string(subject, &str);
validate_print(ctx, HX509_VALIDATE_F_VERBOSE,
"subject name: %s\n", str);
free(str);
- _hx509_name_from_Name(&t->issuer, &name);
- hx509_name_to_string(name, &str);
- hx509_name_free(&name);
+ ret = hx509_cert_get_issuer(cert, &issuer);
+ if (ret) abort();
+ hx509_name_to_string(issuer, &str);
validate_print(ctx, HX509_VALIDATE_F_VERBOSE,
"issuer name: %s\n", str);
free(str);
+ if (hx509_name_cmp(subject, issuer) == 0) {
+ status.selfsigned = 1;
+ validate_print(ctx, HX509_VALIDATE_F_VERBOSE,
+ "\tis a self-signed certificate\n");
+ }
+
validate_print(ctx, HX509_VALIDATE_F_VERBOSE,
"Validity:\n");
@@ -528,11 +758,68 @@ hx509_validate_cert(hx509_context context,
"checking extention: %s\n",
check_extension[j].name);
(*check_extension[j].func)(ctx,
+ &status,
check_extension[j].cf,
&t->extensions->val[i]);
}
} else
validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "no extentions\n");
+ if (status.isca) {
+ if (!status.haveSKI)
+ validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
+ "CA certificate have no SubjectKeyIdentifier\n");
+
+ } else {
+ if (!status.haveAKI)
+ validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
+ "Is not CA and doesn't have "
+ "AuthorityKeyIdentifier\n");
+ }
+
+
+ if (!status.haveSKI)
+ validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
+ "Doesn't have SubjectKeyIdentifier\n");
+
+ if (status.isproxy && status.isca)
+ validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
+ "Proxy and CA at the same time!\n");
+
+ if (status.isproxy) {
+ if (status.haveSAN)
+ validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
+ "Proxy and have SAN\n");
+ if (status.haveIAN)
+ validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
+ "Proxy and have IAN\n");
+ }
+
+ if (hx509_name_is_null_p(subject) && !status.haveSAN)
+ validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
+ "NULL subject DN and doesn't have a SAN\n");
+
+ if (!status.selfsigned && !status.haveCRLDP)
+ validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
+ "Not a CA nor PROXY and doesn't have"
+ "CRL Dist Point\n");
+
+ if (status.selfsigned) {
+ ret = _hx509_verify_signature_bitstring(context,
+ c,
+ &c->signatureAlgorithm,
+ &c->tbsCertificate._save,
+ &c->signatureValue);
+ if (ret == 0)
+ validate_print(ctx, HX509_VALIDATE_F_VERBOSE,
+ "Self-signed certificate was self-signed\n");
+ else
+ validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
+ "Self-signed certificate NOT really self-signed!\n");
+ }
+
+ hx509_name_free(&subject);
+ hx509_name_free(&issuer);
+
return 0;
}
diff --git a/source4/heimdal/lib/hx509/req.c b/source4/heimdal/lib/hx509/req.c
index ca7baa514b..34e3a4ea27 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,v 1.7 2007/01/04 20:20:11 lha Exp $");
+RCSID("$Id: req.c 20934 2007-06-06 15:30:02Z lha $");
struct hx509_request_data {
hx509_name name;
@@ -191,7 +191,7 @@ _hx509_request_to_pkcs10(hx509_context context,
ret = _hx509_create_signature(context,
signer,
- hx509_signature_rsa_with_sha1(),
+ _hx509_crypto_default_sig_alg,
&data,
&r.signatureAlgorithm,
&os);
diff --git a/source4/heimdal/lib/hx509/revoke.c b/source4/heimdal/lib/hx509/revoke.c
index 8067b29c10..0d477945c8 100644
--- a/source4/heimdal/lib/hx509/revoke.c
+++ b/source4/heimdal/lib/hx509/revoke.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 Kungliga Tekniska Högskolan
+ * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -32,7 +32,7 @@
*/
#include "hx_locl.h"
-RCSID("$Id: revoke.c,v 1.32 2006/12/30 17:09:06 lha Exp $");
+RCSID("$Id: revoke.c 20871 2007-06-03 21:22:51Z lha $");
struct revoke_crl {
char *path;
@@ -281,8 +281,11 @@ load_ocsp(hx509_context context, struct revoke_ocsp *ocsp)
ret = parse_ocsp_basic(data, length, &basic);
_hx509_unmap_file(data, length);
- if (ret)
+ if (ret) {
+ hx509_set_error_string(context, 0, ret,
+ "Failed to parse OCSP response");
return ret;
+ }
if (basic.certs) {
int i;
@@ -442,7 +445,8 @@ verify_crl(hx509_context context,
&crl->tbsCertList._save,
&crl->signatureValue);
if (ret) {
- hx509_set_error_string(context, HX509_ERROR_APPEND, ret, "CRL signature invalid");
+ hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
+ "CRL signature invalid");
goto out;
}
@@ -800,7 +804,7 @@ hx509_ocsp_request(hx509_context context,
memset(&req, 0, sizeof(req));
if (digest == NULL)
- digest = hx509_signature_sha1();
+ digest = _hx509_crypto_default_digest_alg;
ctx.req = &req.tbsRequest;
ctx.certs = pool;
@@ -922,7 +926,7 @@ hx509_revoke_ocsp_print(hx509_context context, const char *path, FILE *out)
fprintf(out, "replies: %d\n", ocsp.ocsp.tbsResponseData.responses.len);
for (i = 0; i < ocsp.ocsp.tbsResponseData.responses.len; i++) {
- char *status;
+ const char *status;
switch (ocsp.ocsp.tbsResponseData.responses.val[i].certStatus.element) {
case choice_OCSPCertStatus_good:
status = "good";
@@ -955,6 +959,12 @@ hx509_revoke_ocsp_print(hx509_context context, const char *path, FILE *out)
return ret;
}
+/*
+ * Verify that the `cert' is part of the OCSP reply and its not
+ * expired. Doesn't verify signature the OCSP reply or its done by a
+ * authorized sender, that is assumed to be already done.
+ */
+
int
hx509_ocsp_verify(hx509_context context,
time_t now,
@@ -967,12 +977,17 @@ hx509_ocsp_verify(hx509_context context,
OCSPBasicOCSPResponse basic;
int ret, i;
+ if (now == 0)
+ now = time(NULL);
+
*expiration = 0;
ret = parse_ocsp_basic(data, length, &basic);
- if (ret)
+ if (ret) {
+ hx509_set_error_string(context, 0, ret,
+ "Failed to parse OCSP response");
return ret;
-
+ }
for (i = 0; i < basic.tbsResponseData.responses.len; i++) {
@@ -1003,18 +1018,244 @@ hx509_ocsp_verify(hx509_context context,
now + context->ocsp_time_diff)
continue;
- /* don't allow the next updte to be in the past */
+ /* don't allow the next update to be in the past */
if (basic.tbsResponseData.responses.val[i].nextUpdate) {
if (*basic.tbsResponseData.responses.val[i].nextUpdate < now)
continue;
+ *expiration = *basic.tbsResponseData.responses.val[i].nextUpdate;
} else
- continue;
-
- *expiration = *basic.tbsResponseData.responses.val[i].nextUpdate;
+ *expiration = now;
+ free_OCSPBasicOCSPResponse(&basic);
return 0;
}
+
free_OCSPBasicOCSPResponse(&basic);
+ {
+ hx509_name name;
+ char *subject;
+
+ ret = hx509_cert_get_subject(cert, &name);
+ if (ret) {
+ hx509_clear_error_string(context);
+ goto out;
+ }
+ ret = hx509_name_to_string(name, &subject);
+ hx509_name_free(&name);
+ if (ret) {
+ hx509_clear_error_string(context);
+ goto out;
+ }
+ hx509_set_error_string(context, 0, HX509_CERT_NOT_IN_OCSP,
+ "Certificate %s not in OCSP response "
+ "or not good",
+ subject);
+ free(subject);
+ }
+out:
+ return HX509_CERT_NOT_IN_OCSP;
+}
+
+struct hx509_crl {
+ hx509_certs revoked;
+ time_t expire;
+};
+
+int
+hx509_crl_alloc(hx509_context context, hx509_crl *crl)
+{
+ int ret;
+
+ *crl = calloc(1, sizeof(**crl));
+ if (*crl == NULL) {
+ hx509_set_error_string(context, 0, ENOMEM, "out of memory");
+ return ENOMEM;
+ }
+
+ ret = hx509_certs_init(context, "MEMORY:crl", 0, NULL, &(*crl)->revoked);
+ if (ret) {
+ free(*crl);
+ *crl = NULL;
+ }
+ (*crl)->expire = 0;
+ return ret;
+}
+
+int
+hx509_crl_add_revoked_certs(hx509_context context,
+ hx509_crl crl,
+ hx509_certs certs)
+{
+ return hx509_certs_merge(context, crl->revoked, certs);
+}
+
+int
+hx509_crl_lifetime(hx509_context context, hx509_crl crl, int delta)
+{
+ crl->expire = time(NULL) + delta;
+ return 0;
+}
+
+
+void
+hx509_crl_free(hx509_context context, hx509_crl *crl)
+{
+ if (*crl == NULL)
+ return;
+ hx509_certs_free(&(*crl)->revoked);
+ memset(*crl, 0, sizeof(**crl));
+ free(*crl);
+ *crl = NULL;
+}
+
+static int
+add_revoked(hx509_context context, void *ctx, hx509_cert cert)
+{
+ TBSCRLCertList *c = ctx;
+ unsigned int num;
+ void *ptr;
+ int ret;
+
+ num = c->revokedCertificates->len;
+ ptr = realloc(c->revokedCertificates->val,
+ (num + 1) * sizeof(c->revokedCertificates->val[0]));
+ if (ptr == NULL) {
+ hx509_clear_error_string(context);
+ return ENOMEM;
+ }
+ c->revokedCertificates->val = ptr;
+
+ ret = hx509_cert_get_serialnumber(cert,
+ &c->revokedCertificates->val[num].userCertificate);
+ if (ret) {
+ hx509_clear_error_string(context);
+ return ret;
+ }
+ c->revokedCertificates->val[num].revocationDate.element =
+ choice_Time_generalTime;
+ c->revokedCertificates->val[num].revocationDate.u.generalTime =
+ time(NULL) - 3600 * 24;
+ c->revokedCertificates->val[num].crlEntryExtensions = NULL;
+
+ c->revokedCertificates->len++;
+
+ return 0;
+}
+
+
+int
+hx509_crl_sign(hx509_context context,
+ hx509_cert signer,
+ hx509_crl crl,
+ heim_octet_string *os)
+{
+ const AlgorithmIdentifier *sigalg = _hx509_crypto_default_sig_alg;
+ CRLCertificateList c;
+ size_t size;
+ int ret;
+ hx509_private_key signerkey;
+
+ memset(&c, 0, sizeof(c));
+
+ signerkey = _hx509_cert_private_key(signer);
+ if (signerkey == NULL) {
+ ret = HX509_PRIVATE_KEY_MISSING;
+ hx509_set_error_string(context, 0, ret,
+ "Private key missing for CRL signing");
+ return ret;
+ }
+
+ c.tbsCertList.version = malloc(sizeof(*c.tbsCertList.version));
+ if (c.tbsCertList.version == NULL) {
+ hx509_set_error_string(context, 0, ENOMEM, "out of memory");
+ return ENOMEM;
+ }
+
+ *c.tbsCertList.version = 1;
+
+ ret = copy_AlgorithmIdentifier(sigalg, &c.tbsCertList.signature);
+ if (ret) {
+ hx509_clear_error_string(context);
+ goto out;
+ }
+
+ ret = copy_Name(&_hx509_get_cert(signer)->tbsCertificate.issuer,
+ &c.tbsCertList.issuer);
+ if (ret) {
+ hx509_clear_error_string(context);
+ goto out;
+ }
+
+ c.tbsCertList.thisUpdate.element = choice_Time_generalTime;
+ c.tbsCertList.thisUpdate.u.generalTime = time(NULL) - 24 * 3600;
+
+ c.tbsCertList.nextUpdate = malloc(sizeof(*c.tbsCertList.nextUpdate));
+ if (c.tbsCertList.nextUpdate == NULL) {
+ hx509_set_error_string(context, 0, ENOMEM, "out of memory");
+ ret = ENOMEM;
+ goto out;
+ }
+
+ {
+ time_t next = crl->expire;
+ if (next == 0)
+ next = time(NULL) + 24 * 3600 * 365;
+
+ c.tbsCertList.nextUpdate->element = choice_Time_generalTime;
+ c.tbsCertList.nextUpdate->u.generalTime = next;
+ }
+
+ c.tbsCertList.revokedCertificates =
+ calloc(1, sizeof(*c.tbsCertList.revokedCertificates));
+ if (c.tbsCertList.revokedCertificates == NULL) {
+ hx509_set_error_string(context, 0, ENOMEM, "out of memory");
+ ret = ENOMEM;
+ goto out;
+ }
+ c.tbsCertList.crlExtensions = NULL;
+
+ ret = hx509_certs_iter(context, crl->revoked, add_revoked, &c.tbsCertList);
+ if (ret)
+ goto out;
+
+ /* if not revoked certs, remove OPTIONAL entry */
+ if (c.tbsCertList.revokedCertificates->len == 0) {
+ free(c.tbsCertList.revokedCertificates);
+ c.tbsCertList.revokedCertificates = NULL;
+ }
+
+ ASN1_MALLOC_ENCODE(TBSCRLCertList, os->data, os->length,
+ &c.tbsCertList, &size, ret);
+ if (ret) {
+ hx509_set_error_string(context, 0, ret, "failed to encode tbsCRL");
+ goto out;
+ }
+ if (size != os->length)
+ _hx509_abort("internal ASN.1 encoder error");
+
+
+ ret = _hx509_create_signature_bitstring(context,
+ signerkey,
+ sigalg,
+ os,
+ &c.signatureAlgorithm,
+ &c.signatureValue);
+ free(os->data);
+
+ ASN1_MALLOC_ENCODE(CRLCertificateList, os->data, os->length,
+ &c, &size, ret);
+ free_CRLCertificateList(&c);
+ if (ret) {
+ hx509_set_error_string(context, 0, ret, "failed to encode CRL");
+ goto out;
+ }
+ if (size != os->length)
+ _hx509_abort("internal ASN.1 encoder error");
+
return 0;
+
+out:
+ free_CRLCertificateList(&c);
+ return ret;
}
diff --git a/source4/heimdal/lib/hx509/test_name.c b/source4/heimdal/lib/hx509/test_name.c
index 9017e54ab1..2c6dd516cb 100644
--- a/source4/heimdal/lib/hx509/test_name.c
+++ b/source4/heimdal/lib/hx509/test_name.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 Kungliga Tekniska Högskolan
+ * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -32,7 +32,7 @@
*/
#include "hx_locl.h"
-RCSID("$Id: test_name.c,v 1.6 2006/12/30 23:04:54 lha Exp $");
+RCSID("$Id: test_name.c 19882 2007-01-13 01:02:57Z lha $");
static int
test_name(hx509_context context, const char *name)
@@ -69,6 +69,39 @@ test_name_fail(hx509_context context, const char *name)
return 1;
}
+static int
+test_expand(hx509_context context, const char *name, const char *expected)
+{
+ hx509_env env;
+ hx509_name n;
+ char *s;
+ int ret;
+
+ hx509_env_init(context, &env);
+ hx509_env_add(context, env, "uid", "lha");
+
+ ret = hx509_parse_name(context, name, &n);
+ if (ret)
+ return 1;
+
+ ret = hx509_name_expand(context, n, env);
+ hx509_env_free(&env);
+ if (ret)
+ return 1;
+
+ ret = hx509_name_to_string(n, &s);
+ hx509_name_free(&n);
+ if (ret)
+ return 1;
+
+ ret = strcmp(s, expected) != 0;
+ free(s);
+ if (ret)
+ return 1;
+
+ return 0;
+}
+
int
main(int argc, char **argv)
{
@@ -86,6 +119,13 @@ main(int argc, char **argv)
ret += test_name_fail(context, "CN=foo,=foo");
ret += test_name_fail(context, "CN=foo,really-unknown-type=foo");
+ ret += test_expand(context, "UID=${uid},C=SE", "UID=lha,C=SE");
+ ret += test_expand(context, "UID=foo${uid},C=SE", "UID=foolha,C=SE");
+ ret += test_expand(context, "UID=${uid}bar,C=SE", "UID=lhabar,C=SE");
+ ret += test_expand(context, "UID=f${uid}b,C=SE", "UID=flhab,C=SE");
+ ret += test_expand(context, "UID=${uid}${uid},C=SE", "UID=lhalha,C=SE");
+ ret += test_expand(context, "UID=${uid}{uid},C=SE", "UID=lha{uid},C=SE");
+
hx509_context_free(&context);
return ret;