Apply by doing: cd /usr/src patch -p0 < 020_isakmpd2.patch Then rebuild and install isakmpd: cd sbin/isakmpd make clean make depend make make install Index: sbin/isakmpd/doi.h =================================================================== RCS file: /cvs/src/sbin/isakmpd/doi.h,v retrieving revision 1.10 retrieving revision 1.10.4.1 diff -u -p -r1.10 -r1.10.4.1 --- sbin/isakmpd/doi.h 11 Sep 2002 09:50:43 -0000 1.10 +++ sbin/isakmpd/doi.h 17 Mar 2004 15:05:03 -0000 1.10.4.1 @@ -88,7 +88,7 @@ struct doi { int (*validate_key_information) (u_int8_t *, size_t); int (*validate_notification) (u_int16_t); int (*validate_proto) (u_int8_t); - int (*validate_situation) (u_int8_t *, size_t *); + int (*validate_situation) (u_int8_t *, size_t *, size_t); int (*validate_transform_id) (u_int8_t, u_int8_t); int (*initiator) (struct message *msg); int (*responder) (struct message *msg); Index: sbin/isakmpd/ike_quick_mode.c =================================================================== RCS file: /cvs/src/sbin/isakmpd/ike_quick_mode.c,v retrieving revision 1.67 retrieving revision 1.67.4.1 diff -u -p -r1.67 -r1.67.4.1 --- sbin/isakmpd/ike_quick_mode.c 11 Sep 2002 09:50:43 -0000 1.67 +++ sbin/isakmpd/ike_quick_mode.c 17 Mar 2004 15:05:03 -0000 1.67.4.1 @@ -1168,12 +1168,18 @@ initiator_recv_HASH_SA_NONCE (struct mes if (!ie->id_ci || !ie->id_cr) { - log_error ("initiator_recv_HASH_SA_NONCE: malloc (%lu) failed", - (unsigned long)ie->id_cr_sz); + log_error ("initiator_recv_HASH_SA_NONCE: calloc (%lu, %lu) failed", + (unsigned long)ie->id_cr_sz, (unsigned long)sizeof (char)); if (ie->id_ci) - free (ie->id_ci); + { + free (ie->id_ci); + ie->id_ci = 0; + } if (ie->id_cr) - free (ie->id_cr); + { + free (ie->id_cr); + ie->id_cr = 0; + } return -1; } @@ -1181,7 +1187,9 @@ initiator_recv_HASH_SA_NONCE (struct mes { log_error ("initiator_recv_HASH_SA_NONCE: sa_family mismatch"); free (ie->id_ci); + ie->id_ci = 0; free (ie->id_cr); + ie->id_cr = 0; return -1; } @@ -1201,7 +1209,9 @@ initiator_recv_HASH_SA_NONCE (struct mes log_error ("initiator_recv_HASH_SA_NONCE: unknown sa_family %d", src->sa_family); free (ie->id_ci); + ie->id_ci = 0; free (ie->id_cr); + ie->id_cr = 0; return -1; } memcpy (ie->id_ci + ISAKMP_ID_DATA_OFF, sockaddr_addrdata (src), @@ -1749,9 +1759,15 @@ cleanup: if (my_hash) free (my_hash); if (ie->id_ci) - free (ie->id_ci); + { + free (ie->id_ci); + ie->id_ci = 0; + } if (ie->id_cr) - free (ie->id_cr); + { + free (ie->id_cr); + ie->id_cr = 0; + } return -1; } Index: sbin/isakmpd/ipsec.c =================================================================== RCS file: /cvs/src/sbin/isakmpd/ipsec.c,v retrieving revision 1.72.2.2 retrieving revision 1.72.2.3 diff -u -p -r1.72.2.2 -r1.72.2.3 --- sbin/isakmpd/ipsec.c 16 Jan 2004 00:00:21 -0000 1.72.2.2 +++ sbin/isakmpd/ipsec.c 17 Mar 2004 15:05:03 -0000 1.72.2.3 @@ -127,7 +127,7 @@ static int ipsec_validate_id_information static int ipsec_validate_key_information (u_int8_t *, size_t); static int ipsec_validate_notification (u_int16_t); static int ipsec_validate_proto (u_int8_t); -static int ipsec_validate_situation (u_int8_t *, size_t *); +static int ipsec_validate_situation (u_int8_t *, size_t *, size_t); static int ipsec_validate_transform_id (u_int8_t, u_int8_t); static struct doi ipsec_doi = { @@ -858,35 +858,21 @@ ipsec_validate_proto (u_int8_t proto) } static int -ipsec_validate_situation (u_int8_t *buf, size_t *sz) +ipsec_validate_situation (u_int8_t *buf, size_t *sz, size_t len) { - int sit = GET_IPSEC_SIT_SIT (buf); - int off; - - if (sit & (IPSEC_SIT_SECRECY | IPSEC_SIT_INTEGRITY)) - { - /* - * XXX All the roundups below, round up to 32 bit boundaries given - * that the situation field is aligned. This is not necessarily so, - * but I interpret the drafts as this is like this they want it. - */ - off = ROUNDUP_32 (GET_IPSEC_SIT_SECRECY_LENGTH (buf)); - off += ROUNDUP_32 (GET_IPSEC_SIT_SECRECY_CAT_LENGTH (buf + off)); - off += ROUNDUP_32 (GET_IPSEC_SIT_INTEGRITY_LENGTH (buf + off)); - off += ROUNDUP_32 (GET_IPSEC_SIT_INTEGRITY_CAT_LENGTH (buf + off)); - *sz = off + IPSEC_SIT_SZ; + if (len < IPSEC_SIT_SIT_OFF + IPSEC_SIT_SIT_LEN) + { + log_print ("ipsec_validate_situation: payload too short: %u", + (unsigned int)len); + return -1; } - else - *sz = IPSEC_SIT_SIT_LEN; /* Currently only "identity only" situations are supported. */ -#ifdef notdef - return - sit & ~(IPSEC_SIT_IDENTITY_ONLY | IPSEC_SIT_SECRECY | IPSEC_SIT_INTEGRITY); -#else - return sit & ~IPSEC_SIT_IDENTITY_ONLY; -#endif + if (GET_IPSEC_SIT_SIT (buf) != IPSEC_SIT_IDENTITY_ONLY) return 1; + + *sz = IPSEC_SIT_SIT_LEN; + return 0; } Index: sbin/isakmpd/isakmp_cfg.c =================================================================== RCS file: /cvs/src/sbin/isakmpd/isakmp_cfg.c,v retrieving revision 1.23 retrieving revision 1.23.2.1 diff -u -p -r1.23 -r1.23.2.1 --- sbin/isakmpd/isakmp_cfg.c 9 Jan 2003 12:46:45 -0000 1.23 +++ sbin/isakmpd/isakmp_cfg.c 17 Mar 2004 15:05:03 -0000 1.23.2.1 @@ -360,6 +360,8 @@ cfg_initiator_send_ATTR (struct message SET_ISAKMP_ATTR_LENGTH_VALUE (attr, length); memcpy (attr + ISAKMP_ATTR_VALUE_OFF, sockaddr_addrdata (sa), length); + + free (sa); off += ISAKMP_ATTR_SZ + length; } Index: sbin/isakmpd/isakmp_doi.c =================================================================== RCS file: /cvs/src/sbin/isakmpd/isakmp_doi.c,v retrieving revision 1.14 retrieving revision 1.14.8.1 diff -u -p -r1.14 -r1.14.8.1 --- sbin/isakmpd/isakmp_doi.c 5 Jul 2001 12:36:52 -0000 1.14 +++ sbin/isakmpd/isakmp_doi.c 17 Mar 2004 15:05:03 -0000 1.14.8.1 @@ -72,7 +72,7 @@ static int isakmp_validate_id_informatio static int isakmp_validate_key_information (u_int8_t *, size_t); static int isakmp_validate_notification (u_int16_t); static int isakmp_validate_proto (u_int8_t); -static int isakmp_validate_situation (u_int8_t *, size_t *); +static int isakmp_validate_situation (u_int8_t *, size_t *, size_t); static int isakmp_validate_transform_id (u_int8_t, u_int8_t); static struct doi isakmp_doi = { @@ -202,7 +202,7 @@ isakmp_validate_proto (u_int8_t proto) } static int -isakmp_validate_situation (u_int8_t *buf, size_t *sz) +isakmp_validate_situation (u_int8_t *buf, size_t *sz, size_t len) { /* There are no situations in the ISAKMP DOI. */ *sz = 0; Index: sbin/isakmpd/message.c =================================================================== RCS file: /cvs/src/sbin/isakmpd/message.c,v retrieving revision 1.57.4.1 retrieving revision 1.57.4.2 diff -u -p -r1.57.4.1 -r1.57.4.2 --- sbin/isakmpd/message.c 16 Jan 2004 00:00:21 -0000 1.57.4.1 +++ sbin/isakmpd/message.c 17 Mar 2004 15:05:03 -0000 1.57.4.2 @@ -115,6 +115,13 @@ static struct field *fields[] = { isakmp_vendor_fld, isakmp_attribute_fld }; +static u_int16_t min_payload_lengths[] = { + 0, ISAKMP_SA_SZ, ISAKMP_PROP_SZ, ISAKMP_TRANSFORM_SZ, ISAKMP_KE_SZ, + ISAKMP_ID_SZ, ISAKMP_CERT_SZ, ISAKMP_CERTREQ_SZ, ISAKMP_HASH_SZ, + ISAKMP_SIG_SZ, ISAKMP_NONCE_SZ, ISAKMP_NOTIFY_SZ, ISAKMP_DELETE_SZ, + ISAKMP_VENDOR_SZ, ISAKMP_ATTRIBUTE_SZ +}; + /* * Fields used for checking monotonic increasing of proposal and transform * numbers. @@ -288,10 +295,25 @@ message_parse_payloads (struct message * } /* - * Decode the payload length field. + * Decode and validate the payload length field. */ len = GET_ISAKMP_GEN_LENGTH (buf); + if ((payload < ISAKMP_PAYLOAD_RESERVED_MIN) + && (len < min_payload_lengths[payload])) + { + log_print ("message_parse_payloads: payload too short: %u", len); + message_drop (msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 1); + return -1; + } + + if (buf + len > (u_int8_t *)msg->iov[0].iov_base + msg->iov[0].iov_len) + { + log_print ("message_parse_payloads: payload too long: %u", len); + message_drop (msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 1); + return -1; + } + /* Ignore private payloads. */ if (next >= ISAKMP_PAYLOAD_PRIVATE_MIN) { @@ -555,8 +577,9 @@ message_validate_hash (struct message *m if (isakmp_sa == NULL) { - log_print ("message_validate_hash: invalid hash information"); - return -1; + log_print ("message_validate_hash: invalid hash information"); + message_drop (msg, ISAKMP_NOTIFY_INVALID_HASH_INFORMATION, 0, 1, 1); + return -1; } isa = isakmp_sa->data; @@ -564,14 +587,16 @@ message_validate_hash (struct message *m if (hash == NULL) { - log_print ("message_validate_hash: invalid hash information"); - return -1; + log_print ("message_validate_hash: invalid hash information"); + message_drop (msg, ISAKMP_NOTIFY_INVALID_HASH_INFORMATION, 0, 1, 1); + return -1; } /* If no SKEYID_a, we can not do anything (should not happen). */ if (!isa->skeyid_a) { log_print ("message_validate_hash: invalid hash information"); + message_drop (msg, ISAKMP_NOTIFY_INVALID_HASH_INFORMATION, 0, 1, 1); return -1; } @@ -580,7 +605,10 @@ message_validate_hash (struct message *m isa->skeyid_len)); prf = prf_alloc (isa->prf_type, hash->type, isa->skeyid_a, isa->skeyid_len); if (!prf) - return -1; + { + message_free (msg); + return -1; + } comp_hash = (u_int8_t *)malloc (hash->hashsize); if (!comp_hash) @@ -588,6 +616,7 @@ message_validate_hash (struct message *m log_error ("message_validate_hash: malloc (%lu) failed", (unsigned long)hash->hashsize); prf_free (prf); + message_free (msg); return -1; } @@ -872,7 +901,8 @@ message_validate_sa (struct message *msg * Let the DOI validate the situation, at the same time it tells us what * the length of the situation field is. */ - if (exchange->doi->validate_situation (p->p + ISAKMP_SA_SIT_OFF, &len)) + if (exchange->doi->validate_situation (p->p + ISAKMP_SA_SIT_OFF, &len, + GET_ISAKMP_GEN_LENGTH (p->p) - ISAKMP_SA_SIT_OFF)) { log_print ("message_validate_sa: situation not supported"); message_drop (msg, ISAKMP_NOTIFY_SITUATION_NOT_SUPPORTED, 0, 1, 1); @@ -1261,6 +1291,7 @@ message_recv (struct message *msg) { LOG_DBG ((LOG_MISC, 10, "message_recv: no isakmp_sa for encrypted message")); + message_free (msg); return -1; } @@ -1715,6 +1746,9 @@ message_drop (struct message *msg, int n log_print ("dropped message from %s port %d due to notification type %s", address ? address : "", htons(port), constant_name (isakmp_notify_cst, notify)); + + if (address) + free (address); /* If specified, return a notification. */ if (notify) Index: sbin/isakmpd/util.h =================================================================== RCS file: /cvs/src/sbin/isakmpd/util.h,v retrieving revision 1.14 retrieving revision 1.14.4.1 diff -u -p -r1.14 -r1.14.4.1 --- sbin/isakmpd/util.h 28 May 2002 11:23:20 -0000 1.14 +++ sbin/isakmpd/util.h 17 Mar 2004 15:05:03 -0000 1.14.4.1 @@ -39,8 +39,6 @@ #define _UTIL_H_ #include - -#define ROUNDUP_32(x) (((x) + 3) & ~4) extern int allow_name_lookups; extern int regrand;