From 47960c3941786f6816b1c55c663e130b7824c602 Mon Sep 17 00:00:00 2001 From: Hakan Olsson Date: Fri, 29 Jun 2001 04:12:02 +0000 Subject: Initial IPv6 support. (niklas@ ok) --- sbin/isakmpd/ike_auth.c | 36 ++-- sbin/isakmpd/ike_phase_1.c | 38 +++- sbin/isakmpd/ipsec.c | 326 ++++++++++++++++++----------- sbin/isakmpd/ipsec.h | 17 +- sbin/isakmpd/pf_encap.c | 52 ++++- sbin/isakmpd/pf_key_v2.c | 498 ++++++++++++++++++++++++++++++++------------- sbin/isakmpd/policy.c | 123 +++++++---- sbin/isakmpd/util.c | 124 ++++++++++- sbin/isakmpd/util.h | 6 +- 9 files changed, 856 insertions(+), 364 deletions(-) (limited to 'sbin/isakmpd') diff --git a/sbin/isakmpd/ike_auth.c b/sbin/isakmpd/ike_auth.c index 6e95d4b6e22..91e19ac1475 100644 --- a/sbin/isakmpd/ike_auth.c +++ b/sbin/isakmpd/ike_auth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ike_auth.c,v 1.49 2001/06/28 21:41:58 angelos Exp $ */ +/* $OpenBSD: ike_auth.c,v 1.50 2001/06/29 04:11:59 ho Exp $ */ /* $EOM: ike_auth.c,v 1.59 2000/11/21 00:21:31 angelos Exp $ */ /* @@ -336,7 +336,6 @@ pre_shared_gen_skeyid (struct exchange *exchange, size_t *sz) u_int8_t *key; u_int8_t *buf = 0; size_t keylen; - in_addr_t addr; /* * If we're the responder and have the initiator's ID (which is the @@ -349,16 +348,16 @@ pre_shared_gen_skeyid (struct exchange *exchange, size_t *sz) switch (exchange->id_i[0]) { case IPSEC_ID_IPV4_ADDR: - buf = malloc (16); + util_ntoa ((char **)&buf, AF_INET, exchange->id_i + + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ); if (!buf) - { - log_error ("pre_shared_gen_skeyid: malloc (16) failed"); - return 0; - } - addr = htonl (decode_32 (exchange->id_i + ISAKMP_ID_DATA_OFF - - ISAKMP_GEN_SZ)); - inet_ntop (AF_INET, &addr, buf, 16); + return 0; break; + case IPSEC_ID_IPV6_ADDR: + util_ntoa ((char **)&buf, AF_INET6, exchange->id_i + + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ); + if (!buf) + return 0; case IPSEC_ID_FQDN: case IPSEC_ID_USER_FQDN: @@ -901,7 +900,6 @@ rsa_sig_encode_hash (struct message *msg) u_int8_t *id; size_t id_len; int idtype; - in_addr_t addr; id = initiator ? exchange->id_i : exchange->id_r; id_len = initiator ? exchange->id_i_len : exchange->id_r_len; @@ -1013,14 +1011,16 @@ rsa_sig_encode_hash (struct message *msg) switch (id[ISAKMP_ID_TYPE_OFF - ISAKMP_GEN_SZ]) { case IPSEC_ID_IPV4_ADDR: - buf2 = malloc (16); + util_ntoa ((char **)&buf2, AF_INET, id + ISAKMP_ID_DATA_OFF - + ISAKMP_GEN_SZ); if (!buf2) - { - log_error ("rsa_sig_encode_hash: malloc (16) failed"); - return 0; - } - addr = htonl (decode_32 (id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ)); - inet_ntop (AF_INET, &addr, buf2, 16); + return 0; + break; + case IPSEC_ID_IPV6_ADDR: + util_ntoa ((char **)&buf2, AF_INET6, id + ISAKMP_ID_DATA_OFF - + ISAKMP_GEN_SZ); + if (!buf2) + return 0; break; case IPSEC_ID_FQDN: diff --git a/sbin/isakmpd/ike_phase_1.c b/sbin/isakmpd/ike_phase_1.c index 5b6958b4436..d3a32c1923e 100644 --- a/sbin/isakmpd/ike_phase_1.c +++ b/sbin/isakmpd/ike_phase_1.c @@ -1,9 +1,10 @@ -/* $OpenBSD: ike_phase_1.c,v 1.26 2001/06/05 10:50:55 angelos Exp $ */ +/* $OpenBSD: ike_phase_1.c,v 1.27 2001/06/29 04:12:00 ho Exp $ */ /* $EOM: ike_phase_1.c,v 1.31 2000/12/11 23:47:56 niklas Exp $ */ /* * Copyright (c) 1999, 2000 Niklas Hallqvist. All rights reserved. * Copyright (c) 1999, 2000 Angelos D. Keromytis. All rights reserved. + * Copyright (c) 2001 Håkan Olsson. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -821,12 +822,12 @@ ike_phase_1_send_ID (struct message *msg) switch (id_type) { case IPSEC_ID_IPV4_ADDR: + case IPSEC_ID_IPV6_ADDR: msg->transport->vtbl->get_src (msg->transport, &src, &src_len); /* Already in network byteorder. */ - memcpy (buf + ISAKMP_ID_DATA_OFF, - &((struct sockaddr_in *)src)->sin_addr.s_addr, - sizeof (in_addr_t)); + memcpy (buf + ISAKMP_ID_DATA_OFF, sockaddr_data (src), + sockaddr_len (src)); break; case IPSEC_ID_FQDN: case IPSEC_ID_USER_FQDN: @@ -843,12 +844,18 @@ ike_phase_1_send_ID (struct message *msg) else { msg->transport->vtbl->get_src (msg->transport, &src, &src_len); - /* XXX Assumes IPv4. */ - SET_ISAKMP_ID_TYPE (buf, IPSEC_ID_IPV4_ADDR); + switch (src->sa_family) + { + case AF_INET: + SET_ISAKMP_ID_TYPE (buf, IPSEC_ID_IPV4_ADDR); + break; + case AF_INET6: + SET_ISAKMP_ID_TYPE (buf, IPSEC_ID_IPV6_ADDR); + break; + } /* Already in network byteorder. */ - memcpy (buf + ISAKMP_ID_DATA_OFF, - &((struct sockaddr_in *)src)->sin_addr.s_addr, - sizeof (in_addr_t)); + memcpy (buf + ISAKMP_ID_DATA_OFF, sockaddr_data (src), + sockaddr_len (src)); } if (message_add_payload (msg, ISAKMP_PAYLOAD_ID, buf, sz, 1)) @@ -950,9 +957,20 @@ ike_phase_1_recv_ID (struct message *msg) return -1; } - /* XXX IPv4 specific */ inet_pton (AF_INET, p, rid); break; + case IPSEC_ID_IPV6_ADDR: + p = conf_get_str (rs, "Address"); + if (!p) + { + log_print ("ike_phase_1_recv_ID: failed to get Address in " + "Remote-ID section [%s]", rs); + free (rid); + return -1; + } + + inet_pton (AF_INET6, p, rid); + break; case IPSEC_ID_FQDN: case IPSEC_ID_USER_FQDN: case IPSEC_ID_KEY_ID: diff --git a/sbin/isakmpd/ipsec.c b/sbin/isakmpd/ipsec.c index bb96f2bc841..a7f076b93bf 100644 --- a/sbin/isakmpd/ipsec.c +++ b/sbin/isakmpd/ipsec.c @@ -1,9 +1,10 @@ -/* $OpenBSD: ipsec.c,v 1.46 2001/06/27 03:31:40 angelos Exp $ */ +/* $OpenBSD: ipsec.c,v 1.47 2001/06/29 04:12:00 ho Exp $ */ /* $EOM: ipsec.c,v 1.143 2000/12/11 23:57:42 niklas Exp $ */ /* * Copyright (c) 1998, 1999, 2000, 2001 Niklas Hallqvist. All rights reserved. * Copyright (c) 2001 Angelos D. Keromytis. All rights reserved. + * Copyright (c) 2001 Håkan Olsson. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -184,7 +185,7 @@ int16_t script_new_group_mode[] = { }; struct dst_spi_proto_arg { - in_addr_t dst; + struct sockaddr *dst; u_int32_t spi; u_int8_t proto; }; @@ -207,12 +208,14 @@ ipsec_sa_check (struct sa *sa, void *v_arg) return 0; sa->transport->vtbl->get_dst (sa->transport, &dst, &dstlen); - if (((struct sockaddr_in *)dst)->sin_addr.s_addr == arg->dst) + if (memcmp (sockaddr_data (dst), sockaddr_data (arg->dst), + sockaddr_len (dst)) == 0) incoming = 0; else { sa->transport->vtbl->get_src (sa->transport, &src, &srclen); - if (((struct sockaddr_in *)src)->sin_addr.s_addr == arg->dst) + if (memcmp (sockaddr_data (src), sockaddr_data (arg->dst), + sockaddr_len (src)) == 0) incoming = 1; else return 0; @@ -228,7 +231,7 @@ ipsec_sa_check (struct sa *sa, void *v_arg) /* Find an SA with a "name" of DST, SPI & PROTO. */ struct sa * -ipsec_sa_lookup (in_addr_t dst, u_int32_t spi, u_int8_t proto) +ipsec_sa_lookup (struct sockaddr *dst, u_int32_t spi, u_int8_t proto) { struct dst_spi_proto_arg arg = { dst, spi, proto }; @@ -250,10 +253,19 @@ ipsec_sa_check_flow (struct sa *sa, void *v_arg) || (sa->flags & (SA_FLAG_READY | SA_FLAG_REPLACED)) != SA_FLAG_READY) return 0; - return isa->src_net == isa2->src_net && isa->src_mask == isa2->src_mask - && isa->dst_net == isa2->dst_net && isa->dst_mask == isa2->dst_mask - && isa->tproto == isa2->tproto && isa->sport == isa2->sport - && isa->dport == isa2->dport; + if (isa->tproto != isa2->tproto || isa->sport != isa2->sport + || isa->dport != isa2->dport) + return 0; + + return isa->src_net->sa_family == isa2->src_net->sa_family + && memcmp (sockaddr_data (isa->src_net), sockaddr_data (isa2->src_net), + sockaddr_len (isa->src_net)) == 0 + && memcmp (sockaddr_data (isa->src_mask), sockaddr_data (isa2->src_mask), + sockaddr_len (isa->src_mask)) == 0 + && memcmp (sockaddr_data (isa->dst_net), sockaddr_data (isa2->dst_net), + sockaddr_len (isa->dst_net)) == 0 + && memcmp (sockaddr_data (isa->dst_mask), sockaddr_data (isa2->dst_mask), + sockaddr_len (isa->dst_mask)) == 0; } /* @@ -269,6 +281,9 @@ ipsec_finalize_exchange (struct message *msg) struct ipsec_exch *ie = exchange->data; struct sa *sa = 0, *old_sa; struct proto *proto, *last_proto = 0; +#ifdef USE_DEBUG + char *addr1, *addr2, *mask1, *mask2; +#endif switch (exchange->phase) { @@ -328,13 +343,34 @@ ipsec_finalize_exchange (struct message *msg) /* Responder is source, initiator is destination. */ ipsec_set_network (ie->id_cr, ie->id_ci, isa); +#ifdef USE_DEBUG + if (sockaddr2text (isa->src_net, &addr1, 0)) + addr1 = 0; + if (sockaddr2text (isa->src_mask, &mask1, 0)) + mask1 = 0; + if (sockaddr2text (isa->dst_net, &addr2, 0)) + addr2 = 0; + if (sockaddr2text (isa->dst_mask, &mask2, 0)) + mask2 = 0; + LOG_DBG ((LOG_EXCHANGE, 50, "ipsec_finalize_exchange: " "src %x %x dst %x %x tproto %u sport %u dport %u", - ntohl (isa->src_net), ntohl (isa->src_mask), - ntohl (isa->dst_net), ntohl (isa->dst_mask), + addr1 ? addr1 : "" , mask1 ? mask1 : "", + addr2 ? addr2 : "" , mask2 ? mask2 : "", ntohs (isa->tproto), isa->sport, ntohs (isa->dport))); + if (addr1) + free (addr1); + if (mask1) + free (mask1); + if (addr2) + free (addr2); + if (mask2) + free (mask2); + +#endif /* USE_DEBUG */ + /* * If this is not an SA acquired by the kernel, it needs * to have a SPD entry (a.k.a. flow) set up. @@ -359,59 +395,118 @@ ipsec_set_network (u_int8_t *src_id, u_int8_t *dst_id, struct ipsec_sa *isa) { int id; - /* Set source address. */ + /* Set source address/mask. */ id = GET_ISAKMP_ID_TYPE (src_id); switch (id) { case IPSEC_ID_IPV4_ADDR: - memcpy (&isa->src_net, src_id + ISAKMP_ID_DATA_OFF, sizeof isa->src_net); - isa->src_mask = htonl (0xffffffff); - memcpy (&isa->tproto, - src_id + ISAKMP_ID_DOI_DATA_OFF + IPSEC_ID_PROTO_OFF, - IPSEC_ID_PROTO_LEN); - memcpy (&isa->sport, src_id + ISAKMP_ID_DOI_DATA_OFF + IPSEC_ID_PORT_OFF, - IPSEC_ID_PORT_LEN); + case IPSEC_ID_IPV4_ADDR_SUBNET: + isa->src_net = + (struct sockaddr *)calloc (1, sizeof (struct sockaddr_in)); + /* XXX this may fail ! */ + isa->src_net->sa_family = AF_INET; + isa->src_net->sa_len = sizeof (struct sockaddr_in); + isa->src_mask = + (struct sockaddr *)calloc (1, sizeof (struct sockaddr_in)); + /* XXX this may fail ! */ + isa->src_mask->sa_family = AF_INET; + isa->src_mask->sa_len = sizeof (struct sockaddr_in); + break; + + case IPSEC_ID_IPV6_ADDR: + case IPSEC_ID_IPV6_ADDR_SUBNET: + isa->src_net = + (struct sockaddr *)calloc (1, sizeof (struct sockaddr_in6)); + /* XXX this may fail ! */ + isa->src_net->sa_family = AF_INET6; + isa->src_net->sa_len = sizeof (struct sockaddr_in6); + isa->src_mask = + (struct sockaddr *)calloc (1, sizeof (struct sockaddr_in6)); + /* XXX this may fail ! */ + isa->src_mask->sa_family = AF_INET6; + isa->src_mask->sa_len = sizeof (struct sockaddr_in6); break; + } + + /* Net */ + memcpy (sockaddr_data (isa->src_net), src_id + ISAKMP_ID_DATA_OFF, + sockaddr_len (isa->src_net)); + /* Mask */ + switch (id) + { + case IPSEC_ID_IPV4_ADDR: + case IPSEC_ID_IPV6_ADDR: + memset (sockaddr_data (isa->src_mask), 0xff, + sockaddr_len (isa->src_mask)); + break; case IPSEC_ID_IPV4_ADDR_SUBNET: - memcpy (&isa->src_net, src_id + ISAKMP_ID_DATA_OFF, sizeof isa->src_net); - memcpy (&isa->src_mask, - src_id + ISAKMP_ID_DATA_OFF + sizeof isa->src_net, - sizeof isa->src_mask); - memcpy (&isa->tproto, - src_id + ISAKMP_ID_DOI_DATA_OFF + IPSEC_ID_PROTO_OFF, - IPSEC_ID_PROTO_LEN); - memcpy (&isa->sport, src_id + ISAKMP_ID_DOI_DATA_OFF + IPSEC_ID_PORT_OFF, - IPSEC_ID_PORT_LEN); + case IPSEC_ID_IPV6_ADDR_SUBNET: + memcpy (sockaddr_data (isa->src_mask), src_id + ISAKMP_ID_DATA_OFF + + sockaddr_len (isa->src_net), sockaddr_len (isa->src_mask)); break; - } + } + + memcpy (&isa->tproto, dst_id + ISAKMP_ID_DOI_DATA_OFF + IPSEC_ID_PROTO_OFF, + IPSEC_ID_PROTO_LEN); + memcpy (&isa->dport, dst_id + ISAKMP_ID_DOI_DATA_OFF + IPSEC_ID_PORT_OFF, + IPSEC_ID_PORT_LEN); /* Set destination address. */ id = GET_ISAKMP_ID_TYPE (dst_id); switch (id) { case IPSEC_ID_IPV4_ADDR: - memcpy (&isa->dst_net, dst_id + ISAKMP_ID_DATA_OFF, sizeof isa->dst_net); - isa->dst_mask = htonl (0xffffffff); - memcpy (&isa->tproto, - dst_id + ISAKMP_ID_DOI_DATA_OFF + IPSEC_ID_PROTO_OFF, - IPSEC_ID_PROTO_LEN); - memcpy (&isa->dport, dst_id + ISAKMP_ID_DOI_DATA_OFF + IPSEC_ID_PORT_OFF, - IPSEC_ID_PORT_LEN); + case IPSEC_ID_IPV4_ADDR_SUBNET: + isa->dst_net = + (struct sockaddr *)calloc (1, sizeof (struct sockaddr_in)); + /* XXX this may fail ! */ + isa->dst_net->sa_family = AF_INET; + isa->dst_net->sa_len = sizeof (struct sockaddr_in); + isa->dst_mask = + (struct sockaddr *)calloc (1, sizeof (struct sockaddr_in)); + /* XXX this may fail ! */ + isa->dst_mask->sa_family = AF_INET; + isa->dst_mask->sa_len = sizeof (struct sockaddr_in); + break; + case IPSEC_ID_IPV6_ADDR: + case IPSEC_ID_IPV6_ADDR_SUBNET: + isa->dst_net = + (struct sockaddr *)calloc (1, sizeof (struct sockaddr_in6)); + /* XXX this may fail ! */ + isa->dst_net->sa_family = AF_INET6; + isa->dst_net->sa_len = sizeof (struct sockaddr_in6); + isa->dst_mask = + (struct sockaddr *)calloc (1, sizeof (struct sockaddr_in6)); + /* XXX this may fail ! */ + isa->dst_mask->sa_family = AF_INET6; + isa->dst_mask->sa_len = sizeof (struct sockaddr_in6); break; + } + /* Net */ + memcpy (sockaddr_data (isa->dst_net), dst_id + ISAKMP_ID_DATA_OFF, + sockaddr_len (isa->dst_net)); + + /* Mask */ + switch (id) + { + case IPSEC_ID_IPV4_ADDR: + case IPSEC_ID_IPV6_ADDR: + memset (sockaddr_data (isa->dst_mask), 0xff, + sockaddr_len (isa->dst_mask)); + break; case IPSEC_ID_IPV4_ADDR_SUBNET: - memcpy (&isa->dst_net, dst_id + ISAKMP_ID_DATA_OFF, sizeof isa->dst_net); - memcpy (&isa->dst_mask, - dst_id + ISAKMP_ID_DATA_OFF + sizeof isa->dst_net, - sizeof isa->dst_mask); - memcpy (&isa->tproto, - dst_id + ISAKMP_ID_DOI_DATA_OFF + IPSEC_ID_PROTO_OFF, - IPSEC_ID_PROTO_LEN); - memcpy (&isa->dport, dst_id + ISAKMP_ID_DOI_DATA_OFF + IPSEC_ID_PORT_OFF, - IPSEC_ID_PORT_LEN); + case IPSEC_ID_IPV6_ADDR_SUBNET: + memcpy (sockaddr_data (isa->dst_mask), dst_id + ISAKMP_ID_DATA_OFF + + sockaddr_len (isa->dst_net), sockaddr_len (isa->dst_mask)); break; } + + memcpy (&isa->tproto, dst_id + ISAKMP_ID_DOI_DATA_OFF + IPSEC_ID_PROTO_OFF, + IPSEC_ID_PROTO_LEN); + memcpy (&isa->dport, dst_id + ISAKMP_ID_DOI_DATA_OFF + IPSEC_ID_PORT_OFF, + IPSEC_ID_PORT_LEN); } /* Free the DOI-specific exchange data pointed to by VIE. */ @@ -454,6 +549,14 @@ ipsec_free_sa_data (void *visa) { struct ipsec_sa *isa = visa; + if (isa->src_net) + free (isa->src_net); + if (isa->src_mask) + free (isa->src_mask); + if (isa->dst_net) + free (isa->dst_net); + if (isa->dst_mask) + free (isa->dst_mask); if (isa->skeyid_a) free (isa->skeyid_a); if (isa->skeyid_d) @@ -604,13 +707,24 @@ ipsec_validate_id_information (u_int8_t type, u_int8_t *extra, u_int8_t *buf, { case IPSEC_ID_IPV4_ADDR: LOG_DBG_BUF ((LOG_MESSAGE, 40, "ipsec_validate_id_information: IPv4", - buf, 4)); + buf, sizeof (struct in_addr))); + break; + + case IPSEC_ID_IPV6_ADDR: + LOG_DBG_BUF ((LOG_MESSAGE, 40, "ipsec_validate_id_information: IPv6", + buf, sizeof (struct in6_addr))); break; case IPSEC_ID_IPV4_ADDR_SUBNET: LOG_DBG_BUF ((LOG_MESSAGE, 40, "ipsec_validate_id_information: IPv4 network/netmask", - buf, 8)); + buf, 2 * sizeof (struct in_addr))); + break; + + case IPSEC_ID_IPV6_ADDR_SUBNET: + LOG_DBG_BUF ((LOG_MESSAGE, 40, + "ipsec_validate_id_information: IPv6 network/netmask", + buf, 2 * sizeof (struct in6_addr))); break; default: @@ -768,7 +882,6 @@ static void ipsec_delete_spi_list (struct sockaddr *addr, u_int8_t proto, u_int8_t *spis, int nspis, char *type) { - u_int32_t iaddr = ((struct sockaddr_in *)addr)->sin_addr.s_addr; struct sa *sa; int i; @@ -789,7 +902,7 @@ ipsec_delete_spi_list (struct sockaddr *addr, u_int8_t proto, { u_int32_t spi = ((u_int32_t *)spis)[i]; - sa = ipsec_sa_lookup (iaddr, spi, proto); + sa = ipsec_sa_lookup (addr, spi, proto); } if (sa == NULL) @@ -1568,8 +1681,8 @@ ipsec_keymat_length (struct proto *proto) * Return 0 on success and -1 on failure. */ int -ipsec_get_id (char *section, int *id, struct in_addr *addr, - struct in_addr *mask, u_int8_t *tproto, u_int16_t *port) +ipsec_get_id (char *section, int *id, struct sockaddr **addr, + struct sockaddr **mask, u_int8_t *tproto, u_int16_t *port) { char *type, *address, *netmask; @@ -1584,6 +1697,7 @@ ipsec_get_id (char *section, int *id, struct in_addr *addr, switch (*id) { case IPSEC_ID_IPV4_ADDR: + case IPSEC_ID_IPV6_ADDR: address = conf_get_str (section, "Address"); if (!address) { @@ -1592,7 +1706,7 @@ ipsec_get_id (char *section, int *id, struct in_addr *addr, return -1; } - if (!inet_aton (address, addr)) + if (text2sockaddr (address, NULL, addr)) { log_print ("ipsec_get_id: invalid address %s in section %s", section, address); @@ -1613,6 +1727,7 @@ ipsec_get_id (char *section, int *id, struct in_addr *addr, #endif case IPSEC_ID_IPV4_ADDR_SUBNET: + case IPSEC_ID_IPV6_ADDR_SUBNET: address = conf_get_str (section, "Network"); if (!address) { @@ -1621,7 +1736,7 @@ ipsec_get_id (char *section, int *id, struct in_addr *addr, return -1; } - if (!inet_aton (address, addr)) + if (text2sockaddr (address, NULL, addr)) { log_print ("ipsec_get_id: invalid section %s network %s", section, address); @@ -1636,7 +1751,7 @@ ipsec_get_id (char *section, int *id, struct in_addr *addr, return -1; } - if (!inet_aton (netmask, mask)) + if (text2sockaddr (netmask, NULL, mask)) { log_print ("ipsec_id_build: invalid section %s network %s", section, netmask); @@ -1649,12 +1764,6 @@ ipsec_get_id (char *section, int *id, struct in_addr *addr, break; #ifdef notyet - case IPSEC_ID_IPV6_ADDR: - return -1; - - case IPSEC_ID_IPV6_ADDR_SUBNET: - return -1; - case IPSEC_ID_IPV4_RANGE: return -1; @@ -1680,43 +1789,18 @@ ipsec_get_id (char *section, int *id, struct in_addr *addr, return 0; } -static void -ipsec_ipv4toa (char *buf, size_t size, u_int8_t *addr) -{ -#ifdef HAVE_GETNAMEINFO - 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 *sfrom; - sfrom->sin_family = AF_INET; - memcpy (&sfrom->sin_addr.s_addr, addr, sizeof sfrom->sin_addr.s_addr); - - if (getnameinfo ((struct sockaddr *)sfrom, sfrom->sin_len, buf, size, NULL, - 0, NI_NUMERICHOST) != 0) - { - log_print ("ipsec_ipv4toa: getnameinfo () failed"); - strcpy (buf, ""); - } -#else - strncpy (buf, inet_ntoa (*(struct in_addr *)addr), size - 1); - buf[size - 1] = '\0'; -#endif /* HAVE_GETNAMEINFO */ -} - 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]; + char *addr = 0, *mask = 0; if (id) { if (!isakmpform) { - /* exchanges and SA's dont carry the IDs in ISAKMP form */ + /* exchanges and SAs dont carry the IDs in ISAKMP form */ id -= ISAKMP_ID_TYPE_OFF; id_len += ISAKMP_ID_TYPE_OFF; } @@ -1725,18 +1809,22 @@ ipsec_decode_id (u_int8_t *buf, int size, u_int8_t *id, size_t id_len, switch (id_type) { case IPSEC_ID_IPV4_ADDR: - ipsec_ipv4toa (ntop, sizeof ntop, id + ISAKMP_ID_DATA_OFF); + util_ntoa (&addr, AF_INET, id + ISAKMP_ID_DATA_OFF); snprintf (buf, size, "%08x: %s", - decode_32 (id + ISAKMP_ID_DATA_OFF), ntop); + decode_32 (id + ISAKMP_ID_DATA_OFF), addr); 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); + util_ntoa (&addr, AF_INET, id + ISAKMP_ID_DATA_OFF); + util_ntoa (&mask, AF_INET, 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); + addr, mask); break; + case IPSEC_ID_IPV6_ADDR: + /* XXX */ + break; + case IPSEC_ID_FQDN: case IPSEC_ID_USER_FQDN: /* String is not NUL terminated, be careful */ @@ -1745,7 +1833,6 @@ ipsec_decode_id (u_int8_t *buf, int size, u_int8_t *id, size_t id_len, memcpy (buf, id + ISAKMP_ID_DATA_OFF, id_len); buf[id_len] = '\0'; break; - /* XXX - IPV6 et al */ default: snprintf (buf, size, "", id_type); break; @@ -1753,6 +1840,10 @@ ipsec_decode_id (u_int8_t *buf, int size, u_int8_t *id, size_t id_len, } else snprintf (buf, size, ""); + if (addr) + free (addr); + if (mask) + free (mask); } char * @@ -1777,25 +1868,21 @@ ipsec_decode_ids (char *fmt, u_int8_t *id1, size_t id1_len, u_int8_t * ipsec_build_id (char *section, size_t *sz) { - struct in_addr addr, mask; + struct sockaddr *addr, *mask; u_int8_t *p; - int id; + int id, subnet = 0; u_int8_t tproto = 0; u_int16_t port = 0; if (ipsec_get_id (section, &id, &addr, &mask, &tproto, &port)) return 0; - *sz = ISAKMP_ID_SZ; - switch (id) - { - case IPSEC_ID_IPV4_ADDR: - *sz += sizeof addr; - break; - case IPSEC_ID_IPV4_ADDR_SUBNET: - *sz += sizeof addr + sizeof mask; - break; - } + if (id == IPSEC_ID_IPV4_ADDR_SUBNET || id == IPSEC_ID_IPV6_ADDR_SUBNET) + subnet = 1; + + *sz = ISAKMP_ID_SZ + sockaddr_len (addr); + if (subnet) + *sz += sockaddr_len (mask); p = malloc (*sz); if (!p) @@ -1807,20 +1894,13 @@ ipsec_build_id (char *section, size_t *sz) SET_ISAKMP_ID_TYPE (p, id); SET_ISAKMP_ID_DOI_DATA (p, "\000\000\000"); - switch (id) - { - case IPSEC_ID_IPV4_ADDR: - encode_32 (p + ISAKMP_ID_DATA_OFF, ntohl (addr.s_addr)); - SET_IPSEC_ID_PROTO (p + ISAKMP_ID_DOI_DATA_OFF, tproto); - SET_IPSEC_ID_PORT (p + ISAKMP_ID_DOI_DATA_OFF, port); - break; - case IPSEC_ID_IPV4_ADDR_SUBNET: - encode_32 (p + ISAKMP_ID_DATA_OFF, ntohl (addr.s_addr)); - encode_32 (p + ISAKMP_ID_DATA_OFF + 4, ntohl (mask.s_addr)); - SET_IPSEC_ID_PROTO (p + ISAKMP_ID_DOI_DATA_OFF, tproto); - SET_IPSEC_ID_PORT (p + ISAKMP_ID_DOI_DATA_OFF, port); - break; - } + memcpy (p + ISAKMP_ID_DATA_OFF, sockaddr_data (addr), sockaddr_len (addr)); + if (subnet) + memcpy (p + ISAKMP_ID_DATA_OFF + sockaddr_len (addr), + sockaddr_data (mask), sockaddr_len (mask)); + + SET_IPSEC_ID_PROTO (p + ISAKMP_ID_DOI_DATA_OFF, tproto); + SET_IPSEC_ID_PORT (p + ISAKMP_ID_DOI_DATA_OFF, port); return p; } @@ -2101,9 +2181,13 @@ ipsec_id_size (char *section, u_int8_t *id) switch (*id) { case IPSEC_ID_IPV4_ADDR: - return sizeof (in_addr_t); + return sizeof (struct in_addr); case IPSEC_ID_IPV4_ADDR_SUBNET: - return 2 * sizeof (in_addr_t); + return 2 * sizeof (struct in_addr); + case IPSEC_ID_IPV6_ADDR: + return sizeof (struct in6_addr); + case IPSEC_ID_IPV6_ADDR_SUBNET: + return 2 * sizeof (struct in6_addr); case IPSEC_ID_FQDN: case IPSEC_ID_USER_FQDN: case IPSEC_ID_KEY_ID: diff --git a/sbin/isakmpd/ipsec.h b/sbin/isakmpd/ipsec.h index 5f46c5d0599..3b60305b8b3 100644 --- a/sbin/isakmpd/ipsec.h +++ b/sbin/isakmpd/ipsec.h @@ -1,9 +1,10 @@ -/* $OpenBSD: ipsec.h,v 1.16 2001/06/27 03:31:41 angelos Exp $ */ +/* $OpenBSD: ipsec.h,v 1.17 2001/06/29 04:12:00 ho Exp $ */ /* $EOM: ipsec.h,v 1.42 2000/12/03 07:58:20 angelos Exp $ */ /* * Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved. * Copyright (c) 1999 Angelos D. Keromytis. All rights reserved. + * Copyright (c) 2001 Håkan Olsson. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -110,10 +111,10 @@ struct ipsec_sa { u_int16_t group_desc; /* Tunnel parameters. These are in network byte order. */ - in_addr_t src_net; - in_addr_t src_mask; - in_addr_t dst_net; - in_addr_t dst_mask; + struct sockaddr *src_net; + struct sockaddr *src_mask; + struct sockaddr *dst_net; + struct sockaddr *dst_mask; u_int8_t tproto; u_int16_t sport; u_int16_t dport; @@ -143,8 +144,8 @@ extern int ipsec_esp_authkeylength (struct proto *); extern int ipsec_esp_enckeylength (struct proto *); extern int ipsec_fill_in_hash (struct message *msg); extern int ipsec_gen_g_x (struct message *); -extern int ipsec_get_id (char *, int *, struct in_addr *, struct in_addr *, - u_int8_t *, u_int16_t *); +extern int ipsec_get_id (char *, int *, struct sockaddr **, + struct sockaddr **, u_int8_t *, u_int16_t *); extern ssize_t ipsec_id_size (char *, u_int8_t *); extern void ipsec_init (void); extern int ipsec_initial_contact (struct message *msg); @@ -152,7 +153,7 @@ extern int ipsec_is_attribute_incompatible (u_int16_t, u_int8_t *, u_int16_t, void *); extern int ipsec_keymat_length (struct proto *); extern int ipsec_save_g_x (struct message *); -extern struct sa *ipsec_sa_lookup (in_addr_t, u_int32_t, u_int8_t); +extern struct sa *ipsec_sa_lookup (struct sockaddr *, u_int32_t, u_int8_t); extern char *ipsec_decode_ids(char *, u_int8_t *, size_t, u_int8_t *, size_t, int); diff --git a/sbin/isakmpd/pf_encap.c b/sbin/isakmpd/pf_encap.c index 14322ff8d53..f905180d320 100644 --- a/sbin/isakmpd/pf_encap.c +++ b/sbin/isakmpd/pf_encap.c @@ -1,8 +1,9 @@ -/* $OpenBSD: pf_encap.c,v 1.22 2001/06/27 03:31:42 angelos Exp $ */ +/* $OpenBSD: pf_encap.c,v 1.23 2001/06/29 04:12:00 ho Exp $ */ /* $EOM: pf_encap.c,v 1.73 2000/12/04 04:46:34 angelos Exp $ */ /* * Copyright (c) 1998, 1999, 2001 Niklas Hallqvist. All rights reserved. + * Copyright (c) 2001 Håkan Olsson. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -724,11 +725,14 @@ pf_encap_enable_sa (struct sa *sa, struct sa *isakmp_sa) /* Enable a flow. */ int -pf_encap_enable_spi (in_addr_t laddr, in_addr_t lmask, in_addr_t raddr, - in_addr_t rmask, u_int8_t *spi, u_int8_t proto, - in_addr_t dst) +pf_encap_enable_spi (struct sockaddr *laddr, struct sockaddr *lmask, + struct sockaddr *raddr, struct sockaddr *rmask, + u_int8_t *spi, u_int8_t proto, in_addr_t dst) { struct encap_msghdr *emsg = 0; +#ifdef USE_DEBUG + char *la_str, *lm_str, *ra_str, *rm_str; +#endif emsg = calloc (1, EMT_ENABLESPI_FLEN); if (!emsg) @@ -741,12 +745,34 @@ pf_encap_enable_spi (in_addr_t laddr, in_addr_t lmask, in_addr_t raddr, memcpy (&emsg->em_ena_spi, spi, sizeof emsg->em_ena_spi); emsg->em_ena_dst.s_addr = dst; +#ifdef USE_DEBUG + if (sockaddr2text (laddr, &la_str)) + la_str = 0; + if (sockaddr2text (lmask, &lm_str)) + lm_str = 0; + if (sockaddr2text (raddr, &ra_str)) + ra_str = 0; + if (sockaddr2text (rmask, &rm_str)) + rm_str = 0; + LOG_DBG ((LOG_SYSDEP, 50, "pf_encap_enable_spi: src %x %x dst %x %x", - htonl (laddr), htonl (lmask), htonl (raddr), htonl (rmask))); - emsg->em_ena_isrc.s_addr = laddr; - emsg->em_ena_ismask.s_addr = lmask; - emsg->em_ena_idst.s_addr = raddr; - emsg->em_ena_idmask.s_addr = rmask; + la_str ? la_str : "", lm_str : lm_str ? "", + ra_str ? ra_str : "", rm_str : rm_str ? "")); + + if (la_str) + free (la_str); + if (lm_str) + free (lm_str); + if (ra_str) + free (ra_str); + if (rm_str) + free (rm_str); +#endif /* USE_DEBUG */ + + emsg->em_ena_isrc.s_addr = ((struct sockaddr_in *)laddr)->sin_addr.s_addr; + emsg->em_ena_ismask.s_addr = ((struct sockaddr_in *)lmask)->sin_addr.s_addr; + emsg->em_ena_idst.s_addr = ((struct sockaddr_in *)raddr)->sin_addr.s_addr; + emsg->em_ena_idmask.s_addr = ((struct sockaddr_in *)rmask)->sin_addr.s_addr; emsg->em_ena_flags = ENABLE_FLAG_REPLACE; /* XXX What if IPCOMP etc. comes along? */ @@ -903,7 +929,8 @@ void pf_encap_connection_check (char *conn) { char *conf, *doi_str, *local_id, *remote_id, *peer, *address; - struct in_addr laddr, lmask, raddr, rmask, gwaddr; + struct sockaddr *laddr, *lmask, *raddr, *rmask; + struct in_addr gwaddr; int lid, rid, err; u_int8_t tproto; u_int16_t sport, dport; @@ -974,7 +1001,10 @@ pf_encap_connection_check (char *conn) if (err) return; - if (pf_encap_route (laddr.s_addr, lmask.s_addr, raddr.s_addr, rmask.s_addr, + if (pf_encap_route (((struct sockaddr_in *)laddr)->sin_addr.s_addr, + ((struct sockaddr_in *)lmask)->sin_addr.s_addr, + ((struct sockaddr_in *)raddr)->sin_addr.s_addr, + ((struct sockaddr_in *)rmask)->sin_addr.s_addr, gwaddr.s_addr)) { pf_encap_deregister_on_demand_connection (conn); diff --git a/sbin/isakmpd/pf_key_v2.c b/sbin/isakmpd/pf_key_v2.c index e4fbf459ddc..1011d6536fd 100644 --- a/sbin/isakmpd/pf_key_v2.c +++ b/sbin/isakmpd/pf_key_v2.c @@ -1,9 +1,10 @@ -/* $OpenBSD: pf_key_v2.c,v 1.67 2001/06/27 03:31:43 angelos Exp $ */ +/* $OpenBSD: pf_key_v2.c,v 1.68 2001/06/29 04:12:00 ho Exp $ */ /* $EOM: pf_key_v2.c,v 1.79 2000/12/12 00:33:19 niklas Exp $ */ /* * Copyright (c) 1999, 2000, 2001 Niklas Hallqvist. All rights reserved. * Copyright (c) 1999, 2000, 2001 Angelos D. Keromytis. All rights reserved. + * Copyright (c) 2001 Håkan Olsson. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -53,20 +54,22 @@ #include #include #include +#include #include "sysdep.h" +#include "cert.h" #include "conf.h" #include "exchange.h" #include "ipsec.h" #include "ipsec_num.h" +#include "key.h" #include "log.h" #include "pf_key_v2.h" #include "sa.h" #include "timer.h" #include "transport.h" -#include "cert.h" -#include "key.h" +#include "util.h" #ifdef USE_KEYNOTE #include "policy.h" @@ -647,10 +650,9 @@ pf_key_v2_get_spi (size_t *sz, u_int8_t proto, struct sockaddr *src, /* Setup the ADDRESS extensions. */ len = sizeof (struct sadb_address) + PF_KEY_V2_ROUND (srclen); - addr = malloc (len); + addr = calloc (1, len); if (!addr) goto cleanup; - memset (addr + 1, '\0', sizeof (struct sockaddr_in)); addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC; addr->sadb_address_len = len / PF_KEY_V2_CHUNK; #ifndef __OpenBSD__ @@ -659,18 +661,24 @@ pf_key_v2_get_spi (size_t *sz, u_int8_t proto, struct sockaddr *src, #endif addr->sadb_address_reserved = 0; memcpy (addr + 1, src, srclen); - /* XXX IPv4-specific. */ - ((struct sockaddr_in *)(addr + 1))->sin_port = 0; + switch (((struct sockaddr *)(addr + 1))->sa_family) + { + case AF_INET: + ((struct sockaddr_in *)(addr + 1))->sin_port = 0; + break; + case AF_INET6: + ((struct sockaddr_in6 *)(addr + 1))->sin6_port = 0; + break; + } if (pf_key_v2_msg_add (getspi, (struct sadb_ext *)addr, PF_KEY_V2_NODE_MALLOCED) == -1) goto cleanup; addr = 0; len = sizeof (struct sadb_address) + PF_KEY_V2_ROUND (dstlen); - addr = malloc (len); + addr = calloc (1, len); if (!addr) goto cleanup; - memset (addr + 1, '\0', sizeof (struct sockaddr_in)); addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST; addr->sadb_address_len = len / PF_KEY_V2_CHUNK; #ifndef __OpenBSD__ @@ -679,8 +687,15 @@ pf_key_v2_get_spi (size_t *sz, u_int8_t proto, struct sockaddr *src, #endif addr->sadb_address_reserved = 0; memcpy (addr + 1, dst, dstlen); - /* XXX IPv4-specific. */ - ((struct sockaddr_in *)(addr + 1))->sin_port = 0; + switch (((struct sockaddr *)(addr + 1))->sa_family) + { + case AF_INET: + ((struct sockaddr_in *)(addr + 1))->sin_port = 0; + break; + case AF_INET6: + ((struct sockaddr_in6 *)(addr + 1))->sin6_port = 0; + break; + } if (pf_key_v2_msg_add (getspi, (struct sadb_ext *)addr, PF_KEY_V2_NODE_MALLOCED) == -1) goto cleanup; @@ -761,7 +776,7 @@ pf_key_v2_set_spi (struct sa *sa, struct proto *proto, int incoming, struct sockaddr *src, *dst; struct sadb_ident *sid = 0; char *pp; - int dstlen, srclen, keylen, hashlen, err, idtype; + int srclen, dstlen, keylen, hashlen, err, idtype; struct pf_key_v2_msg *update = 0, *ret = 0; struct ipsec_proto *iproto = proto->data; #if defined (SADB_X_CREDTYPE_NONE) || defined (SADB_X_AUTHTYPE_NONE) @@ -771,6 +786,9 @@ pf_key_v2_set_spi (struct sa *sa, struct proto *proto, int incoming, #ifdef KAME struct sadb_x_sa2 ssa2; #endif +#ifdef USE_DEBUG + char *addr_str; +#endif msg.sadb_msg_type = incoming ? SADB_UPDATE : SADB_ADD; switch (proto->proto) @@ -1002,15 +1020,13 @@ pf_key_v2_set_spi (struct sa *sa, struct proto *proto, int incoming, /* * Setup the ADDRESS extensions. - * - * XXX Addresses have to be thought through. Assumes IPv4. */ if (incoming) sa->transport->vtbl->get_dst (sa->transport, &src, &srclen); else sa->transport->vtbl->get_src (sa->transport, &src, &srclen); len = sizeof *addr + PF_KEY_V2_ROUND (srclen); - addr = malloc (len); + addr = calloc (1, len); if (!addr) goto cleanup; addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC; @@ -1021,14 +1037,22 @@ pf_key_v2_set_spi (struct sa *sa, struct proto *proto, int incoming, #endif addr->sadb_address_reserved = 0; memcpy (addr + 1, src, srclen); - ((struct sockaddr_in *)(addr + 1))->sin_port = 0; + switch (((struct sockaddr *)(addr + 1))->sa_family) + { + case AF_INET: + ((struct sockaddr_in *)(addr + 1))->sin_port = 0; + break; + case AF_INET6: + ((struct sockaddr_in6 *)(addr + 1))->sin6_port = 0; + break; + } if (pf_key_v2_msg_add (update, (struct sadb_ext *)addr, PF_KEY_V2_NODE_MALLOCED) == -1) goto cleanup; addr = 0; len = sizeof *addr + PF_KEY_V2_ROUND (dstlen); - addr = malloc (len); + addr = calloc (1, len); if (!addr) goto cleanup; addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST; @@ -1039,7 +1063,15 @@ pf_key_v2_set_spi (struct sa *sa, struct proto *proto, int incoming, #endif addr->sadb_address_reserved = 0; memcpy (addr + 1, dst, dstlen); - ((struct sockaddr_in *)(addr + 1))->sin_port = 0; + switch (((struct sockaddr *)(addr + 1))->sa_family) + { + case AF_INET: + ((struct sockaddr_in *)(addr + 1))->sin_port = 0; + break; + case AF_INET6: + ((struct sockaddr_in6 *)(addr + 1))->sin6_port = 0; + break; + } if (pf_key_v2_msg_add (update, (struct sadb_ext *)addr, PF_KEY_V2_NODE_MALLOCED) == -1) goto cleanup; @@ -1050,7 +1082,7 @@ pf_key_v2_set_spi (struct sa *sa, struct proto *proto, int incoming, if (iproto->encap_mode == IPSEC_ENCAP_TUNNEL) { len = sizeof *addr + PF_KEY_V2_ROUND (dstlen); - addr = malloc (len); + addr = calloc (1, len); if (!addr) goto cleanup; addr->sadb_address_exttype = SADB_EXT_ADDRESS_PROXY; @@ -1061,7 +1093,15 @@ pf_key_v2_set_spi (struct sa *sa, struct proto *proto, int incoming, #endif addr->sadb_address_reserved = 0; memcpy (addr + 1, dst, dstlen); - ((struct sockaddr_in *)(addr + 1))->sin_port = 0; + switch (((struct sockaddr *)(addr + 1))->sa_family) + { + case AF_INET: + ((struct sockaddr_in *)(addr + 1))->sin_port = 0; + break; + case AF_INET6: + ((struct sockaddr_in6 *)(addr + 1))->sin6_port = 0; + break; + } if (pf_key_v2_msg_add (update, (struct sadb_ext *)addr, PF_KEY_V2_NODE_MALLOCED) == -1) goto cleanup; @@ -1320,12 +1360,18 @@ pf_key_v2_set_spi (struct sa *sa, struct proto *proto, int incoming, /* XXX Here can sensitivity extensions be setup. */ - /* XXX IPv4 specific. */ +#ifdef USE_DEBUG + if (sockaddr2text (dst, &addr_str, 0)) + addr_str = 0; + LOG_DBG ((LOG_SYSDEP, 10, "pf_key_v2_set_spi: satype %d dst %s SPI 0x%x", - msg.sadb_msg_satype, - inet_ntoa (((struct sockaddr_in *)dst)->sin_addr), + msg.sadb_msg_satype, addr_str ? addr_str : "unknown", ntohl (ssa.sadb_sa_spi))); + if (addr_str) + free (addr_str); +#endif /* USE_DEBUG */ + /* * Although PF_KEY knows about expirations, it is unreliable per the specs * thus we need to do them inside isakmpd as well. @@ -1380,7 +1426,61 @@ pf_key_v2_set_spi (struct sa *sa, struct proto *proto, int incoming, static __inline__ int pf_key_v2_mask_to_bits (u_int32_t mask) { - return (33 - ffs (~mask + 1)) % 33; + u_int32_t hmask = ntohl (mask); + return (33 - ffs (~hmask + 1)) % 33; +} + +static int +pf_key_v2_mask6_to_bits (u_int8_t *mask) +{ + int n; + bit_ffc (mask, 128, &n); + return n; +} + +static void +pf_key_v2_setup_sockaddr (void *res, struct sockaddr *src, + struct sockaddr *dst, in_port_t port, int ingress) +{ + struct sockaddr_in *ip4_sa; + struct sockaddr_in6 *ip6_sa; + u_int8_t *p; + + switch (src->sa_family) + { + case AF_INET: + ip4_sa = (struct sockaddr_in *)res; + ip4_sa->sin_family = AF_INET; + ip4_sa->sin_len = sizeof *ip4_sa; + ip4_sa->sin_port = port; + if (dst) + p = (u_int8_t *)(ingress ? + &((struct sockaddr_in *)src)->sin_addr.s_addr : + &((struct sockaddr_in *)dst)->sin_addr.s_addr); + else + p = (u_int8_t *)&((struct sockaddr_in *)src)->sin_addr.s_addr; + ip4_sa->sin_addr.s_addr = *((in_addr_t *)p); + break; + + case AF_INET6: + ip6_sa = (struct sockaddr_in6 *)res; + ip6_sa->sin6_family = AF_INET6; + ip6_sa->sin6_len = sizeof *ip6_sa; + ip6_sa->sin6_port = port; + if (dst) + p = (u_int8_t *)(ingress ? + &((struct sockaddr_in6 *)src)->sin6_addr.s6_addr : + &((struct sockaddr_in6 *)dst)->sin6_addr.s6_addr); + else + p = (u_int8_t *)&((struct sockaddr_in6 *)src)->sin6_addr.s6_addr; + memcpy (ip6_sa->sin6_addr.s6_addr, p, sizeof (struct in6_addr)); + break; + + default: + log_print ("pf_key_v2_setup_sockaddr: unknown family %d\n", + src->sa_family); + break; + } } /* @@ -1389,10 +1489,11 @@ pf_key_v2_mask_to_bits (u_int32_t mask) * Should probably be moved to sysdep.c */ static int -pf_key_v2_flow (in_addr_t laddr, in_addr_t lmask, in_addr_t raddr, - in_addr_t rmask, u_int8_t tproto, u_int16_t sport, - u_int16_t dport, u_int8_t *spi, u_int8_t proto, - in_addr_t dst, in_addr_t src, int delete, int ingress, +pf_key_v2_flow (struct sockaddr *laddr, struct sockaddr *lmask, + struct sockaddr *raddr, struct sockaddr *rmask, + u_int8_t tproto, u_int16_t sport, u_int16_t dport, + u_int8_t *spi, u_int8_t proto, struct sockaddr *dst, + struct sockaddr *src, int delete, int ingress, u_int8_t srcid_type, u_int8_t *srcid, int srcid_len, u_int8_t dstid_type, u_int8_t *dstid, int dstid_len) { @@ -1409,6 +1510,9 @@ pf_key_v2_flow (in_addr_t laddr, in_addr_t lmask, in_addr_t raddr, struct pf_key_v2_msg *flow = 0, *ret = 0; size_t len; int err; +#ifdef USE_DEBUG + char *laddr_str, *lmask_str, *raddr_str, *rmask_str; +#endif #if !defined (SADB_X_SAFLAGS_INGRESS_FLOW) && !defined (SADB_X_EXT_FLOW_TYPE) if (ingress) @@ -1517,98 +1621,74 @@ pf_key_v2_flow (in_addr_t laddr, in_addr_t lmask, in_addr_t raddr, /* * Setup the ADDRESS extensions. - * - * XXX Addresses have to be thought through. Assumes IPv4. */ - len = sizeof *addr + PF_KEY_V2_ROUND (sizeof (struct sockaddr_in)); + len = sizeof *addr + PF_KEY_V2_ROUND (src->sa_len); #ifndef SADB_X_EXT_FLOW_TYPE if (!delete || ingress) #else if (!delete) #endif /* SADB_X_EXT_FLOW_TYPE */ { - addr = malloc (len); + addr = calloc (1, len); if (!addr) goto cleanup; addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST; addr->sadb_address_len = len / PF_KEY_V2_CHUNK; addr->sadb_address_reserved = 0; - memset (addr + 1, '\0', sizeof (struct sockaddr_in)); - ((struct sockaddr_in *)(addr + 1))->sin_len - = sizeof (struct sockaddr_in); - ((struct sockaddr_in *)(addr + 1))->sin_family = AF_INET; #ifdef SADB_X_EXT_FLOW_TYPE - ((struct sockaddr_in *)(addr + 1))->sin_addr.s_addr - = ingress ? src : dst; + pf_key_v2_setup_sockaddr (addr + 1, src, dst, 0, ingress); #else - ((struct sockaddr_in *)(addr + 1))->sin_addr.s_addr = dst; + pf_key_v2_setup_sockaddr (addr + 1, dst, NULL, 0, 0); #endif - ((struct sockaddr_in *)(addr + 1))->sin_port = 0; if (pf_key_v2_msg_add (flow, (struct sadb_ext *)addr, PF_KEY_V2_NODE_MALLOCED) == -1) goto cleanup; addr = 0; } - addr = malloc (len); + addr = calloc (1, len); if (!addr) goto cleanup; addr->sadb_address_exttype = SADB_X_EXT_SRC_FLOW; addr->sadb_address_len = len / PF_KEY_V2_CHUNK; addr->sadb_address_reserved = 0; - memset (addr + 1, '\0', sizeof (struct sockaddr_in)); - ((struct sockaddr_in *)(addr + 1))->sin_len = sizeof (struct sockaddr_in); - ((struct sockaddr_in *)(addr + 1))->sin_family = AF_INET; - ((struct sockaddr_in *)(addr + 1))->sin_addr.s_addr = laddr; - ((struct sockaddr_in *)(addr + 1))->sin_port = sport; + pf_key_v2_setup_sockaddr (addr + 1, laddr, NULL, sport, 0); if (pf_key_v2_msg_add (flow, (struct sadb_ext *)addr, PF_KEY_V2_NODE_MALLOCED) == -1) goto cleanup; addr = 0; - addr = malloc (len); + addr = calloc (1, len); if (!addr) goto cleanup; addr->sadb_address_exttype = SADB_X_EXT_SRC_MASK; addr->sadb_address_len = len / PF_KEY_V2_CHUNK; addr->sadb_address_reserved = 0; - memset (addr + 1, '\0', sizeof (struct sockaddr_in)); - ((struct sockaddr_in *)(addr + 1))->sin_len = sizeof (struct sockaddr_in); - ((struct sockaddr_in *)(addr + 1))->sin_family = AF_INET; - ((struct sockaddr_in *)(addr + 1))->sin_addr.s_addr = lmask; - ((struct sockaddr_in *)(addr + 1))->sin_port = sport ? 0xffff : 0; + pf_key_v2_setup_sockaddr (addr + 1, lmask, NULL, sport ? 0xffff : 0, 0); if (pf_key_v2_msg_add (flow, (struct sadb_ext *)addr, PF_KEY_V2_NODE_MALLOCED) == -1) goto cleanup; addr = 0; - addr = malloc (len); + addr = calloc (1, len); if (!addr) goto cleanup; addr->sadb_address_exttype = SADB_X_EXT_DST_FLOW; addr->sadb_address_len = len / PF_KEY_V2_CHUNK; addr->sadb_address_reserved = 0; - memset (addr + 1, '\0', sizeof (struct sockaddr_in)); - ((struct sockaddr_in *)(addr + 1))->sin_len = sizeof (struct sockaddr_in); - ((struct sockaddr_in *)(addr + 1))->sin_family = AF_INET; - ((struct sockaddr_in *)(addr + 1))->sin_addr.s_addr = raddr; - ((struct sockaddr_in *)(addr + 1))->sin_port = dport; + pf_key_v2_setup_sockaddr (addr + 1, raddr, NULL, sport, 0); if (pf_key_v2_msg_add (flow, (struct sadb_ext *)addr, PF_KEY_V2_NODE_MALLOCED) == -1) goto cleanup; addr = 0; - addr = malloc (len); + addr = calloc (1, len); if (!addr) goto cleanup; addr->sadb_address_exttype = SADB_X_EXT_DST_MASK; addr->sadb_address_len = len / PF_KEY_V2_CHUNK; addr->sadb_address_reserved = 0; - memset (addr + 1, '\0', sizeof (struct sockaddr_in)); - ((struct sockaddr_in *)(addr + 1))->sin_len = sizeof (struct sockaddr_in); - ((struct sockaddr_in *)(addr + 1))->sin_family = AF_INET; - ((struct sockaddr_in *)(addr + 1))->sin_addr.s_addr = rmask; - ((struct sockaddr_in *)(addr + 1))->sin_port = dport ? 0xffff : 0; + pf_key_v2_setup_sockaddr (addr + 1, rmask, NULL, sport ? 0xffff : 0, 0); if (pf_key_v2_msg_add (flow, (struct sadb_ext *)addr, PF_KEY_V2_NODE_MALLOCED) == -1) goto cleanup; @@ -1623,11 +1703,32 @@ pf_key_v2_flow (in_addr_t laddr, in_addr_t lmask, in_addr_t raddr, if (pf_key_v2_msg_add (flow, (struct sadb_ext *)&tprotocol, 0) == -1) goto cleanup; +#ifdef USE_DEBUG + if (sockaddr2text (laddr, &laddr_str, 0)) + laddr_str = 0; + if (sockaddr2text (lmask, &lmask_str, 0)) + lmask_str = 0; + if (sockaddr2text (raddr, &raddr_str, 0)) + raddr_str = 0; + if (sockaddr2text (rmask, &rmask_str, 0)) + rmask_str = 0; + LOG_DBG ((LOG_SYSDEP, 50, "pf_key_v2_flow: src %x %x dst %x %x proto %u sport %u dport %u", - ntohl (laddr), ntohl (lmask), ntohl (raddr), ntohl (rmask), + laddr_str ? laddr_str : "", lmask_str ? laddr_str : "", + raddr_str ? laddr_str : "", rmask_str ? laddr_str : "", tproto, ntohs (sport), ntohs (dport))); + if (laddr_str) + free (laddr_str); + if (lmask_str) + free (lmask_str); + if (raddr_str) + free (raddr_str); + if (rmask_str) + free (rmask_str); +#endif /* USE_DEBUG */ + ret = pf_key_v2_call (flow); pf_key_v2_msg_free (flow); flow = 0; @@ -1669,10 +1770,9 @@ pf_key_v2_flow (in_addr_t laddr, in_addr_t lmask, in_addr_t raddr, struct sadb_x_ipsecrequest *ipsecrequest; struct sadb_x_sa2 ssa2; struct sadb_address *addr = 0; - struct sockaddr_in *saddr; - u_int8_t - policy_buf[sizeof *policy + sizeof *ipsecrequest + 2 * sizeof *saddr]; + struct sockaddr *saddr; struct pf_key_v2_msg *flow = 0, *ret = 0; + u_int8_t *policy_buf; size_t len; int err; @@ -1692,47 +1792,70 @@ pf_key_v2_flow (in_addr_t laddr, in_addr_t lmask, in_addr_t raddr, /* * Setup the ADDRESS extensions. - * - * XXX Addresses have to be thought through. Assumes IPv4. */ - len = sizeof *addr + PF_KEY_V2_ROUND (sizeof (struct sockaddr_in)); - addr = malloc (len); + len = sizeof *addr + PF_KEY_V2_ROUND (src->sa_len); + addr = calloc (1, len); if (!addr) goto cleanup; addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC; addr->sadb_address_len = len / PF_KEY_V2_CHUNK; addr->sadb_address_proto = IPSEC_ULPROTO_ANY; - addr->sadb_address_prefixlen = pf_key_v2_mask_to_bits (ntohl (lmask)); addr->sadb_address_reserved = 0; - memset (addr + 1, '\0', sizeof (struct sockaddr_in)); - ((struct sockaddr_in *)(addr + 1))->sin_len = sizeof (struct sockaddr_in); - ((struct sockaddr_in *)(addr + 1))->sin_family = AF_INET; - ((struct sockaddr_in *)(addr + 1))->sin_addr.s_addr = laddr; - ((struct sockaddr_in *)(addr + 1))->sin_port = IPSEC_PORT_ANY; + pf_key_v2_setup_sockaddr (addr + 1, laddr, NULL, IPSEC_PORT_ANY, 0); + switch (laddr->sa_family) + { + case AF_INET: + ip4_sa = (struct sockaddr_in *)lmask; + addr->sadb_address_prefixlen = + pf_key_v2_mask_to_bits (ip4_sa->sin_addr.in_addr); + break; + case AF_INET6: + ip6_sa = (struct sockaddr_in6 *)lmask; + addr->sadb_address_prefixlen = + pf_key_v2_mask6_to_bits (ip6_sa->sin6_addr.in6_addr); + break; + } if (pf_key_v2_msg_add (flow, (struct sadb_ext *)addr, PF_KEY_V2_NODE_MALLOCED) == -1) goto cleanup; addr = 0; - addr = malloc (len); + addr = calloc (1, len); if (!addr) goto cleanup; addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST; addr->sadb_address_len = len / PF_KEY_V2_CHUNK; addr->sadb_address_proto = IPSEC_ULPROTO_ANY; - addr->sadb_address_prefixlen = pf_key_v2_mask_to_bits (ntohl (rmask)); addr->sadb_address_reserved = 0; - memset (addr + 1, '\0', sizeof (struct sockaddr_in)); - ((struct sockaddr_in *)(addr + 1))->sin_len = sizeof (struct sockaddr_in); - ((struct sockaddr_in *)(addr + 1))->sin_family = AF_INET; - ((struct sockaddr_in *)(addr + 1))->sin_addr.s_addr = raddr; - ((struct sockaddr_in *)(addr + 1))->sin_port = IPSEC_PORT_ANY; + pf_key_v2_setup_sockaddr (addr + 1, raddr, NULL, IPSEC_PORT_ANY, 0); + switch (raddr->sa_family) + { + case AF_INET: + ip4_sa = (struct sockaddr_in *)rmask; + addr->sadb_address_prefixlen = + pf_key_v2_mask_to_bits (ip4_sa->sin_addr.in_addr); + break; + case AF_INET6: + ip6_sa = (struct sockaddr_in6 *)rmask; + addr->sadb_address_prefixlen = + pf_key_v2_mask6_to_bits (ip6_sa->sin6_addr.in6_addr); + break; + } if (pf_key_v2_msg_add (flow, (struct sadb_ext *)addr, PF_KEY_V2_NODE_MALLOCED) == -1) goto cleanup; addr = 0; /* Setup the POLICY extension. */ + policy_buf = (u_int8_t *)calloc (1, sizeof *policy + sizeof *ipsecrequest + + 2 * sockaddr_len (src)); + if (!policy_buf) + { + log_error ("pf_key_v2_flow: calloc %d failed", sizeof *policy + + sizeof *ipsecrequest + 2 * sockaddr_len (src)); + goto cleanup; + } + policy = (struct sadb_x_policy *)policy_buf; policy->sadb_x_policy_exttype = SADB_X_EXT_POLICY; policy->sadb_x_policy_len = sizeof policy_buf / PF_KEY_V2_CHUNK; @@ -1746,7 +1869,7 @@ pf_key_v2_flow (in_addr_t laddr, in_addr_t lmask, in_addr_t raddr, /* Setup the IPSECREQUEST extension part. */ ipsecrequest = (struct sadb_x_ipsecrequest *)(policy + 1); ipsecrequest->sadb_x_ipsecrequest_len - = sizeof *ipsecrequest + 2 * sizeof *saddr; + = sizeof *ipsecrequest + 2 * sockaddr_len (src); switch (proto) { case IPSEC_PROTO_IPSEC_ESP: @@ -1764,26 +1887,45 @@ pf_key_v2_flow (in_addr_t laddr, in_addr_t lmask, in_addr_t raddr, = ingress ? IPSEC_LEVEL_USE : IPSEC_LEVEL_REQUIRE; ipsecrequest->sadb_x_ipsecrequest_reqid = 0; /* XXX */ - /* Add source and destination addresses. XXX IPv4 dependent */ - saddr = (struct sockaddr_in *)(ipsecrequest + 1); - memset (saddr, '\0', sizeof *saddr); - saddr->sin_len = sizeof (struct sockaddr_in); - saddr->sin_family = AF_INET; - saddr->sin_addr.s_addr = src; - saddr->sin_port = 0; - - saddr++; - memset (saddr, '\0', sizeof *saddr); - saddr->sin_len = sizeof (struct sockaddr_in); - saddr->sin_family = AF_INET; - saddr->sin_addr.s_addr = dst; - saddr->sin_port = 0; - + /* Add source and destination addresses. */ + saddr = (struct sockaddr *)(ipsecrequest + 1); + pf_key_v2_setup_sockaddr (saddr, src, NULL, 0, 0); + switch (src->sa_family) + { + case AF_INET: + saddr = (struct sockaddr_in *)saddr + 1; + break; + case AF_INET6: + saddr = (struct sockaddr_in6 *)saddr + 1; + break; + } + pf_key_v2_setup_sockaddr (saddr, dst, NULL, 0, 0); if (pf_key_v2_msg_add (flow, (struct sadb_ext *)policy, 0) == -1) goto cleanup; +#ifdef USE_DEBUG + if (sockaddr2text (laddr, &laddr_str, 0)) + laddr_str = 0; + if (sockaddr2text (lmask, &lmask_str, 0)) + lmask_str = 0; + if (sockaddr2text (raddr, &raddr_str, 0)) + raddr_str = 0; + if (sockaddr2text (rmask, &rmask_str, 0)) + rmask_str = 0; + LOG_DBG ((LOG_SYSDEP, 50, "pf_key_v2_flow: src %x %x dst %x %x", - ntohl (laddr), ntohl (lmask), ntohl (raddr), ntohl (rmask))); + laddr_str ? laddr_str : "", lmask_str ? laddr_str : "", + raddr_str ? laddr_str : "", rmask_str ? laddr_str : "")); + + if (laddr_str) + free (laddr_str); + if (lmask_str) + free (lmask_str); + if (raddr_str) + free (raddr_str); + if (rmask_str) + free (rmask_str); +#endif ret = pf_key_v2_call (flow); pf_key_v2_msg_free (flow); @@ -1825,6 +1967,7 @@ pf_key_v2_convert_id (u_int8_t *id, int idlen, int *reslen, int *idtype) { u_int8_t *res = 0; char addrbuf[ADDRESS_MAX + 5]; + char *addr; switch (id[0]) { @@ -1864,7 +2007,7 @@ pf_key_v2_convert_id (u_int8_t *id, int idlen, int *reslen, int *idtype) case IPSEC_ID_IPV6_ADDR: /* XXX CONNECTION ? */ if (inet_ntop (AF_INET6, id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ, addrbuf, ADDRESS_MAX) != NULL) - *reslen = strlen (addrbuf) + 4; + *reslen = strlen (addrbuf) + 5; strcat (addrbuf, "/128"); res = strdup (addrbuf); if (!res) @@ -1873,7 +2016,30 @@ pf_key_v2_convert_id (u_int8_t *id, int idlen, int *reslen, int *idtype) return res; case IPSEC_ID_IPV4_ADDR_SUBNET: /* XXX PREFIX */ + addr = id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ; + if (inet_ntop (AF_INET, addr, addrbuf, ADDRESS_MAX) != NULL) + *reslen = strlen (addrbuf) + 4; + sprintf (addrbuf + strlen (addrbuf), "/%d", + pf_key_v2_mask_to_bits ((u_int32_t)*(addr + + sizeof (struct in_addr)))); + res = strdup (addrbuf); + if (!res) + return 0; + *idtype = SADB_IDENTTYPE_PREFIX; + return res; + case IPSEC_ID_IPV6_ADDR_SUBNET: /* XXX PREFIX */ + addr = id + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ; + if (inet_ntop (AF_INET6, addr, addrbuf, ADDRESS_MAX) != NULL) + *reslen = strlen (addrbuf) + 5; + sprintf (addrbuf + strlen (addrbuf), "/%d", + pf_key_v2_mask6_to_bits (addr + sizeof (struct in6_addr))); + res = strdup (addrbuf); + if (!res) + return 0; + *idtype = SADB_IDENTTYPE_PREFIX; + return res; + case IPSEC_ID_IPV4_RANGE: case IPSEC_ID_IPV6_RANGE: case IPSEC_ID_DER_ASN1_DN: @@ -1897,7 +2063,8 @@ pf_key_v2_enable_sa (struct sa *sa, struct sa *isakmp_sa) int sidtype = 0, didtype = 0, sidlen = 0, didlen = 0; u_int8_t *sid = 0, *did = 0; #ifndef SADB_X_EXT_FLOW_TYPE - in_addr_t hostmask = 0xffffffff; /* XXX IPv4 specific */ + struct sockaddr_storage hostmask_storage; + struct sockaddr *hostmask = (struct sockaddr *)&hostmask_storage; #endif /* SADB_X_EXT_FLOW_TYPE */ sa->transport->vtbl->get_dst (sa->transport, &dst, &dstlen); @@ -1925,26 +2092,36 @@ pf_key_v2_enable_sa (struct sa *sa, struct sa *isakmp_sa) } #endif /* SADB_X_EXT_FLOW_TYPE */ - /* XXX IPv4 specific */ error = pf_key_v2_flow (isa->src_net, isa->src_mask, isa->dst_net, isa->dst_mask, isa->tproto, isa->sport, isa->dport, - proto->spi[0], proto->proto, - ((struct sockaddr_in *)dst)->sin_addr.s_addr, - ((struct sockaddr_in *)src)->sin_addr.s_addr, 0, 0, + proto->spi[0], proto->proto, dst, src, 0, 0, sidtype, sid, sidlen, didtype, did, didlen); if (error) goto cleanup; #ifndef SADB_X_EXT_FLOW_TYPE + /* Set hostmask to '-1'. */ + switch (dst->sa_family) + { + case AF_INET: + ((struct sockaddr_in *)hostmask)->sin_family = AF_INET; + ((struct sockaddr_in *)hostmask)->sin_len = sizeof (struct in_addr); + memset (&((struct sockaddr_in *)hostmask)->sin_addr.s_addr, 0xff, + sizeof (struct in_addr)); + break; + case AF_INET6: + ((struct sockaddr_in6 *)hostmask)->sin6_family = AF_INET6; + ((struct sockaddr_in6 *)hostmask)->sin6_len = sizeof (struct in6_addr); + memset (&((struct sockaddr_in6 *)hostmask)->sin6_addr.s6_addr, 0xff, + sizeof (struct in6_addr)); + break; + } + /* Ingress flows, handling SA bundles. */ while (TAILQ_NEXT (proto, link)) { - error = pf_key_v2_flow (((struct sockaddr_in *)dst)->sin_addr.s_addr, - hostmask, - ((struct sockaddr_in *)src)->sin_addr.s_addr, - hostmask, 0, 0, 0, proto->spi[1], proto->proto, - ((struct sockaddr_in *)src)->sin_addr.s_addr, - ((struct sockaddr_in *)dst)->sin_addr.s_addr, + error = pf_key_v2_flow (dst, hostmask, src, hostmask, 0, 0, 0, + proto->spi[1], proto->proto, src, dst, 0, 1, 0, 0, 0, 0, 0, 0); if (error) goto cleanup; @@ -1954,9 +2131,7 @@ pf_key_v2_enable_sa (struct sa *sa, struct sa *isakmp_sa) error = pf_key_v2_flow (isa->dst_net, isa->dst_mask, isa->src_net, isa->src_mask, isa->tproto, isa->dport, isa->sport, - proto->spi[1], proto->proto, - ((struct sockaddr_in *)src)->sin_addr.s_addr, - ((struct sockaddr_in *)dst)->sin_addr.s_addr, 0, 1, + proto->spi[1], proto->proto, src, dst, 0, 1, sidtype, sid, sidlen, didtype, did, didlen); cleanup: @@ -2104,7 +2279,8 @@ pf_key_v2_disable_sa (struct sa *sa, int incoming) int dstlen, srclen; struct proto *proto = TAILQ_FIRST (&sa->protos); #ifndef SADB_X_EXT_FLOW_TYPE - in_addr_t hostmask = 0xffffffff; /* XXX IPv4 specific */ + struct sockaddr_storage hostmask_storage; + struct sockaddr *hostmask = (struct sockaddr *)&hostmask_storage; int error; #endif /* SADB_X_EXT_FLOW_TYPE */ @@ -2114,23 +2290,34 @@ pf_key_v2_disable_sa (struct sa *sa, int incoming) if (!incoming) return pf_key_v2_flow (isa->src_net, isa->src_mask, isa->dst_net, isa->dst_mask, isa->tproto, isa->sport, isa->dport, - proto->spi[0], proto->proto, - ((struct sockaddr_in *)dst)->sin_addr.s_addr, - ((struct sockaddr_in *)src)->sin_addr.s_addr, 1, 0, + proto->spi[0], proto->proto, src, dst, 1, 0, 0, 0, 0, 0, 0, 0); else { #ifndef SADB_X_EXT_FLOW_TYPE + /* Set hostmask to '-1'. */ + switch (dst->sa_family) + { + case AF_INET: + ((struct sockaddr_in *)hostmask)->sin_family = AF_INET; + ((struct sockaddr_in *)hostmask)->sin_len = sizeof (struct in_addr); + memset (&((struct sockaddr_in *)hostmask)->sin_addr.s_addr, 0xff, + sizeof (struct in_addr)); + break; + case AF_INET6: + ((struct sockaddr_in6 *)hostmask)->sin6_family = AF_INET6; + ((struct sockaddr_in6 *)hostmask)->sin6_len = + sizeof (struct in6_addr); + memset (&((struct sockaddr_in6 *)hostmask)->sin6_addr.s6_addr, 0xff, + sizeof (struct in6_addr)); + break; + } + /* Ingress flow --- SA bundles */ while (TAILQ_NEXT (proto, link)) { - error = pf_key_v2_flow (((struct sockaddr_in *)dst)->sin_addr.s_addr, - hostmask, - ((struct sockaddr_in *)src)->sin_addr.s_addr, - hostmask, 0, 0, 0, - proto->spi[1], proto->proto, - ((struct sockaddr_in *)src)->sin_addr.s_addr, - ((struct sockaddr_in *)dst)->sin_addr.s_addr, + error = pf_key_v2_flow (dst, hostmask, src, hostmask, 0, 0, 0, + proto->spi[1], proto->proto, src, dst, 1, 1, 0, 0, 0, 0, 0, 0); if (error) return error; @@ -2141,9 +2328,7 @@ pf_key_v2_disable_sa (struct sa *sa, int incoming) return pf_key_v2_flow (isa->dst_net, isa->dst_mask, isa->src_net, isa->src_mask, isa->tproto, isa->dport, isa->sport, proto->spi[1], proto->proto, - ((struct sockaddr_in *)src)->sin_addr.s_addr, - ((struct sockaddr_in *)dst)->sin_addr.s_addr, - 1, 1, 0, 0, 0, 0, 0, 0); + src, dst, 1, 1, 0, 0, 0, 0, 0, 0); } } @@ -2222,15 +2407,13 @@ pf_key_v2_delete_spi (struct sa *sa, struct proto *proto, int incoming) /* * Setup the ADDRESS extensions. - * - * XXX Addresses have to be thought through. Assumes IPv4. */ if (incoming) sa->transport->vtbl->get_dst (sa->transport, &saddr, &saddrlen); else sa->transport->vtbl->get_src (sa->transport, &saddr, &saddrlen); len = sizeof *addr + PF_KEY_V2_ROUND (saddrlen); - addr = malloc (len); + addr = calloc (1, len); if (!addr) goto cleanup; addr->sadb_address_exttype = SADB_EXT_ADDRESS_SRC; @@ -2241,7 +2424,15 @@ pf_key_v2_delete_spi (struct sa *sa, struct proto *proto, int incoming) #endif addr->sadb_address_reserved = 0; memcpy (addr + 1, saddr, saddrlen); - ((struct sockaddr_in *)(addr + 1))->sin_port = 0; + switch (saddr->sa_family) + { + case AF_INET: + ((struct sockaddr_in *)(addr + 1))->sin_port = 0; + break; + case AF_INET6: + ((struct sockaddr_in6 *)(addr + 1))->sin6_port = 0; + break; + } if (pf_key_v2_msg_add (delete, (struct sadb_ext *)addr, PF_KEY_V2_NODE_MALLOCED) == -1) goto cleanup; @@ -2252,7 +2443,7 @@ pf_key_v2_delete_spi (struct sa *sa, struct proto *proto, int incoming) else sa->transport->vtbl->get_dst (sa->transport, &saddr, &saddrlen); len = sizeof *addr + PF_KEY_V2_ROUND (saddrlen); - addr = malloc (len); + addr = calloc (1, len); if (!addr) goto cleanup; addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST; @@ -2263,7 +2454,15 @@ pf_key_v2_delete_spi (struct sa *sa, struct proto *proto, int incoming) #endif addr->sadb_address_reserved = 0; memcpy (addr + 1, saddr, saddrlen); - ((struct sockaddr_in *)(addr + 1))->sin_port = 0; + switch (saddr->sa_family) + { + case AF_INET: + ((struct sockaddr_in *)(addr + 1))->sin_port = 0; + break; + case AF_INET6: + ((struct sockaddr_in6 *)(addr + 1))->sin6_port = 0; + break; + } if (pf_key_v2_msg_add (delete, (struct sadb_ext *)addr, PF_KEY_V2_NODE_MALLOCED) == -1) goto cleanup; @@ -2345,6 +2544,7 @@ pf_key_v2_expire (struct pf_key_v2_msg *pmsg) struct sadb_lifetime *life, *lifecurrent; struct sa *sa; struct pf_key_v2_node *lifenode, *ext; + char *dst_str; msg = (struct sadb_msg *)TAILQ_FIRST (pmsg)->seg; ext = pf_key_v2_find_ext (pmsg, SADB_EXT_SA); @@ -2380,13 +2580,21 @@ pf_key_v2_expire (struct pf_key_v2_msg *pmsg) } lifecurrent = lifenode->seg; - /* XXX IPv4 specific. */ +#ifdef USE_DEBUG + + if (sockaddr2text (dstaddr, &dst_str, 0)) + dst_str = 0; + LOG_DBG ((LOG_SYSDEP, 20, "pf_key_v2_expire: %s dst %s SPI %x sproto %d", life->sadb_lifetime_exttype == SADB_EXT_LIFETIME_SOFT ? "SOFT" - : "HARD", - inet_ntoa (((struct sockaddr_in *)dstaddr)->sin_addr), + : "HARD", dst_str ? dst_str : "", ntohl (ssa->sadb_sa_spi), msg->sadb_msg_satype)); + if (dst_str) + free (dst_str); + +#endif /* USE_DEBUG */ + /* * Find the IPsec SA. The IPsec stack has two SAs for every IKE SA, * one outgoing and one incoming, we regard expirations for any of @@ -2396,10 +2604,8 @@ pf_key_v2_expire (struct pf_key_v2_msg *pmsg) * of the full suite. * * XXX When anything else than AH and ESP is supported this needs to change. - * XXX IPv4 specific. */ - sa = ipsec_sa_lookup (((struct sockaddr_in *)dstaddr)->sin_addr.s_addr, - ssa->sadb_sa_spi, + sa = ipsec_sa_lookup (dstaddr, ssa->sadb_sa_spi, msg->sadb_msg_satype == SADB_SATYPE_ESP ? IPSEC_PROTO_IPSEC_ESP : IPSEC_PROTO_IPSEC_AH); @@ -3647,15 +3853,13 @@ pf_key_v2_group_spis (struct sa *sa, struct proto *proto1, /* * Setup the ADDRESS extensions. - * - * XXX Addresses have to be thought through. Assumes IPv4. */ if (incoming) sa->transport->vtbl->get_src (sa->transport, &saddr, &saddrlen); else sa->transport->vtbl->get_dst (sa->transport, &saddr, &saddrlen); len = sizeof *addr + PF_KEY_V2_ROUND (saddrlen); - addr = malloc (len); + addr = calloc (1, len); if (!addr) goto cleanup; addr->sadb_address_exttype = SADB_EXT_ADDRESS_DST; @@ -3672,7 +3876,7 @@ pf_key_v2_group_spis (struct sa *sa, struct proto *proto1, goto cleanup; addr = 0; - addr = malloc (len); + addr = calloc (1, len); if (!addr) goto cleanup; addr->sadb_address_exttype = SADB_X_EXT_DST2; diff --git a/sbin/isakmpd/policy.c b/sbin/isakmpd/policy.c index 4645c338011..ef0566eef8d 100644 --- a/sbin/isakmpd/policy.c +++ b/sbin/isakmpd/policy.c @@ -1,9 +1,10 @@ -/* $OpenBSD: policy.c,v 1.32 2001/06/07 04:46:45 angelos Exp $ */ +/* $OpenBSD: policy.c,v 1.33 2001/06/29 04:12:01 ho Exp $ */ /* $EOM: policy.c,v 1.49 2000/10/24 13:33:39 niklas Exp $ */ /* * Copyright (c) 1999, 2000, 2001 Angelos D. Keromytis. All rights reserved. * Copyright (c) 1999, 2000, 2001 Niklas Hallqvist. All rights reserved. + * Copyright (c) 2001 Håkan Olsson. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -165,13 +166,14 @@ policy_callback (char *name) u_int8_t *attr, *value, *id, *idlocal, *idremote; size_t id_sz, idlocalsz, idremotesz; - struct sockaddr_in *sin; + struct sockaddr *sin; struct ipsec_exch *ie; struct ipsec_sa *is; int fmt, i, lifetype = 0; in_addr_t net, subnet; u_int16_t len, type; time_t tt; + char *addr; static char mytimeofday[15]; /* We use all these as a cache. */ @@ -626,16 +628,23 @@ policy_callback (char *name) } } - /* XXX IPv4-specific. */ - policy_sa->transport->vtbl->get_src (policy_sa->transport, - (struct sockaddr **)&sin, &fmt); - my_inet_ntop4 (&(sin->sin_addr.s_addr), local_ike_address, - sizeof local_ike_address - 1, 0); + policy_sa->transport->vtbl->get_src (policy_sa->transport, &sin, &fmt); + if (sockaddr2text (sin, &addr, 1)) + { + log_error ("policy_callback: sockaddr2text failed"); + goto bad; + } + memcpy (local_ike_address, addr, sizeof local_ike_address); + free (addr); - policy_sa->transport->vtbl->get_dst (policy_sa->transport, - (struct sockaddr **)&sin, &fmt); - my_inet_ntop4 (&(sin->sin_addr.s_addr), remote_ike_address, - sizeof remote_ike_address - 1, 0); + policy_sa->transport->vtbl->get_dst (policy_sa->transport, &sin, &fmt); + if (sockaddr2text (sin, &addr, 1)) + { + log_error ("policy_callback: sockaddr2text failed"); + goto bad; + } + memcpy (local_ike_address, addr, sizeof remote_ike_address); + free (addr); switch (policy_isakmp_sa->exch_type) { @@ -1039,15 +1048,31 @@ policy_callback (char *name) } else { - policy_sa->transport->vtbl->get_dst (policy_sa->transport, - (struct sockaddr **) &sin, + policy_sa->transport->vtbl->get_dst (policy_sa->transport, &sin, &fmt); - remote_filter_type = "IPv4 address"; - - my_inet_ntop4 (&(sin->sin_addr.s_addr), remote_filter_addr_upper, - sizeof remote_filter_addr_upper - 1, 0); - my_inet_ntop4 (&(sin->sin_addr.s_addr), remote_filter_addr_lower, - sizeof remote_filter_addr_lower - 1, 0); + switch (sin->sa_family) + { + case AF_INET: + remote_filter_type = "IPv4 address"; + break; + case AF_INET6: + remote_filter_type = "IPv6 address"; + break; + default: + log_print ("policy_callback: unsupported protocol family %d", + sin->sa_family); + goto bad; + } + if (sockaddr2text (sin, &addr, 1)) + { + log_error ("policy_callback: sockaddr2text failed"); + goto bad; + } + memcpy (remote_filter_addr_upper, addr, + sizeof remote_filter_addr_upper); + memcpy (remote_filter_addr_lower, addr, + sizeof remote_filter_addr_lower); + free (addr); remote_filter = strdup (remote_filter_addr_upper); if (!remote_filter) { @@ -1242,13 +1267,30 @@ policy_callback (char *name) policy_sa->transport->vtbl->get_src (policy_sa->transport, (struct sockaddr **)&sin, &fmt); + switch (sin->sa_family) + { + case AF_INET: + local_filter_type = "IPv4 address"; + break; + case AF_INET6: + local_filter_type = "IPv6 address"; + break; + default: + log_print ("policy_callback: unsupported protocol family %d", + sin->sa_family); + goto bad; + } - local_filter_type = "IPv4 address"; - - my_inet_ntop4 (&(sin->sin_addr.s_addr), local_filter_addr_upper, - sizeof local_filter_addr_upper - 1, 0); - my_inet_ntop4 (&(sin->sin_addr.s_addr), local_filter_addr_lower, - sizeof local_filter_addr_lower - 1, 0); + if (sockaddr2text (sin, &addr, 1)) + { + log_error ("policy_callback: sockaddr2text failed"); + goto bad; + } + memcpy (local_filter_addr_upper, addr, + sizeof local_filter_addr_upper); + memcpy (local_filter_addr_lower, addr, + sizeof local_filter_addr_lower); + free (addr); local_filter = strdup (local_filter_addr_upper); if (!local_filter) { @@ -1704,7 +1746,7 @@ int keynote_cert_obtain (u_int8_t *id, size_t id_len, void *data, u_int8_t **cert, u_int32_t *certlen) { - char *dirname, *file; + char *dirname, *file, *addr_str; struct stat sb; int idtype, fd, len; @@ -1732,21 +1774,24 @@ keynote_cert_obtain (u_int8_t *id, size_t id_len, void *data, u_int8_t **cert, switch (idtype) { case IPSEC_ID_IPV4_ADDR: - { - struct in_addr in; + case IPSEC_ID_IPV6_ADDR: + util_ntoa (&addr_str, idtype == IPSEC_ID_IPV4_ADDR ? AF_INET : AF_INET6, + id); + if (addr_str == 0) + return 0; - file = calloc (len + 15, sizeof (char)); - if (file == NULL) - { - log_error ("keynote_cert_obtain: failed to allocate %d bytes", - len + 15); - return 0; - } + file = calloc (len + strlen (addr_str), sizeof (char)); + if (file == NULL) + { + log_error ("keynote_cert_obtain: failed to allocate %d bytes", + len + strlen (addr_str)); + free (addr_str); + return 0; + } - memcpy (&in, id, sizeof in); - sprintf (file, "%s/%s/%s", dirname, inet_ntoa (in), CREDENTIAL_FILE); - break; - } + sprintf (file, "%s/%s/%s", dirname, addr_str, CREDENTIAL_FILE); + free (addr_str); + break; case IPSEC_ID_FQDN: case IPSEC_ID_USER_FQDN: diff --git a/sbin/isakmpd/util.c b/sbin/isakmpd/util.c index e9ebba748e6..3e45942d551 100644 --- a/sbin/isakmpd/util.c +++ b/sbin/isakmpd/util.c @@ -1,4 +1,4 @@ -/* $OpenBSD: util.c,v 1.14 2001/06/27 05:16:49 ho Exp $ */ +/* $OpenBSD: util.c,v 1.15 2001/06/29 04:12:01 ho Exp $ */ /* $EOM: util.c,v 1.23 2000/11/23 12:22:08 niklas Exp $ */ /* @@ -269,10 +269,16 @@ text2sockaddr (char *address, char *port, struct sockaddr **sa) #endif } +/* + * Convert a sockaddr to text. With zflag non-zero fill out with zeroes, + * i.e 10.0.0.10 --> "010.000.000.010" + */ int -sockaddr2text (struct sockaddr *sa, char **address) +sockaddr2text (struct sockaddr *sa, char **address, int zflag) { char buf[NI_MAXHOST]; + char *token, *bstart, *p; + int c_pre = 0, c_post = 0; #ifdef HAVE_GETNAMEINFO if (getnameinfo (sa, sa->sa_len, buf, sizeof buf, 0, 0, @@ -293,10 +299,79 @@ sockaddr2text (struct sockaddr *sa, char **address) } #endif - *address = malloc (strlen (buf) + 1); - if (!address) - return -1; - + if (zflag == 0) + { + *address = malloc (strlen (buf) + 1); + if (*address == NULL) + return -1; + } + else + switch (sa->sa_family) + { + case AF_INET: + *address = malloc (16); + if (*address == NULL) + return -1; + bstart = buf; **address = '\0'; + while ((token = strsep (&bstart, ".")) != NULL) + { + if (strlen (*address) > 12) + { + free (*address); + return -1; + } + sprintf (*address + strlen (*address), "%03ld", + strtol (token, NULL, 10)); + if (bstart) + strcat (*address + strlen (*address), "."); + } + break; + case AF_INET6: + *address = malloc (40); + if (!address) + return -1; + bstart = buf; **address = '\0'; + buf[40] = '\0'; /* Make sure buf is terminated. */ + while ((token = strsep (&bstart, ":")) != NULL) + { + if (strlen (token) == 0) + { + /* Encountered a '::'. Fill out the string. */ + /* XXX Isn't there a library function for this somewhere? */ + for (p = buf; p < token - 1; p++) + if (*p == 0) + c_pre++; + for (p = token + 1; p < (bstart + strlen (bstart)); p++) + if (*p == ':') + c_post++; + /* The number of zero groups to add. */ + c_pre = 7 - c_pre - c_post - 1; + if (c_pre > 6 || strlen (*address) > (40 - 5 * c_pre)) + { + free (*address); + return -1; + } + for (; c_pre; c_pre--) + strcat (*address + strlen (*address), "0000:"); + } + else + { + if (strlen (*address) > 35) + { + free (*address); + return -1; + } + sprintf (*address + strlen (*address), "%04lx", + strtol (token, NULL, 16)); + if (bstart) + strcat (*address + strlen (*address), ":"); + } + } + break; + default: + strcpy (buf, ""); + } + strcpy (*address, buf); return 0; } @@ -334,7 +409,41 @@ sockaddr_data (struct sockaddr *sa) return 0; /* XXX */ } } - + +/* + * Convert network address to text. The network address does not need + * to be properly aligned. + */ +void +util_ntoa (char **buf, int af, u_int8_t *addr) +{ + struct sockaddr_storage from; + struct sockaddr *sfrom = (struct sockaddr *)&from; + socklen_t fromlen = sizeof from; + u_int32_t ip4_buf; + + memset (&from, 0, fromlen); + sfrom->sa_family = af; + switch (af) + { + case AF_INET: + sfrom->sa_len = sizeof (struct sockaddr_in); + memcpy (&ip4_buf, addr, sizeof (struct in_addr)); + ((struct sockaddr_in *)sfrom)->sin_addr.s_addr = htonl (ip4_buf); + break; + case AF_INET6: + sfrom->sa_len = sizeof (struct sockaddr_in6); + memcpy (sockaddr_data (sfrom), addr, sizeof (struct in6_addr)); + break; + } + + if (sockaddr2text (sfrom, buf, 0)) + { + log_error ("util_ntoa: sockaddr2text () failed"); + *buf = 0; + } +} + /* * Perform sanity check on files containing secret information. * Returns -1 on failure, 0 otherwise. @@ -370,4 +479,3 @@ check_file_secrecy (char *name, off_t *file_size) return 0; } - diff --git a/sbin/isakmpd/util.h b/sbin/isakmpd/util.h index 84b25d084f0..8e7e4defbb2 100644 --- a/sbin/isakmpd/util.h +++ b/sbin/isakmpd/util.h @@ -1,8 +1,9 @@ -/* $OpenBSD: util.h,v 1.8 2001/06/27 00:10:35 ho Exp $ */ +/* $OpenBSD: util.h,v 1.9 2001/06/29 04:12:01 ho Exp $ */ /* $EOM: util.h,v 1.10 2000/10/24 13:33:39 niklas Exp $ */ /* * Copyright (c) 1998 Niklas Hallqvist. All rights reserved. + * Copyright (c) 2001 Håkan Olsson. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -60,7 +61,8 @@ extern void encode_128 (u_int8_t *, u_int8_t *); #endif extern u_int8_t *getrandom (u_int8_t *, size_t); extern int hex2raw (char *, u_int8_t *, size_t); -extern int sockaddr2text (struct sockaddr *, char **); +extern int sockaddr2text (struct sockaddr *, char **, int); +extern void util_ntoa (char **, int, u_int8_t *); extern int text2sockaddr (char *, char *, struct sockaddr **); extern int sockaddr_len (struct sockaddr *); extern u_int8_t *sockaddr_data (struct sockaddr *); -- cgit v1.2.3