diff options
author | Niklas Hallqvist <niklas@cvs.openbsd.org> | 2000-08-03 07:24:59 +0000 |
---|---|---|
committer | Niklas Hallqvist <niklas@cvs.openbsd.org> | 2000-08-03 07:24:59 +0000 |
commit | e7e610998fa96633d6f7f5026ef127333ef65fe6 (patch) | |
tree | e372091fe888c723dd5123627675c8c81f8884f4 /sbin | |
parent | 57d0d4299c0d563df35a7fb14abdd017c5891807 (diff) |
Merge with EOM 1.126
author: angelos
Be more careful.
author: angelos
Oops, typo.
author: angelos
Avoid endless loop in INITIAL-CONTACT handling.
author: angelos
Don't delete the ISAKMP SA over which we received an INITIAL-CONTACT
payload.
author: provos
make a DOI specific decode_ids, but have isakmp doi decode point to
ipsec.
author: provos
indent
author: provos
introduce ipsec_decode_ids, also decodes FQDN and USER_FQDN now.
new ipsec_clone_id to copy IDs to phase 2 SAs for better status
reports. okay angelos@
Diffstat (limited to 'sbin')
-rw-r--r-- | sbin/isakmpd/ipsec.c | 140 |
1 files changed, 137 insertions, 3 deletions
diff --git a/sbin/isakmpd/ipsec.c b/sbin/isakmpd/ipsec.c index 0ee08e910eb..7903e6cc919 100644 --- a/sbin/isakmpd/ipsec.c +++ b/sbin/isakmpd/ipsec.c @@ -1,5 +1,5 @@ -/* $OpenBSD: ipsec.c,v 1.26 2000/06/08 20:50:41 niklas Exp $ */ -/* $EOM: ipsec.c,v 1.119 2000/05/04 21:44:30 provos Exp $ */ +/* $OpenBSD: ipsec.c,v 1.27 2000/08/03 07:24:58 niklas Exp $ */ +/* $EOM: ipsec.c,v 1.126 2000/07/13 20:05:07 angelos Exp $ */ /* * Copyright (c) 1998, 1999, 2000 Niklas Hallqvist. All rights reserved. @@ -36,6 +36,7 @@ #include <sys/types.h> #include <sys/socket.h> +#include <netdb.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdlib.h> @@ -150,7 +151,8 @@ static struct doi ipsec_doi = { ipsec_validate_situation, ipsec_validate_transform_id, ipsec_initiator, - ipsec_responder + ipsec_responder, + ipsec_decode_ids }; int16_t script_quick_mode[] = { @@ -1254,6 +1256,7 @@ ipsec_handle_leftover_payload (struct message *msg, u_int8_t type, struct sockaddr *dst; socklen_t dstlen; struct sa *sa; + int flag = 0; /* So far, the only thing we handle is an INITIAL-CONTACT NOTIFY. */ switch (type) @@ -1270,6 +1273,19 @@ ipsec_handle_leftover_payload (struct message *msg, u_int8_t type, msg->transport->vtbl->get_dst (msg->transport, &dst, &dstlen); while ((sa = sa_lookup_by_peer (dst, dstlen)) != 0) { + /* + * Don't delete the current SA -- we received the notification + * over it, so it's obviously still active. We temporarily need + * to remove the SA from the list to avoid an endless loop. + */ + + if (sa == msg->isakmp_sa) + { + LIST_REMOVE (sa, link); + flag = 1; + continue; + } + LOG_DBG ((LOG_SA, 30, "ipsec_handle_leftover_payload: " "INITIAL-CONTACT made us delete SA %p", @@ -1277,6 +1293,8 @@ ipsec_handle_leftover_payload (struct message *msg, u_int8_t type, sa_delete (sa, 0); } + if (flag) + sa_enter (msg->isakmp_sa); payload->flags |= PL_MARK; return 0; break; @@ -1467,6 +1485,92 @@ ipsec_get_id (char *section, int *id, struct in_addr *addr, return 0; } +#ifdef USE_DEBUG +static void +ipsec_ipv4toa (char *buf, size_t size, u_int8_t *addr) +{ + struct sockaddr_storage from; + struct sockaddr_in *sfrom = (struct sockaddr_in *)&from; + socklen_t fromlen = sizeof(from); + + memset (&from, 0, fromlen); + sfrom->sin_len = sizeof (struct sockaddr_in); + sfrom->sin_family = AF_INET; + memcpy (&sfrom->sin_addr.s_addr, addr, 4); + + if (getnameinfo ((struct sockaddr *)sfrom, sfrom->sin_len, + buf, size, NULL, 0, NI_NUMERICHOST) != 0) + { + log_error("ipsec_ipv4toa: getnameinfo() failed"); + strcpy(buf, "<error>"); + } +} + +static void +ipsec_decode_id (u_int8_t *buf, int size, u_int8_t *id, size_t id_len, + int isakmpform) +{ + int id_type; + char ntop[NI_MAXHOST], ntop2[NI_MAXHOST]; + + if (id) + { + if (!isakmpform) + { + /* exchanges and SA's dont carry the IDs in ISAKMP form */ + id -= ISAKMP_ID_TYPE_OFF; + id_len += ISAKMP_ID_TYPE_OFF; + } + + id_type = GET_ISAKMP_ID_TYPE (id); + switch (id_type) + { + case IPSEC_ID_IPV4_ADDR: + ipsec_ipv4toa (ntop, sizeof(ntop), id + ISAKMP_ID_DATA_OFF); + snprintf (buf, size, "%08x: %s", + decode_32 (id + ISAKMP_ID_DATA_OFF), ntop); + break; + case IPSEC_ID_IPV4_ADDR_SUBNET: + ipsec_ipv4toa (ntop, sizeof(ntop), id + ISAKMP_ID_DATA_OFF); + ipsec_ipv4toa (ntop2, sizeof(ntop2), id + ISAKMP_ID_DATA_OFF + 4); + snprintf (buf, size, "%08x/%08x: %s/%s", + decode_32 (id + ISAKMP_ID_DATA_OFF), + decode_32 (id + ISAKMP_ID_DATA_OFF + 4), + ntop, ntop2); + break; + case IPSEC_ID_FQDN: + case IPSEC_ID_USER_FQDN: + /* String is not NUL terminated, be careful */ + id_len -= ISAKMP_ID_DATA_OFF; + id_len = MIN(id_len, size - 1); + memcpy (buf, id + ISAKMP_ID_DATA_OFF, id_len); + buf[id_len] = '\0'; + break; + /* XXX - IPV6 et al */ + default: + snprintf (buf, size, "<type unknown: %x>", id_type); + break; + } + } + else + strlcpy(buf, "<noid>", size); +} + +char * +ipsec_decode_ids (char *fmt, u_int8_t *id1, size_t id1_len, + u_int8_t *id2, size_t id2_len, int isakmpform) +{ + static char result[1024]; + char s_id1[256], s_id2[256]; + + ipsec_decode_id(s_id1, sizeof(s_id1), id1, id1_len, isakmpform); + ipsec_decode_id(s_id2, sizeof(s_id2), id2, id2_len, isakmpform); + + snprintf (result, sizeof(result), fmt, s_id1, s_id2); + return result; +} +#endif /* USE_DEBUG */ + /* * Out of a named section SECTION in the configuration file build an * ISAKMP ID payload. Ths payload size should be stashed in SZ. @@ -1518,6 +1622,36 @@ ipsec_build_id (char *section, size_t *sz) } /* + * copy an ISAKMPD id + */ + +int +ipsec_clone_id (u_int8_t **did, size_t *did_len, u_int8_t *id, size_t id_len) +{ + if (*did) + free (*did); + + if (!id_len || id == NULL) + { + *did = NULL; + *did_len = 0; + return 0; + } + + *did = malloc (id_len); + if (*did == NULL) + { + log_error ("ipsec_clone_id: malloc(%d) failed", id_len); + return -1; + } + + *did_len = id_len; + memcpy (*did, id, id_len); + + return 0; +} + +/* * IPSec-specific PROTO initializations. SECTION is only set if we are the * initiator thus only usable there. * XXX I want to fix this later. |