diff options
author | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1998-11-20 07:34:46 +0000 |
---|---|---|
committer | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1998-11-20 07:34:46 +0000 |
commit | 10b8b8980a6c231f53b9d42290438a2abb0e7627 (patch) | |
tree | 2cb8d8868db6a64a13eb802934c437ee4403cd90 | |
parent | eb4416d4df1aa88945ba6589b2ff66981feef9b3 (diff) |
Validate acceptable main mode transforms
-rw-r--r-- | sbin/isakmpd/ike_main_mode.c | 216 |
1 files changed, 212 insertions, 4 deletions
diff --git a/sbin/isakmpd/ike_main_mode.c b/sbin/isakmpd/ike_main_mode.c index 8f2101b4705..b7356eef46d 100644 --- a/sbin/isakmpd/ike_main_mode.c +++ b/sbin/isakmpd/ike_main_mode.c @@ -1,5 +1,5 @@ -/* $OpenBSD: ike_main_mode.c,v 1.3 1998/11/17 11:10:12 niklas Exp $ */ -/* $EOM: ike_main_mode.c,v 1.62 1998/11/12 12:55:08 niklas Exp $ */ +/* $OpenBSD: ike_main_mode.c,v 1.4 1998/11/20 07:34:45 niklas Exp $ */ +/* $EOM: ike_main_mode.c,v 1.63 1998/11/20 07:17:43 niklas Exp $ */ /* * Copyright (c) 1998 Niklas Hallqvist. All rights reserved. @@ -60,6 +60,8 @@ #include "transport.h" #include "util.h" +static int attribute_unacceptable (u_int16_t, u_int8_t *, u_int16_t, void *); +static int ike_main_mode_validate_prop (struct sa *); static int initiator_send_SA (struct message *); static int initiator_recv_SA (struct message *); static int initiator_send_KE_NONCE (struct message *); @@ -112,7 +114,7 @@ initiator_send_SA (struct message *msg) struct proto *proto; /* Get the list of transforms. */ - conf = conf_get_list ("Main mode initiator", "Offered-transforms"); + conf = conf_get_list ("Main mode", "Offered-transforms"); if (!conf) return -1; @@ -424,7 +426,8 @@ responder_recv_SA (struct message *msg) } /* Chose a transform from the SA. */ - if (message_negotiate_sa (msg) || !TAILQ_FIRST (&sa->protos)) + if (message_negotiate_sa (msg, ike_main_mode_validate_prop) + || !TAILQ_FIRST (&sa->protos)) return -1; /* XXX Move into message_negotiate_sa? */ @@ -882,3 +885,208 @@ recv_ID_AUTH (struct message *msg) return 0; } + +struct attr_node { + LIST_ENTRY (attr_node) link; + u_int16_t type; +}; + +struct validation_state { + struct conf_list_node *xf; + LIST_HEAD (attr_head, attr_node) attrs; + char *life; +}; + +static int +ike_main_mode_validate_prop (struct sa *sa) +{ + struct conf_list *conf, *tags; + struct conf_list_node *xf, *tag; + struct proto *proto; + struct validation_state vs; + struct attr_node *node; + + /* Get the list of transforms. */ + conf = conf_get_list ("Main mode", "Accepted-transforms"); + if (!conf) + return 0; + + for (xf = TAILQ_FIRST (&conf->fields); xf; xf = TAILQ_NEXT (xf, link)) + { + for (proto = TAILQ_FIRST (&sa->protos); proto; + proto = TAILQ_NEXT (proto, link)) + { + /* Mark all attributes in our policy as unseen. */ + LIST_INIT (&vs.attrs); + vs.xf = xf; + vs.life = 0; + if (attribute_map (proto->chosen->p + ISAKMP_TRANSFORM_SA_ATTRS_OFF, + GET_ISAKMP_GEN_LENGTH (proto->chosen->p) + - ISAKMP_TRANSFORM_SA_ATTRS_OFF, + attribute_unacceptable, &vs) == -1) + goto try_next; + + /* Sweep over unseen tags in this section. */ + tags = conf_get_tag_list (xf->field); + for (tag = TAILQ_FIRST (&tags->fields); tag; + tag = TAILQ_NEXT (tag, link)) + for (node = LIST_FIRST (&vs.attrs); node; + node = LIST_NEXT (node, link)) + LIST_REMOVE (node, link); + + /* Are there leftover tags in this section? */ + node = LIST_FIRST (&vs.attrs); + if (node) + { + /* We have attributes in our policy we have not seen. */ + while (node) + { + LIST_REMOVE (node, link); + node = LIST_FIRST (&vs.attrs); + } + goto try_next; + } + } + + /* All protocols were OK, we succeeded. */ + log_debug (LOG_MISC, 20, "ike_main_mode_validate_prop: success"); + conf_free_list (conf); + return 1; + + try_next: + } + + log_debug (LOG_MISC, 20, "ike_main_mode_validate_prop: failure"); + conf_free_list (conf); + return 0; +} + +static int +attribute_unacceptable (u_int16_t type, u_int8_t *value, u_int16_t len, + void *vvs) +{ + struct validation_state *vs = vvs; + struct conf_list_node *xf = vs->xf; + struct conf_list *life_conf; + struct conf_list_node *life; + char *tag = constant_lookup (ike_attr_cst, type); + char *str; + struct constant_map *map; + struct attr_node *node; + int rv; + + if (!tag) + { + log_print ("attribute_unacceptable: attribute type %d not known", type); + return 1; + } + + switch (type) + { + case IKE_ATTR_ENCRYPTION_ALGORITHM: + case IKE_ATTR_HASH_ALGORITHM: + case IKE_ATTR_AUTHENTICATION_METHOD: + case IKE_ATTR_GROUP_DESCRIPTION: + case IKE_ATTR_GROUP_TYPE: + case IKE_ATTR_PRF: + str = conf_get_str (xf->field, tag); + if (!str) + /* This attribute does not exist in this policy. */ + return 1; + + map = constant_link_lookup (ike_attr_cst, type); + if (!map) + return 1; + + if (constant_value (map, str) == decode_16 (value)) + { + /* Mark this attribute as seen. */ + node = malloc (sizeof *node); + if (!node) + { + log_print ("attribute_unacceptable: malloc failed"); + return 1; + } + node->type = type; + LIST_INSERT_HEAD (&vs->attrs, node, link); + return 0; + } + return 1; + + case IKE_ATTR_GROUP_PRIME: + case IKE_ATTR_GROUP_GENERATOR_1: + case IKE_ATTR_GROUP_GENERATOR_2: + case IKE_ATTR_GROUP_CURVE_A: + case IKE_ATTR_GROUP_CURVE_B: + /* XXX Bignums not handled yet. */ + return 1; + + case IKE_ATTR_LIFE_TYPE: + case IKE_ATTR_LIFE_DURATION: + rv = 1; + life_conf = conf_get_list (xf->field, "Life"); + if (!life_conf) + /* Life attributes given, but not in our policy. */ + goto bail_out; + + /* + * Each lifetime type must match, otherwise we turn the proposal down. + * In order to do this we need to find the specific section of our + * policy's "Life" list and match its duration + */ + vs->life = 0; + switch (type) + { + case IKE_ATTR_LIFE_TYPE: + for (life = TAILQ_FIRST (&life_conf->fields); life; + life = TAILQ_NEXT (life, link)) + { + str = conf_get_str (life->field, "SA_LIFE_TYPE"); + if (!str) + /* XXX Log this? */ + continue; + + /* + * If this is the type we are looking at, save a pointer + * to this section in vs->life. + */ + if (constant_value (ike_duration_cst, str) == decode_16 (value)) + { + vs->life = life->field; + rv = 0; + goto bail_out; + } + } + /* XXX Log? */ + break; + + case IKE_ATTR_LIFE_DURATION: + rv + = conf_match_num (vs->life, "SA_LIFE_DURATION", decode_16 (value)); + break; + } + + bail_out: + conf_free_list (life_conf); + return rv; + + case IKE_ATTR_KEY_LENGTH: + case IKE_ATTR_FIELD_SIZE: + case IKE_ATTR_GROUP_ORDER: + if (conf_match_num (xf->field, tag, decode_16 (value))) + { + /* Mark this attribute as seen. */ + node = malloc (sizeof *node); + if (!node) + { + log_print ("attribute_unacceptable: malloc failed"); + return 1; + } + node->type = type; + LIST_INSERT_HEAD (&vs->attrs, node, link); + return 0; + } + return 1; + } + return 1; +} |