summaryrefslogtreecommitdiff
path: root/sbin
diff options
context:
space:
mode:
Diffstat (limited to 'sbin')
-rw-r--r--sbin/isakmpd/ike_quick_mode.c258
1 files changed, 198 insertions, 60 deletions
diff --git a/sbin/isakmpd/ike_quick_mode.c b/sbin/isakmpd/ike_quick_mode.c
index ed3d79d56f1..6ce58c86c6b 100644
--- a/sbin/isakmpd/ike_quick_mode.c
+++ b/sbin/isakmpd/ike_quick_mode.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: ike_quick_mode.c,v 1.10 1999/04/03 09:14:52 niklas Exp $ */
-/* $EOM: ike_quick_mode.c,v 1.74 1999/04/03 09:13:55 niklas Exp $ */
+/* $OpenBSD: ike_quick_mode.c,v 1.11 1999/04/05 20:58:52 niklas Exp $ */
+/* $EOM: ike_quick_mode.c,v 1.78 1999/04/05 20:18:32 niklas Exp $ */
/*
* Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved.
@@ -104,23 +104,25 @@ initiator_send_HASH_SA_NONCE (struct message *msg)
int i, suite_no, prop_no, prot_no, xf_no, value, update_nextp, protocol_num;
int prop_cnt = 0;
struct proto *proto;
- struct conf_list *suite_conf = 0, *prot_conf = 0, *xf_conf = 0, *life_conf;
+ struct conf_list *suite_conf, *prot_conf = 0, *xf_conf = 0, *life_conf;
struct conf_list_node *suite, *prot, *xf, *life;
struct constant_map *id_map;
char *protocol_id, *transform_id;
char *local_id, *remote_id;
+ int group_desc = -1, new_group_desc;
/* We want a HASH payload to start with. XXX Share with ike_main_mode.c? */
buf = malloc (ISAKMP_HASH_SZ + hashsize);
if (!buf)
{
- /* XXX Log? */
+ log_error ("initiator_send_HASH_SA_NONCE: malloc (%d) failed",
+ ISAKMP_HASH_SZ + hashsize);
return -1;
}
+
if (message_add_payload (msg, ISAKMP_PAYLOAD_HASH, buf,
ISAKMP_HASH_SZ + hashsize, 1))
{
- /* XXX Log? */
free (buf);
return -1;
}
@@ -150,31 +152,57 @@ initiator_send_HASH_SA_NONCE (struct message *msg)
prop_cnt = 2 * prop_cnt + 10;
new_proposal = realloc (proposal, prop_cnt * sizeof *proposal);
if (!new_proposal)
- goto bail_out;
+ {
+ log_error ("initiator_send_HASH_SA_NONCE: "
+ "realloc (%p, %d) failed",
+ proposal, prop_cnt * sizeof *proposal);
+ goto bail_out;
+ }
proposal = new_proposal;
new_transforms_len = realloc (transforms_len,
prop_cnt * sizeof *transforms_len);
if (!new_transforms_len)
- goto bail_out;
+ {
+ log_error ("initiator_send_HASH_SA_NONCE: "
+ "realloc (%p, %d) failed",
+ transforms_len,
+ prop_cnt * sizeof *transforms_len);
+ goto bail_out;
+ }
transforms_len = new_transforms_len;
new_transform = realloc (transform,
prop_cnt * sizeof *transform);
if (!new_transform)
- goto bail_out;
+ {
+ log_error ("initiator_send_HASH_SA_NONCE: "
+ "realloc (%p, %d) failed",
+ transform, prop_cnt * sizeof *transform);
+ goto bail_out;
+ }
transform = new_transform;
new_transform_cnt = realloc (transform_cnt,
prop_cnt * sizeof *transform_cnt);
if (!new_transform_cnt)
- goto bail_out;
+ {
+ log_error ("initiator_send_HASH_SA_NONCE: "
+ "realloc (%p, %d) failed",
+ transform_cnt, prop_cnt * sizeof *transform_cnt);
+ goto bail_out;
+ }
transform_cnt = new_transform_cnt;
new_transform_len = realloc (transform_len,
prop_cnt * sizeof *transform_len);
if (!new_transform_len)
- goto bail_out;
+ {
+ log_error ("initiator_send_HASH_SA_NONCE: "
+ "realloc (%p, %d) failed",
+ transform_len, prop_cnt * sizeof *transform_len);
+ goto bail_out;
+ }
transform_len = new_transform_len;
}
@@ -198,11 +226,22 @@ initiator_send_HASH_SA_NONCE (struct message *msg)
transform[prop_no] = calloc (transform_cnt[prop_no],
sizeof **transform);
if (!transform[prop_no])
- goto bail_out;
+ {
+ log_error ("initiator_send_HASH_SA_NONCE: "
+ "calloc (%d, %d) failed",
+ transform_cnt[prop_no], sizeof **transform);
+ goto bail_out;
+ }
+
transform_len[prop_no]
= calloc (transform_cnt[prop_no], sizeof **transform_len);
if (!transform_len[prop_no])
- goto bail_out;
+ {
+ log_error ("initiator_send_HASH_SA_NONCE: "
+ "calloc (%d, %d) failed",
+ transform_cnt[prop_no], sizeof **transform_len);
+ goto bail_out;
+ }
transforms_len[prop_no] = 0;
for (xf = TAILQ_FIRST (&xf_conf->fields), xf_no = 0;
@@ -215,7 +254,14 @@ initiator_send_HASH_SA_NONCE (struct message *msg)
+ 9 * ISAKMP_ATTR_VALUE_OFF,
1);
if (!transform[prop_no][xf_no])
- goto bail_out;
+ {
+ log_error ("initiator_send_HASH_SA_NONCE: "
+ "calloc (%d, 1) failed",
+ ISAKMP_TRANSFORM_SA_ATTRS_OFF
+ + 9 * ISAKMP_ATTR_VALUE_OFF);
+ goto bail_out;
+ }
+
SET_ISAKMP_TRANSFORM_NO (transform[prop_no][xf_no], xf_no + 1);
transform_id = conf_get_str (xf->field, "TRANSFORM_ID");
@@ -249,6 +295,7 @@ initiator_send_HASH_SA_NONCE (struct message *msg)
IPSEC_ATTR_SA_LIFE_DURATION,
value);
}
+ conf_free_list (life_conf);
}
attribute_set_constant (xf->field, "ENCAPSULATION_MODE",
@@ -264,6 +311,7 @@ initiator_send_HASH_SA_NONCE (struct message *msg)
ike_group_desc_cst,
IPSEC_ATTR_GROUP_DESCRIPTION, &attr);
+
value = conf_get_num (xf->field, "KEY_LENGTH", 0);
if (value)
attr = attribute_set_basic (attr, IPSEC_ATTR_KEY_LENGTH,
@@ -292,7 +340,25 @@ initiator_send_HASH_SA_NONCE (struct message *msg)
/* Record the real transform size. */
transforms_len[prop_no] += (transform_len[prop_no][xf_no]
= attr - transform[prop_no][xf_no]);
+
+ /*
+ * Make sure that if a group description is specified, it is
+ * specified for all transforms equally.
+ */
+ attr = conf_get_str (xf->field, "GROUP_DESCRIPTION");
+ new_group_desc
+ = attr ? constant_value (ike_group_desc_cst, attr) : 0;
+ if (group_desc == -1)
+ group_desc = new_group_desc;
+ else if (group_desc != new_group_desc)
+ {
+ log_print ("inititor_send_HASH_SA_NONCE: "
+ "differing group descriptions in a proposal");
+ goto bail_out;
+ }
}
+ conf_free_list (xf_conf);
+ xf_conf = 0;
/*
* Get SPI from application.
@@ -307,20 +373,35 @@ initiator_send_HASH_SA_NONCE (struct message *msg)
proposals_len += proposal_len + transforms_len[prop_no];
proposal[prop_no] = malloc (proposal_len);
if (!proposal[prop_no])
- goto bail_out;
+ {
+ log_error ("initiator_send_HASH_SA_NONCE: malloc (%d) failed",
+ proposal_len);
+ goto bail_out;
+ }
+
SET_ISAKMP_PROP_NO (proposal[prop_no], suite_no + 1);
SET_ISAKMP_PROP_PROTO (proposal[prop_no], protocol_num);
/* XXX I would like to see this factored out. */
proto = calloc (1, sizeof *proto);
if (!proto)
- goto bail_out;
+ {
+ log_error ("initiator_send_HASH_SA_NONCE: calloc (1, %d) failed",
+ sizeof *proto);
+ goto bail_out;
+ }
+
if (doi->proto_size)
{
proto->data = calloc (1, doi->proto_size);
if (!proto->data)
- goto bail_out;
+ {
+ log_error ("initiator_send_HASH_SA_NONCE: "
+ "calloc (1, %d) failed", doi->proto_size);
+ goto bail_out;
+ }
}
+
proto->no = suite_no + 1;
proto->proto = protocol_num;
proto->sa = TAILQ_FIRST (&exchange->sa_list);
@@ -341,12 +422,17 @@ initiator_send_HASH_SA_NONCE (struct message *msg)
transform_cnt[prop_no]);
prop_no++;
}
+ conf_free_list (prot_conf);
+ prot_conf = 0;
}
sa_len = ISAKMP_SA_SIT_OFF + IPSEC_SIT_SIT_LEN;
sa_buf = malloc (sa_len);
if (!sa_buf)
- goto bail_out;
+ {
+ log_error ("initiator_send_HASH_SA_NONCE: malloc (%d) failed", sa_len);
+ goto bail_out;
+ }
SET_ISAKMP_SA_DOI (sa_buf, IPSEC_DOI_IPSEC);
SET_IPSEC_SIT_SIT (sa_buf + ISAKMP_SA_SIT_OFF, IPSEC_SIT_IDENTITY_ONLY);
@@ -404,15 +490,20 @@ initiator_send_HASH_SA_NONCE (struct message *msg)
}
/* Generate optional KEY_EXCH payload. */
- if (ie->group)
+ if (group_desc)
{
+ ie->group = group_get (group_desc);
ie->g_x_len = dh_getlen (ie->group);
if (ipsec_gen_g_x (msg))
{
/* XXX Log? */
+ group_free (ie->group);
+ ie->group = 0;
return -1;
}
+ group_free (ie->group);
+ ie->group = 0;
}
/* Generate optional client ID payloads. XXX Share with responder. */
@@ -427,7 +518,7 @@ initiator_send_HASH_SA_NONCE (struct message *msg)
sz);
if (message_add_payload (msg, ISAKMP_PAYLOAD_ID, id, sz, 1))
{
- /* XXX Log? */
+ free (id);
return -1;
}
@@ -438,7 +529,7 @@ initiator_send_HASH_SA_NONCE (struct message *msg)
sz);
if (message_add_payload (msg, ISAKMP_PAYLOAD_ID, id, sz, 1))
{
- /* XXX Log? */
+ free (id);
return -1;
}
}
@@ -482,6 +573,17 @@ initiator_send_HASH_SA_NONCE (struct message *msg)
log_debug_buf (LOG_MISC, 80, "initiator_send_HASH_SA_NONCE: HASH(1)",
buf + ISAKMP_HASH_DATA_OFF, hashsize);
+ conf_free_list (suite_conf);
+ for (i = 0; i < prop_no; i++)
+ {
+ free (transform[i]);
+ free (transform_len[i]);
+ }
+ free (proposal);
+ free (transform);
+ free (transforms_len);
+ free (transform_len);
+ free (transform_cnt);
return 0;
bail_out:
@@ -495,7 +597,7 @@ initiator_send_HASH_SA_NONCE (struct message *msg)
free (proposal[i]);
if (transform[i])
{
- for (xf_no = 0; xf_no < xf_conf->cnt; xf_no++)
+ for (xf_no = 0; xf_no < transform_cnt[i]; xf_no++)
if (transform[i][xf_no])
free (transform[i][xf_no]);
free (transform[i]);
@@ -513,8 +615,7 @@ initiator_send_HASH_SA_NONCE (struct message *msg)
conf_free_list (xf_conf);
if (prot_conf)
conf_free_list (prot_conf);
- if (suite_conf)
- conf_free_list (suite_conf);
+ conf_free_list (suite_conf);
return -1;
}
@@ -553,7 +654,7 @@ initiator_recv_HASH_SA_NONCE (struct message *msg)
return -1;
}
- sa = TAILQ_FIRST (&msg->exchange->sa_list);
+ sa = TAILQ_FIRST (&exchange->sa_list);
/* Build the protection suite in our SA. */
for (xf = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_TRANSFORM]); xf;
@@ -616,26 +717,32 @@ initiator_recv_HASH_SA_NONCE (struct message *msg)
hash->digest, hashsize);
if (memcmp (hashp->p + ISAKMP_HASH_DATA_OFF, hash->digest, hashsize) != 0)
{
- /* XXX Log & notify? */
+ log_print ("initiator_recv_HASH_SA_NONCE: bad hash");
+ /* XXX Notify? */
return -1;
}
/* Mark the HASH as handled. */
hashp->flags |= PL_MARK;
- /* XXX Errors possible? */
+ isa = sa->data;
ie->group = group_get (isa->group_desc);
+ if (!ie->group)
+ {
+ /* XXX Notify peer? */
+ return -1;
+ }
/* Copy out the initiator's nonce. */
if (exchange_save_nonce (msg))
{
- /* XXX How to log and notify peer? */
+ /* XXX Notify peer? */
return -1;
}
/* Handle the optional KEY_EXCH payload. */
if (kep && ipsec_save_g_x (msg))
{
- /* XXX How to log and notify peer? */
+ /* XXX Notify peer? */
return -1;
}
@@ -690,13 +797,13 @@ initiator_send_HASH (struct message *msg)
buf = malloc (ISAKMP_HASH_SZ + hashsize);
if (!buf)
{
- /* XXX Log? */
+ log_error ("initiator_send_HASH: malloc (%d) failed",
+ ISAKMP_HASH_SZ + hashsize);
return -1;
}
if (message_add_payload (msg, ISAKMP_PAYLOAD_HASH, buf,
ISAKMP_HASH_SZ + hashsize, 1))
{
- /* XXX Log? */
free (buf);
return -1;
}
@@ -855,7 +962,7 @@ responder_recv_HASH_SA_NONCE (struct message *msg)
struct exchange *exchange = msg->exchange;
struct ipsec_exch *ie = exchange->data;
struct prf *prf;
- u_int8_t *hash, *my_hash;
+ u_int8_t *hash, *my_hash = 0;
size_t hash_len;
u_int8_t *pkt = msg->iov[0].iov_base;
u_int8_t group_desc = 0;
@@ -871,14 +978,15 @@ responder_recv_HASH_SA_NONCE (struct message *msg)
{
/* XXX Is there a better notification type? */
message_drop (msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 0, 0);
- return -1;
+ goto cleanup;
}
hash_len = GET_ISAKMP_GEN_LENGTH (hash);
my_hash = malloc (hash_len - ISAKMP_GEN_SZ);
if (!my_hash)
{
- /* XXX Log? */
- return -1;
+ log_error ("responder_recv_HASH_SA_NONCE: malloc (%d) failed",
+ hash_len - ISAKMP_GEN_SZ);
+ goto cleanup;
}
/* Check the payload's integrity. */
@@ -888,7 +996,7 @@ responder_recv_HASH_SA_NONCE (struct message *msg)
if (!prf)
{
/* XXX Log? */
- return -1;
+ goto cleanup;
}
prf->Init (prf->prfctx);
log_debug_buf (LOG_MISC, 90, "responder_recv_HASH_SA_NONCE: message_id",
@@ -909,23 +1017,23 @@ responder_recv_HASH_SA_NONCE (struct message *msg)
{
/* XXX Is there a better notification type? */
message_drop (msg, ISAKMP_NOTIFY_INVALID_HASH_INFORMATION, 0, 0, 0);
- return -1;
+ goto cleanup;
}
+ free (my_hash);
+ my_hash = 0;
if (message_negotiate_sa (msg, 0))
- return -1;
+ goto cleanup;
kep = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_KEY_EXCH]);
- for (sa = TAILQ_FIRST (&exchange->sa_list); sa;
- sa = TAILQ_NEXT (sa, next))
+ for (sa = TAILQ_FIRST (&exchange->sa_list); sa; sa = TAILQ_NEXT (sa, next))
{
for (proto = TAILQ_FIRST (&sa->protos); proto;
proto = TAILQ_NEXT (proto, link))
/* XXX we need to have some attributes per proto, not all per SA. */
ipsec_decode_transform (msg, sa, proto, proto->chosen->p);
-
isa = sa->data;
/* Check the SA for reasonableness. */
@@ -953,21 +1061,28 @@ responder_recv_HASH_SA_NONCE (struct message *msg)
retval = 0;
}
- /* XXX Errors possible? */
- ie->group = group_get (group_desc);
+ if (kep)
+ {
+ ie->group = group_get (group_desc);
+ if (!ie->group)
+ {
+ /* XXX Notify peer? */
+ goto cleanup;
+ }
+ }
/* Copy out the initiator's nonce. */
if (exchange_save_nonce (msg))
{
- /* XXX How to log and notify peer? */
- return -1;
+ /* XXX Notify peer? */
+ goto cleanup;
}
/* Handle the optional KEY_EXCH payload. */
if (kep && ipsec_save_g_x (msg))
{
- /* XXX How to log and notify peer? */
- return -1;
+ /* XXX Notify peer? */
+ goto cleanup;
}
/* Handle optional client ID payloads. */
@@ -977,7 +1092,11 @@ responder_recv_HASH_SA_NONCE (struct message *msg)
ie->id_ci_sz = GET_ISAKMP_GEN_LENGTH (idp->p);
ie->id_ci = malloc (ie->id_ci_sz);
if (!ie->id_ci)
- retval = 1;
+ {
+ log_error ("responder_recv_HASH_SA_NONCE: malloc (%d) failed",
+ ie->id_ci_sz);
+ goto cleanup;
+ }
memcpy (ie->id_ci, idp->p, ie->id_ci_sz);
idp->flags |= PL_MARK;
log_debug_buf (LOG_MISC, 90,
@@ -991,7 +1110,11 @@ responder_recv_HASH_SA_NONCE (struct message *msg)
ie->id_cr_sz = GET_ISAKMP_GEN_LENGTH (idp->p);
ie->id_cr = malloc (ie->id_cr_sz);
if (!ie->id_cr)
- retval = 1;
+ {
+ log_error ("responder_recv_HASH_SA_NONCE: malloc (%d) failed",
+ ie->id_cr_sz);
+ goto cleanup;
+ }
memcpy (ie->id_cr, idp->p, ie->id_cr_sz);
idp->flags |= PL_MARK;
log_debug_buf (LOG_MISC, 90,
@@ -1002,6 +1125,15 @@ responder_recv_HASH_SA_NONCE (struct message *msg)
}
return retval;
+
+cleanup:
+ /* Remove all potential protocols that have been added to the SAs. */
+ for (sa = TAILQ_FIRST (&exchange->sa_list); sa; sa = TAILQ_NEXT (sa, next))
+ while ((proto = TAILQ_FIRST (&sa->protos)) != 0)
+ proto_free (proto);
+ if (my_hash)
+ free (my_hash);
+ return -1;
}
/* Reply with the transform we chose. */
@@ -1027,13 +1159,13 @@ responder_send_HASH_SA_NONCE (struct message *msg)
buf = malloc (ISAKMP_HASH_SZ + hashsize);
if (!buf)
{
- /* XXX Log? */
+ log_error ("responder_send_HASH_SA_NONCE: malloc (%d) failed",
+ ISAKMP_HASH_SZ + hashsize);
return -1;
}
if (message_add_payload (msg, ISAKMP_PAYLOAD_HASH, buf,
ISAKMP_HASH_SZ + hashsize, 1))
{
- /* XXX Log? */
free (buf);
return -1;
}
@@ -1066,7 +1198,7 @@ responder_send_HASH_SA_NONCE (struct message *msg)
id = malloc (sz);
if (!id)
{
- /* XXX Log? */
+ log_error ("responder_send_HASH_SA_NONCE: malloc (%d) failed", sz);
return -1;
}
memcpy (id, ie->id_ci, sz);
@@ -1074,7 +1206,7 @@ responder_send_HASH_SA_NONCE (struct message *msg)
sz);
if (message_add_payload (msg, ISAKMP_PAYLOAD_ID, id, sz, 1))
{
- /* XXX Log? */
+ free (id);
return -1;
}
@@ -1082,7 +1214,7 @@ responder_send_HASH_SA_NONCE (struct message *msg)
id = malloc (sz);
if (!id)
{
- /* XXX Log? */
+ log_error ("responder_send_HASH_SA_NONCE: malloc (%d) failed", sz);
return -1;
}
memcpy (id, ie->id_cr, sz);
@@ -1090,7 +1222,7 @@ responder_send_HASH_SA_NONCE (struct message *msg)
sz);
if (message_add_payload (msg, ISAKMP_PAYLOAD_ID, id, sz, 1))
{
- /* XXX Log? */
+ free (id);
return -1;
}
}
@@ -1162,7 +1294,7 @@ responder_recv_HASH (struct message *msg)
struct sa *isakmp_sa = msg->isakmp_sa;
struct ipsec_sa *isa = isakmp_sa->data;
struct prf *prf;
- u_int8_t *hash, *my_hash;
+ u_int8_t *hash, *my_hash = 0;
size_t hash_len;
struct payload *hashp;
@@ -1174,8 +1306,9 @@ responder_recv_HASH (struct message *msg)
my_hash = malloc (hash_len - ISAKMP_GEN_SZ);
if (!my_hash)
{
- /* XXX Log? */
- return -1;
+ log_error ("responder_recv_HASH: malloc (%d) failed",
+ hash_len - ISAKMP_GEN_SZ);
+ goto cleanup;
}
/* Allocate the prf and start calculating our HASH(3). XXX Share? */
@@ -1187,8 +1320,7 @@ responder_recv_HASH (struct message *msg)
if (!prf)
{
/* XXX Log? */
- free (my_hash);
- return -1;
+ goto cleanup;
}
prf->Init (prf->prfctx);
prf->Update (prf->prfctx, "\0", 1);
@@ -1210,12 +1342,18 @@ responder_recv_HASH (struct message *msg)
{
/* XXX Is there a better notification type? */
message_drop (msg, ISAKMP_NOTIFY_INVALID_HASH_INFORMATION, 0, 0, 0);
- return -1;
+ goto cleanup;
}
+ free (my_hash);
sa_reference (msg->isakmp_sa);
exchange_reference (exchange);
post_quick_mode (msg);
return 0;
+
+ cleanup:
+ if (my_hash)
+ free (my_hash);
+ return -1;
}