From 832f8d224926758a9ae0b23a6b45353e44fbc87a Mon Sep 17 00:00:00 2001 From: ume Date: Mon, 11 Jun 2001 12:39:29 +0000 Subject: Sync with recent KAME. This work was based on kame-20010528-freebsd43-snap.tgz and some critical problem after the snap was out were fixed. There are many many changes since last KAME merge. TODO: - The definitions of SADB_* in sys/net/pfkeyv2.h are still different from RFC2407/IANA assignment because of binary compatibility issue. It should be fixed under 5-CURRENT. - ip6po_m member of struct ip6_pktopts is no longer used. But, it is still there because of binary compatibility issue. It should be removed under 5-CURRENT. Reviewed by: itojun Obtained from: KAME MFC after: 3 weeks --- lib/libipsec/ipsec_set_policy.3 | 37 +- lib/libipsec/ipsec_strerror.3 | 27 +- lib/libipsec/ipsec_strerror.c | 8 +- lib/libipsec/ipsec_strerror.h | 4 +- lib/libipsec/libpfkey.h | 15 +- lib/libipsec/pfkey.c | 767 +++++++++++++++++++++++++++++++++------- lib/libipsec/pfkey_dump.c | 134 +++++-- lib/libipsec/policy_token.l | 4 +- lib/libipsec/test-policy.c | 27 +- 9 files changed, 827 insertions(+), 196 deletions(-) (limited to 'lib/libipsec') diff --git a/lib/libipsec/ipsec_set_policy.3 b/lib/libipsec/ipsec_set_policy.3 index 7b71c53..bb27a5b 100644 --- a/lib/libipsec/ipsec_set_policy.3 +++ b/lib/libipsec/ipsec_set_policy.3 @@ -1,7 +1,7 @@ -.\" Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. +.\" $KAME: ipsec_set_policy.3,v 1.14 2001/04/06 07:00:46 itojun Exp $ .\" $FreeBSD$ -.\" $KAME: ipsec_set_policy.3,v 1.10 2000/05/07 05:25:03 itojun Exp $ .\" +.\" Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without @@ -92,7 +92,7 @@ It is caller's responsibility to reclaim the region, by using .Fa policy is formatted as either of the following: .Bl -tag -width "discard" -.It Ar direction Li entrust +.It Ar direction Li discard .Ar direction must be .Li in @@ -100,6 +100,10 @@ or .Li out . .Ar direction specifies which direction the policy needs to be applied. +With +.Li discard +policy, packets will be dropped if they match the policy. +.It Ar direction Li entrust .Li entrust means to consult to SPD defined by .Xr setkey 8 . @@ -164,6 +168,15 @@ and .Ar src is the other node .Pq peer . +If +.Ar mode +is +.Li transport , +Both +.Ar src +and +.Ar dst +can be omited. .Pp .Ar level must be set to one of the following: @@ -222,7 +235,8 @@ Note that there is a bit difference of specification from .Xr setkey 8 . In specification by .Xr setkey 8 , -both entrust and bypass are not used. Refer to +both entrust and bypass are not used. +Refer to .Xr setkey 8 for detail. .Pp @@ -230,12 +244,11 @@ Here are several examples .Pq long lines are wrapped for readability : .Bd -literal -offset indent in discard -out ipsec esp/transport/10.1.1.1-10.1.1.2/require -in ipsec ah/transport/10.1.1.2-10.1.1.1/require -out ipsec esp/transport/10.1.1.2-10.1.1.1/use - ah/tunnel/10.1.1.2-10.1.1.1/unique:1000 -in ipsec ipcomp/transport/10.1.1.2-10.1.1.1/use - esp/transport/10.1.1.2-10.1.1.1/use +out ipsec esp/transport//require +in ipsec ah/transport//require +out ipsec esp/tunnel/10.1.1.2-10.1.1.1/use +in ipsec ipcomp/transport//use + esp/transport//use .Ed .Sh RETURN VALUES .Fn ipsec_set_policy @@ -255,3 +268,7 @@ on errors. .Xr setkey 8 .Sh HISTORY The functions first appeared in WIDE/KAME IPv6 protocol stack kit. +.Pp +IPv6 and IPsec support based on the KAME Project (http://www.kame.net/) stack +was initially integrated into +.Fx 4.0 diff --git a/lib/libipsec/ipsec_strerror.3 b/lib/libipsec/ipsec_strerror.3 index 66ae950..82fa99c 100644 --- a/lib/libipsec/ipsec_strerror.3 +++ b/lib/libipsec/ipsec_strerror.3 @@ -1,7 +1,7 @@ -.\" Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. +.\" $KAME: ipsec_strerror.3,v 1.8 2000/11/20 00:35:14 sakane Exp $ .\" $FreeBSD$ -.\" $KAME: ipsec_strerror.3,v 1.6 2000/05/07 05:25:03 itojun Exp $ .\" +.\" Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without @@ -34,24 +34,23 @@ .\" .Sh NAME .Nm ipsec_strerror -.Nd error code for IPsec policy manipulation library +.Nd error message for IPsec policy manipulation library .\" .Sh SYNOPSIS .Fd #include -.Ft "char *" +.Ft "const char *" .Fn ipsec_strerror .\" .Sh DESCRIPTION .Pa netinet6/ipsec.h declares -.Bd -ragged -offset indent -.Vt extern int ipsec_errcode ; -.Ed .Pp -which is used to pass error code from IPsec policy manipulation library -to user program. +.Dl extern int ipsec_errcode; +.Pp +which is used to pass an error code from IPsec policy manipulation library +to an user program. .Fn ipsec_strerror -can be used to obtain error message string for the error code. +can be used to obtain the error message string for the error code. .Pp The array pointed to is not to be modified by the program. Since @@ -75,7 +74,9 @@ The C string must not be overwritten by user programs. .Xr ipsec_set_policy 3 .\" .Sh HISTORY -The functions first appeared in WIDE/KAME IPv6 protocol stack kit. +.Fn ipsec_strerror +first appeared in WIDE/KAME IPv6 protocol stack kit. .\" -.\" .Sh BUGS -.\" (to be written) +.Sh BUGS +.Fn ipsec_strerror +will return its result which may be overwritten by subsequent calls. diff --git a/lib/libipsec/ipsec_strerror.c b/lib/libipsec/ipsec_strerror.c index 1cf4e4c..d53a9e3 100644 --- a/lib/libipsec/ipsec_strerror.c +++ b/lib/libipsec/ipsec_strerror.c @@ -1,5 +1,5 @@ /* $FreeBSD$ */ -/* $KAME: ipsec_strerror.c,v 1.6 2000/05/07 05:25:03 itojun Exp $ */ +/* $KAME: ipsec_strerror.c,v 1.7 2000/07/30 00:45:12 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. @@ -40,7 +40,7 @@ int __ipsec_errcode; -static char *ipsec_errlist[] = { +static const char *ipsec_errlist[] = { "Success", /*EIPSEC_NO_ERROR*/ "Not supported", /*EIPSEC_NOT_SUPPORTED*/ "Invalid argument", /*EIPSEC_INVAL_ARGUMENT*/ @@ -71,7 +71,7 @@ NULL, /*EIPSEC_SYSTEM_ERROR*/ "Unknown error", /*EIPSEC_MAX*/ }; -char *ipsec_strerror(void) +const char *ipsec_strerror(void) { if (__ipsec_errcode < 0 || __ipsec_errcode > EIPSEC_MAX) __ipsec_errcode = EIPSEC_MAX; @@ -79,7 +79,7 @@ char *ipsec_strerror(void) return ipsec_errlist[__ipsec_errcode]; } -void __ipsec_set_strerror(char *str) +void __ipsec_set_strerror(const char *str) { __ipsec_errcode = EIPSEC_SYSTEM_ERROR; ipsec_errlist[EIPSEC_SYSTEM_ERROR] = str; diff --git a/lib/libipsec/ipsec_strerror.h b/lib/libipsec/ipsec_strerror.h index 02448cd..24d4199 100644 --- a/lib/libipsec/ipsec_strerror.h +++ b/lib/libipsec/ipsec_strerror.h @@ -1,5 +1,5 @@ /* $FreeBSD$ */ -/* $KAME: ipsec_strerror.h,v 1.7 2000/05/07 05:25:03 itojun Exp $ */ +/* $KAME: ipsec_strerror.h,v 1.8 2000/07/30 00:45:12 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. @@ -31,7 +31,7 @@ */ extern int __ipsec_errcode; -extern void __ipsec_set_strerror __P((char *)); +extern void __ipsec_set_strerror __P((const char *)); #define EIPSEC_NO_ERROR 0 /*success*/ #define EIPSEC_NOT_SUPPORTED 1 /*not supported*/ diff --git a/lib/libipsec/libpfkey.h b/lib/libipsec/libpfkey.h index ad87700..1f25a30 100644 --- a/lib/libipsec/libpfkey.h +++ b/lib/libipsec/libpfkey.h @@ -1,5 +1,5 @@ /* $FreeBSD$ */ -/* $KAME: libpfkey.h,v 1.1 2000/06/08 21:28:32 itojun Exp $ */ +/* $KAME: libpfkey.h,v 1.6 2001/03/05 18:22:17 thorpej Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -30,11 +30,15 @@ * SUCH DAMAGE. */ +struct sadb_msg; extern void pfkey_sadump __P((struct sadb_msg *)); extern void pfkey_spdump __P((struct sadb_msg *)); struct sockaddr; +struct sadb_alg; int ipsec_check_keylen __P((u_int, u_int, u_int)); +int ipsec_check_keylen2 __P((u_int, u_int, u_int)); +int ipsec_get_keylen __P((u_int, u_int, struct sadb_alg *)); u_int pfkey_set_softrate __P((u_int, u_int)); u_int pfkey_get_softrate __P((u_int)); int pfkey_send_getspi __P((int, u_int, u_int, struct sockaddr *, @@ -49,17 +53,26 @@ int pfkey_send_add __P((int, u_int, u_int, struct sockaddr *, u_int64_t, u_int64_t, u_int32_t)); int pfkey_send_delete __P((int, u_int, u_int, struct sockaddr *, struct sockaddr *, u_int32_t)); +int pfkey_send_delete_all __P((int, u_int, u_int, + struct sockaddr *, struct sockaddr *)); int pfkey_send_get __P((int, u_int, u_int, struct sockaddr *, struct sockaddr *, u_int32_t)); int pfkey_send_register __P((int, u_int)); int pfkey_recv_register __P((int)); +int pfkey_set_supported __P((struct sadb_msg *, int)); int pfkey_send_flush __P((int, u_int)); int pfkey_send_dump __P((int, u_int)); int pfkey_send_promisc_toggle __P((int, int)); int pfkey_send_spdadd __P((int, struct sockaddr *, u_int, struct sockaddr *, u_int, u_int, caddr_t, int, u_int32_t)); +int pfkey_send_spdadd2 __P((int, struct sockaddr *, u_int, + struct sockaddr *, u_int, u_int, u_int64_t, u_int64_t, + caddr_t, int, u_int32_t)); int pfkey_send_spdupdate __P((int, struct sockaddr *, u_int, struct sockaddr *, u_int, u_int, caddr_t, int, u_int32_t)); +int pfkey_send_spdupdate2 __P((int, struct sockaddr *, u_int, + struct sockaddr *, u_int, u_int, u_int64_t, u_int64_t, + caddr_t, int, u_int32_t)); int pfkey_send_spddelete __P((int, struct sockaddr *, u_int, struct sockaddr *, u_int, u_int, caddr_t, int, u_int32_t)); int pfkey_send_spddelete2 __P((int, u_int32_t)); diff --git a/lib/libipsec/pfkey.c b/lib/libipsec/pfkey.c index 11b6722..6cdea34 100644 --- a/lib/libipsec/pfkey.c +++ b/lib/libipsec/pfkey.c @@ -1,5 +1,5 @@ /* $FreeBSD$ */ -/* $KAME: pfkey.c,v 1.31 2000/06/10 14:17:43 sakane Exp $ */ +/* $KAME: pfkey.c,v 1.39 2001/03/05 18:22:17 thorpej Exp $ */ /* * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. @@ -42,12 +42,16 @@ #include #include #include +#include #include "ipsec_strerror.h" #include "libpfkey.h" #define CALLOC(size, cast) (cast)calloc(1, (size)) +static int findsupportedmap __P((int)); +static int setsupportedmap __P((struct sadb_supported *)); +static struct sadb_alg *findsupportedalg __P((u_int, u_int)); static int pfkey_send_x1 __P((int, u_int, u_int, u_int, struct sockaddr *, struct sockaddr *, u_int32_t, u_int32_t, u_int, caddr_t, u_int, u_int, u_int, u_int, u_int, u_int32_t, u_int32_t, @@ -56,94 +60,215 @@ static int pfkey_send_x2 __P((int, u_int, u_int, u_int, struct sockaddr *, struct sockaddr *, u_int32_t)); static int pfkey_send_x3 __P((int, u_int, u_int)); static int pfkey_send_x4 __P((int, u_int, struct sockaddr *, u_int, - struct sockaddr *, u_int, u_int, char *, int, u_int32_t)); + struct sockaddr *, u_int, u_int, u_int64_t, u_int64_t, + char *, int, u_int32_t)); static int pfkey_send_x5 __P((int, u_int, u_int32_t)); -static caddr_t pfkey_setsadbmsg __P((caddr_t, u_int, u_int, +static caddr_t pfkey_setsadbmsg __P((caddr_t, caddr_t, u_int, u_int, u_int, u_int32_t, pid_t)); -static caddr_t pfkey_setsadbsa __P((caddr_t, u_int32_t, u_int, +static caddr_t pfkey_setsadbsa __P((caddr_t, caddr_t, u_int32_t, u_int, u_int, u_int, u_int32_t)); -static caddr_t pfkey_setsadbaddr __P((caddr_t, u_int, +static caddr_t pfkey_setsadbaddr __P((caddr_t, caddr_t, u_int, struct sockaddr *, u_int, u_int)); -static caddr_t pfkey_setsadbkey __P((caddr_t, u_int, caddr_t, u_int)); -static caddr_t pfkey_setsadblifetime __P((caddr_t, u_int, u_int32_t, u_int32_t, - u_int32_t, u_int32_t)); -static caddr_t pfkey_setsadbxsa2 __P((caddr_t, u_int32_t, u_int32_t)); +static caddr_t pfkey_setsadbkey __P((caddr_t, caddr_t, u_int, caddr_t, u_int)); +static caddr_t pfkey_setsadblifetime __P((caddr_t, caddr_t, u_int, u_int32_t, + u_int32_t, u_int32_t, u_int32_t)); +static caddr_t pfkey_setsadbxsa2 __P((caddr_t, caddr_t, u_int32_t, u_int32_t)); + +/* + * make and search supported algorithm structure. + */ +static struct sadb_supported *ipsec_supported[] = { NULL, NULL, NULL, }; + +static int supported_map[] = { + SADB_SATYPE_AH, + SADB_SATYPE_ESP, + SADB_X_SATYPE_IPCOMP, +}; + +static int +findsupportedmap(satype) + int satype; +{ + int i; + + for (i = 0; i < sizeof(supported_map)/sizeof(supported_map[0]); i++) + if (supported_map[i] == satype) + return i; + return -1; +} + +static struct sadb_alg * +findsupportedalg(satype, alg_id) + u_int satype, alg_id; +{ + int algno; + int tlen; + caddr_t p; + + /* validity check */ + algno = findsupportedmap(satype); + if (algno == -1) { + __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; + return NULL; + } + if (ipsec_supported[algno] == NULL) { + __ipsec_errcode = EIPSEC_DO_GET_SUPP_LIST; + return NULL; + } + + tlen = ipsec_supported[algno]->sadb_supported_len + - sizeof(struct sadb_supported); + p = (caddr_t)(ipsec_supported[algno] + 1); + while (tlen > 0) { + if (tlen < sizeof(struct sadb_alg)) { + /* invalid format */ + break; + } + if (((struct sadb_alg *)p)->sadb_alg_id == alg_id) + return (struct sadb_alg *)p; + + tlen -= sizeof(struct sadb_alg); + p += sizeof(struct sadb_alg); + } + + __ipsec_errcode = EIPSEC_NOT_SUPPORTED; + return NULL; +} + +static int +setsupportedmap(sup) + struct sadb_supported *sup; +{ + struct sadb_supported **ipsup; + + switch (sup->sadb_supported_exttype) { + case SADB_EXT_SUPPORTED_AUTH: + ipsup = &ipsec_supported[findsupportedmap(SADB_SATYPE_AH)]; + break; + case SADB_EXT_SUPPORTED_ENCRYPT: + ipsup = &ipsec_supported[findsupportedmap(SADB_SATYPE_ESP)]; + break; + default: + __ipsec_errcode = EIPSEC_INVAL_SATYPE; + return -1; + } + + if (*ipsup) + free(*ipsup); + + *ipsup = malloc(sup->sadb_supported_len); + if (!*ipsup) { + __ipsec_set_strerror(strerror(errno)); + return -1; + } + memcpy(*ipsup, sup, sup->sadb_supported_len); + + return 0; +} /* * check key length against algorithm specified. - * supported is either SADB_EXT_SUPPORTED_ENCRYPT or SADB_EXT_SUPPORTED_AUTH. - * Refer to keyv2.h to get more info. + * This function is called with SADB_EXT_SUPPORTED_{AUTH,ENCRYPT} as the + * augument, and only calls to ipsec_check_keylen2(); * keylen is the unit of bit. * OUT: * -1: invalid. * 0: valid. */ -struct sadb_msg *ipsec_supported = NULL; - int ipsec_check_keylen(supported, alg_id, keylen) u_int supported; u_int alg_id; u_int keylen; { - u_int tlen; - caddr_t p; - struct sadb_supported *sup; - struct sadb_alg *alg; + int satype; /* validity check */ - if (ipsec_supported == NULL) { - __ipsec_errcode = EIPSEC_DO_GET_SUPP_LIST; - return -1; - } switch (supported) { case SADB_EXT_SUPPORTED_AUTH: + satype = SADB_SATYPE_AH; + break; case SADB_EXT_SUPPORTED_ENCRYPT: + satype = SADB_SATYPE_ESP; break; default: __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; return -1; } - tlen = ipsec_supported->sadb_msg_len - sizeof(struct sadb_msg); - p = (caddr_t)ipsec_supported + sizeof(struct sadb_msg); + return ipsec_check_keylen2(satype, alg_id, keylen); +} - for (; - tlen > 0; - tlen -= sup->sadb_supported_len, p += sup->sadb_supported_len) { +/* + * check key length against algorithm specified. + * satype is one of satype defined at pfkeyv2.h. + * keylen is the unit of bit. + * OUT: + * -1: invalid. + * 0: valid. + */ +int +ipsec_check_keylen2(satype, alg_id, keylen) + u_int satype; + u_int alg_id; + u_int keylen; +{ + struct sadb_alg *alg; - sup = (struct sadb_supported *)p; + alg = findsupportedalg(satype, alg_id); + if (!alg) + return -1; - if (sup->sadb_supported_exttype != supported) - continue; + if (keylen < alg->sadb_alg_minbits || keylen > alg->sadb_alg_maxbits) { + __ipsec_errcode = EIPSEC_INVAL_KEYLEN; + return -1; + } - { - u_int ttlen = sup->sadb_supported_len; - caddr_t pp = p + sizeof(*sup); + __ipsec_errcode = EIPSEC_NO_ERROR; + return 0; +} - for (; - ttlen > 0; - ttlen -= sizeof(*alg), pp += sizeof(*alg)) { - alg = (struct sadb_alg *)pp; +/* + * get max/min key length against algorithm specified. + * satype is one of satype defined at pfkeyv2.h. + * keylen is the unit of bit. + * OUT: + * -1: invalid. + * 0: valid. + */ +int +ipsec_get_keylen(supported, alg_id, alg0) + u_int supported, alg_id; + struct sadb_alg *alg0; +{ + struct sadb_alg *alg; + u_int satype; - if (alg->sadb_alg_id == alg_id) - goto found; - } - } + /* validity check */ + if (!alg0) { + __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; + return -1; } - __ipsec_errcode = EIPSEC_NOT_SUPPORTED; - return -1; - /* NOTREACHED */ - - found: - if (keylen < alg->sadb_alg_minbits - || keylen > alg->sadb_alg_maxbits) { - __ipsec_errcode = EIPSEC_INVAL_KEYLEN; + switch (supported) { + case SADB_EXT_SUPPORTED_AUTH: + satype = SADB_SATYPE_AH; + break; + case SADB_EXT_SUPPORTED_ENCRYPT: + satype = SADB_SATYPE_ESP; + break; + default: + __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; return -1; } + alg = findsupportedalg(satype, alg_id); + if (!alg) + return -1; + + memcpy(alg0, alg, sizeof(*alg0)); + __ipsec_errcode = EIPSEC_NO_ERROR; return 0; } @@ -221,6 +346,7 @@ pfkey_send_getspi(so, satype, mode, src, dst, min, max, reqid, seq) u_int32_t min, max, reqid, seq; { struct sadb_msg *newmsg; + caddr_t ep; int len; int need_spirange = 0; caddr_t p; @@ -268,31 +394,59 @@ pfkey_send_getspi(so, satype, mode, src, dst, min, max, reqid, seq) __ipsec_set_strerror(strerror(errno)); return -1; } + ep = ((caddr_t)newmsg) + len; - p = pfkey_setsadbmsg((caddr_t)newmsg, SADB_GETSPI, - len, satype, seq, getpid()); + p = pfkey_setsadbmsg((caddr_t)newmsg, ep, SADB_GETSPI, + len, satype, seq, getpid()); + if (!p) { + free(newmsg); + return -1; + } - p = pfkey_setsadbxsa2(p, mode, reqid); + p = pfkey_setsadbxsa2(p, ep, mode, reqid); + if (!p) { + free(newmsg); + return -1; + } /* set sadb_address for source */ - p = pfkey_setsadbaddr(p, SADB_EXT_ADDRESS_SRC, src, plen, + p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, plen, IPSEC_ULPROTO_ANY); + if (!p) { + free(newmsg); + return -1; + } /* set sadb_address for destination */ - p = pfkey_setsadbaddr(p, SADB_EXT_ADDRESS_DST, dst, plen, + p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, plen, IPSEC_ULPROTO_ANY); + if (!p) { + free(newmsg); + return -1; + } /* proccessing spi range */ if (need_spirange) { - int _len = sizeof(struct sadb_spirange); + struct sadb_spirange spirange; -#define _SADB_SPIRANGE(p) ((struct sadb_spirange *)(p)) - _SADB_SPIRANGE(p)->sadb_spirange_len = PFKEY_UNIT64(_len); - _SADB_SPIRANGE(p)->sadb_spirange_exttype = SADB_EXT_SPIRANGE; - _SADB_SPIRANGE(p)->sadb_spirange_min = min; - _SADB_SPIRANGE(p)->sadb_spirange_max = max; -#undef _SADB_SPIRANGE(p) - p += _len; + if (p + sizeof(spirange) > ep) { + free(newmsg); + return -1; + } + + memset(&spirange, 0, sizeof(spirange)); + spirange.sadb_spirange_len = PFKEY_UNIT64(sizeof(spirange)); + spirange.sadb_spirange_exttype = SADB_EXT_SPIRANGE; + spirange.sadb_spirange_min = min; + spirange.sadb_spirange_max = max; + + memcpy(p, &spirange, sizeof(spirange)); + + p += sizeof(spirange); + } + if (p != ep) { + free(newmsg); + return -1; } /* send message */ @@ -389,6 +543,91 @@ pfkey_send_delete(so, satype, mode, src, dst, spi) } /* + * sending SADB_DELETE without spi to the kernel. This is + * the "delete all" request (an extension also present in + * Solaris). + * + * OUT: + * positive: success and return length sent + * -1 : error occured, and set errno + */ +int +pfkey_send_delete_all(so, satype, mode, src, dst) + int so; + u_int satype, mode; + struct sockaddr *src, *dst; +{ + struct sadb_msg *newmsg; + int len; + caddr_t p; + int plen; + caddr_t ep; + + /* validity check */ + if (src == NULL || dst == NULL) { + __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; + return -1; + } + if (src->sa_family != dst->sa_family) { + __ipsec_errcode = EIPSEC_FAMILY_MISMATCH; + return -1; + } + switch (src->sa_family) { + case AF_INET: + plen = sizeof(struct in_addr) << 3; + break; + case AF_INET6: + plen = sizeof(struct in6_addr) << 3; + break; + default: + __ipsec_errcode = EIPSEC_INVAL_FAMILY; + return -1; + } + + /* create new sadb_msg to reply. */ + len = sizeof(struct sadb_msg) + + sizeof(struct sadb_address) + + PFKEY_ALIGN8(src->sa_len) + + sizeof(struct sadb_address) + + PFKEY_ALIGN8(dst->sa_len); + + if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) { + __ipsec_set_strerror(strerror(errno)); + return -1; + } + ep = ((caddr_t)newmsg) + len; + + p = pfkey_setsadbmsg((caddr_t)newmsg, ep, SADB_DELETE, len, satype, 0, + getpid()); + if (!p) { + free(newmsg); + return -1; + } + p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, plen, + IPSEC_ULPROTO_ANY); + if (!p) { + free(newmsg); + return -1; + } + p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, plen, + IPSEC_ULPROTO_ANY); + if (!p || p != ep) { + free(newmsg); + return -1; + } + + /* send message */ + len = pfkey_send(so, newmsg, len); + free(newmsg); + + if (len < 0) + return -1; + + __ipsec_errcode = EIPSEC_NO_ERROR; + return len; +} + +/* * sending SADB_GET message to the kernel. * OUT: * positive: success and return length sent. @@ -419,7 +658,29 @@ pfkey_send_register(so, satype) int so; u_int satype; { - int len; + int len, algno; + + if (satype == PF_UNSPEC) { + for (algno = 0; + algno < sizeof(supported_map)/sizeof(supported_map[0]); + algno++) { + if (ipsec_supported[algno]) { + free(ipsec_supported[algno]); + ipsec_supported[algno] = NULL; + } + } + } else { + algno = findsupportedmap(satype); + if (algno == -1) { + __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; + return -1; + } + + if (ipsec_supported[algno]) { + free(ipsec_supported[algno]); + ipsec_supported[algno] = NULL; + } + } if ((len = pfkey_send_x3(so, SADB_REGISTER, satype)) < 0) return -1; @@ -440,51 +701,92 @@ pfkey_recv_register(so) { pid_t pid = getpid(); struct sadb_msg *newmsg; - struct sadb_supported *sup; - caddr_t p; - int tlen; + int error = -1; /* receive message */ do { if ((newmsg = pfkey_recv(so)) == NULL) return -1; - } while (newmsg->sadb_msg_type != SADB_REGISTER || newmsg->sadb_msg_pid != pid); /* check and fix */ newmsg->sadb_msg_len = PFKEY_UNUNIT64(newmsg->sadb_msg_len); - tlen = newmsg->sadb_msg_len - sizeof(struct sadb_msg); - p = (caddr_t)newmsg + sizeof(struct sadb_msg); - while (tlen > 0) { + error = pfkey_set_supported(newmsg, newmsg->sadb_msg_len); + free(newmsg); + + if (error == 0) + __ipsec_errcode = EIPSEC_NO_ERROR; + + return error; +} + +/* + * receiving SADB_REGISTER message from the kernel, and copy buffer for + * sadb_supported returned into ipsec_supported. + * NOTE: sadb_msg_len must be host order. + * IN: + * tlen: msg length, it's to makeing sure. + * OUT: + * 0: success and return length sent. + * -1: error occured, and set errno. + */ +int +pfkey_set_supported(msg, tlen) + struct sadb_msg *msg; + int tlen; +{ + struct sadb_supported *sup; + caddr_t p; + caddr_t ep; + + /* validity */ + if (msg->sadb_msg_len != tlen) { + __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; + return -1; + } + + p = (caddr_t)msg; + ep = p + tlen; + + p += sizeof(struct sadb_msg); + + while (p < ep) { sup = (struct sadb_supported *)p; + if (ep < p + sizeof(*sup) || + PFKEY_EXTLEN(sup) < sizeof(*sup) || + ep < p + sup->sadb_supported_len) { + /* invalid format */ + break; + } + switch (sup->sadb_supported_exttype) { case SADB_EXT_SUPPORTED_AUTH: case SADB_EXT_SUPPORTED_ENCRYPT: - sup->sadb_supported_len = PFKEY_EXTLEN(sup); break; default: __ipsec_errcode = EIPSEC_INVAL_SATYPE; - free(newmsg); return -1; } - tlen -= sup->sadb_supported_len; + /* fixed length */ + sup->sadb_supported_len = PFKEY_EXTLEN(sup); + + /* set supported map */ + if (setsupportedmap(sup) != 0) + return -1; + p += sup->sadb_supported_len; } - if (tlen < 0) { + if (p != ep) { __ipsec_errcode = EIPSEC_INVAL_SATYPE; return -1; } - if (ipsec_supported != NULL) - free(ipsec_supported); - - ipsec_supported = newmsg; - __ipsec_errcode = EIPSEC_NO_ERROR; + return 0; } @@ -570,6 +872,35 @@ pfkey_send_spdadd(so, src, prefs, dst, prefd, proto, policy, policylen, seq) if ((len = pfkey_send_x4(so, SADB_X_SPDADD, src, prefs, dst, prefd, proto, + 0, 0, + policy, policylen, seq)) < 0) + return -1; + + return len; +} + +/* + * sending SADB_X_SPDADD message to the kernel. + * OUT: + * positive: success and return length sent. + * -1 : error occured, and set errno. + */ +int +pfkey_send_spdadd2(so, src, prefs, dst, prefd, proto, ltime, vtime, + policy, policylen, seq) + int so; + struct sockaddr *src, *dst; + u_int prefs, prefd, proto; + u_int64_t ltime, vtime; + caddr_t policy; + int policylen; + u_int32_t seq; +{ + int len; + + if ((len = pfkey_send_x4(so, SADB_X_SPDADD, + src, prefs, dst, prefd, proto, + ltime, vtime, policy, policylen, seq)) < 0) return -1; @@ -595,6 +926,35 @@ pfkey_send_spdupdate(so, src, prefs, dst, prefd, proto, policy, policylen, seq) if ((len = pfkey_send_x4(so, SADB_X_SPDUPDATE, src, prefs, dst, prefd, proto, + 0, 0, + policy, policylen, seq)) < 0) + return -1; + + return len; +} + +/* + * sending SADB_X_SPDUPDATE message to the kernel. + * OUT: + * positive: success and return length sent. + * -1 : error occured, and set errno. + */ +int +pfkey_send_spdupdate2(so, src, prefs, dst, prefd, proto, ltime, vtime, + policy, policylen, seq) + int so; + struct sockaddr *src, *dst; + u_int prefs, prefd, proto; + u_int64_t ltime, vtime; + caddr_t policy; + int policylen; + u_int32_t seq; +{ + int len; + + if ((len = pfkey_send_x4(so, SADB_X_SPDUPDATE, + src, prefs, dst, prefd, proto, + ltime, vtime, policy, policylen, seq)) < 0) return -1; @@ -625,6 +985,7 @@ pfkey_send_spddelete(so, src, prefs, dst, prefd, proto, policy, policylen, seq) if ((len = pfkey_send_x4(so, SADB_X_SPDDELETE, src, prefs, dst, prefd, proto, + 0, 0, policy, policylen, seq)) < 0) return -1; @@ -693,6 +1054,7 @@ pfkey_send_spdsetidx(so, src, prefs, dst, prefd, proto, policy, policylen, seq) if ((len = pfkey_send_x4(so, SADB_X_SPDSETIDX, src, prefs, dst, prefd, proto, + 0, 0, policy, policylen, seq)) < 0) return -1; @@ -753,6 +1115,7 @@ pfkey_send_x1(so, type, satype, mode, src, dst, spi, reqid, wsize, int len; caddr_t p; int plen; + caddr_t ep; /* validity check */ if (src == NULL || dst == NULL) { @@ -793,6 +1156,14 @@ pfkey_send_x1(so, type, satype, mode, src, dst, spi, reqid, wsize, } break; case SADB_X_SATYPE_IPCOMP: + if (e_type == SADB_X_CALG_NONE) { + __ipsec_errcode = EIPSEC_INVAL_ALGS; + return -1; + } + if (a_type != SADB_AALG_NONE) { + __ipsec_errcode = EIPSEC_NO_ALGS; + return -1; + } break; default: __ipsec_errcode = EIPSEC_INVAL_SATYPE; @@ -819,28 +1190,67 @@ pfkey_send_x1(so, type, satype, mode, src, dst, spi, reqid, wsize, __ipsec_set_strerror(strerror(errno)); return -1; } + ep = ((caddr_t)newmsg) + len; - p = pfkey_setsadbmsg((caddr_t)newmsg, type, len, + p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len, satype, seq, getpid()); - p = pfkey_setsadbsa(p, spi, wsize, a_type, e_type, flags); - p = pfkey_setsadbxsa2(p, mode, reqid); - p = pfkey_setsadbaddr(p, SADB_EXT_ADDRESS_SRC, src, plen, + if (!p) { + free(newmsg); + return -1; + } + p = pfkey_setsadbsa(p, ep, spi, wsize, a_type, e_type, flags); + if (!p) { + free(newmsg); + return -1; + } + p = pfkey_setsadbxsa2(p, ep, mode, reqid); + if (!p) { + free(newmsg); + return -1; + } + p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, plen, IPSEC_ULPROTO_ANY); - p = pfkey_setsadbaddr(p, SADB_EXT_ADDRESS_DST, dst, plen, + if (!p) { + free(newmsg); + return -1; + } + p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, plen, IPSEC_ULPROTO_ANY); + if (!p) { + free(newmsg); + return -1; + } - if (e_type != SADB_EALG_NONE) - p = pfkey_setsadbkey(p, SADB_EXT_KEY_ENCRYPT, + if (e_type != SADB_EALG_NONE) { + p = pfkey_setsadbkey(p, ep, SADB_EXT_KEY_ENCRYPT, keymat, e_keylen); - if (a_type != SADB_AALG_NONE) - p = pfkey_setsadbkey(p, SADB_EXT_KEY_AUTH, + if (!p) { + free(newmsg); + return -1; + } + } + if (a_type != SADB_AALG_NONE) { + p = pfkey_setsadbkey(p, ep, SADB_EXT_KEY_AUTH, keymat + e_keylen, a_keylen); + if (!p) { + free(newmsg); + return -1; + } + } /* set sadb_lifetime for destination */ - p = pfkey_setsadblifetime(p, SADB_EXT_LIFETIME_HARD, + p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_HARD, l_alloc, l_bytes, l_addtime, l_usetime); - p = pfkey_setsadblifetime(p, SADB_EXT_LIFETIME_SOFT, + if (!p) { + free(newmsg); + return -1; + } + p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_SOFT, l_alloc, l_bytes, l_addtime, l_usetime); + if (!p || p != ep) { + free(newmsg); + return -1; + } /* send message */ len = pfkey_send(so, newmsg, len); @@ -865,6 +1275,7 @@ pfkey_send_x2(so, type, satype, mode, src, dst, spi) int len; caddr_t p; int plen; + caddr_t ep; /* validity check */ if (src == NULL || dst == NULL) { @@ -899,13 +1310,31 @@ pfkey_send_x2(so, type, satype, mode, src, dst, spi) __ipsec_set_strerror(strerror(errno)); return -1; } + ep = ((caddr_t)newmsg) + len; - p = pfkey_setsadbmsg((caddr_t)newmsg, type, len, satype, 0, getpid()); - p = pfkey_setsadbsa(p, spi, 0, 0, 0, 0); - p = pfkey_setsadbaddr(p, SADB_EXT_ADDRESS_SRC, src, plen, + p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len, satype, 0, + getpid()); + if (!p) { + free(newmsg); + return -1; + } + p = pfkey_setsadbsa(p, ep, spi, 0, 0, 0, 0); + if (!p) { + free(newmsg); + return -1; + } + p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, plen, IPSEC_ULPROTO_ANY); - p = pfkey_setsadbaddr(p, SADB_EXT_ADDRESS_DST, dst, plen, + if (!p) { + free(newmsg); + return -1; + } + p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, plen, IPSEC_ULPROTO_ANY); + if (!p || p != ep) { + free(newmsg); + return -1; + } /* send message */ len = pfkey_send(so, newmsg, len); @@ -929,6 +1358,8 @@ pfkey_send_x3(so, type, satype) { struct sadb_msg *newmsg; int len; + caddr_t p; + caddr_t ep; /* validity check */ switch (type) { @@ -958,8 +1389,14 @@ pfkey_send_x3(so, type, satype) __ipsec_set_strerror(strerror(errno)); return -1; } + ep = ((caddr_t)newmsg) + len; - (void)pfkey_setsadbmsg((caddr_t)newmsg, type, len, satype, 0, getpid()); + p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len, satype, 0, + getpid()); + if (!p || p != ep) { + free(newmsg); + return -1; + } /* send message */ len = pfkey_send(so, newmsg, len); @@ -974,10 +1411,12 @@ pfkey_send_x3(so, type, satype) /* sending SADB_X_SPDADD message to the kernel */ static int -pfkey_send_x4(so, type, src, prefs, dst, prefd, proto, policy, policylen, seq) +pfkey_send_x4(so, type, src, prefs, dst, prefd, proto, + ltime, vtime, policy, policylen, seq) int so; struct sockaddr *src, *dst; u_int type, prefs, prefd, proto; + u_int64_t ltime, vtime; char *policy; int policylen; u_int32_t seq; @@ -986,6 +1425,7 @@ pfkey_send_x4(so, type, src, prefs, dst, prefd, proto, policy, policylen, seq) int len; caddr_t p; int plen; + caddr_t ep; /* validity check */ if (src == NULL || dst == NULL) { @@ -1019,25 +1459,37 @@ pfkey_send_x4(so, type, src, prefs, dst, prefd, proto, policy, policylen, seq) + PFKEY_ALIGN8(src->sa_len) + sizeof(struct sadb_address) + PFKEY_ALIGN8(src->sa_len) + + sizeof(struct sadb_lifetime) + policylen; if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) { __ipsec_set_strerror(strerror(errno)); return -1; } + ep = ((caddr_t)newmsg) + len; - p = pfkey_setsadbmsg((caddr_t)newmsg, type, len, - SADB_SATYPE_UNSPEC, seq, getpid()); - p = pfkey_setsadbaddr(p, - SADB_EXT_ADDRESS_SRC, - src, - prefs, - proto); - p = pfkey_setsadbaddr(p, - SADB_EXT_ADDRESS_DST, - dst, - prefd, - proto); + p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len, + SADB_SATYPE_UNSPEC, seq, getpid()); + if (!p) { + free(newmsg); + return -1; + } + p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, prefs, proto); + if (!p) { + free(newmsg); + return -1; + } + p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, prefd, proto); + if (!p) { + free(newmsg); + return -1; + } + p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_HARD, + 0, 0, ltime, vtime); + if (!p || p + policylen != ep) { + free(newmsg); + return -1; + } memcpy(p, policy, policylen); /* send message */ @@ -1062,6 +1514,7 @@ pfkey_send_x5(so, type, spid) struct sadb_x_policy xpl; int len; caddr_t p; + caddr_t ep; /* create new sadb_msg to reply. */ len = sizeof(struct sadb_msg) @@ -1071,15 +1524,23 @@ pfkey_send_x5(so, type, spid) __ipsec_set_strerror(strerror(errno)); return -1; } + ep = ((caddr_t)newmsg) + len; - p = pfkey_setsadbmsg((caddr_t)newmsg, type, len, - SADB_SATYPE_UNSPEC, 0, getpid()); + p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len, + SADB_SATYPE_UNSPEC, 0, getpid()); + if (!p) { + free(newmsg); + return -1; + } + if (p + sizeof(xpl) != ep) { + free(newmsg); + return -1; + } memset(&xpl, 0, sizeof(xpl)); xpl.sadb_x_policy_len = PFKEY_UNUNIT64(sizeof(xpl)); xpl.sadb_x_policy_exttype = SADB_X_EXT_POLICY; xpl.sadb_x_policy_id = spid; - memcpy(p, &xpl, sizeof(xpl)); /* send message */ @@ -1143,6 +1604,8 @@ pfkey_close(so) * OUT: * NULL : error occured. * others : a pointer to sadb_msg structure. + * + * XXX should be rewritten to pass length explicitly */ struct sadb_msg * pfkey_recv(so) @@ -1152,7 +1615,8 @@ pfkey_recv(so) int len, reallen; while ((len = recv(so, (caddr_t)&buf, sizeof(buf), MSG_PEEK)) < 0) { - if (errno == EINTR) continue; + if (errno == EINTR) + continue; __ipsec_set_strerror(strerror(errno)); return NULL; } @@ -1171,7 +1635,8 @@ pfkey_recv(so) } while ((len = recv(so, (caddr_t)newmsg, reallen, 0)) < 0) { - if (errno == EINTR) continue; + if (errno == EINTR) + continue; __ipsec_set_strerror(strerror(errno)); free(newmsg); return NULL; @@ -1183,6 +1648,13 @@ pfkey_recv(so) return NULL; } + /* don't trust what the kernel says, validate! */ + if (PFKEY_UNUNIT64(newmsg->sadb_msg_len) != len) { + __ipsec_errcode = EIPSEC_SYSTEM_ERROR; + free(newmsg); + return NULL; + } + __ipsec_errcode = EIPSEC_NO_ERROR; return newmsg; } @@ -1219,6 +1691,8 @@ pfkey_send(so, msg, len) * caddr_t mhp[SADB_EXT_MAX + 1]; * OUT: -1: invalid. * 0: valid. + * + * XXX should be rewritten to obtain length explicitly */ int pfkey_align(msg, mhp) @@ -1226,8 +1700,9 @@ pfkey_align(msg, mhp) caddr_t *mhp; { struct sadb_ext *ext; - int tlen, extlen; int i; + caddr_t p; + caddr_t ep; /* XXX should be passed from upper layer */ /* validity check */ if (msg == NULL || mhp == NULL) { @@ -1241,10 +1716,21 @@ pfkey_align(msg, mhp) mhp[0] = (caddr_t)msg; - tlen = PFKEY_UNUNIT64(msg->sadb_msg_len) - sizeof(struct sadb_msg); - ext = (struct sadb_ext *)((caddr_t)msg + sizeof(struct sadb_msg)); + /* initialize */ + p = (caddr_t) msg; + ep = p + PFKEY_UNUNIT64(msg->sadb_msg_len); + + /* skip base header */ + p += sizeof(struct sadb_msg); + + while (p < ep) { + ext = (struct sadb_ext *)p; + if (ep < p + sizeof(*ext) || PFKEY_EXTLEN(ext) < sizeof(*ext) || + ep < p + PFKEY_EXTLEN(ext)) { + /* invalid format */ + break; + } - while (tlen > 0) { /* duplicate check */ /* XXX Are there duplication either KEY_AUTH or KEY_ENCRYPT ?*/ if (mhp[ext->sadb_ext_type] != NULL) { @@ -1281,9 +1767,12 @@ pfkey_align(msg, mhp) return -1; } - extlen = PFKEY_EXTLEN(ext); - tlen -= extlen; - ext = (struct sadb_ext *)((caddr_t)ext + extlen); + p += PFKEY_EXTLEN(ext); + } + + if (p != ep) { + __ipsec_errcode = EIPSEC_INVAL_SADBMSG; + return -1; } __ipsec_errcode = EIPSEC_NO_ERROR; @@ -1413,8 +1902,9 @@ pfkey_check(mhp) * `buf' must has been allocated sufficiently. */ static caddr_t -pfkey_setsadbmsg(buf, type, tlen, satype, seq, pid) +pfkey_setsadbmsg(buf, lim, type, tlen, satype, seq, pid) caddr_t buf; + caddr_t lim; u_int type, satype; u_int tlen; u_int32_t seq; @@ -1426,6 +1916,9 @@ pfkey_setsadbmsg(buf, type, tlen, satype, seq, pid) p = (struct sadb_msg *)buf; len = sizeof(struct sadb_msg); + if (buf + len > lim) + return NULL; + memset(p, 0, len); p->sadb_msg_version = PF_KEY_V2; p->sadb_msg_type = type; @@ -1444,8 +1937,9 @@ pfkey_setsadbmsg(buf, type, tlen, satype, seq, pid) * `buf' must has been allocated sufficiently. */ static caddr_t -pfkey_setsadbsa(buf, spi, wsize, auth, enc, flags) +pfkey_setsadbsa(buf, lim, spi, wsize, auth, enc, flags) caddr_t buf; + caddr_t lim; u_int32_t spi, flags; u_int wsize, auth, enc; { @@ -1455,6 +1949,9 @@ pfkey_setsadbsa(buf, spi, wsize, auth, enc, flags) p = (struct sadb_sa *)buf; len = sizeof(struct sadb_sa); + if (buf + len > lim) + return NULL; + memset(p, 0, len); p->sadb_sa_len = PFKEY_UNIT64(len); p->sadb_sa_exttype = SADB_EXT_SA; @@ -1474,8 +1971,9 @@ pfkey_setsadbsa(buf, spi, wsize, auth, enc, flags) * prefixlen is in bits. */ static caddr_t -pfkey_setsadbaddr(buf, exttype, saddr, prefixlen, ul_proto) +pfkey_setsadbaddr(buf, lim, exttype, saddr, prefixlen, ul_proto) caddr_t buf; + caddr_t lim; u_int exttype; struct sockaddr *saddr; u_int prefixlen; @@ -1487,6 +1985,9 @@ pfkey_setsadbaddr(buf, exttype, saddr, prefixlen, ul_proto) p = (struct sadb_address *)buf; len = sizeof(struct sadb_address) + PFKEY_ALIGN8(saddr->sa_len); + if (buf + len > lim) + return NULL; + memset(p, 0, len); p->sadb_address_len = PFKEY_UNIT64(len); p->sadb_address_exttype = exttype & 0xffff; @@ -1504,8 +2005,10 @@ pfkey_setsadbaddr(buf, exttype, saddr, prefixlen, ul_proto) * OUT: the pointer of buf + len. */ static caddr_t -pfkey_setsadbkey(buf, type, key, keylen) - caddr_t buf, key; +pfkey_setsadbkey(buf, lim, type, key, keylen) + caddr_t buf; + caddr_t lim; + caddr_t key; u_int type, keylen; { struct sadb_key *p; @@ -1514,6 +2017,9 @@ pfkey_setsadbkey(buf, type, key, keylen) p = (struct sadb_key *)buf; len = sizeof(struct sadb_key) + PFKEY_ALIGN8(keylen); + if (buf + len > lim) + return NULL; + memset(p, 0, len); p->sadb_key_len = PFKEY_UNIT64(len); p->sadb_key_exttype = type; @@ -1530,8 +2036,9 @@ pfkey_setsadbkey(buf, type, key, keylen) * OUT: the pointer of buf + len. */ static caddr_t -pfkey_setsadblifetime(buf, type, l_alloc, l_bytes, l_addtime, l_usetime) +pfkey_setsadblifetime(buf, lim, type, l_alloc, l_bytes, l_addtime, l_usetime) caddr_t buf; + caddr_t lim; u_int type; u_int32_t l_alloc, l_bytes, l_addtime, l_usetime; { @@ -1541,6 +2048,9 @@ pfkey_setsadblifetime(buf, type, l_alloc, l_bytes, l_addtime, l_usetime) p = (struct sadb_lifetime *)buf; len = sizeof(struct sadb_lifetime); + if (buf + len > lim) + return NULL; + memset(p, 0, len); p->sadb_lifetime_len = PFKEY_UNIT64(len); p->sadb_lifetime_exttype = type; @@ -1572,8 +2082,9 @@ pfkey_setsadblifetime(buf, type, l_alloc, l_bytes, l_addtime, l_usetime) * `buf' must has been allocated sufficiently. */ static caddr_t -pfkey_setsadbxsa2(buf, mode0, reqid) +pfkey_setsadbxsa2(buf, lim, mode0, reqid) caddr_t buf; + caddr_t lim; u_int32_t mode0; u_int32_t reqid; { @@ -1584,6 +2095,9 @@ pfkey_setsadbxsa2(buf, mode0, reqid) p = (struct sadb_x_sa2 *)buf; len = sizeof(struct sadb_x_sa2); + if (buf + len > lim) + return NULL; + memset(p, 0, len); p->sadb_x_sa2_len = PFKEY_UNIT64(len); p->sadb_x_sa2_exttype = SADB_X_EXT_SA2; @@ -1592,4 +2106,3 @@ pfkey_setsadbxsa2(buf, mode0, reqid) return(buf + len); } - diff --git a/lib/libipsec/pfkey_dump.c b/lib/libipsec/pfkey_dump.c index 6408651..6c74bcd 100644 --- a/lib/libipsec/pfkey_dump.c +++ b/lib/libipsec/pfkey_dump.c @@ -1,5 +1,5 @@ /* $FreeBSD$ */ -/* $KAME: pfkey_dump.c,v 1.19 2000/06/10 06:47:11 sakane Exp $ */ +/* $KAME: pfkey_dump.c,v 1.27 2001/03/12 09:03:38 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. @@ -52,6 +52,29 @@ #include "ipsec_strerror.h" #include "libpfkey.h" +/* cope with old kame headers - ugly */ +#ifndef SADB_X_AALG_MD5 +#define SADB_X_AALG_MD5 SADB_AALG_MD5 +#endif +#ifndef SADB_X_AALG_SHA +#define SADB_X_AALG_SHA SADB_AALG_SHA +#endif +#ifndef SADB_X_AALG_NULL +#define SADB_X_AALG_NULL SADB_AALG_NULL +#endif + +#ifndef SADB_X_EALG_BLOWFISHCBC +#define SADB_X_EALG_BLOWFISHCBC SADB_EALG_BLOWFISHCBC +#endif +#ifndef SADB_X_EALG_CAST128CBC +#define SADB_X_EALG_CAST128CBC SADB_EALG_CAST128CBC +#endif +#ifndef SADB_X_EALG_RC5CBC +#ifdef SADB_EALG_RC5CBC +#define SADB_X_EALG_RC5CBC SADB_EALG_RC5CBC +#endif +#endif + #define GETMSGSTR(str, num) \ do { \ if (sizeof((str)[0]) == 0 \ @@ -63,15 +86,33 @@ do { \ printf("%s ", (str)[(num)]); \ } while (0) +#define GETMSGV2S(v2s, num) \ +do { \ + struct val2str *p; \ + for (p = (v2s); p && p->str; p++) { \ + if (p->val == (num)) \ + break; \ + } \ + if (p && p->str) \ + printf("%s ", p->str); \ + else \ + printf("%d ", (num)); \ +} while (0) + static char *str_ipaddr __P((struct sockaddr *)); static char *str_prefport __P((u_int, u_int, u_int)); static char *str_time __P((time_t)); static void str_lifetime_byte __P((struct sadb_lifetime *, char *)); +struct val2str { + int val; + const char *str; +}; + /* * Must to be re-written about following strings. */ -static char *_str_satype[] = { +static char *str_satype[] = { "unspec", "unknown", "ah", @@ -84,13 +125,13 @@ static char *_str_satype[] = { "ipcomp", }; -static char *_str_mode[] = { +static char *str_mode[] = { "any", "transport", "tunnel", }; -static char *_str_upper[] = { +static char *str_upper[] = { /*0*/ "ip", "icmp", "igmp", "ggp", "ip4", "", "tcp", "", "egp", "", /*10*/ "", "", "", "", "", @@ -106,37 +147,57 @@ static char *_str_upper[] = { /*60*/ "dst6", }; -static char *_str_state[] = { +static char *str_state[] = { "larval", "mature", "dying", "dead", }; -static char *_str_alg_auth[] = { - "none", - "hmac-md5", - "hmac-sha1", - "md5", - "sha", - "null", +static struct val2str str_alg_auth[] = { + { SADB_AALG_NONE, "none", }, + { SADB_AALG_MD5HMAC, "hmac-md5", }, + { SADB_AALG_SHA1HMAC, "hmac-sha1", }, + { SADB_X_AALG_MD5, "md5", }, + { SADB_X_AALG_SHA, "sha", }, + { SADB_X_AALG_NULL, "null", }, +#ifdef SADB_X_AALG_SHA2_256 + { SADB_X_AALG_SHA2_256, "hmac-sha2-256", }, +#endif +#ifdef SADB_X_AALG_SHA2_384 + { SADB_X_AALG_SHA2_384, "hmac-sha2-384", }, +#endif +#ifdef SADB_X_AALG_SHA2_512 + { SADB_X_AALG_SHA2_512, "hmac-sha2-512", }, +#endif + { -1, NULL, }, }; -static char *_str_alg_enc[] = { - "none", - "des-cbc", - "3des-cbc", - "null", - "blowfish-cbc", - "cast128-cbc", - "rc5-cbc", +static struct val2str str_alg_enc[] = { + { SADB_EALG_NONE, "none", }, + { SADB_EALG_DESCBC, "des-cbc", }, + { SADB_EALG_3DESCBC, "3des-cbc", }, + { SADB_EALG_NULL, "null", }, +#ifdef SADB_X_EALG_RC5CBC + { SADB_X_EALG_RC5CBC, "rc5-cbc", }, +#endif + { SADB_X_EALG_CAST128CBC, "cast128-cbc", }, + { SADB_X_EALG_BLOWFISHCBC, "blowfish-cbc", }, +#ifdef SADB_X_EALG_RIJNDAELCBC + { SADB_X_EALG_RIJNDAELCBC, "rijndael-cbc", }, +#endif +#ifdef SADB_X_EALG_TWOFISHCBC + { SADB_X_EALG_TWOFISHCBC, "twofish-cbc", }, +#endif + { -1, NULL, }, }; -static char *_str_alg_comp[] = { - "none", - "oui", - "deflate", - "lzs", +static struct val2str str_alg_comp[] = { + { SADB_X_CALG_NONE, "none", }, + { SADB_X_CALG_OUI, "oui", }, + { SADB_X_CALG_DEFLATE, "deflate", }, + { SADB_X_CALG_LZS, "lzs", }, + { -1, NULL, }, }; /* @@ -204,10 +265,10 @@ pfkey_sadump(m) } printf("\n\t"); - GETMSGSTR(_str_satype, m->sadb_msg_satype); + GETMSGSTR(str_satype, m->sadb_msg_satype); printf("mode="); - GETMSGSTR(_str_mode, m_sa2->sadb_x_sa2_mode); + GETMSGSTR(str_mode, m_sa2->sadb_x_sa2_mode); printf("spi=%u(0x%08x) reqid=%u(0x%08x)\n", (u_int32_t)ntohl(m_sa->sadb_sa_spi), @@ -218,11 +279,11 @@ pfkey_sadump(m) /* encryption key */ if (m->sadb_msg_satype == SADB_X_SATYPE_IPCOMP) { printf("\tC: "); - GETMSGSTR(_str_alg_comp, m_sa->sadb_sa_encrypt); + GETMSGV2S(str_alg_comp, m_sa->sadb_sa_encrypt); } else if (m->sadb_msg_satype == SADB_SATYPE_ESP) { if (m_enc != NULL) { printf("\tE: "); - GETMSGSTR(_str_alg_enc, m_sa->sadb_sa_encrypt); + GETMSGV2S(str_alg_enc, m_sa->sadb_sa_encrypt); ipsec_hexdump((caddr_t)m_enc + sizeof(*m_enc), m_enc->sadb_key_bits / 8); printf("\n"); @@ -232,7 +293,7 @@ pfkey_sadump(m) /* authentication key */ if (m_auth != NULL) { printf("\tA: "); - GETMSGSTR(_str_alg_auth, m_sa->sadb_sa_auth); + GETMSGV2S(str_alg_auth, m_sa->sadb_sa_auth); ipsec_hexdump((caddr_t)m_auth + sizeof(*m_auth), m_auth->sadb_key_bits / 8); printf("\n"); @@ -245,7 +306,7 @@ pfkey_sadump(m) /* state */ printf("state="); - GETMSGSTR(_str_state, m_sa->sadb_sa_state); + GETMSGSTR(str_state, m_sa->sadb_sa_state); printf("seq=%lu pid=%lu\n", (u_long)m->sadb_msg_seq, @@ -307,6 +368,7 @@ pfkey_spdump(m) caddr_t mhp[SADB_EXT_MAX + 1]; struct sadb_address *m_saddr, *m_daddr; struct sadb_x_policy *m_xpl; + struct sadb_lifetime *m_lft = NULL; struct sockaddr *sa; u_int16_t port; @@ -323,6 +385,7 @@ pfkey_spdump(m) m_saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]; m_daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]; m_xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY]; + m_lft = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_HARD]; /* source address */ if (m_saddr == NULL) { @@ -378,7 +441,7 @@ pfkey_spdump(m) if (m_saddr->sadb_address_proto == IPSEC_ULPROTO_ANY) printf("any"); else - GETMSGSTR(_str_upper, m_saddr->sadb_address_proto); + GETMSGSTR(str_upper, m_saddr->sadb_address_proto); /* policy */ { @@ -395,6 +458,13 @@ pfkey_spdump(m) free(d_xpl); } + /* lifetime */ + if (m_lft) { + printf("\tlifetime:%lu validtime:%lu\n", + (u_long)m_lft->sadb_lifetime_addtime, + (u_long)m_lft->sadb_lifetime_usetime); + } + printf("\tspid=%ld seq=%ld pid=%ld\n", (u_long)m_xpl->sadb_x_policy_id, (u_long)m->sadb_msg_seq, diff --git a/lib/libipsec/policy_token.l b/lib/libipsec/policy_token.l index 81d632b..91c89dc 100644 --- a/lib/libipsec/policy_token.l +++ b/lib/libipsec/policy_token.l @@ -1,5 +1,5 @@ /* $FreeBSD$ */ -/* $KAME: policy_token.l,v 1.9 2000/05/07 05:25:03 itojun Exp $ */ +/* $KAME: policy_token.l,v 1.11 2000/12/01 10:08:29 sakane Exp $ */ /* * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. @@ -37,7 +37,6 @@ #include #include #include -#include #include #include @@ -58,6 +57,7 @@ int yylex __P((void)); %} %option noyywrap +%option nounput /* common section */ nl \n diff --git a/lib/libipsec/test-policy.c b/lib/libipsec/test-policy.c index 5a4faf5..960de20 100644 --- a/lib/libipsec/test-policy.c +++ b/lib/libipsec/test-policy.c @@ -1,5 +1,5 @@ /* $FreeBSD$ */ -/* $KAME: test-policy.c,v 1.13 2000/05/07 05:25:03 itojun Exp $ */ +/* $KAME: test-policy.c,v 1.14 2000/12/27 11:38:11 sakane Exp $ */ /* * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. @@ -46,6 +46,8 @@ #include #include +#include "libpfkey.h" + struct req_t { int result; /* expected result; 0:ok 1:ng */ char *str; @@ -111,9 +113,9 @@ test1() result = test1sub1(&reqs[i]); if (result == 0 && reqs[i].result == 1) { - errx(1, "ERROR: expecting failure.\n"); + warnx("ERROR: expecting failure.\n"); } else if (result == 1 && reqs[i].result == 0) { - errx(1, "ERROR: expecting success.\n"); + warnx("ERROR: expecting success.\n"); } } @@ -245,7 +247,8 @@ test2() errx(1, "ERROR: %s\n", ipsec_strerror()); m = pfkey_recv(so); free(m); - + +#if 0 printf("spdsetidx()\n"); if (pfkey_send_spdsetidx(so, (struct sockaddr *)addr, 128, (struct sockaddr *)addr, 128, @@ -262,6 +265,8 @@ test2() m = pfkey_recv(so); free(m); + sleep(4); + printf("spddelete()\n"); if (pfkey_send_spddelete(so, (struct sockaddr *)addr, 128, (struct sockaddr *)addr, 128, @@ -283,19 +288,31 @@ test2() m = pfkey_recv(so); free(m); + sleep(4); + printf("spddelete2()\n"); if (pfkey_send_spddelete2(so, spid) < 0) errx(1, "ERROR: %s\n", ipsec_strerror()); m = pfkey_recv(so); free(m); +#endif + printf("spdadd() with lifetime's 10(s)\n"); + if (pfkey_send_spdadd2(so, (struct sockaddr *)addr, 128, + (struct sockaddr *)addr, 128, + 255, 0, 10, sp2, splen2, 0) < 0) + errx(1, "ERROR: %s\n", ipsec_strerror()); + spid = test2sub(so); + +#if 0 /* expecting failure */ printf("spdupdate()\n"); if (pfkey_send_spdupdate(so, (struct sockaddr *)addr, 128, (struct sockaddr *)addr, 128, 255, sp2, splen2, 0) == 0) { - errx(1, "ERROR: expecting failure.\n"); + warnx("ERROR: expecting failure.\n"); } +#endif return 0; } -- cgit v1.1