From ijackson at chiark.greenend.org.uk Fri Jul 1 22:33:43 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Fri, 1 Jul 2011 22:33:43 +0100 Subject: Another test Message-ID: <19982.15671.234331.73049@chiark.greenend.org.uk> The archives are broken (and past archives are probably lost) ... From ijackson at chiark.greenend.org.uk Fri Jul 1 21:47:46 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Fri, 1 Jul 2011 21:47:46 +0100 Subject: Test Message-ID: <19982.12914.83987.980396@chiark.greenend.org.uk> I want to see if this list, and its archives, are working. Ian. From ijackson at chiark.greenend.org.uk Fri Jul 1 23:56:14 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Fri, 1 Jul 2011 23:56:14 +0100 Subject: secnet friendly hijack Message-ID: <19982.20622.692178.155399@chiark.greenend.org.uk> (Following on from private emails...) I have created a git repo on chiark to be the new public master repo. The intent is that it will have access for me, Steve and Richard Kettlewell and anyone else we decide it ought to. Steve, Richard: Please email me the ssh key(s) you would like to have access. The public gitweb url for the repo is: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git/secnet.git/ Currently "master" contains release 0.1.16 plus a large series of cleanups and bugfixes from Richard and myself. I suggest: There should be a commit hook which sends emails to greenend.commits and/or to this list when "master" is updated. Richard, how easy would this be to set up ? (Asking you because you have such a thing already for some other repos.) We should try to stabilise what we have now a bit (including putting it through valgrind) and call it 1.0.0, and make an announcement. When my new-feature braches are in some kind of reviewable state I will patchbomb them to this list for discussion. Ian. From rjk at terraraq.org.uk Sat Jul 2 10:35:23 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Sat, 02 Jul 2011 10:35:23 +0100 Subject: secnet friendly hijack In-Reply-To: <19982.20622.692178.155399@chiark.greenend.org.uk> References: <19982.20622.692178.155399@chiark.greenend.org.uk> Message-ID: <4E0EE65B.7070306@terraraq.org.uk> On 01/07/2011 23:56, Ian Jackson wrote: > There should be a commit hook which sends emails to greenend.commits > and/or to this list when "master" is updated. Richard, how easy would > this be to set up ? (Asking you because you have such a thing already > for some other repos.) The current implementation is a cronjob rather than a submit hook; as such it is not particularly instantaneous, but I don't really see any good reason it should be. I'd be happy to add to my existing collection. If you'd rather DIY, the tool can be found at: http://www.greenend.org.uk/rjk/2006/newstools.html ttfn/rjk From ijackson at chiark.greenend.org.uk Sat Jul 2 12:44:27 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Sat, 2 Jul 2011 12:44:27 +0100 Subject: secnet friendly hijack In-Reply-To: <4E0EE65B.7070306@terraraq.org.uk> References: <19982.20622.692178.155399@chiark.greenend.org.uk> <4E0EE65B.7070306@terraraq.org.uk> Message-ID: <19983.1179.815446.218340@chiark.greenend.org.uk> Richard Kettlewell writes ("Re: secnet friendly hijack"): > The current implementation is a cronjob rather than a submit hook; as > such it is not particularly instantaneous, but I don't really see any > good reason it should be. I'd be happy to add to my existing collection. Yes, please do. Thanks, Ian. From rjk at terraraq.org.uk Sun Jul 3 14:52:19 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Sun, 03 Jul 2011 14:52:19 +0100 Subject: secnet: osx-specific changes Message-ID: <4E107413.2040105@terraraq.org.uk> These patches are OSX-specific and only affect building and documentation. Comments welcome. Talking of documentation, we could do with a man page. Does anyone have anything half-written or should I start from scratch? ttfn/rjk -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: detect-fink-automatically URL: -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: update-mac-specific-notes URL: From rjk at terraraq.org.uk Sun Jul 3 14:52:22 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Sun, 03 Jul 2011 14:52:22 +0100 Subject: secnet: command line & error checking Message-ID: <4E107416.4090908@terraraq.org.uk> The first of these patches makes the --debug and -d options consistent. The rest all improve error reporting in one way or another. Comments welcome. ttfn/rjk -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: make-d-option-consistent URL: -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: reject-bad-command-lines URL: -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: report-errors-when-a-packet URL: -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: report-route-errors URL: From rjk at terraraq.org.uk Sun Jul 3 15:01:20 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Sun, 03 Jul 2011 15:01:20 +0100 Subject: secnet: support daemon supervisors Message-ID: <4E107630.8050801@terraraq.org.uk> This patch adds a --managed option for use with daemon supervisors such as launchd, and de-conflates daemon specific setup from dropping privileges. Comments and testing especially welcome as it's a more intrusive patch than the others I've posted today. ttfn/rjk -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: add-new-managed-option-for-use URL: From ijackson at chiark.greenend.org.uk Tue Jul 5 12:10:08 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Tue, 5 Jul 2011 12:10:08 +0100 Subject: Improved testing Message-ID: <1309864212-14705-1-git-send-email-ijackson@chiark.greenend.org.uk> This small series provides a test setup which can be used for simple ad-hoc tests. I ran secnet through valgrind with it and at least for startup, key exchange, simple packet exchange, and shutdown, it was valgrind clean. From ijackson at chiark.greenend.org.uk Tue Jul 5 12:10:09 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Tue, 5 Jul 2011 12:10:09 +0100 Subject: [PATCH 1/4] resolver: support IPv4 address literals In-Reply-To: <1309864212-14705-1-git-send-email-ijackson@chiark.greenend.org.uk> References: <1309864212-14705-1-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1309864212-14705-2-git-send-email-ijackson@chiark.greenend.org.uk> Signed-off-by: Ian Jackson --- resolver.c | 16 ++++++++++++++++ 1 files changed, 16 insertions(+), 0 deletions(-) diff --git a/resolver.c b/resolver.c index f60b112..f4eeee6 100644 --- a/resolver.c +++ b/resolver.c @@ -6,6 +6,8 @@ #error secnet requires ADNS version 1.0 or above #endif #include +#include +#include struct adns { @@ -28,6 +30,20 @@ static bool_t resolve_request(void *sst, cstring_t name, struct adns *st=sst; struct query *q; int rv; + const int maxlitlen=50; + + int l=strlen(name); + if (name[0]=='[' && l2 && name[l-1]==']') { + char trimmed[maxlitlen+1]; + memcpy(trimmed,name+1,l-2); + trimmed[l-2]=0; + struct in_addr ia; + if (inet_aton(trimmed,&ia)) + cb(cst,&ia); + else + cb(cst,0); + return True; + } q=safe_malloc(sizeof *q,"resolve_request"); q->cst=cst; -- 1.5.6.5 From ijackson at chiark.greenend.org.uk Tue Jul 5 12:10:10 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Tue, 5 Jul 2011 12:10:10 +0100 Subject: [PATCH 2/4] build system: add *.pyc to .gitignore In-Reply-To: <1309864212-14705-2-git-send-email-ijackson@chiark.greenend.org.uk> References: <1309864212-14705-1-git-send-email-ijackson@chiark.greenend.org.uk> <1309864212-14705-2-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1309864212-14705-3-git-send-email-ijackson@chiark.greenend.org.uk> Python tends to leave this dropping. Signed-off-by: Ian Jackson --- .gitignore | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/.gitignore b/.gitignore index 999fbee..38a2ae0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ *.o *.d +*.pyc conffile.tab.[ch] conffile.yy.[ch] version.c -- 1.5.6.5 From ijackson at chiark.greenend.org.uk Tue Jul 5 12:10:11 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Tue, 5 Jul 2011 12:10:11 +0100 Subject: [PATCH 3/4] Test example: Files for a simple testing configuration now in test-example/ In-Reply-To: <1309864212-14705-3-git-send-email-ijackson@chiark.greenend.org.uk> References: <1309864212-14705-1-git-send-email-ijackson@chiark.greenend.org.uk> <1309864212-14705-2-git-send-email-ijackson@chiark.greenend.org.uk> <1309864212-14705-3-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1309864212-14705-4-git-send-email-ijackson@chiark.greenend.org.uk> Including a set of dummy keys, and dummy IP addresses in 172.18.232.0/28. Signed-off-by: Ian Jackson --- .gitignore | 3 +++ test-example/README | 21 +++++++++++++++++++++ test-example/common.conf | 16 ++++++++++++++++ test-example/inside.conf | 16 ++++++++++++++++ test-example/inside.key.b64 | 10 ++++++++++ test-example/inside.key.pub | 1 + test-example/outside.conf | 16 ++++++++++++++++ test-example/outside.key.b64 | 10 ++++++++++ test-example/outside.key.pub | 1 + test-example/sites | 25 +++++++++++++++++++++++++ 10 files changed, 119 insertions(+), 0 deletions(-) create mode 100644 test-example/README create mode 100644 test-example/common.conf create mode 100644 test-example/inside.conf create mode 100644 test-example/inside.key.b64 create mode 100644 test-example/inside.key.pub create mode 100644 test-example/outside.conf create mode 100644 test-example/outside.key.b64 create mode 100644 test-example/outside.key.pub create mode 100644 test-example/sites diff --git a/.gitignore b/.gitignore index 38a2ae0..f8c7371 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,6 @@ debian/secnet.debhelper.log debian/*.debhelper debian/secnet debian/secnet.substvars + +test-example/*.key +test-example/sites.conf diff --git a/test-example/README b/test-example/README new file mode 100644 index 0000000..a6416f6 --- /dev/null +++ b/test-example/README @@ -0,0 +1,21 @@ +This directory contains some files useful for ad-hoc tests. +With these it is possible to run a test of secnet on a Linux host +even if that Linux host does not have another working network connection. + +The keys here are (obviously) public. They were generated like this: + ssh-keygen -C inside at example.com -f test-example/inside.key -t rsa1 -b 1024 + ssh-keygen -C outside at example.com -f test-example/outside.key -t rsa1 -b 1024 + # edit sites to paste {inside,outside}.key.pub into pubkey lines + base64 inside.key.b64 + base64 outside.key.b64 + +To run the test: + Run the makefile: + make -C test-example/ + In one window, as root + ./secnet -dvnc test-example/inside.conf + And in another + ./secnet -dvnc test-example/outside.conf + Then in a third + ping -I secnet-test-i 172.18.232.2 + diff --git a/test-example/common.conf b/test-example/common.conf new file mode 100644 index 0000000..6f2fef1 --- /dev/null +++ b/test-example/common.conf @@ -0,0 +1,16 @@ +log logfile { + filename "/dev/tty"; + class "info","notice","warning","error","security","fatal"; +}; +system { +}; +resolver adns { +}; +log-events "setup-init","setup-timeout","activate-key","timeout-key","errors", + "security"; +random randomfile("/dev/urandom",no); +transform serpent256-cbc { + max-sequence-skew 10; +}; +include test-example/sites.conf +sites map(site,vpn/test-example/all-sites); diff --git a/test-example/inside.conf b/test-example/inside.conf new file mode 100644 index 0000000..775d593 --- /dev/null +++ b/test-example/inside.conf @@ -0,0 +1,16 @@ +netlink tun { + name "netlink-tun"; # Printed in log messages from this netlink + local-address "172.18.232.9"; + secnet-address "172.18.232.10"; + remote-networks "172.18.232.0/28"; + mtu 500; + buffer sysbuffer(2048); + interface "secnet-test-i"; +}; +comm udp { + port 16097; + buffer sysbuffer(4096); +}; +local-name "test-example/inside/inside"; +local-key rsa-private("test-example/inside.key"); +include test-example/common.conf diff --git a/test-example/inside.key.b64 b/test-example/inside.key.b64 new file mode 100644 index 0000000..d384c7c --- /dev/null +++ b/test-example/inside.key.b64 @@ -0,0 +1,10 @@ +U1NIIFBSSVZBVEUgS0VZIEZJTEUgRk9STUFUIDEuMQoAAAAAAAAAAAQABAC5N9rmU46hhdLO1FVh +Efkc9cq+x/UdC/a+nt0yM4HswxfChfJpcHq008Hkd4KOqRZORG7N5Q8fKPpkrnt3T3qSDX4P5HOW +5Q+2Qc82h1hO4mDbHo2xqmp4hv/88fHgPQTW9MffriDFs24HTt7uOqvx5LNtdmrw5ws6cXuyLwan +lQARAQABAAAAEmluc2lkZUBleGFtcGxlLmNvbe8z7zMD/1/rgT3PAAq+V1ItvJmsySoqUHlE7LfC +PmKxuzQIYLzQvDlNTSE10xZapAtBqSdggeC+p/ORMKeefS4u/lnnmz2tW9TlbtwWfj5Bwm/ftUZR +8BhelZQn5+/vTv1jLZ9dibLhemd20XxpMRIoOg+1w4xfbh1DoJbqs8OCCPPnNVJxAf9h3Hq0x84a +P0JOgyFFNatWcRKVJxapseeZPnpIAnkaDZ0KirE1RZFkHbfL4HFL3kI3MI657rE7rSC2yakvJtX9 +AgDD98/vGKw19bSdM8dHbocQQdDmn3SG5U9psbkvNQh06seKNL9QOeH2iHqjzBXmwTjPiWphdsVP +dFOBy1VE52YPAgDx9QU0xrSytFrjcqlP/FICaBiuJ9g0t4RbYBcm2iZaXLwXLDTX91arNJJrzblX +9yMkHDBDw9j1nKXnig+8dtwbAAAAAA== diff --git a/test-example/inside.key.pub b/test-example/inside.key.pub new file mode 100644 index 0000000..85fea76 --- /dev/null +++ b/test-example/inside.key.pub @@ -0,0 +1 @@ +1024 65537 130064631890186713927887504218626486455931306300999583387009075747001546036643522074275473238061323169592347601185592753550279410171535737146240085267000508853176463710554801101055212967131924064664249613912656320653505750073021702169423354903540699008756137338575553686987244488914481168225136440872431691669 inside at example.com diff --git a/test-example/outside.conf b/test-example/outside.conf new file mode 100644 index 0000000..f1a5228 --- /dev/null +++ b/test-example/outside.conf @@ -0,0 +1,16 @@ +netlink tun { + name "netlink-tun"; # Printed in log messages from this netlink + local-address "172.18.232.1"; + secnet-address "172.18.232.2"; + remote-networks "172.18.232.0/28"; + mtu 500; + buffer sysbuffer(2048); + interface "secnet-test-o"; +}; +comm udp { + port 16096; + buffer sysbuffer(4096); +}; +local-name "test-example/outside/outside"; +local-key rsa-private("test-example/outside.key"); +include test-example/common.conf diff --git a/test-example/outside.key.b64 b/test-example/outside.key.b64 new file mode 100644 index 0000000..f8ed4aa --- /dev/null +++ b/test-example/outside.key.b64 @@ -0,0 +1,10 @@ +U1NIIFBSSVZBVEUgS0VZIEZJTEUgRk9STUFUIDEuMQoAAAAAAAAAAAQABAC4D2q3B/nZUjsGMX72 +5FrgEB1y0uYS732QF/NXOEs9FA8/xmM68NF8JRfCctlCm9kQ9t/0xW+wOQTNg0BFIdgbZjXIwXLy +K9rreM1G1BsTjROtiz1UyjZMpo3Z89SWjtYCVN/UldRhakw/o0vrEKkZDTxiryhhYCGDUkONNsa5 +1QARAQABAAAAE291dHNpZGVAZXhhbXBsZS5jb23IlsiWA/9AO6kbPN5VmBvfGnDbim+oWBde1fjS +zN895Q3X915Sb2iu8fX5QMdqkqtLAbeORkMnZ3BaxHgowI1Lhy1rstbuiUcd3WWB6xUDcQll85Cy ++2IFfvFDKH7HsrzxgWx9M23WewlTje2NmVF0Y3xR39w2jUCLuEcyaWdPPQiLTucCgQH/axUYwPI5 +6QEKPiONve88GpehGCjereP5EjWTJomjQI+brOhnPckiWLwXXtWZoa894jpbVT8BtHNdDUg2gPFV +pwIA0FQowUgwxCnCoNZe/v/K5zwP3ar8OPoBV2c8rnEuZ2sR0AdLcBpaCpOQf7LKk9p+GUOHlMJy +hkrz7tAitvXEdQIA4i2dOA/PVYD6ZCZrwY5SToBmVtOzt2TVdhLbB/XDJ91ydl0uDdyN0Sn/Dyx+ +I55YwyhLA8zNV8mL4ZQS8OLz4QAAAAA= diff --git a/test-example/outside.key.pub b/test-example/outside.key.pub new file mode 100644 index 0000000..5e4cc0f --- /dev/null +++ b/test-example/outside.key.pub @@ -0,0 +1 @@ +1024 65537 129251483458784900555621175262818292872587807329014927540074484804119474262261383244074013537736576331652560727149001626325243856012659665194546933097292703586821422085819615124517093786704646988649444946154384037948502112302285511195679291084694375811092516151263088200304199780052361048758446082354317801941 outside at example.com diff --git a/test-example/sites b/test-example/sites new file mode 100644 index 0000000..5aee3d8 --- /dev/null +++ b/test-example/sites @@ -0,0 +1,25 @@ +vpn test-example +contact devnull at example.com +dh 8db5f2c15ac96d9f3382d1ef4688fba14dc7908ae7dfd71a9cfe7f479a75d506dc53f159aeaf488bde073fe544bc91c099f101fcf60074f30c06e36263c03ca9e07931ce3fc235fe1171dc6d9316fb097bd4362891e2c36e234e7c16b038fd97b1f165c710e90537de66ee4f54001f5712b050d4e07de3fba07607b19b64f6c3 2 +hash sha1 +key-lifetime 72000000 +restrict-nets 172.18.232.0/28 +setup-timeout 2000 +setup-retries 5 + +location inside root +site inside + networks 172.18.232.8/29 + peer 172.18.232.9 + address [127.0.0.1] 16097 + pubkey 1024 65537 130064631890186713927887504218626486455931306300999583387009075747001546036643522074275473238061323169592347601185592753550279410171535737146240085267000508853176463710554801101055212967131924064664249613912656320653505750073021702169423354903540699008756137338575553686987244488914481168225136440872431691669 inside at example.com + +location outside root +site outside + networks 172.18.232.0/29 + peer 172.18.232.1 + address [127.0.0.1] 16096 + pubkey 1024 65537 129251483458784900555621175262818292872587807329014927540074484804119474262261383244074013537736576331652560727149001626325243856012659665194546933097292703586821422085819615124517093786704646988649444946154384037948502112302285511195679291084694375811092516151263088200304199780052361048758446082354317801941 outside at example.com + + + -- 1.5.6.5 From ijackson at chiark.greenend.org.uk Tue Jul 5 12:10:12 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Tue, 5 Jul 2011 12:10:12 +0100 Subject: [PATCH 4/4] Test example: instructions for running under valgrind memcheck. In-Reply-To: <1309864212-14705-4-git-send-email-ijackson@chiark.greenend.org.uk> References: <1309864212-14705-1-git-send-email-ijackson@chiark.greenend.org.uk> <1309864212-14705-2-git-send-email-ijackson@chiark.greenend.org.uk> <1309864212-14705-3-git-send-email-ijackson@chiark.greenend.org.uk> <1309864212-14705-4-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1309864212-14705-5-git-send-email-ijackson@chiark.greenend.org.uk> Signed-off-by: Ian Jackson --- test-example/README | 5 +++++ test-example/memcheck.suppressions | 14 ++++++++++++++ 2 files changed, 19 insertions(+), 0 deletions(-) create mode 100644 test-example/memcheck.suppressions diff --git a/test-example/README b/test-example/README index a6416f6..4c2eca3 100644 --- a/test-example/README +++ b/test-example/README @@ -19,3 +19,8 @@ To run the test: Then in a third ping -I secnet-test-i 172.18.232.2 +For running under valgrind memcheck, do something like this: + valgrind --num-callers=40 --gen-suppressions=yes --db-attach=yes \ + --leak-check=full --suppressions=test-example/memcheck.suppressions \ + ./secnet -dvnc test-example/outside.conf +NB that --num-callers is needed as secnet's stack can be deep. diff --git a/test-example/memcheck.suppressions b/test-example/memcheck.suppressions new file mode 100644 index 0000000..42080da --- /dev/null +++ b/test-example/memcheck.suppressions @@ -0,0 +1,14 @@ +{ + secnet_read_conffile + Memcheck:Leak + ... + fun:read_conffile + fun:main +} +{ + secnet_enter_phase + Memcheck:Leak + ... + fun:enter_phase + fun:main +} -- 1.5.6.5 From matthewv at chiark.greenend.org.uk Tue Jul 5 12:35:52 2011 From: matthewv at chiark.greenend.org.uk (Matthew Vernon) Date: Tue, 05 Jul 2011 12:35:52 +0100 Subject: rjk-nntp-tools: gcrypt library requires initialization before use Message-ID: <4E12F718.2000204@chiark.greenend.org.uk> Hi, I noticed log entries of the form "lj2news: Libgcrypt warning: missing initialization - please fix the application". lj2news and bzr2news in the version (0.21) that I have handy both use libgcrypt functions without doing this. Section 2.4 of the gcrypt manual discusses the initialisation functions: http://www.gnupg.org/documentation/manuals/gcrypt/Initializing-the-library.html#Initializing-the-library I don't think this is particularly difficult to fix, but haven't the tuits myself right now. Regards, Matthew From rjk at terraraq.org.uk Wed Jul 6 08:48:45 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Wed, 06 Jul 2011 08:48:45 +0100 Subject: rjk-nntp-tools: gcrypt library requires initialization before use In-Reply-To: <4E12F718.2000204@chiark.greenend.org.uk> References: <4E12F718.2000204@chiark.greenend.org.uk> Message-ID: <4E14135D.1060707@terraraq.org.uk> On 05/07/2011 12:35, Matthew Vernon wrote: > Hi, > > I noticed log entries of the form "lj2news: Libgcrypt warning: missing > initialization - please fix the application". lj2news and bzr2news in > the version (0.21) that I have handy both use libgcrypt functions > without doing this. Section 2.4 of the gcrypt manual discusses the > initialisation functions: > > http://www.gnupg.org/documentation/manuals/gcrypt/Initializing-the-library.html#Initializing-the-library > > > I don't think this is particularly difficult to fix, but haven't the > tuits myself right now. I don't think I've ever seen this message. Where do you see it and what version of gcrypt are you using? ttfn/rjk From matthewv at chiark.greenend.org.uk Wed Jul 6 09:38:42 2011 From: matthewv at chiark.greenend.org.uk (Matthew Vernon) Date: Wed, 06 Jul 2011 09:38:42 +0100 Subject: rjk-nntp-tools: gcrypt library requires initialization before use In-Reply-To: <4E14135D.1060707@terraraq.org.uk> References: <4E12F718.2000204@chiark.greenend.org.uk> <4E14135D.1060707@terraraq.org.uk> Message-ID: <4E141F12.5020904@chiark.greenend.org.uk> On 06/07/11 08:48, Richard Kettlewell wrote: > On 05/07/2011 12:35, Matthew Vernon wrote: >> Hi, >> >> I noticed log entries of the form "lj2news: Libgcrypt warning: missing >> initialization - please fix the application". lj2news and bzr2news in >> the version (0.21) that I have handy both use libgcrypt functions >> without doing this. Section 2.4 of the gcrypt manual discusses the >> initialisation functions: >> >> http://www.gnupg.org/documentation/manuals/gcrypt/Initializing-the-library.html#Initializing-the-library > > I don't think I've ever seen this message. Where do you see it and what > version of gcrypt are you using? I see it in syslog (I'm usually invoking lj2news from a cron script, but this happens when running it from the command-line too). The exact thing in syslog is: Jul 6 09:35:25 b144-mcv1-mlt lj2news: Libgcrypt warning: missing initialization - please fix the application I have Debian stable's gcrypt, which is libgcrypt11, Version: 1.4.5-2 HTH, Matthew From rjk at terraraq.org.uk Wed Jul 6 19:16:37 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Wed, 06 Jul 2011 19:16:37 +0100 Subject: rjk-nntp-tools: gcrypt library requires initialization before use In-Reply-To: <4E141F12.5020904@chiark.greenend.org.uk> References: <4E12F718.2000204@chiark.greenend.org.uk> <4E14135D.1060707@terraraq.org.uk> <4E141F12.5020904@chiark.greenend.org.uk> Message-ID: <4E14A685.2090403@terraraq.org.uk> On 06/07/2011 09:38, Matthew Vernon wrote: > On 06/07/11 08:48, Richard Kettlewell wrote: >> On 05/07/2011 12:35, Matthew Vernon wrote: >>> Hi, >>> >>> I noticed log entries of the form "lj2news: Libgcrypt warning: missing >>> initialization - please fix the application". lj2news and bzr2news in >>> the version (0.21) that I have handy both use libgcrypt functions >>> without doing this. Section 2.4 of the gcrypt manual discusses the >>> initialisation functions: >>> >>> http://www.gnupg.org/documentation/manuals/gcrypt/Initializing-the-library.html#Initializing-the-library >>> >> >> I don't think I've ever seen this message. Where do you see it and what >> version of gcrypt are you using? > > I see it in syslog (I'm usually invoking lj2news from a cron script, but > this happens when running it from the command-line too). The exact thing > in syslog is: > Jul 6 09:35:25 b144-mcv1-mlt lj2news: Libgcrypt warning: missing > initialization - please fix the application > > I have Debian stable's gcrypt, which is libgcrypt11, Version: 1.4.5-2 Thanks. Fixed in git. ttfn/rjk From rjk at terraraq.org.uk Wed Jul 6 20:54:46 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Wed, 06 Jul 2011 20:54:46 +0100 Subject: Improved testing In-Reply-To: <1309864212-14705-1-git-send-email-ijackson@chiark.greenend.org.uk> References: <1309864212-14705-1-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <4E14BD86.4080201@terraraq.org.uk> On 05/07/2011 12:10, Ian Jackson wrote: > This small series provides a test setup which can be used for simple > ad-hoc tests. I ran secnet through valgrind with it and at least for > startup, key exchange, simple packet exchange, and shutdown, it was > valgrind clean. Looks sensible enough to me. ttfn/rjk From rjk at terraraq.org.uk Wed Jul 6 21:19:24 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Wed, 6 Jul 2011 21:19:24 +0100 Subject: [PATCH 1/4] Make -d option consistent. In-Reply-To: <1309983567-64851-1-git-send-email-rjk@terraraq.org.uk> References: <1309983567-64851-1-git-send-email-rjk@terraraq.org.uk> Message-ID: <1309983567-64851-2-git-send-email-rjk@terraraq.org.uk> From: Richard Kettlewell Previously --debug required an argument and -d did not. The argument was in any case ignored. Signed-off-by: Richard Kettlewell --- secnet.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/secnet.c b/secnet.c index 36750ec..1a4e8fd 100644 --- a/secnet.c +++ b/secnet.c @@ -62,7 +62,7 @@ static void parse_options(int argc, char **argv) {"nodetach", 0, 0, 'n'}, {"silent", 0, 0, 'f'}, {"quiet", 0, 0, 'f'}, - {"debug", 1, 0, 'd'}, + {"debug", 0, 0, 'd'}, {"config", 1, 0, 'c'}, {"just-check-config", 0, 0, 'j'}, {"sites-key", 1, 0, 's'}, @@ -87,7 +87,7 @@ static void parse_options(int argc, char **argv) " -s, --sites-key=name configuration key that " "specifies active sites\n" " -n, --nodetach do not run in background\n" - " -d, --debug=item,... set debug options\n" + " -d, --debug output debug messages\n" " --help display this help and exit\n" " --version output version information " "and exit\n" -- 1.6.4.2 From rjk at terraraq.org.uk Wed Jul 6 21:19:25 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Wed, 6 Jul 2011 21:19:25 +0100 Subject: [PATCH 2/4] Exit nonzero if any unknown options are provided on the command line. In-Reply-To: <1309983567-64851-2-git-send-email-rjk@terraraq.org.uk> References: <1309983567-64851-1-git-send-email-rjk@terraraq.org.uk> <1309983567-64851-2-git-send-email-rjk@terraraq.org.uk> Message-ID: <1309983567-64851-3-git-send-email-rjk@terraraq.org.uk> From: Richard Kettlewell Signed-off-by: Richard Kettlewell --- secnet.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/secnet.c b/secnet.c index 1a4e8fd..f9808b7 100644 --- a/secnet.c +++ b/secnet.c @@ -141,6 +141,7 @@ static void parse_options(int argc, char **argv) break; case '?': + exit(1); break; default: -- 1.6.4.2 From rjk at terraraq.org.uk Wed Jul 6 21:19:26 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Wed, 6 Jul 2011 21:19:26 +0100 Subject: [PATCH 3/4] If 'route' fails, log its exit status. In-Reply-To: <1309983567-64851-3-git-send-email-rjk@terraraq.org.uk> References: <1309983567-64851-1-git-send-email-rjk@terraraq.org.uk> <1309983567-64851-2-git-send-email-rjk@terraraq.org.uk> <1309983567-64851-3-git-send-email-rjk@terraraq.org.uk> Message-ID: <1309983567-64851-4-git-send-email-rjk@terraraq.org.uk> From: Richard Kettlewell Signed-off-by: Richard Kettlewell --- tun.c | 19 +++++++++++-------- 1 files changed, 11 insertions(+), 8 deletions(-) diff --git a/tun.c b/tun.c index 7d1053a..8728676 100644 --- a/tun.c +++ b/tun.c @@ -148,7 +148,7 @@ static bool_t tun_set_route(void *sst, struct netlink_client *routes) string_t network, mask, secnetaddr; struct subnet_list *nets; int32_t i; - int fd=-1; + int fd=-1, rv; if (routes->up == routes->kup) return False; if (st->route_type==TUN_CONFIG_IOCTL) { @@ -174,17 +174,17 @@ static bool_t tun_set_route(void *sst, struct netlink_client *routes) nets->list[i].len,routes->up?"to":"from"); switch (st->route_type) { case TUN_CONFIG_LINUX: - sys_cmd(st->route_path,"route",routes->up?"add":"del", - "-net",network,"netmask",mask, - "gw",secnetaddr,(char *)0); + rv = sys_cmd(st->route_path,"route",routes->up?"add":"del", + "-net",network,"netmask",mask, + "gw",secnetaddr,(char *)0); break; case TUN_CONFIG_BSD: - sys_cmd(st->route_path,"route",routes->up?"add":"del", - "-net",network,secnetaddr,mask,(char *)0); + rv = sys_cmd(st->route_path,"route",routes->up?"add":"del", + "-net",network,secnetaddr,mask,(char *)0); break; case TUN_CONFIG_SOLARIS25: - sys_cmd(st->route_path,"route",routes->up?"add":"del", - network,secnetaddr,(char *)0); + rv = sys_cmd(st->route_path,"route",routes->up?"add":"del", + network,secnetaddr,(char *)0); break; case TUN_CONFIG_IOCTL: { @@ -209,6 +209,7 @@ static bool_t tun_set_route(void *sst, struct netlink_client *routes) if (ioctl(fd,action,&rt)<0) { fatal_perror("tun_set_route: ioctl()"); } + rv = 0; #else fatal("tun_set_route: ioctl method not supported"); #endif @@ -218,6 +219,8 @@ static bool_t tun_set_route(void *sst, struct netlink_client *routes) fatal("tun_set_route: unsupported route command type"); break; } + if(rv != 0) + Message(M_ERR, "tun_set_route: route exited with status %#x\n", rv); free(network); free(mask); } free(secnetaddr); -- 1.6.4.2 From rjk at terraraq.org.uk Wed Jul 6 21:19:27 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Wed, 6 Jul 2011 21:19:27 +0100 Subject: [PATCH 4/4] Report errors when a packet cannot be delivered to the tun device. Wrong-size writes count as errors. In-Reply-To: <1309983567-64851-4-git-send-email-rjk@terraraq.org.uk> References: <1309983567-64851-1-git-send-email-rjk@terraraq.org.uk> <1309983567-64851-2-git-send-email-rjk@terraraq.org.uk> <1309983567-64851-3-git-send-email-rjk@terraraq.org.uk> <1309983567-64851-4-git-send-email-rjk@terraraq.org.uk> Message-ID: <1309983567-64851-5-git-send-email-rjk@terraraq.org.uk> From: Richard Kettlewell The error reporting is rate limited to ensure that the logs are not flooded. Signed-off-by: Richard Kettlewell --- tun.c | 26 +++++++++++++++++++++++--- 1 files changed, 23 insertions(+), 3 deletions(-) diff --git a/tun.c b/tun.c index 8728676..d913f06 100644 --- a/tun.c +++ b/tun.c @@ -3,8 +3,10 @@ #include "netlink.h" #include #include +#include #include #include +#include #include #include #include @@ -134,11 +136,29 @@ static void tun_afterpoll(void *sst, struct pollfd *fds, int nfds) static void tun_deliver_to_kernel(void *sst, struct buffer_if *buf) { struct tun *st=sst; + ssize_t rc; BUF_ASSERT_USED(buf); - /* No error checking, because we'd just throw the packet away - anyway if it didn't work. */ - write(st->fd,buf->start,buf->size); + + /* Log errors, so we can tell what's going on, but only once a + minute, so we don't flood the logs. Short writes count as + errors. */ + rc = write(st->fd,buf->start,buf->size); + if(rc != buf->size) { + static time_t last_report; + time_t now; + time(&now); + if(now >= last_report + 60) { + if(rc < 0) + Message(M_WARNING, + "failed to deliver packet to tun device: %s\n", + strerror(errno)); + else + Message(M_WARNING, + "truncated packet delivered to tun device\n"); + last_report = now; + } + } BUF_FREE(buf); } -- 1.6.4.2 From rjk at terraraq.org.uk Wed Jul 6 21:19:23 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Wed, 6 Jul 2011 21:19:23 +0100 Subject: [PATCH 0/4] Command line parsing and error handling Message-ID: <1309983567-64851-1-git-send-email-rjk@terraraq.org.uk> Feedback welcome. ttfn/rjk From ijackson at chiark.greenend.org.uk Thu Jul 7 01:00:50 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Thu, 7 Jul 2011 01:00:50 +0100 Subject: [PATCH 1/1] Security: Reduce impact of bogus key setup packet DoS Message-ID: <1309996850-31404-1-git-send-email-ijackson@chiark.greenend.org.uk> If a MSG1 (key setup initiation packet) is received containing expected local and remote site names, the receiving secnet will start a key setup attempt with details from that packet. MSG1 packets are (almost necessarily) unauthenticated, so anyone on the Internet can cause this to happen. secnet is only willing to have one key exchange attempt ongoing at once, and will ignore subsequent incoming MSG1s until it has dealt with the first key exchange attempt. So this means that an attacker who can send packets to any secnet instance can DoS secnet at session setup (or key renewal) time. All the attacker needs to know is the secnet site names, and the IP address and port number of one of the secnets. The attacker does not need to spoof their IP address or know any secret keys. If the attacker sends a contant stream of bogus packets they can probably prevent the link coming up at all. This is difficult to fix without changing the protocol. However, there is worse: when the key setup with the bogus peer eventually fails, as it must, secnet invalidates the current session key and its note of where to send actual data packets. It will then refuse to attempt a new key exchange for a timeout period. During this period, data packets will not flow. This means that sending one fairly easy to construct udp packet can cause a 20s outage. Worse, after this one packet has had its effect, the attacker can prevent the connection being reestablished, as described above. In this patch we fix the latter problem. It is simply a bug that the session key and data transport peer address (resulting from a previous successful key exchange) are discarded when a key setup fails. We also provide a test program "test-example/bogus-setutp-request.c" which can be used to reproduce the problem. Signed-off-by: Ian Jackson --- .gitignore | 1 + site.c | 1 - test-example/bogus-setup-request.c | 115 ++++++++++++++++++++++++++++++++++++ 3 files changed, 116 insertions(+), 1 deletions(-) create mode 100644 test-example/bogus-setup-request.c diff --git a/.gitignore b/.gitignore index f8c7371..c5187b5 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,4 @@ debian/secnet.substvars test-example/*.key test-example/sites.conf +test-example/bogus-setup-request diff --git a/site.c b/site.c index 29efb25..006d9b4 100644 --- a/site.c +++ b/site.c @@ -928,7 +928,6 @@ static void enter_state_wait(struct site *st) slog(st,LOG_STATE,"entering state WAIT"); st->timeout=st->now+st->wait_timeout; st->state=SITE_WAIT; - st->peer_valid=False; set_link_quality(st); BUF_FREE(&st->buffer); /* will have had an outgoing packet in it */ /* XXX Erase keys etc. */ diff --git a/test-example/bogus-setup-request.c b/test-example/bogus-setup-request.c new file mode 100644 index 0000000..a0dc702 --- /dev/null +++ b/test-example/bogus-setup-request.c @@ -0,0 +1,115 @@ +/* + test-example/bogus-setup-request 127.0.0.1 19098 test-example/inside/inside 127.0.0.1 16096 test-example/outside/outside + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + /* + | 00000 00 00 00 00 00 00 00 01 01 01 01 01 00 1a 74 65 ........ ......te | + ~~~~~~~~~~~ ~~~~~~~~~~~ ~~~~~~~~~~~ ~~~~~|~~~~~ + sessionid sender's type sender's + zero in index fixed for name + msg1 msg1 + + | 00010 73 74 2d 65 78 61 6d 70 6c 65 2f 69 6e 73 69 64 st-examp le/insid | + | 00020 65 2f 69 6e 73 69 64 65 00 1c 74 65 73 74 2d 65 e/inside ..test-e | + ~~~~~|~~~~~~~~~~~~~~~~~ + recipient's name + + | 00030 78 61 6d 70 6c 65 2f 6f 75 74 73 69 64 65 2f 6f xample/o utside/o | + | 00040 75 74 73 69 64 65 8d f0 3f 35 d6 c8 1f c0 utside.. ?5.... | + ~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~ + sender's nonce + */ + +typedef struct { + const char *name; + union { + struct sockaddr sa; + struct sockaddr_in sin; + }; +} Ep; + +static void endaddr(Ep *ep, char **argv, int base) { + int r; + ep->sin.sin_family=AF_INET; + r=inet_aton(argv[base],&ep->sin.sin_addr); assert(r); + ep->sin.sin_port=htons(atoi(argv[base+1])); + ep->name=argv[base+2]; +} + +static void endname(uint8_t **msgp, const Ep *ep) { + int l=strlen(ep->name); assert(l<=65535); + *(*msgp)++ = l>>8; + *(*msgp)++ = l; + memcpy(*msgp, ep->name, l); + *msgp += l; +} + +static Ep us, them; + +int main(int argc, char **argv) { + int r; + + assert(argc==7); + + endaddr(&us,argv,1); + endaddr(&them,argv,4); + + static const uint8_t mprefix[]={ + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, + 0x01, 0x01, 0x01, 0x01, + }; + static const uint8_t msuffix[]={ + /* our nonce, fixed he he */ + 0x8d, 0xf0, 0x3f, 0x35, 0xd6, 0xc8, 0x1f, 0xc0 + }; + int msglen= (sizeof(mprefix) + + 2+strlen(us.name) + + 2+strlen(them.name) + + sizeof(msuffix)); + uint8_t msg[msglen]; + uint8_t *msgp=msg; + +#define PREFIXSUFFIX(prefixsuffix) do { \ + memcpy(msgp,prefixsuffix,sizeof(prefixsuffix)); \ + msgp += sizeof(prefixsuffix); \ + }while(0) + + PREFIXSUFFIX(mprefix); + + endname(&msgp,&us); + endname(&msgp,&them); + + PREFIXSUFFIX(msuffix); + + assert(msgp == msg+msglen); + + struct protoent *proto=getprotobyname("udp"); + int fd=socket(AF_INET, SOCK_DGRAM, proto->p_proto); + r=bind(fd,&us.sa,sizeof(us)); if (r) { perror("bind us2"); exit(1); } + + for (;;) { + r=sendto(fd,msg,msglen,0,&them.sa,sizeof(them)); + if (r) perror("sendto"); + + r=getchar(); + if (r==EOF) { + if (ferror(stdin)) { perror("getchar"); exit(1); } + break; + } + if (r!='\n') + break; + } + exit(0); +} -- 1.5.6.5 From ijackson at chiark.greenend.org.uk Thu Jul 7 14:57:31 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Thu, 7 Jul 2011 14:57:31 +0100 Subject: [PATCH 3/4] If 'route' fails, log its exit status. In-Reply-To: <1309983567-64851-4-git-send-email-rjk@terraraq.org.uk> References: <1309983567-64851-1-git-send-email-rjk@terraraq.org.uk> <1309983567-64851-2-git-send-email-rjk@terraraq.org.uk> <1309983567-64851-3-git-send-email-rjk@terraraq.org.uk> <1309983567-64851-4-git-send-email-rjk@terraraq.org.uk> Message-ID: <19989.47947.622173.437427@chiark.greenend.org.uk> Richard Kettlewell writes ("[PATCH 3/4] If 'route' fails, log its exit status."): > Signed-off-by: Richard Kettlewell 1,2 look good to me. Re this one: I haven't grepped the source but why shouldn't sys_cmd do this logging ? That would put it all in one place. Ian. From ijackson at chiark.greenend.org.uk Thu Jul 7 14:59:58 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Thu, 7 Jul 2011 14:59:58 +0100 Subject: [PATCH 4/4] Report errors when a packet cannot be delivered to the tun device. Wrong-size writes count as errors. In-Reply-To: <1309983567-64851-5-git-send-email-rjk@terraraq.org.uk> References: <1309983567-64851-1-git-send-email-rjk@terraraq.org.uk> <1309983567-64851-2-git-send-email-rjk@terraraq.org.uk> <1309983567-64851-3-git-send-email-rjk@terraraq.org.uk> <1309983567-64851-4-git-send-email-rjk@terraraq.org.uk> <1309983567-64851-5-git-send-email-rjk@terraraq.org.uk> Message-ID: <19989.48094.842258.454530@chiark.greenend.org.uk> Richard Kettlewell writes ("[PATCH 4/4] Report errors when a packet cannot be delivered to the tun device. Wrong-size writes count as errors."): > + rc = write(st->fd,buf->start,buf->size); > + if(rc != buf->size) { > + static time_t last_report; > + time_t now; > + time(&now); I have a patch in my local tree which provides a global variable "tv_now" containing a struct timeval. Should I try to shuffle this forward for your benefit or shall we fix this use of time() up later ? Ian. From rjk at terraraq.org.uk Thu Jul 7 18:57:35 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Thu, 07 Jul 2011 18:57:35 +0100 Subject: [PATCH 3/4] If 'route' fails, log its exit status. In-Reply-To: <19989.47947.622173.437427@chiark.greenend.org.uk> References: <1309983567-64851-1-git-send-email-rjk@terraraq.org.uk> <1309983567-64851-2-git-send-email-rjk@terraraq.org.uk> <1309983567-64851-3-git-send-email-rjk@terraraq.org.uk> <1309983567-64851-4-git-send-email-rjk@terraraq.org.uk> <19989.47947.622173.437427@chiark.greenend.org.uk> Message-ID: <4E15F38F.8000703@terraraq.org.uk> On 07/07/2011 14:57, Ian Jackson wrote: > Richard Kettlewell writes ("[PATCH 3/4] If 'route' fails, log its exit status."): >> Signed-off-by: Richard Kettlewell > > 1,2 look good to me. > > Re this one: I haven't grepped the source but why shouldn't sys_cmd do > this logging ? That would put it all in one place. That sounds more sensible; I'll redo it to do that. ttfn/rjk From rjk at terraraq.org.uk Thu Jul 7 18:59:12 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Thu, 07 Jul 2011 18:59:12 +0100 Subject: [PATCH 4/4] Report errors when a packet cannot be delivered to the tun device. Wrong-size writes count as errors. In-Reply-To: <19989.48094.842258.454530@chiark.greenend.org.uk> References: <1309983567-64851-1-git-send-email-rjk@terraraq.org.uk> <1309983567-64851-2-git-send-email-rjk@terraraq.org.uk> <1309983567-64851-3-git-send-email-rjk@terraraq.org.uk> <1309983567-64851-4-git-send-email-rjk@terraraq.org.uk> <1309983567-64851-5-git-send-email-rjk@terraraq.org.uk> <19989.48094.842258.454530@chiark.greenend.org.uk> Message-ID: <4E15F3F0.1080202@terraraq.org.uk> On 07/07/2011 14:59, Ian Jackson wrote: > Richard Kettlewell writes ("[PATCH 4/4] Report errors when a packet cannot be delivered to the tun device. Wrong-size writes count as errors."): >> + rc = write(st->fd,buf->start,buf->size); >> + if(rc != buf->size) { >> + static time_t last_report; >> + time_t now; >> + time(&now); > > I have a patch in my local tree which provides a global variable > "tv_now" containing a struct timeval. Should I try to shuffle this > forward for your benefit or shall we fix this use of time() up later ? I'll wait until tv_now appears before pushing this one. BTW. Do you prefer to be CC'd or not on ssd messages? ttfn/rjk From rjk at terraraq.org.uk Sat Jul 9 10:37:35 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Sat, 09 Jul 2011 10:37:35 +0100 Subject: [PATCH 1/4] resolver: support IPv4 address literals In-Reply-To: <1309864212-14705-2-git-send-email-ijackson@chiark.greenend.org.uk> References: <1309864212-14705-1-git-send-email-ijackson@chiark.greenend.org.uk> <1309864212-14705-2-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <4E18215F.8030209@terraraq.org.uk> On 05/07/2011 12:10, Ian Jackson wrote: > Signed-off-by: Ian Jackson > --- > resolver.c | 16 ++++++++++++++++ > 1 files changed, 16 insertions(+), 0 deletions(-) > > diff --git a/resolver.c b/resolver.c > index f60b112..f4eeee6 100644 > --- a/resolver.c > +++ b/resolver.c > @@ -6,6 +6,8 @@ > #error secnet requires ADNS version 1.0 or above > #endif > #include > +#include > +#include > > > struct adns { > @@ -28,6 +30,20 @@ static bool_t resolve_request(void *sst, cstring_t name, > struct adns *st=sst; > struct query *q; > int rv; > + const int maxlitlen=50; > + > + int l=strlen(name); Oh, I missed this earlier. Will overflow if supplied with a ridiculously long string (e.g. on a 64-bit platform). Probably not a big deal, but... ttfn/rjk From rjk at terraraq.org.uk Sat Jul 9 13:18:47 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Sat, 09 Jul 2011 13:18:47 +0100 Subject: [PATCH 3/4] If 'route' fails, log its exit status. In-Reply-To: <19989.47947.622173.437427@chiark.greenend.org.uk> References: <1309983567-64851-1-git-send-email-rjk@terraraq.org.uk> <1309983567-64851-2-git-send-email-rjk@terraraq.org.uk> <1309983567-64851-3-git-send-email-rjk@terraraq.org.uk> <1309983567-64851-4-git-send-email-rjk@terraraq.org.uk> <19989.47947.622173.437427@chiark.greenend.org.uk> Message-ID: <4E184727.4070804@terraraq.org.uk> On 07/07/2011 14:57, Ian Jackson wrote: > Richard Kettlewell writes ("[PATCH 3/4] If 'route' fails, log its exit status."): >> Signed-off-by: Richard Kettlewell > > 1,2 look good to me. I've pushed 1 & 2. ttfn/rjk From rjk at terraraq.org.uk Sat Jul 9 14:59:02 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Sat, 9 Jul 2011 14:59:02 +0100 Subject: [PATCH 0/2] respin of error reporting improvements Message-ID: <1310219944-75586-1-git-send-email-rjk@terraraq.org.uk> Command logging now centralized in sys_cmd() as suggested. ttfn/rjk From rjk at terraraq.org.uk Sat Jul 9 14:59:03 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Sat, 9 Jul 2011 14:59:03 +0100 Subject: [PATCH 1/2] Report errors when a packet cannot be delivered to the tun device. Wrong-size writes count as errors. In-Reply-To: <1310219944-75586-1-git-send-email-rjk@terraraq.org.uk> References: <1310219944-75586-1-git-send-email-rjk@terraraq.org.uk> Message-ID: <1310219944-75586-2-git-send-email-rjk@terraraq.org.uk> From: Richard Kettlewell The error reporting is rate limited to ensure that the logs are not flooded. Signed-off-by: Richard Kettlewell --- tun.c | 26 +++++++++++++++++++++++--- 1 files changed, 23 insertions(+), 3 deletions(-) diff --git a/tun.c b/tun.c index 7d1053a..442fb03 100644 --- a/tun.c +++ b/tun.c @@ -3,8 +3,10 @@ #include "netlink.h" #include #include +#include #include #include +#include #include #include #include @@ -134,11 +136,29 @@ static void tun_afterpoll(void *sst, struct pollfd *fds, int nfds) static void tun_deliver_to_kernel(void *sst, struct buffer_if *buf) { struct tun *st=sst; + ssize_t rc; BUF_ASSERT_USED(buf); - /* No error checking, because we'd just throw the packet away - anyway if it didn't work. */ - write(st->fd,buf->start,buf->size); + + /* Log errors, so we can tell what's going on, but only once a + minute, so we don't flood the logs. Short writes count as + errors. */ + rc = write(st->fd,buf->start,buf->size); + if(rc != buf->size) { + static time_t last_report; + time_t now; + time(&now); + if(now >= last_report + 60) { + if(rc < 0) + Message(M_WARNING, + "failed to deliver packet to tun device: %s\n", + strerror(errno)); + else + Message(M_WARNING, + "truncated packet delivered to tun device\n"); + last_report = now; + } + } BUF_FREE(buf); } -- 1.6.4.2 From rjk at terraraq.org.uk Sat Jul 9 14:59:04 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Sat, 9 Jul 2011 14:59:04 +0100 Subject: [PATCH 2/2] sys_cmd error handling improved in the following ways: (1) If the subprocess exits nonzero then the exit status is unpicked and logged. (2) If the exec in the child fails, the command and errno string are written to stderr (which should end up in secnet's usual log output). (3) _exit() is used instead of exit(), to avoid any possibility of craziness with stdio/atexit/etc. In-Reply-To: <1310219944-75586-2-git-send-email-rjk@terraraq.org.uk> References: <1310219944-75586-1-git-send-email-rjk@terraraq.org.uk> <1310219944-75586-2-git-send-email-rjk@terraraq.org.uk> Message-ID: <1310219944-75586-3-git-send-email-rjk@terraraq.org.uk> From: Richard Kettlewell Signed-off-by: Richard Kettlewell --- process.c | 53 +++++++++++++++++++++++++++++------------------------ 1 files changed, 29 insertions(+), 24 deletions(-) diff --git a/process.c b/process.c index 968e93c..3a47f23 100644 --- a/process.c +++ b/process.c @@ -1,27 +1,12 @@ +#define _GNU_SOURCE #include "secnet.h" #include #include #include #include +#include #include "process.h" -/* Advice about children from Peter: -Better way: before the fork, make a pipe. In the child close the -+reading end. Make the writing end close-on-exec. If the dup2 or exec fails, -+write the errno value. In the parent, close the writing end. Now you can read -+from it. If you get an errno value from the pipe, the process failed and you -+know why. If you get EOF, the exec succeeded. - - So, close on exec only closes if exec isn't going to return then? - qu: I wouldn't bother with all that with pipes. Remember that the -+runtime system can still make exec fail when it's `too late'. - Diz - I would rather have a coherant error message than 'child failed' - The child, if it fails to exec, should print a message to stderr -+(giving errno and what it was trying to execute, most likely), and exit -+nonzero. - It should exit calling _exit. -*/ - /* Process handling - subprocesses, signals, etc. */ static bool_t signal_handling=False; @@ -143,14 +128,33 @@ static void sigchld_handler(void *st, int signum) int sys_cmd(const char *path, const char *arg, ...) { va_list ap; - int rv; + int rv, rc; pid_t c; - va_start(ap,arg); c=fork(); if (c) { /* Parent -> wait for child */ - waitpid(c,&rv,0); + do { + rc = waitpid(c,&rv,0); + } while(rc < 0 && errno == EINTR); + if(rc < 0) + fatal_perror("sys_cmd: waitpid for %s", path); + if(rc != c) /* OS has gone mad */ + fatal("sys_cmd: waitpid for %s returned wrong process ID!", + path); + if(rv) { + /* If the command failed reporting its exit status */ + if(WIFEXITED(rv)) + Message(M_ERR, "sys_cmd(%s,%s,...) exited with status %d\n", + path, arg, WEXITSTATUS(rv)); + else if(WIFSIGNALED(rv)) + Message(M_ERR, "sys_cmd(%s,%s,...) exited with signal %d (%s)%s\n", + path, arg, WTERMSIG(rv), strsignal(WTERMSIG(rv)), + WCOREDUMP(rv) ? " - core dumped" : ""); + else + Message(M_ERR, "sys_cmd(%s,%s,...) exited with wstat %#x", + path, arg, rv); + } } else if (c==0) { char *args[100]; int i; @@ -160,17 +164,18 @@ int sys_cmd(const char *path, const char *arg, ...) if the execvp() fails this seems somewhat pointless, and increases the chance of the child process failing before it gets to exec(). */ - args[0]=(char *)arg; + va_start(ap,arg); + args[0]=(char *)arg; /* program name */ i=1; while ((args[i++]=va_arg(ap,char *))); execvp(path,args); - exit(1); + fprintf(stderr, "sys_cmd(%s,%s,...): %s\n", path, arg, strerror(errno)); + _exit(1); } else { /* Error */ - fatal_perror("sys_cmd(%s,%s,...)"); + fatal_perror("sys_cmd(%s,%s,...)", path, arg); } - va_end(ap); return rv; } -- 1.6.4.2 From rjk at terraraq.org.uk Sat Jul 9 17:13:57 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Sat, 09 Jul 2011 17:13:57 +0100 Subject: [PATCH 2/2] sys_cmd error handling improved in the following ways: (1) If the subprocess exits nonzero then the exit status is unpicked and logged. (2) If the exec in the child fails, the command and errno string are written to stderr (which should end up in secnet's usual log output). (3) _exit() is used instead of exit(), to avoid any possibility of craziness with stdio/atexit/etc. In-Reply-To: <1310219944-75586-3-git-send-email-rjk@terraraq.org.uk> References: <1310219944-75586-1-git-send-email-rjk@terraraq.org.uk> <1310219944-75586-2-git-send-email-rjk@terraraq.org.uk> <1310219944-75586-3-git-send-email-rjk@terraraq.org.uk> Message-ID: <4E187E45.4020803@terraraq.org.uk> I'm not sure what git-send-email was playing at there. The description in a more readable form: sys_cmd error handling improved in the following ways: (1) If the subprocess exits nonzero then the exit status is unpicked and logged. (2) If the exec in the child fails, the command and errno string are written to stderr (which should end up in secnet's usual log output). (3) _exit() is used instead of exit(), to avoid any possibility of craziness with stdio/atexit/etc. ttfn/rjk From rjk at terraraq.org.uk Sun Jul 10 12:23:42 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Sun, 10 Jul 2011 12:23:42 +0100 Subject: [PATCH 0/3] Improve Mac OSX support Message-ID: <1310297025-91831-1-git-send-email-rjk@terraraq.org.uk> This is the current contents of my machacks branch. ttfn/rjk From rjk at terraraq.org.uk Sun Jul 10 12:23:43 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Sun, 10 Jul 2011 12:23:43 +0100 Subject: [PATCH 1/3] Update Mac-specific notes. In-Reply-To: <1310297025-91831-1-git-send-email-rjk@terraraq.org.uk> References: <1310297025-91831-1-git-send-email-rjk@terraraq.org.uk> Message-ID: <1310297025-91831-2-git-send-email-rjk@terraraq.org.uk> - how (and why) to enable IP forwarding - correct 'launchctl unload' invocation Signed-off-by: Richard Kettlewell --- README.mac | 10 +++++++++- setup.mac | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/README.mac b/README.mac index 899f4d1..d6d60a8 100644 --- a/README.mac +++ b/README.mac @@ -25,7 +25,15 @@ To stop secnet: sudo launchctl stop uk.org.greenend.secnet To uninstall: - sudo launchctl unload uk.org.greenend.secnet + sudo launchctl unload /Library/LaunchDaemons/uk.org.greenend.secnet.plist sudo rm -f /Library/LaunchDaemons/uk.org.greenend.secnet.plist +If you need to enable IP forwarding: + sudo sysctl -w net.inet.ip.forwarding=1 + +(Note that on a Mac, you need to enable IP forwarding if you want to +route to addresses on one interface via another; i.e. if you expect to +be able to reach an address on en0 with a packet delivered through +tun0, IP forwarding must be turned on.) + Richard Kettlewell 2011-06-18 diff --git a/setup.mac b/setup.mac index 4473a2e..ff1ae73 100755 --- a/setup.mac +++ b/setup.mac @@ -62,5 +62,5 @@ echo "To stop secnet:" echo " sudo launchctl stop uk.org.greenend.secnet" echo echo "To uninstall:" -echo " sudo launchctl unload uk.org.greenend.secnet" +echo " sudo launchctl unload /Library/LaunchDaemons/uk.org.greenend.secnet.plist" echo " sudo rm -f /Library/LaunchDaemons/uk.org.greenend.secnet.plist" -- 1.6.4.2 From rjk at terraraq.org.uk Sun Jul 10 12:23:44 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Sun, 10 Jul 2011 12:23:44 +0100 Subject: [PATCH 2/3] .gitignore XCode-specific files. In-Reply-To: <1310297025-91831-2-git-send-email-rjk@terraraq.org.uk> References: <1310297025-91831-1-git-send-email-rjk@terraraq.org.uk> <1310297025-91831-2-git-send-email-rjk@terraraq.org.uk> Message-ID: <1310297025-91831-3-git-send-email-rjk@terraraq.org.uk> Checking those files in doesn't make much sense as they change at the drop of a hat. Signed-off-by: Richard Kettlewell --- .gitignore | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/.gitignore b/.gitignore index 999fbee..7c82629 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,5 @@ debian/secnet.debhelper.log debian/*.debhelper debian/secnet debian/secnet.substvars +*.xcodeproj +build -- 1.6.4.2 From rjk at terraraq.org.uk Sun Jul 10 12:23:45 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Sun, 10 Jul 2011 12:23:45 +0100 Subject: [PATCH 3/3] Detect Fink automatically. In-Reply-To: <1310297025-91831-3-git-send-email-rjk@terraraq.org.uk> References: <1310297025-91831-1-git-send-email-rjk@terraraq.org.uk> <1310297025-91831-2-git-send-email-rjk@terraraq.org.uk> <1310297025-91831-3-git-send-email-rjk@terraraq.org.uk> Message-ID: <1310297025-91831-4-git-send-email-rjk@terraraq.org.uk> Saves a bit of manual labour when building on OSX. Signed-off-by: Richard Kettlewell --- README.mac | 2 +- configure | 6 ++++++ configure.in | 6 ++++++ 3 files changed, 13 insertions(+), 1 deletions(-) diff --git a/README.mac b/README.mac index d6d60a8..d8b70ab 100644 --- a/README.mac +++ b/README.mac @@ -6,7 +6,7 @@ How to install secnet on a Fink-equipped OS X system: make sudo make install - Build secnet: - ./configure CPPFLAGS=-I/sw/include LDFLAGS=-L/sw/lib + ./configure make sudo make install - Install tuntap for OSX from http://tuntaposx.sourceforge.net/ diff --git a/configure b/configure index 0bb23b6..761971c 100755 --- a/configure +++ b/configure @@ -2263,6 +2263,12 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $ ac_compiler_gnu=$ac_cv_c_compiler_gnu +# Use Fink if available +if test -d /sw; then + CPPFLAGS="-I/sw/include ${CPPFLAGS}" + LDFLAGS="-L/sw/lib ${LDFLAGS}" +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} diff --git a/configure.in b/configure.in index a548dac..03e27a6 100644 --- a/configure.in +++ b/configure.in @@ -11,6 +11,12 @@ AC_REVISION($Id: configure.in,v 1.4 2002/09/09 22:05:02 steve Exp $) AC_LANG_C +# Use Fink if available +if test -d /sw; then + CPPFLAGS="-I/sw/include ${CPPFLAGS}" + LDFLAGS="-L/sw/lib ${LDFLAGS}" +fi + AC_PROG_MAKE_SET AC_PROG_CC AC_PROG_INSTALL -- 1.6.4.2 From rjk at terraraq.org.uk Sun Jul 10 12:42:22 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Sun, 10 Jul 2011 12:42:22 +0100 Subject: [PATCH 3/4] Test example: Files for a simple testing configuration now in test-example/ In-Reply-To: <1309864212-14705-4-git-send-email-ijackson@chiark.greenend.org.uk> References: <1309864212-14705-1-git-send-email-ijackson@chiark.greenend.org.uk> <1309864212-14705-2-git-send-email-ijackson@chiark.greenend.org.uk> <1309864212-14705-3-git-send-email-ijackson@chiark.greenend.org.uk> <1309864212-14705-4-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <4E19901E.6030703@terraraq.org.uk> > +To run the test: > + Run the makefile: > + make -C test-example/ The makefile referred to seems to be missing. ttfn/rjk From rjk at terraraq.org.uk Sun Jul 10 13:38:11 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Sun, 10 Jul 2011 13:38:11 +0100 Subject: [PATCH 1/1] Security: Reduce impact of bogus key setup packet DoS In-Reply-To: <1309996850-31404-1-git-send-email-ijackson@chiark.greenend.org.uk> References: <1309996850-31404-1-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <4E199D33.5040408@terraraq.org.uk> On 07/07/2011 01:00, Ian Jackson wrote: [...] > In this patch we fix the latter problem. It is simply a bug that the > session key and data transport peer address (resulting from a previous > successful key exchange) are discarded when a key setup fails. > > We also provide a test program "test-example/bogus-setutp-request.c" > which can be used to reproduce the problem. I had to modify the test program slightly to get it to work properly (diff attached). The DoS and the enter_wait_state() patch behave as described. Thoughts: 1) There's a comment in the code suggesting maintaining a blacklist of bad setup sources. I'm not really convinced by this suggestion: slow, overloaded or poorly connected systems might fail to complete setup for an extended period, making them difficult to distinguish from a malicious source. 2) The setup state is broken out into a separate chunk in 'struct site'. Assuming that reflects reality (which I've not checked!) it doesn't seem like it would be especially onerous to have multiple parallel key exchanges selected by source IP address, and to accept whichever completed first and junk the rest. Neither of these help if the attacker has many IP addresses available (in both cases there would have to be some kind of size limit to prevent resource exhaustion). 3) Often the legitimate setup source for a site will be reasonably easy to discover out of band - for instance there may be a DNS name that reliably points at it. secnet could limit what addresses it would accept MSG1 from for such sites. This doesn't introduce a new dependency as it already uses DNS to discover the target address (in fact it would usually be the same name). This does not help if the legitimate peer does not have a stable name. ttfn/rjk -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: bsr.diff URL: From ijackson at chiark.greenend.org.uk Sun Jul 10 22:55:20 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Sun, 10 Jul 2011 22:55:20 +0100 Subject: [PATCH 3/4] Test example: Files for a simple testing configuration now in test-example/ In-Reply-To: <4E19901E.6030703@terraraq.org.uk> References: <1309864212-14705-1-git-send-email-ijackson@chiark.greenend.org.uk> <1309864212-14705-2-git-send-email-ijackson@chiark.greenend.org.uk> <1309864212-14705-3-git-send-email-ijackson@chiark.greenend.org.uk> <1309864212-14705-4-git-send-email-ijackson@chiark.greenend.org.uk> <4E19901E.6030703@terraraq.org.uk> Message-ID: <19994.8136.200821.473936@chiark.greenend.org.uk> Richard Kettlewell writes ("Re: [PATCH 3/4] Test example: Files for a simple testing configuration now in test-example/"): > > +To run the test: > > + Run the makefile: > > + make -C test-example/ > > The makefile referred to seems to be missing. Oops. An overzealous .gitignore. I will fix and resend. Ian. From ijackson at chiark.greenend.org.uk Sun Jul 10 22:58:23 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Sun, 10 Jul 2011 22:58:23 +0100 Subject: [PATCH 2/2] sys_cmd error handling improved in the following ways: (1) If the subprocess exits nonzero then the exit status is unpicked and logged. (2) If the exec in the child fails, the command and errno string are written to stderr (which should end up in secnet's usual log output). (3) _exit() is used instead of exit(), to avoid any possibility of craziness with stdio/atexit/etc. In-Reply-To: <4E187E45.4020803@terraraq.org.uk> References: <1310219944-75586-1-git-send-email-rjk@terraraq.org.uk> <1310219944-75586-2-git-send-email-rjk@terraraq.org.uk> <1310219944-75586-3-git-send-email-rjk@terraraq.org.uk> <4E187E45.4020803@terraraq.org.uk> Message-ID: <19994.8319.846409.887853@chiark.greenend.org.uk> Richard Kettlewell writes ("Re: [PATCH 2/2] sys_cmd error handling improved in the following ways: (1) If the subprocess exits nonzero then the exit status is unpicked and logged. (2) If the exec in the child fails, the command and errno string are written to stderr (which should end up in secnet's usual log output). (3) _exit() is used instead of exit(), to avoid any possibility of craziness with stdio/atexit/etc."): > I'm not sure what git-send-email was playing at there. The description > in a more readable form: The first line of the commit message is supposed to be a short summary (often called the "subject" as it goes into email subjects), and it's conventional to leave a blank line after it. I think git-format-patch/git-send-email probably think the whole first "paragraph" is supposed to be the "subject". If you leavve a blank line it will do the right thing. > sys_cmd error handling improved in the following ways: > (1) If the subprocess exits nonzero then the exit status > is unpicked and logged. Although for this commit message "sys_cmd error handling improved in the following ways:" isn't really a self-contained subject/summary. I would say ] sys_cmd error handling improved ] ] (1) If the subprocess exits nonzero then the exit status ] is unpicked and logged. ] (2) etc. Ian. From ijackson at chiark.greenend.org.uk Sun Jul 10 23:00:06 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Sun, 10 Jul 2011 23:00:06 +0100 Subject: [PATCH 1/4] resolver: support IPv4 address literals In-Reply-To: <4E18215F.8030209@terraraq.org.uk> References: <1309864212-14705-1-git-send-email-ijackson@chiark.greenend.org.uk> <1309864212-14705-2-git-send-email-ijackson@chiark.greenend.org.uk> <4E18215F.8030209@terraraq.org.uk> Message-ID: <19994.8422.633945.817023@chiark.greenend.org.uk> Richard Kettlewell writes ("Re: [PATCH 1/4] resolver: support IPv4 address literals"): > On 05/07/2011 12:10, Ian Jackson wrote: > > + const int maxlitlen=50; > > + > > + int l=strlen(name); > > Oh, I missed this earlier. Will overflow if supplied with a > ridiculously long string (e.g. on a 64-bit platform). Probably not a > big deal, but... Yes, you're right, it should be fixed. Shame strlen returns a size_t ... Ian. From ijackson at chiark.greenend.org.uk Sun Jul 10 23:20:50 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Sun, 10 Jul 2011 23:20:50 +0100 Subject: [PATCH 1/1] Security: Reduce impact of bogus key setup packet DoS In-Reply-To: <4E199D33.5040408@terraraq.org.uk> References: <1309996850-31404-1-git-send-email-ijackson@chiark.greenend.org.uk> <4E199D33.5040408@terraraq.org.uk> Message-ID: <19994.9666.502762.744662@chiark.greenend.org.uk> Richard Kettlewell writes ("Re: [PATCH 1/1] Security: Reduce impact of bogus key setup packet DoS"): > I had to modify the test program slightly to get it to work properly > (diff attached). Thanks. I don't know why my kernel tolerated that mistake! > The DoS and the enter_wait_state() patch behave as > described. :-/ > Thoughts: > > 1) There's a comment in the code suggesting maintaining a blacklist of > bad setup sources. I'm not really convinced by this suggestion: slow, > overloaded or poorly connected systems might fail to complete setup for > an extended period, making them difficult to distinguish from a > malicious source. Quite so. > 2) The setup state is broken out into a separate chunk in 'struct site'. > Assuming that reflects reality (which I've not checked!) it doesn't > seem like it would be especially onerous to have multiple parallel key > exchanges selected by source IP address, and to accept whichever > completed first and junk the rest. Well, except that key exchange packets can consume computational resources doing public key crypto. Since without --enable-hacky-parallel secnet is single threaded that would also be a possible DoS for data transfer, and with that option it's an opportunity to DoS the host by getting secnet to fork lots. > Neither of these help if the attacker has many IP addresses available > (in both cases there would have to be some kind of size limit to prevent > resource exhaustion). I'm afraid think the right answer is a protocol change. The initiator should be required to prove that they can receive packets sent to their address, and then the first thing after that should be signed by the initiator (and there should be a global ratelimit for verification attempts). But I don't propose to do anything like that soon. > 3) Often the legitimate setup source for a site will be reasonably easy > to discover out of band - for instance there may be a DNS name that > reliably points at it. secnet could limit what addresses it would > accept MSG1 from for such sites. This doesn't introduce a new > dependency as it already uses DNS to discover the target address (in > fact it would usually be the same name). The DNS, while harder to attack, is of course not really secure in that sense. This would be a useful feature I think. It would have to be a site option because some users are currently relying on the fact that secnet does not insist on its peer having the right address, even if a DNS name is specified in the config. I think we should revisit this after my "mobile" option is in thhe tree. > This does not help if the legitimate peer does not have a stable name. Yes. I don't have a solution for that... Ian. From ijackson at chiark.greenend.org.uk Sun Jul 10 23:27:02 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Sun, 10 Jul 2011 23:27:02 +0100 Subject: [PATCH 2/2] sys_cmd error handling improved in the following ways: (1) If the subprocess exits nonzero then the exit status is unpicked and logged. (2) If the exec in the child fails, the command and errno string are written to stderr (which should end up in secnet's usual log output). (3) _exit() is used instead of exit(), to avoid any possibility of craziness with stdio/atexit/etc. In-Reply-To: <1310219944-75586-3-git-send-email-rjk@terraraq.org.uk> References: <1310219944-75586-1-git-send-email-rjk@terraraq.org.uk> <1310219944-75586-2-git-send-email-rjk@terraraq.org.uk> <1310219944-75586-3-git-send-email-rjk@terraraq.org.uk> Message-ID: <19994.10038.626678.581670@chiark.greenend.org.uk> Richard Kettlewell writes ("[PATCH 2/2] sys_cmd error handling improved in the following ways: (1) If the subprocess exits nonzero then the exit status is unpicked and logged. (2) If the exec in the child fails, the command and errno string are written to stderr (which should end up in secnet's usual log output). (3) _exit() is used instead of exit(), to avoid any possibility of craziness with stdio/atexit/etc."): > From: Richard Kettlewell The substance looks good to me. You should probably try to keep to theh existing coding style though: whitespace in "if (" was the thing that jumped out at me. We should have sys_vcmd I guess but perhaps not now. If you want to push your "packet cannot be delivered" despite the lack of tv_now, go ahead. I'll produce the tv_now patch RSN now honest, ahm. Ian. From ijackson at chiark.greenend.org.uk Sun Jul 10 23:29:11 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Sun, 10 Jul 2011 23:29:11 +0100 Subject: [PATCH 1/3] Update Mac-specific notes. [and 2 more messages] In-Reply-To: <1310297025-91831-2-git-send-email-rjk@terraraq.org.uk>, <1310297025-91831-3-git-send-email-rjk@terraraq.org.uk>, <1310297025-91831-4-git-send-email-rjk@terraraq.org.uk> References: <1310297025-91831-1-git-send-email-rjk@terraraq.org.uk> <1310297025-91831-2-git-send-email-rjk@terraraq.org.uk> <1310297025-91831-3-git-send-email-rjk@terraraq.org.uk> <1310297025-91831-4-git-send-email-rjk@terraraq.org.uk> Message-ID: <19994.10167.190116.754358@chiark.greenend.org.uk> Richard Kettlewell writes ("[PATCH 1/3] Update Mac-specific notes."): > - how (and why) to enable IP forwarding > - correct 'launchctl unload' invocation I don't have an opinion on these - I think you should just push the mac-specific notes changes. Richard Kettlewell writes ("[PATCH 2/3] .gitignore XCode-specific files."): > Checking those files in doesn't make much sense as they change at the > drop of a hat. ... > +*.xcodeproj > +build This should be /build I think. In case we invent a file "build" somewhere else. Richard Kettlewell writes ("[PATCH 3/3] Detect Fink automatically."): > Saves a bit of manual labour when building on OSX. ... > +# Use Fink if available > +if test -d /sw; then > + CPPFLAGS="-I/sw/include ${CPPFLAGS}" > + LDFLAGS="-L/sw/lib ${LDFLAGS}" > +fi Perhaps this should produce a message of some kind ? Ian. From ijackson at chiark.greenend.org.uk Sun Jul 10 23:49:25 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Sun, 10 Jul 2011 23:49:25 +0100 Subject: [PATCH 2/2] sys_cmd error handling improved in the following ways: (1) If the subprocess exits nonzero then the exit status is unpicked and logged. (2) If the exec in the child fails, the command and errno string are written to stderr (which should end up in secnet's usual log output). (3) _exit() is used instead of exit(), to avoid any possibility of craziness with stdio/atexit/etc. In-Reply-To: <19994.10038.626678.581670@chiark.greenend.org.uk> References: <1310219944-75586-1-git-send-email-rjk@terraraq.org.uk> <1310219944-75586-2-git-send-email-rjk@terraraq.org.uk> <1310219944-75586-3-git-send-email-rjk@terraraq.org.uk> <19994.10038.626678.581670@chiark.greenend.org.uk> Message-ID: <19994.11381.260713.110414@chiark.greenend.org.uk> I wrote: > If you want to push your "packet cannot be delivered" despite the lack > of tv_now, go ahead. I'll produce the tv_now patch RSN now honest, ahm. Um. I went to try to find this patch of mine so I could expedite it but it turned out that it's already in master, as 698280de "make tv_now and now into globals". Look for "now" in secnet.h. Ian. From ijackson at chiark.greenend.org.uk Sun Jul 10 23:55:24 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Sun, 10 Jul 2011 23:55:24 +0100 Subject: [PATCH v2 00/06] secnet: Test example config and DoS fix Message-ID: <1310338530-11143-1-git-send-email-ijackson@chiark.greenend.org.uk> This is the revised version of my test-example series, with the DoS fix for failed key setups added on the end. I used ssize_t for the return value from strlen. I think in general code should not be expected to deal with strings whose lengths don't fit in ssize_t unless this requirement is specifically mentioned. From ijackson at chiark.greenend.org.uk Sun Jul 10 23:55:25 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Sun, 10 Jul 2011 23:55:25 +0100 Subject: [PATCH 1/6] Build system: make several patterns in .gitignore absolute paths In-Reply-To: <1310338530-11143-1-git-send-email-ijackson@chiark.greenend.org.uk> References: <1310338530-11143-1-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1310338530-11143-2-git-send-email-ijackson@chiark.greenend.org.uk> Specifically, version.c, and the files which are generated by autoconf/automake but whose names do not unambiguously say so. Signed-off-by: Ian Jackson --- .gitignore | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 999fbee..1886549 100644 --- a/.gitignore +++ b/.gitignore @@ -2,14 +2,14 @@ *.d conffile.tab.[ch] conffile.yy.[ch] -version.c +/version.c /secnet -config.log -config.h -config.status -stamp-h -Makefile +/config.log +/config.h +/config.status +/stamp-h +/Makefile autom4te.cache -- 1.5.6.5 From ijackson at chiark.greenend.org.uk Sun Jul 10 23:55:26 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Sun, 10 Jul 2011 23:55:26 +0100 Subject: [PATCH 2/6] resolver: support IPv4 address literals In-Reply-To: <1310338530-11143-2-git-send-email-ijackson@chiark.greenend.org.uk> References: <1310338530-11143-1-git-send-email-ijackson@chiark.greenend.org.uk> <1310338530-11143-2-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1310338530-11143-3-git-send-email-ijackson@chiark.greenend.org.uk> Signed-off-by: Ian Jackson IP ADDR LIT size_t strlen --- resolver.c | 16 ++++++++++++++++ 1 files changed, 16 insertions(+), 0 deletions(-) diff --git a/resolver.c b/resolver.c index f60b112..033ddc1 100644 --- a/resolver.c +++ b/resolver.c @@ -6,6 +6,8 @@ #error secnet requires ADNS version 1.0 or above #endif #include +#include +#include struct adns { @@ -28,6 +30,20 @@ static bool_t resolve_request(void *sst, cstring_t name, struct adns *st=sst; struct query *q; int rv; + const int maxlitlen=50; + + ssize_t l=strlen(name); + if (name[0]=='[' && l2 && name[l-1]==']') { + char trimmed[maxlitlen+1]; + memcpy(trimmed,name+1,l-2); + trimmed[l-2]=0; + struct in_addr ia; + if (inet_aton(trimmed,&ia)) + cb(cst,&ia); + else + cb(cst,0); + return True; + } q=safe_malloc(sizeof *q,"resolve_request"); q->cst=cst; -- 1.5.6.5 From ijackson at chiark.greenend.org.uk Sun Jul 10 23:55:27 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Sun, 10 Jul 2011 23:55:27 +0100 Subject: [PATCH 3/6] build system: add *.pyc to .gitignore In-Reply-To: <1310338530-11143-3-git-send-email-ijackson@chiark.greenend.org.uk> References: <1310338530-11143-1-git-send-email-ijackson@chiark.greenend.org.uk> <1310338530-11143-2-git-send-email-ijackson@chiark.greenend.org.uk> <1310338530-11143-3-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1310338530-11143-4-git-send-email-ijackson@chiark.greenend.org.uk> Python tends to leave this dropping. Signed-off-by: Ian Jackson --- .gitignore | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/.gitignore b/.gitignore index 1886549..f554932 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ *.o *.d +*.pyc conffile.tab.[ch] conffile.yy.[ch] /version.c -- 1.5.6.5 From ijackson at chiark.greenend.org.uk Sun Jul 10 23:55:28 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Sun, 10 Jul 2011 23:55:28 +0100 Subject: [PATCH 4/6] Test example: Files for a simple testing configuration now in test-example/ In-Reply-To: <1310338530-11143-4-git-send-email-ijackson@chiark.greenend.org.uk> References: <1310338530-11143-1-git-send-email-ijackson@chiark.greenend.org.uk> <1310338530-11143-2-git-send-email-ijackson@chiark.greenend.org.uk> <1310338530-11143-3-git-send-email-ijackson@chiark.greenend.org.uk> <1310338530-11143-4-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1310338530-11143-5-git-send-email-ijackson@chiark.greenend.org.uk> Including a set of dummy keys, and dummy IP addresses in 172.18.232.0/28. Signed-off-by: Ian Jackson --- .gitignore | 3 +++ test-example/Makefile | 7 +++++++ test-example/README | 21 +++++++++++++++++++++ test-example/common.conf | 16 ++++++++++++++++ test-example/inside.conf | 16 ++++++++++++++++ test-example/inside.key.b64 | 10 ++++++++++ test-example/inside.key.pub | 1 + test-example/outside.conf | 16 ++++++++++++++++ test-example/outside.key.b64 | 10 ++++++++++ test-example/outside.key.pub | 1 + test-example/sites | 25 +++++++++++++++++++++++++ 11 files changed, 126 insertions(+), 0 deletions(-) create mode 100644 test-example/Makefile create mode 100644 test-example/README create mode 100644 test-example/common.conf create mode 100644 test-example/inside.conf create mode 100644 test-example/inside.key.b64 create mode 100644 test-example/inside.key.pub create mode 100644 test-example/outside.conf create mode 100644 test-example/outside.key.b64 create mode 100644 test-example/outside.key.pub create mode 100644 test-example/sites diff --git a/.gitignore b/.gitignore index f554932..e29b9be 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,6 @@ debian/secnet.debhelper.log debian/*.debhelper debian/secnet debian/secnet.substvars + +test-example/*.key +test-example/sites.conf diff --git a/test-example/Makefile b/test-example/Makefile new file mode 100644 index 0000000..67230b8 --- /dev/null +++ b/test-example/Makefile @@ -0,0 +1,7 @@ +all: sites.conf inside.key outside.key + +%.key: %.key.b64 + base64 -d <$< >$@.new && mv -f $@.new $@ + +sites.conf: ../make-secnet-sites sites Makefile + ../make-secnet-sites sites sites.conf diff --git a/test-example/README b/test-example/README new file mode 100644 index 0000000..a6416f6 --- /dev/null +++ b/test-example/README @@ -0,0 +1,21 @@ +This directory contains some files useful for ad-hoc tests. +With these it is possible to run a test of secnet on a Linux host +even if that Linux host does not have another working network connection. + +The keys here are (obviously) public. They were generated like this: + ssh-keygen -C inside at example.com -f test-example/inside.key -t rsa1 -b 1024 + ssh-keygen -C outside at example.com -f test-example/outside.key -t rsa1 -b 1024 + # edit sites to paste {inside,outside}.key.pub into pubkey lines + base64 inside.key.b64 + base64 outside.key.b64 + +To run the test: + Run the makefile: + make -C test-example/ + In one window, as root + ./secnet -dvnc test-example/inside.conf + And in another + ./secnet -dvnc test-example/outside.conf + Then in a third + ping -I secnet-test-i 172.18.232.2 + diff --git a/test-example/common.conf b/test-example/common.conf new file mode 100644 index 0000000..6f2fef1 --- /dev/null +++ b/test-example/common.conf @@ -0,0 +1,16 @@ +log logfile { + filename "/dev/tty"; + class "info","notice","warning","error","security","fatal"; +}; +system { +}; +resolver adns { +}; +log-events "setup-init","setup-timeout","activate-key","timeout-key","errors", + "security"; +random randomfile("/dev/urandom",no); +transform serpent256-cbc { + max-sequence-skew 10; +}; +include test-example/sites.conf +sites map(site,vpn/test-example/all-sites); diff --git a/test-example/inside.conf b/test-example/inside.conf new file mode 100644 index 0000000..775d593 --- /dev/null +++ b/test-example/inside.conf @@ -0,0 +1,16 @@ +netlink tun { + name "netlink-tun"; # Printed in log messages from this netlink + local-address "172.18.232.9"; + secnet-address "172.18.232.10"; + remote-networks "172.18.232.0/28"; + mtu 500; + buffer sysbuffer(2048); + interface "secnet-test-i"; +}; +comm udp { + port 16097; + buffer sysbuffer(4096); +}; +local-name "test-example/inside/inside"; +local-key rsa-private("test-example/inside.key"); +include test-example/common.conf diff --git a/test-example/inside.key.b64 b/test-example/inside.key.b64 new file mode 100644 index 0000000..d384c7c --- /dev/null +++ b/test-example/inside.key.b64 @@ -0,0 +1,10 @@ +U1NIIFBSSVZBVEUgS0VZIEZJTEUgRk9STUFUIDEuMQoAAAAAAAAAAAQABAC5N9rmU46hhdLO1FVh +Efkc9cq+x/UdC/a+nt0yM4HswxfChfJpcHq008Hkd4KOqRZORG7N5Q8fKPpkrnt3T3qSDX4P5HOW +5Q+2Qc82h1hO4mDbHo2xqmp4hv/88fHgPQTW9MffriDFs24HTt7uOqvx5LNtdmrw5ws6cXuyLwan +lQARAQABAAAAEmluc2lkZUBleGFtcGxlLmNvbe8z7zMD/1/rgT3PAAq+V1ItvJmsySoqUHlE7LfC +PmKxuzQIYLzQvDlNTSE10xZapAtBqSdggeC+p/ORMKeefS4u/lnnmz2tW9TlbtwWfj5Bwm/ftUZR +8BhelZQn5+/vTv1jLZ9dibLhemd20XxpMRIoOg+1w4xfbh1DoJbqs8OCCPPnNVJxAf9h3Hq0x84a +P0JOgyFFNatWcRKVJxapseeZPnpIAnkaDZ0KirE1RZFkHbfL4HFL3kI3MI657rE7rSC2yakvJtX9 +AgDD98/vGKw19bSdM8dHbocQQdDmn3SG5U9psbkvNQh06seKNL9QOeH2iHqjzBXmwTjPiWphdsVP +dFOBy1VE52YPAgDx9QU0xrSytFrjcqlP/FICaBiuJ9g0t4RbYBcm2iZaXLwXLDTX91arNJJrzblX +9yMkHDBDw9j1nKXnig+8dtwbAAAAAA== diff --git a/test-example/inside.key.pub b/test-example/inside.key.pub new file mode 100644 index 0000000..85fea76 --- /dev/null +++ b/test-example/inside.key.pub @@ -0,0 +1 @@ +1024 65537 130064631890186713927887504218626486455931306300999583387009075747001546036643522074275473238061323169592347601185592753550279410171535737146240085267000508853176463710554801101055212967131924064664249613912656320653505750073021702169423354903540699008756137338575553686987244488914481168225136440872431691669 inside at example.com diff --git a/test-example/outside.conf b/test-example/outside.conf new file mode 100644 index 0000000..f1a5228 --- /dev/null +++ b/test-example/outside.conf @@ -0,0 +1,16 @@ +netlink tun { + name "netlink-tun"; # Printed in log messages from this netlink + local-address "172.18.232.1"; + secnet-address "172.18.232.2"; + remote-networks "172.18.232.0/28"; + mtu 500; + buffer sysbuffer(2048); + interface "secnet-test-o"; +}; +comm udp { + port 16096; + buffer sysbuffer(4096); +}; +local-name "test-example/outside/outside"; +local-key rsa-private("test-example/outside.key"); +include test-example/common.conf diff --git a/test-example/outside.key.b64 b/test-example/outside.key.b64 new file mode 100644 index 0000000..f8ed4aa --- /dev/null +++ b/test-example/outside.key.b64 @@ -0,0 +1,10 @@ +U1NIIFBSSVZBVEUgS0VZIEZJTEUgRk9STUFUIDEuMQoAAAAAAAAAAAQABAC4D2q3B/nZUjsGMX72 +5FrgEB1y0uYS732QF/NXOEs9FA8/xmM68NF8JRfCctlCm9kQ9t/0xW+wOQTNg0BFIdgbZjXIwXLy +K9rreM1G1BsTjROtiz1UyjZMpo3Z89SWjtYCVN/UldRhakw/o0vrEKkZDTxiryhhYCGDUkONNsa5 +1QARAQABAAAAE291dHNpZGVAZXhhbXBsZS5jb23IlsiWA/9AO6kbPN5VmBvfGnDbim+oWBde1fjS +zN895Q3X915Sb2iu8fX5QMdqkqtLAbeORkMnZ3BaxHgowI1Lhy1rstbuiUcd3WWB6xUDcQll85Cy ++2IFfvFDKH7HsrzxgWx9M23WewlTje2NmVF0Y3xR39w2jUCLuEcyaWdPPQiLTucCgQH/axUYwPI5 +6QEKPiONve88GpehGCjereP5EjWTJomjQI+brOhnPckiWLwXXtWZoa894jpbVT8BtHNdDUg2gPFV +pwIA0FQowUgwxCnCoNZe/v/K5zwP3ar8OPoBV2c8rnEuZ2sR0AdLcBpaCpOQf7LKk9p+GUOHlMJy +hkrz7tAitvXEdQIA4i2dOA/PVYD6ZCZrwY5SToBmVtOzt2TVdhLbB/XDJ91ydl0uDdyN0Sn/Dyx+ +I55YwyhLA8zNV8mL4ZQS8OLz4QAAAAA= diff --git a/test-example/outside.key.pub b/test-example/outside.key.pub new file mode 100644 index 0000000..5e4cc0f --- /dev/null +++ b/test-example/outside.key.pub @@ -0,0 +1 @@ +1024 65537 129251483458784900555621175262818292872587807329014927540074484804119474262261383244074013537736576331652560727149001626325243856012659665194546933097292703586821422085819615124517093786704646988649444946154384037948502112302285511195679291084694375811092516151263088200304199780052361048758446082354317801941 outside at example.com diff --git a/test-example/sites b/test-example/sites new file mode 100644 index 0000000..5aee3d8 --- /dev/null +++ b/test-example/sites @@ -0,0 +1,25 @@ +vpn test-example +contact devnull at example.com +dh 8db5f2c15ac96d9f3382d1ef4688fba14dc7908ae7dfd71a9cfe7f479a75d506dc53f159aeaf488bde073fe544bc91c099f101fcf60074f30c06e36263c03ca9e07931ce3fc235fe1171dc6d9316fb097bd4362891e2c36e234e7c16b038fd97b1f165c710e90537de66ee4f54001f5712b050d4e07de3fba07607b19b64f6c3 2 +hash sha1 +key-lifetime 72000000 +restrict-nets 172.18.232.0/28 +setup-timeout 2000 +setup-retries 5 + +location inside root +site inside + networks 172.18.232.8/29 + peer 172.18.232.9 + address [127.0.0.1] 16097 + pubkey 1024 65537 130064631890186713927887504218626486455931306300999583387009075747001546036643522074275473238061323169592347601185592753550279410171535737146240085267000508853176463710554801101055212967131924064664249613912656320653505750073021702169423354903540699008756137338575553686987244488914481168225136440872431691669 inside at example.com + +location outside root +site outside + networks 172.18.232.0/29 + peer 172.18.232.1 + address [127.0.0.1] 16096 + pubkey 1024 65537 129251483458784900555621175262818292872587807329014927540074484804119474262261383244074013537736576331652560727149001626325243856012659665194546933097292703586821422085819615124517093786704646988649444946154384037948502112302285511195679291084694375811092516151263088200304199780052361048758446082354317801941 outside at example.com + + + -- 1.5.6.5 From ijackson at chiark.greenend.org.uk Sun Jul 10 23:55:29 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Sun, 10 Jul 2011 23:55:29 +0100 Subject: [PATCH 5/6] Test example: instructions for running under valgrind memcheck. In-Reply-To: <1310338530-11143-5-git-send-email-ijackson@chiark.greenend.org.uk> References: <1310338530-11143-1-git-send-email-ijackson@chiark.greenend.org.uk> <1310338530-11143-2-git-send-email-ijackson@chiark.greenend.org.uk> <1310338530-11143-3-git-send-email-ijackson@chiark.greenend.org.uk> <1310338530-11143-4-git-send-email-ijackson@chiark.greenend.org.uk> <1310338530-11143-5-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1310338530-11143-6-git-send-email-ijackson@chiark.greenend.org.uk> Signed-off-by: Ian Jackson --- test-example/README | 5 +++++ test-example/memcheck.suppressions | 14 ++++++++++++++ 2 files changed, 19 insertions(+), 0 deletions(-) create mode 100644 test-example/memcheck.suppressions diff --git a/test-example/README b/test-example/README index a6416f6..4c2eca3 100644 --- a/test-example/README +++ b/test-example/README @@ -19,3 +19,8 @@ To run the test: Then in a third ping -I secnet-test-i 172.18.232.2 +For running under valgrind memcheck, do something like this: + valgrind --num-callers=40 --gen-suppressions=yes --db-attach=yes \ + --leak-check=full --suppressions=test-example/memcheck.suppressions \ + ./secnet -dvnc test-example/outside.conf +NB that --num-callers is needed as secnet's stack can be deep. diff --git a/test-example/memcheck.suppressions b/test-example/memcheck.suppressions new file mode 100644 index 0000000..42080da --- /dev/null +++ b/test-example/memcheck.suppressions @@ -0,0 +1,14 @@ +{ + secnet_read_conffile + Memcheck:Leak + ... + fun:read_conffile + fun:main +} +{ + secnet_enter_phase + Memcheck:Leak + ... + fun:enter_phase + fun:main +} -- 1.5.6.5 From ijackson at chiark.greenend.org.uk Sun Jul 10 23:55:30 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Sun, 10 Jul 2011 23:55:30 +0100 Subject: [PATCH 6/6] Security: Reduce impact of bogus key setup packet DoS In-Reply-To: <1310338530-11143-6-git-send-email-ijackson@chiark.greenend.org.uk> References: <1310338530-11143-1-git-send-email-ijackson@chiark.greenend.org.uk> <1310338530-11143-2-git-send-email-ijackson@chiark.greenend.org.uk> <1310338530-11143-3-git-send-email-ijackson@chiark.greenend.org.uk> <1310338530-11143-4-git-send-email-ijackson@chiark.greenend.org.uk> <1310338530-11143-5-git-send-email-ijackson@chiark.greenend.org.uk> <1310338530-11143-6-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1310338530-11143-7-git-send-email-ijackson@chiark.greenend.org.uk> If a MSG1 (key setup initiation packet) is received containing expected local and remote site names, the receiving secnet will start a key setup attempt with details from that packet. MSG1 packets are (almost necessarily) unauthenticated, so anyone on the Internet can cause this to happen. secnet is only willing to have one key exchange attempt ongoing at once, and will ignore subsequent incoming MSG1s until it has dealt with the first key exchange attempt. So this means that an attacker who can send packets to any secnet instance can DoS secnet at session setup (or key renewal) time. All the attacker needs to know is the secnet site names, and the IP address and port number of one of the secnets. The attacker does not need to spoof their IP address or know any secret keys. If the attacker sends a contant stream of bogus packets they can probably prevent the link coming up at all. This is difficult to fix without changing the protocol. However, there is worse: when the key setup with the bogus peer eventually fails, as it must, secnet invalidates the current session key and its note of where to send actual data packets. It will then refuse to attempt a new key exchange for a timeout period. During this period, data packets will not flow. This means that sending one fairly easy to construct udp packet can cause a 20s outage. Worse, after this one packet has had its effect, the attacker can prevent the connection being reestablished, as described above. In this patch we fix the latter problem. It is simply a bug that the session key and data transport peer address (resulting from a previous successful key exchange) are discarded when a key setup fails. We also provide a test program "test-example/bogus-setutp-request.c" which can be used to reproduce the problem. Signed-off-by: Ian Jackson --- .gitignore | 1 + site.c | 1 - test-example/bogus-setup-request.c | 115 ++++++++++++++++++++++++++++++++++++ 3 files changed, 116 insertions(+), 1 deletions(-) create mode 100644 test-example/bogus-setup-request.c diff --git a/.gitignore b/.gitignore index e29b9be..8ef69ad 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,4 @@ debian/secnet.substvars test-example/*.key test-example/sites.conf +test-example/bogus-setup-request diff --git a/site.c b/site.c index 29efb25..006d9b4 100644 --- a/site.c +++ b/site.c @@ -928,7 +928,6 @@ static void enter_state_wait(struct site *st) slog(st,LOG_STATE,"entering state WAIT"); st->timeout=st->now+st->wait_timeout; st->state=SITE_WAIT; - st->peer_valid=False; set_link_quality(st); BUF_FREE(&st->buffer); /* will have had an outgoing packet in it */ /* XXX Erase keys etc. */ diff --git a/test-example/bogus-setup-request.c b/test-example/bogus-setup-request.c new file mode 100644 index 0000000..c9cfc3c --- /dev/null +++ b/test-example/bogus-setup-request.c @@ -0,0 +1,115 @@ +/* + test-example/bogus-setup-request 127.0.0.1 19098 test-example/inside/inside 127.0.0.1 16096 test-example/outside/outside + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + /* + | 00000 00 00 00 00 00 00 00 01 01 01 01 01 00 1a 74 65 ........ ......te | + ~~~~~~~~~~~ ~~~~~~~~~~~ ~~~~~~~~~~~ ~~~~~|~~~~~ + sessionid sender's type sender's + zero in index fixed for name + msg1 msg1 + + | 00010 73 74 2d 65 78 61 6d 70 6c 65 2f 69 6e 73 69 64 st-examp le/insid | + | 00020 65 2f 69 6e 73 69 64 65 00 1c 74 65 73 74 2d 65 e/inside ..test-e | + ~~~~~|~~~~~~~~~~~~~~~~~ + recipient's name + + | 00030 78 61 6d 70 6c 65 2f 6f 75 74 73 69 64 65 2f 6f xample/o utside/o | + | 00040 75 74 73 69 64 65 8d f0 3f 35 d6 c8 1f c0 utside.. ?5.... | + ~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~ + sender's nonce + */ + +typedef struct { + const char *name; + union { + struct sockaddr sa; + struct sockaddr_in sin; + }; +} Ep; + +static void endaddr(Ep *ep, char **argv, int base) { + int r; + ep->sin.sin_family=AF_INET; + r=inet_aton(argv[base],&ep->sin.sin_addr); assert(r); + ep->sin.sin_port=htons(atoi(argv[base+1])); + ep->name=argv[base+2]; +} + +static void endname(uint8_t **msgp, const Ep *ep) { + int l=strlen(ep->name); assert(l<=65535); + *(*msgp)++ = l>>8; + *(*msgp)++ = l; + memcpy(*msgp, ep->name, l); + *msgp += l; +} + +static Ep us, them; + +int main(int argc, char **argv) { + int r; + + assert(argc==7); + + endaddr(&us,argv,1); + endaddr(&them,argv,4); + + static const uint8_t mprefix[]={ + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, + 0x01, 0x01, 0x01, 0x01, + }; + static const uint8_t msuffix[]={ + /* our nonce, fixed he he */ + 0x8d, 0xf0, 0x3f, 0x35, 0xd6, 0xc8, 0x1f, 0xc0 + }; + int msglen= (sizeof(mprefix) + + 2+strlen(us.name) + + 2+strlen(them.name) + + sizeof(msuffix)); + uint8_t msg[msglen]; + uint8_t *msgp=msg; + +#define PREFIXSUFFIX(prefixsuffix) do { \ + memcpy(msgp,prefixsuffix,sizeof(prefixsuffix)); \ + msgp += sizeof(prefixsuffix); \ + }while(0) + + PREFIXSUFFIX(mprefix); + + endname(&msgp,&us); + endname(&msgp,&them); + + PREFIXSUFFIX(msuffix); + + assert(msgp == msg+msglen); + + struct protoent *proto=getprotobyname("udp"); + int fd=socket(AF_INET, SOCK_DGRAM, proto->p_proto); + r=bind(fd,&us.sa,sizeof(us.sin)); if (r) { perror("bind us2"); exit(1); } + + for (;;) { + r=sendto(fd,msg,msglen,0,&them.sa,sizeof(them.sin)); + if (r < 0) perror("sendto"); + + r=getchar(); + if (r==EOF) { + if (ferror(stdin)) { perror("getchar"); exit(1); } + break; + } + if (r!='\n') + break; + } + exit(0); +} -- 1.5.6.5 From ijackson at chiark.greenend.org.uk Mon Jul 11 01:44:46 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Mon, 11 Jul 2011 01:44:46 +0100 Subject: [PATCH 1/1] comm, site: pass a new "struct comm_addr" rather than sockaddr_in Message-ID: <1310345086-14174-1-git-send-email-ijackson@chiark.greenend.org.uk> This abstracts away the fact that the peer address is a sockaddr_in; instead, most of the code in site.c now only handles the peer address as an opaque structure. We put the struct comm_if* in the address structure too, as this will be useful later. Amongst other things, doing this arranges that the comm client knows which comm is notifying about an incoming packet. Previously the client was expected to "just know" because the only actual client in secnet is site which currently only deals with one comm. Also make the relevant arguments const-correct. Contains consequential changes the signatures of many functions but no intentional functional change. Signed-off-by: Ian Jackson --- secnet.h | 10 ++++++++-- site.c | 29 +++++++++++++++-------------- udp.c | 11 ++++++----- 3 files changed, 29 insertions(+), 21 deletions(-) diff --git a/secnet.h b/secnet.h index b60972f..9965534 100644 --- a/secnet.h +++ b/secnet.h @@ -303,16 +303,22 @@ struct rsaprivkey_if { /* COMM interface */ +struct comm_addr { + /* comm's client may assume this struct is pure data and freely copy it */ + struct comm_if *comm; + struct sockaddr_in sin; +}; + /* Return True if the packet was processed, and shouldn't be passed to any other potential receivers. */ typedef bool_t comm_notify_fn(void *state, struct buffer_if *buf, - struct sockaddr_in *source); + const struct comm_addr *source); typedef void comm_request_notify_fn(void *commst, void *nst, comm_notify_fn *fn); typedef void comm_release_notify_fn(void *commst, void *nst, comm_notify_fn *fn); typedef bool_t comm_sendmsg_fn(void *commst, struct buffer_if *buf, - struct sockaddr_in *dest); + const struct comm_addr *dest); struct comm_if { void *st; int32_t min_start_pad; diff --git a/site.c b/site.c index 29efb25..b273042 100644 --- a/site.c +++ b/site.c @@ -174,7 +174,7 @@ struct site { bool_t current_valid; uint64_t current_key_timeout; /* End of life of current key */ uint64_t renegotiate_key_time; /* When we can negotiate a new key */ - struct sockaddr_in peer; /* Current address of peer */ + struct comm_addr peer; /* Current address of peer */ bool_t peer_valid; /* Peer address becomes invalid when key times out, but only if we have a DNS name for our peer */ @@ -185,7 +185,7 @@ struct site { timeout before we can listen for another setup packet); perhaps we should keep a list of 'bad' sources for setup packets. */ uint32_t setup_session_id; - struct sockaddr_in setup_peer; + struct comm_addr setup_peer; uint8_t localN[NONCELEN]; /* Nonces for key exchange */ uint8_t remoteN[NONCELEN]; struct buffer_if buffer; /* Current outgoing key exchange packet */ @@ -374,7 +374,7 @@ static bool_t generate_msg1(struct site *st) } static bool_t process_msg1(struct site *st, struct buffer_if *msg1, - struct sockaddr_in *src) + const struct comm_addr *src) { struct msg m; @@ -397,7 +397,7 @@ static bool_t generate_msg2(struct site *st) } static bool_t process_msg2(struct site *st, struct buffer_if *msg2, - struct sockaddr_in *src) + const struct comm_addr *src) { struct msg m; cstring_t err; @@ -421,7 +421,7 @@ static bool_t generate_msg3(struct site *st) } static bool_t process_msg3(struct site *st, struct buffer_if *msg3, - struct sockaddr_in *src) + const struct comm_addr *src) { struct msg m; uint8_t *hash; @@ -472,7 +472,7 @@ static bool_t generate_msg4(struct site *st) } static bool_t process_msg4(struct site *st, struct buffer_if *msg4, - struct sockaddr_in *src) + const struct comm_addr *src) { struct msg m; uint8_t *hash; @@ -552,7 +552,7 @@ static bool_t generate_msg5(struct site *st) } static bool_t process_msg5(struct site *st, struct buffer_if *msg5, - struct sockaddr_in *src) + const struct comm_addr *src) { struct msg0 m; cstring_t transform_err; @@ -601,7 +601,7 @@ static bool_t generate_msg6(struct site *st) } static bool_t process_msg6(struct site *st, struct buffer_if *msg6, - struct sockaddr_in *src) + const struct comm_addr *src) { struct msg0 m; cstring_t transform_err; @@ -629,7 +629,7 @@ static bool_t process_msg6(struct site *st, struct buffer_if *msg6, } static bool_t process_msg0(struct site *st, struct buffer_if *msg0, - struct sockaddr_in *src) + const struct comm_addr *src) { struct msg0 m; cstring_t transform_err; @@ -670,7 +670,7 @@ 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) + const struct comm_addr *addr, bool_t incoming) { uint32_t dest=ntohl(*(uint32_t *)buf->start); uint32_t source=ntohl(*(uint32_t *)(buf->start+4)); @@ -713,9 +713,10 @@ static void site_resolve_callback(void *sst, struct in_addr *address) } if (address) { memset(&st->setup_peer,0,sizeof(st->setup_peer)); - st->setup_peer.sin_family=AF_INET; - st->setup_peer.sin_port=htons(st->remoteport); - st->setup_peer.sin_addr=*address; + st->setup_peer.comm=st->comm; + st->setup_peer.sin.sin_family=AF_INET; + st->setup_peer.sin.sin_port=htons(st->remoteport); + st->setup_peer.sin.sin_addr=*address; enter_new_state(st,SITE_SENTMSG1); } else { /* Resolution failed */ @@ -1026,7 +1027,7 @@ static void site_outgoing(void *sst, struct buffer_if *buf) /* This function is called by the communication device to deliver packets from our peers. */ static bool_t site_incoming(void *sst, struct buffer_if *buf, - struct sockaddr_in *source) + const struct comm_addr *source) { struct site *st=sst; uint32_t dest=ntohl(*(uint32_t *)buf->start); diff --git a/udp.c b/udp.c index 7ff4d5f..29192d9 100644 --- a/udp.c +++ b/udp.c @@ -95,7 +95,8 @@ static void udp_afterpoll(void *state, struct pollfd *fds, int nfds) } done=False; for (n=st->notify; n; n=n->next) { - if (n->fn(n->state, st->rbuf, &from)) { + struct comm_addr ca={ &st->ops, from }; + if (n->fn(n->state, st->rbuf, &ca)) { done=True; break; } @@ -156,21 +157,21 @@ static void release_notify(void *commst, void *nst, comm_notify_fn *fn) } static bool_t udp_sendmsg(void *commst, struct buffer_if *buf, - struct sockaddr_in *dest) + const struct comm_addr *dest) { struct udp *st=commst; uint8_t *sa; if (st->use_proxy) { sa=buf->start-8; - memcpy(sa,&dest->sin_addr,4); + memcpy(sa,&dest->sin.sin_addr,4); memset(sa+4,0,4); - memcpy(sa+6,&dest->sin_port,2); + memcpy(sa+6,&dest->sin.sin_port,2); sendto(st->fd,sa,buf->size+8,0,(struct sockaddr *)&st->proxy, sizeof(st->proxy)); } else { sendto(st->fd, buf->start, buf->size, 0, - (struct sockaddr *)dest, sizeof(*dest)); + (struct sockaddr *)&dest->sin, sizeof(dest->sin)); } return True; -- 1.5.6.5 From rjk at terraraq.org.uk Mon Jul 11 19:43:25 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Mon, 11 Jul 2011 19:43:25 +0100 Subject: [PATCH 1/3] Update Mac-specific notes. [and 2 more messages] In-Reply-To: <19994.10167.190116.754358@chiark.greenend.org.uk> References: <1310297025-91831-1-git-send-email-rjk@terraraq.org.uk> <1310297025-91831-2-git-send-email-rjk@terraraq.org.uk> <1310297025-91831-3-git-send-email-rjk@terraraq.org.uk> <1310297025-91831-4-git-send-email-rjk@terraraq.org.uk> <19994.10167.190116.754358@chiark.greenend.org.uk> Message-ID: <4E1B444D.6020506@terraraq.org.uk> On 10/07/2011 23:29, Ian Jackson wrote: > Richard Kettlewell writes ("[PATCH 1/3] Update Mac-specific notes."): >> - how (and why) to enable IP forwarding >> - correct 'launchctl unload' invocation > > I don't have an opinion on these - I think you should just push the > mac-specific notes changes. Pushed. > Richard Kettlewell writes ("[PATCH 2/3] .gitignore XCode-specific files."): >> Checking those files in doesn't make much sense as they change at the >> drop of a hat. > ... >> +*.xcodeproj >> +build > > This should be > /build > I think. In case we invent a file "build" somewhere else. Corrected and pushed. > Richard Kettlewell writes ("[PATCH 3/3] Detect Fink automatically."): >> Saves a bit of manual labour when building on OSX. > ... >> +# Use Fink if available >> +if test -d /sw; then >> + CPPFLAGS="-I/sw/include ${CPPFLAGS}" >> + LDFLAGS="-L/sw/lib ${LDFLAGS}" >> +fi > > Perhaps this should produce a message of some kind ? Good idea. A generally less lazy version to follow at some point. ttfn/rjk From rjk at terraraq.org.uk Mon Jul 11 19:58:57 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Mon, 11 Jul 2011 19:58:57 +0100 Subject: [PATCH 2/2] sys_cmd error handling improved in the following ways: (1) If the subprocess exits nonzero then the exit status is unpicked and logged. (2) If the exec in the child fails, the command and errno string are written to stderr (which should end up in secnet's usual log output). (3) _exit() is used instead of exit(), to avoid any possibility of craziness with stdio/atexit/etc. In-Reply-To: <19994.10038.626678.581670@chiark.greenend.org.uk> References: <1310219944-75586-1-git-send-email-rjk@terraraq.org.uk> <1310219944-75586-2-git-send-email-rjk@terraraq.org.uk> <1310219944-75586-3-git-send-email-rjk@terraraq.org.uk> <19994.10038.626678.581670@chiark.greenend.org.uk> Message-ID: <4E1B47F1.2010107@terraraq.org.uk> On 10/07/2011 23:27, Ian Jackson wrote: > Richard Kettlewell writes ("[PATCH 2/2] sys_cmd error handling improved in the following ways: (1) If the subprocess exits nonzero then the exit status is unpicked and logged. (2) If the exec in the child fails, the command and errno string are written to stderr (which should end up in secnet's usual log output). (3) _exit() is used instead of exit(), to avoid any possibility of craziness with stdio/atexit/etc."): >> From: Richard Kettlewell > > The substance looks good to me. > > You should probably try to keep to theh existing coding style though: > whitespace in "if (" was the thing that jumped out at me. OK, corrected & pushed. > We should have sys_vcmd I guess but perhaps not now. > > If you want to push your "packet cannot be delivered" despite the lack > of tv_now, go ahead. I'll produce the tv_now patch RSN now honest, ahm. Modified to use the global and pushed. ttfn/rjk From ijackson at chiark.greenend.org.uk Wed Jul 13 18:34:27 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Wed, 13 Jul 2011 18:34:27 +0100 Subject: [PATCH v2 00/06] secnet: Test example config and DoS fix In-Reply-To: <1310338530-11143-1-git-send-email-ijackson@chiark.greenend.org.uk> References: <1310338530-11143-1-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <19997.55075.915727.201318@chiark.greenend.org.uk> Ian Jackson writes ("[PATCH v2 00/06] secnet: Test example config and DoS fix"): > This is the revised version of my test-example series, with the DoS > fix for failed key setups added on the end. I have pushed this series. Ian. From ijackson at chiark.greenend.org.uk Thu Jul 14 01:22:35 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Thu, 14 Jul 2011 01:22:35 +0100 Subject: [RFC 0/7] secnet: new features relating to site addresses, etc. Message-ID: <1310602962-8202-1-git-send-email-ijackson@chiark.greenend.org.uk> This series of patches is part of my project to have secnet handle intermittently connected hosts better - plus some yaks I came across on the way. This is still an RFC series. I haven't tested it at all yet, but I thought it would be useful to post it and get some feedback. From ijackson at chiark.greenend.org.uk Thu Jul 14 01:22:36 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Thu, 14 Jul 2011 01:22:36 +0100 Subject: [PATCH 1/7] secnet.h: provide helpful STRING macro (for preprocessor stringification) In-Reply-To: <1310602962-8202-1-git-send-email-ijackson@chiark.greenend.org.uk> References: <1310602962-8202-1-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1310602962-8202-2-git-send-email-ijackson@chiark.greenend.org.uk> Uses preprocessor stringification; can be helpful for rendering compile-time constants (eg compile time limit macros) for messages, etc. Signed-off-by: Ian Jackson --- secnet.h | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/secnet.h b/secnet.h index b60972f..6559ef3 100644 --- a/secnet.h +++ b/secnet.h @@ -495,4 +495,7 @@ extern void log_from_fd(int fd, cstring_t prefix, struct log_if *log); /***** END of log functions *****/ +#define STRING2(x) #x +#define STRING(x) STRING2(x) + #endif /* secnet_h */ -- 1.5.6.5 From ijackson at chiark.greenend.org.uk Thu Jul 14 01:22:37 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Thu, 14 Jul 2011 01:22:37 +0100 Subject: [PATCH 2/7] cleanup: provide helpful FILLZERO macro (for certain memset calls) In-Reply-To: <1310602962-8202-1-git-send-email-ijackson@chiark.greenend.org.uk> References: <1310602962-8202-1-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1310602962-8202-3-git-send-email-ijackson@chiark.greenend.org.uk> This macro replaces these idioms: memset(&foo,0,sizeof(foo)); => FILLZERO(foo); memset(foo,0,sizeof(*foo)); => FILLZERO(*foo); This makes it impossible to accidentally get the wrong size. Use this macro in all such patterns in secnet, apart from two in site.c which are going to be removed soon anyway. Signed-off-by: Ian Jackson --- secnet.h | 2 ++ transform.c | 6 +++--- tun.c | 10 +++++----- udp.c | 4 ++-- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/secnet.h b/secnet.h index 6559ef3..49afd32 100644 --- a/secnet.h +++ b/secnet.h @@ -498,4 +498,6 @@ extern void log_from_fd(int fd, cstring_t prefix, struct log_if *log); #define STRING2(x) #x #define STRING(x) STRING2(x) +#define FILLZERO(obj) (memset(&(obj),0,sizeof((obj)))) + #endif /* secnet_h */ diff --git a/transform.c b/transform.c index b13c2dd..eaa57c1 100644 --- a/transform.c +++ b/transform.c @@ -72,8 +72,8 @@ static void transform_delkey(void *sst) { struct transform_inst *ti=sst; - memset(&ti->cryptkey,0,sizeof(ti->cryptkey)); - memset(&ti->mackey,0,sizeof(ti->mackey)); + FILLZERO(ti->cryptkey); + FILLZERO(ti->mackey); ti->keyed=False; } @@ -252,7 +252,7 @@ static void transform_destroy(void *sst) { struct transform_inst *st=sst; - memset(st,0,sizeof(*st)); /* Destroy key material */ + FILLZERO(st); /* Destroy key material */ free(st); } diff --git a/tun.c b/tun.c index 3db998f..0baaf12 100644 --- a/tun.c +++ b/tun.c @@ -211,7 +211,7 @@ static bool_t tun_set_route(void *sst, struct netlink_client *routes) struct sockaddr_in *sa; int action; - memset(&rt,0,sizeof(rt)); + FILLZERO(rt); sa=(struct sockaddr_in *)&rt.rt_dst; sa->sin_family=AF_INET; sa->sin_addr.s_addr=htonl(nets->list[i].prefix); @@ -292,7 +292,7 @@ static void tun_phase_hook(void *sst, uint32_t newphase) fatal_perror("%s: can't open device file %s",st->nl.name, st->device_path); } - memset(&ifr,0,sizeof(ifr)); + FILLZERO(ifr); ifr.ifr_flags = IFF_TUN | IFF_NO_PI; /* Just send/receive IP packets, no extra headers */ if (st->interface_name) @@ -379,7 +379,7 @@ static void tun_phase_hook(void *sst, uint32_t newphase) /* Interface address */ strncpy(ifr.ifr_name,st->interface_name,IFNAMSIZ); sa=(struct sockaddr_in *)&ifr.ifr_addr; - memset(sa,0,sizeof(*sa)); + FILLZERO(*sa); sa->sin_family=AF_INET; sa->sin_addr.s_addr=htonl(st->local_address); if (ioctl(fd,SIOCSIFADDR, &ifr)!=0) { @@ -389,7 +389,7 @@ static void tun_phase_hook(void *sst, uint32_t newphase) /* Netmask */ strncpy(ifr.ifr_name,st->interface_name,IFNAMSIZ); sa=(struct sockaddr_in *)&ifr.ifr_netmask; - memset(sa,0,sizeof(*sa)); + FILLZERO(*sa); sa->sin_family=AF_INET; sa->sin_addr.s_addr=htonl(0xffffffff); if (ioctl(fd,SIOCSIFNETMASK, &ifr)!=0) { @@ -399,7 +399,7 @@ static void tun_phase_hook(void *sst, uint32_t newphase) /* Destination address (point-to-point) */ strncpy(ifr.ifr_name,st->interface_name,IFNAMSIZ); sa=(struct sockaddr_in *)&ifr.ifr_dstaddr; - memset(sa,0,sizeof(*sa)); + FILLZERO(*sa); sa->sin_family=AF_INET; sa->sin_addr.s_addr=htonl(st->nl.secnet_address); if (ioctl(fd,SIOCSIFDSTADDR, &ifr)!=0) { diff --git a/udp.c b/udp.c index 7ff4d5f..945d1d0 100644 --- a/udp.c +++ b/udp.c @@ -194,7 +194,7 @@ static void udp_phase_hook(void *sst, uint32_t new_phase) st->loc.file,st->loc.line); } - memset(&addr, 0, sizeof(addr)); + FILLZERO(addr); addr.sin_family=AF_INET; addr.sin_addr.s_addr=htonl(st->addr); addr.sin_port=htons(st->port); @@ -279,7 +279,7 @@ static list_t *udp_apply(closure_t *self, struct cloc loc, dict_t *context, l=dict_lookup(d,"proxy"); if (l) { st->use_proxy=True; - memset(&st->proxy,0,sizeof(st->proxy)); + FILLZERO(st->proxy); st->proxy.sin_family=AF_INET; i=list_elem(l,0); if (!i || i->type!=t_string) { -- 1.5.6.5 From ijackson at chiark.greenend.org.uk Thu Jul 14 01:22:38 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Thu, 14 Jul 2011 01:22:38 +0100 Subject: [PATCH 3/7] comm, site: pass a new "struct comm_addr" rather than sockaddr_in In-Reply-To: <1310602962-8202-1-git-send-email-ijackson@chiark.greenend.org.uk> References: <1310602962-8202-1-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1310602962-8202-4-git-send-email-ijackson@chiark.greenend.org.uk> This abstracts away the fact that the peer address is a sockaddr_in; instead, most of the code in site.c now only handles the peer address as an opaque structure. We put the struct comm_if* in the address structure too, as this will be useful later. Amongst other things, doing this arranges that the comm client knows which comm is notifying about an incoming packet. Previously the client was expected to "just know" because the only actual client in secnet is site which currently only deals with one comm. Also make the relevant arguments const-correct. Contains consequential changes the signatures of many functions but no intentional functional change. Signed-off-by: Ian Jackson --- secnet.h | 16 ++++++++++++++-- site.c | 29 +++++++++++++++-------------- udp.c | 15 ++++++++++----- 3 files changed, 39 insertions(+), 21 deletions(-) diff --git a/secnet.h b/secnet.h index 49afd32..809b3a7 100644 --- a/secnet.h +++ b/secnet.h @@ -303,16 +303,28 @@ struct rsaprivkey_if { /* COMM interface */ +struct comm_addr { + /* This struct is pure data; in particular comm's clients may + freely copy it. */ + /* Everyone is also guaranteed that all padding is set to zero, ie + that comm_addrs referring to semantically identical peers will + compare equal with memcmp. Anyone who constructs a comm_addr + must start by memsetting it with FILLZERO, or some + equivalent. */ + struct comm_if *comm; + struct sockaddr_in sin; +}; + /* Return True if the packet was processed, and shouldn't be passed to any other potential receivers. */ typedef bool_t comm_notify_fn(void *state, struct buffer_if *buf, - struct sockaddr_in *source); + const struct comm_addr *source); typedef void comm_request_notify_fn(void *commst, void *nst, comm_notify_fn *fn); typedef void comm_release_notify_fn(void *commst, void *nst, comm_notify_fn *fn); typedef bool_t comm_sendmsg_fn(void *commst, struct buffer_if *buf, - struct sockaddr_in *dest); + const struct comm_addr *dest); struct comm_if { void *st; int32_t min_start_pad; diff --git a/site.c b/site.c index 006d9b4..18ae85d 100644 --- a/site.c +++ b/site.c @@ -174,7 +174,7 @@ struct site { bool_t current_valid; uint64_t current_key_timeout; /* End of life of current key */ uint64_t renegotiate_key_time; /* When we can negotiate a new key */ - struct sockaddr_in peer; /* Current address of peer */ + struct comm_addr peer; /* Current address of peer */ bool_t peer_valid; /* Peer address becomes invalid when key times out, but only if we have a DNS name for our peer */ @@ -185,7 +185,7 @@ struct site { timeout before we can listen for another setup packet); perhaps we should keep a list of 'bad' sources for setup packets. */ uint32_t setup_session_id; - struct sockaddr_in setup_peer; + struct comm_addr setup_peer; uint8_t localN[NONCELEN]; /* Nonces for key exchange */ uint8_t remoteN[NONCELEN]; struct buffer_if buffer; /* Current outgoing key exchange packet */ @@ -374,7 +374,7 @@ static bool_t generate_msg1(struct site *st) } static bool_t process_msg1(struct site *st, struct buffer_if *msg1, - struct sockaddr_in *src) + const struct comm_addr *src) { struct msg m; @@ -397,7 +397,7 @@ static bool_t generate_msg2(struct site *st) } static bool_t process_msg2(struct site *st, struct buffer_if *msg2, - struct sockaddr_in *src) + const struct comm_addr *src) { struct msg m; cstring_t err; @@ -421,7 +421,7 @@ static bool_t generate_msg3(struct site *st) } static bool_t process_msg3(struct site *st, struct buffer_if *msg3, - struct sockaddr_in *src) + const struct comm_addr *src) { struct msg m; uint8_t *hash; @@ -472,7 +472,7 @@ static bool_t generate_msg4(struct site *st) } static bool_t process_msg4(struct site *st, struct buffer_if *msg4, - struct sockaddr_in *src) + const struct comm_addr *src) { struct msg m; uint8_t *hash; @@ -552,7 +552,7 @@ static bool_t generate_msg5(struct site *st) } static bool_t process_msg5(struct site *st, struct buffer_if *msg5, - struct sockaddr_in *src) + const struct comm_addr *src) { struct msg0 m; cstring_t transform_err; @@ -601,7 +601,7 @@ static bool_t generate_msg6(struct site *st) } static bool_t process_msg6(struct site *st, struct buffer_if *msg6, - struct sockaddr_in *src) + const struct comm_addr *src) { struct msg0 m; cstring_t transform_err; @@ -629,7 +629,7 @@ static bool_t process_msg6(struct site *st, struct buffer_if *msg6, } static bool_t process_msg0(struct site *st, struct buffer_if *msg0, - struct sockaddr_in *src) + const struct comm_addr *src) { struct msg0 m; cstring_t transform_err; @@ -670,7 +670,7 @@ 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) + const struct comm_addr *addr, bool_t incoming) { uint32_t dest=ntohl(*(uint32_t *)buf->start); uint32_t source=ntohl(*(uint32_t *)(buf->start+4)); @@ -713,9 +713,10 @@ static void site_resolve_callback(void *sst, struct in_addr *address) } if (address) { memset(&st->setup_peer,0,sizeof(st->setup_peer)); - st->setup_peer.sin_family=AF_INET; - st->setup_peer.sin_port=htons(st->remoteport); - st->setup_peer.sin_addr=*address; + st->setup_peer.comm=st->comm; + st->setup_peer.sin.sin_family=AF_INET; + st->setup_peer.sin.sin_port=htons(st->remoteport); + st->setup_peer.sin.sin_addr=*address; enter_new_state(st,SITE_SENTMSG1); } else { /* Resolution failed */ @@ -1025,7 +1026,7 @@ static void site_outgoing(void *sst, struct buffer_if *buf) /* This function is called by the communication device to deliver packets from our peers. */ static bool_t site_incoming(void *sst, struct buffer_if *buf, - struct sockaddr_in *source) + const struct comm_addr *source) { struct site *st=sst; uint32_t dest=ntohl(*(uint32_t *)buf->start); diff --git a/udp.c b/udp.c index 945d1d0..8ec8581 100644 --- a/udp.c +++ b/udp.c @@ -71,6 +71,7 @@ static void udp_afterpoll(void *state, struct pollfd *fds, int nfds) if (nfds && (fds->revents & POLLIN)) { do { + FILLZERO(from); fromlen=sizeof(from); BUF_ASSERT_FREE(st->rbuf); BUF_ALLOC(st->rbuf,"udp_afterpoll"); @@ -95,7 +96,11 @@ static void udp_afterpoll(void *state, struct pollfd *fds, int nfds) } done=False; for (n=st->notify; n; n=n->next) { - if (n->fn(n->state, st->rbuf, &from)) { + struct comm_addr ca; + FILLZERO(ca); + ca.comm=&st->ops; + ca.sin=from; + if (n->fn(n->state, st->rbuf, &ca)) { done=True; break; } @@ -156,21 +161,21 @@ static void release_notify(void *commst, void *nst, comm_notify_fn *fn) } static bool_t udp_sendmsg(void *commst, struct buffer_if *buf, - struct sockaddr_in *dest) + const struct comm_addr *dest) { struct udp *st=commst; uint8_t *sa; if (st->use_proxy) { sa=buf->start-8; - memcpy(sa,&dest->sin_addr,4); + memcpy(sa,&dest->sin.sin_addr,4); memset(sa+4,0,4); - memcpy(sa+6,&dest->sin_port,2); + memcpy(sa+6,&dest->sin.sin_port,2); sendto(st->fd,sa,buf->size+8,0,(struct sockaddr *)&st->proxy, sizeof(st->proxy)); } else { sendto(st->fd, buf->start, buf->size, 0, - (struct sockaddr *)dest, sizeof(*dest)); + (struct sockaddr *)&dest->sin, sizeof(dest->sin)); } return True; -- 1.5.6.5 From ijackson at chiark.greenend.org.uk Thu Jul 14 01:22:39 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Thu, 14 Jul 2011 01:22:39 +0100 Subject: [PATCH 4/7] Keepalives: Document that they're unimplemented; remove vestigial code In-Reply-To: <1310602962-8202-1-git-send-email-ijackson@chiark.greenend.org.uk> References: <1310602962-8202-1-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1310602962-8202-5-git-send-email-ijackson@chiark.greenend.org.uk> Keepalives are not actually implemented; the keepalive option does nothing. Mention this in the README. Remove the option's parsing and recording from site.c. Signed-off-by: Ian Jackson --- README | 3 ++- site.c | 3 --- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/README b/README index 564b216..dfdba9d 100644 --- a/README +++ b/README @@ -290,7 +290,8 @@ site: dict argument allowing another attempt [20000] renegotiate-time (integer): if we see traffic on the link after this time then renegotiate another session key immediately [depends on key-lifetime] - keepalive (bool): if True then attempt always to keep a valid session key + keepalive (bool): if True then attempt always to keep a valid session key. + Not actually currently implemented. [false] log-events (string list): types of events to log for this site unexpected: unexpected key setup packets (may be late retransmissions) setup-init: start of attempt to setup a session key diff --git a/site.c b/site.c index 18ae85d..4ff37fc 100644 --- a/site.c +++ b/site.c @@ -154,8 +154,6 @@ struct site { int32_t key_renegotiate_time; /* If we see traffic (or a keepalive) after this time, initiate a new key exchange */ - bool_t keepalive; /* Send keepalives to detect peer failure (not yet - implemented) */ uint8_t *setupsig; /* Expected signature of incoming MSG1 packets */ int32_t setupsiglen; /* Allows us to discard packets quickly if @@ -1260,7 +1258,6 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context, cfgfatal(loc,"site", "renegotiate-time must be less than key-lifetime\n"); } - st->keepalive=dict_read_bool(dict,"keepalive",False,"site",loc,False); st->log_events=string_list_to_word(dict_lookup(dict,"log-events"), log_event_table,"site"); -- 1.5.6.5 From ijackson at chiark.greenend.org.uk Thu Jul 14 01:22:40 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Thu, 14 Jul 2011 01:22:40 +0100 Subject: [PATCH 5/7] site: When shutting down, if debug enabled, do dump the MSG7 In-Reply-To: <1310602962-8202-1-git-send-email-ijackson@chiark.greenend.org.uk> References: <1310602962-8202-1-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1310602962-8202-6-git-send-email-ijackson@chiark.greenend.org.uk> Insert a call to dump_packet in send_msg7. The packet is mostly ciphertext and may not make a great deal of sense but turning on debugging should not show all management packets; only data packets should not be shown. Signed-off-by: Ian Jackson --- site.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/site.c b/site.c index 4ff37fc..eaafe87 100644 --- a/site.c +++ b/site.c @@ -912,6 +912,7 @@ static bool_t send_msg7(struct site *st, cstring_t reason) buf_prepend_uint32(&st->buffer,LABEL_MSG0); buf_prepend_uint32(&st->buffer,st->index); buf_prepend_uint32(&st->buffer,st->remote_session_id); + dump_packet(st,&st->buffer,&st->peer,False); st->comm->sendmsg(st->comm->st,&st->buffer,&st->peer); BUF_FREE(&st->buffer); return True; -- 1.5.6.5 From ijackson at chiark.greenend.org.uk Thu Jul 14 01:22:41 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Thu, 14 Jul 2011 01:22:41 +0100 Subject: [PATCH 6/7] mobile peers: new feature In-Reply-To: <1310602962-8202-1-git-send-email-ijackson@chiark.greenend.org.uk> References: <1310602962-8202-1-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1310602962-8202-7-git-send-email-ijackson@chiark.greenend.org.uk> Provides the following new config option, and some satellite options: mobile (bool): if True then peer is "mobile" ie we assume it may change its apparent IP address and port number without either it or us being aware of the change; so, we remember the last several port/addr pairs we've seen and send packets to all of them (subject to a timeout). We maintain one set of addresses for key setup exchanges, and another for data traffic. [false] In the code this involves replacing the comm_addrs for setup_peer and peer with a new struct transport_peers which contains zero or more comm_addrs. This subsumes peer_valid, too. Additionally, we are slightly cleaner about the use of setup_peer: we ensure that we clean it out appropriately when we go into states where it won't (shouldn't) be used. The transport_peers structure is opaque to most of site.c and is manipulated by a new set of functions which implement the detailed semantics described in site.c. The main code in site.c is no longer supposed to call dump_packet and st->comm->sendmsg directly; it should use transport_xmit (which will do dump_packet as well as appropriate sendmsgs). No intentional functional change if mobile=false (the default). Signed-off-by: Ian Jackson --- README | 14 +++- site.c | 270 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 249 insertions(+), 35 deletions(-) diff --git a/README b/README index dfdba9d..2d04b01 100644 --- a/README +++ b/README @@ -290,8 +290,7 @@ site: dict argument allowing another attempt [20000] renegotiate-time (integer): if we see traffic on the link after this time then renegotiate another session key immediately [depends on key-lifetime] - keepalive (bool): if True then attempt always to keep a valid session key. - Not actually currently implemented. [false] + keepalive (bool): if True then attempt always to keep a valid session key log-events (string list): types of events to log for this site unexpected: unexpected key setup packets (may be late retransmissions) setup-init: start of attempt to setup a session key @@ -304,6 +303,17 @@ site: dict argument dump-packets: every key setup packet we see errors: failure of name resolution, internal errors all: everything (too much!) + mobile (bool): if True then peer is "mobile" ie we assume it may change + its apparent IP address and port number without either it or us + being aware of the change; so, we remember the last several port/addr + pairs we've seen and send packets to all of them (subject to a timeout). + We maintain one set of addresses for key setup exchanges, and another for + data traffic. [false] + mobile_peers_max (integer): Maximum number of peer port/addr pairs we + remember and send to. Must be at least 1 and no more than 5. [3] + mobile_peer_timeout (integer): For "mobile" peers only, the length + of time (in seconds) for which we will keep sending to multiple + address/ports from which we have not seen incoming traffic. [120] ** transform diff --git a/site.c b/site.c index eaafe87..1e46416 100644 --- a/site.c +++ b/site.c @@ -31,6 +31,8 @@ #define DEFAULT_KEY_RENEGOTIATE_GAP 300000 /* Five minutes */ #define DEFAULT_SETUP_RETRIES 5 #define DEFAULT_SETUP_TIMEOUT 2000 +#define DEFAULT_MOBILE_PEER_TIMEOUT 120 +#define DEFAULT_MOBILE_PEERS_MAX 3 /* send at most this many copies (default) */ #define DEFAULT_WAIT_TIME 20000 /* Each site can be in one of several possible states. */ @@ -126,12 +128,89 @@ static struct flagstr log_event_table[]={ { NULL, 0 } }; + +/***** TRANSPORT PEERS declarations *****/ + +/* Details of "mobile peer" semantics: + + - We record mobile_peers_max peer address/port numbers ("peers") + for key setup, and separately mobile_peers_max for data + transfer. If these lists fill up, we retain the newest peers. + (For non-mobile peers we only record one of each.) + + - Outgoing packets are sent to every recorded peer in the + applicable list. + + - Data transfer peers are straightforward: whenever we successfully + process a data packet, we record the peer. Also, whenever we + successfully complete a key setup, we merge the key setup + peers into the data transfer peers. + + (For "non-mobile" peers we simply copy the peer used for + successful key setup, and don't change the peer otherwise.) + + - Key setup peers are slightly more complicated. + + Whenever we receive and successfully process a key exchange + packet, we record the peer. + + Whenever we try to initiate a key setup, we copy the list of data + transfer peers and use it for key setup. But we also look to see + if the config supplies an address and port number and if so we + add that as a key setup peer (possibly evicting one of the data + transfer peers we just copied). + + (For "non-mobile" peers, if we if we have a configured peer + address and port, we always use that; otherwise if we have a + current data peer address we use that; otherwise we do not + attempt to initiate a key setup for lack of a peer address.) + + "Record the peer" means + 1. expire any peers last seen >120s ("mobile_peer_timeout") ago + 2. add the peer of the just received packet to the applicable list + (possibly evicting older entries) + NB that we do not expire peers until an incoming packet arrives. + + */ + +#define MAX_MOBILE_PEERS_MAX 5 /* send at most this many copies, compiled max */ + +typedef struct { + struct timeval last; + struct comm_addr addr; +} transport_peer; + +typedef struct { +/* configuration information */ +/* runtime information */ + int npeers; + transport_peer peers[MAX_MOBILE_PEERS_MAX]; +} transport_peers; + +static void transport_clear_peers(transport_peers *peers); +static int transport_peers_valid(transport_peers *peers); +static void transport_peers_copy(transport_peers *dst, + const transport_peers *src); + +static void transport_setup_msgok(struct site *st, const struct comm_addr *a); +static void transport_data_msgok(struct site *st, const struct comm_addr *a); +static bool_t transport_compute_setupinit_peers(struct site *st, + const struct comm_addr *configured_addr /* 0 if none or not found */); + +static void transport_xmit(struct site *st, transport_peers *peers, + struct buffer_if *buf, bool_t candebug); + + /***** END of transport peers declarations *****/ + + struct site { closure_t cl; struct site_if ops; /* configuration information */ string_t localname; string_t remotename; + bool_t peer_mobile; /* Mobile client support */ + int32_t transport_peers_max; string_t tunname; /* localname<->remotename by default, used in logs */ string_t address; /* DNS name for bootstrapping, optional */ int remoteport; /* Port for bootstrapping, optional */ @@ -150,6 +229,7 @@ struct site { int32_t setup_retries; /* How many times to send setup packets */ int32_t setup_timeout; /* Initial timeout for setup packets */ int32_t wait_timeout; /* How long to wait if setup unsuccessful */ + int32_t mobile_peer_timeout; /* How long to remember 2ary addresses */ int32_t key_lifetime; /* How long a key lasts once set up */ int32_t key_renegotiate_time; /* If we see traffic (or a keepalive) after this time, initiate a new @@ -172,9 +252,7 @@ struct site { bool_t current_valid; uint64_t current_key_timeout; /* End of life of current key */ uint64_t renegotiate_key_time; /* When we can negotiate a new key */ - struct comm_addr peer; /* Current address of peer */ - bool_t peer_valid; /* Peer address becomes invalid when key times out, - but only if we have a DNS name for our peer */ + transport_peers peers; /* Current address(es) of peer for data traffic */ /* The current key setup protocol exchange. We can only be involved in one of these at a time. There's a potential for @@ -183,7 +261,7 @@ struct site { timeout before we can listen for another setup packet); perhaps we should keep a list of 'bad' sources for setup packets. */ uint32_t setup_session_id; - struct comm_addr setup_peer; + transport_peers setup_peers; uint8_t localN[NONCELEN]; /* Nonces for key exchange */ uint8_t remoteN[NONCELEN]; struct buffer_if buffer; /* Current outgoing key exchange packet */ @@ -382,7 +460,7 @@ static bool_t process_msg1(struct site *st, struct buffer_if *msg1, if (!unpick_msg(st,LABEL_MSG1,msg1,&m)) return False; - st->setup_peer=*src; + transport_setup_msgok(st,src); st->setup_session_id=m.source; memcpy(st->remoteN,m.nR,NONCELEN); return True; @@ -657,6 +735,7 @@ static bool_t process_msg0(struct site *st, struct buffer_if *msg0, case LABEL_MSG9: /* Deliver to netlink layer */ st->netlink->deliver(st->netlink->st,msg0); + transport_data_msgok(st,src); return True; break; default: @@ -688,8 +767,7 @@ static uint32_t site_status(void *st) static bool_t send_msg(struct site *st) { if (st->retries>0) { - dump_packet(st,&st->buffer,&st->setup_peer,False); - st->comm->sendmsg(st->comm->st,&st->buffer,&st->setup_peer); + transport_xmit(st, &st->setup_peers, &st->buffer, True); st->timeout=st->now+st->setup_timeout; st->retries--; return True; @@ -704,21 +782,28 @@ static bool_t send_msg(struct site *st) static void site_resolve_callback(void *sst, struct in_addr *address) { struct site *st=sst; + struct comm_addr ca_buf, *ca_use; if (st->state!=SITE_RESOLVE) { slog(st,LOG_UNEXPECTED,"site_resolve_callback called unexpectedly"); return; } if (address) { - memset(&st->setup_peer,0,sizeof(st->setup_peer)); - st->setup_peer.comm=st->comm; - st->setup_peer.sin.sin_family=AF_INET; - st->setup_peer.sin.sin_port=htons(st->remoteport); - st->setup_peer.sin.sin_addr=*address; - enter_new_state(st,SITE_SENTMSG1); + FILLZERO(ca_buf); + ca_buf.comm=st->comm; + ca_buf.sin.sin_family=AF_INET; + ca_buf.sin.sin_port=htons(st->remoteport); + ca_buf.sin.sin_addr=*address; + ca_use=&ca_buf; } else { - /* Resolution failed */ slog(st,LOG_ERROR,"resolution of %s failed",st->address); + ca_use=0; + } + if (transport_compute_setupinit_peers(st,ca_use)) { + enter_new_state(st,SITE_SENTMSG1); + } else { + /* Can't figure out who to try to to talk to */ + slog(st,LOG_SETUP_INIT,"key exchange failed: cannot find peer address"); enter_state_run(st); } } @@ -730,9 +815,7 @@ static bool_t initiate_key_setup(struct site *st, cstring_t reason) if (st->address) { slog(st,LOG_SETUP_INIT,"resolving peer address"); return enter_state_resolve(st); - } else if (st->peer_valid) { - slog(st,LOG_SETUP_INIT,"using old peer address"); - st->setup_peer=st->peer; + } else if (transport_compute_setupinit_peers(st,0)) { return enter_new_state(st,SITE_SENTMSG1); } slog(st,LOG_SETUP_INIT,"key exchange failed: no address for peer"); @@ -754,8 +837,7 @@ static void activate_new_key(struct site *st) st->current_valid=True; st->current_key_timeout=st->now+st->key_lifetime; st->renegotiate_key_time=st->now+st->key_renegotiate_time; - st->peer=st->setup_peer; - st->peer_valid=True; + transport_peers_copy(&st->peers,&st->setup_peers); st->remote_session_id=st->setup_session_id; slog(st,LOG_ACTIVATE_KEY,"new key activated"); @@ -796,7 +878,7 @@ static void set_link_quality(struct site *st) quality=LINK_QUALITY_DOWN; else if (st->address) quality=LINK_QUALITY_DOWN_CURRENT_ADDRESS; - else if (st->peer_valid) + else if (transport_peers_valid(&st->peers)) quality=LINK_QUALITY_DOWN_STALE_ADDRESS; else quality=LINK_QUALITY_DOWN; @@ -811,7 +893,7 @@ static void enter_state_run(struct site *st) st->timeout=0; st->setup_session_id=0; - memset(&st->setup_peer,0,sizeof(st->setup_peer)); + transport_clear_peers(&st->setup_peers); memset(st->localN,0,NONCELEN); memset(st->remoteN,0,NONCELEN); st->new_transform->delkey(st->new_transform->st); @@ -902,7 +984,8 @@ static bool_t send_msg7(struct site *st, cstring_t reason) { cstring_t transform_err; - if (st->current_valid && st->peer_valid && st->buffer.free) { + if (st->current_valid && st->buffer.free + && transport_peers_valid(&st->peers)) { BUF_ALLOC(&st->buffer,"site:MSG7"); buffer_init(&st->buffer,st->transform->max_start_pad+(4*3)); buf_append_uint32(&st->buffer,LABEL_MSG7); @@ -912,8 +995,7 @@ static bool_t send_msg7(struct site *st, cstring_t reason) buf_prepend_uint32(&st->buffer,LABEL_MSG0); buf_prepend_uint32(&st->buffer,st->index); buf_prepend_uint32(&st->buffer,st->remote_session_id); - dump_packet(st,&st->buffer,&st->peer,False); - st->comm->sendmsg(st->comm->st,&st->buffer,&st->peer); + transport_xmit(st,&st->peers,&st->buffer,True); BUF_FREE(&st->buffer); return True; } @@ -999,7 +1081,7 @@ static void site_outgoing(void *sst, struct buffer_if *buf) /* In all other states we consider delivering the packet if we have a valid key and a valid address to send it to. */ - if (st->current_valid && st->peer_valid) { + if (st->current_valid && transport_peers_valid(&st->peers)) { /* Transform it and send it */ if (buf->size>0) { buf_prepend_uint32(buf,LABEL_MSG9); @@ -1008,7 +1090,7 @@ static void site_outgoing(void *sst, struct buffer_if *buf) buf_prepend_uint32(buf,LABEL_MSG0); buf_prepend_uint32(buf,st->index); buf_prepend_uint32(buf,st->remote_session_id); - st->comm->sendmsg(st->comm->st,buf,&st->peer); + transport_xmit(st,&st->peers,buf,False); } BUF_FREE(buf); /* See whether we should start negotiating a new key */ @@ -1105,9 +1187,10 @@ static bool_t site_incoming(void *sst, struct buffer_if *buf, /* Setup packet: expected only in state SENTMSG1 */ if (st->state!=SITE_SENTMSG1) { slog(st,LOG_UNEXPECTED,"unexpected MSG2"); - } else if (process_msg2(st,buf,source)) + } else if (process_msg2(st,buf,source)) { + transport_setup_msgok(st,source); enter_new_state(st,SITE_SENTMSG3); - else { + } else { slog(st,LOG_SEC,"invalid MSG2"); } break; @@ -1115,9 +1198,10 @@ static bool_t site_incoming(void *sst, struct buffer_if *buf, /* Setup packet: expected only in state SENTMSG2 */ if (st->state!=SITE_SENTMSG2) { slog(st,LOG_UNEXPECTED,"unexpected MSG3"); - } else if (process_msg3(st,buf,source)) + } else if (process_msg3(st,buf,source)) { + transport_setup_msgok(st,source); enter_new_state(st,SITE_SENTMSG4); - else { + } else { slog(st,LOG_SEC,"invalid MSG3"); } break; @@ -1125,9 +1209,10 @@ static bool_t site_incoming(void *sst, struct buffer_if *buf, /* Setup packet: expected only in state SENTMSG3 */ if (st->state!=SITE_SENTMSG3) { slog(st,LOG_UNEXPECTED,"unexpected MSG4"); - } else if (process_msg4(st,buf,source)) + } else if (process_msg4(st,buf,source)) { + transport_setup_msgok(st,source); enter_new_state(st,SITE_SENTMSG5); - else { + } else { slog(st,LOG_SEC,"invalid MSG4"); } break; @@ -1141,6 +1226,7 @@ static bool_t site_incoming(void *sst, struct buffer_if *buf, if (st->state!=SITE_SENTMSG4) { slog(st,LOG_UNEXPECTED,"unexpected MSG5"); } else if (process_msg5(st,buf,source)) { + transport_setup_msgok(st,source); enter_new_state(st,SITE_RUN); } else { slog(st,LOG_SEC,"invalid MSG5"); @@ -1152,6 +1238,7 @@ static bool_t site_incoming(void *sst, struct buffer_if *buf, slog(st,LOG_UNEXPECTED,"unexpected MSG6"); } else if (process_msg6(st,buf,source)) { BUF_FREE(&st->buffer); /* Free message 5 */ + transport_setup_msgok(st,source); activate_new_key(st); } else { slog(st,LOG_SEC,"invalid MSG6"); @@ -1221,6 +1308,7 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context, } assert(index_sequence < 0xffffffffUL); st->index = ++index_sequence; + st->peer_mobile=dict_read_bool(dict,"mobile",False,"site",loc,False); st->netlink=find_cl_if(dict,"link",CL_NETLINK,True,"site",loc); st->comm=find_cl_if(dict,"comm",CL_COMM,True,"site",loc); st->resolver=find_cl_if(dict,"resolver",CL_RESOLVER,True,"site",loc); @@ -1248,6 +1336,15 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context, dict,"setup-timeout",False,"site",loc,DEFAULT_SETUP_TIMEOUT); st->wait_timeout=dict_read_number( dict,"wait-time",False,"site",loc,DEFAULT_WAIT_TIME); + st->mobile_peer_timeout=dict_read_number( + dict,"mobile-peer-timeout",False,"site",loc,DEFAULT_MOBILE_PEER_TIMEOUT); + st->transport_peers_max= !st->peer_mobile ? 1 : dict_read_number( + dict,"mobile-peers-max",False,"site",loc,DEFAULT_MOBILE_PEERS_MAX); + if (st->transport_peers_max<1 || + st->transport_peers_max>=MAX_MOBILE_PEERS_MAX) { + cfgfatal(loc,"site","mobile-peers-max must be in range 1.." + STRING(MAX_MOBILE_PEERS_MAX) "\n"); + } if (st->key_lifetime < DEFAULT_KEY_RENEGOTIATE_GAP*2) st->key_renegotiate_time=st->key_lifetime/2; @@ -1289,7 +1386,8 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context, st->current_valid=False; st->current_key_timeout=0; - st->peer_valid=False; + transport_clear_peers(&st->peers); + transport_clear_peers(&st->setup_peers); /* XXX mlock these */ st->dhsecret=safe_malloc(st->dh->len,"site:dhsecret"); st->sharedsecret=safe_malloc(st->transform->keylen,"site:sharedsecret"); @@ -1316,3 +1414,109 @@ void site_module(dict_t *dict) { add_closure(dict,"site",site_apply); } + + +/***** TRANSPORT PEERS definitions *****/ + +static int transport_peer_compar(const void *av, const void *bv) { + const transport_peer *a= av; + const transport_peer *b= bv; + /* put most recent first in the array */ + if (timercmp(&a->last, &b->last, <)) return +1; + if (timercmp(&a->last, &b->last, >)) return -11; + return 0; +} + +static void transport_expire_peers(struct site *st, transport_peers *peers) { + /* peers must be sorted first */ + struct timeval oldest; + oldest.tv_sec = tv_now->tv_sec - st->mobile_peer_timeout; + oldest.tv_usec= tv_now->tv_usec; + while (peers->npeers>1 && + timercmp(&peers->peers[peers->npeers-1].last, &oldest, <)) + peers->npeers--; +} + +static void transport_record_peer(struct site *st, transport_peers *peers, + const struct comm_addr *addr) { + int slot; + + for (slot=0; slotnpeers; slot++) + if (!memcmp(&peers->peers[slot].addr, addr, sizeof(*addr))) + goto found; + + if (peers->npeers==st->transport_peers_max) + slot=st->transport_peers_max; + else + slot=peers->npeers++; + + found: + peers->peers[slot].addr=*addr; + peers->peers[slot].last=*tv_now; + + if (peers->npeers>1) + qsort(peers->peers, peers->npeers, + sizeof(*peers->peers), transport_peer_compar); + + transport_expire_peers(st, peers); +} + +static bool_t transport_compute_setupinit_peers(struct site *st, + const struct comm_addr *configured_addr /* 0 if none or not found */) { + + if (!configured_addr && !transport_peers_valid(&st->peers)) + return False; + + slog(st,LOG_SETUP_INIT, + (!configured_addr ? "using only %d old peer address(es)" + : "using %d old peer address(es) plus configured address"), + st->peers); + + /* Non-mobile peers havve st->peers.npeers==0 or ==1, since they + * have transport_peers_max==1. The effect is that this code + * always uses the configured address if supplied, or otherwise + * the existing data peer if one exists; this is as desired. */ + + transport_peers_copy(&st->setup_peers, &st->peers); + + if (configured_addr) + transport_record_peer(st, &st->setup_peers, configured_addr); + + assert(transport_peers_valid(&st->setup_peers)); + return True; +} + +static void transport_setup_msgok(struct site *st, const struct comm_addr *a) { + if (st->peer_mobile) + transport_record_peer(st,&st->setup_peers,a); +} +static void transport_data_msgok(struct site *st, const struct comm_addr *a) { + if (st->peer_mobile) + transport_record_peer(st,&st->peers,a); +} + +static int transport_peers_valid(transport_peers *peers) { + return peers->npeers; +} +static void transport_clear_peers(transport_peers *peers) { + peers->npeers= 0; +} +static void transport_peers_copy(transport_peers *dst, + const transport_peers *src) { + dst->npeers=src->npeers; + memcpy(dst->peers, src->peers, sizeof(*dst->peers) * dst->npeers); +} + +void transport_xmit(struct site *st, transport_peers *peers, + struct buffer_if *buf, bool_t candebug) { + int slot; + transport_expire_peers(st, peers); + for (slot=0; slotnpeers; slot++) { + transport_peer *peer=&peers->peers[slot]; + if (candebug) + dump_packet(st, buf, &peer->addr, False); + peer->addr.comm->sendmsg(peer->addr.comm->st, &st->buffer, &peer->addr); + } +} + +/***** END of transport peers declarations *****/ -- 1.5.6.5 From ijackson at chiark.greenend.org.uk Thu Jul 14 01:22:42 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Thu, 14 Jul 2011 01:22:42 +0100 Subject: [PATCH 7/7] Multiple udp ports for the same site (multiple "comm"s) In-Reply-To: <1310602962-8202-1-git-send-email-ijackson@chiark.greenend.org.uk> References: <1310602962-8202-1-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1310602962-8202-8-git-send-email-ijackson@chiark.greenend.org.uk> Now you can meaningfully specify more than one comm closure (ie, more than one udp port) for a site. secnet will respond to incoming key exchange and data packets on any of the ports. Signed-off-by: Ian Jackson --- README | 5 ++++- site.c | 39 +++++++++++++++++++++++++++++++++------ 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/README b/README index 2d04b01..16fa18f 100644 --- a/README +++ b/README @@ -270,7 +270,10 @@ site: dict argument local-name (string): this site's name for itself name (string): the name of the site's peer link (netlink closure) - comm (comm closure) + comm (one or more comm closures): if there is more than one, the + first one will be used for any key setups initiated by us using the + configured address. Others are only used if our peer talks to + them. resolver (resolver closure) random (randomsrc closure) local-key (rsaprivkey closure) diff --git a/site.c b/site.c index 1e46416..ed0977c 100644 --- a/site.c +++ b/site.c @@ -215,7 +215,8 @@ struct site { string_t address; /* DNS name for bootstrapping, optional */ int remoteport; /* Port for bootstrapping, optional */ struct netlink_if *netlink; - struct comm_if *comm; + struct comm_if **comms; + int ncomms; struct resolver_if *resolver; struct log_if *log; struct random_if *random; @@ -790,7 +791,7 @@ static void site_resolve_callback(void *sst, struct in_addr *address) } if (address) { FILLZERO(ca_buf); - ca_buf.comm=st->comm; + ca_buf.comm=st->comms[0]; ca_buf.sin.sin_family=AF_INET; ca_buf.sin.sin_port=htons(st->remoteport); ca_buf.sin.sin_addr=*address; @@ -1278,6 +1279,7 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context, struct site *st; item_t *item; dict_t *dict; + int i; st=safe_malloc(sizeof(*st),"site_apply"); @@ -1310,7 +1312,20 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context, st->index = ++index_sequence; st->peer_mobile=dict_read_bool(dict,"mobile",False,"site",loc,False); st->netlink=find_cl_if(dict,"link",CL_NETLINK,True,"site",loc); - st->comm=find_cl_if(dict,"comm",CL_COMM,True,"site",loc); + + list_t *comms_cfg=dict_lookup(dict,"comm"); + if (!comms_cfg) cfgfatal(loc,"site","closure list \"comm\" not found"); + st->ncomms=list_length(comms_cfg); + st->comms=safe_malloc_ary(sizeof(*st->comms),st->ncomms,"comms"); + assert(st->ncomms); + for (i=0; incomms; i++) { + item_t *item=list_elem(comms_cfg,i); + if (item->type!=t_closure) cfgfatal(loc,"site","comm is not a closure"); + closure_t *cl=item->data.closure; + if (cl->type!=CL_COMM) cfgfatal(loc,"site","comm closure wrong type"); + st->comms[i]=cl->interface; + } + st->resolver=find_cl_if(dict,"resolver",CL_RESOLVER,True,"site",loc); st->log=find_cl_if(dict,"log",CL_LOG,True,"site",loc); st->random=find_cl_if(dict,"random",CL_RANDOMSRC,True,"site",loc); @@ -1392,13 +1407,25 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context, st->dhsecret=safe_malloc(st->dh->len,"site:dhsecret"); st->sharedsecret=safe_malloc(st->transform->keylen,"site:sharedsecret"); + /* We need to compute some properties of our comms */ +#define COMPUTE_WORST(pad) \ + int worst_##pad=0; \ + for (i=0; incomms; i++) { \ + int thispad=st->comms[i]->pad; \ + if (thispad > worst_##pad) \ + worst_##pad=thispad; \ + } + COMPUTE_WORST(min_start_pad) + COMPUTE_WORST(min_end_pad) + /* We need to register the remote networks with the netlink device */ st->netlink->reg(st->netlink->st, site_outgoing, st, st->transform->max_start_pad+(4*4)+ - st->comm->min_start_pad, - st->transform->max_end_pad+st->comm->min_end_pad); + worst_min_start_pad, + st->transform->max_end_pad+worst_min_end_pad); - st->comm->request_notify(st->comm->st, st, site_incoming); + for (i=0; incomms; i++) + st->comms[i]->request_notify(st->comms[i]->st, st, site_incoming); st->current_transform=st->transform->create(st->transform->st); st->new_transform=st->transform->create(st->transform->st); -- 1.5.6.5 From ijackson at chiark.greenend.org.uk Thu Jul 14 01:39:25 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Thu, 14 Jul 2011 01:39:25 +0100 Subject: [PATCH 6/7] mobile peers: new feature In-Reply-To: <1310602962-8202-7-git-send-email-ijackson@chiark.greenend.org.uk> References: <1310602962-8202-1-git-send-email-ijackson@chiark.greenend.org.uk> <1310602962-8202-7-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <19998.15037.835400.17088@chiark.greenend.org.uk> Ian Jackson writes ("[PATCH 6/7] mobile peers: new feature"): > - keepalive (bool): if True then attempt always to keep a valid session key. > - Not actually currently implemented. [false] > + keepalive (bool): if True then attempt always to keep a valid session key This is some kind of merge fart and shouldn't be in this patch. There are a few bugs too ... Ian. From rjk at terraraq.org.uk Fri Jul 22 21:22:10 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Fri, 22 Jul 2011 21:22:10 +0100 Subject: [PATCH 3/7] comm, site: pass a new "struct comm_addr" rather than sockaddr_in In-Reply-To: <1310602962-8202-4-git-send-email-ijackson@chiark.greenend.org.uk> References: <1310602962-8202-1-git-send-email-ijackson@chiark.greenend.org.uk> <1310602962-8202-4-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <4E29DBF2.6010501@terraraq.org.uk> > static bool_t udp_sendmsg(void *commst, struct buffer_if *buf, > - struct sockaddr_in *dest) > + const struct comm_addr *dest) > { > struct udp *st=commst; > uint8_t *sa; > > if (st->use_proxy) { > sa=buf->start-8; > - memcpy(sa,&dest->sin_addr,4); > + memcpy(sa,&dest->sin.sin_addr,4); > memset(sa+4,0,4); > - memcpy(sa+6,&dest->sin_port,2); > + memcpy(sa+6,&dest->sin.sin_port,2); > sendto(st->fd,sa,buf->size+8,0,(struct sockaddr *)&st->proxy, > sizeof(st->proxy)); This is a tangential point to the patch, which seems fine to me, but I wonder if we can do better than the magic number offsets in there? udp_afterpoll() too. ttfn/rjk From rjk at terraraq.org.uk Sat Jul 23 10:32:19 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Sat, 23 Jul 2011 10:32:19 +0100 Subject: [PATCH 2/3] Config file fixes. In-Reply-To: <1311413540-6378-2-git-send-email-rjk@terraraq.org.uk> References: <1311413540-6378-1-git-send-email-rjk@terraraq.org.uk> <1311413540-6378-2-git-send-email-rjk@terraraq.org.uk> Message-ID: <1311413540-6378-3-git-send-email-rjk@terraraq.org.uk> * Reject integers in excess of 2^32-1 (rather than reducing them mod 2^32). * ptree_dump(): - Remove a magic number. - More realistic recursion limit. * Various bits of type hygeine. Signed-off-by: Richard Kettlewell --- conffile.c | 8 ++++---- conffile.fl | 21 +++++++++++++++++++-- conffile_internal.h | 2 ++ 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/conffile.c b/conffile.c index 5cce211..490d5c1 100644 --- a/conffile.c +++ b/conffile.c @@ -154,7 +154,7 @@ static void ptree_mangle(struct p_node *t) #ifdef DUMP_PARSE_TREE /* Convert a node type to a string, for parse tree dump */ -static string_t ntype(uint32_t type) +static const char *ntype(uint32_t type) { switch(type) { case T_STRING: return "T_STRING"; @@ -179,14 +179,14 @@ static void ptree_indent(int amount) for (i=0; itype<10) { + if (T_IS_PRIMITIVE(n->type)) { switch(n->type) { case T_STRING: printf("T_STRING: \"%s\" (%s line %d)\n", n->data.string,n->loc.file,n->loc.line); break; @@ -197,7 +197,7 @@ static void ptree_dump(struct p_node *n, uint32_t d) default: printf("**unknown primitive type**\n"); break; } } else { - assert(dtype),n->loc.file,n->loc.line); ptree_indent(d); printf(" |-"); ptree_dump(n->l, d+1); diff --git a/conffile.fl b/conffile.fl index 2cfa21b..7228c9e 100644 --- a/conffile.fl +++ b/conffile.fl @@ -29,7 +29,7 @@ do{ \ #define MAX_INCLUDE_DEPTH 10 struct include_stack_item { YY_BUFFER_STATE bst; - uint32_t lineno; + int lineno; cstring_t file; }; struct include_stack_item include_stack[MAX_INCLUDE_DEPTH]; @@ -71,8 +71,25 @@ static struct p_node *stringnode(string_t string) static struct p_node *numnode(string_t number) { struct p_node *r; + unsigned long n; r=leafnode(T_NUMBER); - r->data.number=atoi(number); + errno = 0; + n = strtoul(number, NULL, 10); + /* The caller is expected to only give us [0-9]+, + * so we skip some of the usual syntax checking. */ + r->data.number=n; + /* Give a consistent error message for any kind of + * out-of-range condition */ + if(errno == ERANGE || n != r->data.number) { + Message(M_FATAL,"config file %s line %d: '%s' is too big\n", + config_file, config_lineno, number); + exit(1); + } + if(errno) { + Message(M_FATAL,"config file %s line %d: '%s': %s\n", + config_file, config_lineno, number, strerror(errno)); + exit(1); + } return r; } diff --git a/conffile_internal.h b/conffile_internal.h index 073ab26..44d0ac7 100644 --- a/conffile_internal.h +++ b/conffile_internal.h @@ -23,6 +23,8 @@ typedef cstring_t atom_t; #define T_ALIST 17 #define T_ERROR 20 +#define T_IS_PRIMITIVE(NTYPE) ((NTYPE) < T_ASSIGNMENT) + struct p_node { uint32_t type; struct cloc loc; -- 1.6.4.2 From rjk at terraraq.org.uk Sat Jul 23 10:32:17 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Sat, 23 Jul 2011 10:32:17 +0100 Subject: [PATCH 0/3] Mac support, config file improvements Message-ID: <1311413540-6378-1-git-send-email-rjk@terraraq.org.uk> Detection of Fink is now reported in configure output and is possible to disable. The other two changes are new to this list. I've tested --managed under launchd (OSX daemon supervisor) but not yet tried it with Upstart. ttfn/rjk From rjk at terraraq.org.uk Sat Jul 23 10:32:20 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Sat, 23 Jul 2011 10:32:20 +0100 Subject: [PATCH 3/3] New --managed option for use when running under a daemon supervisor. In-Reply-To: <1311413540-6378-3-git-send-email-rjk@terraraq.org.uk> References: <1311413540-6378-1-git-send-email-rjk@terraraq.org.uk> <1311413540-6378-2-git-send-email-rjk@terraraq.org.uk> <1311413540-6378-3-git-send-email-rjk@terraraq.org.uk> Message-ID: <1311413540-6378-4-git-send-email-rjk@terraraq.org.uk> The effect is secnet is told that it is running as a daemon right from the start, so it knows to follow the logging rules for daemons but not to fork. The conflation of daemonization with dropping privilege is also unpicked by this patch. Most importantly this ensures that errors from PHASE_GETRESOURCES operations such as 'route' commands is sent to the logfile (or syslog). Signed-off-by: Richard Kettlewell --- log.c | 2 +- secnet.c | 87 ++++++++++++++++++++++------------------- secnet.h | 16 +++++--- uk.org.greenend.secnet.plist | 2 +- util.c | 1 + 5 files changed, 60 insertions(+), 48 deletions(-) diff --git a/log.c b/log.c index 6f4b738..1c8d64a 100644 --- a/log.c +++ b/log.c @@ -22,7 +22,7 @@ static void vMessage(uint32_t class, const char *message, va_list args) size_t bp; char *nlp; - if (secnet_is_daemon) { + if (secnet_is_daemon && system_log) { /* Messages go to the system log interface */ bp=strlen(buff); assert(bp < MESSAGE_BUFLEN); diff --git a/secnet.c b/secnet.c index f9808b7..71e40dc 100644 --- a/secnet.c +++ b/secnet.c @@ -60,6 +60,7 @@ static void parse_options(int argc, char **argv) {"help", 0, 0, 2}, {"version", 0, 0, 1}, {"nodetach", 0, 0, 'n'}, + {"managed", 0, 0, 'm'}, {"silent", 0, 0, 'f'}, {"quiet", 0, 0, 'f'}, {"debug", 0, 0, 'd'}, @@ -69,7 +70,7 @@ static void parse_options(int argc, char **argv) {0,0,0,0} }; - c=getopt_long(argc, argv, "vwdnjc:ft:s:", + c=getopt_long(argc, argv, "vwdnjc:ft:s:m", long_options, &option_index); if (c==-1) break; @@ -87,6 +88,7 @@ static void parse_options(int argc, char **argv) " -s, --sites-key=name configuration key that " "specifies active sites\n" " -n, --nodetach do not run in background\n" + " -m, --managed running under a supervisor\n" " -d, --debug output debug messages\n" " --help display this help and exit\n" " --version output version information " @@ -122,6 +124,10 @@ static void parse_options(int argc, char **argv) background=False; break; + case 'm': + secnet_is_daemon=True; + break; + case 'c': if (optarg) configfile=safe_strdup(optarg,"config_filename"); @@ -354,7 +360,7 @@ static void run(void) free(fds); } -static void droppriv(void) +static void become_daemon(void) { FILE *pf=NULL; pid_t p; @@ -362,58 +368,56 @@ static void droppriv(void) add_hook(PHASE_SHUTDOWN,system_phase_hook,NULL); - /* Open the pidfile for writing now: we may be unable to do so - once we drop privileges. */ - if (pidfile) { - pf=fopen(pidfile,"w"); - if (!pf) { - fatal_perror("cannot open pidfile \"%s\"",pidfile); - } - } - if (!background && pf) { - fprintf(pf,"%d\n",getpid()); - fclose(pf); - } - - /* Now drop privileges */ - if (uid!=0) { - if (setuid(uid)!=0) { - fatal_perror("can't set uid to \"%s\"",userid); - } - } - if (background) { + /* We only want to become a daemon if we are not one + already */ + if (background && !secnet_is_daemon) { p=fork(); if (p>0) { - if (pf) { - /* Parent process - write pidfile, exit */ - fprintf(pf,"%d\n",p); - fclose(pf); - } + /* Parent process - just exit */ exit(0); } else if (p==0) { /* Child process - all done, just carry on */ - if (pf) fclose(pf); - /* Close stdin and stdout; we don't need them any more. - stderr is redirected to the system/log facility */ - if (pipe(errfds)!=0) { - fatal_perror("can't create pipe for stderr"); - } - close(0); - close(1); - close(2); - dup2(errfds[1],0); - dup2(errfds[1],1); - dup2(errfds[1],2); secnet_is_daemon=True; setsid(); - log_from_fd(errfds[0],"stderr",system_log); } else { /* Error */ fatal_perror("cannot fork"); exit(1); } } + if(secnet_is_daemon) { + /* stderr etc are redirected to the system/log facility */ + if (pipe(errfds)!=0) { + fatal_perror("can't create pipe for stderr"); + } + if(dup2(errfds[1],0) < 0 + || dup2(errfds[1],1) < 0 + || dup2(errfds[1],2) < 0) + fatal_perror("can't dup2 pipe"); + if(close(errfds[1]) < 0) + fatal_perror("can't close redundant pipe endpoint"); + log_from_fd(errfds[0],"stderr",system_log); + } secnet_pid=getpid(); + + /* Now we can write the pidfile */ + if (pidfile) { + pf=fopen(pidfile,"w"); + if (!pf) { + fatal_perror("cannot open pidfile \"%s\"",pidfile); + } + if(fprintf(pf,"%ld\n",(long)secnet_pid) < 0 + || fclose(pf) < 0) + fatal_perror("cannot write to pidfile \"%s\"",pidfile); + } +} + +static void droppriv(void) { + if (uid!=0) { + if (setuid(uid)!=0) { + fatal_perror("can't set uid to \"%s\"",userid); + } + } } static signal_notify_fn finish,ignore_hup; @@ -446,6 +450,9 @@ int main(int argc, char **argv) exit(0); } + enter_phase(PHASE_DAEMONIZE); + become_daemon(); + enter_phase(PHASE_GETRESOURCES); /* Appropriate phase hooks will have been run */ diff --git a/secnet.h b/secnet.h index b60972f..9f9befa 100644 --- a/secnet.h +++ b/secnet.h @@ -184,17 +184,21 @@ extern void register_for_poll(void *st, beforepoll_fn *before, /* The secnet program goes through a number of phases in its lifetime. Module code may arrange to be called just as various phases are - entered. */ + entered. + + Remember to update the table in util.c if changing the set of + phases. */ #define PHASE_INIT 0 #define PHASE_GETOPTS 1 /* Process command-line arguments */ #define PHASE_READCONFIG 2 /* Parse and process configuration file */ #define PHASE_SETUP 3 /* Process information in configuration */ -#define PHASE_GETRESOURCES 4 /* Obtain all external resources */ -#define PHASE_DROPPRIV 5 /* Last chance for privileged operations */ -#define PHASE_RUN 6 -#define PHASE_SHUTDOWN 7 /* About to die; delete key material, etc. */ -#define NR_PHASES 8 +#define PHASE_DAEMONIZE 4 /* Become a daemon (if necessary) */ +#define PHASE_GETRESOURCES 5 /* Obtain all external resources */ +#define PHASE_DROPPRIV 6 /* Last chance for privileged operations */ +#define PHASE_RUN 7 +#define PHASE_SHUTDOWN 8 /* About to die; delete key material, etc. */ +#define NR_PHASES 9 typedef void hook_fn(void *self, uint32_t newphase); bool_t add_hook(uint32_t phase, hook_fn *f, void *state); diff --git a/uk.org.greenend.secnet.plist b/uk.org.greenend.secnet.plist index f80184b..1de6ca4 100644 --- a/uk.org.greenend.secnet.plist +++ b/uk.org.greenend.secnet.plist @@ -14,7 +14,7 @@ ProgramArguments /usr/local/sbin/secnet - -n + -m WorkingDirectory / diff --git a/util.c b/util.c index fff5b6d..63fe76f 100644 --- a/util.c +++ b/util.c @@ -166,6 +166,7 @@ static const char *phases[NR_PHASES]={ "PHASE_GETOPTS", "PHASE_READCONFIG", "PHASE_SETUP", + "PHASE_DAEMONIZE", "PHASE_GETRESOURCES", "PHASE_DROPPRIV", "PHASE_RUN", -- 1.6.4.2 From rjk at terraraq.org.uk Sat Jul 23 10:32:18 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Sat, 23 Jul 2011 10:32:18 +0100 Subject: [PATCH 1/3] Detect Fink automatically. In-Reply-To: <1311413540-6378-1-git-send-email-rjk@terraraq.org.uk> References: <1311413540-6378-1-git-send-email-rjk@terraraq.org.uk> Message-ID: <1311413540-6378-2-git-send-email-rjk@terraraq.org.uk> The logic is that if Fink is in the path then we should use it. So (unlike certain build systems I could mention) if you want to use a local install of GMP, it should be sufficient to run ./configure without /sw/bin in the path. Signed-off-by: Richard Kettlewell --- README.mac | 2 +- configure | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ configure.in | 8 ++++++++ 3 files changed, 57 insertions(+), 1 deletions(-) diff --git a/README.mac b/README.mac index d6d60a8..d8b70ab 100644 --- a/README.mac +++ b/README.mac @@ -6,7 +6,7 @@ How to install secnet on a Fink-equipped OS X system: make sudo make install - Build secnet: - ./configure CPPFLAGS=-I/sw/include LDFLAGS=-L/sw/lib + ./configure make sudo make install - Install tuntap for OSX from http://tuntaposx.sourceforge.net/ diff --git a/configure b/configure index 0bb23b6..d824749 100755 --- a/configure +++ b/configure @@ -613,6 +613,7 @@ LDFLAGS CFLAGS CC SET_MAKE +FINK target_alias host_alias build_alias @@ -2263,6 +2264,53 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $ ac_compiler_gnu=$ac_cv_c_compiler_gnu +# If fink is on the path then it is assumed we should use it. +# Extract the first word of "fink", so it can be a program name with args. +set dummy fink; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_path_FINK+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + case $FINK in + [\\/]* | ?:[\\/]*) + ac_cv_path_FINK="$FINK" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_FINK="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +FINK=$ac_cv_path_FINK +if test -n "$FINK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FINK" >&5 +$as_echo "$FINK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +if test "x$FINK" != x; then + finkdir=`echo $FINK|sed 's,/[^/]*/[^/]*$,,'` + CPPFLAGS="-I$finkdir/include ${CPPFLAGS}" + LDFLAGS="-L$finkdir/lib ${LDFLAGS}" +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} diff --git a/configure.in b/configure.in index a548dac..4b82f9a 100644 --- a/configure.in +++ b/configure.in @@ -11,6 +11,14 @@ AC_REVISION($Id: configure.in,v 1.4 2002/09/09 22:05:02 steve Exp $) AC_LANG_C +# If fink is on the path then it is assumed we should use it. +AC_PATH_PROG([FINK],[fink]) +if test "x$FINK" != x; then + finkdir=`echo $FINK|sed 's,/[[^/]]*/[[^/]]*$,,'` + CPPFLAGS="-I$finkdir/include ${CPPFLAGS}" + LDFLAGS="-L$finkdir/lib ${LDFLAGS}" +fi + AC_PROG_MAKE_SET AC_PROG_CC AC_PROG_INSTALL -- 1.6.4.2 From rjk at terraraq.org.uk Sun Jul 24 14:24:54 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Sun, 24 Jul 2011 14:24:54 +0100 Subject: [PATCH 7/7] Multiple udp ports for the same site (multiple "comm"s) In-Reply-To: <1310602962-8202-8-git-send-email-ijackson@chiark.greenend.org.uk> References: <1310602962-8202-1-git-send-email-ijackson@chiark.greenend.org.uk> <1310602962-8202-8-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <4E2C1D26.1020701@terraraq.org.uk> > @@ -1310,7 +1312,20 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context, > st->index = ++index_sequence; > st->peer_mobile=dict_read_bool(dict,"mobile",False,"site",loc,False); > st->netlink=find_cl_if(dict,"link",CL_NETLINK,True,"site",loc); > - st->comm=find_cl_if(dict,"comm",CL_COMM,True,"site",loc); > + > + list_t *comms_cfg=dict_lookup(dict,"comm"); > + if (!comms_cfg) cfgfatal(loc,"site","closure list \"comm\" not found"); > + st->ncomms=list_length(comms_cfg); > + st->comms=safe_malloc_ary(sizeof(*st->comms),st->ncomms,"comms"); > + assert(st->ncomms); Another tangent: maybe find_cl_if() and dict_find_item() should error if they find a list with length greater than 1. Adding such a check doesn't break my test rig so there's at least some reason to think it benign l-) I'll include a proposed change in my next patch set. ttfn/rjk From rjk at terraraq.org.uk Sun Jul 24 18:07:27 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Sun, 24 Jul 2011 18:07:27 +0100 Subject: secnet man page Message-ID: <4E2C514F.4040608@terraraq.org.uk> I have put a slightly wobbly HTMLification of the current state of my secnet man page at: http://www.greenend.org.uk/rjk/junk/secnet.html All comments welcome. It is entirely reference material at present and often terse. Things that really need addressing: - A better name for 'pure closures'. 'netlink generator closure' perhaps? - Clarification of ptp mode, which suffers from my own lack of understanding. - More examples (ideally one for each of the built-in closures) - Does SLIP support have buffer size restrictions like tun does? - Check whether everything documented is implemented. I've spotted a number of things that aren't and marked them appropriately but there could be others. sgo-software-discuss will receive a patch series including this manpage shortly. ttfn/rjk From rjk at terraraq.org.uk Sun Jul 24 18:13:30 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Sun, 24 Jul 2011 18:13:30 +0100 Subject: [PATCH 0/7] Miscellaneous patches Message-ID: <1311527617-1358-1-git-send-email-rjk@terraraq.org.uk> Only one proposed code change here, the rest are docs/buildsys/etc. ttfn/rjk From rjk at terraraq.org.uk Sun Jul 24 18:13:32 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Sun, 24 Jul 2011 18:13:32 +0100 Subject: =?UTF-8?q?=5BPATCH=202/7=5D=20Document=20XCode=203=2E2=20import=2E?= In-Reply-To: <1311527617-1358-1-git-send-email-rjk@terraraq.org.uk> References: <1311527617-1358-1-git-send-email-rjk@terraraq.org.uk> Message-ID: <1311527617-1358-3-git-send-email-rjk@terraraq.org.uk> Signed-off-by: Richard Kettlewell --- README.mac | 46 +++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 45 insertions(+), 1 deletions(-) diff --git a/README.mac b/README.mac index d6d60a8..5e018c1 100644 --- a/README.mac +++ b/README.mac @@ -36,4 +36,48 @@ route to addresses on one interface via another; i.e. if you expect to be able to reach an address on en0 with a packet delivered through tun0, IP forwarding must be turned on.) -Richard Kettlewell 2011-06-18 +How to import secnet into XCode 3.2: + +- Set up build directories as follows: + $ mkdir build/Debug build/Release + $ cd build/Debug + $ ~/src/secnet/configure CFLAGS="-g -O0" + $ cd ../Release + $ ~/src/secnet/configure + $ cd ../.. + (Replace ~/src/secnet with the *absolute* path to your secnet tree - + XCode cannot map the relative paths in errors to the source files + otherwise.) +- Start XCode +- Menubar -> File -> New Project + - Choose the Mac OS X -> Other -> External Build System template + - Choose the *parent* of the secnet directory and call the project + secnet + - OK the overwrite (it won't overwrite anything that matters) + - This creates 'build' and 'secnet.xcodeproj' directories in your + secnet tree. +- Right-click Groups & Files -> secnet -> Add -> Existing files and + select all the *.c, *.h, *.y and *.fl files. + - Omit the following files: + - *.yy.[ch] \ + - *.tab.[ch] | generated during build + - version.c | + - config.h / + - snprintf.[ch] - unnecessary on OSX + - Sort by 'kind' may make this easier + - Leave 'Copy items...' unchecked + - Add To Targets should have 'secnet' checked + - For conffile.fl, right click Get Info -> General, and set File + Type to sourcecode.lex. +- Under Groups & Files -> secnet, select all source files and right + click Get Info -> General, and set: + - Tab Width to 8 + - Indent Width to 4 + - Check Editor uses tabs +- Double click click Groups & Files -> Targets secnet + - Add '-C $TARGET_BUILD_DIR' to the start of the arguments. + +You should now be able to build both debug and release configurations +using ?B. + +Richard Kettlewell 2011-07-23 -- 1.7.2.5 From rjk at terraraq.org.uk Sun Jul 24 18:13:31 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Sun, 24 Jul 2011 18:13:31 +0100 Subject: [PATCH 1/7] Fix version number in a couple of places. In-Reply-To: <1311527617-1358-1-git-send-email-rjk@terraraq.org.uk> References: <1311527617-1358-1-git-send-email-rjk@terraraq.org.uk> Message-ID: <1311527617-1358-2-git-send-email-rjk@terraraq.org.uk> Signed-off-by: Richard Kettlewell --- configure | 18 +++++++++--------- configure.in | 2 +- make-secnet-sites | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/configure b/configure index 0bb23b6..5693f28 100755 --- a/configure +++ b/configure @@ -1,7 +1,7 @@ #! /bin/sh # From configure.in Id: configure.in. # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.67 for secnet 0.1.16+. +# Generated by GNU Autoconf 2.67 for secnet 0.1.18+. # # Report bugs to . # @@ -553,8 +553,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='secnet' PACKAGE_TARNAME='secnet' -PACKAGE_VERSION='0.1.16+' -PACKAGE_STRING='secnet 0.1.16+' +PACKAGE_VERSION='0.1.18+' +PACKAGE_STRING='secnet 0.1.18+' PACKAGE_BUGREPORT='secnet at chiark.greenend.org.uk' PACKAGE_URL='' @@ -1207,7 +1207,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures secnet 0.1.16+ to adapt to many kinds of systems. +\`configure' configures secnet 0.1.18+ to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1268,7 +1268,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of secnet 0.1.16+:";; + short | recursive ) echo "Configuration of secnet 0.1.18+:";; esac cat <<\_ACEOF @@ -1354,7 +1354,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -secnet configure 0.1.16+ +secnet configure 0.1.18+ generated by GNU Autoconf 2.67 Copyright (C) 2010 Free Software Foundation, Inc. @@ -1901,7 +1901,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by secnet $as_me 0.1.16+, which was +It was created by secnet $as_me 0.1.18+, which was generated by GNU Autoconf 2.67. Invocation command line was $ $0 $@ @@ -5113,7 +5113,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by secnet $as_me 0.1.16+, which was +This file was extended by secnet $as_me 0.1.18+, which was generated by GNU Autoconf 2.67. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -5179,7 +5179,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -secnet config.status 0.1.16+ +secnet config.status 0.1.18+ configured by $0, generated by GNU Autoconf 2.67, with options \\"\$ac_cs_config\\" diff --git a/configure.in b/configure.in index a548dac..29ced95 100644 --- a/configure.in +++ b/configure.in @@ -2,7 +2,7 @@ dnl Process this file with autoconf to produce a configure script. sinclude(ac_prog_cc_no_writeable_strings.m4) -AC_INIT(secnet,0.1.16+,secnet at chiark.greenend.org.uk) +AC_INIT(secnet,0.1.18+,secnet at chiark.greenend.org.uk) AC_CONFIG_SRCDIR(secnet.c) AC_CONFIG_HEADER(config.h) diff --git a/make-secnet-sites b/make-secnet-sites index 8024c16..8e3ec73 100755 --- a/make-secnet-sites +++ b/make-secnet-sites @@ -60,7 +60,7 @@ sys.path.append("/usr/local/share/secnet") sys.path.append("/usr/share/secnet") import ipaddr -VERSION="0.1.16" +VERSION="0.1.18" # Classes describing possible datatypes in the configuration file -- 1.7.2.5 From rjk at terraraq.org.uk Sun Jul 24 18:13:33 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Sun, 24 Jul 2011 18:13:33 +0100 Subject: [PATCH 3/7] Prohibit lists where single values expected. In-Reply-To: <1311527617-1358-1-git-send-email-rjk@terraraq.org.uk> References: <1311527617-1358-1-git-send-email-rjk@terraraq.org.uk> Message-ID: <1311527617-1358-4-git-send-email-rjk@terraraq.org.uk> Signed-off-by: Richard Kettlewell --- conffile.c | 10 +++------- 1 files changed, 3 insertions(+), 7 deletions(-) diff --git a/conffile.c b/conffile.c index 5cce211..53c334b 100644 --- a/conffile.c +++ b/conffile.c @@ -639,16 +639,10 @@ void add_closure(dict_t *dict, cstring_t name, apply_fn apply) void *find_cl_if(dict_t *dict, cstring_t name, uint32_t type, bool_t fail_if_invalid, cstring_t desc, struct cloc loc) { - list_t *l; item_t *i; closure_t *cl; - l=dict_lookup(dict,name); - if (!l) { - if (!fail_if_invalid) return NULL; - cfgfatal(loc,desc,"closure \"%s\" not found\n",name); - } - i=list_elem(l,0); + i = dict_find_item(dict,name,fail_if_invalid,desc,loc); if (i->type!=t_closure) { if (!fail_if_invalid) return NULL; cfgfatal(loc,desc,"\"%s\" must be a closure\n",name); @@ -673,6 +667,8 @@ item_t *dict_find_item(dict_t *dict, cstring_t key, bool_t required, if (!required) return NULL; cfgfatal(loc,desc,"required parameter \"%s\" not found\n",key); } + if(list_length(l) != 1) + cfgfatal(loc,desc,"parameter \"%s\" has wrong number of values",key); i=list_elem(l,0); return i; } -- 1.7.2.5 From rjk at terraraq.org.uk Sun Jul 24 18:13:34 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Sun, 24 Jul 2011 18:13:34 +0100 Subject: [PATCH 4/7] Correct a couple of errors in the README. In-Reply-To: <1311527617-1358-1-git-send-email-rjk@terraraq.org.uk> References: <1311527617-1358-1-git-send-email-rjk@terraraq.org.uk> Message-ID: <1311527617-1358-5-git-send-email-rjk@terraraq.org.uk> Signed-off-by: Richard Kettlewell --- README | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README b/README index 564b216..b094e66 100644 --- a/README +++ b/README @@ -317,8 +317,8 @@ Defines: null-netlink: dict argument name (string): name for netlink device, used in log messages networks (string list): networks on the host side of the netlink device - exclude-remote-networks (string list): networks that may never be claimed - by any remote site using this netlink device + remote-networks (string list): networks that may be claimed + by the remote site using this netlink device local-address (string): IP address of host's tunnel interface secnet-address (string): IP address of this netlink device ptp-address (string): IP address of the other end of a point-to-point link @@ -336,7 +336,7 @@ a netlink closure: options (string list): allow-route: allow packets coming from this tunnel to be routed to other tunnels as well as the host (used for mobile devices like laptops) - soft-route: remove these routes from the host's routing table when + soft: remove these routes from the host's routing table when the tunnel link quality is zero mtu (integer): default MTU over this link; may be updated by tunnel code -- 1.7.2.5 From rjk at terraraq.org.uk Sun Jul 24 18:13:36 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Sun, 24 Jul 2011 18:13:36 +0100 Subject: [PATCH 6/7] .gitignore build-stamp. In-Reply-To: <1311527617-1358-1-git-send-email-rjk@terraraq.org.uk> References: <1311527617-1358-1-git-send-email-rjk@terraraq.org.uk> Message-ID: <1311527617-1358-7-git-send-email-rjk@terraraq.org.uk> Signed-off-by: Richard Kettlewell --- .gitignore | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/.gitignore b/.gitignore index a54ee6d..b7f6187 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,4 @@ debian/secnet.substvars test-example/*.key test-example/sites.conf test-example/bogus-setup-request +build-stamp -- 1.7.2.5 From rjk at terraraq.org.uk Sun Jul 24 18:13:35 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Sun, 24 Jul 2011 18:13:35 +0100 Subject: [PATCH 5/7] Introduce an installdirs target. In-Reply-To: <1311527617-1358-1-git-send-email-rjk@terraraq.org.uk> References: <1311527617-1358-1-git-send-email-rjk@terraraq.org.uk> Message-ID: <1311527617-1358-6-git-send-email-rjk@terraraq.org.uk> Signed-off-by: Richard Kettlewell --- Makefile.in | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Makefile.in b/Makefile.in index 68b7b7b..e82baf6 100644 --- a/Makefile.in +++ b/Makefile.in @@ -139,8 +139,10 @@ version.c: Makefile echo "char version[]=\"secnet $(VERSION)\";" >>$@.new mv -f $@.new $@ -install: all +installdirs: $(INSTALL) -d $(prefix)/share/secnet $(sbindir) + +install: installdirs $(INSTALL_PROGRAM) secnet $(sbindir)/`echo secnet|sed '$(transform)'` $(INSTALL_PROGRAM) ${srcdir}/make-secnet-sites $(sbindir)/`echo make-secnet-sites|sed '$(transform)'` $(INSTALL) ${srcdir}/ipaddr.py $(prefix)/share/secnet/ipaddr.py -- 1.7.2.5 From rjk at terraraq.org.uk Sun Jul 24 18:13:37 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Sun, 24 Jul 2011 18:13:37 +0100 Subject: [PATCH 7/7] Add a man page. In-Reply-To: <1311527617-1358-1-git-send-email-rjk@terraraq.org.uk> References: <1311527617-1358-1-git-send-email-rjk@terraraq.org.uk> Message-ID: <1311527617-1358-8-git-send-email-rjk@terraraq.org.uk> As it stands it is purely reference material - no conceptual or tutorial stuff whatsoever. Signed-off-by: Richard Kettlewell --- Makefile.in | 3 + debian/rules | 2 +- secnet.8 | 776 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 780 insertions(+), 1 deletions(-) create mode 100644 secnet.8 diff --git a/Makefile.in b/Makefile.in index e82baf6..301bd84 100644 --- a/Makefile.in +++ b/Makefile.in @@ -48,6 +48,7 @@ exec_prefix:=@exec_prefix@ sbindir:=@sbindir@ sysconfdir:=@sysconfdir@ transform:=@program_transform_name@ +mandir:=@mandir@ TARGETS:=secnet @@ -141,11 +142,13 @@ version.c: Makefile installdirs: $(INSTALL) -d $(prefix)/share/secnet $(sbindir) + $(INSTALL) -d $(mandir)/man8 install: installdirs $(INSTALL_PROGRAM) secnet $(sbindir)/`echo secnet|sed '$(transform)'` $(INSTALL_PROGRAM) ${srcdir}/make-secnet-sites $(sbindir)/`echo make-secnet-sites|sed '$(transform)'` $(INSTALL) ${srcdir}/ipaddr.py $(prefix)/share/secnet/ipaddr.py + $(INSTALL) secnet.8 $(mandir)/man8/secnet.8 clean: $(RM) -f *.o *.yy.c *.tab.[ch] $(TARGETS) core version.c diff --git a/debian/rules b/debian/rules index 590f484..da2a871 100755 --- a/debian/rules +++ b/debian/rules @@ -52,7 +52,7 @@ binary-arch: build install # dh_installmime dh_installinit # dh_installcron -# dh_installman + dh_installman # dh_installinfo dh_installchangelogs dh_link diff --git a/secnet.8 b/secnet.8 new file mode 100644 index 0000000..869d297 --- /dev/null +++ b/secnet.8 @@ -0,0 +1,776 @@ +.TH secnet 8 + +.SH NAME +secnet \- VPN router daemon + +.SH SYNOPSIS +\fBsecnet\fR [\fIOPTIONS\fR] + +.SH DESCRIPTION +\fBsecnet\fR allows virtual private networks to be constructed +spanning multiple separate sites. + +.SH OPTIONS +.TP +.B --verbose\fR, \fB-v +Enable extra diagnostics. +.TP +.B --nowarnings\fR, \fB-w +Suppress warnings. +.TP +.B --help +Display usage message. +.TP +.B --version +Display version string. +.TP +.B --nodetach\fR, \fB-n +Don't go into background. +The default behaviour is to become a daemon during startup. +.TP +.B --silent\fR, \fB--quiet\fR, \fB-f +Suppress error messages. +.TP +.B --debug\fR, \fB-d +Enable debug messages. +.TP +.B --config\fR, \fB-c \fIPATH +Specify configuration file. +The default is \fI/etc/secnet/secnet.conf\fR. +.TP +.B --just-check-config\fR, \fB-j +Check configuration and exit. +.TP +.B --sites-key\fR, \fB-s \fIKEY +Configuration file key defining active sites. +The default is \fBsites\fR. + +.SH "CONFIGURATION FILE" +.SS Overview +The default configuration file is \fI/etc/secnet/secnet.conf\fR. +This can be overridden with the \fB--config\fR option. +.PP +The configuration file defines a dictionary (a mapping from keys to +values) of configuration information for secnet. +It is recursive in nature, i.e. values may themselves include dictionaries. +Any node in the nested structure thus defined can be identified by a +\fIpath\fR, which is the sequence of keys necessary to reach it from +the root, separated by "/" characters. +See \fBPaths\fR below for how this is used. +.PP +Furthermore, when a key is looked up in a dictionary, if it cannot be +found, it is sought in the parent dictionary, and so on back to the +root. +For instance, each \fIsite\fR must contain the \fBresolver\fR key, but +in a typical configuration there is no value in having different +resolvers for each site. +Therefore \fBresolver\fR is defined at the root and thus automatically +incorporated into all sites. +.SS Whitespace +Whitespace, including newlines, is ignored except to the extent that +it bounds other symbols. +.PP +Comment begin with "#" and continues to the end of the line. +Comments are ignored. +.SS Inclusion +A file may be recursively included into the configuration file using a +line of the form: +.IP +\fBinclude \fIPATH +.PP +This is handled at a higher level than the main parser and so +precludes the possibility of using the string \fBinclude\fR for any +other purpose. +.\" check if this is true. it's probably a bug! +.SS Assignments +The configuration file contains one or more assigments. +Each assignment is written: +.IP +\fIkey\fR [\fB=\fR] \fIlist\fR\fB;\fR +.PP +i.e. the equals sign is optional. +The semicolon is mandatory in all contexts. +.PP +Keys start with a letter or "_" and continue with any numbers of +letters, digits, "_" and "-". +.PP +Each \fIkey\fR is a list of one or more \fIvalues\fR, separated by commas. +Possible values types are \fIboolean\fR, \fIstring\fR, \fInumber\fR, +\fIdictionary\fR, \fIpath\fR and \fIclosure evaluation\fR. +.\" This man page draws a distinction between a closure (the thing +.\" evaluated) and a closure evaluation (the closure plus is +.\" arguments). +.SS "Strings" +Strings are contained within "double quotes". +There is (currently) no escape syntax and no way to include quotes +inside strings. +.PP +Example: +.nf + filename "/var/log/secnet"; +.fi +.SS "Numbers" +Numbers are encoded in decimal and do not include a sign. +Numbers must lie in the range 0 to 4294967295. +.PP +Example: +.nf + mtu 1400; +.fi +.SS "Dictionaries" +.\" In conffile.y dictionaries can be preceded by a search path, but +.\" this is not implemented elsewhere, so not documented here. +Dictionaries consist of one or more assignments, in the same syntax as +given above, enclosed in "{" and "}". +.PP +Example: +.nf + system { + userid "secnet"; + pidfile "/var/run/secnet.pid"; + }; +.fi +.SS "Paths" +Paths allow a key already defined in the configuration to be aliased. +.PP +Paths consist of a sequence of keys separated by "/". +If the path starts with a "/" then it is an \fIabsolute path\fR and +the search starts at the root of the configuration. +Otherwise it is a \fIrelative path\fR and starts in the containing +dictionary or in any of its parents, down to and including the root. +If there is more than one match, the one furthest from the root "wins". +.PP +The value of a path is the list assigned to the key it refers to. +Lists are flattened; for example if a key is defined as a list of two +paths, and each of those refers to a list of two integers, the +original key is therefore defined to be a list of four integers, not +a list consisting of two lists. +.PP +It is not possible to refer to a \fIlater\fR key using a path. +.PP +Example: +.nf + vpn { + test { + kakajou vpn-data/test/kakajou/kakajou; + araminta vpn-data/test/araminta/araminta; + deodand vpn-data/test/deodand/deodand; + all-sites kakajou,araminta,deodand; + }; + }; + all-sites vpn/test/all-sites; +.fi +.PP +Here, each of \fBvpn/test/kakajou\fR, \fBvpn/test/araminta\fR and +\fBvpn/test/deodand\fR are defined as aliases to values defined +elsewhere. +\fBvpn/tests/all-sites\fR is defined as the list of all three of those +values, and \fBall-sites\fR is then defined to be an alias for that. +.SS "Booleans" +The (single-element) paths \fBfalse\fR, \fBno\fR and \fBnowise\fR are +predefined and refer to a boolean false value. +Similarly \fBtrue\fR, \fByes\fR and \fBverily\fR point at a boolean +true value. +.PP +In all six cases, variants with just the first letter capitalized, and +with all letters capitalized, are also provided. +.PP +Example: +.nf + random randomfile("/dev/urandom",no); +.fi +.SS "Closure Evaluation" +Closure evaluation uses the following syntax: +.IP +\fICLOSURE \fB( \fIARGUMENTS \fB) +.PP +\fICLOSURE\fR may be a path referring to a closure, or may itself be a +closure evaluation. +.PP +\fIARGUMENTS\fR is a list of zero or more values, separated by commas. +As a shortcut, if the arguments consist of a single dictionary, the +parentheses may be ommitted: +.IP +\fICLOSURE \fB{ \fR... \fB} +.PP +Example: +.nf + sites map(site, vpn/test/all-sites); +.fi +.PP +When a closure is evaluated it returns a value (a list, much as above) +and may also have side effects (which may be immediate or may be +deferred to some later phase of execution). +A list of built-in closures is given below. +.SS "Mandatory Keys" +Two keys are mandatory. +\fBsystem\fR must be a dictionary in which the following keys can be +looked up: +.TP +.B log +A \fIlog closure\fR; see the \fBlogfile\fR documentation below. +The destination for log messages. +Mandatory. +.TP +.B userid +A string. +The userid to run as after dropping privilege. +Optional. +.TP +.B pidfile +A string. +The path to write a pidfile. +Optional. +.PP +\fBsites\fR should be a list of \fIsite closures\fR; see the \fBsite\fR documentation below. +This defines the collection of tunnel endpoints that \fBsecnet\fR will +communicate with. +.PP +Recall the recursive lookup logic described in \fBOverview\fR above: +if (for instance) \fBlog\fR is defined in the top level dictionary but +not in \fBsystem\fR, it will nevertheless be found when looked up in +the latter. + +.SH CLOSURES +\fBsecnet\fR contains a collection of built-in closures +with names (i.e. single-element paths) given below. +.PP +Most of them return anonymous closures of various types, +which are described contextually. + +.SS adns +\fBadns(\fIDICT\fB)\fR => \fIresolver closure\fR +.TP +.I DICT +This either be empty or contain the single key \fBconfig\fR, with a +string value giving configuration to supply to ADNS. +This might be read from a file using \fBreadfile\fR. +.PP +A \fIresolver closure\fR is a means of converting hostnames into +network addresses. + +.SS diffie-hellman +.PP +\fBdiffie-hellman(\fIMODULUS\fB, \fIGENERATOR\fR[\fB, \fICHECK\fR]\fB)\fR => \fIdh closure\fR +.TP +.I MODULUS +String. +The prime modulus \fIp\fR in hex. +.TP +.I GENERATOR +String. +The generator \fIg\fR in hex. +.TP +.I CHECK +Boolean. +If \fBtrue\fR (the default) then check if \fIp\fR is prime. +.PP +A \fIdh closure\fR defines a group to be used for key exchange. +The same group must be used by all sites in the VPN. + +.SS logfile +\fBlogfile(\fIDICT\fB)\fR => \fIlog closure\fR +.PP +Valid keys in the \fIDICT\fR argument are: +.TP +.B filename +The path to log to. +.TP +.B class +A list of strings defining which classes of message to log. +The possible message classes are \fBdebug-config\fR, +\fBdebug-phase\fR, \fBdebug\fR, \fBinfo\fR, \fBnotice\fR, +\fBwarning\fR, \fBerror\fR, \fBsecurity\fR and \fBfatal\fR. +.IP +\fBall-debug\fR is the union of all the \fBdebug\fR... classes. +\fBdefault\fR is equivalent to \fBwarning, error, security, fatal\fR. +\fBverbose\fR is equivalent to \fBinfo, notice, warning, error, +security, fatal\fR. +\fBquiet\fR is equivalent to \fBfatal\fR. +.PP +A \fIlog closure\fR is a means of saving log messages. +See also \fBsyslog\fR below. + +.SS makelist +\fBmakelist(\fIDICT\fB)\fR => \fILIST\fR +.PP +Returns the (flattened) list of values from the dictionary, discarding +the keys. + +.SS map +\fBmap(\fICLOSURE\fB, \fIINPUT\fR...\fB)\fR => \fILIST\fR +.PP +Applies \fICLOSURE\fR to all its additional input arguments and +returns the resulting list. + +.SS md5 +\fBmd5\fR is a \fIhash closure\fR implementing the MD5 algorithm. + +.SS null-netlink +\fBnull-netlink(\fIDICT\fB)\fR => \fInetlink closure\fR +.br +\fBnull-netlink(\fIDICT\fB)\fR => \fIpure closure\fR +.\" TODO pure closure is what it's called internally but this is a +.\" very opaque name to use in docs +.PP +Valid keys in the \fIDICT\fR argument are: +.TP +.B name +String. +The name for the netlink device. +The default is \fBnull-netlink\fR. +.TP +.B networks +List of strings. +The networks on the host side of the netlink device. +.TP +.B remote-networks +List of strings. +Networks that may be claimed by remote sites using this netlink device. +.TP +.B secnet-address +String. +IP address of this netlink. +Incompatible with \fBptp-address\fR. +.TP +.B ptp-address +String. +IP address of the other end of a point-to-point link. +Incompatible with \fBsecnet-address\fR. +.TP +.B mtu +Number. +The MTU of the netlink device. +The default is 1000. +.PP +If \fBptp-address\fR is used then the result is a \fInetlink closure\fR. +This can be used directly with the \fBlink\fR key in the \fBsites\fR +closure (see below). +.PP +If \fBsecnet-address\fR is used then the result is a \fIpure +closure\fR. +This must be evaluated to yield a \fInetlink closure\fR, using a +dictionary argument with the following keys: +.TP +.B routes +String list. +networks reachable via this tunnel, in \fIaddress\fB/\fIbits\fR format. +.TP +.B options +String list. +A list of options: +.RS +.TP +.B allow-route +Allow packets received via this tunnel to be routed down other tunnels +(without this option only packets from the host will be routed). +.TP +.B soft +Remove these routes from the host routing table when the link quality +is 0. +.RE +.TP +.B mtu +Number. +Default MTU over this link. +The default is inherited from the \fIpure closure\fR. +.TP +.B priority +Number. +The priority of this link. +Higher values beat lower values. +The default is 0. + +.\" TODO ptp-address turns up in sites.conf, but why? I think this +.\" is a bug in make-secnet-sites; it is not used by + \" netlink_inst_create. + +.PP +A \fInetlink closure\fR is a virtual IP link, and is supplied to the +\fBlink\fR key of a \fIsite\fR closure. +.PP +The netlink created by \fBnull-netlink\fR has no connection to the +host. +See \fBtun\fR and \fBuserv-ipif\fR below for more useful alternatives. + + + +.SS randomfile +\fBrandomfile(\fIFILENAME\fR[\fB, \fIBLOCKING\fR]\fB)\fR => \fIrandomsource closure\fR +.TP +.I FILENAME +String. +Path to random device, e.g. \fI/dev/urandom\fR. +.TP +.I BLOCKING +Boolean. +\fBTrue\fR if this is a blocking device and \fBfalse\fR otherwise (the default). +Blocking device support is not implemented so this must always be +\fBFalse\fR or absent. +.PP +A \fIrandomsource closure\fR is a source of random numbers. + +.SS readfile +\fBreadfile(\fIPATH\fB)\fR => \fISTRING\fR +.PP +Read the contents of the file \fIPATH\fR (a string) and return it as a string. + +.SS serpent256-cbc +\fBserpent256-cbc(\fIDICT\fB)\fR => \fItransform closure\fR +.PP +Valid keys in the \fIDICT\fR argument are: +.TP +.B max-sequence-skew +The maximum acceptable difference between the sequence number in a +received, decrypted message and the previous one. +The default is 10. +It may be necessary to increase this is if connectivity is poor. +.PP +A \fItransform closure\fR is a reversible means of transforming +messages for transmission over a (presumably) insecure network. +It is responsible for both confidentiality and integrity. + +.SS rsa-private +\fBrsa-private(\fIPATH\fB\fR[, \fICHECK\fR]\fB)\fR => \fIrsaprivkey closure\fR +.TP +.I PATH +String. +The path to a file containing an RSA private key in SSH format +(version 1). +There must be no passphrase. +.TP +.I CHECK +Boolean. +If \fBtrue\fR (the default) then check that the key is valid. + +.SS rsa-public +\fBrsa-public(\fIKEY\fB, \fIMODULUS\fB)\fR => \fIrsapubkey closure\fR +.TP +.I KEY +String. +The public key exponent (\fIe\fR), in decimal. +.TP +.I MODULUS +String. +The modulus (\fIn\fR), in decimal. + +.SS sha1 +\fBsha1\fR is a \fIhash closure\fR implementing the SHA-1 algorithm. + +.SS site +\fBsite(\fIDICT\fB)\fR => \fIsite closure\fR +.PP +Valid keys in the \fIDICT\fR argument are: +.TP +.B local-name +String. +The site's name for itself. +.TP +.B name +String. +The name of the site's peer. +.TP +.B link +A \fInetlink closure\fR. +.TP +.B comm +A \fIcomm closure\fR. +.TP +.B resolver +A \fIresolver closure\fR. +.TP +.B random +A \fIrandomsource closure\fR. +.TP +.B local-key +An \fIrsaprivkey closure\fR. +The key used to prove our identity to the peer. +.TP +.B address +String. +The DNS name of the peer. +Optional, but if it is missing then it will not be possible to +initiate new connections to the peer. +.TP +.B port +Number. +The port to contact the peer. +.TP +.B key +An \fIrsapubkey closure\fR. +The key used to verify the peer's identity. +.TP +.B transform +A \fItransform closure\fR. +Used to protect packets exchanged with the peer. +.TP +.B dh +A \fIdh closure\fR. +The group to use in key exchange. +.TP +.B hash +The hash function used during setup. +.\" TODO clarify what we actually use it for! +.TP +.B key-lifetime +Number. +The maximum lifetime of a session key in milliseconds. +The default is one hour. +.TP +.B setup-retries +Number. +The maximum number of times a key negotiation packet will be +transmitted before giving up. +The default is 5. +.TP +.B setup-timeout +Number. +The time between retransmissions of key negotiation packets, in milliseconds. +The default is one second. +.TP +.B wait-time +Number. +The time to wait after a failed key setup before making another +attempt, in milliseconds. +The default is 20s. +.TP +.B renegotiate-time +Number. +The time after which a new session key will be negotiated, \fIif\fR +there is traffic on the link, in milliseconds. +It must not be greater than the \fBkey-lifetime\fR. +The default 5 minutes less than the key lifetime, unless the lifetime +is less than 10 minutes in which case the default is half the +lifetime. +.TP +.B keepalive +Boolean. +If \fBtrue\fR then attempt to always maintain a live session key. +Not implemented. +.TP +.B log-events +String list. +Types of event to log for this site. +.RS +.TP +.B unexpected +Unexpected key setup packets (including late retransmissions). +.TP +.B setup-init +Start of attempt to setup a session key. +.TP +.B setup-timeout +Failure of attempt to setup a session key, through timeout. +.TP +.B activate-key +Activation of a new session key. +.TP +.B timeout-key +Deletion of current session key through age. +.TP +.B security +Anything potentially suspicious. +.TP +.B state-change +Steps in the key setup protocol. +.TP +.B packet-drop +Whenever we throw away an outgoing packet. +.TP +.B dump-packets +Every key setup packet we see. +.TP +.B errors +Failure of name resolution, internal errors. +.TP +.B all +Everything (too much!) +.RE +.PP +A \fIsite closure\fR defines one site to communicate with. +\fBsecnet\fR expects the (root) key \fBsite\fR to be a list of site +closures. + +.SS sysbuffer +\fBsysbuffer(\fR[\fISIZE\fR[\fB, \fIOPTIONS\fR]]\fB)\fR => \fIbuffer closure\fR +.TP +.I SIZE +Number. +The size of the buffer in bytes. +This must be between 64 and 131072. +The default is 4096. +.TP +.I OPTIONS +Dictionary. +Optional and presently unused. +.\" lockdown is accepted but ignored. +.PP +A \fIbuffer closure\fR is a means of buffering packets to send or that +have been received. + +.SS syslog +\fBsyslog(\fIDICT\fB)\fR => \fIlog closure\fR +.PP +Valid keys in the \fIDICT\fR argument are: +.TP +.B ident +String. +The ident string to pass to \fBopenlog\fR(3); this value will appear +in each message. +.TP +.B facility +String. +The facility to log as. +The possible values are \fBauthpriv\fR, \fBcron\fR, \fBdaemon\fR, +\fBkern\fR, \fBlocal0\fR-\fB7\fR, \fBlpr\fR, \fBmail\fR, \fBnews\fR, +\fBsyslog\fR, \fBuser\fR and \fBuucp\fR. +.PP +See also \fBlogfile\fR above. + +.SS tun +\fBtun(\fIDICT\fB)\fR => \fInetlink closure\fR +.br +\fBtun(\fIDICT\fB)\fR => \fIpure closure\fR +.PP +Valid keys in the \fIDICT\fR argument are those documented for +\fBnull-netlink\fR above, plus: +.TP +.B flavour +String. +The type of TUN interface to use. +Possible values are \fBlinux\fR, \fBbsd\fR, \fBstreams\fR and \fBguess\fR. +The default is \fBguess\fR. +.TP +.B device +String. +The path to the TUN/TAP device file. +The default is \fI/dev/net/tun\fR for the \fBlinux\fR flavour and +\fI/dev/tun\fR for the others. +.TP +.B interface +String. +The interface to use. +The default is to pick one automatically. +This cannot be used with the \fBstreams\fR flavour. +.TP +.B local-address +String. +IP address of the host's tunnel interface. +.\" README says this belongs to netlink-null but actually it's + \" duplicated between slip & tun +.TP +.B ifconfig-path +String. +The name of the \fBifconfig\fR command. +The default is simply "ifconfig". +.TP +.B route-path +String. +The name of the \fBroute\fR command. +The default is simply "route". +.TP +.B ifconfig-type +String. +The syntax expected by the \fBifconfig\fR command. +Possible values are \fBlinux\fR, \fBbsd\fR, \fBioctl\fR, +\fBsolaris-2.5\fR and \fBguess\fR. +The default is \fBguess\fR. +.TP +.B route-type +String. +The syntax expected by the \fBifconfig\fR command. +Possible values are \fBlinux\fR, \fBbsd\fR, \fBioctl\fR, +\fBsolaris-2.5\fR and \fBguess\fR. +The default is \fBguess\fR. +.TP +.B buffer +A \fIbuffer closure\fR to use for packets transferred from the host to secnet. +The buffer size must be at least 60 greater than the MTU. +.\" TODO rumour has is that buffers are sometimes shareable between +.\" netlink devices - document that if the conditions are reasonable +.\" ones. +.PP +The \fBifconfig-type\fR and \fBroute-type\fR values determine how +those commands are executed. +If they are set to \fBioctl\fR then low-level system calls are used +directly instead of invoking the commands. +.PP +The netlink created by \fBtun\fR uses the \fBtun\fR device to +communicate with the host kernel. + +.SS udp +\fBudp(\fIDICT\fB)\fR => \fIcomm closure\fR +.PP +Valid keys in the \fIDICT\fR argument are: +.TP +.B address +String. +The IP address to bind on. +The default is 0.0.0.0, i.e. "any". +.TP +.B port +Number. +The port number to bind to. +The default is 0, i.e. the OS will choose one. +It is suggested that any given VPN agree a common port number. +.TP +.B buffer +A \fIbuffer closure\fR. +See the \fBsysbuffer\fR closure above. +.TP +.B authbind +String. +The path to a helper program to bind the socket. +Optional. +.IP +The program will be invoked with the address and port number as its +arguments, and with the socket to bind as file descriptor 0. +It should either bind the socket as requested, or exit with nonzero +status. +.PP +A \fIcomm closure\fR is a means of sending and receiving messages via +a network. +It does not provide confidentiality, reliablity or availability. + +.SS userv-ipif +\fBuserv-ipif(\fIDICT\fB)\fR => \fInetlink closure\fR +.br +\fBuserv-ipif(\fIDICT\fB)\fR => \fIpure closure\fR +.PP +Valid keys in the \fIDICT\fR argument are those documented for +\fBnull-netlink\fR above, plus: +.TP +.B local-address +String. +IP address of the host's SLIP interface. +.\" README says this belongs to netlink-null but actually it's + \" duplicated between SLIP & tun +.TP +.B userv-path +String. +Where to find \fBuserv\fR(1). +The default is \fB"userv"\fR. +.TP +.B service-user +String. +The name of the user that owns the service. +The default is \fB"root"\fR. +.TP +.B service-name +String. +The name of the service to request. +The default is \fB"ipif"\fR. +.TP +.B buffer +A \fIbuffer closure\fR to use for packets transferred from the host to secnet. +.PP +The netlink created by \fBuserv-ipif\fR invokes the specified \fBuserv\fR service with pipes connected to its standard input and output. +It uses SLIP to communicate with the host kernel via these pipes. + +.SH FILES +.TP +.I /etc/secnet/secnet.conf +Configuration file. + +.SH "SEE ALSO" +\fBuserv\fR(1) -- 1.7.2.5 From rjk at terraraq.org.uk Sat Jul 30 16:45:15 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Sat, 30 Jul 2011 16:45:15 +0100 Subject: Disorder, bzr and git Message-ID: <4E34270B.1030509@terraraq.org.uk> I have imported Disorder into git. Anyone with an outstanding bzr branch should be able to fast-export/fast-import and end up with a history-compatible git branch. The clone command is: git clone https://code.google.com/p/disorder/ The source code be browsed online at: http://code.google.com/p/disorder/source/browse/ ttfn/rjk From ijackson at chiark.greenend.org.uk Thu Aug 4 15:08:54 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Thu, 4 Aug 2011 15:08:54 +0100 Subject: secnet: "IP"-over-DNS transport Message-ID: <20026.42998.400085.489455@chiark.greenend.org.uk> FYI I am working on a series which will allow secnet to use DNS as a transport mechanism. That is: * secnet will be able to be a stunt DNS server (obv. it will need an IP address to which it can bind to :53, appropriate delegations) * secnet will be able to be a stunt DNS client So far so good. These are new "comm"s. On clients you'd configure a comm list including (a) the normal udp comm (b) the stunt dns client comm. The server would have both comms and the clients would be recorded as mobile. I think that part of this will have to be a way to tell secnet to switch into and out of this mode. That is, I will have to invent a control socket interface. Thinking about this, I propose to invent a new kind of closure to which everything can register itself. The control socket would be AF_UNIX line-based commands, suitable for nc.openbsd or dedicated clients. At the moment I imagine the only command would be "site such-and-such, switch to comm index N" or "all sites, switch to comm index N". Opinions welcome. Ian. From ijackson at chiark.greenend.org.uk Thu Aug 4 15:10:16 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Thu, 4 Aug 2011 15:10:16 +0100 Subject: [PATCH 3/7] comm, site: pass a new "struct comm_addr" rather than sockaddr_in In-Reply-To: <4E29DBF2.6010501@terraraq.org.uk> References: <1310602962-8202-1-git-send-email-ijackson@chiark.greenend.org.uk> <1310602962-8202-4-git-send-email-ijackson@chiark.greenend.org.uk> <4E29DBF2.6010501@terraraq.org.uk> Message-ID: <20026.43080.659010.848182@chiark.greenend.org.uk> Richard Kettlewell writes ("Re: [PATCH 3/7] comm, site: pass a new "struct comm_addr" rather than sockaddr_in"): > > - memcpy(sa,&dest->sin_addr,4); > > + memcpy(sa,&dest->sin.sin_addr,4); > > memset(sa+4,0,4); > > - memcpy(sa+6,&dest->sin_port,2); > > + memcpy(sa+6,&dest->sin.sin_port,2); > > sendto(st->fd,sa,buf->size+8,0,(struct sockaddr *)&st->proxy, > > sizeof(st->proxy)); > > This is a tangential point to the patch, which seems fine to me, but I > wonder if we can do better than the magic number offsets in there? > udp_afterpoll() too. The whole of secnet is full of this kind of non-declarative definition of its protocol syntax. Unless we want to introduce a formal marshalling system, I think this approach will have to do. Ian. From ijackson at chiark.greenend.org.uk Thu Aug 4 15:16:21 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Thu, 4 Aug 2011 15:16:21 +0100 Subject: [PATCH 2/3] Config file fixes. In-Reply-To: <1311413540-6378-3-git-send-email-rjk@terraraq.org.uk> References: <1311413540-6378-1-git-send-email-rjk@terraraq.org.uk> <1311413540-6378-2-git-send-email-rjk@terraraq.org.uk> <1311413540-6378-3-git-send-email-rjk@terraraq.org.uk> Message-ID: <20026.43445.798879.210034@chiark.greenend.org.uk> Richard Kettlewell writes ("[PATCH 2/3] Config file fixes."): > * Reject integers in excess of 2^32-1 (rather than reducing them mod > 2^32). > * ptree_dump(): > - Remove a magic number. > - More realistic recursion limit. > * Various bits of type hygeine. ... > +#define T_IS_PRIMITIVE(NTYPE) ((NTYPE) < T_ASSIGNMENT) Yes, much better. > /* Convert a node type to a string, for parse tree dump */ > -static string_t ntype(uint32_t type) > +static const char *ntype(uint32_t type) We seem to be gradually abolishing [c]string_t. Perhaps we should do so globally ? (Says the guy with a huge outstanding patch serieses...) > @@ -197,7 +197,7 @@ static void ptree_dump(struct p_node *n, uint32_t d) > default: printf("**unknown primitive type**\n"); break; > } > } else { > - assert(d + assert(d<10000); This is an excessive recursion catch, isn't it ? Why is it a uint32_t even ? I think my uint32_t => int changes should probably have touched this too. > diff --git a/conffile.fl b/conffile.fl > index 2cfa21b..7228c9e 100644 > --- a/conffile.fl > +++ b/conffile.fl ... > - uint32_t lineno; > + int lineno; I remember spotting this and not changing it. I can't remember why. > @@ -71,8 +71,25 @@ static struct p_node *stringnode(string_t string) > static struct p_node *numnode(string_t number) > { > struct p_node *r; > + unsigned long n; > r=leafnode(T_NUMBER); > - r->data.number=atoi(number); > + errno = 0; > + n = strtoul(number, NULL, 10); > + /* The caller is expected to only give us [0-9]+, > + * so we skip some of the usual syntax checking. */ By "the caller" you mean flex ? Ian. From ijackson at chiark.greenend.org.uk Thu Aug 4 15:23:18 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Thu, 4 Aug 2011 15:23:18 +0100 Subject: [PATCH 3/3] New --managed option for use when running under a daemon supervisor. In-Reply-To: <1311413540-6378-4-git-send-email-rjk@terraraq.org.uk> References: <1311413540-6378-1-git-send-email-rjk@terraraq.org.uk> <1311413540-6378-2-git-send-email-rjk@terraraq.org.uk> <1311413540-6378-3-git-send-email-rjk@terraraq.org.uk> <1311413540-6378-4-git-send-email-rjk@terraraq.org.uk> Message-ID: <20026.43862.211587.311898@chiark.greenend.org.uk> Richard Kettlewell writes ("[PATCH 3/3] New --managed option for use when running under a daemon supervisor."): > - if (secnet_is_daemon) { > + if (secnet_is_daemon && system_log) { This is an unrelated bugfix, isn't it ? The rest of this patch seems like a good plan from the description although I confess that from reading the patch I wasn't able to review it for correctness. Have you tested each combination of modes now supported ? Ian. From ijackson at chiark.greenend.org.uk Thu Aug 4 15:25:29 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Thu, 4 Aug 2011 15:25:29 +0100 Subject: [PATCH 2/7] Document XCode 3.2 import. In-Reply-To: <1311527617-1358-3-git-send-email-rjk@terraraq.org.uk> References: <1311527617-1358-1-git-send-email-rjk@terraraq.org.uk> <1311527617-1358-3-git-send-email-rjk@terraraq.org.uk> Message-ID: <20026.43993.735788.835154@chiark.greenend.org.uk> Richard Kettlewell writes ("[PATCH 2/7] Document XCode 3.2 import."): > Signed-off-by: Richard Kettlewell Acked-by: Ian Jackson [ This is LKML-speak for "I approve of this patch and it should be applied. I don't know why they don't write "Approved-by" but we probably shouldn't invent our own convention. ] I'm not sure why your MUA encoded the email so heavily. Ian. From ijackson at chiark.greenend.org.uk Thu Aug 4 15:26:37 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Thu, 4 Aug 2011 15:26:37 +0100 Subject: [PATCH 1/7] Fix version number in a couple of places. In-Reply-To: <1311527617-1358-2-git-send-email-rjk@terraraq.org.uk> References: <1311527617-1358-1-git-send-email-rjk@terraraq.org.uk> <1311527617-1358-2-git-send-email-rjk@terraraq.org.uk> Message-ID: <20026.44061.183200.746000@chiark.greenend.org.uk> Richard Kettlewell writes ("[PATCH 1/7] Fix version number in a couple of places."): > Signed-off-by: Richard Kettlewell Acked-by: Ian Jackson But, wouldn't it be better to do this automatically somehow ? Perhaps we should have it do something involving "git-describe", iff there is a .git directory, and have a tarball release process which leaves a version dropping file ? Ian. From ijackson at chiark.greenend.org.uk Thu Aug 4 15:29:35 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Thu, 4 Aug 2011 15:29:35 +0100 Subject: [PATCH 3/7] Prohibit lists where single values expected. In-Reply-To: <1311527617-1358-4-git-send-email-rjk@terraraq.org.uk> References: <1311527617-1358-1-git-send-email-rjk@terraraq.org.uk> <1311527617-1358-4-git-send-email-rjk@terraraq.org.uk> Message-ID: <20026.44239.190529.961881@chiark.greenend.org.uk> Richard Kettlewell writes ("[PATCH 3/7] Prohibit lists where single values expected."): > Signed-off-by: Richard Kettlewell Acked-by: Ian Jackson From ijackson at chiark.greenend.org.uk Thu Aug 4 15:29:57 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Thu, 4 Aug 2011 15:29:57 +0100 Subject: [PATCH 4/7] Correct a couple of errors in the README. In-Reply-To: <1311527617-1358-5-git-send-email-rjk@terraraq.org.uk> References: <1311527617-1358-1-git-send-email-rjk@terraraq.org.uk> <1311527617-1358-5-git-send-email-rjk@terraraq.org.uk> Message-ID: <20026.44261.517123.809549@chiark.greenend.org.uk> Richard Kettlewell writes ("[PATCH 4/7] Correct a couple of errors in the README."): > Signed-off-by: Richard Kettlewell Acked-by: Ian Jackson From ijackson at chiark.greenend.org.uk Thu Aug 4 15:30:31 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Thu, 4 Aug 2011 15:30:31 +0100 Subject: [PATCH 6/7] .gitignore build-stamp. In-Reply-To: <1311527617-1358-7-git-send-email-rjk@terraraq.org.uk> References: <1311527617-1358-1-git-send-email-rjk@terraraq.org.uk> <1311527617-1358-7-git-send-email-rjk@terraraq.org.uk> Message-ID: <20026.44295.529527.918246@chiark.greenend.org.uk> Richard Kettlewell writes ("[PATCH 6/7] .gitignore build-stamp."): > Signed-off-by: Richard Kettlewell > --- > .gitignore | 1 + > 1 files changed, 1 insertions(+), 0 deletions(-) ... > +build-stamp Acked-by: Ian Jackson I think I had a similar but longer patch, in which case I'll cope with any merge conflict. Ian. From ijackson at chiark.greenend.org.uk Thu Aug 4 15:30:42 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Thu, 4 Aug 2011 15:30:42 +0100 Subject: [PATCH 5/7] Introduce an installdirs target. In-Reply-To: <1311527617-1358-6-git-send-email-rjk@terraraq.org.uk> References: <1311527617-1358-1-git-send-email-rjk@terraraq.org.uk> <1311527617-1358-6-git-send-email-rjk@terraraq.org.uk> Message-ID: <20026.44306.681710.734917@chiark.greenend.org.uk> Richard Kettlewell writes ("[PATCH 5/7] Introduce an installdirs target."): > Signed-off-by: Richard Kettlewell Acked-by: Ian Jackson From ijackson at chiark.greenend.org.uk Thu Aug 4 15:45:30 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Thu, 4 Aug 2011 15:45:30 +0100 Subject: [PATCH 7/7] Add a man page. In-Reply-To: <1311527617-1358-8-git-send-email-rjk@terraraq.org.uk> References: <1311527617-1358-1-git-send-email-rjk@terraraq.org.uk> <1311527617-1358-8-git-send-email-rjk@terraraq.org.uk> Message-ID: <20026.45194.728708.163434@chiark.greenend.org.uk> Richard Kettlewell writes ("[PATCH 7/7] Add a man page."): > As it stands it is purely reference material - no conceptual or > tutorial stuff whatsoever. This doesn't seem to include the -m option you introduced earlier ? Re "include" it would be helpful to mention that "include" is newline-terminated and must not have a trailing semicolon. Re path aliasing (since you've evidently just read the code): does the first match have to match the whole path, or just the first element of the target ? Eg if you have sponge { inner { sponge = 3; something = sponge/inner; }; do you get "something=3" or an error ? In the built-in closures: are these all elements of the root dictionary ? Can they be redefined ? You might want to add some text a bit like: Closures can be applied, during configuration, to arguments to make other values (normally, other closures). For example, "adns" is a closure which takes a dictionary (containing configuration data) and returns a "resolver closure". Closures may also provide functionality used by other parts of secnet. For example, a "resolver closure" is one which other parts of secnet can use to convert hostnames to network addresses. Most closures provide only one of these facilities. A closure which can only be invoked during configuration to make other values is a "pure closure". Ian. From rjk at terraraq.org.uk Fri Aug 5 19:30:02 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Fri, 05 Aug 2011 19:30:02 +0100 Subject: [PATCH 2/7] Document XCode 3.2 import. In-Reply-To: <20026.43993.735788.835154@chiark.greenend.org.uk> References: <1311527617-1358-1-git-send-email-rjk@terraraq.org.uk> <1311527617-1358-3-git-send-email-rjk@terraraq.org.uk> <20026.43993.735788.835154@chiark.greenend.org.uk> Message-ID: <4E3C36AA.3020006@terraraq.org.uk> On 04/08/2011 15:25, Ian Jackson wrote: > I'm not sure why your MUA encoded the email so heavily. The only MUA was git. Headers in the BCC to me: Return-path: Envelope-to: richard at sfere.greenend.org.uk Delivery-date: Sun, 24 Jul 2011 18:13:39 +0100 Received: from richard by araminta.anjou.terraraq.org.uk with local (Exim 4.72) (envelope-from ) id 1Ql2FH-0000Mk-3P; Sun, 24 Jul 2011 18:13:39 +0100 From: Richard Kettlewell To: sgo-software-discuss at greenend.org.uk Subject: =?UTF-8?q?=5BPATCH=202/7=5D=20Document=20XCode=203=2E2=20import=2E?= Date: Sun, 24 Jul 2011 18:13:32 +0100 Message-Id: <1311527617-1358-3-git-send-email-rjk at terraraq.org.uk> X-Mailer: git-send-email 1.7.2.5 In-Reply-To: <1311527617-1358-1-git-send-email-rjk at terraraq.org.uk> References: <1311527617-1358-1-git-send-email-rjk at terraraq.org.uk> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: Richard Kettlewell I blame mailman for the base64. ttfn/rjk From rjk at terraraq.org.uk Fri Aug 5 19:30:56 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Fri, 05 Aug 2011 19:30:56 +0100 Subject: [PATCH 1/7] Fix version number in a couple of places. In-Reply-To: <20026.44061.183200.746000@chiark.greenend.org.uk> References: <1311527617-1358-1-git-send-email-rjk@terraraq.org.uk> <1311527617-1358-2-git-send-email-rjk@terraraq.org.uk> <20026.44061.183200.746000@chiark.greenend.org.uk> Message-ID: <4E3C36E0.9010400@terraraq.org.uk> On 04/08/2011 15:26, Ian Jackson wrote: > Richard Kettlewell writes ("[PATCH 1/7] Fix version number in a couple of places."): >> Signed-off-by: Richard Kettlewell > > Acked-by: Ian Jackson > > But, wouldn't it be better to do this automatically somehow ? Yes, absolutely. > Perhaps we should have it do something involving "git-describe", iff > there is a .git directory, and have a tarball release process > which leaves a version dropping file ? I'll have a play sometime, if nobody beats me to it. ttfn/rjk From rjk at terraraq.org.uk Fri Aug 5 22:17:07 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Fri, 05 Aug 2011 22:17:07 +0100 Subject: [PATCH 2/3] Config file fixes. In-Reply-To: <20026.43445.798879.210034@chiark.greenend.org.uk> References: <1311413540-6378-1-git-send-email-rjk@terraraq.org.uk> <1311413540-6378-2-git-send-email-rjk@terraraq.org.uk> <1311413540-6378-3-git-send-email-rjk@terraraq.org.uk> <20026.43445.798879.210034@chiark.greenend.org.uk> Message-ID: <4E3C5DD3.7000400@terraraq.org.uk> On 04/08/2011 15:16, Ian Jackson wrote: > Richard Kettlewell writes ("[PATCH 2/3] Config file fixes."): >> /* Convert a node type to a string, for parse tree dump */ >> -static string_t ntype(uint32_t type) >> +static const char *ntype(uint32_t type) > > We seem to be gradually abolishing [c]string_t. Perhaps we should do > so globally ? (Says the guy with a huge outstanding patch serieses...) I'll add it to my list. l-) >> @@ -197,7 +197,7 @@ static void ptree_dump(struct p_node *n, uint32_t d) >> default: printf("**unknown primitive type**\n"); break; >> } >> } else { >> - assert(d> + assert(d<10000); > > This is an excessive recursion catch, isn't it ? Why is it a uint32_t > even ? I think my uint32_t => int changes should probably have > touched this too. Oh, yes, int would be much better. >> diff --git a/conffile.fl b/conffile.fl >> index 2cfa21b..7228c9e 100644 >> --- a/conffile.fl >> +++ b/conffile.fl > ... >> - uint32_t lineno; >> + int lineno; > > I remember spotting this and not changing it. I can't remember why. I've skimmed its uses again and still can't see any reason not to make it 'int'. It's assigned from config_lineno which is an int in current HEAD, so it's not like it gives you an extra 2 billion lines of elbow room (in case you want to use the config infrastructure to its true potential l-) >> @@ -71,8 +71,25 @@ static struct p_node *stringnode(string_t string) >> static struct p_node *numnode(string_t number) >> { >> struct p_node *r; >> + unsigned long n; >> r=leafnode(T_NUMBER); >> - r->data.number=atoi(number); >> + errno = 0; >> + n = strtoul(number, NULL, 10); >> + /* The caller is expected to only give us [0-9]+, >> + * so we skip some of the usual syntax checking. */ > > By "the caller" you mean flex ? Yes; the only caller of numnode[1] is in conffile.fl: [[:digit:]]+ yylval=numnode(yytext); return TOK_NUMBER; If we ever call it from elsewhere with inadequately constrained input then the comment would become false. I can add the extra checking if you think that's worthwhile. [1] or 'duodenum', as tbird's spelling checker would prefer. ttfn/rjk From ijackson at chiark.greenend.org.uk Mon Aug 8 16:11:03 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Mon, 8 Aug 2011 16:11:03 +0100 Subject: [PATCH 1/7] Fix version number in a couple of places. In-Reply-To: <4E3C36E0.9010400@terraraq.org.uk> References: <1311527617-1358-1-git-send-email-rjk@terraraq.org.uk> <1311527617-1358-2-git-send-email-rjk@terraraq.org.uk> <20026.44061.183200.746000@chiark.greenend.org.uk> <4E3C36E0.9010400@terraraq.org.uk> Message-ID: <20031.64647.417657.69609@chiark.greenend.org.uk> Richard Kettlewell writes ("Re: [PATCH 1/7] Fix version number in a couple of places."): > On 04/08/2011 15:26, Ian Jackson wrote: > > Perhaps we should have it do something involving "git-describe", iff > > there is a .git directory, and have a tarball release process > > which leaves a version dropping file ? > > I'll have a play sometime, if nobody beats me to it. For an example of the kind of approach I took in another project, see here: http://www.chiark.greenend.org.uk/ucgi/~ijackson/git?p=trains;a=blob;f=.git-revid;h=74037ae58d4c246dff8c4643d51c16ae8cd4a55b;hb=HEAD used in Makefiles etc. directly, or like this: http://www.chiark.greenend.org.uk/ucgi/~ijackson/git?p=trains;a=blob;f=layout/layout;h=fac0f7603488d756f4d6ae8419e72b716abc824a;hb=HEAD (see near line 2008, or search for revid) This was a quick-and-dirty replacement for an arrangement based on CVS revids. Ian. From ijackson at chiark.greenend.org.uk Mon Aug 8 16:12:20 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Mon, 8 Aug 2011 16:12:20 +0100 Subject: [PATCH 2/3] Config file fixes. In-Reply-To: <4E3C5DD3.7000400@terraraq.org.uk> References: <1311413540-6378-1-git-send-email-rjk@terraraq.org.uk> <1311413540-6378-2-git-send-email-rjk@terraraq.org.uk> <1311413540-6378-3-git-send-email-rjk@terraraq.org.uk> <20026.43445.798879.210034@chiark.greenend.org.uk> <4E3C5DD3.7000400@terraraq.org.uk> Message-ID: <20031.64724.903783.899711@chiark.greenend.org.uk> Richard Kettlewell writes ("Re: [PATCH 2/3] Config file fixes."): > On 04/08/2011 15:16, Ian Jackson wrote: > > We seem to be gradually abolishing [c]string_t. Perhaps we should do > > so globally ? (Says the guy with a huge outstanding patch serieses...) > > I'll add it to my list. l-) Heh. > > This is an excessive recursion catch, isn't it ? Why is it a uint32_t > > even ? I think my uint32_t => int changes should probably have > > touched this too. > > Oh, yes, int would be much better. Right. > >> - uint32_t lineno; > >> + int lineno; > > > > I remember spotting this and not changing it. I can't remember why. > > I've skimmed its uses again and still can't see any reason not to make > it 'int'. It's assigned from config_lineno which is an int in current > HEAD, so it's not like it gives you an extra 2 billion lines of elbow > room (in case you want to use the config infrastructure to its true > potential l-) Right. > >> + /* The caller is expected to only give us [0-9]+, > >> + * so we skip some of the usual syntax checking. */ > > > > By "the caller" you mean flex ? > > Yes; the only caller of numnode[1] is in conffile.fl: Right. I was just a bit curious about the comment but I think it's fine in that context. > I can add the extra checking if > you think that's worthwhile. No, not really. Thanks, Ian. From rjk at terraraq.org.uk Mon Aug 15 22:46:04 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Mon, 15 Aug 2011 22:46:04 +0100 Subject: secnet: last call for the next release Message-ID: <4E49939C.7090202@terraraq.org.uk> Dear secnet fans, We plan to make a new release of secnet in the near future. Please let us know (via this list) if you feel that any proposed change should, or should not, be in it; or forever hold your peace. ttfn/rjk (where "forever" = until the next release) From ijackson at chiark.greenend.org.uk Wed Aug 17 19:18:47 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Wed, 17 Aug 2011 19:18:47 +0100 Subject: secnet: last call for the next release In-Reply-To: <4E49939C.7090202@terraraq.org.uk> References: <4E49939C.7090202@terraraq.org.uk> Message-ID: <20044.1543.112936.853561@chiark.greenend.org.uk> Richard Kettlewell writes ("secnet: last call for the next release"): > We plan to make a new release of secnet in the near future. Please let > us know (via this list) if you feel that any proposed change should, or > should not, be in it; or forever hold your peace. Having looked at my repo and the master branch, I think we should try to get my "mobile sites" series into the tree. I will repost this as a ~18-patch series, very shortly. Ian. From ijackson at chiark.greenend.org.uk Wed Aug 17 23:54:22 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Wed, 17 Aug 2011 23:54:22 +0100 Subject: [PATCH 04/18] cleanup: Style improvement to python literals in make-secnet-sites In-Reply-To: <1313621676-16031-1-git-send-email-ijackson@chiark.greenend.org.uk> References: <1313621676-16031-1-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1313621676-16031-5-git-send-email-ijackson@chiark.greenend.org.uk> Python literals can have a trailing comma after the last element. Doing this is a good idea as it means that adding new elements at the end doesn't necessitate modifying the previous line. No intentional functional change. Signed-off-by: Ian Jackson --- make-secnet-sites | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/make-secnet-sites b/make-secnet-sites index 8e3ec73..403782b 100755 --- a/make-secnet-sites +++ b/make-secnet-sites @@ -148,7 +148,7 @@ keywords={ 'networks':(networks,"Claimed networks"), 'pubkey':(rsakey,"RSA public site key"), 'peer':(single_ipaddr,"Tunnel peer IP address"), - 'address':(address,"External contact address and port") + 'address':(address,"External contact address and port"), } def sp(name,value): @@ -165,7 +165,7 @@ global_properties={ 'setup-retries':sp, 'wait-time':sp, 'renegotiate-time':sp, - 'restrict-nets':(lambda name,value:"# restrict-nets %s\n"%value) + 'restrict-nets':(lambda name,value:"# restrict-nets %s\n"%value), } class level: @@ -252,7 +252,7 @@ class sitelevel(level): 'address':sp, 'networks':None, 'peer':None, - 'pubkey':(lambda n,v:"key %s;\n"%v) + 'pubkey':(lambda n,v:"key %s;\n"%v), }) require_properties={ 'dh':"Diffie-Hellman group", @@ -261,7 +261,7 @@ class sitelevel(level): 'networks':"Networks claimed by the site", 'hash':"hash function", 'peer':"Gateway address of the site", - 'pubkey':"RSA public key of the site" + 'pubkey':"RSA public key of the site", } def __init__(self,w): level.__init__(self,w) -- 1.7.2.5 From ijackson at chiark.greenend.org.uk Wed Aug 17 23:54:18 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Wed, 17 Aug 2011 23:54:18 +0100 Subject: [PATCH v2 00/18] Mobile sites, multiple udp ports, cleanups, etc. Message-ID: <1313621676-16031-1-git-send-email-ijackson@chiark.greenend.org.uk> This series introduces my new mobile sites feature, and a related feature of being able to run with multiple udp ports. I think we should consider which parts of this series ought to be in the forthcoming release. My current thoughts are that we should make a stable branch now, and apply half of this series to it: These to go into the stable branch, subject to review: 01-06 Uncontroversial cleanups 07-09 Reorganisation and minor functional improvements They are textually large but should be functionally fairly low-risk provided someone else has double-checked them. These are more doubtful: 10-11 Preparatory interface and protocol changes 12-14 New feature: mobile sites 15-16 New feature: ability to use multiple udp ports 17-18 Tests for the new features Given that the current master has some fairly significant improvements most of which are cleanup and documentation, it might be argued that we should make a "maintenance" release and also shortly thereafter a "new features" release. But partly this depends on who we are making a release for. So far I've had one enquiry, and it's not clear to me whether that user would benefit from the new features. I've asked them to post here with their opinion. Finally: some of this series were posted before as the 7-patch series "new features relating to site addresses, etc". They have been updated, extended and some bugs have been fixed. From ijackson at chiark.greenend.org.uk Wed Aug 17 23:54:25 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Wed, 17 Aug 2011 23:54:25 +0100 Subject: [PATCH 07/18] site: When shutting down, if debug enabled, do dump the MSG7 In-Reply-To: <1313621676-16031-1-git-send-email-ijackson@chiark.greenend.org.uk> References: <1313621676-16031-1-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1313621676-16031-8-git-send-email-ijackson@chiark.greenend.org.uk> Insert a call to dump_packet in send_msg7. The packet is mostly ciphertext and may not make a great deal of sense but turning on debugging should not show all management packets; only data packets should not be shown. Signed-off-by: Ian Jackson --- site.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/site.c b/site.c index 34805f6..157d9f2 100644 --- a/site.c +++ b/site.c @@ -909,6 +909,7 @@ static bool_t send_msg7(struct site *st, cstring_t reason) buf_prepend_uint32(&st->buffer,LABEL_MSG0); buf_prepend_uint32(&st->buffer,st->index); buf_prepend_uint32(&st->buffer,st->remote_session_id); + dump_packet(st,&st->buffer,&st->peer,False); st->comm->sendmsg(st->comm->st,&st->buffer,&st->peer); BUF_FREE(&st->buffer); return True; -- 1.7.2.5 From ijackson at chiark.greenend.org.uk Wed Aug 17 23:54:19 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Wed, 17 Aug 2011 23:54:19 +0100 Subject: [PATCH 01/18] Test example: improve logging, choice of ports In-Reply-To: <1313621676-16031-1-git-send-email-ijackson@chiark.greenend.org.uk> References: <1313621676-16031-1-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1313621676-16031-2-git-send-email-ijackson@chiark.greenend.org.uk> * Turn up the logging in test-example/common.conf, to "all". * Change the udp port numbers we use to 16900 and 16910, which conveniently have a "0" for "outside" and a "1" for "inside". * Swap the order of the inside and outside sites in the sites file, so that the consistentliy-lower-numbered "outside" comes first. Signed-off-by: Ian Jackson --- test-example/common.conf | 3 +-- test-example/inside.conf | 2 +- test-example/outside.conf | 2 +- test-example/sites | 17 +++++++---------- 4 files changed, 10 insertions(+), 14 deletions(-) diff --git a/test-example/common.conf b/test-example/common.conf index 6f2fef1..64bfc81 100644 --- a/test-example/common.conf +++ b/test-example/common.conf @@ -6,8 +6,7 @@ system { }; resolver adns { }; -log-events "setup-init","setup-timeout","activate-key","timeout-key","errors", - "security"; +log-events "all"; random randomfile("/dev/urandom",no); transform serpent256-cbc { max-sequence-skew 10; diff --git a/test-example/inside.conf b/test-example/inside.conf index 775d593..4d41f30 100644 --- a/test-example/inside.conf +++ b/test-example/inside.conf @@ -8,7 +8,7 @@ netlink tun { interface "secnet-test-i"; }; comm udp { - port 16097; + port 16910; buffer sysbuffer(4096); }; local-name "test-example/inside/inside"; diff --git a/test-example/outside.conf b/test-example/outside.conf index f1a5228..db78b7b 100644 --- a/test-example/outside.conf +++ b/test-example/outside.conf @@ -8,7 +8,7 @@ netlink tun { interface "secnet-test-o"; }; comm udp { - port 16096; + port 16900; buffer sysbuffer(4096); }; local-name "test-example/outside/outside"; diff --git a/test-example/sites b/test-example/sites index 5aee3d8..470357b 100644 --- a/test-example/sites +++ b/test-example/sites @@ -7,19 +7,16 @@ restrict-nets 172.18.232.0/28 setup-timeout 2000 setup-retries 5 -location inside root -site inside - networks 172.18.232.8/29 - peer 172.18.232.9 - address [127.0.0.1] 16097 - pubkey 1024 65537 130064631890186713927887504218626486455931306300999583387009075747001546036643522074275473238061323169592347601185592753550279410171535737146240085267000508853176463710554801101055212967131924064664249613912656320653505750073021702169423354903540699008756137338575553686987244488914481168225136440872431691669 inside at example.com - location outside root site outside networks 172.18.232.0/29 peer 172.18.232.1 - address [127.0.0.1] 16096 + address [127.0.0.1] 16900 pubkey 1024 65537 129251483458784900555621175262818292872587807329014927540074484804119474262261383244074013537736576331652560727149001626325243856012659665194546933097292703586821422085819615124517093786704646988649444946154384037948502112302285511195679291084694375811092516151263088200304199780052361048758446082354317801941 outside at example.com - - +location inside root +site inside + networks 172.18.232.8/29 + peer 172.18.232.9 + address [127.0.0.1] 16910 + pubkey 1024 65537 130064631890186713927887504218626486455931306300999583387009075747001546036643522074275473238061323169592347601185592753550279410171535737146240085267000508853176463710554801101055212967131924064664249613912656320653505750073021702169423354903540699008756137338575553686987244488914481168225136440872431691669 inside at example.com -- 1.7.2.5 From ijackson at chiark.greenend.org.uk Wed Aug 17 23:54:26 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Wed, 17 Aug 2011 23:54:26 +0100 Subject: [PATCH 08/18] comm, site: pass a new "struct comm_addr" rather than sockaddr_in In-Reply-To: <1313621676-16031-1-git-send-email-ijackson@chiark.greenend.org.uk> References: <1313621676-16031-1-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1313621676-16031-9-git-send-email-ijackson@chiark.greenend.org.uk> This abstracts away the fact that the peer address is a sockaddr_in; instead, most of the code in site.c now only handles the peer address as an opaque structure. We put the struct comm_if* in the address structure too, as this will be useful later. Amongst other things, doing this arranges that the comm client knows which comm is notifying about an incoming packet. Previously the client was expected to "just know" because the only actual client in secnet is site which currently only deals with one comm. Also make the relevant arguments const-correct. Contains consequential changes the signatures of many functions but no intentional functional change. Signed-off-by: Ian Jackson --- secnet.h | 16 ++++++++++++++-- site.c | 29 +++++++++++++++-------------- udp.c | 15 ++++++++++----- 3 files changed, 39 insertions(+), 21 deletions(-) diff --git a/secnet.h b/secnet.h index 49afd32..809b3a7 100644 --- a/secnet.h +++ b/secnet.h @@ -303,16 +303,28 @@ struct rsaprivkey_if { /* COMM interface */ +struct comm_addr { + /* This struct is pure data; in particular comm's clients may + freely copy it. */ + /* Everyone is also guaranteed that all padding is set to zero, ie + that comm_addrs referring to semantically identical peers will + compare equal with memcmp. Anyone who constructs a comm_addr + must start by memsetting it with FILLZERO, or some + equivalent. */ + struct comm_if *comm; + struct sockaddr_in sin; +}; + /* Return True if the packet was processed, and shouldn't be passed to any other potential receivers. */ typedef bool_t comm_notify_fn(void *state, struct buffer_if *buf, - struct sockaddr_in *source); + const struct comm_addr *source); typedef void comm_request_notify_fn(void *commst, void *nst, comm_notify_fn *fn); typedef void comm_release_notify_fn(void *commst, void *nst, comm_notify_fn *fn); typedef bool_t comm_sendmsg_fn(void *commst, struct buffer_if *buf, - struct sockaddr_in *dest); + const struct comm_addr *dest); struct comm_if { void *st; int32_t min_start_pad; diff --git a/site.c b/site.c index 157d9f2..837745f 100644 --- a/site.c +++ b/site.c @@ -172,7 +172,7 @@ struct site { bool_t current_valid; uint64_t current_key_timeout; /* End of life of current key */ uint64_t renegotiate_key_time; /* When we can negotiate a new key */ - struct sockaddr_in peer; /* Current address of peer */ + struct comm_addr peer; /* Current address of peer */ bool_t peer_valid; /* Peer address becomes invalid when key times out, but only if we have a DNS name for our peer */ @@ -183,7 +183,7 @@ struct site { timeout before we can listen for another setup packet); perhaps we should keep a list of 'bad' sources for setup packets. */ uint32_t setup_session_id; - struct sockaddr_in setup_peer; + struct comm_addr setup_peer; uint8_t localN[NONCELEN]; /* Nonces for key exchange */ uint8_t remoteN[NONCELEN]; struct buffer_if buffer; /* Current outgoing key exchange packet */ @@ -372,7 +372,7 @@ static bool_t generate_msg1(struct site *st) } static bool_t process_msg1(struct site *st, struct buffer_if *msg1, - struct sockaddr_in *src) + const struct comm_addr *src) { struct msg m; @@ -395,7 +395,7 @@ static bool_t generate_msg2(struct site *st) } static bool_t process_msg2(struct site *st, struct buffer_if *msg2, - struct sockaddr_in *src) + const struct comm_addr *src) { struct msg m; cstring_t err; @@ -419,7 +419,7 @@ static bool_t generate_msg3(struct site *st) } static bool_t process_msg3(struct site *st, struct buffer_if *msg3, - struct sockaddr_in *src) + const struct comm_addr *src) { struct msg m; uint8_t *hash; @@ -470,7 +470,7 @@ static bool_t generate_msg4(struct site *st) } static bool_t process_msg4(struct site *st, struct buffer_if *msg4, - struct sockaddr_in *src) + const struct comm_addr *src) { struct msg m; uint8_t *hash; @@ -550,7 +550,7 @@ static bool_t generate_msg5(struct site *st) } static bool_t process_msg5(struct site *st, struct buffer_if *msg5, - struct sockaddr_in *src) + const struct comm_addr *src) { struct msg0 m; cstring_t transform_err; @@ -599,7 +599,7 @@ static bool_t generate_msg6(struct site *st) } static bool_t process_msg6(struct site *st, struct buffer_if *msg6, - struct sockaddr_in *src) + const struct comm_addr *src) { struct msg0 m; cstring_t transform_err; @@ -627,7 +627,7 @@ static bool_t process_msg6(struct site *st, struct buffer_if *msg6, } static bool_t process_msg0(struct site *st, struct buffer_if *msg0, - struct sockaddr_in *src) + const struct comm_addr *src) { struct msg0 m; cstring_t transform_err; @@ -666,7 +666,7 @@ 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) + const struct comm_addr *addr, bool_t incoming) { uint32_t dest=ntohl(*(uint32_t *)buf->start); uint32_t source=ntohl(*(uint32_t *)(buf->start+4)); @@ -709,9 +709,10 @@ static void site_resolve_callback(void *sst, struct in_addr *address) } if (address) { memset(&st->setup_peer,0,sizeof(st->setup_peer)); - st->setup_peer.sin_family=AF_INET; - st->setup_peer.sin_port=htons(st->remoteport); - st->setup_peer.sin_addr=*address; + st->setup_peer.comm=st->comm; + st->setup_peer.sin.sin_family=AF_INET; + st->setup_peer.sin.sin_port=htons(st->remoteport); + st->setup_peer.sin.sin_addr=*address; enter_new_state(st,SITE_SENTMSG1); } else { /* Resolution failed */ @@ -1022,7 +1023,7 @@ static void site_outgoing(void *sst, struct buffer_if *buf) /* This function is called by the communication device to deliver packets from our peers. */ static bool_t site_incoming(void *sst, struct buffer_if *buf, - struct sockaddr_in *source) + const struct comm_addr *source) { struct site *st=sst; uint32_t dest=ntohl(*(uint32_t *)buf->start); diff --git a/udp.c b/udp.c index 945d1d0..8ec8581 100644 --- a/udp.c +++ b/udp.c @@ -71,6 +71,7 @@ static void udp_afterpoll(void *state, struct pollfd *fds, int nfds) if (nfds && (fds->revents & POLLIN)) { do { + FILLZERO(from); fromlen=sizeof(from); BUF_ASSERT_FREE(st->rbuf); BUF_ALLOC(st->rbuf,"udp_afterpoll"); @@ -95,7 +96,11 @@ static void udp_afterpoll(void *state, struct pollfd *fds, int nfds) } done=False; for (n=st->notify; n; n=n->next) { - if (n->fn(n->state, st->rbuf, &from)) { + struct comm_addr ca; + FILLZERO(ca); + ca.comm=&st->ops; + ca.sin=from; + if (n->fn(n->state, st->rbuf, &ca)) { done=True; break; } @@ -156,21 +161,21 @@ static void release_notify(void *commst, void *nst, comm_notify_fn *fn) } static bool_t udp_sendmsg(void *commst, struct buffer_if *buf, - struct sockaddr_in *dest) + const struct comm_addr *dest) { struct udp *st=commst; uint8_t *sa; if (st->use_proxy) { sa=buf->start-8; - memcpy(sa,&dest->sin_addr,4); + memcpy(sa,&dest->sin.sin_addr,4); memset(sa+4,0,4); - memcpy(sa+6,&dest->sin_port,2); + memcpy(sa+6,&dest->sin.sin_port,2); sendto(st->fd,sa,buf->size+8,0,(struct sockaddr *)&st->proxy, sizeof(st->proxy)); } else { sendto(st->fd, buf->start, buf->size, 0, - (struct sockaddr *)dest, sizeof(*dest)); + (struct sockaddr *)&dest->sin, sizeof(dest->sin)); } return True; -- 1.7.2.5 From ijackson at chiark.greenend.org.uk Wed Aug 17 23:54:23 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Wed, 17 Aug 2011 23:54:23 +0100 Subject: [PATCH 05/18] Keepalives: Document that they're unimplemented; remove vestigial code In-Reply-To: <1313621676-16031-1-git-send-email-ijackson@chiark.greenend.org.uk> References: <1313621676-16031-1-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1313621676-16031-6-git-send-email-ijackson@chiark.greenend.org.uk> Keepalives are not actually implemented; the keepalive option does nothing. Mention this in the README. Remove the option's parsing and recording from site.c. Signed-off-by: Ian Jackson --- README | 3 ++- site.c | 3 --- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/README b/README index b094e66..73679c2 100644 --- a/README +++ b/README @@ -290,7 +290,8 @@ site: dict argument allowing another attempt [20000] renegotiate-time (integer): if we see traffic on the link after this time then renegotiate another session key immediately [depends on key-lifetime] - keepalive (bool): if True then attempt always to keep a valid session key + keepalive (bool): if True then attempt always to keep a valid session key. + Not actually currently implemented. [false] log-events (string list): types of events to log for this site unexpected: unexpected key setup packets (may be late retransmissions) setup-init: start of attempt to setup a session key diff --git a/site.c b/site.c index 006d9b4..a7775bd 100644 --- a/site.c +++ b/site.c @@ -154,8 +154,6 @@ struct site { int32_t key_renegotiate_time; /* If we see traffic (or a keepalive) after this time, initiate a new key exchange */ - bool_t keepalive; /* Send keepalives to detect peer failure (not yet - implemented) */ uint8_t *setupsig; /* Expected signature of incoming MSG1 packets */ int32_t setupsiglen; /* Allows us to discard packets quickly if @@ -1259,7 +1257,6 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context, cfgfatal(loc,"site", "renegotiate-time must be less than key-lifetime\n"); } - st->keepalive=dict_read_bool(dict,"keepalive",False,"site",loc,False); st->log_events=string_list_to_word(dict_lookup(dict,"log-events"), log_event_table,"site"); -- 1.7.2.5 From ijackson at chiark.greenend.org.uk Wed Aug 17 23:54:20 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Wed, 17 Aug 2011 23:54:20 +0100 Subject: [PATCH 02/18] secnet.h: provide helpful STRING macro (for preprocessor stringification) In-Reply-To: <1313621676-16031-1-git-send-email-ijackson@chiark.greenend.org.uk> References: <1313621676-16031-1-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1313621676-16031-3-git-send-email-ijackson@chiark.greenend.org.uk> Uses preprocessor stringification; can be helpful for rendering compile-time constants (eg compile time limit macros) for messages, etc. Not used yet; will be used later in this series. Signed-off-by: Ian Jackson --- secnet.h | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/secnet.h b/secnet.h index b60972f..6559ef3 100644 --- a/secnet.h +++ b/secnet.h @@ -495,4 +495,7 @@ extern void log_from_fd(int fd, cstring_t prefix, struct log_if *log); /***** END of log functions *****/ +#define STRING2(x) #x +#define STRING(x) STRING2(x) + #endif /* secnet_h */ -- 1.7.2.5 From ijackson at chiark.greenend.org.uk Wed Aug 17 23:54:24 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Wed, 17 Aug 2011 23:54:24 +0100 Subject: [PATCH 06/18] site: Remove some spurious "break"s In-Reply-To: <1313621676-16031-1-git-send-email-ijackson@chiark.greenend.org.uk> References: <1313621676-16031-1-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1313621676-16031-7-git-send-email-ijackson@chiark.greenend.org.uk> Remove two occurrences of "break" which immediately follow unconditional "return". No functional change. Signed-off-by: Ian Jackson --- site.c | 2 -- 1 files changed, 0 insertions(+), 2 deletions(-) diff --git a/site.c b/site.c index a7775bd..34805f6 100644 --- a/site.c +++ b/site.c @@ -653,12 +653,10 @@ static bool_t process_msg0(struct site *st, struct buffer_if *msg0, /* We must forget about the current session. */ delete_key(st,"request from peer",LOG_SEC); return True; - break; case LABEL_MSG9: /* Deliver to netlink layer */ st->netlink->deliver(st->netlink->st,msg0); return True; - break; default: slog(st,LOG_SEC,"incoming encrypted message of type %08x " "(unknown)",type); -- 1.7.2.5 From ijackson at chiark.greenend.org.uk Wed Aug 17 23:54:27 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Wed, 17 Aug 2011 23:54:27 +0100 Subject: [PATCH 09/18] Site tuning defaults: Improve documentation; internal improvements In-Reply-To: <1313621676-16031-1-git-send-email-ijackson@chiark.greenend.org.uk> References: <1313621676-16031-1-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1313621676-16031-10-git-send-email-ijackson@chiark.greenend.org.uk> Two documentation fixes: * Quote the correct default value for setup-timeout (setup_retry_interval) in the README. * Improve the documentation of the default value for renegotiate-time. Three simple internal improvements: * Change definitions of DEFAULT_* to forms which make the semantics of the values clearer, thus obviating the need for the comments giving human-readable values. * Add comments to DEFAULT_* time values giving the units (currently, they are all in millisecons). * Rename (in the code) SETUP_TIMEOUT and setup_timeout to SETUP_RETRY_INTERVAL, which is more accurate. We leave the config dictionary entry with the misleading name (particularly, since we have no facility for spotting obsolete or misspelled config keys). Also two changes which are preparatory to the mobile peers support: * New macro DEFAULT(D) which currently simply expands to DEFAULT_*. * New convenience macro CFG_NUMBER for a common pattern of use for dict_read_number, which uses DEFAULT(). No intentional functional changes. Signed-off-by: Ian Jackson --- README | 5 +++-- site.c | 33 ++++++++++++++++----------------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/README b/README index 73679c2..0109cfa 100644 --- a/README +++ b/README @@ -285,11 +285,12 @@ site: dict argument setup-retries (integer): max number of times to transmit a key negotiation packet [5] setup-timeout (integer): time between retransmissions of key negotiation - packets, in ms [1000] + packets, in ms [2000] wait-time (integer): after failed key setup, wait this long (in ms) before allowing another attempt [20000] renegotiate-time (integer): if we see traffic on the link after this time - then renegotiate another session key immediately [depends on key-lifetime] + then renegotiate another session key immediately (in ms) + [half key-lifetime, or key-lifetime minus 5 mins, whichever is longer]. keepalive (bool): if True then attempt always to keep a valid session key. Not actually currently implemented. [false] log-events (string list): types of events to log for this site diff --git a/site.c b/site.c index 837745f..13a6bc3 100644 --- a/site.c +++ b/site.c @@ -27,11 +27,11 @@ #define SETUP_BUFFER_LEN 2048 -#define DEFAULT_KEY_LIFETIME 3600000 /* One hour */ -#define DEFAULT_KEY_RENEGOTIATE_GAP 300000 /* Five minutes */ +#define DEFAULT_KEY_LIFETIME (3600*1000) /* [ms] */ +#define DEFAULT_KEY_RENEGOTIATE_GAP (5*60*1000) /* [ms] */ #define DEFAULT_SETUP_RETRIES 5 -#define DEFAULT_SETUP_TIMEOUT 2000 -#define DEFAULT_WAIT_TIME 20000 +#define DEFAULT_SETUP_RETRY_INTERVAL (2*1000) /* [ms] */ +#define DEFAULT_WAIT_TIME (20*1000) /* [ms] */ /* Each site can be in one of several possible states. */ @@ -148,7 +148,7 @@ struct site { uint32_t index; /* Index of this site */ int32_t setup_retries; /* How many times to send setup packets */ - int32_t setup_timeout; /* Initial timeout for setup packets */ + int32_t setup_retry_interval; /* Initial timeout for setup packets */ int32_t wait_timeout; /* How long to wait if setup unsuccessful */ int32_t key_lifetime; /* How long a key lasts once set up */ int32_t key_renegotiate_time; /* If we see traffic (or a keepalive) @@ -688,7 +688,7 @@ static bool_t send_msg(struct site *st) if (st->retries>0) { dump_packet(st,&st->buffer,&st->setup_peer,False); st->comm->sendmsg(st->comm->st,&st->buffer,&st->setup_peer); - st->timeout=st->now+st->setup_timeout; + st->timeout=st->now+st->setup_retry_interval; st->retries--; return True; } else { @@ -875,7 +875,7 @@ static bool_t enter_new_state(struct site *st, uint32_t next) r= gen(st) && send_msg(st); hacky_par_end(&r, - st->setup_retries, st->setup_timeout, + st->setup_retries, st->setup_retry_interval, send_msg, st); if (r) { @@ -1238,19 +1238,18 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context, st->dh=find_cl_if(dict,"dh",CL_DH,True,"site",loc); st->hash=find_cl_if(dict,"hash",CL_HASH,True,"site",loc); - st->key_lifetime=dict_read_number( - dict,"key-lifetime",False,"site",loc,DEFAULT_KEY_LIFETIME); - st->setup_retries=dict_read_number( - dict,"setup-retries",False,"site",loc,DEFAULT_SETUP_RETRIES); - st->setup_timeout=dict_read_number( - dict,"setup-timeout",False,"site",loc,DEFAULT_SETUP_TIMEOUT); - st->wait_timeout=dict_read_number( - dict,"wait-time",False,"site",loc,DEFAULT_WAIT_TIME); +#define DEFAULT(D) DEFAULT_##D +#define CFG_NUMBER(k,D) dict_read_number(dict,(k),False,"site",loc,DEFAULT(D)); - if (st->key_lifetime < DEFAULT_KEY_RENEGOTIATE_GAP*2) + st->key_lifetime= CFG_NUMBER("key-lifetime", KEY_LIFETIME); + st->setup_retries= CFG_NUMBER("setup-retries", SETUP_RETRIES); + st->setup_retry_interval= CFG_NUMBER("setup-timeout", SETUP_RETRY_INTERVAL); + st->wait_timeout= CFG_NUMBER("wait-time", WAIT_TIME); + + if (st->key_lifetime < DEFAULT(KEY_RENEGOTIATE_GAP)*2) st->key_renegotiate_time=st->key_lifetime/2; else - st->key_renegotiate_time=st->key_lifetime-DEFAULT_KEY_RENEGOTIATE_GAP; + st->key_renegotiate_time=st->key_lifetime-DEFAULT(KEY_RENEGOTIATE_GAP); st->key_renegotiate_time=dict_read_number( dict,"renegotiate-time",False,"site",loc,st->key_renegotiate_time); if (st->key_renegotiate_time > st->key_lifetime) { -- 1.7.2.5 From ijackson at chiark.greenend.org.uk Wed Aug 17 23:54:21 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Wed, 17 Aug 2011 23:54:21 +0100 Subject: [PATCH 03/18] cleanup: provide helpful FILLZERO macro (for certain memset calls) In-Reply-To: <1313621676-16031-1-git-send-email-ijackson@chiark.greenend.org.uk> References: <1313621676-16031-1-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1313621676-16031-4-git-send-email-ijackson@chiark.greenend.org.uk> This macro replaces these idioms: memset(&foo,0,sizeof(foo)); => FILLZERO(foo); memset(foo,0,sizeof(*foo)); => FILLZERO(*foo); This makes it impossible to accidentally get the wrong size. Use this macro in all such patterns in secnet, apart from two in site.c which are going to be removed soon anyway. No intentional functional change. Signed-off-by: Ian Jackson --- secnet.h | 2 ++ transform.c | 6 +++--- tun.c | 10 +++++----- udp.c | 4 ++-- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/secnet.h b/secnet.h index 6559ef3..49afd32 100644 --- a/secnet.h +++ b/secnet.h @@ -498,4 +498,6 @@ extern void log_from_fd(int fd, cstring_t prefix, struct log_if *log); #define STRING2(x) #x #define STRING(x) STRING2(x) +#define FILLZERO(obj) (memset(&(obj),0,sizeof((obj)))) + #endif /* secnet_h */ diff --git a/transform.c b/transform.c index b13c2dd..8fdf9fd 100644 --- a/transform.c +++ b/transform.c @@ -72,8 +72,8 @@ static void transform_delkey(void *sst) { struct transform_inst *ti=sst; - memset(&ti->cryptkey,0,sizeof(ti->cryptkey)); - memset(&ti->mackey,0,sizeof(ti->mackey)); + FILLZERO(ti->cryptkey); + FILLZERO(ti->mackey); ti->keyed=False; } @@ -252,7 +252,7 @@ static void transform_destroy(void *sst) { struct transform_inst *st=sst; - memset(st,0,sizeof(*st)); /* Destroy key material */ + FILLZERO(*st); /* Destroy key material */ free(st); } diff --git a/tun.c b/tun.c index 3db998f..0baaf12 100644 --- a/tun.c +++ b/tun.c @@ -211,7 +211,7 @@ static bool_t tun_set_route(void *sst, struct netlink_client *routes) struct sockaddr_in *sa; int action; - memset(&rt,0,sizeof(rt)); + FILLZERO(rt); sa=(struct sockaddr_in *)&rt.rt_dst; sa->sin_family=AF_INET; sa->sin_addr.s_addr=htonl(nets->list[i].prefix); @@ -292,7 +292,7 @@ static void tun_phase_hook(void *sst, uint32_t newphase) fatal_perror("%s: can't open device file %s",st->nl.name, st->device_path); } - memset(&ifr,0,sizeof(ifr)); + FILLZERO(ifr); ifr.ifr_flags = IFF_TUN | IFF_NO_PI; /* Just send/receive IP packets, no extra headers */ if (st->interface_name) @@ -379,7 +379,7 @@ static void tun_phase_hook(void *sst, uint32_t newphase) /* Interface address */ strncpy(ifr.ifr_name,st->interface_name,IFNAMSIZ); sa=(struct sockaddr_in *)&ifr.ifr_addr; - memset(sa,0,sizeof(*sa)); + FILLZERO(*sa); sa->sin_family=AF_INET; sa->sin_addr.s_addr=htonl(st->local_address); if (ioctl(fd,SIOCSIFADDR, &ifr)!=0) { @@ -389,7 +389,7 @@ static void tun_phase_hook(void *sst, uint32_t newphase) /* Netmask */ strncpy(ifr.ifr_name,st->interface_name,IFNAMSIZ); sa=(struct sockaddr_in *)&ifr.ifr_netmask; - memset(sa,0,sizeof(*sa)); + FILLZERO(*sa); sa->sin_family=AF_INET; sa->sin_addr.s_addr=htonl(0xffffffff); if (ioctl(fd,SIOCSIFNETMASK, &ifr)!=0) { @@ -399,7 +399,7 @@ static void tun_phase_hook(void *sst, uint32_t newphase) /* Destination address (point-to-point) */ strncpy(ifr.ifr_name,st->interface_name,IFNAMSIZ); sa=(struct sockaddr_in *)&ifr.ifr_dstaddr; - memset(sa,0,sizeof(*sa)); + FILLZERO(*sa); sa->sin_family=AF_INET; sa->sin_addr.s_addr=htonl(st->nl.secnet_address); if (ioctl(fd,SIOCSIFDSTADDR, &ifr)!=0) { diff --git a/udp.c b/udp.c index 7ff4d5f..945d1d0 100644 --- a/udp.c +++ b/udp.c @@ -194,7 +194,7 @@ static void udp_phase_hook(void *sst, uint32_t new_phase) st->loc.file,st->loc.line); } - memset(&addr, 0, sizeof(addr)); + FILLZERO(addr); addr.sin_family=AF_INET; addr.sin_addr.s_addr=htonl(st->addr); addr.sin_port=htons(st->port); @@ -279,7 +279,7 @@ static list_t *udp_apply(closure_t *self, struct cloc loc, dict_t *context, l=dict_lookup(d,"proxy"); if (l) { st->use_proxy=True; - memset(&st->proxy,0,sizeof(st->proxy)); + FILLZERO(st->proxy); st->proxy.sin_family=AF_INET; i=list_elem(l,0); if (!i || i->type!=t_string) { -- 1.7.2.5 From ijackson at chiark.greenend.org.uk Wed Aug 17 23:54:28 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Wed, 17 Aug 2011 23:54:28 +0100 Subject: [PATCH 10/18] comm, udp: Provide an addr_to_string method In-Reply-To: <1313621676-16031-1-git-send-email-ijackson@chiark.greenend.org.uk> References: <1313621676-16031-1-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1313621676-16031-11-git-send-email-ijackson@chiark.greenend.org.uk> This method writes (into a single static buffer) a string describing a comm_addr. It describes both the comm instance and the peer address. No callers yet, but one is about to be introduced. Signed-off-by: Ian Jackson --- secnet.h | 4 ++++ udp.c | 27 +++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 0 deletions(-) diff --git a/secnet.h b/secnet.h index 809b3a7..fbb7660 100644 --- a/secnet.h +++ b/secnet.h @@ -325,6 +325,9 @@ typedef void comm_release_notify_fn(void *commst, void *nst, comm_notify_fn *fn); typedef bool_t comm_sendmsg_fn(void *commst, struct buffer_if *buf, const struct comm_addr *dest); +typedef const char *comm_addr_to_string_fn(void *commst, + const struct comm_addr *ca); + /* Returned string is in a static buffer. */ struct comm_if { void *st; int32_t min_start_pad; @@ -332,6 +335,7 @@ struct comm_if { comm_request_notify_fn *request_notify; comm_release_notify_fn *release_notify; comm_sendmsg_fn *sendmsg; + comm_addr_to_string_fn *addr_to_string; }; /* LOG interface */ diff --git a/udp.c b/udp.c index 8ec8581..f420664 100644 --- a/udp.c +++ b/udp.c @@ -16,6 +16,8 @@ #include #include #include +#include +#include #include "util.h" #include "unaligned.h" #include "ipaddr.h" @@ -46,6 +48,30 @@ struct udp { struct sockaddr_in proxy; }; +static const char *saddr_to_string(const struct sockaddr_in *sin) { + static char bufs[2][100]; + static int b; + + b ^= 1; + snprintf(bufs[b], sizeof(bufs[b]), "[%s]:%d", + inet_ntoa(sin->sin_addr), + ntohs(sin->sin_port)); + return bufs[b]; +} + +static const char *addr_to_string(void *commst, const struct comm_addr *ca) { + struct udp *st=commst; + static char sbuf[100]; + + struct sockaddr_in la; + la.sin_addr.s_addr=htonl(st->addr); + la.sin_port=htons(st->port); + + snprintf(sbuf, sizeof(sbuf), "udp:%s-%s", + saddr_to_string(&la), saddr_to_string(&ca->sin)); + return sbuf; +} + static int udp_beforepoll(void *state, struct pollfd *fds, int *nfds_io, int *timeout_io) { @@ -267,6 +293,7 @@ static list_t *udp_apply(closure_t *self, struct cloc loc, dict_t *context, st->ops.request_notify=request_notify; st->ops.release_notify=release_notify; st->ops.sendmsg=udp_sendmsg; + st->ops.addr_to_string=addr_to_string; st->port=0; st->use_proxy=False; -- 1.7.2.5 From ijackson at chiark.greenend.org.uk Wed Aug 17 23:54:29 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Wed, 17 Aug 2011 23:54:29 +0100 Subject: [PATCH 11/18] Protocol change: Initiate key setup on incoming packets, not outgoing ones In-Reply-To: <1313621676-16031-1-git-send-email-ijackson@chiark.greenend.org.uk> References: <1313621676-16031-1-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1313621676-16031-12-git-send-email-ijackson@chiark.greenend.org.uk> If data is exchanged after the "renegotiation time", we need to refresh the data transfer key - ie, to initiate a key setup. Previously this was done by the peer which wanted to transmit data using an existing but in-need-of-refreshing key. However, mobile peers may often be disconnected. There is no point trying to do a key renegotiation while they are disconnected. Thus it is better to have the renegotiation initiated by a peer which receives a data packet. That means that if there is a network outage, renegotiation will be deferred until the network is restored. In particular, it means that a mobile node which has no underlying network but which has applications trying to send data will not waste effort attempting key renegotiation until it once more has connectivity. This minor functional change should be harmless or even beneficial for non-mobile sites too. It simply means that the other peer will play the role of initiator during renegotiation, but since which peer played this role is arbitrary for non-mobile sites this should make no difference. Compatibility: In the case of an old version of secnet talking to a new version, only data packets in one direction will cause renegotiation. This should not be a problem since all real-world IP protocols involve data in both directions. So we make the new behaviour universal rather than making it depend on the forthcoming "mobile-peer" site config option. Signed-off-by: Ian Jackson --- site.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/site.c b/site.c index 13a6bc3..5a4b64a 100644 --- a/site.c +++ b/site.c @@ -656,6 +656,9 @@ static bool_t process_msg0(struct site *st, struct buffer_if *msg0, case LABEL_MSG9: /* Deliver to netlink layer */ st->netlink->deliver(st->netlink->st,msg0); + /* See whether we should start negotiating a new key */ + if (st->now > st->renegotiate_key_time) + initiate_key_setup(st,"incoming packet in renegotiation window"); return True; default: slog(st,LOG_SEC,"incoming encrypted message of type %08x " @@ -1009,9 +1012,6 @@ static void site_outgoing(void *sst, struct buffer_if *buf) st->comm->sendmsg(st->comm->st,buf,&st->peer); } BUF_FREE(buf); - /* See whether we should start negotiating a new key */ - if (st->now > st->renegotiate_key_time) - initiate_key_setup(st,"outgoing packet in renegotiation window"); return; } -- 1.7.2.5 From ijackson at chiark.greenend.org.uk Wed Aug 17 23:54:30 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Wed, 17 Aug 2011 23:54:30 +0100 Subject: [PATCH 12/18] Mobile sites: Maintain multiple addresses for some peers (new feature) In-Reply-To: <1313621676-16031-1-git-send-email-ijackson@chiark.greenend.org.uk> References: <1313621676-16031-1-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1313621676-16031-13-git-send-email-ijackson@chiark.greenend.org.uk> Provides the following new config option, and some satellite options: mobile (bool): if True then peer is "mobile" ie we assume it may change its apparent IP address and port number without either it or us being aware of the change; so, we remember the last several port/addr pairs we've seen and send packets to all of them (subject to a timeout). We maintain one set of addresses for key setup exchanges, and another for data traffic. [false] In the code this involves replacing the comm_addrs for setup_peer and peer with a new struct transport_peers which contains zero or more comm_addrs. This subsumes peer_valid, too. Additionally, we are slightly cleaner about the use of setup_peer: we ensure that we clean it out appropriately when we go into states where it won't (shouldn't) be used. The transport_peers structure is opaque to most of site.c and is manipulated by a new set of functions which implement the detailed semantics described in site.c. The main code in site.c is no longer supposed to call dump_packet and st->comm->sendmsg directly; it should use transport_xmit (which will do dump_packet as well as appropriate sendmsgs). No intentional functional change if mobile=false (the default) and the new debug log feature ("peer-addrs") is not enabled. Signed-off-by: Ian Jackson --- README | 17 ++++ site.c | 318 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 302 insertions(+), 33 deletions(-) diff --git a/README b/README index 0109cfa..3736b89 100644 --- a/README +++ b/README @@ -304,7 +304,24 @@ site: dict argument packet-drop: whenever we throw away an outgoing packet dump-packets: every key setup packet we see errors: failure of name resolution, internal errors + peer-addrs: changes to sets of peer addresses (interesting for mobile peers) all: everything (too much!) + mobile (bool): if True then peer is "mobile" ie we assume it may + change its apparent IP address and port number without either it + or us being aware of the change; so, we remember the last several + port/addr pairs we've seen and send packets to all of them + (subject to a timeout). We maintain one set of addresses for key + setup exchanges, and another for data traffic. Two communicating + peers must not each regard the other as mobile, or all the traffic + in each direction will be triplicated (strictly, transmitted + mobile-peers-max times) and anyway two peers whose public contact + address may suddenly change couldn't communicate reliably because + their contact addresses might both change at once. [false] + mobile-peers-max (integer): Maximum number of peer port/addr pairs we + remember and send to. Must be at least 1 and no more than 5. [3] + mobile-peer-expiry (integer): For "mobile" peers only, the length + of time (in seconds) for which we will keep sending to multiple + address/ports from which we have not seen incoming traffic. [120] ** transform diff --git a/site.c b/site.c index 5a4b64a..9d09ebc 100644 --- a/site.c +++ b/site.c @@ -32,6 +32,8 @@ #define DEFAULT_SETUP_RETRIES 5 #define DEFAULT_SETUP_RETRY_INTERVAL (2*1000) /* [ms] */ #define DEFAULT_WAIT_TIME (20*1000) /* [ms] */ +#define DEFAULT_MOBILE_PEER_EXPIRY (2*60) /* [s] */ +#define DEFAULT_MOBILE_PEERS_MAX 3 /* send at most this many copies (default) */ /* Each site can be in one of several possible states. */ @@ -108,6 +110,7 @@ static cstring_t state_name(uint32_t state) #define LOG_DROP 0x00000080 #define LOG_DUMP 0x00000100 #define LOG_ERROR 0x00000400 +#define LOG_PEER_ADDRS 0x00000800 static struct flagstr log_event_table[]={ { "unexpected", LOG_UNEXPECTED }, @@ -120,18 +123,98 @@ static struct flagstr log_event_table[]={ { "packet-drop", LOG_DROP }, { "dump-packets", LOG_DUMP }, { "errors", LOG_ERROR }, + { "peer-addrs", LOG_PEER_ADDRS }, { "default", LOG_SETUP_INIT|LOG_SETUP_TIMEOUT| LOG_ACTIVATE_KEY|LOG_TIMEOUT_KEY|LOG_SEC|LOG_ERROR }, { "all", 0xffffffff }, { NULL, 0 } }; + +/***** TRANSPORT PEERS declarations *****/ + +/* Details of "mobile peer" semantics: + + - We record mobile_peers_max peer address/port numbers ("peers") + for key setup, and separately mobile_peers_max for data + transfer. If these lists fill up, we retain the newest peers. + (For non-mobile peers we only record one of each.) + + - Outgoing packets are sent to every recorded peer in the + applicable list. + + - Data transfer peers are straightforward: whenever we successfully + process a data packet, we record the peer. Also, whenever we + successfully complete a key setup, we merge the key setup + peers into the data transfer peers. + + (For "non-mobile" peers we simply copy the peer used for + successful key setup, and don't change the peer otherwise.) + + - Key setup peers are slightly more complicated. + + Whenever we receive and successfully process a key exchange + packet, we record the peer. + + Whenever we try to initiate a key setup, we copy the list of data + transfer peers and use it for key setup. But we also look to see + if the config supplies an address and port number and if so we + add that as a key setup peer (possibly evicting one of the data + transfer peers we just copied). + + (For "non-mobile" peers, if we if we have a configured peer + address and port, we always use that; otherwise if we have a + current data peer address we use that; otherwise we do not + attempt to initiate a key setup for lack of a peer address.) + + "Record the peer" means + 1. expire any peers last seen >120s ("mobile-peer-expiry") ago + 2. add the peer of the just received packet to the applicable list + (possibly evicting older entries) + NB that we do not expire peers until an incoming packet arrives. + + */ + +#define MAX_MOBILE_PEERS_MAX 5 /* send at most this many copies, compiled max */ + +typedef struct { + struct timeval last; + struct comm_addr addr; +} transport_peer; + +typedef struct { +/* configuration information */ +/* runtime information */ + int npeers; + transport_peer peers[MAX_MOBILE_PEERS_MAX]; +} transport_peers; + +static void transport_peers_clear(struct site *st, transport_peers *peers); +static int transport_peers_valid(transport_peers *peers); +static void transport_peers_copy(struct site *st, transport_peers *dst, + const transport_peers *src); + +static void transport_setup_msgok(struct site *st, const struct comm_addr *a); +static void transport_data_msgok(struct site *st, const struct comm_addr *a); +static bool_t transport_compute_setupinit_peers(struct site *st, + const struct comm_addr *configured_addr /* 0 if none or not found */); +static void transport_record_peer(struct site *st, transport_peers *peers, + const struct comm_addr *addr, const char *m); + +static void transport_xmit(struct site *st, transport_peers *peers, + struct buffer_if *buf, bool_t candebug); + + /***** END of transport peers declarations *****/ + + struct site { closure_t cl; struct site_if ops; /* configuration information */ string_t localname; string_t remotename; + bool_t peer_mobile; /* Mobile client support */ + int32_t transport_peers_max; string_t tunname; /* localname<->remotename by default, used in logs */ string_t address; /* DNS name for bootstrapping, optional */ int remoteport; /* Port for bootstrapping, optional */ @@ -150,6 +233,7 @@ struct site { int32_t setup_retries; /* How many times to send setup packets */ int32_t setup_retry_interval; /* Initial timeout for setup packets */ int32_t wait_timeout; /* How long to wait if setup unsuccessful */ + int32_t mobile_peer_expiry; /* How long to remember 2ary addresses */ int32_t key_lifetime; /* How long a key lasts once set up */ int32_t key_renegotiate_time; /* If we see traffic (or a keepalive) after this time, initiate a new @@ -172,9 +256,7 @@ struct site { bool_t current_valid; uint64_t current_key_timeout; /* End of life of current key */ uint64_t renegotiate_key_time; /* When we can negotiate a new key */ - struct comm_addr peer; /* Current address of peer */ - bool_t peer_valid; /* Peer address becomes invalid when key times out, - but only if we have a DNS name for our peer */ + transport_peers peers; /* Current address(es) of peer for data traffic */ /* The current key setup protocol exchange. We can only be involved in one of these at a time. There's a potential for @@ -183,7 +265,7 @@ struct site { timeout before we can listen for another setup packet); perhaps we should keep a list of 'bad' sources for setup packets. */ uint32_t setup_session_id; - struct comm_addr setup_peer; + transport_peers setup_peers; uint8_t localN[NONCELEN]; /* Nonces for key exchange */ uint8_t remoteN[NONCELEN]; struct buffer_if buffer; /* Current outgoing key exchange packet */ @@ -214,6 +296,7 @@ static void slog(struct site *st, uint32_t event, cstring_t msg, ...) case LOG_DROP: class=M_DEBUG; break; case LOG_DUMP: class=M_DEBUG; break; case LOG_ERROR: class=M_ERR; break; + case LOG_PEER_ADDRS: class=M_DEBUG; break; default: class=M_ERR; break; } @@ -382,7 +465,7 @@ static bool_t process_msg1(struct site *st, struct buffer_if *msg1, if (!unpick_msg(st,LABEL_MSG1,msg1,&m)) return False; - st->setup_peer=*src; + transport_record_peer(st,&st->setup_peers,src,"msg1"); st->setup_session_id=m.source; memcpy(st->remoteN,m.nR,NONCELEN); return True; @@ -656,6 +739,7 @@ static bool_t process_msg0(struct site *st, struct buffer_if *msg0, case LABEL_MSG9: /* Deliver to netlink layer */ st->netlink->deliver(st->netlink->st,msg0); + transport_data_msgok(st,src); /* See whether we should start negotiating a new key */ if (st->now > st->renegotiate_key_time) initiate_key_setup(st,"incoming packet in renegotiation window"); @@ -689,8 +773,7 @@ static uint32_t site_status(void *st) static bool_t send_msg(struct site *st) { if (st->retries>0) { - dump_packet(st,&st->buffer,&st->setup_peer,False); - st->comm->sendmsg(st->comm->st,&st->buffer,&st->setup_peer); + transport_xmit(st, &st->setup_peers, &st->buffer, True); st->timeout=st->now+st->setup_retry_interval; st->retries--; return True; @@ -705,21 +788,28 @@ static bool_t send_msg(struct site *st) static void site_resolve_callback(void *sst, struct in_addr *address) { struct site *st=sst; + struct comm_addr ca_buf, *ca_use; if (st->state!=SITE_RESOLVE) { slog(st,LOG_UNEXPECTED,"site_resolve_callback called unexpectedly"); return; } if (address) { - memset(&st->setup_peer,0,sizeof(st->setup_peer)); - st->setup_peer.comm=st->comm; - st->setup_peer.sin.sin_family=AF_INET; - st->setup_peer.sin.sin_port=htons(st->remoteport); - st->setup_peer.sin.sin_addr=*address; - enter_new_state(st,SITE_SENTMSG1); + FILLZERO(ca_buf); + ca_buf.comm=st->comm; + ca_buf.sin.sin_family=AF_INET; + ca_buf.sin.sin_port=htons(st->remoteport); + ca_buf.sin.sin_addr=*address; + ca_use=&ca_buf; } else { - /* Resolution failed */ slog(st,LOG_ERROR,"resolution of %s failed",st->address); + ca_use=0; + } + if (transport_compute_setupinit_peers(st,ca_use)) { + enter_new_state(st,SITE_SENTMSG1); + } else { + /* Can't figure out who to try to to talk to */ + slog(st,LOG_SETUP_INIT,"key exchange failed: cannot find peer address"); enter_state_run(st); } } @@ -731,9 +821,7 @@ static bool_t initiate_key_setup(struct site *st, cstring_t reason) if (st->address) { slog(st,LOG_SETUP_INIT,"resolving peer address"); return enter_state_resolve(st); - } else if (st->peer_valid) { - slog(st,LOG_SETUP_INIT,"using old peer address"); - st->setup_peer=st->peer; + } else if (transport_compute_setupinit_peers(st,0)) { return enter_new_state(st,SITE_SENTMSG1); } slog(st,LOG_SETUP_INIT,"key exchange failed: no address for peer"); @@ -755,8 +843,7 @@ static void activate_new_key(struct site *st) st->current_valid=True; st->current_key_timeout=st->now+st->key_lifetime; st->renegotiate_key_time=st->now+st->key_renegotiate_time; - st->peer=st->setup_peer; - st->peer_valid=True; + transport_peers_copy(st,&st->peers,&st->setup_peers); st->remote_session_id=st->setup_session_id; slog(st,LOG_ACTIVATE_KEY,"new key activated"); @@ -797,7 +884,7 @@ static void set_link_quality(struct site *st) quality=LINK_QUALITY_DOWN; else if (st->address) quality=LINK_QUALITY_DOWN_CURRENT_ADDRESS; - else if (st->peer_valid) + else if (transport_peers_valid(&st->peers)) quality=LINK_QUALITY_DOWN_STALE_ADDRESS; else quality=LINK_QUALITY_DOWN; @@ -812,7 +899,7 @@ static void enter_state_run(struct site *st) st->timeout=0; st->setup_session_id=0; - memset(&st->setup_peer,0,sizeof(st->setup_peer)); + transport_peers_clear(st,&st->setup_peers); memset(st->localN,0,NONCELEN); memset(st->remoteN,0,NONCELEN); st->new_transform->delkey(st->new_transform->st); @@ -903,7 +990,8 @@ static bool_t send_msg7(struct site *st, cstring_t reason) { cstring_t transform_err; - if (st->current_valid && st->peer_valid && st->buffer.free) { + if (st->current_valid && st->buffer.free + && transport_peers_valid(&st->peers)) { BUF_ALLOC(&st->buffer,"site:MSG7"); buffer_init(&st->buffer,st->transform->max_start_pad+(4*3)); buf_append_uint32(&st->buffer,LABEL_MSG7); @@ -913,8 +1001,7 @@ static bool_t send_msg7(struct site *st, cstring_t reason) buf_prepend_uint32(&st->buffer,LABEL_MSG0); buf_prepend_uint32(&st->buffer,st->index); buf_prepend_uint32(&st->buffer,st->remote_session_id); - dump_packet(st,&st->buffer,&st->peer,False); - st->comm->sendmsg(st->comm->st,&st->buffer,&st->peer); + transport_xmit(st,&st->peers,&st->buffer,True); BUF_FREE(&st->buffer); return True; } @@ -1000,7 +1087,7 @@ static void site_outgoing(void *sst, struct buffer_if *buf) /* In all other states we consider delivering the packet if we have a valid key and a valid address to send it to. */ - if (st->current_valid && st->peer_valid) { + if (st->current_valid && transport_peers_valid(&st->peers)) { /* Transform it and send it */ if (buf->size>0) { buf_prepend_uint32(buf,LABEL_MSG9); @@ -1009,7 +1096,7 @@ static void site_outgoing(void *sst, struct buffer_if *buf) buf_prepend_uint32(buf,LABEL_MSG0); buf_prepend_uint32(buf,st->index); buf_prepend_uint32(buf,st->remote_session_id); - st->comm->sendmsg(st->comm->st,buf,&st->peer); + transport_xmit(st,&st->peers,buf,False); } BUF_FREE(buf); return; @@ -1103,9 +1190,10 @@ static bool_t site_incoming(void *sst, struct buffer_if *buf, /* Setup packet: expected only in state SENTMSG1 */ if (st->state!=SITE_SENTMSG1) { slog(st,LOG_UNEXPECTED,"unexpected MSG2"); - } else if (process_msg2(st,buf,source)) + } else if (process_msg2(st,buf,source)) { + transport_setup_msgok(st,source); enter_new_state(st,SITE_SENTMSG3); - else { + } else { slog(st,LOG_SEC,"invalid MSG2"); } break; @@ -1113,9 +1201,10 @@ static bool_t site_incoming(void *sst, struct buffer_if *buf, /* Setup packet: expected only in state SENTMSG2 */ if (st->state!=SITE_SENTMSG2) { slog(st,LOG_UNEXPECTED,"unexpected MSG3"); - } else if (process_msg3(st,buf,source)) + } else if (process_msg3(st,buf,source)) { + transport_setup_msgok(st,source); enter_new_state(st,SITE_SENTMSG4); - else { + } else { slog(st,LOG_SEC,"invalid MSG3"); } break; @@ -1123,9 +1212,10 @@ static bool_t site_incoming(void *sst, struct buffer_if *buf, /* Setup packet: expected only in state SENTMSG3 */ if (st->state!=SITE_SENTMSG3) { slog(st,LOG_UNEXPECTED,"unexpected MSG4"); - } else if (process_msg4(st,buf,source)) + } else if (process_msg4(st,buf,source)) { + transport_setup_msgok(st,source); enter_new_state(st,SITE_SENTMSG5); - else { + } else { slog(st,LOG_SEC,"invalid MSG4"); } break; @@ -1139,6 +1229,7 @@ static bool_t site_incoming(void *sst, struct buffer_if *buf, if (st->state!=SITE_SENTMSG4) { slog(st,LOG_UNEXPECTED,"unexpected MSG5"); } else if (process_msg5(st,buf,source)) { + transport_setup_msgok(st,source); enter_new_state(st,SITE_RUN); } else { slog(st,LOG_SEC,"invalid MSG5"); @@ -1150,6 +1241,7 @@ static bool_t site_incoming(void *sst, struct buffer_if *buf, slog(st,LOG_UNEXPECTED,"unexpected MSG6"); } else if (process_msg6(st,buf,source)) { BUF_FREE(&st->buffer); /* Free message 5 */ + transport_setup_msgok(st,source); activate_new_key(st); } else { slog(st,LOG_SEC,"invalid MSG6"); @@ -1219,6 +1311,7 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context, } assert(index_sequence < 0xffffffffUL); st->index = ++index_sequence; + st->peer_mobile=dict_read_bool(dict,"mobile",False,"site",loc,False); st->netlink=find_cl_if(dict,"link",CL_NETLINK,True,"site",loc); st->comm=find_cl_if(dict,"comm",CL_COMM,True,"site",loc); st->resolver=find_cl_if(dict,"resolver",CL_RESOLVER,True,"site",loc); @@ -1246,6 +1339,17 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context, st->setup_retry_interval= CFG_NUMBER("setup-timeout", SETUP_RETRY_INTERVAL); st->wait_timeout= CFG_NUMBER("wait-time", WAIT_TIME); + st->mobile_peer_expiry= dict_read_number( + dict,"mobile-peer-expiry",False,"site",loc,DEFAULT_MOBILE_PEER_EXPIRY); + + st->transport_peers_max= !st->peer_mobile ? 1 : dict_read_number( + dict,"mobile-peers-max",False,"site",loc,DEFAULT_MOBILE_PEERS_MAX); + if (st->transport_peers_max<1 || + st->transport_peers_max>=MAX_MOBILE_PEERS_MAX) { + cfgfatal(loc,"site","mobile-peers-max must be in range 1.." + STRING(MAX_MOBILE_PEERS_MAX) "\n"); + } + if (st->key_lifetime < DEFAULT(KEY_RENEGOTIATE_GAP)*2) st->key_renegotiate_time=st->key_lifetime/2; else @@ -1286,7 +1390,8 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context, st->current_valid=False; st->current_key_timeout=0; - st->peer_valid=False; + transport_peers_clear(st,&st->peers); + transport_peers_clear(st,&st->setup_peers); /* XXX mlock these */ st->dhsecret=safe_malloc(st->dh->len,"site:dhsecret"); st->sharedsecret=safe_malloc(st->transform->keylen,"site:sharedsecret"); @@ -1313,3 +1418,150 @@ void site_module(dict_t *dict) { add_closure(dict,"site",site_apply); } + + +/***** TRANSPORT PEERS definitions *****/ + +static void transport_peers_debug(struct site *st, transport_peers *dst, + const char *didwhat, + int nargs, const struct comm_addr *args, + size_t stride) { + int i; + char *argp; + + if (!(st->log_events & LOG_PEER_ADDRS)) + return; /* an optimisation */ + + slog(st, LOG_PEER_ADDRS, "peers (%s) %s nargs=%d => npeers=%d", + (dst==&st->peers ? "data" : + dst==&st->setup_peers ? "setup" : "UNKNOWN"), + didwhat, nargs, dst->npeers); + + for (i=0, argp=(void*)args; + icomm->addr_to_string(ca->comm->st,ca)); + } + for (i=0; inpeers; i++) { + struct timeval diff; + timersub(tv_now,&dst->peers[i].last,&diff); + const struct comm_addr *ca=&dst->peers[i].addr; + slog(st, LOG_PEER_ADDRS, " peers: addrs[%d]=%s T-%ld.%06ld", + i, ca->comm->addr_to_string(ca->comm->st,ca), + (unsigned long)diff.tv_sec, (unsigned long)diff.tv_usec); + } +} + +static int transport_peer_compar(const void *av, const void *bv) { + const transport_peer *a=av; + const transport_peer *b=bv; + /* put most recent first in the array */ + if (timercmp(&a->last, &b->last, <)) return +1; + if (timercmp(&a->last, &b->last, >)) return -11; + return 0; +} + +static void transport_peers_expire(struct site *st, transport_peers *peers) { + /* peers must be sorted first */ + int previous_peers=peers->npeers; + struct timeval oldest; + oldest.tv_sec = tv_now->tv_sec - st->mobile_peer_expiry; + oldest.tv_usec = tv_now->tv_usec; + while (peers->npeers>1 && + timercmp(&peers->peers[peers->npeers-1].last, &oldest, <)) + peers->npeers--; + if (peers->npeers != previous_peers) + transport_peers_debug(st,peers,"expire", 0,0,0); +} + +static void transport_record_peer(struct site *st, transport_peers *peers, + const struct comm_addr *addr, const char *m) { + int slot, changed=0; + + for (slot=0; slotnpeers; slot++) + if (!memcmp(&peers->peers[slot].addr, addr, sizeof(*addr))) + goto found; + + changed=1; + if (peers->npeers==st->transport_peers_max) + slot=st->transport_peers_max; + else + slot=peers->npeers++; + + found: + peers->peers[slot].addr=*addr; + peers->peers[slot].last=*tv_now; + + if (peers->npeers>1) + qsort(peers->peers, peers->npeers, + sizeof(*peers->peers), transport_peer_compar); + + if (changed || peers->npeers!=1) + transport_peers_debug(st,peers,m, 1,addr,0); + transport_peers_expire(st, peers); +} + +static bool_t transport_compute_setupinit_peers(struct site *st, + const struct comm_addr *configured_addr /* 0 if none or not found */) { + + if (!configured_addr && !transport_peers_valid(&st->peers)) + return False; + + slog(st,LOG_SETUP_INIT, + (!configured_addr ? "using only %d old peer address(es)" + : "using configured address, and/or perhaps %d old peer address(es)"), + st->peers); + + /* Non-mobile peers havve st->peers.npeers==0 or ==1, since they + * have transport_peers_max==1. The effect is that this code + * always uses the configured address if supplied, or otherwise + * the existing data peer if one exists; this is as desired. */ + + transport_peers_copy(st,&st->setup_peers,&st->peers); + + if (configured_addr) + transport_record_peer(st,&st->setup_peers,configured_addr,"setupinit"); + + assert(transport_peers_valid(&st->setup_peers)); + return True; +} + +static void transport_setup_msgok(struct site *st, const struct comm_addr *a) { + if (st->peer_mobile) + transport_record_peer(st,&st->setup_peers,a,"setupmsg"); +} +static void transport_data_msgok(struct site *st, const struct comm_addr *a) { + if (st->peer_mobile) + transport_record_peer(st,&st->peers,a,"datamsg"); +} + +static int transport_peers_valid(transport_peers *peers) { + return peers->npeers; +} +static void transport_peers_clear(struct site *st, transport_peers *peers) { + peers->npeers= 0; + transport_peers_debug(st,peers,"clear",0,0,0); +} +static void transport_peers_copy(struct site *st, transport_peers *dst, + const transport_peers *src) { + dst->npeers=src->npeers; + memcpy(dst->peers, src->peers, sizeof(*dst->peers) * dst->npeers); + transport_peers_debug(st,dst,"copy", + src->npeers, &src->peers->addr, sizeof(src->peers)); +} + +void transport_xmit(struct site *st, transport_peers *peers, + struct buffer_if *buf, bool_t candebug) { + int slot; + transport_peers_expire(st, peers); + for (slot=0; slotnpeers; slot++) { + transport_peer *peer=&peers->peers[slot]; + if (candebug) + dump_packet(st, buf, &peer->addr, False); + peer->addr.comm->sendmsg(peer->addr.comm->st, buf, &peer->addr); + } +} + +/***** END of transport peers declarations *****/ -- 1.7.2.5 From ijackson at chiark.greenend.org.uk Wed Aug 17 23:54:31 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Wed, 17 Aug 2011 23:54:31 +0100 Subject: [PATCH 13/18] Mobile sites: Require specification of whether we think we are mobile In-Reply-To: <1313621676-16031-1-git-send-email-ijackson@chiark.greenend.org.uk> References: <1313621676-16031-1-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1313621676-16031-14-git-send-email-ijackson@chiark.greenend.org.uk> We introduce a new config option "local-mobile" which must match our peers' idea of whether we are mobile. This is cross-checked with the "site" entry for our own site, if there is one, to detect mistakes. We do not transfer this data in the protocol because we don't want to break compatibility with older secnets which do not understand mobile peers at all. Signed-off-by: Ian Jackson --- README | 6 ++++++ site.c | 17 ++++++++++++++++- 2 files changed, 22 insertions(+), 1 deletions(-) diff --git a/README b/README index 3736b89..7e40edf 100644 --- a/README +++ b/README @@ -322,6 +322,12 @@ site: dict argument mobile-peer-expiry (integer): For "mobile" peers only, the length of time (in seconds) for which we will keep sending to multiple address/ports from which we have not seen incoming traffic. [120] + local-mobile (bool): if True then other peers have been told we are + "mobile". This should be True iff the peers' site configurations + for us have "mobile True" (and if we find a site configuration for + ourselves in the config, we insist on this). The effect is to + check that there are no links both ends of which are allegedly + mobile (which is not supported, so those links are ignored). [false] ** transform diff --git a/site.c b/site.c index 9d09ebc..8be5523 100644 --- a/site.c +++ b/site.c @@ -1300,18 +1300,33 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context, dict=item->data.dict; st->localname=dict_read_string(dict, "local-name", True, "site", loc); st->remotename=dict_read_string(dict, "name", True, "site", loc); + + st->peer_mobile=dict_read_bool(dict,"mobile",False,"site",loc,False); + bool_t local_mobile= + dict_read_bool(dict,"local-mobile",False,"site",loc,False); + /* Sanity check (which also allows the 'sites' file to include site() closures for all sites including our own): refuse to talk to ourselves */ if (strcmp(st->localname,st->remotename)==0) { Message(M_DEBUG,"site %s: local-name==name -> ignoring this site\n", st->localname); + if (st->peer_mobile != local_mobile) + cfgfatal(loc,"site","site %s's peer-mobile=%d" + " but our local-mobile=%d\n", + st->localname, st->peer_mobile, local_mobile); + free(st); + return NULL; + } + if (st->peer_mobile && local_mobile) { + Message(M_WARNING,"site %s: site is mobile but so are we" + " -> ignoring this site\n", st->remotename); free(st); return NULL; } + assert(index_sequence < 0xffffffffUL); st->index = ++index_sequence; - st->peer_mobile=dict_read_bool(dict,"mobile",False,"site",loc,False); st->netlink=find_cl_if(dict,"link",CL_NETLINK,True,"site",loc); st->comm=find_cl_if(dict,"comm",CL_COMM,True,"site",loc); st->resolver=find_cl_if(dict,"resolver",CL_RESOLVER,True,"site",loc); -- 1.7.2.5 From ijackson at chiark.greenend.org.uk Wed Aug 17 23:54:32 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Wed, 17 Aug 2011 23:54:32 +0100 Subject: [PATCH 14/18] Mobile sites: Use different default tuning parameters In-Reply-To: <1313621676-16031-1-git-send-email-ijackson@chiark.greenend.org.uk> References: <1313621676-16031-1-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1313621676-16031-15-git-send-email-ijackson@chiark.greenend.org.uk> Links involving mobile peers are best served by somewhat different tuning parameters. So make the defaults vary accordingly. Signed-off-by: Ian Jackson --- README | 21 +++++++++++++++------ site.c | 10 +++++++++- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/README b/README index 7e40edf..96114f0 100644 --- a/README +++ b/README @@ -281,16 +281,18 @@ site: dict argument transform (transform closure): how to mangle packets sent between sites dh (dh closure) hash (hash closure) - key-lifetime (integer): max lifetime of a session key, in ms [one hour] + key-lifetime (integer): max lifetime of a session key, in ms + [one hour; mobile: 2 days] setup-retries (integer): max number of times to transmit a key negotiation - packet [5] + packet [5; mobile: 30] setup-timeout (integer): time between retransmissions of key negotiation - packets, in ms [2000] + packets, in ms [2000; mobile: 1000] wait-time (integer): after failed key setup, wait this long (in ms) before - allowing another attempt [20000] + allowing another attempt [20000; mobile: 10000] renegotiate-time (integer): if we see traffic on the link after this time then renegotiate another session key immediately (in ms) - [half key-lifetime, or key-lifetime minus 5 mins, whichever is longer]. + [half key-lifetime, or key-lifetime minus 5 mins (mobile: 12 hours), + whichever is longer]. keepalive (bool): if True then attempt always to keep a valid session key. Not actually currently implemented. [false] log-events (string list): types of events to log for this site @@ -327,7 +329,14 @@ site: dict argument for us have "mobile True" (and if we find a site configuration for ourselves in the config, we insist on this). The effect is to check that there are no links both ends of which are allegedly - mobile (which is not supported, so those links are ignored). [false] + mobile (which is not supported, so those links are ignored) and + to change some of the tuning parameter defaults. [false] + +Links involving mobile peers have some different tuning parameter +default values, which are generally more aggressive about retrying key +setup but more relaxed about using old keys. These are noted with +"mobile:", above, and apply whether the mobile peer is local or +remote. ** transform diff --git a/site.c b/site.c index 8be5523..ed9e803 100644 --- a/site.c +++ b/site.c @@ -32,6 +32,13 @@ #define DEFAULT_SETUP_RETRIES 5 #define DEFAULT_SETUP_RETRY_INTERVAL (2*1000) /* [ms] */ #define DEFAULT_WAIT_TIME (20*1000) /* [ms] */ + +#define DEFAULT_MOBILE_KEY_LIFETIME (2*24*3600*1000) /* [ms] */ +#define DEFAULT_MOBILE_KEY_RENEGOTIATE_GAP (12*3600*1000) /* [ms] */ +#define DEFAULT_MOBILE_SETUP_RETRIES 30 +#define DEFAULT_MOBILE_SETUP_RETRY_INTERVAL (1*1000) /* [ms] */ +#define DEFAULT_MOBILE_WAIT_TIME (10*1000) /* [ms] */ + #define DEFAULT_MOBILE_PEER_EXPIRY (2*60) /* [s] */ #define DEFAULT_MOBILE_PEERS_MAX 3 /* send at most this many copies (default) */ @@ -1346,7 +1353,8 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context, st->dh=find_cl_if(dict,"dh",CL_DH,True,"site",loc); st->hash=find_cl_if(dict,"hash",CL_HASH,True,"site",loc); -#define DEFAULT(D) DEFAULT_##D +#define DEFAULT(D) (st->peer_mobile || local_mobile \ + ? DEFAULT_MOBILE_##D : DEFAULT_##D) #define CFG_NUMBER(k,D) dict_read_number(dict,(k),False,"site",loc,DEFAULT(D)); st->key_lifetime= CFG_NUMBER("key-lifetime", KEY_LIFETIME); -- 1.7.2.5 From ijackson at chiark.greenend.org.uk Wed Aug 17 23:54:33 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Wed, 17 Aug 2011 23:54:33 +0100 Subject: [PATCH 15/18] Mobile sites: Support in make-secnet-sites In-Reply-To: <1313621676-16031-1-git-send-email-ijackson@chiark.greenend.org.uk> References: <1313621676-16031-1-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1313621676-16031-16-git-send-email-ijackson@chiark.greenend.org.uk> This allows a sites file to specify that a site is mobile; the mobile flag gets propagated into the generated sites.conf. Includes new support for boolean values. Signed-off-by: Ian Jackson --- make-secnet-sites | 15 +++++++++++++++ 1 files changed, 15 insertions(+), 0 deletions(-) diff --git a/make-secnet-sites b/make-secnet-sites index 403782b..4c6f0f4 100755 --- a/make-secnet-sites +++ b/make-secnet-sites @@ -54,6 +54,7 @@ import time import sys import os import getopt +import re # The ipaddr library is installed as part of secnet sys.path.append("/usr/local/share/secnet") @@ -108,6 +109,18 @@ class email: def __str__(self): return '<%s>'%(self.addr) +class boolean: + "A boolean" + def __init__(self,w): + if re.match('[TtYy1]',w[1]): + self.b=True + elif re.match('[FfNn0]',w[1]): + self.b=False + else: + complain("invalid boolean value"); + def __str__(self): + return ['False','True'][self.b] + class num: "A decimal number" def __init__(self,w): @@ -149,6 +162,7 @@ keywords={ 'pubkey':(rsakey,"RSA public site key"), 'peer':(single_ipaddr,"Tunnel peer IP address"), 'address':(address,"External contact address and port"), + 'mobile':(boolean,"Site is mobile"), } def sp(name,value): @@ -253,6 +267,7 @@ class sitelevel(level): 'networks':None, 'peer':None, 'pubkey':(lambda n,v:"key %s;\n"%v), + 'mobile':sp, }) require_properties={ 'dh':"Diffie-Hellman group", -- 1.7.2.5 From ijackson at chiark.greenend.org.uk Wed Aug 17 23:54:34 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Wed, 17 Aug 2011 23:54:34 +0100 Subject: [PATCH 16/18] Multiple udp ports for the same site (multiple "comm"s) In-Reply-To: <1313621676-16031-1-git-send-email-ijackson@chiark.greenend.org.uk> References: <1313621676-16031-1-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1313621676-16031-17-git-send-email-ijackson@chiark.greenend.org.uk> Now you can meaningfully specify more than one comm closure (ie, more than one udp port) for a site. secnet will respond to incoming key exchange and data packets on any of the ports. Signed-off-by: Ian Jackson --- README | 5 ++++- site.c | 39 +++++++++++++++++++++++++++++++++------ 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/README b/README index 96114f0..1901223 100644 --- a/README +++ b/README @@ -270,7 +270,10 @@ site: dict argument local-name (string): this site's name for itself name (string): the name of the site's peer link (netlink closure) - comm (comm closure) + comm (one or more comm closures): if there is more than one, the + first one will be used for any key setups initiated by us using the + configured address. Others are only used if our peer talks to + them. resolver (resolver closure) random (randomsrc closure) local-key (rsaprivkey closure) diff --git a/site.c b/site.c index ed9e803..624752c 100644 --- a/site.c +++ b/site.c @@ -226,7 +226,8 @@ struct site { string_t address; /* DNS name for bootstrapping, optional */ int remoteport; /* Port for bootstrapping, optional */ struct netlink_if *netlink; - struct comm_if *comm; + struct comm_if **comms; + int ncomms; struct resolver_if *resolver; struct log_if *log; struct random_if *random; @@ -803,7 +804,7 @@ static void site_resolve_callback(void *sst, struct in_addr *address) } if (address) { FILLZERO(ca_buf); - ca_buf.comm=st->comm; + ca_buf.comm=st->comms[0]; ca_buf.sin.sin_family=AF_INET; ca_buf.sin.sin_port=htons(st->remoteport); ca_buf.sin.sin_addr=*address; @@ -1288,6 +1289,7 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context, struct site *st; item_t *item; dict_t *dict; + int i; st=safe_malloc(sizeof(*st),"site_apply"); @@ -1335,7 +1337,20 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context, assert(index_sequence < 0xffffffffUL); st->index = ++index_sequence; st->netlink=find_cl_if(dict,"link",CL_NETLINK,True,"site",loc); - st->comm=find_cl_if(dict,"comm",CL_COMM,True,"site",loc); + + list_t *comms_cfg=dict_lookup(dict,"comm"); + if (!comms_cfg) cfgfatal(loc,"site","closure list \"comm\" not found"); + st->ncomms=list_length(comms_cfg); + st->comms=safe_malloc_ary(sizeof(*st->comms),st->ncomms,"comms"); + assert(st->ncomms); + for (i=0; incomms; i++) { + item_t *item=list_elem(comms_cfg,i); + if (item->type!=t_closure) cfgfatal(loc,"site","comm is not a closure"); + closure_t *cl=item->data.closure; + if (cl->type!=CL_COMM) cfgfatal(loc,"site","comm closure wrong type"); + st->comms[i]=cl->interface; + } + st->resolver=find_cl_if(dict,"resolver",CL_RESOLVER,True,"site",loc); st->log=find_cl_if(dict,"log",CL_LOG,True,"site",loc); st->random=find_cl_if(dict,"random",CL_RANDOMSRC,True,"site",loc); @@ -1419,13 +1434,25 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context, st->dhsecret=safe_malloc(st->dh->len,"site:dhsecret"); st->sharedsecret=safe_malloc(st->transform->keylen,"site:sharedsecret"); + /* We need to compute some properties of our comms */ +#define COMPUTE_WORST(pad) \ + int worst_##pad=0; \ + for (i=0; incomms; i++) { \ + int thispad=st->comms[i]->pad; \ + if (thispad > worst_##pad) \ + worst_##pad=thispad; \ + } + COMPUTE_WORST(min_start_pad) + COMPUTE_WORST(min_end_pad) + /* We need to register the remote networks with the netlink device */ st->netlink->reg(st->netlink->st, site_outgoing, st, st->transform->max_start_pad+(4*4)+ - st->comm->min_start_pad, - st->transform->max_end_pad+st->comm->min_end_pad); + worst_min_start_pad, + st->transform->max_end_pad+worst_min_end_pad); - st->comm->request_notify(st->comm->st, st, site_incoming); + for (i=0; incomms; i++) + st->comms[i]->request_notify(st->comms[i]->st, st, site_incoming); st->current_transform=st->transform->create(st->transform->st); st->new_transform=st->transform->create(st->transform->st); -- 1.7.2.5 From ijackson at chiark.greenend.org.uk Wed Aug 17 23:54:35 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Wed, 17 Aug 2011 23:54:35 +0100 Subject: [PATCH 17/18] Multiple udp ports: Add to test In-Reply-To: <1313621676-16031-1-git-send-email-ijackson@chiark.greenend.org.uk> References: <1313621676-16031-1-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1313621676-16031-18-git-send-email-ijackson@chiark.greenend.org.uk> For testing, add an extra port to one of the sites in test-example. Signed-off-by: Ian Jackson --- test-example/inside.conf | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/test-example/inside.conf b/test-example/inside.conf index 4d41f30..49f2b1c 100644 --- a/test-example/inside.conf +++ b/test-example/inside.conf @@ -8,6 +8,9 @@ netlink tun { interface "secnet-test-i"; }; comm udp { + port 16913; + buffer sysbuffer(4096); +}, udp { port 16910; buffer sysbuffer(4096); }; -- 1.7.2.5 From ijackson at chiark.greenend.org.uk Wed Aug 17 23:54:36 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Wed, 17 Aug 2011 23:54:36 +0100 Subject: [PATCH 18/18] Mobile sites: Update test example In-Reply-To: <1313621676-16031-1-git-send-email-ijackson@chiark.greenend.org.uk> References: <1313621676-16031-1-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1313621676-16031-19-git-send-email-ijackson@chiark.greenend.org.uk> Make the "inside" site in test-example be mobile. Signed-off-by: Ian Jackson --- test-example/inside.conf | 1 + test-example/sites | 1 + 2 files changed, 2 insertions(+), 0 deletions(-) diff --git a/test-example/inside.conf b/test-example/inside.conf index 49f2b1c..a64f125 100644 --- a/test-example/inside.conf +++ b/test-example/inside.conf @@ -16,4 +16,5 @@ comm udp { }; local-name "test-example/inside/inside"; local-key rsa-private("test-example/inside.key"); +local-mobile True; include test-example/common.conf diff --git a/test-example/sites b/test-example/sites index 470357b..648819b 100644 --- a/test-example/sites +++ b/test-example/sites @@ -19,4 +19,5 @@ site inside networks 172.18.232.8/29 peer 172.18.232.9 address [127.0.0.1] 16910 + mobile True pubkey 1024 65537 130064631890186713927887504218626486455931306300999583387009075747001546036643522074275473238061323169592347601185592753550279410171535737146240085267000508853176463710554801101055212967131924064664249613912656320653505750073021702169423354903540699008756137338575553686987244488914481168225136440872431691669 inside at example.com -- 1.7.2.5 From ijackson at chiark.greenend.org.uk Wed Aug 24 18:20:45 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Wed, 24 Aug 2011 18:20:45 +0100 Subject: [PATCH v2 00/18] Mobile sites, multiple udp ports, cleanups, etc. In-Reply-To: <1313621676-16031-1-git-send-email-ijackson@chiark.greenend.org.uk> References: <1313621676-16031-1-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <20053.13037.177343.564602@chiark.greenend.org.uk> Ian Jackson writes ("[PATCH v2 00/18] Mobile sites, multiple udp ports, cleanups, etc."): > But partly this depends on who we are making a release for. So far > I've had one enquiry, and it's not clear to me whether that user would > benefit from the new features. I've asked them to post here with > their opinion. I spoke to Jon Amery on IRC: 18:02 Senji: You were going to have an opinion about what should be in the secnet release. 18:03 Yes. I should turn the amorphous mass in my head into an opinion. 18:06 Personally I would like the whole lot to go in because then I could use the new release for zealot. 18:07 We could make two releases but the only point of that would be if someone were promising to do backports of important fixes. 18:07 As a 5c summary I think all the mobile and even ip-over-dns stuff would be really handy for me, but I've managed without them before. 18:07 The IP-over-DNS stuff isn't even a half-written proof-of-concept at this stage. 18:08 OK well if they would be handy for you then I guess that means we should include them. 18:13 IWBNI someone other than just me had read them though :-) I think the conclusion of that is that we should push my series to master, and call the result a release candidate. 0.2.0~rc1 or 1.0.0~rc1 ? Ian. From rjk at terraraq.org.uk Sat Dec 10 13:07:17 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Sat, 10 Dec 2011 13:07:17 +0000 Subject: [PATCH 3/3] New --managed option for use when running under a daemon supervisor. In-Reply-To: <20026.43862.211587.311898@chiark.greenend.org.uk> References: <1311413540-6378-1-git-send-email-rjk@terraraq.org.uk> <1311413540-6378-2-git-send-email-rjk@terraraq.org.uk> <1311413540-6378-3-git-send-email-rjk@terraraq.org.uk> <1311413540-6378-4-git-send-email-rjk@terraraq.org.uk> <20026.43862.211587.311898@chiark.greenend.org.uk> Message-ID: <4EE35985.1050603@terraraq.org.uk> On 04/08/2011 15:23, Ian Jackson wrote: > Richard Kettlewell writes ("[PATCH 3/3] New --managed option for use when running under a daemon supervisor."): >> - if (secnet_is_daemon) { >> + if (secnet_is_daemon&& system_log) { > > This is an unrelated bugfix, isn't it ? > > The rest of this patch seems like a good plan from the description > although I confess that from reading the patch I wasn't able to review > it for correctness. Have you tested each combination of modes now > supported ? I need to spend some more time thinking about this one. Apart from that I've pushed everything I've got. ttfn/rjk From rjk at terraraq.org.uk Sat Dec 10 15:28:34 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Sat, 10 Dec 2011 15:28:34 +0000 Subject: secnet and clang Message-ID: <4EE37AA2.80204@terraraq.org.uk> I've fed secnet through Clang and its static analyzer. First, just the compiler: It complained about a bunch of unused function arguments. I have a patch to fix this. It also found an error in md5.c. I have a patch for this too. And the analyser: The results can be found at: http://deodand.anjou.terraraq.org.uk/~richard/secnet.scan/ The sha1.c dead assignments are attempts to clear possibly-sensitive values from RAM and of course are ineffective with post-neolithic compilers. Actually both GCC and Clang have those variables in registers at that point anyway, even in 32-bit builds, so they'd be extra-pointless even if not optimized out. The conffile.tab.c assignments might be less dead with other configurations of the Bison macro soup. conffile.yy.c:1387, 1535. False positives as far as I can see - yy_ensure_buffer_stack fatals if the allocation fails, so the analyzer's initial assumption should never be true. conffile.yy.c:1508 etc. The original code in conffile.y looks OK to me. Either the analyser's reasoning is defective (the explanations at 1366-69 seem rather suspect) or there is a bug in Bison. conffile.yy.c:556. False positive, the operation would not be idempotent on an LP64 platform. conffile.yy.c:1577, 1582. True but uninteresting. ttfn/rjk From rjk at terraraq.org.uk Sat Dec 10 17:08:29 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Sat, 10 Dec 2011 17:08:29 +0000 Subject: [PATCH 3/3] New --managed option for use when running under a daemon supervisor. In-Reply-To: <20026.43862.211587.311898@chiark.greenend.org.uk> References: <1311413540-6378-1-git-send-email-rjk@terraraq.org.uk> <1311413540-6378-2-git-send-email-rjk@terraraq.org.uk> <1311413540-6378-3-git-send-email-rjk@terraraq.org.uk> <1311413540-6378-4-git-send-email-rjk@terraraq.org.uk> <20026.43862.211587.311898@chiark.greenend.org.uk> Message-ID: <4EE3920D.2010909@terraraq.org.uk> On 04/08/2011 15:23, Ian Jackson wrote: > Richard Kettlewell writes ("[PATCH 3/3] New --managed option for use when running under a daemon supervisor."): >> - if (secnet_is_daemon) { >> + if (secnet_is_daemon&& system_log) { > > This is an unrelated bugfix, isn't it ? It was arguably a conceptual confusion that secnet_is_daemon is conflated with system_log having been created, but in the code as it previously stood the sequencing meant that secnet_is_daemon!=0 implied system_log has been created, so it would never go wrong in practice. I don't believe it makes sense to break it out into a separate commit. Actually I think it should simply be: if(system_log) ttfn/rjk From rjk at terraraq.org.uk Sun Dec 11 21:38:16 2011 From: rjk at terraraq.org.uk (Richard Kettlewell) Date: Sun, 11 Dec 2011 21:38:16 +0000 Subject: [PATCH 2/3] Config file fixes. In-Reply-To: <20026.43445.798879.210034@chiark.greenend.org.uk> References: <1311413540-6378-1-git-send-email-rjk@terraraq.org.uk> <1311413540-6378-2-git-send-email-rjk@terraraq.org.uk> <1311413540-6378-3-git-send-email-rjk@terraraq.org.uk> <20026.43445.798879.210034@chiark.greenend.org.uk> Message-ID: <4EE522C8.3040303@terraraq.org.uk> On 04/08/2011 15:16, Ian Jackson wrote: > Richard Kettlewell writes ("[PATCH 2/3] Config file fixes."): >> /* Convert a node type to a string, for parse tree dump */ >> -static string_t ntype(uint32_t type) >> +static const char *ntype(uint32_t type) > > We seem to be gradually abolishing [c]string_t. Perhaps we should do > so globally ? (Says the guy with a huge outstanding patch serieses...) I have a change for this, it will be in the next patchbomb (or it can be found in github). ttfn/rjk From ijackson at chiark.greenend.org.uk Thu Dec 15 13:45:37 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Thu, 15 Dec 2011 13:45:37 +0000 Subject: [PATCH 0/3] Improvements to mobile sites and sites file Message-ID: <1323956740-14914-1-git-send-email-ijackson@chiark.greenend.org.uk> I tried to switch the vpn on my netbook, zealot, from udptunnel to secnet. However, I encountered two problems: * The setup on the chiark end was unnecessarily complicated. I think the best way to fix this involves provide an "include" facility for sites files. * A bug prevents secnet, when used with userv-ipif, creating routes for mobile sites. From ijackson at chiark.greenend.org.uk Thu Dec 15 13:45:39 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Thu, 15 Dec 2011 13:45:39 +0000 Subject: [PATCH 2/3] make-secnet-sites: new "include" keyword In-Reply-To: <1323956740-14914-1-git-send-email-ijackson@chiark.greenend.org.uk> References: <1323956740-14914-1-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1323956740-14914-3-git-send-email-ijackson@chiark.greenend.org.uk> Allow "headers" files and "sites" files to contain "include" directives. Signed-off-by: Ian Jackson --- make-secnet-sites | 22 +++++++++++++++------- 1 files changed, 15 insertions(+), 7 deletions(-) diff --git a/make-secnet-sites b/make-secnet-sites index f102b1f..fe58bde 100755 --- a/make-secnet-sites +++ b/make-secnet-sites @@ -329,7 +329,7 @@ def set_property(obj,w): else: obj.properties[w[0]]=keywords[w[0]][0](w) -def pline(i): +def pline(i,allow_include=False): "Process a configuration file line" global allow_defs, obstack, root w=string.split(i) @@ -340,6 +340,14 @@ def pline(i): allow_defs=sitelevel.depth obstack=[root] return + if keyword=='include': + if not allow_include: + complain("include not permitted here") + return + if len(w) != 2: + complain("include requires one argument") + pfilepath(w[1],allow_include=allow_include) + return if levels.has_key(keyword): # We may go up any number of levels, but only down by one newdepth=levels[keyword].depth @@ -379,12 +387,12 @@ def pline(i): complain("unknown keyword '%s'"%(keyword)) -def pfilepath(pathname): +def pfilepath(pathname,allow_include=False): f=open(pathname) - pfile(pathname,f.readlines()) + pfile(pathname,f.readlines(),allow_include=allow_include) f.close() -def pfile(name,lines): +def pfile(name,lines,allow_include=False): "Process a file" global file,line file=name @@ -393,7 +401,7 @@ def pfile(name,lines): line=line+1 if (i[0]=='#'): continue if (i[len(i)-1]=='\n'): i=i[:len(i)-1] # strip trailing LF - pline(i) + pline(i,allow_include=allow_include) def outputsites(w): "Output include file for secnet configuration" @@ -455,14 +463,14 @@ else: if not ok: print "caller not in group %s"%group sys.exit(1) - pfilepath(header) + pfilepath(header,allow_include=True) userinput=sys.stdin.readlines() pfile("user input",userinput) else: if len(sys.argv)>3: print "Too many arguments" sys.exit(1) - pfilepath(sys.argv[1]) + pfilepath(sys.argv[1],allow_include=True) of=sys.stdout if len(sys.argv)>2: of=open(sys.argv[2],'w') -- 1.5.6.5 From ijackson at chiark.greenend.org.uk Thu Dec 15 13:45:38 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Thu, 15 Dec 2011 13:45:38 +0000 Subject: [PATCH 1/3] make-secnet-sites: refactor to break out new function "pfilepath" In-Reply-To: <1323956740-14914-1-git-send-email-ijackson@chiark.greenend.org.uk> References: <1323956740-14914-1-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1323956740-14914-2-git-send-email-ijackson@chiark.greenend.org.uk> No intentional functional change. Signed-off-by: Ian Jackson --- make-secnet-sites | 14 +++++++------- 1 files changed, 7 insertions(+), 7 deletions(-) diff --git a/make-secnet-sites b/make-secnet-sites index 4c6f0f4..f102b1f 100755 --- a/make-secnet-sites +++ b/make-secnet-sites @@ -379,6 +379,11 @@ def pline(i): complain("unknown keyword '%s'"%(keyword)) +def pfilepath(pathname): + f=open(pathname) + pfile(pathname,f.readlines()) + f.close() + def pfile(name,lines): "Process a file" global file,line @@ -450,19 +455,14 @@ else: if not ok: print "caller not in group %s"%group sys.exit(1) - f=open(header) - headerinput=f.readlines() - f.close() - pfile(header,headerinput) + pfilepath(header) userinput=sys.stdin.readlines() pfile("user input",userinput) else: if len(sys.argv)>3: print "Too many arguments" sys.exit(1) - f=open(sys.argv[1]) - pfile(sys.argv[1],f.readlines()) - f.close() + pfilepath(sys.argv[1]) of=sys.stdout if len(sys.argv)>2: of=open(sys.argv[2],'w') -- 1.5.6.5 From ijackson at chiark.greenend.org.uk Thu Dec 15 13:45:40 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Thu, 15 Dec 2011 13:45:40 +0000 Subject: [PATCH 3/3] userv-ipif: Always request routes from userv, regardless of link quality In-Reply-To: <1323956740-14914-1-git-send-email-ijackson@chiark.greenend.org.uk> References: <1323956740-14914-1-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1323956740-14914-4-git-send-email-ijackson@chiark.greenend.org.uk> Previously the userv-ipif netlink would not request (from userv) a route for a site for which the link quality was DOWN. The link quality is a dynamic quantity but userv-ipif lacks any machinery for dynamically adding routes, so this is wrong. Instead, in userv-ipif, unconditionally add routes for all sites, regardless of link up status. In practice this code is run during startup and the only reason a link might be down at that point, ie LINK_QUALITY_DOWN, is that it does not have an address configured. Mobile sites are often in this situation. Signed-off-by: Ian Jackson --- slip.c | 12 +++++------- 1 files changed, 5 insertions(+), 7 deletions(-) diff --git a/slip.c b/slip.c index a296e42..7c138d1 100644 --- a/slip.c +++ b/slip.c @@ -257,13 +257,11 @@ static void userv_invoke_userv(struct userv *st) allnets=ipset_new(); for (r=st->slip.nl.clients; r; r=r->next) { - if (r->up) { - struct ipset *nan; - r->kup=True; - nan=ipset_union(allnets,r->networks); - ipset_free(allnets); - allnets=nan; - } + struct ipset *nan; + r->kup=True; + nan=ipset_union(allnets,r->networks); + ipset_free(allnets); + allnets=nan; } snets=ipset_to_subnet_list(allnets); ipset_free(allnets); -- 1.5.6.5 From rjk at greenend.org.uk Thu Dec 15 21:46:13 2011 From: rjk at greenend.org.uk (Richard Kettlewell) Date: Thu, 15 Dec 2011 21:46:13 +0000 Subject: [PATCH 0/3] Improvements to mobile sites and sites file In-Reply-To: <1323956740-14914-1-git-send-email-ijackson@chiark.greenend.org.uk> References: <1323956740-14914-1-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <4EEA6AA5.4040701@greenend.org.uk> On 15/12/2011 13:45, Ian Jackson wrote: > I tried to switch the vpn on my netbook, zealot, from udptunnel to > secnet. However, I encountered two problems: > > * The setup on the chiark end was unnecessarily complicated. I think > the best way to fix this involves provide an "include" facility for > sites files. > > * A bug prevents secnet, when used with userv-ipif, creating routes > for mobile sites. All looks OK to me. Tangential thoughts for the future: * We should document make-secnet-sites. * It might worth thinking about the minimum Python version to target. 2.5 seems like a practical choice since it's lenny's default; squeeze defaults to 2.6 but has 2.5 available which makes testing possible even without lenny. Snow Leopard (previous OSX release) matches squeeze. ttfn/rjk From ijackson at chiark.greenend.org.uk Fri Dec 16 15:59:18 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Fri, 16 Dec 2011 15:59:18 +0000 Subject: [PATCH 2/3] make-secnet-sites: new "include" keyword In-Reply-To: <1323956740-14914-3-git-send-email-ijackson@chiark.greenend.org.uk> References: <1323956740-14914-1-git-send-email-ijackson@chiark.greenend.org.uk> <1323956740-14914-3-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <20203.27350.633999.519698@chiark.greenend.org.uk> Ian Jackson writes ("[PATCH 2/3] make-secnet-sites: new "include" keyword"): > Allow "headers" files and "sites" files to contain "include" > directives. This had a misfeature which ought to be fixed: relative pathnames were resolved relative to make-secnet-sites's working directory, rather than relativity to the file containing the "include" directive. Also it was missing a return after the complain about the wrong number of arguments to "include". So here is v2. commit c4497addc3984dca4f1d3e77f3d49eaf5c00077a Author: Ian Jackson Date: Thu Dec 15 01:01:38 2011 +0000 make-secnet-sites: new "include" keyword Allow "headers" files and "sites" files to contain "include" directives. Signed-off-by: Ian Jackson diff --git a/make-secnet-sites b/make-secnet-sites index f102b1f..547f572 100755 --- a/make-secnet-sites +++ b/make-secnet-sites @@ -329,7 +329,7 @@ def set_property(obj,w): else: obj.properties[w[0]]=keywords[w[0]][0](w) -def pline(i): +def pline(i,allow_include=False): "Process a configuration file line" global allow_defs, obstack, root w=string.split(i) @@ -340,6 +340,16 @@ def pline(i): allow_defs=sitelevel.depth obstack=[root] return + if keyword=='include': + if not allow_include: + complain("include not permitted here") + return + if len(w) != 2: + complain("include requires one argument") + return + newfile=os.path.join(os.path.dirname(file),w[1]) + pfilepath(newfile,allow_include=allow_include) + return if levels.has_key(keyword): # We may go up any number of levels, but only down by one newdepth=levels[keyword].depth @@ -379,12 +389,12 @@ def pline(i): complain("unknown keyword '%s'"%(keyword)) -def pfilepath(pathname): +def pfilepath(pathname,allow_include=False): f=open(pathname) - pfile(pathname,f.readlines()) + pfile(pathname,f.readlines(),allow_include=allow_include) f.close() -def pfile(name,lines): +def pfile(name,lines,allow_include=False): "Process a file" global file,line file=name @@ -393,7 +403,7 @@ def pfile(name,lines): line=line+1 if (i[0]=='#'): continue if (i[len(i)-1]=='\n'): i=i[:len(i)-1] # strip trailing LF - pline(i) + pline(i,allow_include=allow_include) def outputsites(w): "Output include file for secnet configuration" @@ -455,14 +465,14 @@ else: if not ok: print "caller not in group %s"%group sys.exit(1) - pfilepath(header) + pfilepath(header,allow_include=True) userinput=sys.stdin.readlines() pfile("user input",userinput) else: if len(sys.argv)>3: print "Too many arguments" sys.exit(1) - pfilepath(sys.argv[1]) + pfilepath(sys.argv[1],allow_include=True) of=sys.stdout if len(sys.argv)>2: of=open(sys.argv[2],'w') From ijackson at chiark.greenend.org.uk Fri Dec 16 16:01:47 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Fri, 16 Dec 2011 16:01:47 +0000 Subject: [PATCH 0/3] Improvements to mobile sites and sites file In-Reply-To: <4EEA6AA5.4040701@greenend.org.uk> References: <1323956740-14914-1-git-send-email-ijackson@chiark.greenend.org.uk> <4EEA6AA5.4040701@greenend.org.uk> Message-ID: <20203.27499.154873.91870@chiark.greenend.org.uk> Richard Kettlewell writes ("Re: [PATCH 0/3] Improvements to mobile sites and sites file"): > On 15/12/2011 13:45, Ian Jackson wrote: > > I tried to switch the vpn on my netbook, zealot, from udptunnel to > > secnet. However, I encountered two problems: > > > > * The setup on the chiark end was unnecessarily complicated. I think > > the best way to fix this involves provide an "include" facility for > > sites files. > > > > * A bug prevents secnet, when used with userv-ipif, creating routes > > for mobile sites. > > All looks OK to me. Thanks for the review. I'll do a bit more double-checking but probably push and deploy the results soon. > Tangential thoughts for the future: > > * We should document make-secnet-sites. Yes. > * It might worth thinking about the minimum Python version > to target. 2.5 seems like a practical choice since it's > lenny's default; squeeze defaults to 2.6 but has 2.5 > available which makes testing possible even without lenny. > Snow Leopard (previous OSX release) matches squeeze. Would we really benefit much from features in newer Pythons ? Ian. From rjk at greenend.org.uk Sat Dec 17 13:19:49 2011 From: rjk at greenend.org.uk (Richard Kettlewell) Date: Sat, 17 Dec 2011 13:19:49 +0000 Subject: [PATCH 0/3] Improvements to mobile sites and sites file In-Reply-To: <20203.27499.154873.91870@chiark.greenend.org.uk> References: <1323956740-14914-1-git-send-email-ijackson@chiark.greenend.org.uk> <4EEA6AA5.4040701@greenend.org.uk> <20203.27499.154873.91870@chiark.greenend.org.uk> Message-ID: <4EEC96F5.6030404@greenend.org.uk> On 16/12/2011 16:01, Ian Jackson wrote: > Richard Kettlewell writes ("Re: [PATCH 0/3] Improvements to mobile sites and sites file"): >> * It might worth thinking about the minimum Python version >> to target. 2.5 seems like a practical choice since it's >> lenny's default; squeeze defaults to 2.6 but has 2.5 >> available which makes testing possible even without lenny. >> Snow Leopard (previous OSX release) matches squeeze. > > Would we really benefit much from features in newer Pythons ? The point is to know what to test against so one can discover if one has unknowingly used a too-new feature. ttfn/rjk From ijackson at chiark.greenend.org.uk Sat Dec 17 22:03:12 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Sat, 17 Dec 2011 22:03:12 +0000 Subject: [PATCH 0/5] Fixes for recent breakage, make mobile work Message-ID: <1324159397-28439-1-git-send-email-ijackson@chiark.greenend.org.uk> Some of my recent changes turned out not to work very well. Also, some other changes were needed to get the mobile sites functionality working properly, and to be able to split out on chiark configuration for "unusual" sites. Signed-off-by: Ian Jackson From ijackson at chiark.greenend.org.uk Sat Dec 17 22:03:13 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Sat, 17 Dec 2011 22:03:13 +0000 Subject: [PATCH 1/5] netlink: Fix up link down behaviour In-Reply-To: <1324159397-28439-1-git-send-email-ijackson@chiark.greenend.org.uk> References: <1324159397-28439-1-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1324159397-28439-2-git-send-email-ijackson@chiark.greenend.org.uk> Partially reverts 04f92904ea6c41517ff7154910c16ef4c3bc646b "userv-ipif: Always request routes from userv, regardless of link quality" It turns out that this check is necessary to avoid bringing up a route for a "netlink" stanza in the configuration file which is never used. In particular, this avoids bringing up a netlink for (a) sites which are not mentioned in the config file (b) the site on which secnet is running. Signed-off-by: Ian Jackson --- netlink.c | 2 +- secnet.h | 9 +++++---- slip.c | 12 +++++++----- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/netlink.c b/netlink.c index 5226ad1..df51d9c 100644 --- a/netlink.c +++ b/netlink.c @@ -909,7 +909,7 @@ static closure_t *netlink_inst_create(struct netlink *st, c->deliver=NULL; c->dst=NULL; c->name=name; - c->link_quality=LINK_QUALITY_DOWN; + c->link_quality=LINK_QUALITY_UNUSED; c->mtu=mtu?mtu:st->mtu; c->options=options; c->outcount=0; diff --git a/secnet.h b/secnet.h index 06beb05..ecbb995 100644 --- a/secnet.h +++ b/secnet.h @@ -420,10 +420,11 @@ struct transform_if { typedef void netlink_deliver_fn(void *st, struct buffer_if *buf); /* site code can tell netlink when outgoing packets will be dropped, so netlink can generate appropriate ICMP and make routing decisions */ -#define LINK_QUALITY_DOWN 0 /* No chance of a packet being delivered */ -#define LINK_QUALITY_DOWN_STALE_ADDRESS 1 /* Link down, old address information */ -#define LINK_QUALITY_DOWN_CURRENT_ADDRESS 2 /* Link down, current address information */ -#define LINK_QUALITY_UP 3 /* Link active */ +#define LINK_QUALITY_UNUSED 0 /* This link is unused, do not make this netlink */ +#define LINK_QUALITY_DOWN 1 /* No chance of a packet being delivered right away*/ +#define LINK_QUALITY_DOWN_STALE_ADDRESS 2 /* Link down, old address information */ +#define LINK_QUALITY_DOWN_CURRENT_ADDRESS 3 /* Link down, current address information */ +#define LINK_QUALITY_UP 4 /* Link active */ #define MAXIMUM_LINK_QUALITY 3 typedef void netlink_link_quality_fn(void *st, uint32_t quality); typedef void netlink_register_fn(void *st, netlink_deliver_fn *deliver, diff --git a/slip.c b/slip.c index 7c138d1..db89a27 100644 --- a/slip.c +++ b/slip.c @@ -257,11 +257,13 @@ static void userv_invoke_userv(struct userv *st) allnets=ipset_new(); for (r=st->slip.nl.clients; r; r=r->next) { - struct ipset *nan; - r->kup=True; - nan=ipset_union(allnets,r->networks); - ipset_free(allnets); - allnets=nan; + if (r->link_quality > LINK_QUALITY_UNUSED) { + struct ipset *nan; + r->kup=True; + nan=ipset_union(allnets,r->networks); + ipset_free(allnets); + allnets=nan; + } } snets=ipset_to_subnet_list(allnets); ipset_free(allnets); -- 1.5.6.5 From ijackson at chiark.greenend.org.uk Sat Dec 17 22:03:14 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Sat, 17 Dec 2011 22:03:14 +0000 Subject: [PATCH 2/5] make-secnet-sites: Fix userv invocation after pfilepath In-Reply-To: <1324159397-28439-1-git-send-email-ijackson@chiark.greenend.org.uk> References: <1324159397-28439-1-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1324159397-28439-3-git-send-email-ijackson@chiark.greenend.org.uk> The commit 9b8369e07aeba5ed2c69fb4a7f74d07c8cebe015 make-secnet-sites: refactor to break out new function "pfilepath" broke the userv service invocation, because it turned out that later code depended on the "headerlines" variable whose assignment had been removed and replaced by a call to pfilepath. Make pfilepath return the lines read from the file and assign the result to headerlines. Signed-off-by: Ian Jackson --- make-secnet-sites | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-) diff --git a/make-secnet-sites b/make-secnet-sites index 547f572..5911a39 100755 --- a/make-secnet-sites +++ b/make-secnet-sites @@ -391,8 +391,10 @@ def pline(i,allow_include=False): def pfilepath(pathname,allow_include=False): f=open(pathname) - pfile(pathname,f.readlines(),allow_include=allow_include) + lines=f.readlines() + pfile(pathname,lines,allow_include=allow_include) f.close() + return lines def pfile(name,lines,allow_include=False): "Process a file" @@ -465,7 +467,7 @@ else: if not ok: print "caller not in group %s"%group sys.exit(1) - pfilepath(header,allow_include=True) + headerinput=pfilepath(header,allow_include=True) userinput=sys.stdin.readlines() pfile("user input",userinput) else: -- 1.5.6.5 From ijackson at chiark.greenend.org.uk Sat Dec 17 22:03:15 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Sat, 17 Dec 2011 22:03:15 +0000 Subject: [PATCH 3/5] make-secnet-sites: Allow sites with no address In-Reply-To: <1324159397-28439-1-git-send-email-ijackson@chiark.greenend.org.uk> References: <1324159397-28439-1-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1324159397-28439-4-git-send-email-ijackson@chiark.greenend.org.uk> Signed-off-by: Ian Jackson --- make-secnet-sites | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/make-secnet-sites b/make-secnet-sites index 5911a39..9d0c6a6 100755 --- a/make-secnet-sites +++ b/make-secnet-sites @@ -267,12 +267,12 @@ class sitelevel(level): 'networks':None, 'peer':None, 'pubkey':(lambda n,v:"key %s;\n"%v), + 'address':None, 'mobile':sp, }) require_properties={ 'dh':"Diffie-Hellman group", 'contact':"Site admin contact address", - 'address':"Site external access address", 'networks':"Networks claimed by the site", 'hash':"hash function", 'peer':"Gateway address of the site", -- 1.5.6.5 From ijackson at chiark.greenend.org.uk Sat Dec 17 22:03:16 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Sat, 17 Dec 2011 22:03:16 +0000 Subject: [PATCH 4/5] make-secnet-sites: New -P option In-Reply-To: <1324159397-28439-1-git-send-email-ijackson@chiark.greenend.org.uk> References: <1324159397-28439-1-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1324159397-28439-5-git-send-email-ijackson@chiark.greenend.org.uk> make-secnet-sites generates a config file which defines the keys "vpn-data", "vpn", and "all-sites". To make it possible to usefully include the output of more than one different piece of output from make-secnet-sites, support the option -P , which generates a config file which defines "vpn-data", "vpn", and "all-sites". Signed-off-by: Ian Jackson --- make-secnet-sites | 15 ++++++++++----- 1 files changed, 10 insertions(+), 5 deletions(-) diff --git a/make-secnet-sites b/make-secnet-sites index 9d0c6a6..c49467a 100755 --- a/make-secnet-sites +++ b/make-secnet-sites @@ -320,6 +320,7 @@ def moan(msg): root=level(['root','root']) # All vpns are children of this node obstack=[root] allow_defs=0 # Level above which new definitions are permitted +prefix='' def set_property(obj,w): "Set a property on a configuration node" @@ -415,20 +416,21 @@ def outputsites(w): w.write("# Command line: %s\n\n"%string.join(sys.argv)) # Raw VPN data section of file - w.write("vpn-data {\n") + w.write(prefix+"vpn-data {\n") for i in root.children.values(): i.output_data(w,2,"") w.write("};\n") # Per-VPN flattened lists - w.write("vpn {\n") + w.write(prefix+"vpn {\n") for i in root.children.values(): - i.output_vpnflat(w,2,"vpn-data") + i.output_vpnflat(w,2,prefix+"vpn-data") w.write("};\n") # Flattened list of sites - w.write("all-sites %s;\n"%string.join(map(lambda x:"vpn/%s/all-sites"% - x,root.children.keys()),",")) + w.write(prefix+"all-sites %s;\n"%string.join( + map(lambda x:"%svpn/%s/all-sites"%(prefix,x), + root.children.keys()),",")) # Are we being invoked from userv? service=0 @@ -471,6 +473,9 @@ else: userinput=sys.stdin.readlines() pfile("user input",userinput) else: + if sys.argv[1]=='-P': + prefix=sys.argv[2] + sys.argv[1:3]=[] if len(sys.argv)>3: print "Too many arguments" sys.exit(1) -- 1.5.6.5 From ijackson at chiark.greenend.org.uk Sat Dec 17 22:03:17 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Sat, 17 Dec 2011 22:03:17 +0000 Subject: [PATCH 5/5] make-secnet-sites: If definition found in wrong place, bomb out In-Reply-To: <1324159397-28439-1-git-send-email-ijackson@chiark.greenend.org.uk> References: <1324159397-28439-1-git-send-email-ijackson@chiark.greenend.org.uk> Message-ID: <1324159397-28439-6-git-send-email-ijackson@chiark.greenend.org.uk> If it doesn't exit here, make-secnet-sites might subsequently crash with Python stack backtrace. Signed-off-by: Ian Jackson --- make-secnet-sites | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/make-secnet-sites b/make-secnet-sites index c49467a..9e00720 100755 --- a/make-secnet-sites +++ b/make-secnet-sites @@ -376,6 +376,8 @@ def pline(i,allow_include=False): if nl.depth Replace : bad IP packet from with : bad IP packet from : reason Signed-off-by: Ian Jackson --- netlink.c | 28 ++++++++++++++++++++-------- 1 files changed, 20 insertions(+), 8 deletions(-) diff --git a/netlink.c b/netlink.c index 5226ad1..559821d 100644 --- a/netlink.c +++ b/netlink.c @@ -384,19 +384,29 @@ static void netlink_icmp_simple(struct netlink *st, struct buffer_if *buf, * 3. Checksums correctly. * 4. Doesn't have a bogus length */ -static bool_t netlink_check(struct netlink *st, struct buffer_if *buf) +static bool_t netlink_check(struct netlink *st, struct buffer_if *buf, + char *errmsgbuf, int errmsgbuflen) { +#define BAD(...) do{ \ + snprintf(errmsgbuf,errmsgbuflen,__VA_ARGS__); \ + return False; \ + }while(0) + struct iphdr *iph=(struct iphdr *)buf->start; int32_t len; - if (iph->ihl < 5 || iph->version != 4) return False; - if (buf->size < iph->ihl*4) return False; - if (ip_fast_csum((uint8_t *)iph, iph->ihl)!=0) return False; + if (iph->ihl < 5) BAD("ihl %u",iph->ihl); + if (iph->version != 4) BAD("version %u",iph->version); + if (buf->size < iph->ihl*4) BAD("size %"PRId32"<%u*4",buf->size,iph->ihl); + if (ip_fast_csum((uint8_t *)iph, iph->ihl)!=0) BAD("csum"); len=ntohs(iph->tot_len); /* There should be no padding */ - if (buf->size!=len || len<(iph->ihl<<2)) return False; + if (buf->size!=len) BAD("len %"PRId32"!=%"PRId32,buf->size,len); + if (len<(iph->ihl<<2)) BAD("len %"PRId32"<(%u<<2)",len,iph->ihl); /* XXX check that there's no source route specified */ return True; + +#undef BAD } /* Deliver a packet. "client" is the _origin_ of the packet, not its @@ -595,11 +605,13 @@ static void netlink_incoming(struct netlink *st, struct netlink_client *client, { uint32_t source,dest; struct iphdr *iph; + char errmsgbuf[50]; BUF_ASSERT_USED(buf); - if (!netlink_check(st,buf)) { - Message(M_WARNING,"%s: bad IP packet from %s\n", - st->name,client?client->name:"host"); + if (!netlink_check(st,buf,errmsgbuf,sizeof(errmsgbuf))) { + Message(M_WARNING,"%s: bad IP packet from %s: %s\n", + st->name,client?client->name:"host", + errmsgbuf); BUF_FREE(buf); return; } -- 1.7.2.5 From ijackson at chiark.greenend.org.uk Mon Dec 26 17:57:59 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Mon, 26 Dec 2011 17:57:59 +0000 Subject: [PATCH] netlink: report why a packet is bad In-Reply-To: <20215.29719.305283.712213@chiark.greenend.org.uk> References: <20215.29719.305283.712213@chiark.greenend.org.uk> Message-ID: <20216.46503.285474.65071@chiark.greenend.org.uk> Ian Jackson writes ("[PATCH] netlink: report why a packet is bad"): > Replace > : bad IP packet from > with > : bad IP packet from : reason I should report the motivation for this patch, really. At some point on Friday the 23rd, secnet on chiark stopped working. Looking at the log in ~secnet/live/log showed this: 22:27:09 sgo/chiark/chiark<->chiark/relativity/zealot: new key activated [this is entirely normal] 23:18:13 nl-ipif: bad IP packet from host [repeated dozens of times] 23:41:31 nl-ipif: bad IP packet from host [only once] [and that was the end of the log] I was online and noticed that something was amiss and investigated. I found these messages in the log. There was no secnet running, but there was a set of userv ipif processes. I killed the userv ipif and restarted secnet: Dec 23 23:44:33 nl-ipif: about to invoke: userv root ipif [blah blah] Dec 23 23:44:33 nl-ipif: userv-ipif pid is 3367 Dec 23 23:44:34 secnet 0.2.1 [3364]: starting [and then everything seems to go well] Since then we had several recurrences of the "bad IP packet from host" messages. But there were fewer in each case. secnet survived. I have looked for a core dump in ~secnet/live but there wasn't one. At some point I will make sure that secnet's startup arrangements arrange that core dumps are properly enabled. Ian. From ijackson at chiark.greenend.org.uk Mon Dec 26 18:02:37 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Mon, 26 Dec 2011 18:02:37 +0000 Subject: [PATCH] netlink: report why a packet is bad In-Reply-To: <20216.46503.285474.65071@chiark.greenend.org.uk> References: <20215.29719.305283.712213@chiark.greenend.org.uk> <20216.46503.285474.65071@chiark.greenend.org.uk> Message-ID: <20216.46781.21244.349608@chiark.greenend.org.uk> Ian Jackson writes ("Re: [PATCH] netlink: report why a packet is bad"): > I was online and noticed that something was amiss and investigated. > I found these messages in the log. There was no secnet running, but > there was a set of userv ipif processes. Process accounting logs say: begin date and time command user group tty dev FSDX sigexit ... 2011-12-18 14:51:21 secnet secnet secnet 00000000 F X k ABRT Ian. From ijackson at chiark.greenend.org.uk Wed Dec 28 00:46:59 2011 From: ijackson at chiark.greenend.org.uk (Ian Jackson) Date: Wed, 28 Dec 2011 00:46:59 +0000 Subject: [PATCH] netlink: report why a packet is bad In-Reply-To: <20216.46781.21244.349608@chiark.greenend.org.uk> References: <20215.29719.305283.712213@chiark.greenend.org.uk> <20216.46503.285474.65071@chiark.greenend.org.uk> <20216.46781.21244.349608@chiark.greenend.org.uk> Message-ID: <20218.26371.813192.635211@chiark.greenend.org.uk> Earlier today I found that my VPN to my netbook was broken. On investigation with strace I found secnet blocked on write to fd 12. This fd appeared to be one of its fds to the userv ipif farm. I ran out of time before I was able to strace the corresponding copy of cat and determine which of the userv client's fds it corresponded to. But I think the fd must have been the one for transferring packet data from secnet to the kernel. The only reasonable explanation for blocking on that fd would seem to be a kernel bug in the slip line discipline. I'm aware of bugs in the slip line discipline - I've seen regular kernel oopses in slattach in some kernels, at least as recently as lenny. I have an experimental but as-yet-unreleased version of userv ipif which uses tun rather than slattach. I will try to prioritise (a) releasing it and (b) installing it on chiark. While I'm on these kind of subjects I noticed that the stderr output from userv ipif doesn't seem to end up in ~secnet/live/log. Ian.