summaryrefslogtreecommitdiff
path: root/sbin
diff options
context:
space:
mode:
authorNiklas Hallqvist <niklas@cvs.openbsd.org>1999-04-05 20:58:53 +0000
committerNiklas Hallqvist <niklas@cvs.openbsd.org>1999-04-05 20:58:53 +0000
commit85b173b4da77445e16f8f4d6f885797cac8ed10f (patch)
tree3f57b1e7a21ec867a1a227e04ba32263f883a934 /sbin
parent0fff68e2b753923bdbc01fe82e4815e4d96da2e1 (diff)
Merge with EOM 1.78
clear pointer when what is pointed to is freed Fix PFS in initator mode. Improve commentary. Some more error reporting. GC proto structures if we bail out on a message. Never free twice. Error handling of group allocation. Memory alloc. error reporting. Mem leak plugging.
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;
}