summaryrefslogtreecommitdiff
path: root/sbin
diff options
context:
space:
mode:
authorReyk Floeter <reyk@cvs.openbsd.org>2010-06-27 05:49:06 +0000
committerReyk Floeter <reyk@cvs.openbsd.org>2010-06-27 05:49:06 +0000
commitc0728d07cb9f081d4ebd094f5475f3542a8db633 (patch)
tree13f1fdc2452565ee64dda4df363326d9f620aa32 /sbin
parent8eb100c81f1d8479b193b2a578ca0088b69b3ea0 (diff)
When a peer requests a certificate from the local gateway, we first
lookup a cert from /etc/iked/certs/ that is signed by a requested CA. As a second step we also compare the subjectAltName of any found certificate now to match the local srcid; this allows to have multiple certs for the same CA but different srcids in the certs/ directory but enforces that the subjectAltName has to be set correctly. requested by jsg@
Diffstat (limited to 'sbin')
-rw-r--r--sbin/iked/ca.c135
-rw-r--r--sbin/iked/iked.h6
-rw-r--r--sbin/iked/ikev2_pld.c5
3 files changed, 95 insertions, 51 deletions
diff --git a/sbin/iked/ca.c b/sbin/iked/ca.c
index 3428bcf6f0c..197e0ad3dc4 100644
--- a/sbin/iked/ca.c
+++ b/sbin/iked/ca.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ca.c,v 1.8 2010/06/27 01:37:56 reyk Exp $ */
+/* $OpenBSD: ca.c,v 1.9 2010/06/27 05:49:05 reyk Exp $ */
/* $vantronix: ca.c,v 1.29 2010/06/02 12:22:58 reyk Exp $ */
/*
@@ -56,12 +56,13 @@ int ca_getreq(struct iked *, struct imsg *);
int ca_getcert(struct iked *, struct imsg *);
int ca_getauth(struct iked *, struct imsg *);
X509 *ca_by_subjectpubkey(X509_STORE *, u_int8_t *, size_t);
-X509 *ca_by_issuer(X509_STORE *, X509_NAME *);
+X509 *ca_by_issuer(X509_STORE *, X509_NAME *, struct iked_static_id *);
int ca_subjectpubkey_digest(X509 *, u_int8_t *, u_int *);
int ca_validate_cert(struct iked *, struct iked_static_id *,
void *, size_t);
struct ibuf *
ca_x509_serialize(X509 *);
+int ca_x509_subjectaltname_cmp(X509 *, struct iked_static_id *);
int ca_x509_subjectaltname(X509 *cert, struct iked_id *);
int ca_key_serialize(EVP_PKEY *, struct iked_id *);
int ca_dispatch_parent(int, struct iked_proc *, struct imsg *);
@@ -232,22 +233,49 @@ ca_setcert(struct iked *env, struct iked_sahdr *sh, struct iked_id *id,
}
int
-ca_setreq(struct iked *env, struct iked_sahdr *sh, u_int8_t type,
- u_int8_t *data, size_t len, enum iked_procid id)
+ca_setreq(struct iked *env, struct iked_sahdr *sh,
+ struct iked_static_id *localid, u_int8_t type, u_int8_t *data,
+ size_t len, enum iked_procid procid)
{
- struct iovec iov[3];
- int iovcnt = 3;
-
- iov[0].iov_base = sh;
- iov[0].iov_len = sizeof(*sh);
- iov[1].iov_base = &type;
- iov[1].iov_len = sizeof(type);
- iov[2].iov_base = data;
- iov[2].iov_len = len;
+ struct iovec iov[4];
+ int iovcnt = 0;
+ struct iked_static_id idb;
+ struct iked_id id;
+ int ret = -1;
- if (imsg_composev_proc(env, id, IMSG_CERTREQ, -1, iov, iovcnt) == -1)
+ /* Convert to a static Id */
+ bzero(&id, sizeof(id));
+ if (ikev2_policy2id(localid, &id, 0) != 0)
return (-1);
- return (0);
+
+ bzero(&idb, sizeof(idb));
+ idb.id_type = id.id_type;
+ idb.id_offset = id.id_offset;
+ idb.id_length = ibuf_length(id.id_buf);
+ memcpy(&idb.id_data, ibuf_data(id.id_buf),
+ ibuf_length(id.id_buf));
+ iov[iovcnt].iov_base = &idb;
+ iov[iovcnt].iov_len = sizeof(idb);
+ iovcnt++;
+
+ iov[iovcnt].iov_base = sh;
+ iov[iovcnt].iov_len = sizeof(*sh);
+ iovcnt++;
+ iov[iovcnt].iov_base = &type;
+ iov[iovcnt].iov_len = sizeof(type);
+ iovcnt++;
+ iov[iovcnt].iov_base = data;
+ iov[iovcnt].iov_len = len;
+ iovcnt++;
+
+ if (imsg_composev_proc(env, procid,
+ IMSG_CERTREQ, -1, iov, iovcnt) == -1)
+ goto done;
+
+ ret = 0;
+ done:
+ ibuf_release(id.id_buf);
+ return (ret);
}
int
@@ -337,15 +365,19 @@ ca_getreq(struct iked *env, struct imsg *imsg)
u_int i, n;
X509 *ca = NULL, *cert = NULL;
struct ibuf *buf;
+ struct iked_static_id id;
ptr = (u_int8_t *)imsg->data;
len = IMSG_DATA_SIZE(imsg);
- i = sizeof(u_int8_t) + sizeof(sh);
+ i = sizeof(id) + sizeof(u_int8_t) + sizeof(sh);
if (len < i || ((len - i) % SHA_DIGEST_LENGTH) != 0)
return (-1);
- memcpy(&sh, ptr, sizeof(sh));
- memcpy(&type, ptr + sizeof(sh), sizeof(u_int8_t));
+ memcpy(&id, ptr, sizeof(id));
+ if (id.id_type == IKEV2_ID_NONE)
+ return (-1);
+ memcpy(&sh, ptr + sizeof(id), sizeof(sh));
+ memcpy(&type, ptr + sizeof(id) + sizeof(sh), sizeof(u_int8_t));
if (type != IKEV2_CERT_X509_CERT)
return (-1);
@@ -360,7 +392,7 @@ ca_getreq(struct iked *env, struct imsg *imsg)
log_debug("%s: found CA %s", __func__, ca->name);
if ((cert = ca_by_issuer(store->ca_certs,
- X509_get_subject_name(ca))) != NULL) {
+ X509_get_subject_name(ca), &id)) != NULL) {
/* XXX should we re-validate our own cert here? */
break;
}
@@ -625,7 +657,7 @@ ca_by_subjectpubkey(X509_STORE *ctx, u_int8_t *sig, size_t siglen)
}
X509 *
-ca_by_issuer(X509_STORE *ctx, X509_NAME *subject)
+ca_by_issuer(X509_STORE *ctx, X509_NAME *subject, struct iked_static_id *id)
{
STACK_OF(X509_OBJECT) *h;
X509_OBJECT *xo;
@@ -645,8 +677,11 @@ ca_by_issuer(X509_STORE *ctx, X509_NAME *subject)
cert = xo->data.x509;
if ((issuer = X509_get_issuer_name(cert)) == NULL)
continue;
- else if (X509_NAME_cmp(subject, issuer) == 0)
+ else if (X509_NAME_cmp(subject, issuer) == 0) {
+ if (ca_x509_subjectaltname_cmp(cert, id) != 0)
+ continue;
return (cert);
+ }
}
return (NULL);
@@ -777,11 +812,7 @@ ca_validate_cert(struct iked *env, struct iked_static_id *id,
size_t idlen, idoff;
const u_int8_t *idptr;
X509_NAME *idname = NULL, *subject;
- struct iked_id sanid;
const char *errstr = "failed";
- char idstr[IKED_ID_SIZE];
-
- bzero(&sanid, sizeof(sanid));
if (len == 0) {
/* Data is already an X509 certificate */
@@ -819,26 +850,8 @@ ca_validate_cert(struct iked *env, struct iked_static_id *id,
}
break;
default:
- if (ca_x509_subjectaltname(cert, &sanid) != 0) {
- errstr = "missing subjectAltName extension";
- goto done;
- }
-
- print_id(&sanid, idstr, sizeof(idstr));
-
- /* Compare id types, length and data */
- if ((id->id_type != sanid.id_type) ||
- ((ssize_t)ibuf_size(sanid.id_buf) !=
- (id->id_length - id->id_offset)) ||
- (memcmp(id->id_data + id->id_offset,
- ibuf_data(sanid.id_buf),
- ibuf_size(sanid.id_buf)) != 0)) {
- log_debug("%s: subjectAltName %s is not %s/%s",
- __func__, idstr,
- print_map(id->id_type, ikev2_id_map),
- id->id_data + id->id_offset);
-
- errstr = "subjectAltName mismatch";
+ if (ca_x509_subjectaltname_cmp(cert, id) != 0) {
+ errstr = "invalid subjectAltName extension";
goto done;
}
break;
@@ -874,7 +887,6 @@ ca_validate_cert(struct iked *env, struct iked_static_id *id,
log_debug("%s: %s %.100s", __func__, cert->name,
ret == 0 ? "ok" : errstr);
- ibuf_release(sanid.id_buf);
if (idname != NULL)
X509_NAME_free(idname);
if (rawcert != NULL) {
@@ -887,6 +899,37 @@ ca_validate_cert(struct iked *env, struct iked_static_id *id,
}
int
+ca_x509_subjectaltname_cmp(X509 *cert, struct iked_static_id *id)
+{
+ struct iked_id sanid;
+ char idstr[IKED_ID_SIZE];
+ int ret = -1;
+
+ bzero(&sanid, sizeof(sanid));
+
+ if (ca_x509_subjectaltname(cert, &sanid) != 0)
+ return (-1);
+
+ print_id(&sanid, idstr, sizeof(idstr));
+
+ /* Compare id types, length and data */
+ if ((id->id_type != sanid.id_type) ||
+ ((ssize_t)ibuf_size(sanid.id_buf) !=
+ (id->id_length - id->id_offset)) ||
+ (memcmp(id->id_data + id->id_offset,
+ ibuf_data(sanid.id_buf),
+ ibuf_size(sanid.id_buf)) != 0)) {
+ log_debug("%s: %s mismatched", __func__, idstr);
+ goto done;
+ }
+
+ ret = 0;
+ done:
+ ibuf_release(sanid.id_buf);
+ return (ret);
+}
+
+int
ca_x509_subjectaltname(X509 *cert, struct iked_id *id)
{
X509_EXTENSION *san;
diff --git a/sbin/iked/iked.h b/sbin/iked/iked.h
index 4ad1a26ab76..15281d0ce92 100644
--- a/sbin/iked/iked.h
+++ b/sbin/iked/iked.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: iked.h,v 1.15 2010/06/27 01:03:22 reyk Exp $ */
+/* $OpenBSD: iked.h,v 1.16 2010/06/27 05:49:05 reyk Exp $ */
/* $vantronix: iked.h,v 1.61 2010/06/03 07:57:33 reyk Exp $ */
/*
@@ -662,8 +662,8 @@ int pfkey_init(void);
/* ca.c */
pid_t caproc(struct iked *, struct iked_proc *);
-int ca_setreq(struct iked *, struct iked_sahdr *, u_int8_t,
- u_int8_t *, size_t, enum iked_procid);
+int ca_setreq(struct iked *, struct iked_sahdr *, struct iked_static_id *,
+ u_int8_t, u_int8_t *, size_t, enum iked_procid);
int ca_setcert(struct iked *, struct iked_sahdr *, struct iked_id *,
u_int8_t, u_int8_t *, size_t, enum iked_procid);
int ca_setauth(struct iked *, struct iked_sa *,
diff --git a/sbin/iked/ikev2_pld.c b/sbin/iked/ikev2_pld.c
index 3895e12f7c1..fd43e34fbef 100644
--- a/sbin/iked/ikev2_pld.c
+++ b/sbin/iked/ikev2_pld.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ikev2_pld.c,v 1.11 2010/06/27 01:03:22 reyk Exp $ */
+/* $OpenBSD: ikev2_pld.c,v 1.12 2010/06/27 05:49:05 reyk Exp $ */
/* $vantronix: ikev2.c,v 1.101 2010/06/03 07:57:33 reyk Exp $ */
/*
@@ -553,7 +553,8 @@ ikev2_pld_certreq(struct iked *env, struct ikev2_payload *pld,
else
sa->sa_statevalid |= IKED_REQ_CERT;
- ca_setreq(env, &sa->sa_hdr, cert.cert_type, buf, len, PROC_CERT);
+ ca_setreq(env, &sa->sa_hdr, &sa->sa_policy->pol_localid,
+ cert.cert_type, buf, len, PROC_CERT);
return (0);
}