summaryrefslogtreecommitdiff
path: root/sbin
diff options
context:
space:
mode:
authorReyk Floeter <reyk@cvs.openbsd.org>2010-06-14 23:14:10 +0000
committerReyk Floeter <reyk@cvs.openbsd.org>2010-06-14 23:14:10 +0000
commit4352486464fdc177d68bb32455b40349f6e081e7 (patch)
tree3ee5dc23be40d9547778967d57df2f2e3d635560 /sbin
parentec8268c259a5afa181428b71aa9f1588cdb63186 (diff)
Initiator mode with certificates; needs more work but works.
Diffstat (limited to 'sbin')
-rw-r--r--sbin/iked/iked.h5
-rw-r--r--sbin/iked/ikev2.c108
-rw-r--r--sbin/iked/ikev2_pld.c15
-rw-r--r--sbin/iked/policy.c56
4 files changed, 123 insertions, 61 deletions
diff --git a/sbin/iked/iked.h b/sbin/iked/iked.h
index d6e39200e77..3b9cf2c85f0 100644
--- a/sbin/iked/iked.h
+++ b/sbin/iked/iked.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: iked.h,v 1.10 2010/06/14 21:12:56 reyk Exp $ */
+/* $OpenBSD: iked.h,v 1.11 2010/06/14 23:14:09 reyk Exp $ */
/* $vantronix: iked.h,v 1.61 2010/06/03 07:57:33 reyk Exp $ */
/*
@@ -306,7 +306,8 @@ struct iked_sa {
int sa_state;
u_int sa_stateflags;
- u_int sa_staterequire;
+ u_int sa_stateinit; /* SA_INIT */
+ u_int sa_statevalid; /* IKE_AUTH */
int sa_cp; /* XXX */
diff --git a/sbin/iked/ikev2.c b/sbin/iked/ikev2.c
index 2db3bd36d2f..c0e4a8e9af7 100644
--- a/sbin/iked/ikev2.c
+++ b/sbin/iked/ikev2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ikev2.c,v 1.13 2010/06/14 21:12:56 reyk Exp $ */
+/* $OpenBSD: ikev2.c,v 1.14 2010/06/14 23:14:09 reyk Exp $ */
/* $vantronix: ikev2.c,v 1.101 2010/06/03 07:57:33 reyk Exp $ */
/*
@@ -56,12 +56,15 @@ struct iked_sa *
u_int8_t *, u_int8_t **, size_t *);
void ikev2_recv(struct iked *, struct iked_message *);
+int ikev2_ike_auth(struct iked *, struct iked_sa *);
void ikev2_init_recv(struct iked *, struct iked_message *,
struct ike_header *);
int ikev2_init_ike_sa(struct iked *, struct iked_policy *);
-int ikev2_init_ike_auth(struct iked *, struct iked_message *);
-int ikev2_init_done(struct iked *, struct iked_message *);
+int ikev2_init_ike_auth(struct iked *, struct iked_sa *);
+int ikev2_init_auth(struct iked *, struct iked_message *);
+int ikev2_init_done(struct iked *, struct iked_sa *,
+ struct iked_message *);
void ikev2_resp_recv(struct iked *, struct iked_message *,
struct ike_header *);
@@ -213,14 +216,14 @@ ikev2_dispatch_cert(int fd, struct iked_proc *p, struct imsg *imsg)
if (imsg->hdr.type == IMSG_CERTVALID) {
log_debug("%s: peer certificate is valid", __func__);
+ sa_stateflags(sa, IKED_REQ_VALID);
sa_state(env, sa, IKEV2_STATE_VALID);
- } else
+ } else {
log_debug("%s: peer certificate is invalid", __func__);
+ }
- sa_stateflags(sa, IKED_REQ_VALID);
-
- if (ikev2_resp_ike_auth(env, sa) != 0)
- log_debug("%s: failed to send auth response", __func__);
+ if (ikev2_ike_auth(env, sa) != 0)
+ log_debug("%s: failed to send ike auth", __func__);
break;
case IMSG_CERT:
if ((sa = ikev2_getimsgdata(env, imsg,
@@ -252,8 +255,8 @@ ikev2_dispatch_cert(int fd, struct iked_proc *p, struct imsg *imsg)
sa_stateflags(sa, IKED_REQ_CERT);
- if (ikev2_resp_ike_auth(env, sa) != 0)
- log_debug("%s: failed to send auth response", __func__);
+ if (ikev2_ike_auth(env, sa) != 0)
+ log_debug("%s: failed to send ike auth", __func__);
break;
case IMSG_AUTH:
if ((sa = ikev2_getimsgdata(env, imsg,
@@ -279,8 +282,8 @@ ikev2_dispatch_cert(int fd, struct iked_proc *p, struct imsg *imsg)
sa_stateflags(sa, IKED_REQ_AUTH);
- if (ikev2_resp_ike_auth(env, sa) != 0)
- log_debug("%s: failed to send auth response", __func__);
+ if (ikev2_ike_auth(env, sa) != 0)
+ log_debug("%s: failed to send ike auth", __func__);
break;
default:
return (-1);
@@ -383,6 +386,18 @@ ikev2_recv(struct iked *env, struct iked_message *msg)
sa_free(env, sa);
}
+int
+ikev2_ike_auth(struct iked *env, struct iked_sa *sa)
+{
+ if (sa->sa_hdr.sh_initiator) {
+ if (sa_stateok(sa, IKEV2_STATE_AUTH_SUCCESS))
+ return (ikev2_init_done(env, sa, NULL));
+ else
+ return (ikev2_init_ike_auth(env, sa));
+ }
+ return (ikev2_resp_ike_auth(env, sa));
+}
+
void
ikev2_init_recv(struct iked *env, struct iked_message *msg,
struct ike_header *hdr)
@@ -425,10 +440,10 @@ ikev2_init_recv(struct iked *env, struct iked_message *msg,
switch (hdr->ike_exchange) {
case IKEV2_EXCHANGE_IKE_SA_INIT:
- (void)ikev2_init_ike_auth(env, msg);
+ (void)ikev2_init_auth(env, msg);
break;
case IKEV2_EXCHANGE_IKE_AUTH:
- (void)ikev2_init_done(env, msg);
+ (void)ikev2_init_done(env, sa, msg);
break;
case IKEV2_EXCHANGE_CREATE_CHILD_SA:
default:
@@ -580,18 +595,9 @@ ikev2_init_ike_sa(struct iked *env, struct iked_policy *pol)
}
int
-ikev2_init_ike_auth(struct iked *env, struct iked_message *msg)
+ikev2_init_auth(struct iked *env, struct iked_message *msg)
{
struct iked_sa *sa = msg->msg_sa;
- struct iked_policy *pol = sa->sa_policy;
- struct ikev2_payload *pld;
- struct ikev2_cert *cert;
- struct ikev2_auth *auth;
- struct iked_id *id, *certid;
- struct ibuf *e = NULL;
- u_int8_t firstpayload;
- int ret = -1;
- ssize_t len;
struct ibuf *authmsg;
if (sa == NULL)
@@ -608,11 +614,29 @@ ikev2_init_ike_auth(struct iked *env, struct iked_message *msg)
return (-1);
}
- /* XXX this doesn't work with certificates */
- ca_setauth(env, sa, authmsg, PROC_CERT);
+ if (ca_setauth(env, sa, authmsg, PROC_CERT) == -1) {
+ log_debug("%s: failed to get cert", __func__);
+ return (-1);
+ }
+
+ return (ikev2_init_ike_auth(env, sa));
+}
+
+int
+ikev2_init_ike_auth(struct iked *env, struct iked_sa *sa)
+{
+ struct iked_policy *pol = sa->sa_policy;
+ struct ikev2_payload *pld;
+ struct ikev2_cert *cert;
+ struct ikev2_auth *auth;
+ struct iked_id *id, *certid;
+ struct ibuf *e = NULL;
+ u_int8_t firstpayload;
+ int ret = -1;
+ ssize_t len;
if (!sa_stateok(sa, IKEV2_STATE_SA_INIT))
- return (0); /* ignore */
+ return (0);
if (!sa->sa_localauth.id_type) {
log_debug("%s: no local auth", __func__);
@@ -635,7 +659,7 @@ ikev2_init_ike_auth(struct iked *env, struct iked_message *msg)
len = ibuf_size(id->id_buf);
/* CERT payload */
- if ((sa->sa_staterequire & IKED_REQ_CERT) &&
+ if ((sa->sa_stateinit & IKED_REQ_CERT) &&
(certid->id_type != IKEV2_CERT_NONE)) {
if (ikev2_next_payload(pld, len,
IKEV2_PAYLOAD_CERT) == -1)
@@ -648,6 +672,22 @@ ikev2_init_ike_auth(struct iked *env, struct iked_message *msg)
if (ibuf_cat(e, certid->id_buf) != 0)
goto done;
len = ibuf_size(certid->id_buf) + sizeof(*cert);
+
+ if (env->sc_certreqtype) {
+ if (ikev2_next_payload(pld, len,
+ IKEV2_PAYLOAD_CERTREQ) == -1)
+ goto done;
+
+ /* CERTREQ payload */
+ if ((pld = ikev2_add_payload(e)) == NULL)
+ goto done;
+ if ((cert = ibuf_advance(e, sizeof(*cert))) == NULL)
+ goto done;
+ cert->cert_type = env->sc_certreqtype;
+ if (ikev2_add_buf(e, env->sc_certreq) == -1)
+ goto done;
+ len = ibuf_size(env->sc_certreq) + sizeof(*cert);
+ }
}
if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_AUTH) == -1)
@@ -715,12 +755,12 @@ ikev2_init_ike_auth(struct iked *env, struct iked_message *msg)
}
int
-ikev2_init_done(struct iked *env, struct iked_message *msg)
+ikev2_init_done(struct iked *env, struct iked_sa *sa,
+ struct iked_message *msg)
{
- struct iked_sa *sa = msg->msg_sa;
int ret;
- if (!TAILQ_EMPTY(&msg->msg_proposals)) {
+ if (msg != NULL && !TAILQ_EMPTY(&msg->msg_proposals)) {
if (ikev2_sa_negotiate(sa,
&sa->sa_policy->pol_proposals,
&msg->msg_proposals, IKEV2_SAPROTO_ESP) != 0) {
@@ -1518,7 +1558,7 @@ ikev2_resp_ike_sa_init(struct iked *env, struct iked_message *msg)
len += sizeof(*n);
}
- if (env->sc_certreqtype && (sa->sa_staterequire & IKED_REQ_CERT)) {
+ if (env->sc_certreqtype && (sa->sa_statevalid & IKED_REQ_CERT)) {
if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_CERTREQ) == -1)
goto done;
@@ -1622,7 +1662,7 @@ ikev2_resp_ike_auth(struct iked *env, struct iked_sa *sa)
len = ibuf_size(id->id_buf);
/* CERT payload */
- if ((sa->sa_staterequire & IKED_REQ_CERT) &&
+ if ((sa->sa_statevalid & IKED_REQ_CERT) &&
(certid->id_type != IKEV2_CERT_NONE)) {
if (ikev2_next_payload(pld, len,
IKEV2_PAYLOAD_CERT) == -1)
@@ -1743,7 +1783,7 @@ ikev2_resp_ike_eap(struct iked *env, struct iked_sa *sa, struct ibuf *eapmsg)
goto done;
len = ibuf_size(id->id_buf);
- if ((sa->sa_staterequire & IKED_REQ_CERT) &&
+ if ((sa->sa_statevalid & IKED_REQ_CERT) &&
(certid->id_type != IKEV2_CERT_NONE)) {
if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_CERT) == -1)
goto done;
diff --git a/sbin/iked/ikev2_pld.c b/sbin/iked/ikev2_pld.c
index e40597be833..f1bc7c32d48 100644
--- a/sbin/iked/ikev2_pld.c
+++ b/sbin/iked/ikev2_pld.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ikev2_pld.c,v 1.6 2010/06/14 21:12:56 reyk Exp $ */
+/* $OpenBSD: ikev2_pld.c,v 1.7 2010/06/14 23:14:09 reyk Exp $ */
/* $vantronix: ikev2.c,v 1.101 2010/06/03 07:57:33 reyk Exp $ */
/*
@@ -510,10 +510,10 @@ ikev2_pld_cert(struct iked *env, struct ikev2_payload *pld,
if (!ikev2_msg_frompeer(msg))
return (0);
- if (!sa->sa_hdr.sh_initiator && !msg->msg_response) {
+ if (!sa->sa_hdr.sh_initiator) {
certid = &sa->sa_icert;
id = &sa->sa_iid;
- } else if (sa->sa_hdr.sh_initiator && msg->msg_response) {
+ } else if (sa->sa_hdr.sh_initiator) {
certid = &sa->sa_rcert;
id = &sa->sa_rid;
} else
@@ -535,6 +535,7 @@ int
ikev2_pld_certreq(struct iked *env, struct ikev2_payload *pld,
struct iked_message *msg, off_t offset)
{
+ struct iked_sa *sa = msg->msg_sa;
struct ikev2_cert cert;
u_int8_t *buf;
size_t len;
@@ -562,10 +563,12 @@ ikev2_pld_certreq(struct iked *env, struct ikev2_payload *pld,
return (-1);
/* Optional certreq for PSK */
- msg->msg_sa->sa_staterequire |= IKED_REQ_CERT;
+ if (sa->sa_hdr.sh_initiator)
+ sa->sa_stateinit |= IKED_REQ_CERT;
+ else
+ sa->sa_statevalid |= IKED_REQ_CERT;
- ca_setreq(env, &msg->msg_sa->sa_hdr, cert.cert_type,
- buf, len, PROC_CERT);
+ ca_setreq(env, &sa->sa_hdr, cert.cert_type, buf, len, PROC_CERT);
return (0);
}
diff --git a/sbin/iked/policy.c b/sbin/iked/policy.c
index 2833a8616cd..90d09856b91 100644
--- a/sbin/iked/policy.c
+++ b/sbin/iked/policy.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: policy.c,v 1.7 2010/06/14 21:12:56 reyk Exp $ */
+/* $OpenBSD: policy.c,v 1.8 2010/06/14 23:14:09 reyk Exp $ */
/* $vantronix: policy.c,v 1.29 2010/05/28 15:34:35 reyk Exp $ */
/*
@@ -139,10 +139,17 @@ sa_state(struct iked *env, struct iked_sa *sa, int state)
void
sa_stateflags(struct iked_sa *sa, u_int flags)
{
+ u_int require;
+
+ if (sa->sa_state > IKEV2_STATE_SA_INIT)
+ require = sa->sa_statevalid;
+ else
+ require = sa->sa_stateinit;
+
log_debug("%s: 0x%02x -> 0x%02x %s (required 0x%02x)", __func__,
sa->sa_stateflags, sa->sa_stateflags | flags,
print_bits(sa->sa_stateflags | flags,
- IKED_REQ_BITS), sa->sa_staterequire);
+ IKED_REQ_BITS), require);
sa->sa_stateflags |= flags;
}
@@ -150,18 +157,25 @@ sa_stateflags(struct iked_sa *sa, u_int flags)
int
sa_stateok(struct iked_sa *sa, int state)
{
+ u_int require;
+
if (sa->sa_state < state)
return (0);
- if (state == IKEV2_STATE_VALID ||
+
+ if (state == IKEV2_STATE_SA_INIT)
+ require = sa->sa_stateinit;
+ else
+ require = sa->sa_statevalid;
+
+ if (state == IKEV2_STATE_SA_INIT ||
+ state == IKEV2_STATE_VALID ||
state == IKEV2_STATE_EAP) {
- log_debug("%s: flags 0x%02x require 0x%02x %s", __func__,
- (sa->sa_stateflags & sa->sa_staterequire),
- sa->sa_staterequire,
- print_bits(sa->sa_staterequire,
- IKED_REQ_BITS));
-
- if ((sa->sa_stateflags & sa->sa_staterequire) !=
- sa->sa_staterequire)
+ log_debug("%s: %s flags 0x%02x, require 0x%02x %s", __func__,
+ print_map(state, ikev2_state_map),
+ (sa->sa_stateflags & require), require,
+ print_bits(require, IKED_REQ_BITS));
+
+ if ((sa->sa_stateflags & require) != require)
return (0); /* not ready, ignore */
}
return (1);
@@ -173,6 +187,7 @@ sa_new(struct iked *env, u_int64_t ispi, u_int64_t rspi,
{
struct iked_sa *sa;
struct iked_id *localid;
+ u_int diff;
if ((ispi == 0 && rspi == 0) ||
(sa = sa_lookup(env, ispi, rspi, initiator)) == NULL) {
@@ -188,24 +203,27 @@ sa_new(struct iked *env, u_int64_t ispi, u_int64_t rspi,
else
pol = sa->sa_policy;
- sa->sa_staterequire = IKED_REQ_AUTH|IKED_REQ_SA;
+ sa->sa_statevalid = IKED_REQ_AUTH|IKED_REQ_SA;
if (pol != NULL && pol->pol_auth.auth_eap) {
- sa->sa_staterequire |= IKED_REQ_CERT;
+ sa->sa_statevalid |= IKED_REQ_CERT;
} else if (pol != NULL && pol->pol_auth.auth_method !=
IKEV2_AUTH_SHARED_KEY_MIC) {
- sa->sa_staterequire |= IKED_REQ_VALID|IKED_REQ_CERT;
+ sa->sa_statevalid |= IKED_REQ_VALID|IKED_REQ_CERT;
}
+ if (initiator) {
+ localid = &sa->sa_iid;
+ diff = IKED_REQ_VALID|IKED_REQ_SA;
+ sa->sa_stateinit = sa->sa_statevalid & ~diff;
+ sa->sa_statevalid = sa->sa_statevalid & diff;
+ } else
+ localid = &sa->sa_rid;
+
if (sa->sa_hdr.sh_ispi == 0)
sa->sa_hdr.sh_ispi = ispi;
if (sa->sa_hdr.sh_rspi == 0)
sa->sa_hdr.sh_rspi = rspi;
- if (initiator)
- localid = &sa->sa_iid;
- else
- localid = &sa->sa_rid;
-
if (!ibuf_length(localid->id_buf) &&
ikev2_policy2id(&pol->pol_localid, localid, 1) != 0) {
log_debug("%s: failed to get local id", __func__);