diff options
author | Hakan Olsson <ho@cvs.openbsd.org> | 2004-08-10 15:59:12 +0000 |
---|---|---|
committer | Hakan Olsson <ho@cvs.openbsd.org> | 2004-08-10 15:59:12 +0000 |
commit | ad93a395f096ca7b9a0833d0906d723b7880e483 (patch) | |
tree | 40283255eb9e94abcc82178a9dbb6c11f09a3932 /sbin | |
parent | e6aea2c186d9eef5275040b69b69d4764a29f5b8 (diff) |
Better implementation of the Dead Peer Detection protocol, RFC 3706.
hshoexer@ ok.
Diffstat (limited to 'sbin')
-rw-r--r-- | sbin/isakmpd/dpd.c | 428 | ||||
-rw-r--r-- | sbin/isakmpd/dpd.h | 14 | ||||
-rw-r--r-- | sbin/isakmpd/exchange.c | 17 | ||||
-rw-r--r-- | sbin/isakmpd/ipsec.c | 40 | ||||
-rw-r--r-- | sbin/isakmpd/isakmp_num.cst | 5 | ||||
-rw-r--r-- | sbin/isakmpd/isakmpd.conf.5 | 8 | ||||
-rw-r--r-- | sbin/isakmpd/message.c | 66 | ||||
-rw-r--r-- | sbin/isakmpd/message.h | 6 | ||||
-rw-r--r-- | sbin/isakmpd/pf_key_v2.c | 201 | ||||
-rw-r--r-- | sbin/isakmpd/pf_key_v2.h | 14 | ||||
-rw-r--r-- | sbin/isakmpd/sa.c | 6 | ||||
-rw-r--r-- | sbin/isakmpd/sa.h | 47 | ||||
-rw-r--r-- | sbin/isakmpd/sysdep.h | 19 | ||||
-rw-r--r-- | sbin/isakmpd/sysdep/bsdi/sysdep.c | 12 | ||||
-rw-r--r-- | sbin/isakmpd/sysdep/darwin/sysdep.c | 12 | ||||
-rw-r--r-- | sbin/isakmpd/sysdep/freebsd/sysdep.c | 12 | ||||
-rw-r--r-- | sbin/isakmpd/sysdep/freeswan/sysdep.c | 12 | ||||
-rw-r--r-- | sbin/isakmpd/sysdep/linux/sysdep.c | 12 | ||||
-rw-r--r-- | sbin/isakmpd/sysdep/netbsd/sysdep.c | 12 | ||||
-rw-r--r-- | sbin/isakmpd/sysdep/openbsd/sysdep.c | 11 | ||||
-rw-r--r-- | sbin/isakmpd/udp_encap.c | 8 |
21 files changed, 677 insertions, 285 deletions
diff --git a/sbin/isakmpd/dpd.c b/sbin/isakmpd/dpd.c index 3bbaf05109d..6eb2ceb97c9 100644 --- a/sbin/isakmpd/dpd.c +++ b/sbin/isakmpd/dpd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dpd.c,v 1.3 2004/08/08 19:11:06 deraadt Exp $ */ +/* $OpenBSD: dpd.c,v 1.4 2004/08/10 15:59:10 ho Exp $ */ /* * Copyright (c) 2004 Håkan Olsson. All rights reserved. @@ -29,14 +29,17 @@ #include "sysdep.h" +#include "conf.h" #include "dpd.h" #include "exchange.h" +#include "hash.h" #include "ipsec.h" #include "isakmp_fld.h" #include "log.h" #include "message.h" #include "sa.h" #include "timer.h" +#include "transport.h" #include "util.h" /* From RFC 3706. */ @@ -51,30 +54,16 @@ static const char dpd_vendor_id[] = { DPD_MINOR }; -int16_t script_dpd[] = { - ISAKMP_PAYLOAD_NOTIFY, /* Initiator -> responder. */ - ISAKMP_PAYLOAD_HASH, - EXCHANGE_SCRIPT_SWITCH, - ISAKMP_PAYLOAD_NOTIFY, /* Responder -> initiator. */ - ISAKMP_PAYLOAD_HASH, - EXCHANGE_SCRIPT_END -}; - -static int dpd_initiator_send_notify(struct message *); -static int dpd_initiator_recv_ack(struct message *); -static int dpd_responder_recv_notify(struct message *); -static int dpd_responder_send_ack(struct message *); -static void dpd_event(void *); +#define DPD_RETRANS_MAX 5 /* max number of retries. */ +#define DPD_RETRANS_WAIT 5 /* seconds between retries. */ -int (*isakmp_dpd_initiator[])(struct message *) = { - dpd_initiator_send_notify, - dpd_initiator_recv_ack -}; +/* DPD Timer State */ +enum dpd_tstate { DPD_TIMER_NORMAL, DPD_TIMER_CHECK }; -int (*isakmp_dpd_responder[])(struct message *) = { - dpd_responder_recv_notify, - dpd_responder_send_ack -}; +static void dpd_check_event(void *); +static void dpd_event(void *); +static u_int32_t dpd_timer_interval(u_int32_t); +static void dpd_timer_reset(struct sa *, u_int32_t, enum dpd_tstate); /* Add the DPD VENDOR ID payload. */ int @@ -127,225 +116,256 @@ dpd_check_vendor_payload(struct message *msg, struct payload *p) if (memcmp(dpd_vendor_id, pbuf + ISAKMP_GEN_SZ, vlen) == 0) { /* This peer is DPD capable. */ - msg->exchange->flags |= EXCHANGE_FLAG_DPD_CAP_PEER; - LOG_DBG((LOG_EXCHANGE, 10, "dpd_check_vendor_payload: " - "DPD capable peer detected")); + if (msg->isakmp_sa) { + msg->exchange->flags |= EXCHANGE_FLAG_DPD_CAP_PEER; + LOG_DBG((LOG_EXCHANGE, 10, "dpd_check_vendor_payload: " + "DPD capable peer detected")); + if (dpd_timer_interval(0) != 0) { + LOG_DBG((LOG_EXCHANGE, 10, + "dpd_check_vendor_payload: enabling")); + msg->isakmp_sa->flags |= SA_FLAG_DPD; + dpd_timer_reset(msg->isakmp_sa, 0, + DPD_TIMER_NORMAL); + } + } p->flags |= PL_MARK; - return; } - return; } -static int -dpd_add_notify(struct message *msg, u_int16_t type, u_int32_t seqno) +/* + * All incoming DPD Notify messages enter here. Message has been validated. + */ +void +dpd_handle_notify(struct message *msg, struct payload *p) { - struct sa *isakmp_sa = msg->isakmp_sa; - char *buf; - u_int32_t buflen; - - if (!isakmp_sa) { - log_print("dpd_add_notify: no isakmp_sa"); - return -1; - } - - buflen = ISAKMP_NOTIFY_SZ + ISAKMP_HDR_COOKIES_LEN + DPD_SEQNO_SZ; - buf = malloc(buflen); - if (!buf) { - log_error("dpd_add_notify: malloc(%d) failed", - ISAKMP_NOTIFY_SZ + DPD_SEQNO_SZ); - return -1; + struct sa *isakmp_sa = msg->isakmp_sa; + u_int16_t notify = GET_ISAKMP_NOTIFY_MSG_TYPE(p->p); + u_int32_t p_seq; + + /* Extract the sequence number. */ + memcpy(&p_seq, p->p + ISAKMP_NOTIFY_SPI_OFF + ISAKMP_HDR_COOKIES_LEN, + sizeof p_seq); + p_seq = ntohl(p_seq); + + LOG_DBG((LOG_MESSAGE, 40, "dpd_handle_notify: got %s seq %u", + constant_name(isakmp_notify_cst, notify), p_seq)); + + switch (notify) { + case ISAKMP_NOTIFY_STATUS_DPD_R_U_THERE: + /* The other peer wants to know we're alive. */ + if (p_seq <= isakmp_sa->dpd_rseq) { + log_print("dpd_handle_notify: bad R_U_THERE seqno " + "%u <= %u", p_seq, isakmp_sa->dpd_rseq); + return; + } + isakmp_sa->dpd_rseq = p_seq; + message_send_dpd_notify(isakmp_sa, + ISAKMP_NOTIFY_STATUS_DPD_R_U_THERE_ACK, p_seq); + break; + + case ISAKMP_NOTIFY_STATUS_DPD_R_U_THERE_ACK: + /* This should be a response to a R_U_THERE we've sent. */ + if (isakmp_sa->dpd_seq != p_seq) { + log_print("dpd_handle_notify: got bad ACK seqno %u, " + "expected %u", p_seq, isakmp_sa->dpd_seq); + /* XXX Give up? Retry? */ + return; + } + break; + default: } - SET_ISAKMP_NOTIFY_DOI(buf, IPSEC_DOI_IPSEC); - SET_ISAKMP_NOTIFY_PROTO(buf, ISAKMP_PROTO_ISAKMP); - SET_ISAKMP_NOTIFY_SPI_SZ(buf, ISAKMP_HDR_COOKIES_LEN); - SET_ISAKMP_NOTIFY_MSG_TYPE(buf, type); - memcpy(buf + ISAKMP_NOTIFY_SPI_OFF, isakmp_sa->cookies, - ISAKMP_HDR_COOKIES_LEN); - - memcpy(buf + ISAKMP_NOTIFY_SPI_OFF + ISAKMP_HDR_COOKIES_LEN, &seqno, - sizeof (u_int32_t)); - - if (message_add_payload(msg, ISAKMP_PAYLOAD_NOTIFY, buf, buflen, 1)) { - free(buf); - return -1; - } + /* Mark handled. */ + p->flags |= PL_MARK; - return 0; + /* The other peer is alive, so we can safely wait a while longer. */ + if (isakmp_sa->flags & SA_FLAG_DPD) + dpd_timer_reset(isakmp_sa, 0, DPD_TIMER_NORMAL); } -static int -dpd_initiator_send_notify(struct message *msg) +/* Calculate the time until next DPD exchange. */ +static u_int32_t +dpd_timer_interval(u_int32_t offset) { - if (!msg->isakmp_sa) { - log_print("dpd_initiator_send_notify: no isakmp_sa"); - return -1; - } - - if (msg->isakmp_sa->dpd_seq == 0) { - /* RFC 3706: first seq# should be random, with MSB zero. */ - getrandom((u_int8_t *)&msg->isakmp_sa->seq, - sizeof msg->isakmp_sa->seq); - msg->isakmp_sa->dpd_seq &= 0x7FFF; - } else - msg->isakmp_sa->dpd_seq++; - - return dpd_add_notify(msg, ISAKMP_NOTIFY_STATUS_DPD_R_U_THERE, - msg->isakmp_sa->dpd_seq); + int32_t v = 0; + +#ifdef notyet + v = ...; /* XXX Per-peer specified DPD intervals? */ +#endif + if (!v) + v = conf_get_num("General", "DPD-check-interval", 0); + if (v < 1) + return 0; /* DPD-Check-Interval < 1 means disable DPD */ + + v -= offset; + return v < 1 ? 1 : v; } -static int -dpd_initiator_recv_ack(struct message *msg) +static void +dpd_timer_reset(struct sa *sa, u_int32_t time_passed, enum dpd_tstate mode) { - struct payload *p = payload_first(msg, ISAKMP_PAYLOAD_NOTIFY); - struct sa *isakmp_sa = msg->isakmp_sa; - struct timeval tv; - u_int32_t rseq; + struct timeval tv; - if (msg->exchange->phase != 2) { - message_drop(msg, ISAKMP_NOTIFY_INVALID_EXCHANGE_TYPE, 0, 1, - 0); - return -1; - } - - if (GET_ISAKMP_NOTIFY_MSG_TYPE(p->p) - != ISAKMP_NOTIFY_STATUS_DPD_R_U_THERE_ACK) { - message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0); - return -1; - } - - /* Presumably, we've been through message_validate_notify(). */ + if (sa->dpd_event) + timer_remove_event(sa->dpd_event); - /* Validate the SPI. Perhaps move to message_validate_notify(). */ - if (memcmp(p->p + ISAKMP_NOTIFY_SPI_OFF, isakmp_sa->cookies, - ISAKMP_HDR_COOKIES_LEN) != 0) { - log_print("dpd_initiator_recv_ack: bad cookies"); - message_drop(msg, ISAKMP_NOTIFY_INVALID_SPI, 0, 1, 0); - return -1; - } - - /* Check the seqno. */ - memcpy(p->p + ISAKMP_NOTIFY_SPI_OFF + ISAKMP_HDR_COOKIES_LEN, &rseq, - sizeof rseq); - rseq = ntohl(rseq); - - if (isakmp_sa->seq != rseq) { - log_print("dpd_initiator_recv_ack: bad seqno %u, expected %u", - rseq, isakmp_sa->seq); - message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0); - return -1; - } - - /* Peer is alive. Reset timer. */ gettimeofday(&tv, 0); - tv.tv_sec += DPD_DEFAULT_WORRY_METRIC; /* XXX Configurable */ - - isakmp_sa->dpd_nextev = timer_add_event("dpd_event", dpd_event, - isakmp_sa, &tv); - if (!isakmp_sa->dpd_nextev) - log_print("dpd_initiator_recv_ack: timer_add_event " - "failed"); - else - sa_reference(isakmp_sa); - - /* Mark handled. */ - p->flags |= PL_MARK; - - return 0; + switch (mode) { + case DPD_TIMER_NORMAL: + tv.tv_sec += dpd_timer_interval(time_passed); + sa->dpd_event = timer_add_event("dpd_event", dpd_event, sa, + &tv); + break; + case DPD_TIMER_CHECK: + tv.tv_sec += DPD_RETRANS_WAIT; + sa->dpd_event = timer_add_event("dpd_check_event", + dpd_check_event, sa, &tv); + break; + default: + } + if (!sa->dpd_event) + log_print("dpd_timer_reset: timer_add_event failed"); } +/* Helper function for dpd_exchange_finalization(). */ static int -dpd_responder_recv_notify(struct message *msg) +dpd_find_sa(struct sa *sa, void *v_sa) { - struct payload *p = payload_first(msg, ISAKMP_PAYLOAD_NOTIFY); - struct sa *isakmp_sa = msg->isakmp_sa; - struct timeval tv; - u_int32_t rseq; + struct sa *isakmp_sa = v_sa; - if (msg->exchange->phase != 2) { - message_drop(msg, ISAKMP_NOTIFY_INVALID_EXCHANGE_TYPE, 0, 1, - 0); - return -1; - } + return (sa->phase == 2 && + memcmp(sa->id_i, isakmp_sa->id_i, sa->id_i_len) == 0 && + memcmp(sa->id_r, isakmp_sa->id_r, sa->id_r_len) == 0); +} - if (GET_ISAKMP_NOTIFY_MSG_TYPE(p->p) != - ISAKMP_NOTIFY_STATUS_DPD_R_U_THERE) { - message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0); - return -1; - } +struct dpd_args { + struct sa *isakmp_sa; + u_int32_t interval; +}; - /* Presumably, we've gone through message_validate_notify(). */ - /* XXX */ +/* Helper function for dpd_event(). */ +static int +dpd_check_time(struct sa *sa, void *v_arg) +{ + struct dpd_args *args = v_arg; + struct sockaddr *dst; + struct proto *proto; + struct sa_kinfo *ksa; + struct timeval tv; - /* Validate the SPI. Perhaps move to message_validate_notify(). */ - if (memcmp(p->p + ISAKMP_NOTIFY_SPI_OFF, isakmp_sa->cookies, - ISAKMP_HDR_COOKIES_LEN) != 0) { - log_print("dpd_initiator_recv_notify: bad cookies"); - message_drop(msg, ISAKMP_NOTIFY_INVALID_SPI, 0, 1, 0); - return -1; - } + if (sa->phase == 1 || (args->isakmp_sa->flags & SA_FLAG_DPD) == 0 || + dpd_find_sa(sa, args->isakmp_sa) == 0) + return 0; - /* Get the seqno. */ - memcpy(p->p + ISAKMP_NOTIFY_SPI_OFF + ISAKMP_HDR_COOKIES_LEN, &rseq, - sizeof rseq); - rseq = ntohl(rseq); + proto = TAILQ_FIRST(&sa->protos); + if (!proto || !proto->data) + return 0; + sa->transport->vtbl->get_src(sa->transport, &dst); - /* Check increasing seqno. */ - if (rseq <= isakmp_sa->dpd_rseq) { - log_print("dpd_initiator_recv_notify: bad seqno (%u <= %u)", - rseq, isakmp_sa->dpd_rseq); - message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0); - return -1; - } - isakmp_sa->dpd_rseq = rseq; + gettimeofday(&tv, 0); + ksa = sysdep_ipsec_get_kernel_sa(proto->spi[1], proto->spi_sz[1], + proto->proto, dst); - /* - * Ok, now we know the peer is alive, in case we're wondering. - * If so, reset timers, etc... here. - */ - if (isakmp_sa->dpd_nextev) { - timer_remove_event(isakmp_sa->dpd_nextev); - sa_release(isakmp_sa); - - gettimeofday(&tv, 0); - tv.tv_sec += DPD_DEFAULT_WORRY_METRIC; /* XXX Configurable */ - - isakmp_sa->dpd_nextev = timer_add_event("dpd_event", dpd_event, - isakmp_sa, &tv); - if (!isakmp_sa->dpd_nextev) - log_print("dpd_responder_recv_notify: timer_add_event " - "failed"); - else - sa_reference(isakmp_sa); - } + if (!ksa || !ksa->last_used) + return 0; - /* Mark handled. */ - p->flags |= PL_MARK; + LOG_DBG((LOG_MESSAGE, 80, "dpd_check_time: " + "SA %p last use %u second(s) ago", sa, + (u_int32_t)(tv.tv_sec - ksa->last_used))); + if ((u_int32_t)(tv.tv_sec - ksa->last_used) < args->interval) { + args->interval = (u_int32_t)(tv.tv_sec - ksa->last_used); + return 1; + } + return 0; } - -static int -dpd_responder_send_ack(struct message *msg) + +/* Called by the timer. */ +static void +dpd_event(void *v_sa) { - if (!msg->isakmp_sa) - return -1; + struct sa *isakmp_sa = v_sa; + struct dpd_args args; +#if defined (USE_DEBUG) + struct sockaddr *dst; + char *addr; +#endif + + isakmp_sa->dpd_event = 0; + + /* Check if there's been any incoming SA activity since last time. */ + args.isakmp_sa = isakmp_sa; + args.interval = dpd_timer_interval(0); + if (sa_find(dpd_check_time, &args)) { + if (args.interval > dpd_timer_interval(0)) + args.interval = 0; + dpd_timer_reset(isakmp_sa, args.interval, DPD_TIMER_NORMAL); + return; + } - return dpd_add_notify(msg, ISAKMP_NOTIFY_STATUS_DPD_R_U_THERE_ACK, - msg->isakmp_sa->dpd_rseq); + /* No activity seen, do a DPD exchange. */ + if (isakmp_sa->dpd_seq == 0) { + /* + * RFC 3706: first seq# should be random, with MSB zero, + * otherwise we just increment it. + */ + getrandom((u_int8_t *)&isakmp_sa->dpd_seq, + sizeof isakmp_sa->dpd_seq); + isakmp_sa->dpd_seq &= 0x7FFF; + } else + isakmp_sa->dpd_seq++; + +#if defined (USE_DEBUG) + isakmp_sa->transport->vtbl->get_dst(isakmp_sa->transport, &dst); + if (sockaddr2text(dst, &addr, 0) == -1) + addr = 0; + LOG_DBG((LOG_MESSAGE, 30, "dpd_event: sending R_U_THERE to %s seq %u", + addr ? addr : "<unknown>", isakmp_sa->dpd_seq)); + if (addr) + free(addr); +#endif + message_send_dpd_notify(isakmp_sa, ISAKMP_NOTIFY_STATUS_DPD_R_U_THERE, + isakmp_sa->dpd_seq); + + /* And set the short timer. */ + dpd_timer_reset(isakmp_sa, 0, DPD_TIMER_CHECK); } +/* + * Called by the timer. If this function is called, it means we did not + * recieve any R_U_THERE_ACK confirmation from the other peer. + */ static void -dpd_event(void *v_sa) +dpd_check_event(void *v_sa) { - struct sa *sa = v_sa; - - sa->dpd_nextev = 0; - sa_release(sa); - - if ((sa->flags & SA_FLAG_DPD) == 0) + struct sa *isakmp_sa = v_sa; + struct sa *sa; + + isakmp_sa->dpd_event = 0; + + if (++isakmp_sa->dpd_failcount < DPD_RETRANS_MAX) { + LOG_DBG((LOG_MESSAGE, 10, "dpd_check_event: " + "peer not responding, retry %u of %u", + isakmp_sa->dpd_failcount, DPD_RETRANS_MAX)); + message_send_dpd_notify(isakmp_sa, + ISAKMP_NOTIFY_STATUS_DPD_R_U_THERE, isakmp_sa->dpd_seq); + dpd_timer_reset(isakmp_sa, 0, DPD_TIMER_CHECK); return; - - /* Create a new DPD exchange. XXX */ + } + + /* + * Peer is considered dead. Delete all SAs created under isakmp_sa. + */ + LOG_DBG((LOG_MESSAGE, 10, "dpd_check_event: peer is dead, " + "deleting all SAs connected to SA %p", isakmp_sa)); + while ((sa = sa_find(dpd_find_sa, isakmp_sa)) != 0) { + LOG_DBG((LOG_MESSAGE, 30, "dpd_check_event: deleting SA %p", + sa)); + sa_delete(sa, 0); + } + LOG_DBG((LOG_MESSAGE, 30, "dpd_check_event: deleting ISAKMP SA %p", + isakmp_sa)); + sa_delete(isakmp_sa, 0); } diff --git a/sbin/isakmpd/dpd.h b/sbin/isakmpd/dpd.h index 6b6f1210deb..fa62c5b08b7 100644 --- a/sbin/isakmpd/dpd.h +++ b/sbin/isakmpd/dpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: dpd.h,v 1.1 2004/06/20 15:20:06 ho Exp $ */ +/* $OpenBSD: dpd.h,v 1.2 2004/08/10 15:59:10 ho Exp $ */ /* * Copyright (c) 2004 Håkan Olsson. All rights reserved. @@ -27,16 +27,12 @@ #ifndef _DPD_H_ #define _DPD_H_ -#define DPD_DEFAULT_WORRY_METRIC 300 /* seconds */ - struct message; struct payload; +struct sa; -int dpd_add_vendor_payload(struct message *); -void dpd_check_vendor_payload(struct message *, struct payload *); - -extern int (*isakmp_dpd_initiator[])(struct message *); -extern int (*isakmp_dpd_responder[])(struct message *); -extern int16_t script_dpd[]; +int dpd_add_vendor_payload(struct message *); +void dpd_check_vendor_payload(struct message *, struct payload *); +void dpd_handle_notify(struct message *, struct payload *); #endif /* _DPD_H_ */ diff --git a/sbin/isakmpd/exchange.c b/sbin/isakmpd/exchange.c index 2d2073c52bf..2deec9cc793 100644 --- a/sbin/isakmpd/exchange.c +++ b/sbin/isakmpd/exchange.c @@ -1,4 +1,4 @@ -/* $OpenBSD: exchange.c,v 1.101 2004/08/08 19:11:06 deraadt Exp $ */ +/* $OpenBSD: exchange.c,v 1.102 2004/08/10 15:59:10 ho Exp $ */ /* $EOM: exchange.c,v 1.143 2000/12/04 00:02:25 angelos Exp $ */ /* @@ -47,9 +47,6 @@ #include "cookie.h" #include "crypto.h" #include "doi.h" -#ifdef USE_DPD -#include "dpd.h" -#endif #include "exchange.h" #include "ipsec_num.h" #include "isakmp.h" @@ -190,10 +187,6 @@ exchange_script(struct exchange *exchange) case ISAKMP_EXCH_TRANSACTION: return script_transaction; #endif -#ifdef USE_DPD - case ISAKMP_EXCH_DPD: - return script_dpd; -#endif default: if (exchange->type >= ISAKMP_EXCH_DOI_MIN && exchange->type <= ISAKMP_EXCH_DOI_MAX) @@ -854,10 +847,9 @@ exchange_establish_p1(struct transport *t, u_int8_t type, u_int32_t doi, } msg->exchange = exchange; - /* Do not create SA for an information, transaction or DPD exchange. */ + /* Do not create SA for an information or transaction exchange. */ if (exchange->type != ISAKMP_EXCH_INFO - && exchange->type != ISAKMP_EXCH_TRANSACTION - && exchange->type != ISAKMP_EXCH_DPD) { + && exchange->type != ISAKMP_EXCH_TRANSACTION) { /* * Don't install a transport into this SA as it will be an * INADDR_ANY address in the local end, which is not good at @@ -970,8 +962,7 @@ exchange_establish_p2(struct sa *isakmp_sa, u_int8_t type, char *name, * XXX How to handle new group mode? */ if (exchange->type != ISAKMP_EXCH_INFO && - exchange->type != ISAKMP_EXCH_TRANSACTION && - exchange->type != ISAKMP_EXCH_DPD) { + exchange->type != ISAKMP_EXCH_TRANSACTION) { /* XXX Number of SAs should come from the args structure. */ for (i = 0; i < 1; i++) if (sa_create(exchange, isakmp_sa->transport)) { diff --git a/sbin/isakmpd/ipsec.c b/sbin/isakmpd/ipsec.c index a1537912a7b..8a80719e3bd 100644 --- a/sbin/isakmpd/ipsec.c +++ b/sbin/isakmpd/ipsec.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ipsec.c,v 1.102 2004/08/08 19:11:06 deraadt Exp $ */ +/* $OpenBSD: ipsec.c,v 1.103 2004/08/10 15:59:10 ho Exp $ */ /* $EOM: ipsec.c,v 1.143 2000/12/11 23:57:42 niklas Exp $ */ /* @@ -47,6 +47,9 @@ #include "crypto.h" #include "dh.h" #include "doi.h" +#if defined (USE_DPD) +#include "dpd.h" +#endif #include "exchange.h" #include "hash.h" #include "ike_aggressive.h" @@ -928,11 +931,13 @@ ipsec_initiator(struct message *msg) /* Check that the SA is coherent with the IKE rules. */ if (exchange->type != ISAKMP_EXCH_TRANSACTION - && ((exchange->phase == 1 && exchange->type != ISAKMP_EXCH_ID_PROT - && exchange->type != ISAKMP_EXCH_AGGRESSIVE - && exchange->type != ISAKMP_EXCH_INFO) - || (exchange->phase == 2 && exchange->type != IKE_EXCH_QUICK_MODE - && exchange->type != ISAKMP_EXCH_INFO))) { + && ((exchange->phase == 1 && + exchange->type != ISAKMP_EXCH_ID_PROT && + exchange->type != ISAKMP_EXCH_AGGRESSIVE && + exchange->type != ISAKMP_EXCH_INFO) + || (exchange->phase == 2 && + exchange->type != IKE_EXCH_QUICK_MODE && + exchange->type != ISAKMP_EXCH_INFO))) { log_print("ipsec_initiator: unsupported exchange type %d " "in phase %d", exchange->type, exchange->phase); return -1; @@ -1023,11 +1028,13 @@ ipsec_responder(struct message *msg) /* Check that a new exchange is coherent with the IKE rules. */ if (exchange->step == 0 && exchange->type != ISAKMP_EXCH_TRANSACTION - && ((exchange->phase == 1 && exchange->type != ISAKMP_EXCH_ID_PROT - && exchange->type != ISAKMP_EXCH_AGGRESSIVE - && exchange->type != ISAKMP_EXCH_INFO) - || (exchange->phase == 2 && exchange->type == - ISAKMP_EXCH_ID_PROT))) { + && ((exchange->phase == 1 && + exchange->type != ISAKMP_EXCH_ID_PROT && + exchange->type != ISAKMP_EXCH_AGGRESSIVE && + exchange->type != ISAKMP_EXCH_INFO) + || (exchange->phase == 2 && + exchange->type != IKE_EXCH_QUICK_MODE && + exchange->type != ISAKMP_EXCH_INFO))) { message_drop(msg, ISAKMP_NOTIFY_UNSUPPORTED_EXCHANGE_TYPE, 0, 1, 0); return -1; @@ -1038,19 +1045,16 @@ ipsec_responder(struct message *msg) case ISAKMP_EXCH_ID_PROT: script = ike_main_mode_responder; break; - #ifdef USE_AGGRESSIVE case ISAKMP_EXCH_AGGRESSIVE: script = ike_aggressive_responder; break; #endif - #ifdef USE_ISAKMP_CFG case ISAKMP_EXCH_TRANSACTION: script = isakmp_cfg_responder; break; #endif - case ISAKMP_EXCH_INFO: for (p = payload_first(msg, ISAKMP_PAYLOAD_NOTIFY); p; p = TAILQ_NEXT(p, link)) { @@ -1064,6 +1068,13 @@ ipsec_responder(struct message *msg) /* Handled by leftover logic. */ break; +#if defined (USE_DPD) + case ISAKMP_NOTIFY_STATUS_DPD_R_U_THERE: + case ISAKMP_NOTIFY_STATUS_DPD_R_U_THERE_ACK: + dpd_handle_notify(msg, p); + break; +#endif + default: p->flags |= PL_MARK; break; @@ -1074,7 +1085,6 @@ ipsec_responder(struct message *msg) * If any DELETEs are in here, let the logic of leftover * payloads deal with them. */ - return 0; case IKE_EXCH_QUICK_MODE: diff --git a/sbin/isakmpd/isakmp_num.cst b/sbin/isakmpd/isakmp_num.cst index 24d994abbfa..45d3963bc90 100644 --- a/sbin/isakmpd/isakmp_num.cst +++ b/sbin/isakmpd/isakmp_num.cst @@ -1,4 +1,4 @@ -# $OpenBSD: isakmp_num.cst,v 1.9 2004/06/20 15:20:07 ho Exp $ +# $OpenBSD: isakmp_num.cst,v 1.10 2004/08/10 15:59:10 ho Exp $ # $EOM: isakmp_num.cst,v 1.3 2000/05/17 03:09:50 angelos Exp $ # @@ -78,8 +78,7 @@ ISAKMP_EXCH INFO 5 # XXX the following are not quite legitimate according to the IETF process TRANSACTION 6 - DPD 7 - FUTURE_MIN 8 + FUTURE_MIN 7 FUTURE_MAX 31 DOI_MIN 32 DOI_MAX 255 diff --git a/sbin/isakmpd/isakmpd.conf.5 b/sbin/isakmpd/isakmpd.conf.5 index c1020578876..db3dd7869df 100644 --- a/sbin/isakmpd/isakmpd.conf.5 +++ b/sbin/isakmpd/isakmpd.conf.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: isakmpd.conf.5,v 1.93 2004/07/08 10:37:12 jmc Exp $ +.\" $OpenBSD: isakmpd.conf.5,v 1.94 2004/08/10 15:59:10 ho Exp $ .\" $EOM: isakmpd.conf.5,v 1.57 2000/12/21 14:43:17 ho Exp $ .\" .\" Copyright (c) 1998, 1999, 2000 Niklas Hallqvist. All rights reserved. @@ -170,7 +170,11 @@ Thus .Nm isakmpd only takes care of the SA establishment. .It Em Check-interval -The interval between watchdog checks of connections we want up at all times. +The interval between watchdog checks of connections we want up at all +times. +.It Em DPD-check-interval +The interval between RFC 3706 (Dead Peer Detection) messages. +The default value is 0 (zero), which means DPD is disabled. .It Em Exchange-max-time How many seconds should an exchange maximally take to set up before we give up. diff --git a/sbin/isakmpd/message.c b/sbin/isakmpd/message.c index 313f2379a2e..4b99e400004 100644 --- a/sbin/isakmpd/message.c +++ b/sbin/isakmpd/message.c @@ -1,4 +1,4 @@ -/* $OpenBSD: message.c,v 1.86 2004/08/08 19:11:06 deraadt Exp $ */ +/* $OpenBSD: message.c,v 1.87 2004/08/10 15:59:10 ho Exp $ */ /* $EOM: message.c,v 1.156 2000/10/10 12:36:39 provos Exp $ */ /* @@ -888,7 +888,16 @@ message_validate_notify(struct message *msg, struct payload *p) message_free(msg); return -1; } - /* XXX Validate the SPI. */ + + /* Validate the SPI. XXX Just ISAKMP for now. */ + if (proto == ISAKMP_PROTO_ISAKMP && + GET_ISAKMP_NOTIFY_SPI_SZ(p->p) == ISAKMP_HDR_COOKIES_LEN && + memcmp(p->p + ISAKMP_NOTIFY_SPI_OFF, msg->isakmp_sa->cookies, + ISAKMP_HDR_COOKIES_LEN) != 0) { + log_print("message_validate_notify: bad cookies"); + message_drop(msg, ISAKMP_NOTIFY_INVALID_SPI, 0, 1, 0); + return -1; + } if (type < ISAKMP_NOTIFY_INVALID_PAYLOAD_TYPE || (type >= ISAKMP_NOTIFY_RESERVED_MIN @@ -904,6 +913,7 @@ message_validate_notify(struct message *msg, struct payload *p) message_free(msg); return -1; } + return 0; } @@ -1521,6 +1531,8 @@ message_send(struct message *msg) && exchange->flags & EXCHANGE_FLAG_ENCRYPT) { if (!exchange->keystate) { exchange->keystate = exchange->doi->get_keystate(msg); + if (!exchange->keystate) + return; exchange->crypto = exchange->keystate->xf; exchange->flags |= EXCHANGE_FLAG_ENCRYPT; } @@ -1647,6 +1659,13 @@ struct info_args { u_int16_t nspis; u_int8_t *spis; } d; +#if defined (USE_DPD) + struct { + u_int16_t msg_type; + u_int8_t *spi; + u_int32_t seq; + } dpd; +#endif } u; }; @@ -1714,12 +1733,30 @@ message_send_delete(struct sa *sa) } } +#if defined (USE_DPD) +void +message_send_dpd_notify(struct sa* isakmp_sa, u_int16_t notify, u_int32_t seq) +{ + struct info_args args; + + args.discr = 'P'; + args.doi = IPSEC_DOI_IPSEC; + args.proto = ISAKMP_PROTO_ISAKMP; + args.spi_sz = ISAKMP_HDR_COOKIES_LEN; + args.u.dpd.msg_type = notify; + args.u.dpd.spi = isakmp_sa->cookies; + args.u.dpd.seq = htonl(seq); + + exchange_establish_p2(isakmp_sa, ISAKMP_EXCH_INFO, 0, &args, 0, 0); +} +#endif + /* Build the informational message into MSG. */ int message_send_info(struct message *msg) { u_int8_t *buf; - size_t sz; + size_t sz = 0; struct info_args *args = msg->extra; u_int8_t payload; @@ -1728,8 +1765,21 @@ message_send_info(struct message *msg) if (msg->exchange->doi->informational_pre_hook(msg)) return -1; - sz = (args->discr == 'N' ? ISAKMP_NOTIFY_SPI_OFF + args->spi_sz - : ISAKMP_DELETE_SPI_OFF + args->u.d.nspis * args->spi_sz); + switch (args->discr) { +#if defined (USE_DPD) + case 'P': + sz = sizeof args->u.dpd.seq; + /* FALLTHROUGH */ +#endif + case 'N': + sz += ISAKMP_NOTIFY_SPI_OFF + args->spi_sz; + break; + case 'D': + default: /* Silence gcc */ + sz = ISAKMP_DELETE_SPI_OFF + args->u.d.nspis * args->spi_sz; + break; + } + buf = calloc(1, sz); if (!buf) { log_error("message_send_info: calloc (1, %lu) failed", @@ -1738,6 +1788,12 @@ message_send_info(struct message *msg) return -1; } switch (args->discr) { +#if defined (USE_DPD) + case 'P': + memcpy(buf + ISAKMP_NOTIFY_SPI_OFF + args->spi_sz, + &args->u.dpd.seq, sizeof args->u.dpd.seq); + /* FALLTHROUGH */ +#endif case 'N': /* Build the NOTIFY payload. */ payload = ISAKMP_PAYLOAD_NOTIFY; diff --git a/sbin/isakmpd/message.h b/sbin/isakmpd/message.h index 63d05d9f7d3..14b1d9a9977 100644 --- a/sbin/isakmpd/message.h +++ b/sbin/isakmpd/message.h @@ -1,4 +1,4 @@ -/* $OpenBSD: message.h,v 1.21 2004/06/20 17:17:35 ho Exp $ */ +/* $OpenBSD: message.h,v 1.22 2004/08/10 15:59:10 ho Exp $ */ /* $EOM: message.h,v 1.51 2000/10/10 12:36:39 provos Exp $ */ /* @@ -198,4 +198,8 @@ extern void message_setup_header(struct message *, u_int8_t, u_int8_t, struct payload *payload_first(struct message *, u_int8_t); struct payload *payload_last(struct message *, u_int8_t); +#if defined (USE_DPD) +extern void message_send_dpd_notify(struct sa*, u_int16_t, u_int32_t); +#endif + #endif /* _MESSAGE_H_ */ diff --git a/sbin/isakmpd/pf_key_v2.c b/sbin/isakmpd/pf_key_v2.c index e89ba626eb7..41637f51cf4 100644 --- a/sbin/isakmpd/pf_key_v2.c +++ b/sbin/isakmpd/pf_key_v2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf_key_v2.c,v 1.147 2004/08/08 19:11:06 deraadt Exp $ */ +/* $OpenBSD: pf_key_v2.c,v 1.148 2004/08/10 15:59:10 ho Exp $ */ /* $EOM: pf_key_v2.c,v 1.79 2000/12/12 00:33:19 niklas Exp $ */ /* @@ -680,7 +680,7 @@ pf_key_v2_get_spi(size_t *sz, u_int8_t proto, struct sockaddr *src, break; } if (pf_key_v2_msg_add(getspi, (struct sadb_ext *) addr, - PF_KEY_V2_NODE_MALLOCED) == -1) + PF_KEY_V2_NODE_MALLOCED) == -1) goto cleanup; addr = 0; @@ -777,6 +777,203 @@ cleanup: return 0; } +/* Fetch SA information from the kernel. XXX OpenBSD only? */ +struct sa_kinfo * +pf_key_v2_get_kernel_sa(u_int8_t *spi, size_t spi_sz, u_int8_t proto, + struct sockaddr *dst) +{ + struct sadb_msg msg; + struct sadb_sa *ssa; + struct sadb_address *addr = 0; + struct sockaddr *sa; + struct sadb_lifetime *life; + struct pf_key_v2_msg *gettdb = 0, *ret = 0; + struct pf_key_v2_node *ext; + static struct sa_kinfo ksa; +#if defined (SADB_X_EXT_UDPENCAP) + struct sadb_x_udpencap *udpencap; +#endif + int len, err; + + if (spi_sz != sizeof (ssa->sadb_sa_spi)) + return 0; + + msg.sadb_msg_type = SADB_GET; + switch (proto) { + case IPSEC_PROTO_IPSEC_ESP: + msg.sadb_msg_satype = SADB_SATYPE_ESP; + break; + case IPSEC_PROTO_IPSEC_AH: + msg.sadb_msg_satype = SADB_SATYPE_AH; + break; +#ifdef SADB_X_SATYPE_IPCOMP + case IPSEC_PROTO_IPCOMP: + msg.sadb_msg_satype = SADB_X_SATYPE_IPCOMP; + break; +#endif + default: + log_print("pf_key_v2_get_kernel_sa: invalid proto %d", proto); + goto cleanup; + } + + gettdb = pf_key_v2_msg_new(&msg, 0); + if (!gettdb) + goto cleanup; + + /* SPI */ + ssa = (struct sadb_sa *)calloc(1, sizeof *ssa); + if (!ssa) { + log_print("pf_key_v2_get_kernel_sa: calloc(1, %lu) failed", + (unsigned long)sizeof *ssa); + goto cleanup; + } + + ssa->sadb_sa_exttype = SADB_EXT_SA; + ssa->sadb_sa_len = sizeof *ssa / PF_KEY_V2_CHUNK; + memcpy(&ssa->sadb_sa_spi, spi, sizeof ssa->sadb_sa_spi); + ssa->sadb_sa_state = SADB_SASTATE_MATURE; + if (pf_key_v2_msg_add(gettdb, (struct sadb_ext *)ssa, + PF_KEY_V2_NODE_MALLOCED) == -1) + goto cleanup; + ssa = 0; + + /* XXX KAME SADB_X_EXT_xyz here? */ + + /* Address */ + len = + sizeof(struct sadb_address) + PF_KEY_V2_ROUND(sysdep_sa_len(dst)); + 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; +#ifndef __OpenBSD__ + addr->sadb_address_proto = 0; + addr->sadb_address_prefixlen = 0; +#endif + addr->sadb_address_reserved = 0; + memcpy(addr + 1, dst, sysdep_sa_len(dst)); + 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(gettdb, (struct sadb_ext *)addr, + PF_KEY_V2_NODE_MALLOCED) == -1) + goto cleanup; + addr = 0; + + ret = pf_key_v2_call(gettdb); + pf_key_v2_msg_free(gettdb); + gettdb = 0; + if (!ret) + goto cleanup; + err = ((struct sadb_msg *)TAILQ_FIRST(ret)->seg)->sadb_msg_errno; + if (err) { + log_print("pf_key_v2_get_kernel_sa: SADB_GET: %s", + strerror(err)); + goto cleanup; + } + + /* Extract the data. */ + memset(&ksa, 0, sizeof ksa); + + ext = pf_key_v2_find_ext(ret, SADB_EXT_SA); + if (!ext) + goto cleanup; + + ssa = (struct sadb_sa *)ext; + ksa.spi = ssa->sadb_sa_spi; + ksa.wnd = ssa->sadb_sa_replay; + ksa.flags = ssa->sadb_sa_flags; + + ext = pf_key_v2_find_ext(ret, SADB_EXT_LIFETIME_CURRENT); + if (ext) { + life = (struct sadb_lifetime *)ext->seg; + ksa.cur_allocations = life->sadb_lifetime_allocations; + ksa.cur_bytes = life->sadb_lifetime_bytes; + ksa.first_use = life->sadb_lifetime_usetime; + ksa.established = life->sadb_lifetime_addtime; + } + + ext = pf_key_v2_find_ext(ret, SADB_EXT_LIFETIME_SOFT); + if (ext) { + life = (struct sadb_lifetime *)ext->seg; + ksa.soft_allocations = life->sadb_lifetime_allocations; + ksa.soft_bytes = life->sadb_lifetime_bytes; + ksa.soft_timeout = life->sadb_lifetime_addtime; + ksa.soft_first_use = life->sadb_lifetime_usetime; + } + + ext = pf_key_v2_find_ext(ret, SADB_EXT_LIFETIME_HARD); + if (ext) { + life = (struct sadb_lifetime *)ext->seg; + ksa.exp_allocations = life->sadb_lifetime_allocations; + ksa.exp_bytes = life->sadb_lifetime_bytes; + ksa.exp_timeout = life->sadb_lifetime_addtime; + ksa.exp_first_use = life->sadb_lifetime_usetime; + } + +#if defined (SADB_X_EXT_LIFETIME_LASTUSE) + ext = pf_key_v2_find_ext(ret, SADB_X_EXT_LIFETIME_LASTUSE); + if (ext) { + life = (struct sadb_lifetime *)ext->seg; + ksa.last_used = life->sadb_lifetime_usetime; + } +#endif + + ext = pf_key_v2_find_ext(ret, SADB_EXT_ADDRESS_SRC); + if (ext) { + sa = (struct sockaddr *)ext->seg; + memcpy(&ksa.src, sa, + sa->sa_family == AF_INET ? sizeof(struct sockaddr_in) : + sizeof(struct sockaddr_in6)); + } + + ext = pf_key_v2_find_ext(ret, SADB_EXT_ADDRESS_DST); + if (ext) { + sa = (struct sockaddr *)ext->seg; + memcpy(&ksa.dst, sa, + sa->sa_family == AF_INET ? sizeof(struct sockaddr_in) : + sizeof(struct sockaddr_in6)); + } + + ext = pf_key_v2_find_ext(ret, SADB_EXT_ADDRESS_PROXY); + if (ext) { + sa = (struct sockaddr *)ext->seg; + memcpy(sa, &ksa.proxy, + sa->sa_family == AF_INET ? sizeof(struct sockaddr_in) : + sizeof(struct sockaddr_in6)); + } + +#if defined (SADB_X_EXT_UDPENCAP) + ext = pf_key_v2_find_ext(ret, SADB_X_EXT_UDPENCAP); + if (ext) { + udpencap = (struct sadb_x_udpencap *)ext->seg; + ksa.udpencap_port = udpencap->sadb_x_udpencap_port; + } +#endif + + pf_key_v2_msg_free(ret); + + LOG_DBG_BUF((LOG_SYSDEP, 50, "pf_key_v2_get_kernel_sa: spi", spi, + spi_sz)); + + return &ksa; + + cleanup: + if (addr) + free (addr); + if (gettdb) + pf_key_v2_msg_free(gettdb); + if (ret) + pf_key_v2_msg_free(ret); + return 0; +} + static void pf_key_v2_setup_sockaddr(void *res, struct sockaddr *src, struct sockaddr *dst, in_port_t port, int ingress) diff --git a/sbin/isakmpd/pf_key_v2.h b/sbin/isakmpd/pf_key_v2.h index 374c07f3d56..8eaed1a8b45 100644 --- a/sbin/isakmpd/pf_key_v2.h +++ b/sbin/isakmpd/pf_key_v2.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pf_key_v2.h,v 1.11 2004/06/26 06:07:03 hshoexer Exp $ */ +/* $OpenBSD: pf_key_v2.h,v 1.12 2004/08/10 15:59:10 ho Exp $ */ /* $EOM: pf_key_v2.h,v 1.4 2000/12/04 04:46:35 angelos Exp $ */ /* @@ -38,6 +38,7 @@ struct proto; struct sa; struct sockaddr; +struct kernel_sa; extern int pf_key_v2_socket; @@ -45,13 +46,16 @@ extern void pf_key_v2_connection_check(char *); extern int pf_key_v2_delete_spi(struct sa *, struct proto *, int); extern int pf_key_v2_enable_sa(struct sa *, struct sa *); extern int pf_key_v2_enable_spi(in_addr_t, in_addr_t, in_addr_t, - in_addr_t, u_int8_t *, u_int8_t, in_addr_t); + in_addr_t, u_int8_t *, u_int8_t, in_addr_t); +extern struct sa_kinfo *pf_key_v2_get_kernel_sa(u_int8_t *, size_t, u_int8_t, + struct sockaddr *); extern u_int8_t *pf_key_v2_get_spi(size_t *, u_int8_t, struct sockaddr *, - struct sockaddr *, u_int32_t); + struct sockaddr *, u_int32_t); extern int pf_key_v2_group_spis(struct sa *, struct proto *, - struct proto *, int); + struct proto *, int); extern void pf_key_v2_handler(int); extern int pf_key_v2_open(void); -extern int pf_key_v2_set_spi(struct sa *, struct proto *, int, struct sa *); +extern int pf_key_v2_set_spi(struct sa *, struct proto *, int, + struct sa *); #endif /* _PF_KEY_V2_H_ */ diff --git a/sbin/isakmpd/sa.c b/sbin/isakmpd/sa.c index 977c7e00e91..14c78576687 100644 --- a/sbin/isakmpd/sa.c +++ b/sbin/isakmpd/sa.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sa.c,v 1.85 2004/08/08 19:11:06 deraadt Exp $ */ +/* $OpenBSD: sa.c,v 1.86 2004/08/10 15:59:10 ho Exp $ */ /* $EOM: sa.c,v 1.112 2000/12/12 00:22:52 niklas Exp $ */ /* @@ -799,8 +799,8 @@ sa_release(struct sa *sa) timer_remove_event(sa->nat_t_keepalive); #endif #if defined (USE_DPD) - if (sa->dpd_nextev) - timer_remove_event(sa->dpd_nextev); + if (sa->dpd_event) + timer_remove_event(sa->dpd_event); #endif if (sa->transport) transport_release(sa->transport); diff --git a/sbin/isakmpd/sa.h b/sbin/isakmpd/sa.h index c0635dc43bf..4f6100f83a7 100644 --- a/sbin/isakmpd/sa.h +++ b/sbin/isakmpd/sa.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sa.h,v 1.40 2004/06/21 23:27:10 ho Exp $ */ +/* $OpenBSD: sa.h,v 1.41 2004/08/10 15:59:10 ho Exp $ */ /* $EOM: sa.h,v 1.58 2000/10/10 12:39:01 provos Exp $ */ /* @@ -212,7 +212,8 @@ struct sa { /* IKE DPD (RFC3706) message sequence number. */ u_int32_t dpd_seq; /* sent */ u_int32_t dpd_rseq; /* recieved */ - struct event *dpd_nextev; /* time of next event */ + u_int32_t dpd_failcount; /* # of subsequent failures */ + struct event *dpd_event; /* time of next event */ #endif }; @@ -272,4 +273,46 @@ extern void sa_report(void); extern void sa_dump(int, int, char *, struct sa *); extern void sa_report_all(FILE *); extern int sa_setup_expirations(struct sa *); + +/* + * This structure contains most of the data of the in-kernel SA. + * Currently only used to collect the tdb_last_used time for DPD. + */ +struct sa_kinfo { + u_int32_t flags; /* /usr/include/netinet/ip_ipsp.h */ + + u_int32_t exp_allocations; + u_int32_t soft_allocations; + u_int32_t cur_allocations; + + u_int64_t exp_bytes; + u_int64_t soft_bytes; + u_int64_t cur_bytes; + + u_int64_t exp_timeout; + u_int64_t soft_timeout; + + u_int64_t first_use; + u_int64_t established; + u_int64_t soft_first_use; + u_int64_t exp_first_use; + + u_int64_t last_used; + u_int64_t last_marked; + + struct sockaddr_storage dst; + struct sockaddr_storage src; + struct sockaddr_storage proxy; + + u_int32_t spi; + u_int32_t rpl; + u_int16_t udpencap_port; + u_int16_t amxkeylen; + u_int16_t emxkeylen; + u_int16_t ivlen; + u_int8_t sproto; + u_int8_t wnd; + u_int8_t satype; +}; + #endif /* _SA_H_ */ diff --git a/sbin/isakmpd/sysdep.h b/sbin/isakmpd/sysdep.h index 7bc7826f283..50de8191d09 100644 --- a/sbin/isakmpd/sysdep.h +++ b/sbin/isakmpd/sysdep.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sysdep.h,v 1.18 2004/08/08 19:11:06 deraadt Exp $ */ +/* $OpenBSD: sysdep.h,v 1.19 2004/08/10 15:59:10 ho Exp $ */ /* $EOM: sysdep.h,v 1.17 2000/12/04 04:46:35 angelos Exp $ */ /* @@ -50,15 +50,14 @@ extern int sysdep_cleartext(int, int); extern void sysdep_connection_check(char *); extern int sysdep_ipsec_delete_spi(struct sa *, struct proto *, int); extern int sysdep_ipsec_enable_sa(struct sa *, struct sa *); -extern u_int8_t * -sysdep_ipsec_get_spi(size_t *, u_int8_t, struct sockaddr *, - struct sockaddr *, u_int32_t); -extern int -sysdep_ipsec_group_spis(struct sa *, struct proto *, - struct proto *, int); -extern int -sysdep_ipsec_set_spi(struct sa *, struct proto *, int, - struct sa *); +extern u_int8_t *sysdep_ipsec_get_spi(size_t *, u_int8_t, struct sockaddr *, + struct sockaddr *, u_int32_t); +extern struct sa_kinfo *sysdep_ipsec_get_kernel_sa(u_int8_t *, size_t, + u_int8_t, struct sockaddr *); +extern int sysdep_ipsec_group_spis(struct sa *, struct proto *, + struct proto *, int); +extern int sysdep_ipsec_set_spi(struct sa *, struct proto *, int, + struct sa *); extern char *sysdep_progname(void); extern u_int32_t sysdep_random(void); extern u_int8_t sysdep_sa_len(struct sockaddr *); diff --git a/sbin/isakmpd/sysdep/bsdi/sysdep.c b/sbin/isakmpd/sysdep/bsdi/sysdep.c index ba6e7c5c7cf..99715d55e55 100644 --- a/sbin/isakmpd/sysdep/bsdi/sysdep.c +++ b/sbin/isakmpd/sysdep/bsdi/sysdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sysdep.c,v 1.11 2003/06/03 14:53:11 ho Exp $ */ +/* $OpenBSD: sysdep.c,v 1.12 2004/08/10 15:59:10 ho Exp $ */ /* * Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved. @@ -121,6 +121,16 @@ sysdep_ipsec_get_spi (size_t *sz, u_int8_t proto, struct sockaddr *src, return KEY_API (get_spi) (sz, proto, src, dst, seq); } +struct sa_kinfo * +sysdep_ipsec_get_kernel_sa(u_int8_t *spi, size_t spi_sz, u_int8_t proto, + struct sockaddr *dst) +{ + if (app_none) + return 0; + /* XXX return KEY_API(get_kernel_sa)(spi, spi_sz, proto, dst); */ + return 0; +} + /* Force communication on socket FD to go in the clear. */ int sysdep_cleartext (int fd, int af) diff --git a/sbin/isakmpd/sysdep/darwin/sysdep.c b/sbin/isakmpd/sysdep/darwin/sysdep.c index d09002bb72e..cd61d5ae84c 100644 --- a/sbin/isakmpd/sysdep/darwin/sysdep.c +++ b/sbin/isakmpd/sysdep/darwin/sysdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sysdep.c,v 1.2 2003/06/03 14:53:11 ho Exp $ */ +/* $OpenBSD: sysdep.c,v 1.3 2004/08/10 15:59:10 ho Exp $ */ /* * Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved. @@ -124,6 +124,16 @@ sysdep_ipsec_get_spi (size_t *sz, u_int8_t proto, struct sockaddr *src, return KEY_API (get_spi) (sz, proto, src, dst, seq); } +struct sa_kinfo * +sysdep_ipsec_get_kernel_sa(u_int8_t *spi, size_t spi_sz, u_int8_t proto, + struct sockaddr *dst) +{ + if (app_none) + return 0; + /* XXX return KEY_API(get_kernel_sa)(spi, spi_sz, proto, dst); */ + return 0; +} + /* Force communication on socket FD to go in the clear. */ int sysdep_cleartext (int fd, int af) diff --git a/sbin/isakmpd/sysdep/freebsd/sysdep.c b/sbin/isakmpd/sysdep/freebsd/sysdep.c index 62043d8f6ed..2679fc814c6 100644 --- a/sbin/isakmpd/sysdep/freebsd/sysdep.c +++ b/sbin/isakmpd/sysdep/freebsd/sysdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sysdep.c,v 1.12 2003/06/03 14:53:11 ho Exp $ */ +/* $OpenBSD: sysdep.c,v 1.13 2004/08/10 15:59:10 ho Exp $ */ /* * Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved. @@ -124,6 +124,16 @@ sysdep_ipsec_get_spi (size_t *sz, u_int8_t proto, struct sockaddr *src, return KEY_API (get_spi) (sz, proto, src, dst, seq); } +struct sa_kinfo * +sysdep_ipsec_get_kernel_sa(u_int8_t *spi, size_t spi_sz, u_int8_t proto, + struct sockaddr *dst) +{ + if (app_none) + return 0; + /* XXX return KEY_API(get_kernel_sa)(spi, spi_sz, proto, dst); */ + return 0; +} + /* Force communication on socket FD to go in the clear. */ int sysdep_cleartext (int fd, int af) diff --git a/sbin/isakmpd/sysdep/freeswan/sysdep.c b/sbin/isakmpd/sysdep/freeswan/sysdep.c index afba442aa4c..9e99d7e0c68 100644 --- a/sbin/isakmpd/sysdep/freeswan/sysdep.c +++ b/sbin/isakmpd/sysdep/freeswan/sysdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sysdep.c,v 1.2 2003/06/03 14:53:11 ho Exp $ */ +/* $OpenBSD: sysdep.c,v 1.3 2004/08/10 15:59:10 ho Exp $ */ /* * Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved. @@ -142,6 +142,16 @@ sysdep_ipsec_get_spi (size_t *sz, u_int8_t proto, struct sockaddr *src, return klips_get_spi (sz, proto, src, dst, seq); } +struct sa_kinfo * +sysdep_ipsec_get_kernel_sa(u_int8_t *spi, size_t spi_sz, u_int8_t proto, + struct sockaddr *dst) +{ + if (app_none) + return 0; + /* XXX return KEY_API(get_kernel_sa)(spi, spi_sz, proto, dst); */ + return 0; +} + int sysdep_cleartext (int fd, int af) { diff --git a/sbin/isakmpd/sysdep/linux/sysdep.c b/sbin/isakmpd/sysdep/linux/sysdep.c index 927b2059c22..4eab40b3878 100644 --- a/sbin/isakmpd/sysdep/linux/sysdep.c +++ b/sbin/isakmpd/sysdep/linux/sysdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sysdep.c,v 1.15 2003/12/14 14:34:58 ho Exp $ */ +/* $OpenBSD: sysdep.c,v 1.16 2004/08/10 15:59:10 ho Exp $ */ /* * Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved. @@ -132,6 +132,16 @@ sysdep_ipsec_get_spi (size_t *sz, u_int8_t proto, struct sockaddr *src, return KEY_API (get_spi) (sz, proto, src, dst, seq); } +struct sa_kinfo * +sysdep_ipsec_get_kernel_sa(u_int8_t *spi, size_t spi_sz, u_int8_t proto, + struct sockaddr *dst) +{ + if (app_none) + return 0; + /* XXX return KEY_API(get_kernel_sa)(spi, spi_sz, proto, dst); */ + return 0; +} + /* Force communication on socket FD to go in the clear. */ int sysdep_cleartext (int fd, int af) diff --git a/sbin/isakmpd/sysdep/netbsd/sysdep.c b/sbin/isakmpd/sysdep/netbsd/sysdep.c index 3d3d1103f81..272071561ec 100644 --- a/sbin/isakmpd/sysdep/netbsd/sysdep.c +++ b/sbin/isakmpd/sysdep/netbsd/sysdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sysdep.c,v 1.12 2003/06/03 14:53:11 ho Exp $ */ +/* $OpenBSD: sysdep.c,v 1.13 2004/08/10 15:59:10 ho Exp $ */ /* * Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved. @@ -121,6 +121,16 @@ sysdep_ipsec_get_spi (size_t *sz, u_int8_t proto, struct sockaddr *src, return KEY_API (get_spi) (sz, proto, src, dst, seq); } +struct sa_kinfo * +sysdep_ipsec_get_kernel_sa(u_int8_t *spi, size_t spi_sz, u_int8_t proto, + struct sockaddr *dst) +{ + if (app_none) + return 0; + /* XXX return KEY_API(get_kernel_sa)(spi, spi_sz, proto, dst); */ + return 0; +} + /* Force communication on socket FD to go in the clear. */ int sysdep_cleartext (int fd, int af) diff --git a/sbin/isakmpd/sysdep/openbsd/sysdep.c b/sbin/isakmpd/sysdep/openbsd/sysdep.c index fc4b14d8af2..f59922fde23 100644 --- a/sbin/isakmpd/sysdep/openbsd/sysdep.c +++ b/sbin/isakmpd/sysdep/openbsd/sysdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sysdep.c,v 1.27 2004/06/26 06:07:03 hshoexer Exp $ */ +/* $OpenBSD: sysdep.c,v 1.28 2004/08/10 15:59:11 ho Exp $ */ /* $EOM: sysdep.c,v 1.9 2000/12/04 04:46:35 angelos Exp $ */ /* @@ -133,6 +133,15 @@ sysdep_ipsec_get_spi(size_t *sz, u_int8_t proto, struct sockaddr *src, return KEY_API(get_spi)(sz, proto, src, dst, seq); } +struct sa_kinfo * +sysdep_ipsec_get_kernel_sa(u_int8_t *spi, size_t spi_sz, u_int8_t proto, + struct sockaddr *dst) +{ + if (app_none) + return 0; + return KEY_API(get_kernel_sa)(spi, spi_sz, proto, dst); +} + /* Force communication on socket FD to go in the clear. */ int sysdep_cleartext(int fd, int af) diff --git a/sbin/isakmpd/udp_encap.c b/sbin/isakmpd/udp_encap.c index a01cbf78e59..3acd1ca98e1 100644 --- a/sbin/isakmpd/udp_encap.c +++ b/sbin/isakmpd/udp_encap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: udp_encap.c,v 1.6 2004/08/08 19:11:06 deraadt Exp $ */ +/* $OpenBSD: udp_encap.c,v 1.7 2004/08/10 15:59:10 ho Exp $ */ /* * Copyright (c) 1998, 1999, 2001 Niklas Hallqvist. All rights reserved. @@ -381,7 +381,7 @@ udp_encap_handle_message(struct transport *t) /* Check NULL-ESP marker. */ if (n < (ssize_t)sizeof(u_int32_t) || *(u_int32_t *)buf != 0) { /* Should never happen. */ - log_print ("udp_encap_handle_message: " + log_print("udp_encap_handle_message: " "Null-ESP marker not NULL or short message"); return; } @@ -389,11 +389,11 @@ udp_encap_handle_message(struct transport *t) msg = message_alloc(t, buf + sizeof (u_int32_t), n - sizeof (u_int32_t)); if (!msg) { - log_error ("failed to allocate message structure, dropping " + log_error("failed to allocate message structure, dropping " "packet received on transport %p", u); return; } - message_recv (msg); + message_recv(msg); } /* |