From 5963521296680c2aeb40baeb72459dffc14cd996 Mon Sep 17 00:00:00 2001 From: Stephen Early Date: Mon, 24 Sep 2001 00:48:00 +0100 Subject: [PATCH] Import release 0.07 --- INSTALL | 4 ++ Makefile.in | 8 +++- config.h.bot | 10 +++- config.h.in | 39 ++++++---------- configure | 74 ++++++++++++++++++++++------- configure.in | 4 ++ example.conf | 1 + netlink.c | 15 +++--- secnet.c | 2 +- secnet.h | 3 +- site.c | 130 ++++++++++++++++++++++++++------------------------- transform.c | 66 +++++++++++++++++++++++--- unaligned.h | 42 +++++++++++++++++ util.c | 5 +- 14 files changed, 274 insertions(+), 129 deletions(-) create mode 100644 unaligned.h diff --git a/INSTALL b/INSTALL index 2001fa8..b384b9c 100644 --- a/INSTALL +++ b/INSTALL @@ -4,6 +4,8 @@ USE AT YOUR OWN RISK. THIS IS ALPHA TEST SOFTWARE. I DO NOT GUARANTEE THAT THERE WILL BE PROTOCOL COMPATIBILITY BETWEEN DIFFERENT VERSIONS. +PROTOCOL COMPATIBILITY WAS BROKEN BETWEEN secnet-0.06 AND secnet-0.07 + * Preparation ** System software support @@ -11,6 +13,8 @@ VERSIONS. Ensure that you have libgmp2-dev and adns installed (and bison and flex, and for that matter gcc...). +[On BSD install /usr/ports/devel/bison and /usr/ports/devel/libgnugetopt] + If you intend to configure secnet to obtain packets from the kernel through userv-ipif, install and configure userv-ipif. It is part of userv-utils, available from ftp.chiark.greenend.org.uk in diff --git a/Makefile.in b/Makefile.in index 2dea738..a7d9df8 100644 --- a/Makefile.in +++ b/Makefile.in @@ -18,7 +18,7 @@ .PHONY: all clean realclean dist install PACKAGE:=secnet -VERSION:=0.06 +VERSION:=0.07 @SET_MAKE@ @@ -53,7 +53,7 @@ DISTFILES:=COPYING INSTALL Makefile.in NOTES README TODO conffile.c \ example-sites-file example.conf install.sh linux md5.c md5.h \ modules.c modules.h netlink.c random.c resolver.c rsa.c \ secnet.c secnet.h serpent.c serpent.h serpentsboxes.h \ - site.c transform.c udp.c util.c util.h + site.c transform.c udp.c unaligned.h util.c util.h %.c: %.y @@ -72,6 +72,9 @@ Makefile: Makefile.in config.status config.status: configure $(srcdir)/configure --no-create +config.h: config.h.in config.status + $(SHELL) config.status + $(OBJECTS): config.h secnet.h util.h conffile.o conffile.tab.o conffile.yy.o: conffile.h conffile_internal.h secnet.c: conffile.h @@ -79,6 +82,7 @@ md5.o: md5.h serpent.o transform.o: serpent.h serpent.o: serpentsboxes.h conffile.o: modules.h +site.c util.c: unaligned.h secnet: $(OBJECTS) diff --git a/config.h.bot b/config.h.bot index ff6ecda..47befcb 100644 --- a/config.h.bot +++ b/config.h.bot @@ -2,8 +2,14 @@ /* These are from config.h.bot, pasted onto the end of config.h.in. */ -#ifdef HAVE_SYS_CDEFS_H -#include +#ifdef HAVE_INTTYPES_H +#include +#else +#ifdef HAVE_STDINT_H +#include +#else +#error you must define uint32_t, uint16_t etc. +#endif #endif #endif /* _CONFIG_H */ diff --git a/config.h.in b/config.h.in index 5d31bab..c52fd8c 100644 --- a/config.h.in +++ b/config.h.in @@ -1,27 +1,4 @@ /* config.h.in. Generated automatically from configure.in by autoheader. */ -/*************************************************************************** - * - * Part II Project, "A secure, private IP network" - * Stephen Early - * - * - * $RCSfile$ - * - * Description: - * - * Copyright: (C) Stephen Early 1995 - * - * $Revision$ - * - * $Date$ - * - * $State$ - * - ***************************************************************************/ - -/* $Log$ - */ - #ifndef _CONFIG_H #define _CONFIG_H @@ -33,9 +10,15 @@ byte first (like Motorola and SPARC, unlike Intel and VAX). */ #undef WORDS_BIGENDIAN +/* Define if you have the header file. */ +#undef HAVE_INTTYPES_H + /* Define if you have the header file. */ #undef HAVE_LINUX_IF_H +/* Define if you have the header file. */ +#undef HAVE_STDINT_H + /* Define if you have the adns library (-ladns). */ #undef HAVE_LIBADNS @@ -48,8 +31,14 @@ /* These are from config.h.bot, pasted onto the end of config.h.in. */ -#ifdef HAVE_SYS_CDEFS_H -#include +#ifdef HAVE_INTTYPES_H +#include +#else +#ifdef HAVE_STDINT_H +#include +#else +#error you must define uint32_t, uint16_t etc. +#endif #endif #endif /* _CONFIG_H */ diff --git a/configure b/configure index 4ca2072..3bcb172 100755 --- a/configure +++ b/configure @@ -1084,7 +1084,7 @@ EOF fi -for ac_hdr in linux/if.h +for ac_hdr in stdint.h inttypes.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 @@ -1124,15 +1124,55 @@ else fi done +for ac_hdr in linux/if.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:1132: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1142: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6 -echo "configure:1129: checking whether byte ordering is bigendian" >&5 +echo "configure:1169: checking whether byte ordering is bigendian" >&5 if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_cv_c_bigendian=unknown # See if sys/param.h defines the BYTE_ORDER macro. cat > conftest.$ac_ext < #include @@ -1143,11 +1183,11 @@ int main() { #endif ; return 0; } EOF -if { (eval echo configure:1147: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1187: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* # It does; now see whether it defined to BIG_ENDIAN or not. cat > conftest.$ac_ext < #include @@ -1158,7 +1198,7 @@ int main() { #endif ; return 0; } EOF -if { (eval echo configure:1162: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1202: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_bigendian=yes else @@ -1178,7 +1218,7 @@ if test "$cross_compiling" = yes; then { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:1235: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_c_bigendian=no else @@ -1216,7 +1256,7 @@ fi echo $ac_n "checking for mpz_init_set_str in -lgmp2""... $ac_c" 1>&6 -echo "configure:1220: checking for mpz_init_set_str in -lgmp2" >&5 +echo "configure:1260: checking for mpz_init_set_str in -lgmp2" >&5 ac_lib_var=`echo gmp2'_'mpz_init_set_str | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1224,7 +1264,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lgmp2 $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1279: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -1263,7 +1303,7 @@ else fi echo $ac_n "checking for yywrap in -lfl""... $ac_c" 1>&6 -echo "configure:1267: checking for yywrap in -lfl" >&5 +echo "configure:1307: checking for yywrap in -lfl" >&5 ac_lib_var=`echo fl'_'yywrap | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1271,7 +1311,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lfl $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1326: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -1310,7 +1350,7 @@ else fi echo $ac_n "checking for adns_init in -ladns""... $ac_c" 1>&6 -echo "configure:1314: checking for adns_init in -ladns" >&5 +echo "configure:1354: checking for adns_init in -ladns" >&5 ac_lib_var=`echo adns'_'adns_init | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1318,7 +1358,7 @@ else ac_save_LIBS="$LIBS" LIBS="-ladns $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1373: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else diff --git a/configure.in b/configure.in index cb47835..9bb9248 100644 --- a/configure.in +++ b/configure.in @@ -12,11 +12,15 @@ AC_PROG_CC AC_PROG_INSTALL AC_PATH_PROG(RM,rm) AC_STDC_HEADERS +AC_CHECK_HEADERS(stdint.h inttypes.h) AC_CHECK_HEADERS(linux/if.h) AC_C_BIGENDIAN +AC_CHECK_LIB(gmp,mpz_init_set_str) AC_CHECK_LIB(gmp2,mpz_init_set_str) AC_CHECK_LIB(fl,yywrap) AC_CHECK_LIB(adns,adns_init) +AC_CHECK_LIB(getopt,getopt_long) +AC_CHECK_LIB(gnugetopt,getopt_long) AC_OUTPUT(Makefile) diff --git a/example.conf b/example.conf index 96a8433..e3f6011 100644 --- a/example.conf +++ b/example.conf @@ -46,6 +46,7 @@ system { # wait-time wait between unsuccessful key setup attempts, in ms # Use the universal TUN/TAP driver to get packets to and from the kernel +# (use tun-old if you are not on Linux-2.4) netlink tun { name "netlink-tun"; # Printed in log messages from this netlink # interface "tun0"; # You may set your own interface name if you wish; diff --git a/netlink.c b/netlink.c index 0b1ebe4..9f4626a 100644 --- a/netlink.c +++ b/netlink.c @@ -18,8 +18,6 @@ packet to the kernel we check that the tunnel it came over could reasonably have produced it. */ -/* XXX now implement TUN. Kernel needs recompiling. */ - #include #include #include @@ -961,8 +959,10 @@ static list_t *tun_apply(closure_t *self, struct cloc loc, dict_t *context, st->device_path=dict_read_string(dict,"device",False,"tun-netlink",loc); st->interface_name=dict_read_string(dict,"interface",False, "tun-netlink",loc); - st->ifconfig_path=dict_read_string(dict,"device",False,"tun-netlink",loc); - st->route_path=dict_read_string(dict,"device",False,"tun-netlink",loc); + st->ifconfig_path=dict_read_string(dict,"ifconfig-path", + False,"tun-netlink",loc); + st->route_path=dict_read_string(dict,"route-path", + False,"tun-netlink",loc); if (!st->device_path) st->device_path="/dev/net/tun"; if (!st->ifconfig_path) st->ifconfig_path="ifconfig"; @@ -1026,8 +1026,9 @@ static list_t *tun_old_apply(closure_t *self, struct cloc loc, dict_t *context, "tun-netlink",loc); search_for_if=dict_read_bool(dict,"interface-search",False,"tun-netlink", loc,st->device_path==NULL); - st->ifconfig_path=dict_read_string(dict,"device",False,"tun-netlink",loc); - st->route_path=dict_read_string(dict,"device",False,"tun-netlink",loc); + st->ifconfig_path=dict_read_string(dict,"ifconfig-path",False, + "tun-netlink",loc); + st->route_path=dict_read_string(dict,"route-path",False,"tun-netlink",loc); if (!st->device_path) st->device_path="/dev/tun"; if (!st->ifconfig_path) st->ifconfig_path="ifconfig"; @@ -1056,7 +1057,7 @@ static list_t *tun_old_apply(closure_t *self, struct cloc loc, dict_t *context, sprintf(st->interface_name,"tun%d",i); Message(M_INFO,"%s: allocated network interface %s " "through %s\n",st->nl.name,st->interface_name,dname); - continue; + break; } } if (st->fd==-1) { diff --git a/secnet.c b/secnet.c index 1cb38db..b1599e1 100644 --- a/secnet.c +++ b/secnet.c @@ -11,6 +11,7 @@ extern char version[]; #include #include #include +#include #include #include #include @@ -18,7 +19,6 @@ extern char version[]; #include #include #include -#include #include "secnet.h" #include "util.h" diff --git a/secnet.h b/secnet.h index db3bee2..9274059 100644 --- a/secnet.h +++ b/secnet.h @@ -3,13 +3,12 @@ #ifndef secnet_h #define secnet_h +#include "config.h" #include -#include #include #include #include #include -#include "config.h" typedef char *string_t; diff --git a/site.c b/site.c index 1a664ce..4ca53cd 100644 --- a/site.c +++ b/site.c @@ -5,12 +5,13 @@ #include "secnet.h" #include "util.h" +#include "unaligned.h" #define SETUP_BUFFER_LEN 2048 -#define DEFAULT_KEY_LIFETIME 15000 +#define DEFAULT_KEY_LIFETIME 3600000 #define DEFAULT_SETUP_RETRIES 5 -#define DEFAULT_SETUP_TIMEOUT 500 +#define DEFAULT_SETUP_TIMEOUT 1000 #define DEFAULT_WAIT_TIME 10000 /* Each site can be in one of several possible states. */ @@ -94,7 +95,7 @@ static string_t state_name(uint32_t state) #define LOG_SETUP_TIMEOUT 0x00000004 #define LOG_ACTIVATE_KEY 0x00000008 #define LOG_TIMEOUT_KEY 0x00000010 -#define LOG_SECURITY 0x00000020 +#define LOG_SEC 0x00000020 #define LOG_STATE 0x00000040 #define LOG_DROP 0x00000080 #define LOG_DUMP 0x00000100 @@ -186,7 +187,7 @@ static void enter_state_wait(struct site *st); #define CHECK_EMPTY(b) do { if ((b)->size!=0) return False; } while(0) #define CHECK_TYPE(b,t) do { uint32_t type; \ CHECK_AVAIL((b),4); \ - type=*(uint32_t *)buf_unprepend((b),4); \ + type=buf_unprepend_uint32((b)); \ if (type!=(t)) return False; } while(0) struct msg { @@ -217,10 +218,10 @@ static bool_t generate_msg(struct site *st, uint32_t type, string_t what) st->retries=st->setup_retries; BUF_ALLOC(&st->buffer,what); buffer_init(&st->buffer,0); - *(uint32_t *)buf_append(&st->buffer,4)= - (type==LABEL_MSG1?0:st->setup_session_id); - *(uint32_t *)buf_append(&st->buffer,4)=(uint32_t)st; - *(uint32_t *)buf_append(&st->buffer,4)=type; + buf_append_uint32(&st->buffer, + (type==LABEL_MSG1?0:st->setup_session_id)); + buf_append_uint32(&st->buffer,(uint32_t)st); + buf_append_uint32(&st->buffer,type); buf_append_string(&st->buffer,st->localname); buf_append_string(&st->buffer,st->remotename); memcpy(buf_append(&st->buffer,NONCELEN),st->localN,NONCELEN); @@ -244,16 +245,16 @@ static bool_t unpick_msg(struct site *st, uint32_t type, { m->hashstart=msg->start; CHECK_AVAIL(msg,4); - m->dest=*(uint32_t *)buf_unprepend(msg,4); + m->dest=buf_unprepend_uint32(msg); CHECK_AVAIL(msg,4); - m->source=*(uint32_t *)buf_unprepend(msg,4); + m->source=buf_unprepend_uint32(msg); CHECK_TYPE(msg,type); CHECK_AVAIL(msg,2); - m->remlen=ntohs(*(uint16_t *)buf_unprepend(msg,2)); + m->remlen=buf_unprepend_uint16(msg); CHECK_AVAIL(msg,m->remlen); m->remote=buf_unprepend(msg,m->remlen); CHECK_AVAIL(msg,2); - m->loclen=ntohs(*(uint16_t *)buf_unprepend(msg,2)); + m->loclen=buf_unprepend_uint16(msg); CHECK_AVAIL(msg,m->loclen); m->local=buf_unprepend(msg,m->loclen); CHECK_AVAIL(msg,NONCELEN); @@ -269,12 +270,12 @@ static bool_t unpick_msg(struct site *st, uint32_t type, return True; } CHECK_AVAIL(msg,2); - m->pklen=ntohs(*(uint16_t *)buf_unprepend(msg,2)); + m->pklen=buf_unprepend_uint16(msg); CHECK_AVAIL(msg,m->pklen); m->pk=buf_unprepend(msg,m->pklen); m->hashlen=msg->start-m->hashstart; CHECK_AVAIL(msg,2); - m->siglen=ntohs(*(uint16_t *)buf_unprepend(msg,2)); + m->siglen=buf_unprepend_uint16(msg); CHECK_AVAIL(msg,m->siglen); m->sig=buf_unprepend(msg,m->siglen); CHECK_EMPTY(msg); @@ -322,15 +323,15 @@ static bool_t process_msg2(struct site *st, struct buffer_if *msg2, /* Check that the site names and our nonce have been sent back correctly, and then store our peer's nonce. */ if (memcmp(m.remote,st->remotename,strlen(st->remotename)!=0)) { - slog(st,LOG_SECURITY,"msg2: bad B (remote site name)"); + slog(st,LOG_SEC,"msg2: bad B (remote site name)"); return False; } if (memcmp(m.local,st->localname,strlen(st->localname)!=0)) { - slog(st,LOG_SECURITY,"msg2: bad A (local site name)"); + slog(st,LOG_SEC,"msg2: bad A (local site name)"); return False; } if (memcmp(m.nL,st->localN,NONCELEN)!=0) { - slog(st,LOG_SECURITY,"msg2: bad nA (locally generated nonce)"); + slog(st,LOG_SEC,"msg2: bad nA (locally generated nonce)"); return False; } st->setup_session_id=m.source; @@ -358,19 +359,19 @@ static bool_t process_msg3(struct site *st, struct buffer_if *msg3, /* Check that the site names and nonces have been sent back correctly */ if (memcmp(m.remote,st->remotename,strlen(st->remotename)!=0)) { - slog(st,LOG_SECURITY,"msg3: bad A (remote site name)"); + slog(st,LOG_SEC,"msg3: bad A (remote site name)"); return False; } if (memcmp(m.local,st->localname,strlen(st->localname)!=0)) { - slog(st,LOG_SECURITY,"msg3: bad B (local site name)"); + slog(st,LOG_SEC,"msg3: bad B (local site name)"); return False; } if (memcmp(m.nR,st->remoteN,NONCELEN)!=0) { - slog(st,LOG_SECURITY,"msg3: bad nA (remotely generated nonce)"); + slog(st,LOG_SEC,"msg3: bad nA (remotely generated nonce)"); return False; } if (memcmp(m.nL,st->localN,NONCELEN)!=0) { - slog(st,LOG_SECURITY,"msg3: bad nB (locally generated nonce)"); + slog(st,LOG_SEC,"msg3: bad nB (locally generated nonce)"); return False; } @@ -381,7 +382,7 @@ static bool_t process_msg3(struct site *st, struct buffer_if *msg3, /* Terminate signature with a '0' - cheating, but should be ok */ m.sig[m.siglen]=0; if (!st->pubkey->check(st->pubkey->st,hash,st->hash->len,m.sig)) { - slog(st,LOG_SECURITY,"msg3 signature failed check!"); + slog(st,LOG_SEC,"msg3 signature failed check!"); return False; } @@ -420,19 +421,19 @@ static bool_t process_msg4(struct site *st, struct buffer_if *msg4, /* Check that the site names and nonces have been sent back correctly */ if (memcmp(m.remote,st->remotename,strlen(st->remotename)!=0)) { - slog(st,LOG_SECURITY,"msg4: bad B (remote site name)"); + slog(st,LOG_SEC,"msg4: bad B (remote site name)"); return False; } if (memcmp(m.local,st->localname,strlen(st->localname)!=0)) { - slog(st,LOG_SECURITY,"msg4: bad A (local site name)"); + slog(st,LOG_SEC,"msg4: bad A (local site name)"); return False; } if (memcmp(m.nR,st->remoteN,NONCELEN)!=0) { - slog(st,LOG_SECURITY,"msg4: bad nB (remotely generated nonce)"); + slog(st,LOG_SEC,"msg4: bad nB (remotely generated nonce)"); return False; } if (memcmp(m.nL,st->localN,NONCELEN)!=0) { - slog(st,LOG_SECURITY,"msg4: bad nA (locally generated nonce)"); + slog(st,LOG_SEC,"msg4: bad nA (locally generated nonce)"); return False; } @@ -443,7 +444,7 @@ static bool_t process_msg4(struct site *st, struct buffer_if *msg4, /* Terminate signature with a '0' - cheating, but should be ok */ m.sig[m.siglen]=0; if (!st->pubkey->check(st->pubkey->st,hash,st->hash->len,m.sig)) { - slog(st,LOG_SECURITY,"msg4 signature failed check!"); + slog(st,LOG_SEC,"msg4 signature failed check!"); return False; } @@ -466,12 +467,12 @@ static bool_t generate_msg5(struct site *st) BUF_ALLOC(&st->buffer,"site:MSG5"); /* We are going to add three words to the transformed message */ buffer_init(&st->buffer,st->transform->max_start_pad+(4*3)); - *(uint32_t *)buf_append(&st->buffer,4)=LABEL_MSG5; + buf_append_uint32(&st->buffer,LABEL_MSG5); st->new_transform->forwards(st->new_transform->st,&st->buffer, &transform_err); - *(uint32_t *)buf_prepend(&st->buffer,4)=LABEL_MSG5; - *(uint32_t *)buf_prepend(&st->buffer,4)=(uint32_t)st; - *(uint32_t *)buf_prepend(&st->buffer,4)=st->setup_session_id; + buf_prepend_uint32(&st->buffer,LABEL_MSG5); + buf_prepend_uint32(&st->buffer,(uint32_t)st); + buf_prepend_uint32(&st->buffer,st->setup_session_id); st->retries=st->setup_retries; return True; @@ -487,11 +488,11 @@ static bool_t unpick_msg0(struct site *st, struct buffer_if *msg0, struct msg0 *m) { CHECK_AVAIL(msg0,4); - m->dest=*(uint32_t *)buf_unprepend(msg0,4); + m->dest=buf_unprepend_uint32(msg0); CHECK_AVAIL(msg0,4); - m->source=*(uint32_t *)buf_unprepend(msg0,4); + m->source=buf_unprepend_uint32(msg0); CHECK_AVAIL(msg0,4); - m->type=*(uint32_t *)buf_unprepend(msg0,4); + m->type=buf_unprepend_uint32(msg0); return True; /* Leaves transformed part of buffer untouched */ } @@ -507,13 +508,13 @@ static bool_t process_msg5(struct site *st, struct buffer_if *msg5, if (st->new_transform->reverse(st->new_transform->st, msg5,&transform_err)) { /* There's a problem */ - slog(st,LOG_SECURITY,"process_msg5: transform: %s",transform_err); + slog(st,LOG_SEC,"process_msg5: transform: %s",transform_err); return False; } /* Buffer should now contain untransformed PING packet data */ CHECK_AVAIL(msg5,4); - if ((*(uint32_t *)buf_unprepend(msg5,4))!=LABEL_MSG5) { - slog(st,LOG_SECURITY,"MSG5/PING packet contained invalid data"); + if (buf_unprepend_uint32(msg5)!=LABEL_MSG5) { + slog(st,LOG_SEC,"MSG5/PING packet contained invalid data"); return False; } CHECK_EMPTY(msg5); @@ -527,12 +528,12 @@ static bool_t generate_msg6(struct site *st) BUF_ALLOC(&st->buffer,"site:MSG6"); /* We are going to add three words to the transformed message */ buffer_init(&st->buffer,st->transform->max_start_pad+(4*3)); - *(uint32_t *)buf_append(&st->buffer,4)=LABEL_MSG6; + buf_append_uint32(&st->buffer,LABEL_MSG6); st->new_transform->forwards(st->new_transform->st,&st->buffer, &transform_err); - *(uint32_t *)buf_prepend(&st->buffer,4)=LABEL_MSG6; - *(uint32_t *)buf_prepend(&st->buffer,4)=(uint32_t)st; - *(uint32_t *)buf_prepend(&st->buffer,4)=st->setup_session_id; + buf_prepend_uint32(&st->buffer,LABEL_MSG6); + buf_prepend_uint32(&st->buffer,(uint32_t)st); + buf_prepend_uint32(&st->buffer,st->setup_session_id); st->retries=1; /* Peer will retransmit MSG5 if necessary */ return True; @@ -549,13 +550,13 @@ static bool_t process_msg6(struct site *st, struct buffer_if *msg6, if (st->new_transform->reverse(st->new_transform->st, msg6,&transform_err)) { /* There's a problem */ - slog(st,LOG_SECURITY,"process_msg6: transform: %s",transform_err); + slog(st,LOG_SEC,"process_msg6: transform: %s",transform_err); return False; } /* Buffer should now contain untransformed PING packet data */ CHECK_AVAIL(msg6,4); - if ((*(uint32_t *)buf_unprepend(msg6,4))!=LABEL_MSG6) { - slog(st,LOG_SECURITY,"MSG6/PONG packet contained invalid data"); + if (buf_unprepend_uint32(msg6)!=LABEL_MSG6) { + slog(st,LOG_SEC,"MSG6/PONG packet contained invalid data"); return False; } CHECK_EMPTY(msg6); @@ -584,11 +585,11 @@ static bool_t process_msg0(struct site *st, struct buffer_if *msg0, if (st->current_transform->reverse(st->current_transform->st, msg0,&transform_err)) { /* There's a problem */ - slog(st,LOG_SECURITY,"transform: %s",transform_err); + slog(st,LOG_SEC,"transform: %s",transform_err); return False; } CHECK_AVAIL(msg0,4); - type=*(uint32_t *)buf_unprepend(msg0,4); + type=buf_unprepend_uint32(msg0); switch(type) { case LABEL_MSG9: /* Deliver to netlink layer */ @@ -596,7 +597,7 @@ static bool_t process_msg0(struct site *st, struct buffer_if *msg0, return True; break; default: - slog(st,LOG_SECURITY,"incoming message of type %08x (unknown)",type); + slog(st,LOG_SEC,"incoming message of type %08x (unknown)",type); break; } return False; @@ -605,9 +606,9 @@ static bool_t process_msg0(struct site *st, struct buffer_if *msg0, static void dump_packet(struct site *st, struct buffer_if *buf, struct sockaddr_in *addr, bool_t incoming) { - uint32_t dest=*(uint32_t *)buf->start; - uint32_t source=*(uint32_t *)(buf->start+4); - uint32_t msgtype=*(uint32_t *)(buf->start+8); + uint32_t dest=ntohl(*(uint32_t *)buf->start); + uint32_t source=ntohl(*(uint32_t *)(buf->start+4)); + uint32_t msgtype=ntohl(*(uint32_t *)(buf->start+8)); if (st->log_events & LOG_DUMP) log(st->log,0,"(%s,%s): %s: %08x<-%08x: %08x:", @@ -887,12 +888,12 @@ static void site_outgoing(void *sst, void *cid, struct buffer_if *buf) a valid key and a valid address to send it to. */ if (st->current_valid && st->peer_valid) { /* Transform it and send it */ - *(uint32_t *)buf_prepend(buf,4)=LABEL_MSG9; + buf_prepend_uint32(buf,LABEL_MSG9); st->current_transform->forwards(st->current_transform->st, buf, &transform_err); - *(uint32_t *)buf_prepend(buf,4)=LABEL_MSG0; - *(uint32_t *)buf_prepend(buf,4)=(uint32_t)st; - *(uint32_t *)buf_prepend(buf,4)=st->remote_session_id; + buf_prepend_uint32(buf,LABEL_MSG0); + buf_prepend_uint32(buf,(uint32_t)st); + buf_prepend_uint32(buf,st->remote_session_id); st->comm->sendmsg(st->comm->st,buf,&st->peer); BUF_FREE(buf); return; @@ -918,7 +919,7 @@ static bool_t site_incoming(void *sst, struct buffer_if *buf, struct sockaddr_in *source) { struct site *st=sst; - uint32_t dest=*(uint32_t *)buf->start; + uint32_t dest=ntohl(*(uint32_t *)buf->start); if (dest==0) { if (buf->size<(st->setupsiglen+8+NONCELEN)) return False; @@ -971,7 +972,7 @@ static bool_t site_incoming(void *sst, struct buffer_if *buf, return False; /* Not for us. */ } if (dest==(uint32_t)st) { - uint32_t msgtype=*(uint32_t *)(buf->start+8); + uint32_t msgtype=ntohl(*(uint32_t *)(buf->start+8)); /* Explicitly addressed to us */ if (msgtype!=LABEL_MSG0) dump_packet(st,buf,source,True); switch (msgtype) { @@ -981,7 +982,7 @@ static bool_t site_incoming(void *sst, struct buffer_if *buf, case LABEL_MSG1: /* Setup packet: should not have been explicitly addressed to us */ - slog(st,LOG_SECURITY,"incoming explicitly addressed msg1"); + slog(st,LOG_SEC,"incoming explicitly addressed msg1"); break; case LABEL_MSG2: /* Setup packet: expected only in state SENTMSG1 */ @@ -990,7 +991,7 @@ static bool_t site_incoming(void *sst, struct buffer_if *buf, } else if (process_msg2(st,buf,source)) enter_state_sentmsg3(st); else { - slog(st,LOG_SECURITY,"invalid MSG2"); + slog(st,LOG_SEC,"invalid MSG2"); } break; case LABEL_MSG3: @@ -1000,7 +1001,7 @@ static bool_t site_incoming(void *sst, struct buffer_if *buf, } else if (process_msg3(st,buf,source)) enter_state_sentmsg4(st); else { - slog(st,LOG_SECURITY,"invalid MSG3"); + slog(st,LOG_SEC,"invalid MSG3"); } break; case LABEL_MSG4: @@ -1010,7 +1011,7 @@ static bool_t site_incoming(void *sst, struct buffer_if *buf, } else if (process_msg4(st,buf,source)) enter_state_sentmsg5(st); else { - slog(st,LOG_SECURITY,"invalid MSG4"); + slog(st,LOG_SEC,"invalid MSG4"); } break; case LABEL_MSG5: @@ -1025,7 +1026,7 @@ static bool_t site_incoming(void *sst, struct buffer_if *buf, } else if (process_msg5(st,buf,source)) { send_msg6(st); } else { - slog(st,LOG_SECURITY,"invalid MSG5"); + slog(st,LOG_SEC,"invalid MSG5"); } break; case LABEL_MSG6: @@ -1036,7 +1037,7 @@ static bool_t site_incoming(void *sst, struct buffer_if *buf, BUF_FREE(&st->buffer); /* Free message 5 */ activate_new_key(st); } else { - slog(st,LOG_SECURITY,"invalid MSG6"); + slog(st,LOG_SEC,"invalid MSG6"); } break; case LABEL_MSG8: @@ -1044,7 +1045,7 @@ static bool_t site_incoming(void *sst, struct buffer_if *buf, slog(st,LOG_ERROR,"received a NAK"); break; default: - slog(st,LOG_SECURITY,"received message of unknown type 0x%08x", + slog(st,LOG_SEC,"received message of unknown type 0x%08x", msgtype); break; } @@ -1116,7 +1117,7 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context, st->wait_timeout=dict_read_number(dict,"wait-time", False,"site",loc,DEFAULT_WAIT_TIME); /* XXX should be configurable */ - st->log_events=LOG_SECURITY|LOG_ERROR| + st->log_events=LOG_SEC|LOG_ERROR| LOG_ACTIVATE_KEY|LOG_TIMEOUT_KEY|LOG_SETUP_INIT|LOG_SETUP_TIMEOUT; st->tunname=safe_malloc(strlen(st->localname)+strlen(st->remotename)+5, @@ -1124,6 +1125,7 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context, sprintf(st->tunname,"%s<->%s",st->localname,st->remotename); /* The information we expect to see in incoming messages of type 1 */ + /* XXX fix this bit for unaligned access */ st->setupsiglen=strlen(st->remotename)+strlen(st->localname)+8; st->setupsig=safe_malloc(st->setupsiglen,"site_apply"); *(uint32_t *)&(st->setupsig[0])=LABEL_MSG1; diff --git a/transform.c b/transform.c index f94f5ae..174beda 100644 --- a/transform.c +++ b/transform.c @@ -11,10 +11,22 @@ #include "secnet.h" #include "util.h" #include "serpent.h" +#include "unaligned.h" /* Required key length in bytes */ #define REQUIRED_KEYLEN ((512+64+32)/8) +#ifdef WORDS_BIGENDIAN +static inline uint32_t byteswap(uint32_t a) +{ + return + ((a&0x000000ff)<<24) | + ((a&0x0000ff00)<<8) | + ((a&0x00ff0000)>>8) | + ((a&0xff000000)>>24); +} +#endif + struct transform { closure_t cl; uint32_t line; @@ -58,9 +70,9 @@ static bool_t transform_setkey(void *sst, uint8_t *key, uint32_t keylen) serpent_makekey(&ti->cryptkey,256,key); serpent_makekey(&ti->mackey,256,key+32); - ti->cryptiv=*(uint32_t *)(key+64); - ti->maciv=*(uint32_t *)(key+68); - ti->sendseq=*(uint32_t *)(key+72); + ti->cryptiv=ntohl(*(uint32_t *)(key+64)); + ti->maciv=ntohl(*(uint32_t *)(key+68)); + ti->sendseq=ntohl(*(uint32_t *)(key+72)); ti->lastrecvseq=ti->sendseq; ti->keyed=True; @@ -93,7 +105,7 @@ static uint32_t transform_forward(void *sst, struct buffer_if *buf, } /* Sequence number */ - *(uint32_t *)buf_prepend(buf,4)=htonl(ti->sendseq); + buf_prepend_uint32(buf,ti->sendseq); ti->sendseq++; /* PKCS5, stolen from IWJ */ @@ -119,13 +131,26 @@ static uint32_t transform_forward(void *sst, struct buffer_if *buf, block encrypted once again. */ for (n=(uint32_t *)buf->start; n<(uint32_t *)(buf->start+buf->size); n+=4) { +#ifdef WORDS_BIGENDIAN + macplain[0]=macacc[0]^byteswap(n[0]); + macplain[1]=macacc[1]^byteswap(n[1]); + macplain[2]=macacc[2]^byteswap(n[2]); + macplain[3]=macacc[3]^byteswap(n[3]); +#else macplain[0]=macacc[0]^n[0]; macplain[1]=macacc[1]^n[1]; macplain[2]=macacc[2]^n[2]; macplain[3]=macacc[3]^n[3]; +#endif serpent_encrypt(&ti->mackey,macplain,macacc); } serpent_encrypt(&ti->mackey,macacc,macacc); +#ifdef WORDS_BIGENDIAN + macacc[0]=byteswap(macacc[0]); + macacc[1]=byteswap(macacc[1]); + macacc[2]=byteswap(macacc[2]); + macacc[3]=byteswap(macacc[3]); +#endif memcpy(buf_append(buf,16),macacc,16); /* Serpent-CBC. We expand the ID as for CBCMAC, do the encryption, @@ -139,15 +164,22 @@ static uint32_t transform_forward(void *sst, struct buffer_if *buf, p=iv; for (n=(uint32_t *)buf->start; n<(uint32_t *)(buf->start+buf->size); n+=4) { +#ifdef WORDS_BIGENDIAN + n[0]=byteswap(p[0]^n[0]); + n[1]=byteswap(p[1]^n[1]); + n[2]=byteswap(p[2]^n[2]); + n[3]=byteswap(p[3]^n[3]); +#else n[0]=p[0]^n[0]; n[1]=p[1]^n[1]; n[2]=p[2]^n[2]; n[3]=p[3]^n[3]; +#endif serpent_encrypt(&ti->cryptkey,n,n); p=n; } - *(uint32_t *)buf_prepend(buf,4)=ti->cryptiv; + buf_prepend_uint32(buf,ti->cryptiv); ti->cryptiv++; return 0; @@ -175,17 +207,24 @@ static uint32_t transform_reverse(void *sst, struct buffer_if *buf, /* CBC */ memset(iv,0,16); - iv[0]=*(uint32_t *)buf_unprepend(buf,4); + iv[0]=buf_unprepend_uint32(buf); serpent_encrypt(&ti->cryptkey,iv,iv); /* XXX assert bufsize is multiple of blocksize */ for (n=(uint32_t *)buf->start; n<(uint32_t *)(buf->start+buf->size); n+=4) { pct[0]=n[0]; pct[1]=n[1]; pct[2]=n[2]; pct[3]=n[3]; serpent_decrypt(&ti->cryptkey,n,n); +#ifdef WORDS_BIGENDIAN + n[0]=byteswap(iv[0]^n[0]); + n[1]=byteswap(iv[1]^n[1]); + n[2]=byteswap(iv[2]^n[2]); + n[3]=byteswap(iv[3]^n[3]); +#else n[0]=iv[0]^n[0]; n[1]=iv[1]^n[1]; n[2]=iv[2]^n[2]; n[3]=iv[3]^n[3]; +#endif iv[0]=pct[0]; iv[1]=pct[1]; iv[2]=pct[2]; iv[3]=pct[3]; } @@ -199,13 +238,26 @@ static uint32_t transform_reverse(void *sst, struct buffer_if *buf, block encrypted once again. */ for (n=(uint32_t *)buf->start; n<(uint32_t *)(buf->start+buf->size); n+=4) { +#ifdef WORDS_BIGENDIAN + macplain[0]=macacc[0]^byteswap(n[0]); + macplain[1]=macacc[1]^byteswap(n[1]); + macplain[2]=macacc[2]^byteswap(n[2]); + macplain[3]=macacc[3]^byteswap(n[3]); +#else macplain[0]=macacc[0]^n[0]; macplain[1]=macacc[1]^n[1]; macplain[2]=macacc[2]^n[2]; macplain[3]=macacc[3]^n[3]; +#endif serpent_encrypt(&ti->mackey,macplain,macacc); } serpent_encrypt(&ti->mackey,macacc,macacc); +#ifdef WORDS_BIGENDIAN + macacc[0]=byteswap(macacc[0]); + macacc[1]=byteswap(macacc[1]); + macacc[2]=byteswap(macacc[2]); + macacc[3]=byteswap(macacc[3]); +#endif if (memcmp(macexpected,macacc,16)!=0) { *errmsg="invalid MAC"; return 1; @@ -230,7 +282,7 @@ static uint32_t transform_reverse(void *sst, struct buffer_if *buf, /* Sequence number must be within max_skew of lastrecvseq; lastrecvseq is only allowed to increase. */ - seqnum=ntohl(*(uint32_t *)buf_unprepend(buf,4)); + seqnum=buf_unprepend_uint32(buf); skew=seqnum-ti->lastrecvseq; if (skew<10) { /* Ok */ diff --git a/unaligned.h b/unaligned.h new file mode 100644 index 0000000..45b0d3c --- /dev/null +++ b/unaligned.h @@ -0,0 +1,42 @@ +#ifndef unaligned_h +#define unaligned_h + +/* Parts of the secnet key-exchange protocol require access to + unaligned big-endian quantities in buffers. These macros provide + convenient access, even on architectures that don't support unaligned + accesses. */ + +#define put_uint32(a,v) do { (a)[0]=(v)>>24; (a)[1]=((v)&0xff0000)>>16; \ +(a)[2]=((v)&0xff00)>>8; (a)[3]=(v)&0xff; } while(0) + +#define put_uint16(a,v) do {(a)[0]=((v)&0xff00)>>8; (a)[1]=(v)&0xff;} while(0) + +#define get_uint32(a) (((a)[0]<<24)|((a)[1]<<16)|((a)[2])<<8|(a)[3]) + +#define get_uint16(a) (((a)[0]<<8)|(a)[1]) + +#define buf_append_uint32(buf,v) do { uint8_t *c=buf_append((buf),4); \ + put_uint32(c,(v)); } while(0) + +#define buf_append_uint16(buf,v) do { uint8_t *c=buf_append((buf),2); \ + put_uint16(c,(v)); } while(0) + +#define buf_prepend_uint32(buf,v) do { uint8_t *c=buf_prepend((buf),4); \ + put_uint32(c,(v)); } while(0) + +#define buf_prepend_uint16(buf,v) do { uint8_t *c=buf_prepend((buf),2); \ + put_uint16(c,(v)); } while(0) + +#define buf_unappend_uint32(buf) ({uint8_t *c=buf_unappend((buf),4); \ + get_uint32(c);}) + +#define buf_unappend_uint16(buf) ({uint8_t *c=buf_unappend((buf),2); \ + get_uint16(c);}) + +#define buf_unprepend_uint32(buf) ({uint8_t *c=buf_unprepend((buf),4); \ + get_uint32(c);}) + +#define buf_unprepend_uint16(buf) ({uint8_t *c=buf_unprepend((buf),2); \ + get_uint16(c);}) + +#endif /* unaligned_h */ diff --git a/util.c b/util.c index 1929383..c652537 100644 --- a/util.c +++ b/util.c @@ -15,12 +15,13 @@ #include #include #include -#include +#include #include #include #include #include "util.h" #include "secnet.h" +#include "unaligned.h" #define MIN_BUFFER_SIZE 64 #define DEFAULT_BUFFER_SIZE 4096 @@ -522,7 +523,7 @@ void buf_append_string(struct buffer_if *buf, string_t s) uint16_t len; len=strlen(s); - *(uint16_t *)buf_append(buf,2)=htons(len); + buf_append_uint16(buf,len); memcpy(buf_append(buf,len),s,len); } -- 2.30.2