aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChia-chi Yeh <chiachi@android.com>2011-07-04 17:21:23 -0700
committerChia-chi Yeh <chiachi@android.com>2011-07-07 00:16:04 -0700
commitf8a6a7636d53a5730c58ae041e4e09ae12e1657c (patch)
tree2d0059f37c93a41af4c58c7d2f7c588b21339b99
parentc9ac7d2fae3a233f928fd3f643ffa20b6ea602d3 (diff)
downloadipsec-tools-f8a6a7636d53a5730c58ae041e4e09ae12e1657c.tar.gz
ipsec-tools: Update to 0.8.0.
This change updates ipsec-tools to 0.8.0. However, a quick test reveals a regression in IPSec PSK sessions. The server rejects the first packet of phase 2 negotiation with INVALID-ID-INFORMATION error. After testing files one by one, it turns out that using the old ipsec_doi.c fixes the problem. Then the next error shows that identity check is failed. This can be fixed by marking few lines in isakmp_quick.c just like 0.7.3. This change adds ipsec_doi-0.7.3.c as a temporary fix. I will come back and see if I can find the real problem. IPSec RSA sessions will be covered in the next change. Change-Id: I48f0026c3be07f506b3901b59202081bf88f41c9
-rw-r--r--Android.mk21
-rw-r--r--ChangeLog1277
-rw-r--r--Makefile21
-rw-r--r--NEWS48
-rw-r--r--README17
-rw-r--r--ThirdPartyProject.prop8
-rw-r--r--config.h2
-rw-r--r--main.c203
-rw-r--r--setup.c471
-rw-r--r--src/include-glibc/Makefile.in67
-rw-r--r--src/libipsec/Makefile.in245
-rw-r--r--src/libipsec/ipsec_dump_policy.c9
-rw-r--r--src/libipsec/ipsec_get_policylen.c2
-rw-r--r--src/libipsec/ipsec_set_policy.330
-rw-r--r--src/libipsec/ipsec_strerror.c4
-rw-r--r--src/libipsec/key_debug.c53
-rw-r--r--src/libipsec/libpfkey.h24
-rw-r--r--src/libipsec/pfkey.c510
-rw-r--r--src/libipsec/pfkey_dump.c59
-rw-r--r--src/libipsec/policy_parse.h44
-rw-r--r--src/libipsec/policy_parse.y2
-rw-r--r--src/libipsec/policy_token.l2
-rw-r--r--src/racoon/Makefile.am4
-rw-r--r--src/racoon/Makefile.in488
-rw-r--r--src/racoon/admin.c467
-rw-r--r--src/racoon/admin.h19
-rw-r--r--src/racoon/admin_var.h3
-rw-r--r--src/racoon/backupsa.c7
-rw-r--r--src/racoon/cfparse.h682
-rw-r--r--src/racoon/cfparse.y775
-rw-r--r--src/racoon/cftoken.l37
-rw-r--r--src/racoon/crypto_openssl.c240
-rw-r--r--src/racoon/crypto_openssl.h5
-rw-r--r--src/racoon/debug.h3
-rw-r--r--src/racoon/dnssec.c37
-rw-r--r--src/racoon/dnssec.h4
-rw-r--r--src/racoon/doc/FAQ4
-rw-r--r--src/racoon/doc/README.privsep152
-rw-r--r--src/racoon/eaytest.c3
-rw-r--r--src/racoon/evt.c253
-rw-r--r--src/racoon/evt.h86
-rw-r--r--src/racoon/grabmyaddr.c1372
-rw-r--r--src/racoon/grabmyaddr.h28
-rw-r--r--src/racoon/handler.c604
-rw-r--r--src/racoon/handler.h133
-rw-r--r--src/racoon/ipsec_doi-0.7.3.c5022
-rw-r--r--src/racoon/ipsec_doi.c863
-rw-r--r--src/racoon/ipsec_doi.h20
-rw-r--r--src/racoon/isakmp.c1045
-rw-r--r--src/racoon/isakmp.h16
-rw-r--r--src/racoon/isakmp_agg.c303
-rw-r--r--src/racoon/isakmp_base.c143
-rw-r--r--src/racoon/isakmp_cfg.c159
-rw-r--r--src/racoon/isakmp_frag.c2
-rw-r--r--src/racoon/isakmp_ident.c293
-rw-r--r--src/racoon/isakmp_inf.c431
-rw-r--r--src/racoon/isakmp_inf.h5
-rw-r--r--src/racoon/isakmp_quick.c669
-rw-r--r--src/racoon/isakmp_unity.c43
-rw-r--r--src/racoon/isakmp_unity.h6
-rw-r--r--src/racoon/isakmp_var.h56
-rw-r--r--src/racoon/isakmp_xauth.c182
-rw-r--r--src/racoon/isakmp_xauth.h41
-rw-r--r--src/racoon/kmpstat.c18
-rw-r--r--src/racoon/localconf.c21
-rw-r--r--src/racoon/localconf.h11
-rw-r--r--src/racoon/main.c335
-rw-r--r--src/racoon/misc.c13
-rw-r--r--src/racoon/misc.h3
-rw-r--r--src/racoon/nattraversal.c55
-rw-r--r--src/racoon/nattraversal.h6
-rw-r--r--src/racoon/oakley.c684
-rw-r--r--src/racoon/oakley.h53
-rw-r--r--src/racoon/pfkey.c1545
-rw-r--r--src/racoon/pfkey.h8
-rw-r--r--src/racoon/plainrsa-gen.c141
-rw-r--r--src/racoon/plog.c49
-rw-r--r--src/racoon/plog.h2
-rw-r--r--src/racoon/policy.c40
-rw-r--r--src/racoon/policy.h12
-rw-r--r--src/racoon/privsep.c555
-rw-r--r--src/racoon/privsep.h10
-rw-r--r--src/racoon/proposal.c18
-rw-r--r--src/racoon/proposal.h4
-rw-r--r--src/racoon/prsa_par.h44
-rw-r--r--src/racoon/prsa_par.y31
-rw-r--r--src/racoon/racoon.88
-rw-r--r--src/racoon/racoon.conf.5338
-rw-r--r--src/racoon/racoonctl.877
-rw-r--r--src/racoon/racoonctl.c637
-rw-r--r--src/racoon/remoteconf.c878
-rw-r--r--src/racoon/remoteconf.h153
-rw-r--r--src/racoon/rsalist.c61
-rw-r--r--src/racoon/rsalist.h4
-rw-r--r--src/racoon/sainfo.c194
-rw-r--r--src/racoon/sainfo.h14
-rwxr-xr-xsrc/racoon/samples/roadwarrior/client/phase1-down.sh31
-rwxr-xr-xsrc/racoon/samples/roadwarrior/client/phase1-up.sh29
-rw-r--r--src/racoon/schedule.c205
-rw-r--r--src/racoon/schedule.h70
-rw-r--r--src/racoon/session.c462
-rw-r--r--src/racoon/session.h5
-rw-r--r--src/racoon/sockmisc.c248
-rw-r--r--src/racoon/sockmisc.h38
-rw-r--r--src/racoon/strnames.c4
-rw-r--r--src/racoon/throttle.c73
-rw-r--r--src/racoon/throttle.h6
-rw-r--r--src/racoon/var.h2
-rw-r--r--src/racoon/vendorid.c52
-rw-r--r--src/racoon/vendorid.h39
110 files changed, 17276 insertions, 7834 deletions
diff --git a/Android.mk b/Android.mk
index b11ce55..078770f 100644
--- a/Android.mk
+++ b/Android.mk
@@ -21,6 +21,10 @@ LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
+ src/racoon/algorithm.c \
+ src/racoon/crypto_openssl.c \
+ src/racoon/genlist.c \
+ src/racoon/handler.c \
src/racoon/isakmp.c \
src/racoon/isakmp_agg.c \
src/racoon/isakmp_base.c \
@@ -29,22 +33,19 @@ LOCAL_SRC_FILES := \
src/racoon/isakmp_inf.c \
src/racoon/isakmp_newg.c \
src/racoon/isakmp_quick.c \
- src/racoon/handler.c \
- src/racoon/pfkey.c \
- src/racoon/ipsec_doi.c \
+ src/racoon/ipsec_doi-0.7.3.c \
+ src/racoon/nattraversal.c \
src/racoon/oakley.c \
- src/racoon/vendorid.c \
+ src/racoon/pfkey.c \
src/racoon/policy.c \
- src/racoon/crypto_openssl.c \
- src/racoon/algorithm.c \
src/racoon/proposal.c \
- src/racoon/strnames.c \
+ src/racoon/remoteconf.c \
src/racoon/schedule.c \
+ src/racoon/sockmisc.c \
src/racoon/str2val.c \
- src/racoon/genlist.c \
+ src/racoon/strnames.c \
+ src/racoon/vendorid.c \
src/racoon/vmbuf.c \
- src/racoon/sockmisc.c \
- src/racoon/nattraversal.c \
main.c \
setup.c
diff --git a/ChangeLog b/ChangeLog
index 0bc2ef7..b071e40 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,46 +1,574 @@
-2009-08-13 tag ipsec-tools-0_7_3
+2011-03-17 Yvan Vanhullebus <vanhu@netasq.com>
-2009-08-13 Yvan Vanhullebus <vanhu@netasq.com>
+ * src/racoon/oakley.c: fixed a memory leak in
+ oakley_append_rmconf_cr() while generating plist. patch by Roman
+ Hoog Antink <rha@open.ch>
+
+ * src/racoon/oakley.c: free name later, to avoid a memory use after
+ free in oakley_check_certid(). also give iph1->remote to some plog()
+ calls. patch by Roman Hoog Antink <rha@open.ch>
+
+ * src/racoon/oakley.c: fixed a memory leak in
+ oakley_check_certid(). patch by Roman Hoog Antink <rha@open.ch>
+
+2011-03-15 Yvan Vanhullebus <vanhu@netasq.com>
+
+ * src/racoon/: isakmp.c, isakmp_inf.c, pfkey.c: directly call
+ isakmp_ph1delete() instead of scheduling isakmp_ph1delete_stub(), as
+ it is useless an can lead to memory access after free
+
+2011-03-14 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/: grabmyaddr.c, handler.c, isakmp.c, isakmp_inf.c,
+ isakmp_quick.c, nattraversal.c, pfkey.c, policy.c, sockmisc.c,
+ sockmisc.h, throttle.c: Explicitly compare return value of
+ cmpsaddr() against a return value define to make it more obvious
+ what is the intended action. One more return value is also added, to
+ fix comparison of security policy descriptors. Namely, getsp()
+ should not allow wildcard matching (as the comment says, it does
+ exact matching) - otherwise we get problems when kernel has generic
+ policy with no ports, and a second similar policy with ports.
+
+2011-03-14 Yvan Vanhullebus <vanhu@netasq.com>
+
+ * src/racoon/: cfparse.y, isakmp_xauth.c, isakmp_xauth.h,
+ remoteconf.c, remoteconf.h, rsalist.c, rsalist.h: avoid some
+ memory leaks / free memory access when reloading conf and have
+ inherited config. patch from Roman Hoog Antink <rha@open.ch>
+
+ * src/racoon/handler.c: removed an useless comment
+
+ * src/racoon/handler.c: check if we got RMCONF_ERR_MULTIPLE from
+ getrmconf_by_ph1() in revalidate_ph1tree_rmconf()
+
+2011-03-11 Yvan Vanhullebus <vanhu@netasq.com>
+
+ * src/racoon/: handler.c, isakmp.c: directly delete a ph1 in
+ remove_ph1-) instead of scheduling it, to avoid (completely ?) a
+ race condition when reloading configuration
+
+2011-03-06 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/privsep.c: Quiet a gcc warning when strict-aliasing
+ checks are enabled. Reported by Stephen Clark.
+
+2011-03-02 Yvan Vanhullebus <vanhu@netasq.com>
+
+ * src/racoon/session.c: flush sainfo list when closing session.
+ patch by Roman Hoog Antink <rha@open.ch>
+
+ * src/racoon/: remoteconf.c, rsalist.c, rsalist.h: free rsa
+ structures when deleting a struct rmconf. patch by Roman Hoog Antink
+ <rha@open.ch>
+
+ * src/racoon/: cfparse.y, remoteconf.c, remoteconf.h: free spspec
+ when deleting a rmconf struct. patch by Roman Hoog Antink
+ <rha@open.ch>
+
+ * src/racoon/: remoteconf.c, session.c: fixed some memory leaks in
+ remoteconf. patch by Roman Hoog Antink <rha@open.ch>
+
+ * src/racoon/: cfparse.y, prsa_par.y: fixed some memory leaks
+ during configuration parsing. patch by Roman Hoog Antink
+ <rha@open.ch>
+
+2011-03-01 Yvan Vanhullebus <vanhu@netasq.com>
+
+ * src/racoon/: isakmp.c, pfkey.c: plog text fixes, patch from M E
+ Andersson <debian@gisladisker.se>
+
+ * src/racoon/cfparse.y: reset yyerrorcount before doing parse
+ stuff. patch by Roman Hoog Antink <rha@open.ch>
+
+2011-02-20 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/oakley.c: From Roman Hoog Antink <rha@open.ch>: Fix
+ memory leak when using plain RSA key authentication.
+
+2011-02-11 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/plainrsa-gen.c: From Mats E Andersson
+ <debian@gisladisker.se>: Fix fprintf format specifier usage from
+ previous patch.
+
+2011-02-10 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/plainrsa-gen.c: From Mats Erik Andersson
+ <debian@gisladisker.se>: Implement importing of RSA keys from PEM
+ files.
+
+ * src/racoon/prsa_par.y: From M E Andersson
+ <debian@gisladisker.se>: Fix parsing of restricted RSA key
+ addresses.
+
+2011-02-02 Yvan Vanhullebus <vanhu@netasq.com>
+
+ * src/racoon/: cftoken.l, isakmp.c, remoteconf.h, sainfo.c,
+ sainfo.h: store ph1id in an u_int32_t instead of a (signed)int.
+ Patch from Christophe Carre
+
+2011-01-28 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/: sainfo.c, sainfo.h, session.c: From Roman Hoog
+ Antink <rha@open.ch>: Clean up sainfo reloading: rename the
+ functions, and remove unneeded global variable.
+
+ * src/racoon/: remoteconf.c, remoteconf.h, session.c: From Roman
+ Hoog Antink <rha@open.ch>: Clean up rmconf reloading: rename the
+ functions, and remove unneeded global variable.
+
+ * src/racoon/plog.c: From Roman Hoog Antink <rha@open.ch>: Log
+ remote IP address if available (slightly modified by tteras)
+
+2011-01-22 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/isakmp_inf.c: From Roman Hoog Antink <rha@open.ch>:
+ Fixes a null pointer dereference that might occur after removing
+ peers from the config and then reloading.
+
+2011-01-20 Yvan Vanhullebus <vanhu@netasq.com>
+
+ * src/libipsec/pfkey.c: fixed a typo, it will now compile when
+ KMADDRESS is defined. reported by Roman Hoog Antink (rha (at)
+ open.ch)
+
+2010-12-28 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/handler.c: From Roman Hoog Antink <rha@open.ch>: Fix
+ config reload to not delete too many phase 2 handles, because wrong
+ chain field is used when enumerating the handles.
+
+2010-12-16 gdt
+
+ * src/racoon/oakley.c: When encountering a certificate where "ID
+ mismatched with ASN1 SubjectName", and verify_identifier is off,
+ don't raise an error. This makes the behavior match the man page.
+
+ Patch sent for review long ago:
+ http://mail-index.netbsd.org/tech-security/2006/03/24/0000.html
+ with no negative feedback received to date.
+
+2010-12-14 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/ipsec_doi.c: From Roman Hoog Antink <rha@open.ch>: Fix
+ possible null derefence.
+
+2010-12-08 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/admin.c: Use separate SA addresses for phase2's
+ created by admin command. The phase2 startup overwrites src/dst with
+ ISAKMP ports if they are zero and we don't want that to happen for
+ the SA ports.
+
+2010-12-08 joerg
+
+ * src/libipsec/pfkey.c: ANSIfy
+
+2010-12-07 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/isakmp_quick.c: Fix spacing and improve wording in
+ some log messages.
+
+2010-12-03 Timo Teras <timo.teras@iki.fi>
+
+ * src/libipsec/ipsec_dump_policy.c: Recognize direction for Linux
+ per-socket policies.
+
+ * src/: libipsec/libpfkey.h, libipsec/pfkey_dump.c, setkey/parse.y,
+ setkey/setkey.8: Support GRE key as upper layer protocol
+ specifier (will be supported in Linux kernel 2.6.38).
+
+ * src/racoon/grabmyaddr.c: Netlink deletion notification does not
+ guarentee actual address deletion: it might still exist on some
+ other interface. Make sure we do not unbind unless the address is
+ really gone.
+
+2010-11-17 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/: handler.c, handler.h, isakmp.c, isakmp_inf.c: Fix my
+ previous patch to not call purge_remote() twice. Change the place
+ where purge_remote() is called. This fixes also a possible crash
+ from the same patch since ph1->remote can be NULL (when we are
+ responder and config is not yet selected).
+
+2010-11-12 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/: admin.c, isakmp.c, isakmp_var.h, pfkey.c:
+ isakmp_post_acquire is now called from admin commands too, add a
+ flag so admin commands can be used to establish even passive links
+ on demand.
+
+ * src/racoon/isakmp.c: Purge all IPsec-SA's if the last main
+ ISAKMP-SA for the node is deleted by remote request and the phase1
+ rekeying is enabled (this will also trigger the new phase1_dead
+ script hook).
+
+ * src/racoon/: handler.h, isakmp_inf.c: Improve DPD sequence checks
+ to allow any reply within valid sequence window to be proof of
+ livelyness. This can improves things if there's random packet
+ delays, or if racoon is not getting enough CPU time.
+
+ * src/racoon/: admin.c, admin.h, kmpstat.c, racoonctl.c: Extern
+ admin protocol to allow reply packets to exceed 64kb. E.g SA dumps
+ with many established SAs can be easily over the limit.
+
+2010-10-22 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/grabmyaddr.c: Change Linux Netlink address monitoring
+ to monitor local route changes. This works around a kernel bug, and
+ slightly improves behaviour on some special cases.
+
+2010-10-21 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/: admin.c, evt.c, grabmyaddr.c, isakmp.c, pfkey.c,
+ session.c, session.h: Introduce priorities for file descriptor
+ polling mechanism and give priority to admin port. If admin port is
+ used by ISAKMP-SA hook scripts they should be preferred, other wise
+ heavy traffic can delay admin port requests considerably. This in
+ turn may cause renegotiation loop for ISAKMP-SA. This is mostly
+ useful for OpenNHRP setup, but can benefit other setups too.
+
+ * src/racoon/: admin.c, handler.c, handler.h: Remove
+ initial-contact entry when all ISAKMP-SA are purged via adminport.
+ This will avoid stale security associations if some of the delete
+ notifications happens to get lost.
+
+2010-10-20 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/crypto_openssl.c: Use high-level openssl EVP and HMAC
+ functions when possible: this allows openssl to perform hardware
+ acceleration if available.
+
+ * src/racoon/: isakmp.c, isakmp_quick.c: Various improvements to
+ error log messages and a few additional error log messages to
+ improve diagnosing an error condition.
+
+ * src/racoon/grabmyaddr.c: Fix address comparison so we actually
+ close sockets which were bound to IP-address that got deconfigured.
+
+2010-10-11 Yvan Vanhullebus <vanhu@netasq.com>
+
+ * src/racoon/ipsec_doi.c: report a higher encryption key length in
+ approval for OBEY / CLAIM / STRICT modes
+
+2010-09-27 Yvan Vanhullebus <vanhu@netasq.com>
+
+ * src/racoon/isakmp_xauth.c: fixed some typos in logs (reported by
+ fazaeli (at) sepehrs.com)
+
+2010-09-24 Yvan Vanhullebus <vanhu@netasq.com>
+
+ * src/racoon/cftoken.l: fixed a fd leak, patch by getlaser (at)
+ gmail.com
+
+2010-09-22 Yvan Vanhullebus <vanhu@netasq.com>
+
+ * src/racoon/admin.c: get the correct length of username when
+ processing ADMIN_LOGOUT_USER, patch by rweikusat (at) mssgmbh.com
+
+ * src/racoon/nattraversal.h: fixed a typo in macros, reported by
+ marisp (at) mt.lv
+
+2010-09-21 Yvan Vanhullebus <vanhu@netasq.com>
+
+ * src/racoon/isakmp_cfg.c: moved from utmp.h to utmpx.h (patch
+ provided by marcin.cieslak (at) gmail.com)
+
+2010-09-08 Yvan Vanhullebus <vanhu@netasq.com>
+
+ * src/racoon/remoteconf.c: fixed remoteconf selection when no ID
+ specified in configuration, and added some debug to remoteconf
+ selection
+
+2010-08-26 Yvan Vanhullebus <vanhu@netasq.com>
+
+ * src/racoon/remoteconf.c: fix by Sergio.Gelato (at) astro.su.se:
+ duplicate some dynamic values in duprmconf()
+
+2010-08-04 Yvan Vanhullebus <vanhu@netasq.com>
+
+ * src/racoon/isakmp_cfg.c: fixed answer for IP4_SUBNET request
+
+2010-07-30 Yvan Vanhullebus <vanhu@netasq.com>
+
+ * src/racoon/doc/FAQ: updated link to NetBSD's documentation
+
+2010-06-22 Thomas Klausner <wiz@netbsd.org>
+
+ * src/racoon/racoon.conf.5: Bump date for previous.
+
+2010-06-22 Yvan Vanhullebus <vanhu@netasq.com>
+
+ * src/racoon/: cfparse.y, cftoken.l, isakmp.c, isakmp_inf.c,
+ racoon.conf.5, remoteconf.c, remoteconf.h: added a specific
+ script hook when a dead peer is detected
+
+2010-06-04 Thomas Klausner <wiz@netbsd.org>
+
+ * src/setkey/setkey.8: New sentence, new line. Bump date for
+ previous.
+
+2010-06-04 Yvan Vanhullebus <vanhu@netasq.com>
+
+ * src/setkey/: parse.y, setkey.8, token.l: Added support for
+ spdupdate command in setkey
+
+2010-04-07 Yvan Vanhullebus <vanhu@netasq.com>
+
+ * src/libipsec/ipsec_strerror.c: by Eric Preston: fixed a typo
+
+2010-04-02 Christos Zoulas <christos@netbsd.org>
+
+ * src/: libipsec/pfkey_dump.c, racoon/backupsa.c: handle ctime
+ returning NULL.
+
+2010-03-11 Christos Zoulas <christos@netbsd.org>
+
+ * src/racoon/handler.c: PR/42363: Yasuoka Masahiko: Second part of
+ the patch: iterate only on the phase2 handles that are bound by the
+ given phase1 handle.
+
+2010-03-05 Timo Teras <timo.teras@iki.fi>
+
+ * src/: libipsec/ipsec_set_policy.3, racoon/privsep.c,
+ racoon/doc/FAQ, setkey/setkey.8: From Stefan Bauer: Fix multiple
+ typoes and manpage formatting errors.
- * NEWS, configure.ac: 0.7.3 release
+2010-03-04 Yvan Vanhullebus <vanhu@netasq.com>
+
+ * src/racoon/session.c: From Pierre POMES: fixed admin port
+ initialization
+
+2010-02-28 snj
+
+ * src/racoon/: sockmisc.c, sockmisc.h: Fight the ever-increasing
+ size of src checkouts by spelling "useful" without an extra l.
+
+2010-02-09 Thomas Klausner <wiz@netbsd.org>
+
+ * src/racoon/: pfkey.c, proposal.h: Fix typo in comment.
+
+2010-01-17 Thomas Klausner <wiz@netbsd.org>
+
+ * src/racoon/sainfo.c: Free strdeupped string after using it. Found
+ by cppcheck.
+
+ * src/racoon/: eaytest.c, ipsec_doi.c: Close file handles after
+ using them. Found by cppcheck.
+
+2010-01-15 joerg
+
+ * src/setkey/setkey.8: Use .%U instead of .%O for URLs.
+
+2009-12-11 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/Makefile.am: From Paul Wernau: vmbuf.h was defined
+ twice in the headers. Remove the redundant entry so new install tool
+ does not complain about overwriting just installed file.
+
+2009-11-22 Christos Zoulas <christos@netbsd.org>
+
+ * src/racoon/handler.c: PR/42363: Yasuoka Masahiko:
+
+ racoon uses a wrong IPsec-SA handle that is for other peer in case
+ it receives a ISAKMP message for IPsec-SA that has the same
+ message-id as the message-id that is received before.
+
+ racoon uses message-id to find the handle of IPsec-SA. The
+ message-id is a unique number for each peer, but different peers may
+ use the same value.
+
+ Different Windows Vista or Windows 7 peers seem to use the same
+ message-id. racoon can handle the first Windows's Phase-2, but it
+ cannot handle the second Windows. Because racoon misunderstands the
+ message for the second Windows as the message for the first Windows.
+
+ >Category: bin >Synopsis: racoon uses a wrong IPsec-SA
+ that is for different peer >Confidential: no >Severity:
+ serious >Priority: medium >Responsible: bin-bug-people
+ >State: open >Class: sw-bug >Submitter-Id: net
+ >Arrival-Date: Sun Nov 22 18:25:00 +0000 2009 >Originator:
+ yasuoka@iij.ad.jp
+
+2009-10-29 Christos Zoulas <christos@netbsd.org>
+
+ * src/setkey/token.l: use %option noinput nounput
+
+2009-10-28 Christos Zoulas <christos@netbsd.org>
+
+ * src/setkey/token.l: no unput
+
+2009-10-14 joerg
+
+ * src/libipsec/ipsec_set_policy.3: Do not use .Xo/.Xc to workaround
+ ancient groff limits.
+
+ * src/setkey/setkey.8: Do not use .Xo/.Xc to work around ancient
+ groff limits. Fix markup.
+
+ * src/racoon/racoon.conf.5: Don't use .Xo/.Xc to work around
+ ancient groff limits. Set only one list type.
+
+2009-09-18 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/: isakmp_agg.c, isakmp_ident.c: From Tomas Mraz: Fix
+ gssapi error checking.
+
+2009-09-03 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/: admin.c, handler.c, handler.h, isakmp.c,
+ isakmp_var.h, pfkey.c: When rekeying phase2 use phase1 used to
+ negotiate phase2 as a hint to select the phase1 for rekeying the new
+ phase2.
+
+2009-09-01 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/: nattraversal.c, racoon.conf.5, vendorid.c: Check
+ nat_traversal configuration from remote configuration candidates
+ when acting as responder. Enable NAT-T if any of the remote
+ candidates have NAT-T enabled.
+
+ * src/racoon/remoteconf.c: Change remote conf matching level to
+ matching score. This way one can override anonymous certificate
+ block config with more exact "inhereted" IP specific block.
+
+ * src/racoon/: isakmp.c, racoon.conf.5: From Maik Broemme: export
+ ISAKMP SA identity as REMOTE_ID for phase1 up script (trac #313).
+
+2009-08-24 Yvan Vanhullebus <vanhu@netasq.com>
+
+ * src/racoon/oakley.c: fixed typo: algoriym -> algorithm
+
+2009-08-19 Yvan Vanhullebus <vanhu@netasq.com>
+
+ * src/racoon/remoteconf.c: fixed address check in
+ rmconf_match_type(), just check address with wildcard port
+
+2009-08-19 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/remoteconf.c: Have an enum for rmconf_match_type()
+ return values to make the code a bit more readable.
+
+2009-08-18 Yvan Vanhullebus <vanhu@netasq.com>
+
+ * src/racoon/oakley.c: typo: algoritym -> algorithm
+
+2009-08-17 Yvan Vanhullebus <vanhu@netasq.com>
+
+ * src/libipsec/libpfkey.h: do not use SADB_X_NAT_T_NEW_MAPPING to
+ check system support for NAT-T, as at least FreeBSD doesn't have
+ this define anymore
+
+ * src/racoon/schedule.h: include stddef.h so we have a chance to
+ get the system offsetof if present
+
+ * src/racoon/crypto_openssl.h: removed a self include
+
+2009-08-13 Yvan Vanhullebus <vanhu@netasq.com>
* src/racoon/oakley.c: fixed a potential DoS in
oakley_do_decrypt(), reported by Orange Labs
+2009-08-10 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/pfkey.c: Don't print EAGAIN error from
+ pfkey_handler(), it can occur normally under some code paths and is
+ not a hard error in any case.
+
2009-08-06 Timo Teras <timo.teras@iki.fi>
* src/setkey/setkey.c: From Paul Wenau: Check fgets return value in
setkey to make gcc happy.
-2009-06-19 Timo Teras <timo.teras@iki.fi>
+2009-08-05 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/pfkey.c: From Paul Wernau: Fix transport mode per-port
+ security associations that got broke during NAT-T fixes.
+
+2009-07-07 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/sockmisc.c: From Arnaud Ebalard: Fix possible usage of
+ uninitialized local variable (not sure if any code path triggers
+ this, but this makes compiler happy).
+
+2009-07-03 Timo Teras <timo.teras@iki.fi>
- * src/racoon/ipsec_doi.c: Backport S.P.Zeidler's fix to IPv6
- address related stack smashing in ipsecdoi_id2str() from CVS HEAD.
+ * src/racoon/: admin.c, grabmyaddr.c, handler.c, handler.h,
+ isakmp.c, isakmp_cfg.c, isakmp_inf.c, isakmp_quick.c,
+ nattraversal.c, pfkey.c, policy.c, remoteconf.c, remoteconf.h,
+ sockmisc.c, sockmisc.h, throttle.c: Get rid of the evil CMPSADDR
+ macro. Trac #295.
+
+ * src/: libipsec/libpfkey.h, libipsec/pfkey.c, racoon/isakmp.c,
+ racoon/isakmp_inf.c, racoon/pfkey.c, racoon/pfkey.h: From Yvan
+ Vanhullebus: Use SADB_X_EXT_NAT_T_* consistently for passing the
+ NAT-T port information. This might break compatibility with some
+ kernels, but as discussed this is the proper way to pass NAT-T ports
+ and the broken kernels need to be fixed.
+
+2009-06-24 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/session.c: Fix a call to null pointer: in some cases,
+ the unmonitor_fd can be called from another fd's callback. That
+ could lead to still have callback pending after unmonitoring the fd
+ resulting in a call to null pointer. This is fixed by making
+ unmonitor_fd now clear the pending fd_set too. Bug was introduced
+ by my commit in 2008-12-23.
+
+2009-05-20 Yvan Vanhullebus <vanhu@netasq.com>
+
+ * src/racoon/isakmp.h: typo
+
+2009-05-19 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/: ipsec_doi.c, isakmp.c: From Jukka Salmi: Fix couple
+ of typos from previous commit.
2009-05-18 Timo Teras <timo.teras@iki.fi>
+ * src/racoon/: ipsec_doi.c, isakmp.c, sockmisc.c, sockmisc.h: From
+ Tomas Mraz: Introduce union sockaddr_any and use it to make code
+ more readable. Related to trac #293.
+
* src/racoon/isakmp_inf.c: From Tomas Mraz: Remove variable that is
not really used; only referenced while uninitialized causing
valgrind error.
* src/racoon/nattraversal.c: From Tomas Mraz: Fix natt_flags check.
+2009-05-04 Thomas Klausner <wiz@netbsd.org>
+
+ * src/racoon/racoon.conf.5: Remove superfluous spaces around
+ parentheses.
+
2009-04-29 Timo Teras <timo.teras@iki.fi>
* src/racoon/crypto_openssl.c: From Ross Meng: Fix a memory leak in
X509 certificate validation.
-2009-04-22 tag ipsec-tools-0_7_2
+2009-04-28 Timo Teras <timo.teras@iki.fi>
-2009-04-22 Timo Teras <timo.teras@iki.fi>
+ * src/racoon/handler.c: Reset nat_oa variables too when reusing
+ phase two handler. Otherwise phase2 rekeying might fail in some
+ scenarios.
- * NEWS, configure.ac: Updates for 0.7.2 release
+2009-04-22 Timo Teras <timo.teras@iki.fi>
* src/racoon/isakmp_frag.c: From Neil Kettle: Fix a possible null
pointer dereference in fragmentation code.
+2009-04-21 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/: grabmyaddr.c, grabmyaddr.h, session.c: Fix
+ strict_address to work again. The lists needs to be initialized
+ before configuration is read, which happens before my_addr_init()
+ call.
+
2009-04-20 Timo Teras <timo.teras@iki.fi>
+ * src/racoon/: isakmp.c, isakmp.h, isakmp_var.h: Fix a memory leak
+ in certificate request generation.
+
* src/racoon/: isakmp_inf.c, isakmp_xauth.c, plog.c: Orignally from
Bin Li: Fix possible memory corruption in binsanitize().
@@ -56,25 +584,257 @@
* src/racoon/handler.c: From Paul Moore: Phase2 message id's should
be unique wrt phase1, not globally.
+2009-03-13 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/: pfkey.c, remoteconf.h: From Arnaud Ebalard: Fix
+ couple of problems with previous commit.
+
+2009-03-12 he
+
+ * src/racoon/: isakmp.c, remoteconf.c: When casting to/from a
+ pointer to an integral type (a bad practice, if you ask me), you
+ need to cast via intptr_t for portability.
+
+2009-03-12 Thomas Klausner <wiz@netbsd.org>
+
+ * src/racoon/racoon.conf.5: New sentence, new line. Avoid marking
+ up punctuation.
+
+ * src/racoon/racoonctl.8: Bump date for previous. Sort options to
+ establish-sa. Stop using Xo/Xc.
+
+2009-03-12 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/: admin.c, cfparse.y, cftoken.l, crypto_openssl.c,
+ crypto_openssl.h, dnssec.c, dnssec.h, handler.c, handler.h,
+ ipsec_doi.c, ipsec_doi.h, isakmp.c, isakmp.h, isakmp_agg.c,
+ isakmp_base.c, isakmp_ident.c, isakmp_inf.c, isakmp_quick.c,
+ isakmp_var.h, nattraversal.c, oakley.c, oakley.h, racoon.conf.5,
+ racoonctl.8, racoonctl.c, remoteconf.c, remoteconf.h, sockmisc.c,
+ vendorid.c: Support multiple anonymous remotes and decide
+ remoteconf based on identity, received certificates and other
+ information. General code clean up.
+
+2009-03-06 Timo Teras <timo.teras@iki.fi>
+
+ * src/setkey/: extern.h, parse.y, setkey.c: setkey: fix deleteall
+ in Linux
+
+ Linux requires SADB_DELETE message to have SPI. So send a
+ SADB_DELETE message for each matching SA. Trac #284.
+
+ From: Gabriel Somlo <somlo@cmu.edu>
+
2009-02-16 Timo Teras <timo.teras@iki.fi>
* src/libipsec/policy_parse.y: From Paul Moore: Fix a heap
corruption bug (yacc return non-null terminated buffer and sprintf
writes over bounds).
-2009-01-20 Timo Teras <timo.teras@iki.fi>
+2009-02-11 Yvan Vanhullebus <vanhu@netasq.com>
- * configure.ac: Fix a CPPLAGS typo to CPPFLAGS which was intended
+ * src/racoon/: isakmp.c, sockmisc.c, sockmisc.h: trac#301: fixed
+ IPsec SAs flush in purge_remote() when NAT-T enabled but no NAT-T on
+ tunnel
+
+2009-02-03 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/isakmp.c: From: Phil Sutter. Fix script environment
+ variables with IPv6 addresses.
+
+2009-01-26 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/main.c: Argument parsing needs lcconf initialized.
+
+2009-01-24 Thomas Klausner <wiz@netbsd.org>
+
+ * src/racoon/racoonctl.c: Sort options in usage.
+
+ * src/racoon/racoonctl.8: Sort options. New sentence, new line.
+
+ * src/racoon/racoon.8: Sort options.
+
+2009-01-23 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/: racoonctl.8, racoonctl.c: Update usage and manpage
+ for racoonctl.
+
+ * src/racoon/: main.c, racoon.8: Racoon -v to print version and
+ compilation information. Update usage message.
- * misc/cvs2cl.pl, misc/cvsusermap, Makefile.am: Autogenerate
+ * NEWS: Update NEWS with major changes since 0.7 release.
+
+ * src/racoon/schedule.c: Fix monotonic scheduler change, to not
+ refresh 'now' before exit. Otherwise we can return negative timeout
+ after spending time handling other events.
+
+ * src/racoon/: handler.c, pfkey.c: From Arnaud Ebalard: Handle
+ reception of MIGRATE message during Phase 1 and Phase 2 negotiation.
+ Also corrects some debugging statements.
+
+ * src/racoon/pfkey.c: From Arnaud Ebalard: On the responder (for
+ instance), there is a need to not only migrate local and remote
+ addresses of Phase 1 that match previous addresses but also the
+ local and remote addresses of a Phase 1 *associated* with a migrated
+ Phase 2. For instance, we have that need when receiving the first
+ MIGRATE/KMADDRESS message because the old addresses are still the
+ HoA and the address of the HA (while the peer has contacted us using
+ the CoA and we have negotiated this address as src attribute in
+ Phase 2). The patch fixes that by having migrate_ph1_ike_addresses()
+ called from migrate_ph2_ike_addresses() callback.
+
+ * src/racoon/isakmp_quick.c: From Arnaud Ebalard: Set phase2 spid
+ when acting as responder.
+
+ * configure.ac, src/racoon/handler.c, src/racoon/handler.h,
+ src/racoon/isakmp_inf.c, src/racoon/isakmp_xauth.c,
+ src/racoon/schedule.c, src/racoon/schedule.h,
+ src/racoon/throttle.c, src/racoon/throttle.h: Detect if monotonic
+ system clock is available, and use it for relative time measurements
+ to avoid complite hang if time jumps backwards.
+
+ * src/racoon/: cfparse.y, ipsec_doi.c, isakmp.c, isakmp_agg.c,
+ isakmp_base.c, isakmp_cfg.c, isakmp_ident.c, isakmp_xauth.c,
+ oakley.c, oakley.h: Fix authentication method ambiguity by
+ internally using unique ID and setting/interpreting the wire format
+ based on received vendor ID:s. Fixes trac #280.
+
+ * src/racoon/: handler.h, isakmp_agg.c, isakmp_base.c,
+ isakmp_ident.c, vendorid.c, vendorid.h: Introduce vendorid
+ bitmask that can be used otherwhere to detect peer capabilities.
+
+ * configure.ac, src/racoon/admin.c, src/racoon/evt.c,
+ src/racoon/grabmyaddr.c, src/racoon/isakmp.c, src/racoon/pfkey.c,
+ src/racoon/session.c, src/racoon/session.h: Remove "fastquit"
+ configure option and make it the default behaviour. The previous
+ normal behaviour is buggy, as after flush kernel can immediately
+ create larval SA:s which would prevent exit.
+
+2009-01-20 Timo Teras <timo.teras@iki.fi>
+
+ * Makefile.am, misc/cvs2cl.pl, misc/cvsusermap: Autogenerate
ChangeLog from NetBSD CVS. Put sourceforge.net changes to
ChangeLog.old.
- * misc/cvs2cl.pl: file cvs2cl.pl was added on branch
- ipsec-tools-0_7-branch on 2009-01-20 14:36:32 +0000
+2009-01-10 Thomas Klausner <wiz@netbsd.org>
+
+ * src/racoon/racoon.conf.5: Make ready for HTML output. Use proper
+ escape for backslash ('\e').
+
+2009-01-10 Timo Teras <timo.teras@iki.fi>
- * misc/cvsusermap: file cvsusermap was added on branch
- ipsec-tools-0_7-branch on 2009-01-20 14:36:32 +0000
+ * src/racoon/: crypto_openssl.c, racoon.conf.5: From Cyrus Rahman:
+ Accept RFC2253 compliant escaped special characters for asn1dn
+ identifier.
+
+2009-01-09 Timo Teras <timo.teras@iki.fi>
+
+ * configure.ac: Fix a CPPLAGS typo to CPPFLAGS which was intended
+
+2009-01-05 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/: cfparse.y, cftoken.l, racoon.conf.5: Remove obsolete
+ configuration options, fix radius configuration block and add GRE as
+ recognized protocol.
+
+ * src/racoon/session.c: Do not use counting in signal handling as
+ it was unsafe by not using atomic functions (post increment is not
+ necessarily atomic). Instead reap all children on SIGCHLD as that
+ was the only signal needing signal counting.
+
+2008-12-30 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/session.c: schedular() call can now modify fd mask so
+ make the working copy just before calling select(); otherwise it can
+ contain bad file descriptors
+
+2008-12-29 Michael van Elst <mlelstv@netbsd.org>
+
+ * src/setkey/parse.y: support icmp codes. Fixes PR 39056.
+
+2008-12-24 Christos Zoulas <christos@netbsd.org>
+
+ * src/racoon/grabmyaddr.c: remove sin{6,}_len linux does not have
+ it. From Timo Teras.
+
+ * src/racoon/grabmyaddr.c: I was wrong. addr is actually set.
+
+ * src/racoon/grabmyaddr.c:
+ - make this compile by zeroing out the whole structure not just
+ bogus fields.
+ - set length field of sockets appropriately.
+ - mark bogus no-op code (I don't understand what the author intended
+ here).
+
+2008-12-23 Thomas Klausner <wiz@netbsd.org>
+
+ * src/racoon/racoon.conf.5: Bump date for identity configuration
+ option removal.
+
+2008-12-23 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/: cfparse.y, cftoken.l, ipsec_doi.c, localconf.c,
+ localconf.h, racoon.conf.5: Remove the obsoleted global identity
+ configuration option.
+
+ * src/racoon/: admin.c, admin_var.h, cfparse.y, debug.h, evt.c,
+ evt.h, grabmyaddr.c, grabmyaddr.h, handler.c, isakmp.c,
+ isakmp_inf.c, isakmp_var.h, localconf.c, localconf.h, main.c,
+ nattraversal.c, pfkey.c, pfkey.h, privsep.c, session.c,
+ session.h: rewrite local address detection make some functions
+ static that arr not needed globally rework how fd_set is
+ construction for the main loop select()
+
+2008-12-18 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/pfkey.c: From Arnaud Ebalard: Delete larval ph2handles
+ when expire with hard lifetime received
+
+2008-12-16 Timo Teras <timo.teras@iki.fi>
+
+ * README: Update README
+
+ * src/racoon/pfkey.c: Fix transport mode address selection in
+ acquire handling. Some earlier fixes got lost on 2008-12-05 commit.
+
+2008-12-11 Yvan Vanhullebus <vanhu@netasq.com>
+
+ * src/racoon/grabmyaddr.c: Fixed compilation on FreeBSD (RTM_IFINFO
+ and RTM_OIFINFO stuff)
+
+ * src/racoon/isakmp.c: Fixed compilation when DPD support is
+ disabled
+
+2008-12-08 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/: pfkey.c, privsep.c, privsep.h: Do not cache pfkey
+ sockets: it might cause to not handle some pfkey events when
+ select() has marked pfkey socket readable, but a timer callback
+ first calls pfkey_dump_sadb().
+
+2008-12-05 Timo Teras <timo.teras@iki.fi>
+
+ * src/: libipsec/key_debug.c, libipsec/libpfkey.h,
+ libipsec/pfkey.c, racoon/handler.c, racoon/handler.h,
+ racoon/ipsec_doi.c, racoon/isakmp.c, racoon/isakmp_quick.c,
+ racoon/pfkey.c, racoon/policy.c, racoon/policy.h: From Arnaud
+ Ebalard: Improved Mobile IPv6 support per
+ draft-ebalard-mext-pfkey-enhanced-migrate.
+
+2008-12-04 Christoph Badura <bad@netbsd.org>
+
+ * src/racoon/privsep.c: Fix typo in previous and use SIG_IGN as I
+ intended.
+
+2008-12-02 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/session.c: Explicitly ignore SIGPIPE. Default action
+ on Linux is terminate.
+
+2008-11-28 Thomas Klausner <wiz@netbsd.org>
+
+ * src/racoon/racoon.conf.5: Remove empty line. Fix typo. New
+ sentence, new line.
2008-11-27 Yvan Vanhullebus <vanhu@netasq.com>
@@ -83,26 +843,181 @@
* src/racoon/isakmp_cfg.c: Fixed pool resizing
+2008-11-27 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/pfkey.c: From Arnaud Ebalard: Remove MAXNESTEDSA
+ weirdness. It's probably meant for bundle support which is not done.
+ When someone actually writes bundle support, the nested SA stuff
+ would probably be reworked too anyway.
+
+ * src/: libipsec/libpfkey.h, libipsec/pfkey.c, racoon/cfparse.y,
+ racoon/cftoken.l, racoon/localconf.c, racoon/localconf.h,
+ racoon/pfkey.c, racoon/racoon.conf.5: From: Matthew Krenzer
+ Ability to set pfkey socket buffer size via configuration file
+ directive. (Indentation and minor fixes by me.)
+
+2008-11-25 Christoph Badura <bad@netbsd.org>
+
+ * src/racoon/: evt.c, privsep.c, session.c: Avoid using
+ MSG_NOSIGNAL as it is not available everywhere. Ignore SIGPIPE
+ instead.
+
+ * src/racoon/grabmyaddr.c: Ignore unspecified and looback
+ addresses. Ignoring unspecified addresses prevents racoon from
+ trying to bind to the wildcard address and specific addresses
+ simultaneously after e.g. dhclient has changed an interface's
+ address to 0.0.0.0.
+
+ * src/racoon/grabmyaddr.c: RTM_DELETE and RTM_IFINFO don't carry
+ info for added or deleted addresses. Ignore them silently.
+
+ * src/racoon/grabmyaddr.c: Ignoring an unsuitable address is not an
+ error. Therefore log it as informational. Make it clear from the
+ log message that a route message is not interesting.
+
+ * src/racoon/grabmyaddr.c: Use insmyaddr() instead of open coding
+ it.
+
+ * src/racoon/isakmp.c: Do not return erroneously from isakmp_open()
+ when setting IPV6_USE_MIN_MTU fails.
+
+ * src/racoon/: grabmyaddr.c, isakmp.c: Keep myaddr.sock at -1 when
+ no socket is opened.
+
+2008-11-08 Christoph Badura <bad@netbsd.org>
+
+ * src/racoon/samples/roadwarrior/client/: phase1-down.sh,
+ phase1-up.sh: Preserve owner and permissions of original
+ /etc/resolv.conf. Ensure that new /etc/resolv.conf isn't group or
+ world writable.
+
+ * src/racoon/samples/roadwarrior/client/: phase1-down.sh,
+ phase1-up.sh: Print and check INTERNAL_NETMASK4.
+
+ * src/racoon/samples/roadwarrior/client/: phase1-down.sh,
+ phase1-up.sh: Make the handling of NAT-T SPD entries automatic.
+
+ * src/racoon/samples/roadwarrior/client/: phase1-down.sh,
+ phase1-up.sh: Ensure that the determination of the default
+ gateway and the corresponding interface don't get confused by
+ multiple, possibly non-IPv4 default routes. Bring the NetBSD case
+ of deleting the VPN routes and address in line with the Linux case
+ and delete the address after deleting the VPN routes.
+
+2008-11-06 Yvan Vanhullebus <vanhu@netasq.com>
+
+ * src/racoon/sainfo.c: fixed delsainfo() to avoid a crash when
+ iddst's value is SAINFO_CLIENTADDR
+
+2008-10-29 S.P.Zeidler <spz@netbsd.org>
+
+ * src/racoon/ipsec_doi.c: Changes to ipsecdoi_id2str():
+
+ struct sockaddr -> struct sockaddr_storage fixes a stack overflow
+
+ For non-linklocal addresses the value in 'scope' is garbage and gets
+ set to zero instead.
+
+2008-10-27 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/pfkey.c: From Arnaud Ebalard: Add missing return to
+ error path
+
+ * src/racoon/grabmyaddr.c: From Francis Dupont (sent by Arnaud
+ Ebalard): recognize RTM_IFANNOUNCE
+
+ * src/racoon/grabmyaddr.c: From Arnaud Ebalard: Fix indentation
+ issues for readability
+
+ * src/racoon/session.c: From Arnaud Ebalard: initfds() needs to be
+ called only if monitored file descriptor numbers have changed
+
+ * src/racoon/isakmp_var.h: From Arnaud Ebalard: Remove duplicate
+ declaration
+
+2008-10-23 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/: privsep.c, session.c, session.h: From Krzysztof
+ Piotr Oledzki <olel@ans.pl>: Revert parts of 2008-08-06 commit; the
+ problem those changes address are already handled in a sensible way
+ by Cyrus Rahman's patch from 2008-03-06.
+
+2008-10-09 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/isakmp_quick.c: From Arnaud Ebalard: remove
+ unnecessary unbindph12() call which is now done in remph2()
+
2008-09-25 Yvan Vanhullebus <vanhu@netasq.com>
* src/racoon/isakmp.c: Fixed resending mechanism to have non-ESP
marker for retransmitted packets
+2008-09-19 Thomas Klausner <wiz@netbsd.org>
+
+ * src/racoon/racoon.conf.5: New sentence, new line.
+
+2008-09-19 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/: admin.c, cfparse.y, cftoken.l, handler.c, handler.h,
+ isakmp.c, isakmp_cfg.c, isakmp_inf.c, isakmp_quick.c,
+ isakmp_var.h, isakmp_xauth.c, pfkey.c, proposal.c, racoon.conf.5,
+ remoteconf.c, remoteconf.h: Implement ISAKMP SA rekeying
+ configurable with rekey {on|off|force} option in remote conf.
+
+ * src/racoon/: handler.c, handler.h, isakmp.c, isakmp_inf.c,
+ isakmp_quick.c, isakmp_var.h, isakmp_xauth.c, isakmp_xauth.h,
+ nattraversal.c, pfkey.c, pfkey.h, schedule.c, schedule.h,
+ session.c: Change struct sched to be allocated be the caller to
+ avoid some memory allocations. Optimize scheduling algorithm to not
+ scan all entries in the main loop.
+
2008-09-17 Yvan Vanhullebus <vanhu@netasq.com>
* src/racoon/isakmp_inf.c: Fixed port match in purge_ipsec_spi()
when NAT-T enabled and trying to purge non NAT-T SAs
+2008-09-09 Yvan Vanhullebus <vanhu@netasq.com>
+
+ * src/racoon/pfkey.c: Some calls to set_port() were not correctly
+ updated in the previous commit
+
+2008-09-03 Yvan Vanhullebus <vanhu@netasq.com>
+
+ * src/racoon/pfkey.c: From Tomas Mraz: Duplicate addresses in
+ pk_sendxxx functions, as they may be altered for NAT-T stuff.
+
+2008-09-03 Timo Teras <timo.teras@iki.fi>
+
+ * src/: libipsec/pfkey.c, racoon/pfkey.c, racoon/sockmisc.c:
+ - Fix reloading of SPD (Linux satype check, handling of SPD dump
+ responses)
+ - Remove some spurious error log message from extract_port()
+
+2008-08-29 Gregory McGarry <gmcgarry@netbsd.org>
+
+ * src/racoon/isakmp.c: Eliminate gcc-specific feature of empty
+ structures.
+
+ * src/racoon/evt.h: Eliminate superfluous semicolon.
+
+ * src/racoon/: admin.c, admin.h: Eliminate gcc-specific feature of
+ unnamed structures added recently.
+
2008-08-12 Yvan Vanhullebus <vanhu@netasq.com>
- * src/racoon/isakmp.c: From Krzysztof Oledzki: Remove ph1handler if
- we received an invalid first exchange from initiator.
+ * src/racoon/isakmp.c: From Krzysztof Piotr Oledzki: Remove
+ ph1handler if we received an invalid first exchange from initiator.
-2008-07-23 tag ipsec-tools-0_7_1
+2008-08-06 Timo Teras <timo.teras@iki.fi>
-2008-07-23 Yvan Vanhullebus <vanhu@netasq.com>
+ * src/racoon/: privsep.c, session.c, session.h: From Krzysztof
+ Piotr Oledzki: Make privileged process exit if unprivileged process
+ is terminated and some spelling fixes.
- * NEWS: NEWS for 0.7.1 release
+2008-07-23 Matthew Grooms <mgrooms@shrew.net>
+
+ * src/racoon/: cfparse.y, session.c: Add some missing ifdefs
+ required for non-radius enabled builds.
2008-07-23 Timo Teras <timo.teras@iki.fi>
@@ -114,16 +1029,30 @@
2008-07-22 Yvan Vanhullebus <vanhu@netasq.com>
- * configure.ac: 0.7.1 coming !
-
* src/racoon/proposal.c: From Kohki Ohhira: fix some memory leaks,
when malloc fails or when peer sends invalid proposal.
-2008-07-21 Timo Teras <timo.teras@iki.fi>
+2008-07-22 Matthew Grooms <mgrooms@shrew.net>
+
+ * src/racoon/: cfparse.y, cftoken.l, isakmp_cfg.c, isakmp_xauth.c,
+ isakmp_xauth.h, main.c, racoon.conf.5, session.c: Add an optional
+ radius configuration section to the racoon.conf file. This is
+ similar to the the LDAP configuration section and overrides settings
+ in the system radius configuration file.
+
+2008-07-21 Matthias Scheler <tron@netbsd.org>
* src/racoon/cfparse.y: Correct typo to fix the build.
- * src/racoon/cfparse.y: Do not set default gss id if xauth is used.
+2008-07-21 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/: isakmp_agg.c, isakmp_base.c, isakmp_ident.c,
+ vendorid.c, vendorid.h: Separate generic vendor id handling to a
+ new function and use it.
+
+ * src/racoon/cfparse.y: Do not set default gss id if xauth is used,
+ otherwise gss-id attribute might be sent even if it was not
+ requested.
2008-07-15 Matthew Grooms <mgrooms@shrew.net>
@@ -134,6 +1063,17 @@
racoonctl.c: Fix a conflict with the FreeBSD 8 system hexdump
function.
+2008-07-14 Timo Teras <timo.teras@iki.fi>
+
+ * src/racoon/: handler.h, ipsec_doi.c, ipsec_doi.h, isakmp_quick.c,
+ pfkey.c: Handle RESPONDER-LIFETIME notification in quick mode.
+
+ * src/racoon/: handler.h, isakmp.c, isakmp_agg.c, isakmp_ident.c,
+ isakmp_inf.c, isakmp_inf.h, isakmp_quick.c, strnames.c: Clean up
+ notification payload handling. Handle INITIAL-CONTACT notification
+ in last main mode exchange (delayed) and during quick mode
+ exchanges.
+
2008-07-11 Timo Teras <timo.teras@iki.fi>
* src/racoon/: isakmp.c, isakmp_inf.c: Original patch from Atis
@@ -147,48 +1087,125 @@
2008-07-02 Yvan Vanhullebus <vanhu@netasq.com>
- * src/racoon/isakmp_inf.c: From Timo Teras: fixed some %d to %zu
- (size_t values).
+ * src/racoon/isakmp_inf.c: From Timo Teras: fix some %d to %zu
+ (size_t values)
+
+2008-06-18 Thomas Klausner <wiz@netbsd.org>
+
+ * src/racoon/racoonctl.8: Bump date for previous.
2008-06-18 Matthew Grooms <mgrooms@shrew.net>
- * src/racoon/: grabmyaddr.c, admin.c, ipsec_doi.c, isakmp.c,
- isakmp_cfg.c, isakmp_inf.c, remoteconf.c: Use utility functions
- to evaluate and manipulate network port values. No functional
- changes. Submitted by Timo Teras.
+ * src/racoon/: admin.c, admin.h, racoonctl.8, racoonctl.c: Add an
+ admin port command to retrieve the peer certificate. Submitted by
+ Timo Teras.
+
+ * src/racoon/: admin.c, grabmyaddr.c, isakmp.c, misc.c, misc.h: Set
+ sockets to be closed on exec to avoid potential file descriptor
+ inheritance issues. Submitted by Timo Teras.
+
+ * src/racoon/: admin.c, grabmyaddr.c, ipsec_doi.c, isakmp.c,
+ isakmp_cfg.c, isakmp_inf.c, privsep.c, remoteconf.c: Use utility
+ functions to evaluate and manipulate network port values. No
+ functional changes. Submitted by Timo Teras.
+
+ * src/racoon/: admin.c, racoonctl.c: Admin port code cleanup. No
+ functional changes. Submitted by Timo Teras.
+
+ * src/racoon/pfkey.c: Correct a phase2 status event. Submitted by
+ Timo Teras.
+
+2008-05-24 Christos Zoulas <christos@netbsd.org>
+
+ * src/racoon/privsep.c: Coverity CID 5018: Fix double frees.
+
+2008-05-08 Emmanuel Dreyfus <manu@netbsd.org>
+
+ * configure.ac: From Christian Hohnstaedt: allow out of tree
+ building
+
+2008-04-30 Martin Husemann <martin@netbsd.org>
+
+ * netbsd-import.sh: Convert TNF licenses to new 2 clause variant
2008-04-25 Yvan Vanhullebus <vanhu@netasq.com>
* src/racoon/isakmp_inf.c: From Timo Teras: extract port numbers
from SADB_X_EXT_NAT_T[SD]PORT if present in purge_ipsec_spi().
+2008-04-13 Christos Zoulas <christos@netbsd.org>
+
+ * src/racoon/privsep.c: for symmetry set controllen the same way we
+ set it on the receiving side.
+
+2008-04-02 Emmanuel Dreyfus <manu@netbsd.org>
+
+ * src/racoon/: Makefile.am, sockmisc.c, sockmisc.h: fix Linux build
+
+2008-03-28 Christos Zoulas <christos@netbsd.org>
+
+ * src/racoon/privsep.c: properly fix the variable stack allocation
+ code.
+
+2008-03-28 Emmanuel Dreyfus <manu@netbsd.org>
+
+ * src/racoon/privsep.c: Still from Cyrus Rahman: fix file
+ descriptor leak introduced by previous commit.
+
+ * src/racoon/: Makefile.am, isakmp.c, isakmp_inf.c, privsep.c,
+ privsep.h, sockmisc.c, doc/README.privsep: From Cyrus Rahman:
+ Allow interface reconfiguration when running in privilege separation
+ mode, document privilege separation
+
2008-03-06 Yvan Vanhullebus <vanhu@netasq.com>
* src/racoon/oakley.c: Generates a log if cert validation has been
disabled by configuration
+2008-03-06 Emmanuel Dreyfus <manu@netbsd.org>
+
+ * src/racoon/: privsep.c, session.c: From Cyrus Rahman
+ <crahman@gmail.com> privilegied instance exit when unprivilegied one
+ terminates. Save PID in real root, not in chroot
+
+2008-03-06 Matthew Grooms <mgrooms@shrew.net>
+
+ * src/racoon/: admin.c, isakmp.c, isakmp_var.h, pfkey.c,
+ racoonctl.8, racoonctl.c: Add the ability to initiate IPsec SA
+ negotiations using the admin socket. Submitted by Timo Teras.
+
+ * src/racoon/: admin.c, admin.h, evt.c, evt.h, handler.c,
+ handler.h, isakmp.c, isakmp_agg.c, isakmp_base.c, isakmp_cfg.c,
+ isakmp_ident.c, isakmp_inf.c, isakmp_var.h, isakmp_xauth.c,
+ racoonctl.8, racoonctl.c, session.c: Refactor admin socket event
+ protocol to be less error prone. Backwards compatibility is
+ provided. Submitted by Timo Teras.
+
2008-03-05 Matthew Grooms <mgrooms@shrew.net>
* src/racoon/cfparse.y: Properly initialize the unity network
struct to prevent erroneous protocol and port info from being
transmitted.
- * src/racoon/pfkey.c: Provide better handling for pfkey socket read
+ * src/racoon/: pfkey.c, pfkey.h, session.c: Reload SPD on SIGHUP or
+ adminport reload. Also provide better handling for pfkey socket read
errors. Submitted by Timo Teras.
2008-02-25 Emmanuel Dreyfus <manu@netbsd.org>
- * src/racoon/ipsec_doi.c: From Brian Haley <brian.haley@hp.com>:
+ * src/racoon/ipsec_doi.c: From Brian Haley <brian.haley@hp.com>
There's a cut/paste error in cmp_aproppair_i(), it's supposed to be
checking spi_size but it's not. I'm not sure this patch is correct,
but what's there isn't either.
- Add fogotten entry in ChangeLog
-
2008-02-22 Emmanuel Dreyfus <manu@netbsd.org>
- * src/racoon/isakmp.c: Fix bad address length computation, from
- Brian Haley.
+ * src/racoon/isakmp.c: Fix address length, from Brian Haley
+
+2008-02-10 S.P.Zeidler <spz@netbsd.org>
+
+ * src/racoon/ipsec_doi.c: closes PR bin/37644 did not meet violent
+ opposition ( :) ) on ipsec-tools-devel
2008-01-11 Yvan Vanhullebus <vanhu@netasq.com>
@@ -208,12 +1225,58 @@
* src/racoon/: handler.c, handler.h: added an 'established' arg to
getph1byaddr()
+2007-12-31 Matthew Grooms <mgrooms@shrew.net>
+
+ * src/racoon/: policy.c, racoonctl.8, racoonctl.c: Add GRE protocol
+ number to racoonctl. Correct id wildcard matching for transport
+ mode. Submitted by Timo Teras.
+
+2007-12-12 Matthew Grooms <mgrooms@shrew.net>
+
+ * NEWS, src/racoon/isakmp_quick.c: Add corrections submitted in a
+ follow up patch for the nat-t oa support.
+
+ * src/racoon/: handler.c, handler.h, isakmp_quick.c, pfkey.c: Add
+ support for nat-t oa payload handling. Submitted by Timo Teras.
+
+2007-12-04 Matthew Grooms <mgrooms@shrew.net>
+
+ * src/racoon/: ipsec_doi.c, ipsec_doi.h, isakmp_quick.c: Modify
+ ipsecdoi_sockaddr2id() to obtain an id without specifying the exact
+ prefix length. Correct a memory leak in phase2. Both submitted by
+ Timo Teras.
+
+2007-12-01 Thomas Klausner <wiz@netbsd.org>
+
+ * src/racoon/racoon.conf.5: Fix typos. New sentence, new line.
+
2007-11-29 Yvan Vanhullebus <vanhu@netasq.com>
* src/racoon/Makefile.am: From Natanael Copa: fixed a race
condition when building yacc stuff.
-2007-11-06 Yvan Vanhullebus <vanhu@netasq.com>
+2007-11-09 Yvan Vanhullebus <vanhu@netasq.com>
+
+ * src/racoon/pfkey.c: From Arnaud Ebalard: Some sanity checking in
+ pk_recv()
+
+ * src/racoon/policy.c: From Arnaud Ebalard: Better matching of SPD
+ entries in getsp_r().
+
+ * src/racoon/isakmp_quick.c: From Arnaud Ebalard: Added some debug
+ in get_proposal_r().
+
+2007-10-19 Emmanuel Dreyfus <manu@netbsd.org>
+
+ * src/racoon/: isakmp_cfg.c, isakmp_unity.c, isakmp_unity.h,
+ racoon.conf.5: Add SPLITNET_{INCLUDR_LOCAL}_CIDR to hook scripts
+
+2007-10-15 Yvan Vanhullebus <vanhu@netasq.com>
+
+ * src/libipsec/pfkey.c: Try to increase the buffer size of the
+ pfkey socket, this may help things when we have a huge SPD
+
+2007-10-02 Yvan Vanhullebus <vanhu@netasq.com>
* src/racoon/crypto_openssl.c: From Scott Lamb: include plog.h to
work with the new plog macro.
@@ -223,34 +1286,53 @@
* src/racoon/: plog.c, plog.h: From Scott Lamb: new plog macro.
-2007-10-15 Yvan Vanhullebus <vanhu@netasq.com>
+2007-09-19 Matthew Grooms <mgrooms@shrew.net>
- * src/libipsec/pfkey.c: Try to increase the buffer size of the
- pfkey socket, this may help things when we have a huge SPD
+ * src/racoon/isakmp.c: Set REUSE option on sockets to prevent
+ failures associated with closing and immediately re-opening.
+ Submitted by Gabriel Somlo.
-2007-09-19 Matthew Grooms <mgrooms@shrew.net>
+ * src/racoon/isakmp_unity.c: Prevent duplicate entries in splitnet
+ list. Submitted by Gabriel Somlo.
+
+2007-09-13 Matthew Grooms <mgrooms@shrew.net>
* configure.ac: Fix autoconf check for selinux support. Submitted
by Joy Latten.
+2007-09-12 Matthew Grooms <mgrooms@shrew.net>
+
+ * src/racoon/: cfparse.y, cftoken.l, handler.c, isakmp_quick.c,
+ pfkey.c, racoon.conf.5, sainfo.c, sainfo.h: Implement clientaddr
+ sainfo remote id option and refine the sainfo man page syntax.
+
+2007-09-05 Matthew Grooms <mgrooms@shrew.net>
+
+ * src/racoon/sainfo.c: Sort sainfo sections on insert and improve
+ matching logic.
+
2007-09-03 Matthew Grooms <mgrooms@shrew.net>
* src/racoon/: cftoken.l, racoon.conf.5: Correct the syntax for
wins4 in the man page and add nbns4 as an alias. Pointed out by
Claas Langbehn.
-2007-08-09 tag ipsec-tools-0_7
+2007-08-07 Emmanuel Dreyfus <manu@netbsd.org>
-2007-08-09 Matthew Grooms <mgrooms@shrew.net>
+ * src/racoon/isakmp_xauth.c: src/racoon/isakmp_xauth.c: Don't mix
+ up RADIUS authentication and authorization ports. Allow
+ interoperability with freeradius
- * NEWS, configure.ac: Prepare for 0.7 release tag.
+2007-07-24 Matthew Grooms <mgrooms@shrew.net>
-2007-08-07 Emmanuel Dreyfus <manu@netbsd.org>
+ * NEWS: Update NEWS file with additional 0.7 improvements.
- * src/racoon/isakmp_xauth.c: Don't mix up RADIUS authentication and
- authorization ports. Allow interoperability with freeradius
+2007-07-18 Matthew Grooms <mgrooms@shrew.net>
-2007-08-01 Yvan Vanhullebus <vanhu@netasq.com>
+ * src/racoon/racoon.conf.5: Various racoon configuration manpage
+ updates.
+
+2007-07-18 Yvan Vanhullebus <vanhu@netasq.com>
* configure.ac, src/libipsec/ipsec_dump_policy.c,
src/libipsec/ipsec_get_policylen.c,
@@ -269,58 +1351,50 @@
src/setkey/token.l: use a single PATH_IPSEC_H to fix some
path_to_ipsec.h issues
-2007-07-24 Matthew Grooms <mgrooms@shrew.net>
-
- * NEWS: Update NEWS file with additional 0.7 improvements.
-
-2007-07-18 Matthew Grooms <mgrooms@shrew.net>
-
- * src/racoon/racoon.conf.5: Various racoon configuration manpage
- updates.
-
2007-07-16 Yvan Vanhullebus <vanhu@netasq.com>
* src/racoon/grabmyaddr.c: fixed a socket leak
-2007-06-12 tag ipsec-tools-0_7-RC1
-
-2007-06-12 tag ipsec-tools-0_7-rc1
-
-2007-06-12 Emmanuel Dreyfus <manu@netbsd.org>
-
- * configure.ac: ipsec-tools used to use tags in lower case
-
-2007-06-12 Yvan Vanhullebus <vanhu@netasq.com>
-
- * configure.ac: 0.7-RC1
+ * src/racoon/proposal.c: indentation
2007-06-07 Emmanuel Dreyfus <manu@netbsd.org>
- * src/racoon/: main.c, policy.h, security.c: From Joy Latten
- <latten@austin.ibm.com> Fix file descriptor shortage when using
- labeled IPsec.
-
* src/racoon/isakmp_cfg.c: From Paul Winder
- <Paul.Winder@tadpole.com> Fix ignored INTERNAL_DNS4_LIST
+ <Paul.Winder@tadpole.com>: Fix ignored INTERNAL_DNS4_LIST
2007-06-06 Yvan Vanhullebus <vanhu@netasq.com>
* src/racoon/: eaytest.c, var.h: From Rong-En Fan: fix compilation
with gcc 4.2
-2007-06-06 Emmanuel Dreyfus <manu@netbsd.org>
-
- * src/racoon/kmpstat.c: From Jianli Liu <jlliu@nortel.com>: Use the
- specified socket path instead of the default location
-
-2007-06-06 Yvan Vanhullebus <vanhu@netasq.com>
-
* src/racoon/session.c: From Jianli Liu: speed up interfaces update
when they change.
* src/racoon/handler.c: ignore obsolete lifebyte when validating
reloaded configuration
+2007-05-31 Emmanuel Dreyfus <manu@netbsd.org>
+
+ * src/racoon/: main.c, policy.h, security.c: From Joy Latten
+ <latten@austin.ibm.com> Fix file descriptor shortage when using
+ labeled IPsec.
+
+2007-05-30 Emmanuel Dreyfus <manu@netbsd.org>
+
+ * src/racoon/kmpstat.c: From Jianli Liu <jlliu@nortel.com>: In
+ racoonctl, use the specified socket path instead of the default
+ location
+
+2007-05-16 Christos Zoulas <christos@netbsd.org>
+
+ * src/racoon/cfparse.y: coverity CID 4168: yyerror() does not
+ return, so we proceed to de-reference NULL. Make it return -1
+ instead like in other places.
+
+ * src/racoon/cfparse.y: coverity CID 4170: yyerror() does not
+ return, so we proceed to de-reference NULL. Make it return -1
+ instead like in other places.
+
2007-05-04 Yvan Vanhullebus <vanhu@netasq.com>
* src/racoon/handler.c: search a ph1 by address if iph2->ph1 is
@@ -345,18 +1419,17 @@
* src/racoon/oakley.c: dumps peer's ID and peer's certificate
subject /subjectaltname if they don't match
-2007-03-29 tag ipsec-tools-0_7-beta3
-
-2007-03-29 Emmanuel Dreyfus <manu@netbsd.org>
-
- * configure.ac: Bump to 0.7beta3
-
2007-03-26 Yvan Vanhullebus <vanhu@netasq.com>
* src/racoon/isakmp_inf.c: Store the DPD main scheduler in ph1
handler, to be able to cancel it when removing the handler, and some
minor cleanups in DPD code
+2007-03-24 Christos Zoulas <christos@netbsd.org>
+
+ * src/racoon/isakmp_xauth.c: PR/36069: Huang Yushuo: racoon can't
+ work with pam_group Set RUSER.
+
2007-03-23 Yvan Vanhullebus <vanhu@netasq.com>
* src/racoon/: ipsec_doi.c, security.c: From Joy Latten: fix a
@@ -389,13 +1462,7 @@
* src/racoon/isakmp.c: Consider a negociation timeout when
retry_counter is <=0 instead of < 0
-2007-03-06 tag ipsec-tools-0_7-beta2
-
-2007-03-06 Emmanuel Dreyfus <manu@netbsd.org>
-
- * configure.ac: Bump to 0.7beta2
-
-2007-03-01 Matthew Grooms <mgrooms@shrew.net>
+2007-02-28 Matthew Grooms <mgrooms@shrew.net>
* src/racoon/ipsec_doi.c: Add logic to allow ip address ids to be
matched to ip subnet ids when appropriate.
@@ -423,12 +1490,6 @@
* src/racoon/isakmp.c: Removed a debug printf....
-2007-02-16 tag ipsec-tools-0_7-beta1
-
-2007-02-16 Emmanuel Dreyfus <manu@netbsd.org>
-
- * configure.ac: Bump to 0.7beta1
-
2007-02-16 Yvan Vanhullebus <vanhu@netasq.com>
* src/racoon/ipsec_doi.c: From Olivier Warin: Fix a %zu in a
@@ -436,7 +1497,7 @@
2007-02-15 Emmanuel Dreyfus <manu@netbsd.org>
- * src/racoon/security.c: Missing file for SELinux
+ * src/racoon/security.c: Missing SELinux file
* configure.ac: Missing stuff for SELinux
@@ -460,6 +1521,20 @@
deleted from payload instead of just deleting the ISAKMP SA used to
protect the informational exchange.
+2006-12-26 Arnaud Lacombe <alc@netbsd.org>
+
+ * src/racoon/ipsec_doi.c: CID-4167: check for 'iph1->approval !=
+ NULL'
+
+2006-12-23 Thomas Klausner <wiz@netbsd.org>
+
+ * src/racoon/racoon.conf.5: Use even more macros.
+
+ * src/racoon/racoon.conf.5: Use more macros.
+
+ * src/racoon/racoon.conf.5: Serial comma, and bump date for
+ previous.
+
2006-12-18 Yvan Vanhullebus <vanhu@netasq.com>
* src/racoon/crypto_openssl.c: From Joy Latten: fix a memory leak
diff --git a/Makefile b/Makefile
index 52d3187..06e2a39 100644
--- a/Makefile
+++ b/Makefile
@@ -3,6 +3,10 @@ all:
-Isrc/racoon -Isrc/racoon/missing -DHAVE_CONFIG_H -lcrypto \
src/libipsec/pfkey.c \
src/libipsec/ipsec_strerror.c \
+ src/racoon/algorithm.c \
+ src/racoon/crypto_openssl.c \
+ src/racoon/genlist.c \
+ src/racoon/handler.c \
src/racoon/isakmp.c \
src/racoon/isakmp_agg.c \
src/racoon/isakmp_base.c \
@@ -11,21 +15,18 @@ all:
src/racoon/isakmp_inf.c \
src/racoon/isakmp_newg.c \
src/racoon/isakmp_quick.c \
- src/racoon/handler.c \
- src/racoon/pfkey.c \
- src/racoon/ipsec_doi.c \
+ src/racoon/ipsec_doi-0.7.3.c \
+ src/racoon/nattraversal.c \
src/racoon/oakley.c \
- src/racoon/vendorid.c \
+ src/racoon/pfkey.c \
src/racoon/policy.c \
- src/racoon/crypto_openssl.c \
- src/racoon/algorithm.c \
src/racoon/proposal.c \
- src/racoon/strnames.c \
+ src/racoon/remoteconf.c \
src/racoon/schedule.c \
+ src/racoon/sockmisc.c \
src/racoon/str2val.c \
- src/racoon/genlist.c \
+ src/racoon/strnames.c \
+ src/racoon/vendorid.c \
src/racoon/vmbuf.c \
- src/racoon/sockmisc.c \
- src/racoon/nattraversal.c \
main.c \
setup.c
diff --git a/NEWS b/NEWS
index 29ce752..6193c65 100644
--- a/NEWS
+++ b/NEWS
@@ -1,36 +1,38 @@
Version history:
----------------
-
-0.7.3 - 23 August 2009
- o Fix a remote crash and a memory leak
- o Fixed a NAT-T flag check
- o Some code cleanups/compilation fixes with recent gcc
-
-0.7.2 - 22 April 2009
- o Fix a remote crash in fragmentation code
- o Phase2 message identities are phase1 specific (Vista compatibility=
- o Autogenerate ChangeLog from cvs metadata
- o Fix mode config pool resizing
- o NAT-T fixes related to purging of IPsec SA:s and retransmission
- o Remove phase1 handler immediately if first exchange is bad
- o A bunch of memory leak and possible memory corruptions (triggerable
- by bad configuration or startup parameters)
-
-0.7.1 - 23 July 2008
+0.8 - 18 March 2011
+ o Fix authentication method ambiguity with kerberos and xauth
+ o RFC2253 compliant escaping of asn1dn identifiers (Cyrus Rahman)
+ o Local address code rewrite to speed things up
+ o Improved MIPv6 support (Arnaud Ebalard)
+ o ISAKMP SA (phase1) rekeying
+ o Improved scheduler (faster algorithm, support monotonic clock)
+ o Handle RESPONDER-LIFETIME in quick mode
+ o Handle INITIAL-CONTACT in from main mode too
+ o Rewritten event handling framework for admin port
+ o Ability to initiate IPsec SA through admin port
+ o NAT-T Original Address handling (transport mode NAT-T support)
+ o clean NAT-T - PFkey support
+ o support for multiple anonymous remoteconfs
+ o Remove various obsolete configuration options
+ o A lot of other bug fixes, performance improvements and clean ups
+
+0.7.1 - 23 July 2008
o Fixes a memory leak when invalid proposal received
o Some fixes in DPD
o do not set default gss id if xauth is used
o fixed hybrid enabled builds
o fixed compilation on FreeBSD8
o cleanup in network port value manipulation
- o gets ports from SADB_X_EXT_NAT_T_[SD]PORT if present in purge_ipsec_spi()
- o Generates a log if cert validation has been disabled by configuration
+ o Gets ports from SADB_X_EXT_NAT_T_[SD]PORT if present in
+ purge_ipsec_spi()
+ o Generates a log if cert validation has been disabled by
+ configuration
o better handling for pfkey socket read errors
o Fixes in yacc / bison stuff
o new plog() macro (reduced CPU usage when logging is disabled)
- o Try to works better with huge SPD/SAD
+ o Try to work better with huge SPD/SAD
o Corrected modecfg option syntax
- o Many other various fixes...
0.7 - 09 August 2007
o Xauth with pre-shared key PSK
@@ -63,7 +65,7 @@ Version history:
o ESP fragmentation in tunnel mode can be tunned (NetBSD only)
o racoon admin interface is exported (header and library) to
help building control programs for racoon (think GUI)
- o Fixed single DES support; single DES users MUST UPGRADE.
+ o Fixed single DES support; single DES users MUST UPGRADE.
0.5 - 10 April 2005
o Rewritten buildsystem. Now completely autoconfed, automaked,
@@ -91,7 +93,7 @@ Version history:
o All source files now have 3-clause BSD license.
0.3 - 14 April 2004
- o Fixed setkey to handle multiline commands again.
+ o Fixed setkey to handle multiline commands again.
o Added command 'exit' to setkey.
o Fixed racoon to only Warn if no CRL was found.
o Improved testsuite.
diff --git a/README b/README
index 2e4f90a..9623997 100644
--- a/README
+++ b/README
@@ -11,20 +11,27 @@ in the Linux 2.6+ kernel. It works as well on NetBSD and FreeBSD.
IPsec-tools were ported to Linux from the KAME project
(http://www.kame.net) by Derek Atkins <derek@ihtfp.com>.
-Currently the package is actively maintained and developed
-by Michal Ludvig <mludvig@suse.cz>, Aidas Kasparas <a.kasparas@gmc.lt>
-Emmanuel Dreyfus <manu@netbsd.org>, VANHULLEBUS Yvan <vanhu@zeninc.net>,
-and Fred Senault <fred.letter@lacave.net>.
+Currently the package is actively maintained and developed by:
+ Emmanuel Dreyfus <manu@netbsd.org>
+ VANHULLEBUS Yvan <vanhu@free.fr>
+ Matthew Grooms <mgrooms@shrew.net>
+ Timo Teräs <timo.teras@iki.fi>
Sources can be found at the IPsec-Tools home page at:
http://ipsec-tools.sourceforge.net/
+And CVS repository is hosted at NetBSD tree:
+ cvs -danoncvs@anoncvs.netbsd.org:/cvsroot co ipsec-tools
+
+Bug reports and project wiki is located at:
+ https://trac.ipsec-tools.net/
+
Please report any problems to the mailing list:
ipsec-tools-devel@lists.sourceforge.net
ipsec-tools-users@lists.sourceforge.net
You can also browse the list archive:
- http://sourceforge.net/mailarchive/forum.php?forum_id=32000
+ http://sf.net/mailarchive/forum.php?forum_name=ipsec-tools-devel
Credits:
IHTFP Consulting, see http://www.ihtfp.com/
diff --git a/ThirdPartyProject.prop b/ThirdPartyProject.prop
index 6ec7936..9af3ed7 100644
--- a/ThirdPartyProject.prop
+++ b/ThirdPartyProject.prop
@@ -1,7 +1,7 @@
-# Copyright 2010 Google Inc. All Rights Reserved.
-#Fri Jul 16 10:03:09 PDT 2010
-currentVersion=0.7.3
-version=0.7.3 (unreleased)
+# Copyright 2011 Google Inc. All Rights Reserved.
+#Tue Jul 5 19:05:36 PDT 2011
+currentVersion=0.8.0
+version=0.8.0
isNative=true
name=ipsec-tools
keywords=ipsec-tools
diff --git a/config.h b/config.h
index fd560d4..87099b5 100644
--- a/config.h
+++ b/config.h
@@ -21,4 +21,6 @@
#define HAVE_SYS_TIME_H 1
#define HAVE_UNISTD_H
+#define RETSIGTYPE void
+
#define ANDROID_PATCHED
diff --git a/main.c b/main.c
index a123afb..c10e32b 100644
--- a/main.c
+++ b/main.c
@@ -16,56 +16,40 @@
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#include <stdarg.h>
#include <signal.h>
+#include <poll.h>
+
+#ifdef ANDROID_CHANGES
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
-#include <sys/select.h>
-
-#ifdef ANDROID_CHANGES
-#include <sys/ioctl.h>
-#include <linux/if.h>
#include <android/log.h>
#include <cutils/sockets.h>
#include <private/android_filesystem_config.h>
-#include "keystore_get.h"
#endif
#include "config.h"
-#include "libpfkey.h"
#include "gcmalloc.h"
-#include "vmbuf.h"
-#include "crypto_openssl.h"
-#include "oakley.h"
-#include "pfkey.h"
+#include "session.h"
#include "schedule.h"
-#include "isakmp_var.h"
-#include "nattraversal.h"
-#include "localconf.h"
-#include "sockmisc.h"
-#include "grabmyaddr.h"
#include "plog.h"
-#include "admin.h"
-#include "privsep.h"
-#include "misc.h"
#ifdef ANDROID_CHANGES
-static int get_control_and_arguments(int *argc, char ***argv)
+static void android_get_arguments(int *argc, char ***argv)
{
static char *args[32];
int control;
int i;
if ((i = android_get_control_socket("racoon")) == -1) {
- return -1;
+ return;
}
do_plog(LLV_DEBUG, "Waiting for control socket");
if (listen(i, 1) == -1 || (control = accept(i, NULL, 0)) == -1) {
do_plog(LLV_ERROR, "Cannot get control socket");
- exit(-1);
+ exit(1);
}
close(i);
@@ -75,7 +59,7 @@ static int get_control_and_arguments(int *argc, char ***argv)
if (recv(control, &bytes[0], 1, 0) != 1
|| recv(control, &bytes[1], 1, 0) != 1) {
do_plog(LLV_ERROR, "Cannot get argument length");
- exit(-1);
+ exit(1);
} else {
int length = bytes[0] << 8 | bytes[1];
int offset = 0;
@@ -90,7 +74,7 @@ static int get_control_and_arguments(int *argc, char ***argv)
offset += n;
} else {
do_plog(LLV_ERROR, "Cannot get argument value");
- exit(-1);
+ exit(1);
}
}
args[i][length] = 0;
@@ -100,38 +84,19 @@ static int get_control_and_arguments(int *argc, char ***argv)
*argc = i;
*argv = args;
- return control;
-}
-
-static void bind_interface()
-{
- struct ifreq ifreqs[64];
- struct ifconf ifconf = {.ifc_len = sizeof(ifreqs), .ifc_req = ifreqs};
- struct myaddrs *p = lcconf->myaddrs;
-
- if (ioctl(p->sock, SIOCGIFCONF, &ifconf) == -1) {
- do_plog(LLV_WARNING, "Cannot list interfaces");
- return;
- }
-
- while (p) {
- int i = ifconf.ifc_len / sizeof(struct ifreq) - 1;
- while (i >= 0 && cmpsaddrwop(p->addr, &ifreqs[i].ifr_addr)) {
- --i;
- }
- if (i < 0 || setsockopt(p->sock, SOL_SOCKET, SO_BINDTODEVICE,
- ifreqs[i].ifr_name, IFNAMSIZ) == -1) {
- do_plog(LLV_WARNING, "Cannot bind socket %d to proper interface",
- p->sock);
- }
- p = p->next;
- }
+ close(control);
}
#endif
extern void setup(int argc, char **argv);
-int f_local = 0;
+
+static int monitor_count;
+static struct {
+ int (*callback)(void *ctx, int fd);
+ void *ctx;
+} monitors[10];
+static struct pollfd pollfds[10];
static void terminate(int signal)
{
@@ -145,69 +110,60 @@ static void terminated()
int main(int argc, char **argv)
{
- fd_set fdset;
- int fdset_size;
- struct myaddrs *p;
-#ifdef ANDROID_CHANGES
- int control = get_control_and_arguments(&argc, &argv);
-#endif
+ do_plog(LLV_INFO, "ipsec-tools 0.8.0 (http://ipsec-tools.sf.net)\n");
signal(SIGHUP, terminate);
signal(SIGINT, terminate);
signal(SIGTERM, terminate);
signal(SIGPIPE, SIG_IGN);
- setup(argc, argv);
-
- do_plog(LLV_INFO, "ipsec-tools 0.7.3 (http://ipsec-tools.sf.net)\n");
atexit(terminated);
- eay_init();
- oakley_dhinit();
- compute_vendorids();
- sched_init();
-
- if (pfkey_init() < 0 || isakmp_init() < 0) {
- exit(1);
- }
-
-#ifdef ENABLE_NATT
- natt_keepalive_init();
-#endif
-
#ifdef ANDROID_CHANGES
- bind_interface();
- setuid(AID_VPN);
+/* setuid(AID_VPN); */
+ android_get_arguments(&argc, &argv);
#endif
-
- FD_ZERO(&fdset);
- FD_SET(lcconf->sock_pfkey, &fdset);
- fdset_size = lcconf->sock_pfkey;
- for (p = lcconf->myaddrs; p; p = p->next) {
- FD_SET(p->sock, &fdset);
- if (fdset_size < p->sock) {
- fdset_size = p->sock;
- }
- }
- ++fdset_size;
+ setup(argc, argv);
while (1) {
- fd_set readset = fdset;
- struct timeval *timeout = schedular();
- if (select(fdset_size, &readset, NULL, NULL, timeout) < 0) {
- exit(1);
- }
- if (FD_ISSET(lcconf->sock_pfkey, &readset)) {
- pfkey_handler();
- }
- for (p = lcconf->myaddrs; p; p = p->next) {
- if (FD_ISSET(p->sock, &readset)) {
- isakmp_handler(p->sock);
+ struct timeval *tv = schedular();
+ int timeout = tv->tv_sec * 1000 + tv->tv_usec / 1000 + 1;
+
+ if (poll(pollfds, monitor_count, timeout) > 0) {
+ int i;
+ for (i = 0; i < monitor_count; ++i) {
+ if (pollfds[i].revents & POLLHUP) {
+ do_plog(LLV_ERROR, "fd %d is closed\n", pollfds[i].fd);
+ exit(1);
+ }
+ if (pollfds[i].revents & POLLIN) {
+ monitors[i].callback(monitors[i].ctx, pollfds[i].fd);
+ }
}
}
}
return 0;
}
+/* session.h */
+
+void monitor_fd(int fd, int (*callback)(void *, int), void *ctx, int priority)
+{
+ if (fd < 0 || monitor_count == 10) {
+ do_plog(LLV_ERROR, "Cannot monitor fd");
+ exit(1);
+ }
+ monitors[monitor_count].callback = callback;
+ monitors[monitor_count].ctx = ctx;
+ pollfds[monitor_count].fd = fd;
+ pollfds[monitor_count].events = POLLIN;
+ ++monitor_count;
+}
+
+void unmonitor_fd(int fd)
+{
+ exit(1);
+}
+
/* plog.h */
void do_plog(int level, char *format, ...)
@@ -245,54 +201,3 @@ char *binsanitize(char *data, size_t length)
}
return output;
}
-
-/* privsep.h */
-
-int privsep_pfkey_open()
-{
- return pfkey_open();
-}
-
-void privsep_pfkey_close(int key)
-{
- pfkey_close(key);
-}
-
-vchar_t *privsep_eay_get_pkcs1privkey(char *file)
-{
- return eay_get_pkcs1privkey(file);
-}
-
-vchar_t *privsep_getpsk(const char *key, int size)
-{
- vchar_t *p = NULL;
- if (key && (p = vmalloc(size)) != NULL) {
- memcpy(p->v, key, p->l);
- }
- return p;
-}
-
-int privsep_script_exec(char *script, int name, char * const *environ)
-{
- return 0;
-}
-
-/* grabmyaddr.h */
-
-int getsockmyaddr(struct sockaddr *addr)
-{
- struct myaddrs *p;
- for (p = lcconf->myaddrs; p; p = p->next) {
- if (cmpsaddrstrict(addr, p->addr) == 0) {
- return p->sock;
- }
- }
- return -1;
-}
-
-/* misc.h */
-
-int racoon_hexdump(void *data, size_t length)
-{
- return 0;
-}
diff --git a/setup.c b/setup.c
index 8bbbf81..eb575ce 100644
--- a/setup.c
+++ b/setup.c
@@ -17,22 +17,29 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netdb.h>
+#include <fcntl.h>
#include "config.h"
+#include "gcmalloc.h"
#include "libpfkey.h"
#include "var.h"
#include "isakmp_var.h"
#include "isakmp.h"
#include "vmbuf.h"
+#include "crypto_openssl.h"
#include "oakley.h"
#include "ipsec_doi.h"
#include "algorithm.h"
#include "vendorid.h"
+#include "schedule.h"
+#include "pfkey.h"
+#include "nattraversal.h"
#include "proposal.h"
#include "sainfo.h"
#include "localconf.h"
@@ -42,71 +49,43 @@
#include "plog.h"
#include "admin.h"
#include "privsep.h"
+#include "misc.h"
-static struct myaddrs myaddrs[2];
-static struct etypes main_mode = { .type = ISAKMP_ETYPE_IDENT };
static struct localconf localconf;
-static struct remoteconf remoteconf;
static struct sainfo sainfo;
static char *pre_shared_key;
-static struct sockaddr target;
+
+static char *interface;
+static struct sockaddr *target;
+static struct {
+ struct sockaddr *addr;
+ int fd;
+} myaddrs[2];
struct localconf *lcconf = &localconf;
char *script_names[SCRIPT_MAX + 1];
+int f_local = 0;
+
+/*****************************************************************************/
-static void set_default()
+static void add_sainfo_algorithm(int class, int algorithm, int length)
{
- localconf.myaddrs = &myaddrs[0];
- localconf.port_isakmp = PORT_ISAKMP;
- localconf.port_isakmp_natt = PORT_ISAKMP_NATT;
- localconf.default_af = AF_INET;
- localconf.pad_random = LC_DEFAULT_PAD_RANDOM;
- localconf.pad_randomlen = LC_DEFAULT_PAD_RANDOM;
- localconf.pad_strict = LC_DEFAULT_PAD_STRICT;
- localconf.pad_excltail = LC_DEFAULT_PAD_EXCLTAIL;
- localconf.retry_counter = 10;
- localconf.retry_interval = 3;
- localconf.count_persend = LC_DEFAULT_COUNT_PERSEND;
- localconf.secret_size = LC_DEFAULT_SECRETSIZE;
- localconf.retry_checkph1 = LC_DEFAULT_RETRY_CHECKPH1;
- localconf.wait_ph2complete = LC_DEFAULT_WAIT_PH2COMPLETE;
- localconf.natt_ka_interval = LC_DEFAULT_NATT_KA_INTERVAL;
- localconf.pathinfo[LC_PATHTYPE_CERT] = "/";
-
- remoteconf.etypes = &main_mode;
- remoteconf.doitype = IPSEC_DOI;
- remoteconf.sittype = IPSECDOI_SIT_IDENTITY_ONLY;
- remoteconf.idvtype = IDTYPE_ADDRESS;
- remoteconf.nonce_size = DEFAULT_NONCE_SIZE;
-
- remoteconf.ike_frag = TRUE;
- remoteconf.esp_frag = IP_MAXPACKET;
- remoteconf.ini_contact = TRUE;
- remoteconf.pcheck_level = PROP_CHECK_OBEY;
- remoteconf.verify_identifier = FALSE;
- remoteconf.verify_cert = TRUE;
- remoteconf.getcert_method = ISAKMP_GETCERT_PAYLOAD;
- remoteconf.certtype = ISAKMP_CERT_X509SIGN;
- remoteconf.getcacert_method = ISAKMP_GETCERT_LOCALFILE;
- remoteconf.cacerttype = ISAKMP_CERT_X509SIGN;
- remoteconf.send_cert = TRUE;
- remoteconf.send_cr = TRUE;
- remoteconf.gen_policy = TRUE;
- remoteconf.retry_counter = LC_DEFAULT_RETRY_COUNTER;
- remoteconf.retry_interval = LC_DEFAULT_RETRY_INTERVAL;
- remoteconf.nat_traversal = TRUE;
- remoteconf.rsa_private = genlist_init();
- remoteconf.rsa_public = genlist_init();
- remoteconf.dpd = TRUE;
- remoteconf.dpd_interval = 0;
- remoteconf.dpd_retry = 5;
- remoteconf.dpd_maxfails = 5;
+ struct sainfoalg *p = calloc(1, sizeof(struct sainfoalg));
+ p->alg = algorithm;
+ p->encklen = length;
- sainfo.lifetime = IPSECDOI_ATTR_SA_LD_SEC_DEFAULT;
- sainfo.lifebyte = IPSECDOI_ATTR_SA_LD_KB_MAX;
+ if (!sainfo.algs[class]) {
+ sainfo.algs[class] = p;
+ } else {
+ struct sainfoalg *q = sainfo.algs[class];
+ while (q->next) {
+ q = q->next;
+ }
+ q->next = p;
+ }
}
-static void set_address(char *server, char *port)
+static void set_globals(char *interfaze, char *server)
{
struct addrinfo hints = {
.ai_flags = AI_NUMERICSERV,
@@ -117,73 +96,60 @@ static void set_address(char *server, char *port)
#endif
.ai_socktype = SOCK_DGRAM,
};
- struct addrinfo *r;
+ struct addrinfo *info;
- if (getaddrinfo(server, port, &hints, &r) != 0) {
- do_plog(LLV_ERROR, "Cannot resolve server address\n");
+ if (getaddrinfo(server, "80", &hints, &info) != 0) {
+ do_plog(LLV_ERROR, "Cannot resolve address: %s\n", server);
exit(1);
}
- if (r->ai_next) {
- do_plog(LLV_WARNING, "Multiple server address found\n");
+ if (info->ai_next) {
+ do_plog(LLV_WARNING, "Found multiple addresses. Use the first one.\n");
}
- remoteconf.remote = dupsaddr(r->ai_addr);
- freeaddrinfo(r);
+ target = dupsaddr(info->ai_addr);
+ freeaddrinfo(info);
- myaddrs[0].addr = getlocaladdr(remoteconf.remote);
+ interface = interfaze;
+ myaddrs[0].addr = getlocaladdr(target);
if (!myaddrs[0].addr) {
do_plog(LLV_ERROR, "Cannot get local address\n");
exit(1);
}
-}
+ set_port(target, 0);
+ set_port(myaddrs[0].addr, 0);
+ myaddrs[0].fd = -1;
+ myaddrs[1].addr = dupsaddr(myaddrs[0].addr);
+ myaddrs[1].fd = -1;
-static void add_proposal(int auth, int hash, int encryption, int length)
-{
- struct isakmpsa *p = calloc(1, sizeof(struct isakmpsa));
- p->prop_no = 1;
- p->lifetime = OAKLEY_ATTR_SA_LD_SEC_DEFAULT;
- p->enctype = encryption;
- p->encklen = length;
- p->authmethod = auth;
- p->hashtype = hash;
- p->dh_group = OAKLEY_ATTR_GRP_DESC_MODP1024;
- p->vendorid = VENDORID_UNKNOWN;
- p->rmconf = &remoteconf;
+ localconf.port_isakmp = PORT_ISAKMP;
+ localconf.port_isakmp_natt = PORT_ISAKMP_NATT;
+ localconf.default_af = AF_INET;
+ localconf.pad_random = LC_DEFAULT_PAD_RANDOM;
+ localconf.pad_randomlen = LC_DEFAULT_PAD_RANDOM;
+ localconf.pad_strict = LC_DEFAULT_PAD_STRICT;
+ localconf.pad_excltail = LC_DEFAULT_PAD_EXCLTAIL;
+ localconf.retry_counter = 10;
+ localconf.retry_interval = 3;
+ localconf.count_persend = LC_DEFAULT_COUNT_PERSEND;
+ localconf.secret_size = LC_DEFAULT_SECRETSIZE;
+ localconf.retry_checkph1 = LC_DEFAULT_RETRY_CHECKPH1;
+ localconf.wait_ph2complete = LC_DEFAULT_WAIT_PH2COMPLETE;
+ localconf.natt_ka_interval = LC_DEFAULT_NATT_KA_INTERVAL;
- if (!remoteconf.proposal) {
- p->trns_no = 1;
- remoteconf.proposal = p;
- } else {
- struct isakmpsa *q = remoteconf.proposal;
- while (q->next) {
- q = q->next;
- }
- p->trns_no = q->trns_no + 1;
- q->next = p;
- }
+ sainfo.lifetime = IPSECDOI_ATTR_SA_LD_SEC_DEFAULT;
+ sainfo.lifebyte = IPSECDOI_ATTR_SA_LD_KB_MAX;
+ add_sainfo_algorithm(algclass_ipsec_auth, IPSECDOI_ATTR_AUTH_HMAC_SHA1, 0);
+ add_sainfo_algorithm(algclass_ipsec_auth, IPSECDOI_ATTR_AUTH_HMAC_MD5, 0);
+ add_sainfo_algorithm(algclass_ipsec_enc, IPSECDOI_ESP_3DES, 0);
+ add_sainfo_algorithm(algclass_ipsec_enc, IPSECDOI_ESP_DES, 0);
+ add_sainfo_algorithm(algclass_ipsec_enc, IPSECDOI_ESP_AES, 128);
}
-static void add_sainfo_algorithm(int class, int algorithm, int length)
-{
- struct sainfoalg *p = calloc(1, sizeof(struct sainfoalg));
- p->alg = algorithm;
- p->encklen = length;
-
- if (!sainfo.algs[class]) {
- sainfo.algs[class] = p;
- } else {
- struct sainfoalg *q = sainfo.algs[class];
- while (q->next) {
- q = q->next;
- }
- q->next = p;
- }
-}
+/*****************************************************************************/
-static int match(struct sadb_address *address)
+static int policy_match(struct sadb_address *address)
{
if (address) {
- struct sockaddr *source = PFKEY_ADDR_SADDR(address);
- return !cmpsaddrwop(source, &target);
+ return cmpsaddr(PFKEY_ADDR_SADDR(address), target) < CMPSADDR_MISMATCH;
}
return 0;
}
@@ -213,8 +179,8 @@ static void flush()
if (p->sadb_msg_errno || pfkey_align(p, q) || pfkey_check(q)) {
continue;
}
- if (match((struct sadb_address *)q[SADB_EXT_ADDRESS_SRC]) ||
- match((struct sadb_address *)q[SADB_EXT_ADDRESS_DST])) {
+ if (policy_match((struct sadb_address *)q[SADB_EXT_ADDRESS_SRC]) ||
+ policy_match((struct sadb_address *)q[SADB_EXT_ADDRESS_DST])) {
p->sadb_msg_type = (p->sadb_msg_type == SADB_DUMP) ?
SADB_DELETE : SADB_X_SPDDELETE;
p->sadb_msg_reserved = 0;
@@ -227,34 +193,68 @@ static void flush()
}
/* flush; spdflush;
- * spdadd local remote udp -P out ipsec esp/transport//require; */
-static void spdadd(struct sockaddr *local, struct sockaddr *remote)
+ * spdadd src dst protocol -P out ipsec esp/transport//require; OR
+ * spdadd src any protocol -P out ipsec esp/tunnel/local-remote/require; */
+static void spdadd(struct sockaddr *src, struct sockaddr *dst,
+ int protocol, struct sockaddr *local, struct sockaddr *remote)
{
struct __attribute__((packed)) {
struct sadb_x_policy p;
struct sadb_x_ipsecrequest q;
+ char addresses[sizeof(struct sockaddr_storage) * 2];
} policy;
- int prefix = (local->sa_family == AF_INET) ? sizeof(struct in_addr) * 8 :
- sizeof(struct in6_addr) * 8;
- int key = pfkey_open();
+ struct sockaddr_storage any = {
+#ifndef __linux__
+ .ss_len = src->sa_len,
+#endif
+ .ss_family = src->sa_family,
+ };
+
+ int src_prefix = (src->sa_family == AF_INET) ? 32 : 128;
+ int dst_prefix = src_prefix;
+ int length = 0;
+ int key;
+
+ /* Fill default values. */
memset(&policy, 0, sizeof(policy));
- policy.p.sadb_x_policy_len = PFKEY_UNIT64(sizeof(policy));
policy.p.sadb_x_policy_exttype = SADB_X_EXT_POLICY;
policy.p.sadb_x_policy_type = IPSEC_POLICY_IPSEC;
policy.p.sadb_x_policy_dir = IPSEC_DIR_OUTBOUND;
#ifdef HAVE_PFKEY_POLICY_PRIORITY
policy.p.sadb_x_policy_priority = PRIORITY_DEFAULT;
#endif
- policy.q.sadb_x_ipsecrequest_len = sizeof(struct sadb_x_ipsecrequest);
policy.q.sadb_x_ipsecrequest_proto = IPPROTO_ESP;
policy.q.sadb_x_ipsecrequest_mode = IPSEC_MODE_TRANSPORT;
policy.q.sadb_x_ipsecrequest_level = IPSEC_LEVEL_REQUIRE;
- target = *remote;
+ /* Deal with tunnel mode. */
+ if (!dst) {
+ policy.q.sadb_x_ipsecrequest_mode = IPSEC_MODE_TUNNEL;
+ dst = (struct sockaddr *)&any;
+ dst_prefix = 0;
+
+ length = sysdep_sa_len(local);
+ memcpy(policy.addresses, local, length);
+ memcpy(&policy.addresses[length], remote, length);
+ length += length;
+
+ /* Use the source address to flush policies. */
+ racoon_free(target);
+ target = dupsaddr(src);
+ }
+
+ /* Fix lengths. */
+ length += sizeof(policy.q);
+ policy.q.sadb_x_ipsecrequest_len = length;
+ length += sizeof(policy.p);
+ policy.p.sadb_x_policy_len = PFKEY_UNIT64(length);
+
+ /* Always do a flush before adding the new policy. */
flush();
- if (pfkey_send_spdadd(key, local, prefix, remote, prefix, IPPROTO_UDP,
- (caddr_t)&policy, sizeof(policy), 0) <= 0) {
+ key = pfkey_open();
+ if (pfkey_send_spdadd(key, src, src_prefix, dst, dst_prefix, protocol,
+ (caddr_t)&policy, length, 0) <= 0) {
do_plog(LLV_ERROR, "Cannot initialize SAD and SPD\n");
exit(1);
}
@@ -262,66 +262,135 @@ static void spdadd(struct sockaddr *local, struct sockaddr *remote)
atexit(flush);
}
-void setup(int argc, char **argv)
+/*****************************************************************************/
+
+static void add_proposal(struct remoteconf *remoteconf,
+ int auth, int hash, int encryption, int length)
{
- int auth;
- if (argc != 4 && argc != 6) {
- printf("Usage: %s server port pre-shared-key\n"
- " %s server port my-private-key my-cert ca-cert\n",
- argv[0], argv[0]);
- exit(0);
- }
- set_default();
+ struct isakmpsa *p = racoon_calloc(1, sizeof(struct isakmpsa));
+ p->prop_no = 1;
+ p->lifetime = OAKLEY_ATTR_SA_LD_SEC_DEFAULT;
+ p->enctype = encryption;
+ p->encklen = length;
+ p->authmethod = auth;
+ p->hashtype = hash;
+ p->dh_group = OAKLEY_ATTR_GRP_DESC_MODP1024;
+ p->vendorid = VENDORID_UNKNOWN;
- /* Set local address and remote address. */
- set_address(argv[1], argv[2]);
+ if (!remoteconf->proposal) {
+ p->trns_no = 1;
+ remoteconf->proposal = p;
+ } else {
+ struct isakmpsa *q = remoteconf->proposal;
+ while (q->next) {
+ q = q->next;
+ }
+ p->trns_no = q->trns_no + 1;
+ q->next = p;
+ }
+}
- /* Initialize SAD and SPD. */
- spdadd(myaddrs[0].addr, remoteconf.remote);
+void setup(int argc, char **argv)
+{
+ struct remoteconf *remoteconf;
+ int auth;
- /* Set local port and remote port. */
- set_port(myaddrs[0].addr, localconf.port_isakmp);
- set_port(remoteconf.remote, localconf.port_isakmp);
+ if (argc > 2) {
+ set_globals(argv[1], argv[2]);
+
+ /* Initialize everything else. */
+ eay_init();
+ initrmconf();
+ oakley_dhinit();
+ compute_vendorids();
+ sched_init();
+ if (pfkey_init() < 0 || isakmp_init() < 0) {
+ exit(1);
+ }
#ifdef ENABLE_NATT
- myaddrs[0].next = &myaddrs[1];
- myaddrs[1].addr = dupsaddr(myaddrs[0].addr);
- set_port(myaddrs[1].addr, localconf.port_isakmp_natt);
- myaddrs[1].udp_encap = 1;
+ natt_keepalive_init();
#endif
- /* Set authentication method. */
- if (argc == 4) {
- pre_shared_key = argv[3];
+ /* Create remote configuration. */
+ remoteconf = newrmconf();
+ remoteconf->etypes = racoon_calloc(1, sizeof(struct etypes));
+ remoteconf->etypes->type = ISAKMP_ETYPE_IDENT;
+ remoteconf->ike_frag = TRUE;
+ remoteconf->pcheck_level = PROP_CHECK_OBEY;
+ remoteconf->gen_policy = TRUE;
+ remoteconf->nat_traversal = TRUE;
+ remoteconf->remote = dupsaddr(target);
+ set_port(remoteconf->remote, localconf.port_isakmp);
+ }
+
+ /* Set authentication method and credentials. */
+ if (argc == 6 && !strcmp(argv[3], "udppsk")) {
+ set_port(target, atoi(argv[4]));
+ spdadd(myaddrs[0].addr, target, IPPROTO_UDP, NULL, NULL);
+ pre_shared_key = argv[5];
+ remoteconf->idvtype = IDTYPE_ADDRESS;
auth = OAKLEY_ATTR_AUTH_METHOD_PSKEY;
- } else {
- remoteconf.idvtype = IDTYPE_ASN1DN;
- remoteconf.myprivfile = argv[3];
- remoteconf.mycertfile = argv[4];
- remoteconf.cacertfile = argv[5];
+ } else if (argc == 8 && !strcmp(argv[3], "udprsa")) {
+ set_port(target, atoi(argv[4]));
+ spdadd(myaddrs[0].addr, target, IPPROTO_UDP, NULL, NULL);
+ remoteconf->myprivfile = argv[5];
+ remoteconf->mycertfile = argv[6];
+ remoteconf->cacertfile = argv[7];
+ remoteconf->idvtype = IDTYPE_ASN1DN;
auth = OAKLEY_ATTR_AUTH_METHOD_RSASIG;
+ } else {
+ printf("Usage: %s <interface> <server> [...],\n"
+ " where [...] can be:\n"
+ " udppsk <port> <pre-shared-key>\n"
+ " udprsa <port> <my-private-key> <my-cert> <ca-cert>\n",
+ argv[0]);
+ exit(0);
}
- /* Create proposals. */
- add_proposal(auth, OAKLEY_ATTR_HASH_ALG_SHA, OAKLEY_ATTR_ENC_ALG_3DES, 0);
- add_proposal(auth, OAKLEY_ATTR_HASH_ALG_MD5, OAKLEY_ATTR_ENC_ALG_3DES, 0);
- add_proposal(auth, OAKLEY_ATTR_HASH_ALG_SHA, OAKLEY_ATTR_ENC_ALG_DES, 0);
- add_proposal(auth, OAKLEY_ATTR_HASH_ALG_MD5, OAKLEY_ATTR_ENC_ALG_DES, 0);
- add_proposal(auth, OAKLEY_ATTR_HASH_ALG_SHA, OAKLEY_ATTR_ENC_ALG_AES, 128);
- add_proposal(auth, OAKLEY_ATTR_HASH_ALG_MD5, OAKLEY_ATTR_ENC_ALG_AES, 128);
-
- /* Create sainfo algorithms. */
- add_sainfo_algorithm(algclass_ipsec_auth, IPSECDOI_ATTR_AUTH_HMAC_SHA1, 0);
- add_sainfo_algorithm(algclass_ipsec_auth, IPSECDOI_ATTR_AUTH_HMAC_MD5, 0);
- add_sainfo_algorithm(algclass_ipsec_enc, IPSECDOI_ESP_3DES, 0);
- add_sainfo_algorithm(algclass_ipsec_enc, IPSECDOI_ESP_DES, 0);
- add_sainfo_algorithm(algclass_ipsec_enc, IPSECDOI_ESP_AES, 128);
+ /* Add proposals. */
+ add_proposal(remoteconf, auth,
+ OAKLEY_ATTR_HASH_ALG_SHA, OAKLEY_ATTR_ENC_ALG_3DES, 0);
+ add_proposal(remoteconf, auth,
+ OAKLEY_ATTR_HASH_ALG_MD5, OAKLEY_ATTR_ENC_ALG_3DES, 0);
+ add_proposal(remoteconf, auth,
+ OAKLEY_ATTR_HASH_ALG_SHA, OAKLEY_ATTR_ENC_ALG_DES, 0);
+ add_proposal(remoteconf, auth,
+ OAKLEY_ATTR_HASH_ALG_MD5, OAKLEY_ATTR_ENC_ALG_DES, 0);
+ add_proposal(remoteconf, auth,
+ OAKLEY_ATTR_HASH_ALG_SHA, OAKLEY_ATTR_ENC_ALG_AES, 128);
+ add_proposal(remoteconf, auth,
+ OAKLEY_ATTR_HASH_ALG_MD5, OAKLEY_ATTR_ENC_ALG_AES, 128);
+
+ /* Install remote configuration. */
+ insrmconf(remoteconf);
+
+ /* Create ISAKMP sockets. */
+ set_port(myaddrs[0].addr, localconf.port_isakmp);
+ myaddrs[0].fd = isakmp_open(myaddrs[0].addr, FALSE);
+ if (myaddrs[0].fd == -1) {
+ do_plog(LLV_ERROR, "Cannot create ISAKMP socket");
+ exit(1);
+ }
+#ifdef ENABLE_NATT
+ set_port(myaddrs[1].addr, localconf.port_isakmp_natt);
+ myaddrs[1].fd = isakmp_open(myaddrs[1].addr, TRUE);
+ if (myaddrs[1].fd == -1) {
+ do_plog(LLV_WARNING, "Cannot create ISAKMP socket for NAT-T");
+ }
+#endif
}
+/*****************************************************************************/
+
/* localconf.h */
vchar_t *getpskbyaddr(struct sockaddr *addr)
{
- return privsep_getpsk(pre_shared_key, strlen(pre_shared_key));
+ vchar_t *p = NULL;
+ if (pre_shared_key && (p = vmalloc(strlen(pre_shared_key)))) {
+ memcpy(p->v, pre_shared_key, p->l);
+ }
+ return p;
}
vchar_t *getpskbyname(vchar_t *name)
@@ -334,61 +403,75 @@ void getpathname(char *path, int length, int type, const char *name)
strncpy(path, name, length);
}
-/* remoteconf.h */
+/* sainfo.h */
-struct remoteconf *getrmconf(struct sockaddr *addr)
+struct sainfo *getsainfo(const vchar_t *src, const vchar_t *dst,
+ const vchar_t *peer, const vchar_t *client, uint32_t remoteid)
{
- return cmpsaddrwop(addr, remoteconf.remote) ? NULL : &remoteconf;
+ return &sainfo;
}
-struct isakmpsa *dupisakmpsa(struct isakmpsa *sa)
+const char *sainfo2str(const struct sainfo *si)
{
- struct isakmpsa *p = NULL;
- if (sa && (p = malloc(sizeof(struct isakmpsa)))) {
- *p = *sa;
- p->next = NULL;
- if (sa->dhgrp) {
- oakley_setdhgroup(sa->dh_group, &p->dhgrp);
- }
- }
- return p;
+ return "*";
}
-void delisakmpsa(struct isakmpsa *sa)
+/* privsep.h */
+
+int privsep_socket(int domain, int type, int protocol)
{
- while (sa) {
- struct isakmpsa *p = sa->next;
- if (sa->dhgrp) {
- oakley_dhgrp_free(sa->dhgrp);
- }
- free(sa);
- sa = p;
+ int fd = socket(domain, type, protocol);
+ if ((domain == AF_INET || domain == AF_INET6) && setsockopt(
+ fd, SOL_SOCKET, SO_BINDTODEVICE, interface, strlen(interface))) {
+ do_plog(LLV_WARNING, "Cannot bind socket to %s", interface);
}
+ return fd;
}
-struct etypes *check_etypeok(struct remoteconf *rmconf, uint8_t etype)
+int privsep_bind(int fd, const struct sockaddr *addr, socklen_t addrlen)
{
- struct etypes *p = rmconf->etypes;
- while (p && etype != p->type) {
- p = p->next;
- }
- return p;
+ return bind(fd, addr, addrlen);
}
-struct remoteconf *foreachrmconf(rmconf_func_t function, void *data)
+vchar_t *privsep_eay_get_pkcs1privkey(char *file)
{
- return (*function)(&remoteconf, data);
+ return eay_get_pkcs1privkey(file);
}
-/* sainfo.h */
+int privsep_script_exec(char *script, int name, char * const *environ)
+{
+ return 0;
+}
-struct sainfo *getsainfo(const vchar_t *src, const vchar_t *dst,
- const vchar_t *peer, int remoteid)
+/* grabmyaddr.h */
+
+int myaddr_getsport(struct sockaddr *addr)
{
- return &sainfo;
+ return 0;
}
-const char *sainfo2str(const struct sainfo *si)
+int myaddr_getfd(struct sockaddr *addr)
{
- return "*";
+#ifdef ENABLE_NATT
+ if (myaddrs[1].fd != -1 &&
+ cmpsaddr(addr, myaddrs[1].addr) == CMPSADDR_MATCH) {
+ return myaddrs[1].fd;
+ }
+#endif
+ if (cmpsaddr(addr, myaddrs[0].addr) < CMPSADDR_MISMATCH) {
+ return myaddrs[0].fd;
+ }
+ return -1;
+}
+
+/* misc.h */
+
+int racoon_hexdump(void *data, size_t length)
+{
+ return 0;
+}
+
+void close_on_exec(int fd)
+{
+ fcntl(fd, F_SETFD, FD_CLOEXEC);
}
diff --git a/src/include-glibc/Makefile.in b/src/include-glibc/Makefile.in
index 842728e..d92fdf6 100644
--- a/src/include-glibc/Makefile.in
+++ b/src/include-glibc/Makefile.in
@@ -1,8 +1,9 @@
-# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
@@ -15,8 +16,9 @@
@SET_MAKE@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
@@ -41,6 +43,7 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
SOURCES =
DIST_SOURCES =
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@@ -58,23 +61,18 @@ CONFIGURE_AMFLAGS = @CONFIGURE_AMFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CRYPTOBJS = @CRYPTOBJS@
-CXX = @CXX@
-CXXCPP = @CXXCPP@
-CXXDEPMODE = @CXXDEPMODE@
-CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DSYMUTIL = @DSYMUTIL@
-ECHO = @ECHO@
+DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
EXTRA_CRYPTO = @EXTRA_CRYPTO@
-F77 = @F77@
-FFLAGS = @FFLAGS@
+FGREP = @FGREP@
FRAG_OBJS = @FRAG_OBJS@
GLIBC_BUGS = @GLIBC_BUGS@
GREP = @GREP@
@@ -88,6 +86,7 @@ INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
KERNEL_INCLUDE = @KERNEL_INCLUDE@
KRB5_CONFIG = @KRB5_CONFIG@
+LD = @LD@
LDFLAGS = @LDFLAGS@
LEX = @LEX@
LEXLIB = @LEXLIB@
@@ -95,18 +94,24 @@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
NATT_OBJS = @NATT_OBJS@
+NM = @NM@
NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@
@@ -124,8 +129,7 @@ abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
-ac_ct_CXX = @ac_ct_CXX@
-ac_ct_F77 = @ac_ct_F77@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -157,6 +161,7 @@ libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
@@ -169,6 +174,7 @@ sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
EXTRA_DIST = \
@@ -185,14 +191,14 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
- && exit 0; \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/include-glibc/Makefile'; \
- cd $(top_srcdir) && \
- $(AUTOMAKE) --foreign src/include-glibc/Makefile
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/include-glibc/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign src/include-glibc/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
@@ -210,6 +216,7 @@ $(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
mostlyclean-libtool:
-rm -f *.lo
@@ -239,13 +246,17 @@ distdir: $(DISTFILES)
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
- cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
- cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
- test -f $(distdir)/$$file \
- || cp -p $$d/$$file $(distdir)/$$file \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
@@ -273,6 +284,7 @@ clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
-test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
maintainer-clean-generic:
@@ -292,6 +304,8 @@ dvi-am:
html: html-am
+html-am:
+
info: info-am
info-am:
@@ -300,18 +314,28 @@ install-data-am:
install-dvi: install-dvi-am
+install-dvi-am:
+
install-exec-am:
install-html: install-html-am
+install-html-am:
+
install-info: install-info-am
+install-info-am:
+
install-man:
install-pdf: install-pdf-am
+install-pdf-am:
+
install-ps: install-ps-am
+install-ps-am:
+
installcheck-am:
maintainer-clean: maintainer-clean-am
@@ -351,6 +375,7 @@ uninstall-am:
touch .includes
all: .includes
+
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
diff --git a/src/libipsec/Makefile.in b/src/libipsec/Makefile.in
index 748877a..cd0993b 100644
--- a/src/libipsec/Makefile.in
+++ b/src/libipsec/Makefile.in
@@ -1,8 +1,9 @@
-# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
@@ -17,8 +18,9 @@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
@@ -45,15 +47,30 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
*) f=$$p;; \
esac;
-am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(man3dir)" \
"$(DESTDIR)$(libipsecdir)"
-libLTLIBRARIES_INSTALL = $(INSTALL)
LTLIBRARIES = $(lib_LTLIBRARIES)
am__DEPENDENCIES_1 =
libipsec_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
@@ -67,6 +84,7 @@ libipsec_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
+am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
@@ -88,7 +106,6 @@ DIST_SOURCES = $(libipsec_la_SOURCES)
man3dir = $(mandir)/man3
NROFF = nroff
MANS = $(man3_MANS)
-libipsecHEADERS_INSTALL = $(INSTALL_HEADER)
HEADERS = $(libipsec_HEADERS) $(noinst_HEADERS)
ETAGS = etags
CTAGS = ctags
@@ -107,23 +124,18 @@ CONFIGURE_AMFLAGS = @CONFIGURE_AMFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CRYPTOBJS = @CRYPTOBJS@
-CXX = @CXX@
-CXXCPP = @CXXCPP@
-CXXDEPMODE = @CXXDEPMODE@
-CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DSYMUTIL = @DSYMUTIL@
-ECHO = @ECHO@
+DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
EXTRA_CRYPTO = @EXTRA_CRYPTO@
-F77 = @F77@
-FFLAGS = @FFLAGS@
+FGREP = @FGREP@
FRAG_OBJS = @FRAG_OBJS@
GLIBC_BUGS = @GLIBC_BUGS@
GREP = @GREP@
@@ -137,6 +149,7 @@ INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
KERNEL_INCLUDE = @KERNEL_INCLUDE@
KRB5_CONFIG = @KRB5_CONFIG@
+LD = @LD@
LDFLAGS = @LDFLAGS@
LEX = @LEX@
LEXLIB = @LEXLIB@
@@ -144,18 +157,24 @@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
NATT_OBJS = @NATT_OBJS@
+NM = @NM@
NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@
@@ -173,8 +192,7 @@ abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
-ac_ct_CXX = @ac_ct_CXX@
-ac_ct_F77 = @ac_ct_F77@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -206,6 +224,7 @@ libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
@@ -218,6 +237,7 @@ sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
@@ -262,14 +282,14 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
- && exit 0; \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/libipsec/Makefile'; \
- cd $(top_srcdir) && \
- $(AUTOMAKE) --foreign src/libipsec/Makefile
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/libipsec/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign src/libipsec/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
@@ -287,23 +307,28 @@ $(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
install-libLTLIBRARIES: $(lib_LTLIBRARIES)
@$(NORMAL_INSTALL)
test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
- @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ list2=; for p in $$list; do \
if test -f $$p; then \
- f=$(am__strip_dir) \
- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
+ list2="$$list2 $$p"; \
else :; fi; \
- done
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
+ }
uninstall-libLTLIBRARIES:
@$(NORMAL_UNINSTALL)
- @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
- p=$(am__strip_dir) \
- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
done
clean-libLTLIBRARIES:
@@ -339,21 +364,21 @@ distclean-compile:
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c $<
.c.obj:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
.c.lo:
@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
@@ -369,82 +394,74 @@ mostlyclean-libtool:
clean-libtool:
-rm -rf .libs _libs
-install-man3: $(man3_MANS) $(man_MANS)
+install-man3: $(man3_MANS)
@$(NORMAL_INSTALL)
test -z "$(man3dir)" || $(MKDIR_P) "$(DESTDIR)$(man3dir)"
- @list='$(man3_MANS) $(dist_man3_MANS) $(nodist_man3_MANS)'; \
- l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
- for i in $$l2; do \
- case "$$i" in \
- *.3*) list="$$list $$i" ;; \
- esac; \
+ @list='$(man3_MANS)'; test -n "$(man3dir)" || exit 0; \
+ { for i in $$list; do echo "$$i"; done; \
+ } | while read p; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; echo "$$p"; \
+ done | \
+ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
+ sed 'N;N;s,\n, ,g' | { \
+ list=; while read file base inst; do \
+ if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man3dir)/$$inst'"; \
+ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man3dir)/$$inst" || exit $$?; \
+ fi; \
done; \
- for i in $$list; do \
- if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
- else file=$$i; fi; \
- ext=`echo $$i | sed -e 's/^.*\\.//'`; \
- case "$$ext" in \
- 3*) ;; \
- *) ext='3' ;; \
- esac; \
- inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
- inst=`echo $$inst | sed -e 's/^.*\///'`; \
- inst=`echo $$inst | sed '$(transform)'`.$$ext; \
- echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man3dir)/$$inst'"; \
- $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man3dir)/$$inst"; \
- done
+ for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+ while read files; do \
+ test -z "$$files" || { \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man3dir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(man3dir)" || exit $$?; }; \
+ done; }
+
uninstall-man3:
@$(NORMAL_UNINSTALL)
- @list='$(man3_MANS) $(dist_man3_MANS) $(nodist_man3_MANS)'; \
- l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
- for i in $$l2; do \
- case "$$i" in \
- *.3*) list="$$list $$i" ;; \
- esac; \
- done; \
- for i in $$list; do \
- ext=`echo $$i | sed -e 's/^.*\\.//'`; \
- case "$$ext" in \
- 3*) ;; \
- *) ext='3' ;; \
- esac; \
- inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
- inst=`echo $$inst | sed -e 's/^.*\///'`; \
- inst=`echo $$inst | sed '$(transform)'`.$$ext; \
- echo " rm -f '$(DESTDIR)$(man3dir)/$$inst'"; \
- rm -f "$(DESTDIR)$(man3dir)/$$inst"; \
- done
+ @list='$(man3_MANS)'; test -n "$(man3dir)" || exit 0; \
+ files=`{ for i in $$list; do echo "$$i"; done; \
+ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+ test -z "$$files" || { \
+ echo " ( cd '$(DESTDIR)$(man3dir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(man3dir)" && rm -f $$files; }
install-libipsecHEADERS: $(libipsec_HEADERS)
@$(NORMAL_INSTALL)
test -z "$(libipsecdir)" || $(MKDIR_P) "$(DESTDIR)$(libipsecdir)"
- @list='$(libipsec_HEADERS)'; for p in $$list; do \
+ @list='$(libipsec_HEADERS)'; test -n "$(libipsecdir)" || list=; \
+ for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
- f=$(am__strip_dir) \
- echo " $(libipsecHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(libipsecdir)/$$f'"; \
- $(libipsecHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(libipsecdir)/$$f"; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libipsecdir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(libipsecdir)" || exit $$?; \
done
uninstall-libipsecHEADERS:
@$(NORMAL_UNINSTALL)
- @list='$(libipsec_HEADERS)'; for p in $$list; do \
- f=$(am__strip_dir) \
- echo " rm -f '$(DESTDIR)$(libipsecdir)/$$f'"; \
- rm -f "$(DESTDIR)$(libipsecdir)/$$f"; \
- done
+ @list='$(libipsec_HEADERS)'; test -n "$(libipsecdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(libipsecdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(libipsecdir)" && rm -f $$files
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
- $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
mkid -fID $$unique
tags: TAGS
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
- tags=; \
+ set x; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
@@ -452,34 +469,52 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
- if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
- $$tags $$unique; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
fi
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
- tags=; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
- test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
- $$tags $$unique
+ $$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
- && cd $(top_srcdir) \
- && gtags -i $(GTAGS_ARGS) $$here
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
+ @list='$(MANS)'; if test -n "$$list"; then \
+ list=`for p in $$list; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \
+ if test -n "$$list" && \
+ grep 'ab help2man is required to generate this page' $$list >/dev/null; then \
+ echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \
+ grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \
+ echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \
+ echo " typically \`make maintainer-clean' will remove them" >&2; \
+ exit 1; \
+ else :; fi; \
+ else :; fi
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
@@ -495,13 +530,17 @@ distdir: $(DISTFILES)
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
- cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
- cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
- test -f $(distdir)/$$file \
- || cp -p $$d/$$file $(distdir)/$$file \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
@@ -534,6 +573,7 @@ clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@@ -559,6 +599,8 @@ dvi-am:
html: html-am
+html-am:
+
info: info-am
info-am:
@@ -567,18 +609,28 @@ install-data-am: install-libipsecHEADERS install-man
install-dvi: install-dvi-am
+install-dvi-am:
+
install-exec-am: install-libLTLIBRARIES
install-html: install-html-am
+install-html-am:
+
install-info: install-info-am
+install-info-am:
+
install-man: install-man3
install-pdf: install-pdf-am
+install-pdf-am:
+
install-ps: install-ps-am
+install-ps-am:
+
installcheck-am:
maintainer-clean: maintainer-clean-am
@@ -604,7 +656,7 @@ uninstall-am: uninstall-libLTLIBRARIES uninstall-libipsecHEADERS \
uninstall-man: uninstall-man3
-.MAKE: install-am install-strip
+.MAKE: all check install install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
clean-libLTLIBRARIES clean-libtool ctags distclean \
@@ -622,6 +674,7 @@ uninstall-man: uninstall-man3
uninstall-am uninstall-libLTLIBRARIES \
uninstall-libipsecHEADERS uninstall-man uninstall-man3
+
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
diff --git a/src/libipsec/ipsec_dump_policy.c b/src/libipsec/ipsec_dump_policy.c
index bdadb47..4d0eb77 100644
--- a/src/libipsec/ipsec_dump_policy.c
+++ b/src/libipsec/ipsec_dump_policy.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ipsec_dump_policy.c,v 1.7.6.1 2007/08/01 11:52:17 vanhu Exp $ */
+/* $NetBSD: ipsec_dump_policy.c,v 1.9 2010/12/03 15:01:11 tteras Exp $ */
/* Id: ipsec_dump_policy.c,v 1.10 2005/06/29 09:12:37 manubsd Exp */
@@ -53,7 +53,10 @@
#include "libpfkey.h"
static const char *ipsp_dir_strs[] = {
- "any", "in", "out", "fwd"
+ "any", "in", "out", "fwd",
+#ifdef __linux__
+ "in(socket)", "out(socket)"
+#endif
};
static const char *ipsp_policy_strs[] = {
@@ -165,6 +168,8 @@ ipsec_dump_policy1(policy, delimiter, withports)
case IPSEC_DIR_OUTBOUND:
#ifdef HAVE_POLICY_FWD
case IPSEC_DIR_FWD:
+ case IPSEC_DIR_FWD + 1:
+ case IPSEC_DIR_FWD + 2:
#endif
break;
default:
diff --git a/src/libipsec/ipsec_get_policylen.c b/src/libipsec/ipsec_get_policylen.c
index 2f4f6e9..5a49778 100644
--- a/src/libipsec/ipsec_get_policylen.c
+++ b/src/libipsec/ipsec_get_policylen.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ipsec_get_policylen.c,v 1.6.6.1 2007/08/01 11:52:17 vanhu Exp $ */
+/* $NetBSD: ipsec_get_policylen.c,v 1.7 2007/07/18 12:07:50 vanhu Exp $ */
/* $KAME: ipsec_get_policylen.c,v 1.5 2000/05/07 05:25:03 itojun Exp $ */
diff --git a/src/libipsec/ipsec_set_policy.3 b/src/libipsec/ipsec_set_policy.3
index 643b582..f3832b5 100644
--- a/src/libipsec/ipsec_set_policy.3
+++ b/src/libipsec/ipsec_set_policy.3
@@ -1,4 +1,4 @@
-.\" $NetBSD: ipsec_set_policy.3,v 1.13 2006/09/09 16:22:09 manu Exp $
+.\" $NetBSD: ipsec_set_policy.3,v 1.15 2010/03/05 06:47:58 tteras Exp $
.\"
.\" $KAME: ipsec_set_policy.3,v 1.16 2003/01/06 21:59:03 sumikawa Exp $
.\"
@@ -124,14 +124,10 @@ be specified when libipsec has been compiled against kernel headers that
support policy priorities (Linux \*[Gt]= 2.6.6).
It takes one of the following formats:
.Bl -tag -width "discard"
-.It Xo
-.Ar {priority,prio} offset
-.Xc
+.It Ar {priority,prio} offset
.Ar offset
-is an integer in the range -2147483647..214783648.
-.It Xo
-.Ar {priority,prio} base {+,-} offset
-.Xc
+is an integer in the range \-2147483647..214783648.
+.It Ar {priority,prio} base {+,-} offset
.Ar base
is either
.Li low (-1073741824) ,
@@ -162,12 +158,7 @@ means to consult the SPD defined by
means to bypass the IPsec processing.
.Pq the packet will be transmitted in clear .
This is for privileged sockets.
-.It Xo
-.Ar direction
-.Bq Ar priority specification
-.Li ipsec
-.Ar request ...
-.Xc
+.It Ar direction Bo Ar priority specification Bc Li ipsec Ar request ...
.Li ipsec
means that the matching packets are subject to IPsec processing.
.Li ipsec
@@ -175,16 +166,7 @@ can be followed by one or more
.Ar request
strings, which are formatted as below:
.Bl -tag -width "discard"
-.It Xo
-.Ar protocol
-.Li /
-.Ar mode
-.Li /
-.Ar src
-.Li -
-.Ar dst
-.Op Ar /level
-.Xc
+.It Ar protocol Li / Ar mode Li / Ar src Li - Ar dst Op Ar /level
.Ar protocol
is either
.Li ah ,
diff --git a/src/libipsec/ipsec_strerror.c b/src/libipsec/ipsec_strerror.c
index ad1ab2a..ca26d0e 100644
--- a/src/libipsec/ipsec_strerror.c
+++ b/src/libipsec/ipsec_strerror.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ipsec_strerror.c,v 1.4.6.1 2007/08/01 11:52:17 vanhu Exp $ */
+/* $NetBSD: ipsec_strerror.c,v 1.6 2010/04/07 14:53:52 vanhu Exp $ */
/* $KAME: ipsec_strerror.c,v 1.7 2000/07/30 00:45:12 itojun Exp $ */
@@ -63,7 +63,7 @@ static const char *ipsec_errlist[] = {
"Invalid key length", /*EIPSEC_INVAL_KEYLEN*/
"Invalid address family", /*EIPSEC_INVAL_FAMILY*/
"Invalid prefix length", /*EIPSEC_INVAL_PREFIXLEN*/
-"Invalid direciton", /*EIPSEC_INVAL_DIR*/
+"Invalid direction", /*EIPSEC_INVAL_DIR*/
"SPI range violation", /*EIPSEC_INVAL_SPI*/
"No protocol specified", /*EIPSEC_NO_PROTO*/
"No algorithm specified", /*EIPSEC_NO_ALGS*/
diff --git a/src/libipsec/key_debug.c b/src/libipsec/key_debug.c
index 60f1602..e381a98 100644
--- a/src/libipsec/key_debug.c
+++ b/src/libipsec/key_debug.c
@@ -1,4 +1,4 @@
-/* $NetBSD: key_debug.c,v 1.7.6.1 2007/08/01 11:52:18 vanhu Exp $ */
+/* $NetBSD: key_debug.c,v 1.9 2008/12/05 06:02:20 tteras Exp $ */
/* $KAME: key_debug.c,v 1.29 2001/08/16 14:25:41 itojun Exp $ */
@@ -91,6 +91,10 @@ static void kdebug_sadb_x_nat_t_port __P((struct sadb_ext *ext));
static void kdebug_sadb_x_packet __P((struct sadb_ext *));
#endif
+#ifdef SADB_X_EXT_KMADDRESS
+static void kdebug_sadb_x_kmaddress __P((struct sadb_ext *));
+#endif
+
#ifdef _KERNEL
static void kdebug_secreplay __P((struct secreplay *));
#endif
@@ -194,6 +198,11 @@ kdebug_sadb(base)
kdebug_sadb_x_packet(ext);
break;
#endif
+#ifdef SADB_X_EXT_KMADDRESS
+ case SADB_X_EXT_KMADDRESS:
+ kdebug_sadb_x_kmaddress(ext);
+ break;
+#endif
default:
printf("kdebug_sadb: invalid ext_type %u was passed.\n",
ext->sadb_ext_type);
@@ -556,6 +565,48 @@ kdebug_sadb_x_packet(ext)
}
#endif
+#ifdef SADB_X_EXT_KMADDRESS
+static void
+kdebug_sadb_x_kmaddress(ext)
+ struct sadb_ext *ext;
+{
+ struct sadb_x_kmaddress *kma = (struct sadb_x_kmaddress *)ext;
+ struct sockaddr * sa;
+ sa_family_t family;
+ int len, sa_len;
+
+ /* sanity check */
+ if (ext == NULL)
+ panic("kdebug_sadb_x_kmaddress: NULL pointer was passed.\n");
+
+ len = (PFKEY_UNUNIT64(kma->sadb_x_kmaddress_len) - sizeof(*kma));
+
+ printf("sadb_x_kmaddress{ reserved=0x%02x%02x%02x%02x }\n",
+ ((u_char *)(void *)&kma->sadb_x_kmaddress_reserved)[0],
+ ((u_char *)(void *)&kma->sadb_x_kmaddress_reserved)[1],
+ ((u_char *)(void *)&kma->sadb_x_kmaddress_reserved)[2],
+ ((u_char *)(void *)&kma->sadb_x_kmaddress_reserved)[3]);
+
+ sa = (struct sockaddr *)(kma + 1);
+ if (len < sizeof(struct sockaddr) || (sa_len = sysdep_sa_len(sa)) > len)
+ panic("kdebug_sadb_x_kmaddress: not enough data to read"
+ " first sockaddr.\n");
+ kdebug_sockaddr((void *)sa); /* local address */
+ family = sa->sa_family;
+
+ len -= sa_len;
+ sa = (struct sockaddr *)((char *)sa + sa_len);
+ if (len < sizeof(struct sockaddr) || sysdep_sa_len(sa) > len)
+ panic("kdebug_sadb_x_kmaddress: not enough data to read"
+ " second sockaddr.\n");
+ kdebug_sockaddr((void *)sa); /* remote address */
+
+ if (family != sa->sa_family)
+ printf("kdebug_sadb_x_kmaddress: !!!! Please, note the "
+ "unexpected mismatch in address family.\n");
+}
+#endif
+
#ifdef _KERNEL
/* %%%: about SPD and SAD */
diff --git a/src/libipsec/libpfkey.h b/src/libipsec/libpfkey.h
index b312015..ff4c603 100644
--- a/src/libipsec/libpfkey.h
+++ b/src/libipsec/libpfkey.h
@@ -1,4 +1,4 @@
-/* $NetBSD: libpfkey.h,v 1.12.4.1 2007/08/01 11:52:18 vanhu Exp $ */
+/* $NetBSD: libpfkey.h,v 1.18 2010/12/03 14:32:52 tteras Exp $ */
/* Id: libpfkey.h,v 1.13 2005/12/04 20:26:43 manubsd Exp */
@@ -121,6 +121,10 @@ u_int pfkey_set_softrate __P((u_int, u_int));
u_int pfkey_get_softrate __P((u_int));
int pfkey_send_getspi __P((int, u_int, u_int, struct sockaddr *,
struct sockaddr *, u_int32_t, u_int32_t, u_int32_t, u_int32_t));
+int pfkey_send_getspi_nat __P((int, u_int, u_int,
+ struct sockaddr *, struct sockaddr *, u_int8_t, u_int16_t, u_int16_t,
+ u_int32_t, u_int32_t, u_int32_t, u_int32_t));
+
int pfkey_send_update2 __P((struct pfkey_send_sa_args *));
int pfkey_send_add2 __P((struct pfkey_send_sa_args *));
int pfkey_send_delete __P((int, u_int, u_int,
@@ -154,12 +158,22 @@ int pfkey_send_spdsetidx __P((int, struct sockaddr *, u_int,
int pfkey_send_spdflush __P((int));
int pfkey_send_spddump __P((int));
#ifdef SADB_X_MIGRATE
-int pfkey_send_migrate __P((int, struct sockaddr *, u_int,
- struct sockaddr *, u_int, u_int, caddr_t, int, u_int32_t));
+int pfkey_send_migrate __P((int, struct sockaddr *, struct sockaddr *,
+ struct sockaddr *, u_int, struct sockaddr *, u_int, u_int,
+ caddr_t, int, u_int32_t));
+#endif
+
+/* XXX should be somewhere else !!!
+ */
+#ifdef SADB_X_EXT_NAT_T_TYPE
+#define PFKEY_ADDR_X_PORT(ext) (ntohs(((struct sadb_x_nat_t_port *)ext)->sadb_x_nat_t_port_port))
+#define PFKEY_ADDR_X_NATTYPE(ext) ( ext != NULL && ((struct sadb_x_nat_t_type *)ext)->sadb_x_nat_t_type_type )
#endif
+
int pfkey_open __P((void));
void pfkey_close __P((int));
+int pfkey_set_buffer_size __P((int, int));
struct sadb_msg *pfkey_recv __P((int));
int pfkey_send __P((int, struct sadb_msg *, int));
int pfkey_align __P((struct sadb_msg *, caddr_t *));
@@ -200,6 +214,10 @@ int pfkey_send_add_nat __P((int, u_int, u_int, struct sockaddr *,
#define IPPROTO_IPCOMP IPPROTO_COMP
#endif
+#ifndef IPPROTO_MH
+#define IPPROTO_MH 135
+#endif
+
static __inline u_int8_t
sysdep_sa_len (const struct sockaddr *sa)
{
diff --git a/src/libipsec/pfkey.c b/src/libipsec/pfkey.c
index fae0415..e64cf36 100644
--- a/src/libipsec/pfkey.c
+++ b/src/libipsec/pfkey.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pfkey.c,v 1.13.4.2 2007/10/15 16:05:22 vanhu Exp $ */
+/* $NetBSD: pfkey.c,v 1.21 2011/01/20 16:08:35 vanhu Exp $ */
/* $KAME: pfkey.c,v 1.47 2003/10/02 19:52:12 itojun Exp $ */
@@ -71,6 +71,12 @@ static caddr_t pfkey_setsadbsa __P((caddr_t, caddr_t, u_int32_t, u_int,
u_int, u_int, u_int32_t));
static caddr_t pfkey_setsadbaddr __P((caddr_t, caddr_t, u_int,
struct sockaddr *, u_int, u_int));
+
+#ifdef SADB_X_EXT_KMADDRESS
+static caddr_t pfkey_setsadbkmaddr __P((caddr_t, caddr_t, struct sockaddr *,
+ struct sockaddr *));
+#endif
+
static caddr_t pfkey_setsadbkey __P((caddr_t, caddr_t, u_int, caddr_t, u_int));
static caddr_t pfkey_setsadblifetime __P((caddr_t, caddr_t, u_int, u_int32_t,
u_int32_t, u_int32_t, u_int32_t));
@@ -374,11 +380,10 @@ pfkey_get_softrate(type)
* -1 : error occured, and set errno.
*/
int
-pfkey_send_getspi(so, satype, mode, src, dst, min, max, reqid, seq)
- int so;
- u_int satype, mode;
- struct sockaddr *src, *dst;
- u_int32_t min, max, reqid, seq;
+pfkey_send_getspi_nat(int so, u_int satype, u_int mode, struct sockaddr *src,
+ struct sockaddr *dst, u_int8_t natt_type, u_int16_t sport,
+ u_int16_t dport, u_int32_t min, u_int32_t max, u_int32_t reqid,
+ u_int32_t seq)
{
struct sadb_msg *newmsg;
caddr_t ep;
@@ -425,6 +430,14 @@ pfkey_send_getspi(so, satype, mode, src, dst, min, max, reqid, seq)
len += sizeof(struct sadb_spirange);
}
+#ifdef SADB_X_EXT_NAT_T_TYPE
+ if(natt_type||sport||dport){
+ len += sizeof(struct sadb_x_nat_t_type);
+ len += sizeof(struct sadb_x_nat_t_port);
+ len += sizeof(struct sadb_x_nat_t_port);
+ }
+#endif
+
if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) {
__ipsec_set_strerror(strerror(errno));
return -1;
@@ -460,6 +473,32 @@ pfkey_send_getspi(so, satype, mode, src, dst, min, max, reqid, seq)
return -1;
}
+#ifdef SADB_X_EXT_NAT_T_TYPE
+ /* Add nat-t messages */
+ if (natt_type) {
+ p = pfkey_set_natt_type(p, ep, SADB_X_EXT_NAT_T_TYPE,
+ natt_type);
+ if (!p) {
+ free(newmsg);
+ return -1;
+ }
+
+ p = pfkey_set_natt_port(p, ep, SADB_X_EXT_NAT_T_SPORT,
+ sport);
+ if (!p) {
+ free(newmsg);
+ return -1;
+ }
+
+ p = pfkey_set_natt_port(p, ep, SADB_X_EXT_NAT_T_DPORT,
+ dport);
+ if (!p) {
+ free(newmsg);
+ return -1;
+ }
+ }
+#endif
+
/* proccessing spi range */
if (need_spirange) {
struct sadb_spirange spirange;
@@ -495,6 +534,15 @@ pfkey_send_getspi(so, satype, mode, src, dst, min, max, reqid, seq)
return len;
}
+int
+pfkey_send_getspi(int so, u_int satype, u_int mode, struct sockaddr *src,
+ struct sockaddr *dst, u_int32_t min, u_int32_t max, u_int32_t reqid,
+ u_int32_t seq)
+{
+ return pfkey_send_getspi_nat(so, satype, mode, src, dst, 0, 0, 0,
+ min, max, reqid, seq);
+}
+
/*
* sending SADB_UPDATE message to the kernel.
* The length of key material is a_keylen + e_keylen.
@@ -503,12 +551,10 @@ pfkey_send_getspi(so, satype, mode, src, dst, min, max, reqid, seq)
* -1 : error occured, and set errno.
*/
int
-pfkey_send_update2(sa_parms)
- struct pfkey_send_sa_args *sa_parms;
+pfkey_send_update2(struct pfkey_send_sa_args *sa_parms)
{
int len;
-
sa_parms->type = SADB_UPDATE;
if ((len = pfkey_send_x1(sa_parms)) < 0)
return -1;
@@ -524,8 +570,7 @@ pfkey_send_update2(sa_parms)
* -1 : error occured, and set errno.
*/
int
-pfkey_send_add2(sa_parms)
- struct pfkey_send_sa_args *sa_parms;
+pfkey_send_add2(struct pfkey_send_sa_args *sa_parms)
{
int len;
@@ -543,11 +588,8 @@ pfkey_send_add2(sa_parms)
* -1 : error occured, and set errno.
*/
int
-pfkey_send_delete(so, satype, mode, src, dst, spi)
- int so;
- u_int satype, mode;
- struct sockaddr *src, *dst;
- u_int32_t spi;
+pfkey_send_delete(int so, u_int satype, u_int mode, struct sockaddr *src,
+ struct sockaddr *dst, u_int32_t spi)
{
int len;
if ((len = pfkey_send_x2(so, SADB_DELETE, satype, mode, src, dst, spi)) < 0)
@@ -567,10 +609,8 @@ pfkey_send_delete(so, satype, mode, src, dst, spi)
*/
/*ARGSUSED*/
int
-pfkey_send_delete_all(so, satype, mode, src, dst)
- int so;
- u_int satype, mode;
- struct sockaddr *src, *dst;
+pfkey_send_delete_all(int so, u_int satype, u_int mode, struct sockaddr *src,
+ struct sockaddr *dst)
{
struct sadb_msg *newmsg;
int len;
@@ -649,11 +689,8 @@ pfkey_send_delete_all(so, satype, mode, src, dst)
* -1 : error occured, and set errno.
*/
int
-pfkey_send_get(so, satype, mode, src, dst, spi)
- int so;
- u_int satype, mode;
- struct sockaddr *src, *dst;
- u_int32_t spi;
+pfkey_send_get(int so, u_int satype, u_int mode, struct sockaddr *src,
+ struct sockaddr *dst, u_int32_t spi)
{
int len;
if ((len = pfkey_send_x2(so, SADB_GET, satype, mode, src, dst, spi)) < 0)
@@ -669,9 +706,7 @@ pfkey_send_get(so, satype, mode, src, dst, spi)
* -1 : error occured, and set errno.
*/
int
-pfkey_send_register(so, satype)
- int so;
- u_int satype;
+pfkey_send_register(int so, u_int satype)
{
int len, algno;
@@ -711,8 +746,7 @@ pfkey_send_register(so, satype)
* -1: error occured, and set errno.
*/
int
-pfkey_recv_register(so)
- int so;
+pfkey_recv_register(int so)
{
pid_t pid = getpid();
struct sadb_msg *newmsg;
@@ -751,9 +785,7 @@ pfkey_recv_register(so)
* -1: error occured, and set errno.
*/
int
-pfkey_set_supported(msg, tlen)
- struct sadb_msg *msg;
- int tlen;
+pfkey_set_supported(struct sadb_msg *msg, int tlen)
{
struct sadb_supported *sup;
caddr_t p;
@@ -815,9 +847,7 @@ pfkey_set_supported(msg, tlen)
* -1 : error occured, and set errno.
*/
int
-pfkey_send_flush(so, satype)
- int so;
- u_int satype;
+pfkey_send_flush(int so, u_int satype)
{
int len;
@@ -834,9 +864,7 @@ pfkey_send_flush(so, satype)
* -1 : error occured, and set errno.
*/
int
-pfkey_send_dump(so, satype)
- int so;
- u_int satype;
+pfkey_send_dump(int so, u_int satype)
{
int len;
@@ -859,9 +887,7 @@ pfkey_send_dump(so, satype)
* algorithms is.
*/
int
-pfkey_send_promisc_toggle(so, flag)
- int so;
- int flag;
+pfkey_send_promisc_toggle(int so, int flag)
{
int len;
@@ -879,13 +905,9 @@ pfkey_send_promisc_toggle(so, flag)
* -1 : error occured, and set errno.
*/
int
-pfkey_send_spdadd(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
- int so;
- struct sockaddr *src, *dst;
- u_int prefs, prefd, proto;
- caddr_t policy;
- int policylen;
- u_int32_t seq;
+pfkey_send_spdadd(int so, struct sockaddr *src, u_int prefs,
+ struct sockaddr *dst, u_int prefd, u_int proto, caddr_t policy,
+ int policylen, u_int32_t seq)
{
int len;
@@ -905,15 +927,9 @@ pfkey_send_spdadd(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
* -1 : error occured, and set errno.
*/
int
-pfkey_send_spdadd2(so, src, prefs, dst, prefd, proto, ltime, vtime,
- policy, policylen, seq)
- int so;
- struct sockaddr *src, *dst;
- u_int prefs, prefd, proto;
- u_int64_t ltime, vtime;
- caddr_t policy;
- int policylen;
- u_int32_t seq;
+pfkey_send_spdadd2(int so, struct sockaddr *src, u_int prefs,
+ struct sockaddr *dst, u_int prefd, u_int proto, u_int64_t ltime,
+ u_int64_t vtime, caddr_t policy, int policylen, u_int32_t seq)
{
int len;
@@ -933,13 +949,9 @@ pfkey_send_spdadd2(so, src, prefs, dst, prefd, proto, ltime, vtime,
* -1 : error occured, and set errno.
*/
int
-pfkey_send_spdupdate(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
- int so;
- struct sockaddr *src, *dst;
- u_int prefs, prefd, proto;
- caddr_t policy;
- int policylen;
- u_int32_t seq;
+pfkey_send_spdupdate(int so, struct sockaddr *src, u_int prefs,
+ struct sockaddr *dst, u_int prefd, u_int proto, caddr_t policy,
+ int policylen, u_int32_t seq)
{
int len;
@@ -959,15 +971,9 @@ pfkey_send_spdupdate(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
* -1 : error occured, and set errno.
*/
int
-pfkey_send_spdupdate2(so, src, prefs, dst, prefd, proto, ltime, vtime,
- policy, policylen, seq)
- int so;
- struct sockaddr *src, *dst;
- u_int prefs, prefd, proto;
- u_int64_t ltime, vtime;
- caddr_t policy;
- int policylen;
- u_int32_t seq;
+pfkey_send_spdupdate2(int so, struct sockaddr *src, u_int prefs,
+ struct sockaddr *dst, u_int prefd, u_int proto, u_int64_t ltime,
+ u_int64_t vtime, caddr_t policy, int policylen, u_int32_t seq)
{
int len;
@@ -987,13 +993,9 @@ pfkey_send_spdupdate2(so, src, prefs, dst, prefd, proto, ltime, vtime,
* -1 : error occured, and set errno.
*/
int
-pfkey_send_spddelete(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
- int so;
- struct sockaddr *src, *dst;
- u_int prefs, prefd, proto;
- caddr_t policy;
- int policylen;
- u_int32_t seq;
+pfkey_send_spddelete(int so, struct sockaddr *src, u_int prefs,
+ struct sockaddr *dst, u_int prefd, u_int proto, caddr_t policy,
+ int policylen, u_int32_t seq)
{
int len;
@@ -1018,9 +1020,7 @@ pfkey_send_spddelete(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
* -1 : error occured, and set errno.
*/
int
-pfkey_send_spddelete2(so, spid)
- int so;
- u_int32_t spid;
+pfkey_send_spddelete2(int so, u_int32_t spid)
{
int len;
@@ -1037,9 +1037,7 @@ pfkey_send_spddelete2(so, spid)
* -1 : error occured, and set errno.
*/
int
-pfkey_send_spdget(so, spid)
- int so;
- u_int32_t spid;
+pfkey_send_spdget(int so, u_int32_t spid)
{
int len;
@@ -1056,13 +1054,9 @@ pfkey_send_spdget(so, spid)
* -1 : error occured, and set errno.
*/
int
-pfkey_send_spdsetidx(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
- int so;
- struct sockaddr *src, *dst;
- u_int prefs, prefd, proto;
- caddr_t policy;
- int policylen;
- u_int32_t seq;
+pfkey_send_spdsetidx(int so, struct sockaddr *src, u_int prefs,
+ struct sockaddr *dst, u_int prefd, u_int proto, caddr_t policy,
+ int policylen, u_int32_t seq)
{
int len;
@@ -1087,8 +1081,7 @@ pfkey_send_spdsetidx(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
* -1 : error occured, and set errno.
*/
int
-pfkey_send_spdflush(so)
- int so;
+pfkey_send_spdflush(int so)
{
int len;
@@ -1105,8 +1098,7 @@ pfkey_send_spdflush(so)
* -1 : error occured, and set errno.
*/
int
-pfkey_send_spddump(so)
- int so;
+pfkey_send_spddump(int so)
{
int len;
@@ -1125,13 +1117,9 @@ pfkey_send_spddump(so)
* -1 : error occured, and set errno.
*/
int
-pfkey_send_migrate(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
- int so;
- struct sockaddr *src, *dst;
- u_int prefs, prefd, proto;
- caddr_t policy;
- int policylen;
- u_int32_t seq;
+pfkey_send_migrate(int so, struct sockaddr *local, struct sockaddr *remote,
+ struct sockaddr *src, u_int prefs, struct sockaddr *dst, u_int prefd,
+ u_int proto, caddr_t policy, int policylen, u_int32_t seq)
{
struct sadb_msg *newmsg;
int len;
@@ -1149,6 +1137,17 @@ pfkey_send_migrate(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
return -1;
}
+ if (local == NULL || remote == NULL) {
+ __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
+ return -1;
+ }
+#ifdef SADB_X_EXT_KMADDRESS
+ if (local->sa_family != remote->sa_family) {
+ __ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
+ return -1;
+ }
+#endif
+
switch (src->sa_family) {
case AF_INET:
plen = sizeof(struct in_addr) << 3;
@@ -1167,6 +1166,10 @@ pfkey_send_migrate(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
/* create new sadb_msg to reply. */
len = sizeof(struct sadb_msg)
+#ifdef SADB_X_EXT_KMADDRESS
+ + sizeof(struct sadb_x_kmaddress)
+ + PFKEY_ALIGN8(2*sysdep_sa_len(local))
+#endif
+ sizeof(struct sadb_address)
+ PFKEY_ALIGN8(sysdep_sa_len(src))
+ sizeof(struct sadb_address)
@@ -1185,6 +1188,13 @@ pfkey_send_migrate(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
free(newmsg);
return -1;
}
+#ifdef SADB_X_EXT_KMADDRESS
+ p = pfkey_setsadbkmaddr(p, ep, local, remote);
+ if (!p) {
+ free(newmsg);
+ return -1;
+ }
+#endif
p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, prefs, proto);
if (!p) {
free(newmsg);
@@ -1212,8 +1222,7 @@ pfkey_send_migrate(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
/* sending SADB_ADD or SADB_UPDATE message to the kernel */
static int
-pfkey_send_x1(sa_parms)
- struct pfkey_send_sa_args *sa_parms;
+pfkey_send_x1(struct pfkey_send_sa_args *sa_parms)
{
struct sadb_msg *newmsg;
int len;
@@ -1486,11 +1495,8 @@ pfkey_send_x1(sa_parms)
/* sending SADB_DELETE or SADB_GET message to the kernel */
/*ARGSUSED*/
static int
-pfkey_send_x2(so, type, satype, mode, src, dst, spi)
- int so;
- u_int type, satype, mode;
- struct sockaddr *src, *dst;
- u_int32_t spi;
+pfkey_send_x2(int so, u_int type, u_int satype, u_int mode,
+ struct sockaddr *src, struct sockaddr *dst, u_int32_t spi)
{
struct sadb_msg *newmsg;
int len;
@@ -1573,9 +1579,7 @@ pfkey_send_x2(so, type, satype, mode, src, dst, spi)
* to the kernel
*/
static int
-pfkey_send_x3(so, type, satype)
- int so;
- u_int type, satype;
+pfkey_send_x3(int so, u_int type, u_int satype)
{
struct sadb_msg *newmsg;
int len;
@@ -1635,15 +1639,9 @@ pfkey_send_x3(so, type, satype)
/* sending SADB_X_SPDADD message to the kernel */
static int
-pfkey_send_x4(so, type, src, prefs, dst, prefd, proto,
- ltime, vtime, policy, policylen, seq)
- int so;
- struct sockaddr *src, *dst;
- u_int type, prefs, prefd, proto;
- u_int64_t ltime, vtime;
- char *policy;
- int policylen;
- u_int32_t seq;
+pfkey_send_x4(int so, u_int type, struct sockaddr *src, u_int prefs,
+ struct sockaddr *dst, u_int prefd, u_int proto, u_int64_t ltime,
+ u_int64_t vtime, char *policy, int policylen, u_int32_t seq)
{
struct sadb_msg *newmsg;
int len;
@@ -1729,10 +1727,7 @@ pfkey_send_x4(so, type, src, prefs, dst, prefd, proto,
/* sending SADB_X_SPDGET or SADB_X_SPDDELETE message to the kernel */
static int
-pfkey_send_x5(so, type, spid)
- int so;
- u_int type;
- u_int32_t spid;
+pfkey_send_x5(int so, u_int type, u_int32_t spid)
{
struct sadb_msg *newmsg;
struct sadb_x_policy xpl;
@@ -1785,7 +1780,7 @@ pfkey_send_x5(so, type, spid)
* others : success and return value of socket.
*/
int
-pfkey_open()
+pfkey_open(void)
{
int so;
int bufsiz = 128 * 1024; /*is 128K enough?*/
@@ -1811,6 +1806,42 @@ pfkey_open()
return so;
}
+int
+pfkey_set_buffer_size(int so, int size)
+{
+ int newsize;
+ int actual_bufsiz;
+ socklen_t sizebufsiz;
+ int desired_bufsiz;
+
+ /*
+ * on linux you may need to allow the kernel to allocate
+ * more buffer space by increasing:
+ * /proc/sys/net/core/rmem_max and wmem_max
+ */
+ if (size > 0) {
+ actual_bufsiz = 0;
+ sizebufsiz = sizeof(actual_bufsiz);
+ desired_bufsiz = size * 1024;
+ if ((getsockopt(so, SOL_SOCKET, SO_RCVBUF,
+ &actual_bufsiz, &sizebufsiz) < 0)
+ || (actual_bufsiz < desired_bufsiz)) {
+ if (setsockopt(so, SOL_SOCKET, SO_RCVBUF,
+ &desired_bufsiz, sizeof(desired_bufsiz)) < 0) {
+ __ipsec_set_strerror(strerror(errno));
+ return -1;
+ }
+ }
+ }
+
+ /* return actual buffer size */
+ actual_bufsiz = 0;
+ sizebufsiz = sizeof(actual_bufsiz);
+ getsockopt(so, SOL_SOCKET, SO_RCVBUF,
+ &actual_bufsiz, &sizebufsiz);
+ return actual_bufsiz / 1024;
+}
+
/*
* close a socket.
* OUT:
@@ -1818,8 +1849,7 @@ pfkey_open()
* -1: fail.
*/
void
-pfkey_close(so)
- int so;
+pfkey_close(int so)
{
(void)close(so);
@@ -1837,8 +1867,7 @@ pfkey_close(so)
* XXX should be rewritten to pass length explicitly
*/
struct sadb_msg *
-pfkey_recv(so)
- int so;
+pfkey_recv(int so)
{
struct sadb_msg buf, *newmsg;
int len, reallen;
@@ -1895,10 +1924,7 @@ pfkey_recv(so)
* -1 : fail.
*/
int
-pfkey_send(so, msg, len)
- int so;
- struct sadb_msg *msg;
- int len;
+pfkey_send(int so, struct sadb_msg *msg, int len)
{
if ((len = send(so, (void *)msg, (socklen_t)len, 0)) < 0) {
__ipsec_set_strerror(strerror(errno));
@@ -1924,9 +1950,7 @@ pfkey_send(so, msg, len)
* XXX should be rewritten to obtain length explicitly
*/
int
-pfkey_align(msg, mhp)
- struct sadb_msg *msg;
- caddr_t *mhp;
+pfkey_align(struct sadb_msg *msg, caddr_t *mhp)
{
struct sadb_ext *ext;
int i;
@@ -2001,6 +2025,9 @@ pfkey_align(msg, mhp)
#ifdef SADB_X_EXT_PACKET
case SADB_X_EXT_PACKET:
#endif
+#ifdef SADB_X_EXT_KMADDRESS
+ case SADB_X_EXT_KMADDRESS:
+#endif
#ifdef SADB_X_EXT_SEC_CTX
case SADB_X_EXT_SEC_CTX:
#endif
@@ -2035,8 +2062,7 @@ pfkey_align(msg, mhp)
* 0: valid.
*/
int
-pfkey_check(mhp)
- caddr_t *mhp;
+pfkey_check(caddr_t *mhp)
{
struct sadb_msg *msg;
@@ -2112,6 +2138,12 @@ pfkey_check(mhp)
break;
/*FALLTHROUGH*/
default:
+#ifdef __linux__
+ /* Linux kernel seems to be buggy and return
+ * uninitialized satype for spd flush message */
+ if (msg->sadb_msg_type == SADB_X_SPDFLUSH)
+ break;
+#endif
__ipsec_errcode = EIPSEC_INVAL_SATYPE;
return -1;
}
@@ -2159,13 +2191,8 @@ pfkey_check(mhp)
* `buf' must has been allocated sufficiently.
*/
static caddr_t
-pfkey_setsadbmsg(buf, lim, type, tlen, satype, seq, pid)
- caddr_t buf;
- caddr_t lim;
- u_int type, satype;
- u_int tlen;
- u_int32_t seq;
- pid_t pid;
+pfkey_setsadbmsg(caddr_t buf, caddr_t lim, u_int type, u_int tlen,
+ u_int satype, u_int32_t seq, pid_t pid)
{
struct sadb_msg *p;
u_int len;
@@ -2194,11 +2221,8 @@ pfkey_setsadbmsg(buf, lim, type, tlen, satype, seq, pid)
* `buf' must has been allocated sufficiently.
*/
static caddr_t
-pfkey_setsadbsa(buf, lim, spi, wsize, auth, enc, flags)
- caddr_t buf;
- caddr_t lim;
- u_int32_t spi, flags;
- u_int wsize, auth, enc;
+pfkey_setsadbsa(caddr_t buf, caddr_t lim, u_int32_t spi, u_int wsize,
+ u_int auth, u_int enc, u_int32_t flags)
{
struct sadb_sa *p;
u_int len;
@@ -2228,13 +2252,8 @@ pfkey_setsadbsa(buf, lim, spi, wsize, auth, enc, flags)
* prefixlen is in bits.
*/
static caddr_t
-pfkey_setsadbaddr(buf, lim, exttype, saddr, prefixlen, ul_proto)
- caddr_t buf;
- caddr_t lim;
- u_int exttype;
- struct sockaddr *saddr;
- u_int prefixlen;
- u_int ul_proto;
+pfkey_setsadbaddr(caddr_t buf, caddr_t lim, u_int exttype,
+ struct sockaddr *saddr, u_int prefixlen, u_int ul_proto)
{
struct sadb_address *p;
u_int len;
@@ -2257,16 +2276,50 @@ pfkey_setsadbaddr(buf, lim, exttype, saddr, prefixlen, ul_proto)
return(buf + len);
}
+#ifdef SADB_X_EXT_KMADDRESS
+/*
+ * set data into sadb_x_kmaddress.
+ * `buf' must has been allocated sufficiently.
+ */
+static caddr_t
+pfkey_setsadbkmaddr(caddr_t buf, caddr_t lim, struct sockaddr *local,
+ struct sockaddr *remote)
+{
+ struct sadb_x_kmaddress *p;
+ struct sockaddr *sa;
+ u_int salen = sysdep_sa_len(local);
+ u_int len;
+
+ /* sanity check */
+ if (local->sa_family != remote->sa_family)
+ return NULL;
+
+ p = (void *)buf;
+ len = sizeof(struct sadb_x_kmaddress) + PFKEY_ALIGN8(2*salen);
+
+ if (buf + len > lim)
+ return NULL;
+
+ memset(p, 0, len);
+ p->sadb_x_kmaddress_len = PFKEY_UNIT64(len);
+ p->sadb_x_kmaddress_exttype = SADB_X_EXT_KMADDRESS;
+ p->sadb_x_kmaddress_reserved = 0;
+ sa = (struct sockaddr *)(p + 1);
+ memcpy(sa, local, salen);
+ sa = (struct sockaddr *)((char *)sa + salen);
+ memcpy(sa, remote, salen);
+
+ return(buf + len);
+}
+#endif
+
/*
* set sadb_key structure after clearing buffer with zero.
* OUT: the pointer of buf + len.
*/
static caddr_t
-pfkey_setsadbkey(buf, lim, type, key, keylen)
- caddr_t buf;
- caddr_t lim;
- caddr_t key;
- u_int type, keylen;
+pfkey_setsadbkey(caddr_t buf, caddr_t lim, u_int type, caddr_t key,
+ u_int keylen)
{
struct sadb_key *p;
u_int len;
@@ -2293,11 +2346,8 @@ pfkey_setsadbkey(buf, lim, type, key, keylen)
* OUT: the pointer of buf + len.
*/
static caddr_t
-pfkey_setsadblifetime(buf, lim, type, l_alloc, l_bytes, l_addtime, l_usetime)
- caddr_t buf;
- caddr_t lim;
- u_int type;
- u_int32_t l_alloc, l_bytes, l_addtime, l_usetime;
+pfkey_setsadblifetime(caddr_t buf, caddr_t lim, u_int type, u_int32_t l_alloc,
+ u_int32_t l_bytes, u_int32_t l_addtime, u_int32_t l_usetime)
{
struct sadb_lifetime *p;
u_int len;
@@ -2339,11 +2389,7 @@ pfkey_setsadblifetime(buf, lim, type, l_alloc, l_bytes, l_addtime, l_usetime)
* `buf' must has been allocated sufficiently.
*/
static caddr_t
-pfkey_setsadbxsa2(buf, lim, mode0, reqid)
- caddr_t buf;
- caddr_t lim;
- u_int32_t mode0;
- u_int32_t reqid;
+pfkey_setsadbxsa2(caddr_t buf, caddr_t lim, u_int32_t mode0, u_int32_t reqid)
{
struct sadb_x_sa2 *p;
u_int8_t mode = mode0 & 0xff;
@@ -2366,11 +2412,7 @@ pfkey_setsadbxsa2(buf, lim, mode0, reqid)
#ifdef SADB_X_EXT_NAT_T_TYPE
static caddr_t
-pfkey_set_natt_type(buf, lim, type, l_natt_type)
- caddr_t buf;
- caddr_t lim;
- u_int type;
- u_int8_t l_natt_type;
+pfkey_set_natt_type(caddr_t buf, caddr_t lim, u_int type, u_int8_t l_natt_type)
{
struct sadb_x_nat_t_type *p;
u_int len;
@@ -2390,11 +2432,7 @@ pfkey_set_natt_type(buf, lim, type, l_natt_type)
}
static caddr_t
-pfkey_set_natt_port(buf, lim, type, l_natt_port)
- caddr_t buf;
- caddr_t lim;
- u_int type;
- u_int16_t l_natt_port;
+pfkey_set_natt_port(caddr_t buf, caddr_t lim, u_int type, u_int16_t l_natt_port)
{
struct sadb_x_nat_t_port *p;
u_int len;
@@ -2416,11 +2454,8 @@ pfkey_set_natt_port(buf, lim, type, l_natt_port)
#ifdef SADB_X_EXT_NAT_T_FRAG
static caddr_t
-pfkey_set_natt_frag(buf, lim, type, l_natt_frag)
- caddr_t buf;
- caddr_t lim;
- u_int type;
- u_int16_t l_natt_frag;
+pfkey_set_natt_frag(caddr_t buf, caddr_t lim, u_int type,
+ u_int16_t l_natt_frag)
{
struct sadb_x_nat_t_frag *p;
u_int len;
@@ -2442,13 +2477,8 @@ pfkey_set_natt_frag(buf, lim, type, l_natt_frag)
#ifdef SADB_X_EXT_SEC_CTX
static caddr_t
-pfkey_setsecctx(buf, lim, type, ctx_doi, ctx_alg, sec_ctx, sec_ctxlen)
- caddr_t buf;
- caddr_t lim;
- u_int type;
- u_int8_t ctx_doi, ctx_alg;
- caddr_t sec_ctx;
- u_int16_t sec_ctxlen;
+pfkey_setsecctx(caddr_t buf, caddr_t lim, u_int type, u_int8_t ctx_doi,
+ u_int8_t ctx_alg, caddr_t sec_ctx, u_int16_t sec_ctxlen)
{
struct sadb_x_sec_ctx *p;
u_int len;
@@ -2477,18 +2507,11 @@ pfkey_setsecctx(buf, lim, type, ctx_doi, ctx_alg, sec_ctx, sec_ctxlen)
* libipsec users. Please use pfkey_send_update2 and pfkey_send_add2 instead
*/
int
-pfkey_send_update(so, satype, mode, src, dst, spi, reqid, wsize,
- keymat, e_type, e_keylen, a_type, a_keylen, flags,
- l_alloc, l_bytes, l_addtime, l_usetime, seq)
- int so;
- u_int satype, mode, wsize;
- struct sockaddr *src, *dst;
- u_int32_t spi, reqid;
- caddr_t keymat;
- u_int e_type, e_keylen, a_type, a_keylen, flags;
- u_int32_t l_alloc;
- u_int64_t l_bytes, l_addtime, l_usetime;
- u_int32_t seq;
+pfkey_send_update(int so, u_int satype, u_int mode, struct sockaddr *src,
+ struct sockaddr *dst, u_int32_t spi, u_int32_t reqid, u_int wsize,
+ caddr_t keymat, u_int e_type, u_int e_keylen, u_int a_type,
+ u_int a_keylen, u_int flags, u_int32_t l_alloc, u_int64_t l_bytes,
+ u_int64_t l_addtime, u_int64_t l_usetime, u_int32_t seq)
{
struct pfkey_send_sa_args psaa;
@@ -2518,24 +2541,13 @@ pfkey_send_update(so, satype, mode, src, dst, spi, reqid, wsize,
}
int
-pfkey_send_update_nat(so, satype, mode, src, dst, spi, reqid, wsize,
- keymat, e_type, e_keylen, a_type, a_keylen, flags,
- l_alloc, l_bytes, l_addtime, l_usetime, seq,
- l_natt_type, l_natt_sport, l_natt_dport, l_natt_oa,
- l_natt_frag)
- int so;
- u_int satype, mode, wsize;
- struct sockaddr *src, *dst;
- u_int32_t spi, reqid;
- caddr_t keymat;
- u_int e_type, e_keylen, a_type, a_keylen, flags;
- u_int32_t l_alloc;
- u_int64_t l_bytes, l_addtime, l_usetime;
- u_int32_t seq;
- u_int8_t l_natt_type;
- u_int16_t l_natt_sport, l_natt_dport;
- struct sockaddr *l_natt_oa;
- u_int16_t l_natt_frag;
+pfkey_send_update_nat(int so, u_int satype, u_int mode, struct sockaddr *src,
+ struct sockaddr *dst, u_int32_t spi, u_int32_t reqid, u_int wsize,
+ caddr_t keymat, u_int e_type, u_int e_keylen, u_int a_type,
+ u_int a_keylen, u_int flags, u_int32_t l_alloc, u_int64_t l_bytes,
+ u_int64_t l_addtime, u_int64_t l_usetime, u_int32_t seq,
+ u_int8_t l_natt_type, u_int16_t l_natt_sport, u_int16_t l_natt_dport,
+ struct sockaddr *l_natt_oa, u_int16_t l_natt_frag)
{
struct pfkey_send_sa_args psaa;
@@ -2570,18 +2582,11 @@ pfkey_send_update_nat(so, satype, mode, src, dst, spi, reqid, wsize,
}
int
-pfkey_send_add(so, satype, mode, src, dst, spi, reqid, wsize,
- keymat, e_type, e_keylen, a_type, a_keylen, flags,
- l_alloc, l_bytes, l_addtime, l_usetime, seq)
- int so;
- u_int satype, mode, wsize;
- struct sockaddr *src, *dst;
- u_int32_t spi, reqid;
- caddr_t keymat;
- u_int e_type, e_keylen, a_type, a_keylen, flags;
- u_int32_t l_alloc;
- u_int64_t l_bytes, l_addtime, l_usetime;
- u_int32_t seq;
+pfkey_send_add(int so, u_int satype, u_int mode, struct sockaddr *src,
+ struct sockaddr *dst, u_int32_t spi, u_int32_t reqid, u_int wsize,
+ caddr_t keymat, u_int e_type, u_int e_keylen, u_int a_type,
+ u_int a_keylen, u_int flags, u_int32_t l_alloc, u_int64_t l_bytes,
+ u_int64_t l_addtime, u_int64_t l_usetime, u_int32_t seq)
{
struct pfkey_send_sa_args psaa;
@@ -2611,24 +2616,13 @@ pfkey_send_add(so, satype, mode, src, dst, spi, reqid, wsize,
}
int
-pfkey_send_add_nat(so, satype, mode, src, dst, spi, reqid, wsize,
- keymat, e_type, e_keylen, a_type, a_keylen, flags,
- l_alloc, l_bytes, l_addtime, l_usetime, seq,
- l_natt_type, l_natt_sport, l_natt_dport, l_natt_oa,
- l_natt_frag)
- int so;
- u_int satype, mode, wsize;
- struct sockaddr *src, *dst;
- u_int32_t spi, reqid;
- caddr_t keymat;
- u_int e_type, e_keylen, a_type, a_keylen, flags;
- u_int32_t l_alloc;
- u_int64_t l_bytes, l_addtime, l_usetime;
- u_int32_t seq;
- u_int8_t l_natt_type;
- u_int16_t l_natt_sport, l_natt_dport;
- struct sockaddr *l_natt_oa;
- u_int16_t l_natt_frag;
+pfkey_send_add_nat(int so, u_int satype, u_int mode, struct sockaddr *src,
+ struct sockaddr *dst, u_int32_t spi, u_int32_t reqid, u_int wsize,
+ caddr_t keymat, u_int e_type, u_int e_keylen, u_int a_type,
+ u_int a_keylen, u_int flags, u_int32_t l_alloc, u_int64_t l_bytes,
+ u_int64_t l_addtime, u_int64_t l_usetime, u_int32_t seq,
+ u_int8_t l_natt_type, u_int16_t l_natt_sport, u_int16_t l_natt_dport,
+ struct sockaddr *l_natt_oa, u_int16_t l_natt_frag)
{
struct pfkey_send_sa_args psaa;
diff --git a/src/libipsec/pfkey_dump.c b/src/libipsec/pfkey_dump.c
index 8fa4084..4627ebc 100644
--- a/src/libipsec/pfkey_dump.c
+++ b/src/libipsec/pfkey_dump.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pfkey_dump.c,v 1.15.6.1 2007/08/01 11:52:18 vanhu Exp $ */
+/* $NetBSD: pfkey_dump.c,v 1.18 2010/12/03 14:32:52 tteras Exp $ */
/* $KAME: pfkey_dump.c,v 1.45 2003/09/08 10:14:56 itojun Exp $ */
@@ -716,13 +716,19 @@ str_prefport(family, pref, port, ulp)
else
snprintf(prefbuf, sizeof(prefbuf), "/%u", pref);
- if (ulp == IPPROTO_ICMPV6)
+ switch (ulp) {
+ case IPPROTO_ICMP:
+ case IPPROTO_ICMPV6:
+ case IPPROTO_MH:
+ case IPPROTO_GRE:
memset(portbuf, 0, sizeof(portbuf));
- else {
+ break;
+ default:
if (port == IPSEC_PORT_ANY)
- snprintf(portbuf, sizeof(portbuf), "[%s]", "any");
+ strcpy(portbuf, "[any]");
else
snprintf(portbuf, sizeof(portbuf), "[%u]", port);
+ break;
}
snprintf(buf, sizeof(buf), "%s%s", prefbuf, portbuf);
@@ -734,29 +740,26 @@ static void
str_upperspec(ulp, p1, p2)
u_int ulp, p1, p2;
{
- if (ulp == IPSEC_ULPROTO_ANY)
- printf("any");
- else if (ulp == IPPROTO_ICMPV6) {
- printf("icmp6");
- if (!(p1 == IPSEC_PORT_ANY && p2 == IPSEC_PORT_ANY))
- printf(" %u,%u", p1, p2);
- } else {
- struct protoent *ent;
+ struct protoent *ent;
- switch (ulp) {
- case IPPROTO_IPV4:
- printf("ip4");
- break;
- default:
- ent = getprotobynumber((int)ulp);
- if (ent)
- printf("%s", ent->p_name);
- else
- printf("%u", ulp);
+ ent = getprotobynumber((int)ulp);
+ if (ent)
+ printf("%s", ent->p_name);
+ else
+ printf("%u", ulp);
- endprotoent();
- break;
- }
+ if (p1 == IPSEC_PORT_ANY && p2 == IPSEC_PORT_ANY)
+ return;
+
+ switch (ulp) {
+ case IPPROTO_ICMP:
+ case IPPROTO_ICMPV6:
+ case IPPROTO_MH:
+ printf(" %u,%u", p1, p2);
+ break;
+ case IPPROTO_GRE:
+ printf(" %u", (p1 << 16) + p2);
+ break;
}
}
@@ -774,8 +777,10 @@ str_time(t)
for (;i < 20;) buf[i++] = ' ';
} else {
char *t0;
- t0 = ctime(&t);
- memcpy(buf, t0 + 4, 20);
+ if ((t0 = ctime(&t)) == NULL)
+ memset(buf, '?', 20);
+ else
+ memcpy(buf, t0 + 4, 20);
}
buf[20] = '\0';
diff --git a/src/libipsec/policy_parse.h b/src/libipsec/policy_parse.h
index a4c1d0b..dc629dd 100644
--- a/src/libipsec/policy_parse.h
+++ b/src/libipsec/policy_parse.h
@@ -1,24 +1,23 @@
-/* A Bison parser, made by GNU Bison 2.3. */
-/* Skeleton interface for Bison's Yacc-like parsers in C
+/* A Bison parser, made by GNU Bison 2.4.1. */
- Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+/* Skeleton interface for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
+
+ This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
@@ -29,10 +28,11 @@
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
-
+
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
+
/* Tokens. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
@@ -80,22 +80,28 @@
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
-#line 129 "policy_parse.y"
{
+
+/* Line 1676 of yacc.c */
+#line 129 "policy_parse.y"
+
u_int num;
u_int32_t num32;
struct _val {
int len;
char *buf;
} val;
-}
-/* Line 1489 of yacc.c. */
-#line 94 "policy_parse.h"
- YYSTYPE;
+
+
+
+/* Line 1676 of yacc.c */
+#line 99 "policy_parse.h"
+} YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
#endif
extern YYSTYPE __libipseclval;
+
diff --git a/src/libipsec/policy_parse.y b/src/libipsec/policy_parse.y
index a13dc12..321f4f0 100644
--- a/src/libipsec/policy_parse.y
+++ b/src/libipsec/policy_parse.y
@@ -1,4 +1,4 @@
-/* $NetBSD: policy_parse.y,v 1.9.6.2 2009/02/16 18:38:26 tteras Exp $ */
+/* $NetBSD: policy_parse.y,v 1.11 2009/02/16 18:36:21 tteras Exp $ */
/* $KAME: policy_parse.y,v 1.21 2003/12/12 08:01:26 itojun Exp $ */
diff --git a/src/libipsec/policy_token.l b/src/libipsec/policy_token.l
index 0833c20..243b678 100644
--- a/src/libipsec/policy_token.l
+++ b/src/libipsec/policy_token.l
@@ -1,4 +1,4 @@
-/* $NetBSD: policy_token.l,v 1.6.6.1 2007/08/01 11:52:19 vanhu Exp $ */
+/* $NetBSD: policy_token.l,v 1.7 2007/07/18 12:07:50 vanhu Exp $ */
/* Id: policy_token.l,v 1.12 2005/05/05 12:32:18 manubsd Exp */
diff --git a/src/racoon/Makefile.am b/src/racoon/Makefile.am
index 202a18e..dbaded9 100644
--- a/src/racoon/Makefile.am
+++ b/src/racoon/Makefile.am
@@ -3,7 +3,7 @@
sbin_PROGRAMS = racoon racoonctl plainrsa-gen
noinst_PROGRAMS = eaytest
include_racoon_HEADERS = racoonctl.h var.h vmbuf.h misc.h gcmalloc.h admin.h \
- schedule.h sockmisc.h vmbuf.h isakmp_var.h isakmp.h isakmp_xauth.h \
+ schedule.h sockmisc.h isakmp_var.h isakmp.h isakmp_xauth.h \
isakmp_cfg.h isakmp_unity.h ipsec_doi.h evt.h
lib_LTLIBRARIES = libracoon.la
@@ -48,6 +48,7 @@ racoonctl_SOURCES = racoonctl.c str2val.c
racoonctl_LDADD = libracoon.la ../libipsec/libipsec.la
libracoon_la_SOURCES = kmpstat.c vmbuf.c sockmisc.c misc.c
+libracoon_la_CFLAGS = -DNOUSE_PRIVSEP $(AM_CFLAGS)
plainrsa_gen_SOURCES = plainrsa-gen.c plog.c \
crypto_openssl.c logger.c
@@ -88,6 +89,7 @@ EXTRA_DIST = \
${man5_MANS} ${man8_MANS} \
missing/crypto/rijndael/boxes-fst.dat \
doc/FAQ doc/README.certificate doc/README.gssapi doc/README.plainrsa \
+ doc/README.privsep \
contrib/sp.pl stats.pl \
samples/psk.txt.sample samples/racoon.conf.sample \
samples/psk.txt.in samples/racoon.conf.in \
diff --git a/src/racoon/Makefile.in b/src/racoon/Makefile.in
index 47e997b..4b4e635 100644
--- a/src/racoon/Makefile.in
+++ b/src/racoon/Makefile.in
@@ -1,8 +1,9 @@
-# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
@@ -20,8 +21,9 @@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
@@ -52,21 +54,40 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
*) f=$$p;; \
esac;
-am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(sbindir)" \
"$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)" \
"$(DESTDIR)$(include_racoondir)"
-libLTLIBRARIES_INSTALL = $(INSTALL)
LTLIBRARIES = $(lib_LTLIBRARIES)
libracoon_la_LIBADD =
-am_libracoon_la_OBJECTS = kmpstat.lo vmbuf.lo sockmisc.lo misc.lo
+am_libracoon_la_OBJECTS = libracoon_la-kmpstat.lo \
+ libracoon_la-vmbuf.lo libracoon_la-sockmisc.lo \
+ libracoon_la-misc.lo
libracoon_la_OBJECTS = $(am_libracoon_la_OBJECTS)
-sbinPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+libracoon_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libracoon_la_CFLAGS) \
+ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
PROGRAMS = $(noinst_PROGRAMS) $(sbin_PROGRAMS)
am_eaytest_OBJECTS = eaytest.$(OBJEXT) plog.$(OBJEXT) logger.$(OBJEXT)
eaytest_OBJECTS = $(am_eaytest_OBJECTS)
@@ -96,6 +117,7 @@ racoonctl_DEPENDENCIES = libracoon.la ../libipsec/libipsec.la
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
+am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
@@ -124,10 +146,11 @@ man5dir = $(mandir)/man5
man8dir = $(mandir)/man8
NROFF = nroff
MANS = $(man5_MANS) $(man8_MANS)
-include_racoonHEADERS_INSTALL = $(INSTALL_HEADER)
HEADERS = $(include_racoon_HEADERS) $(noinst_HEADERS)
ETAGS = etags
CTAGS = ctags
+am__tty_colors = \
+red=; grn=; lgn=; blu=; std=
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
@@ -143,23 +166,18 @@ CONFIGURE_AMFLAGS = @CONFIGURE_AMFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CRYPTOBJS = @CRYPTOBJS@
-CXX = @CXX@
-CXXCPP = @CXXCPP@
-CXXDEPMODE = @CXXDEPMODE@
-CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DSYMUTIL = @DSYMUTIL@
-ECHO = @ECHO@
+DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
EXTRA_CRYPTO = @EXTRA_CRYPTO@
-F77 = @F77@
-FFLAGS = @FFLAGS@
+FGREP = @FGREP@
FRAG_OBJS = @FRAG_OBJS@
GLIBC_BUGS = @GLIBC_BUGS@
GREP = @GREP@
@@ -173,6 +191,7 @@ INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
KERNEL_INCLUDE = @KERNEL_INCLUDE@
KRB5_CONFIG = @KRB5_CONFIG@
+LD = @LD@
LDFLAGS = @LDFLAGS@
LEX = @LEX@
LEXLIB = @LEXLIB@
@@ -180,18 +199,24 @@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
NATT_OBJS = @NATT_OBJS@
+NM = @NM@
NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@
@@ -209,8 +234,7 @@ abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
-ac_ct_CXX = @ac_ct_CXX@
-ac_ct_F77 = @ac_ct_F77@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -242,6 +266,7 @@ libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
@@ -254,10 +279,11 @@ sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
include_racoon_HEADERS = racoonctl.h var.h vmbuf.h misc.h gcmalloc.h admin.h \
- schedule.h sockmisc.h vmbuf.h isakmp_var.h isakmp.h isakmp_xauth.h \
+ schedule.h sockmisc.h isakmp_var.h isakmp.h isakmp_xauth.h \
isakmp_cfg.h isakmp_unity.h ipsec_doi.h evt.h
lib_LTLIBRARIES = libracoon.la
@@ -302,6 +328,7 @@ racoon_DEPENDENCIES = \
racoonctl_SOURCES = racoonctl.c str2val.c
racoonctl_LDADD = libracoon.la ../libipsec/libipsec.la
libracoon_la_SOURCES = kmpstat.c vmbuf.c sockmisc.c misc.c
+libracoon_la_CFLAGS = -DNOUSE_PRIVSEP $(AM_CFLAGS)
plainrsa_gen_SOURCES = plainrsa-gen.c plog.c \
crypto_openssl.c logger.c
@@ -341,6 +368,7 @@ EXTRA_DIST = \
${man5_MANS} ${man8_MANS} \
missing/crypto/rijndael/boxes-fst.dat \
doc/FAQ doc/README.certificate doc/README.gssapi doc/README.plainrsa \
+ doc/README.privsep \
contrib/sp.pl stats.pl \
samples/psk.txt.sample samples/racoon.conf.sample \
samples/psk.txt.in samples/racoon.conf.in \
@@ -362,14 +390,14 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
- && exit 0; \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/racoon/Makefile'; \
- cd $(top_srcdir) && \
- $(AUTOMAKE) --foreign src/racoon/Makefile
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/racoon/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign src/racoon/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
@@ -387,23 +415,28 @@ $(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
install-libLTLIBRARIES: $(lib_LTLIBRARIES)
@$(NORMAL_INSTALL)
test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
- @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ list2=; for p in $$list; do \
if test -f $$p; then \
- f=$(am__strip_dir) \
- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
+ list2="$$list2 $$p"; \
else :; fi; \
- done
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
+ }
uninstall-libLTLIBRARIES:
@$(NORMAL_UNINSTALL)
- @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
- p=$(am__strip_dir) \
- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
done
clean-libLTLIBRARIES:
@@ -415,42 +448,59 @@ clean-libLTLIBRARIES:
rm -f "$${dir}/so_locations"; \
done
libracoon.la: $(libracoon_la_OBJECTS) $(libracoon_la_DEPENDENCIES)
- $(LINK) -rpath $(libdir) $(libracoon_la_OBJECTS) $(libracoon_la_LIBADD) $(LIBS)
+ $(libracoon_la_LINK) -rpath $(libdir) $(libracoon_la_OBJECTS) $(libracoon_la_LIBADD) $(LIBS)
clean-noinstPROGRAMS:
- @list='$(noinst_PROGRAMS)'; for p in $$list; do \
- f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
- echo " rm -f $$p $$f"; \
- rm -f $$p $$f ; \
- done
+ @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
install-sbinPROGRAMS: $(sbin_PROGRAMS)
@$(NORMAL_INSTALL)
test -z "$(sbindir)" || $(MKDIR_P) "$(DESTDIR)$(sbindir)"
- @list='$(sbin_PROGRAMS)'; for p in $$list; do \
- p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
- if test -f $$p \
- || test -f $$p1 \
- ; then \
- f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
- echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(sbinPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(sbindir)/$$f'"; \
- $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(sbinPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(sbindir)/$$f" || exit 1; \
- else :; fi; \
- done
+ @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p || test -f $$p1; \
+ then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \
+ } \
+ ; done
uninstall-sbinPROGRAMS:
@$(NORMAL_UNINSTALL)
- @list='$(sbin_PROGRAMS)'; for p in $$list; do \
- f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
- echo " rm -f '$(DESTDIR)$(sbindir)/$$f'"; \
- rm -f "$(DESTDIR)$(sbindir)/$$f"; \
- done
+ @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(sbindir)" && rm -f $$files
clean-sbinPROGRAMS:
- @list='$(sbin_PROGRAMS)'; for p in $$list; do \
- f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
- echo " rm -f $$p $$f"; \
- rm -f $$p $$f ; \
- done
+ @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
eaytest$(EXEEXT): $(eaytest_OBJECTS) $(eaytest_DEPENDENCIES)
@rm -f eaytest$(EXEEXT)
$(LINK) $(eaytest_OBJECTS) $(eaytest_LDADD) $(LIBS)
@@ -506,11 +556,13 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isakmp_quick.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isakmp_unity.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isakmp_xauth.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kmpstat.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libracoon_la-kmpstat.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libracoon_la-misc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libracoon_la-sockmisc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libracoon_la-vmbuf.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/localconf.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logger.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nattraversal.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/oakley.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pfkey.Po@am__quote@
@@ -532,51 +584,77 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/security.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/session.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sha2.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sockmisc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/str2val.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strnames.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/throttle.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vendorid.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vmbuf.Plo@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c $<
.c.obj:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
.c.lo:
@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+libracoon_la-kmpstat.lo: kmpstat.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libracoon_la_CFLAGS) $(CFLAGS) -MT libracoon_la-kmpstat.lo -MD -MP -MF $(DEPDIR)/libracoon_la-kmpstat.Tpo -c -o libracoon_la-kmpstat.lo `test -f 'kmpstat.c' || echo '$(srcdir)/'`kmpstat.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libracoon_la-kmpstat.Tpo $(DEPDIR)/libracoon_la-kmpstat.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='kmpstat.c' object='libracoon_la-kmpstat.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libracoon_la_CFLAGS) $(CFLAGS) -c -o libracoon_la-kmpstat.lo `test -f 'kmpstat.c' || echo '$(srcdir)/'`kmpstat.c
+
+libracoon_la-vmbuf.lo: vmbuf.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libracoon_la_CFLAGS) $(CFLAGS) -MT libracoon_la-vmbuf.lo -MD -MP -MF $(DEPDIR)/libracoon_la-vmbuf.Tpo -c -o libracoon_la-vmbuf.lo `test -f 'vmbuf.c' || echo '$(srcdir)/'`vmbuf.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libracoon_la-vmbuf.Tpo $(DEPDIR)/libracoon_la-vmbuf.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='vmbuf.c' object='libracoon_la-vmbuf.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libracoon_la_CFLAGS) $(CFLAGS) -c -o libracoon_la-vmbuf.lo `test -f 'vmbuf.c' || echo '$(srcdir)/'`vmbuf.c
+
+libracoon_la-sockmisc.lo: sockmisc.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libracoon_la_CFLAGS) $(CFLAGS) -MT libracoon_la-sockmisc.lo -MD -MP -MF $(DEPDIR)/libracoon_la-sockmisc.Tpo -c -o libracoon_la-sockmisc.lo `test -f 'sockmisc.c' || echo '$(srcdir)/'`sockmisc.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libracoon_la-sockmisc.Tpo $(DEPDIR)/libracoon_la-sockmisc.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sockmisc.c' object='libracoon_la-sockmisc.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libracoon_la_CFLAGS) $(CFLAGS) -c -o libracoon_la-sockmisc.lo `test -f 'sockmisc.c' || echo '$(srcdir)/'`sockmisc.c
+
+libracoon_la-misc.lo: misc.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libracoon_la_CFLAGS) $(CFLAGS) -MT libracoon_la-misc.lo -MD -MP -MF $(DEPDIR)/libracoon_la-misc.Tpo -c -o libracoon_la-misc.lo `test -f 'misc.c' || echo '$(srcdir)/'`misc.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libracoon_la-misc.Tpo $(DEPDIR)/libracoon_la-misc.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc.c' object='libracoon_la-misc.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libracoon_la_CFLAGS) $(CFLAGS) -c -o libracoon_la-misc.lo `test -f 'misc.c' || echo '$(srcdir)/'`misc.c
+
sha2.obj: missing/crypto/sha2/sha2.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sha2.obj -MD -MP -MF $(DEPDIR)/sha2.Tpo -c -o sha2.obj `if test -f 'missing/crypto/sha2/sha2.c'; then $(CYGPATH_W) 'missing/crypto/sha2/sha2.c'; else $(CYGPATH_W) '$(srcdir)/missing/crypto/sha2/sha2.c'; fi`
-@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/sha2.Tpo $(DEPDIR)/sha2.Po
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/sha2.Tpo $(DEPDIR)/sha2.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='missing/crypto/sha2/sha2.c' object='sha2.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sha2.obj `if test -f 'missing/crypto/sha2/sha2.c'; then $(CYGPATH_W) 'missing/crypto/sha2/sha2.c'; else $(CYGPATH_W) '$(srcdir)/missing/crypto/sha2/sha2.c'; fi`
rijndael-api-fst.obj: missing/crypto/rijndael/rijndael-api-fst.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rijndael-api-fst.obj -MD -MP -MF $(DEPDIR)/rijndael-api-fst.Tpo -c -o rijndael-api-fst.obj `if test -f 'missing/crypto/rijndael/rijndael-api-fst.c'; then $(CYGPATH_W) 'missing/crypto/rijndael/rijndael-api-fst.c'; else $(CYGPATH_W) '$(srcdir)/missing/crypto/rijndael/rijndael-api-fst.c'; fi`
-@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rijndael-api-fst.Tpo $(DEPDIR)/rijndael-api-fst.Po
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/rijndael-api-fst.Tpo $(DEPDIR)/rijndael-api-fst.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='missing/crypto/rijndael/rijndael-api-fst.c' object='rijndael-api-fst.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rijndael-api-fst.obj `if test -f 'missing/crypto/rijndael/rijndael-api-fst.c'; then $(CYGPATH_W) 'missing/crypto/rijndael/rijndael-api-fst.c'; else $(CYGPATH_W) '$(srcdir)/missing/crypto/rijndael/rijndael-api-fst.c'; fi`
rijndael-alg-fst.obj: missing/crypto/rijndael/rijndael-alg-fst.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rijndael-alg-fst.obj -MD -MP -MF $(DEPDIR)/rijndael-alg-fst.Tpo -c -o rijndael-alg-fst.obj `if test -f 'missing/crypto/rijndael/rijndael-alg-fst.c'; then $(CYGPATH_W) 'missing/crypto/rijndael/rijndael-alg-fst.c'; else $(CYGPATH_W) '$(srcdir)/missing/crypto/rijndael/rijndael-alg-fst.c'; fi`
-@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rijndael-alg-fst.Tpo $(DEPDIR)/rijndael-alg-fst.Po
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/rijndael-alg-fst.Tpo $(DEPDIR)/rijndael-alg-fst.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='missing/crypto/rijndael/rijndael-alg-fst.c' object='rijndael-alg-fst.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rijndael-alg-fst.obj `if test -f 'missing/crypto/rijndael/rijndael-alg-fst.c'; then $(CYGPATH_W) 'missing/crypto/rijndael/rijndael-alg-fst.c'; else $(CYGPATH_W) '$(srcdir)/missing/crypto/rijndael/rijndael-alg-fst.c'; fi`
@@ -592,127 +670,108 @@ mostlyclean-libtool:
clean-libtool:
-rm -rf .libs _libs
-install-man5: $(man5_MANS) $(man_MANS)
+install-man5: $(man5_MANS)
@$(NORMAL_INSTALL)
test -z "$(man5dir)" || $(MKDIR_P) "$(DESTDIR)$(man5dir)"
- @list='$(man5_MANS) $(dist_man5_MANS) $(nodist_man5_MANS)'; \
- l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
- for i in $$l2; do \
- case "$$i" in \
- *.5*) list="$$list $$i" ;; \
- esac; \
+ @list='$(man5_MANS)'; test -n "$(man5dir)" || exit 0; \
+ { for i in $$list; do echo "$$i"; done; \
+ } | while read p; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; echo "$$p"; \
+ done | \
+ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
+ sed 'N;N;s,\n, ,g' | { \
+ list=; while read file base inst; do \
+ if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man5dir)/$$inst'"; \
+ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man5dir)/$$inst" || exit $$?; \
+ fi; \
done; \
- for i in $$list; do \
- if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
- else file=$$i; fi; \
- ext=`echo $$i | sed -e 's/^.*\\.//'`; \
- case "$$ext" in \
- 5*) ;; \
- *) ext='5' ;; \
- esac; \
- inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
- inst=`echo $$inst | sed -e 's/^.*\///'`; \
- inst=`echo $$inst | sed '$(transform)'`.$$ext; \
- echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man5dir)/$$inst'"; \
- $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man5dir)/$$inst"; \
- done
+ for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+ while read files; do \
+ test -z "$$files" || { \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man5dir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(man5dir)" || exit $$?; }; \
+ done; }
+
uninstall-man5:
@$(NORMAL_UNINSTALL)
- @list='$(man5_MANS) $(dist_man5_MANS) $(nodist_man5_MANS)'; \
- l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
- for i in $$l2; do \
- case "$$i" in \
- *.5*) list="$$list $$i" ;; \
- esac; \
- done; \
- for i in $$list; do \
- ext=`echo $$i | sed -e 's/^.*\\.//'`; \
- case "$$ext" in \
- 5*) ;; \
- *) ext='5' ;; \
- esac; \
- inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
- inst=`echo $$inst | sed -e 's/^.*\///'`; \
- inst=`echo $$inst | sed '$(transform)'`.$$ext; \
- echo " rm -f '$(DESTDIR)$(man5dir)/$$inst'"; \
- rm -f "$(DESTDIR)$(man5dir)/$$inst"; \
- done
-install-man8: $(man8_MANS) $(man_MANS)
+ @list='$(man5_MANS)'; test -n "$(man5dir)" || exit 0; \
+ files=`{ for i in $$list; do echo "$$i"; done; \
+ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+ test -z "$$files" || { \
+ echo " ( cd '$(DESTDIR)$(man5dir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(man5dir)" && rm -f $$files; }
+install-man8: $(man8_MANS)
@$(NORMAL_INSTALL)
test -z "$(man8dir)" || $(MKDIR_P) "$(DESTDIR)$(man8dir)"
- @list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \
- l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
- for i in $$l2; do \
- case "$$i" in \
- *.8*) list="$$list $$i" ;; \
- esac; \
+ @list='$(man8_MANS)'; test -n "$(man8dir)" || exit 0; \
+ { for i in $$list; do echo "$$i"; done; \
+ } | while read p; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; echo "$$p"; \
+ done | \
+ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
+ sed 'N;N;s,\n, ,g' | { \
+ list=; while read file base inst; do \
+ if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \
+ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \
+ fi; \
done; \
- for i in $$list; do \
- if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
- else file=$$i; fi; \
- ext=`echo $$i | sed -e 's/^.*\\.//'`; \
- case "$$ext" in \
- 8*) ;; \
- *) ext='8' ;; \
- esac; \
- inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
- inst=`echo $$inst | sed -e 's/^.*\///'`; \
- inst=`echo $$inst | sed '$(transform)'`.$$ext; \
- echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \
- $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst"; \
- done
+ for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+ while read files; do \
+ test -z "$$files" || { \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \
+ done; }
+
uninstall-man8:
@$(NORMAL_UNINSTALL)
- @list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \
- l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
- for i in $$l2; do \
- case "$$i" in \
- *.8*) list="$$list $$i" ;; \
- esac; \
- done; \
- for i in $$list; do \
- ext=`echo $$i | sed -e 's/^.*\\.//'`; \
- case "$$ext" in \
- 8*) ;; \
- *) ext='8' ;; \
- esac; \
- inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
- inst=`echo $$inst | sed -e 's/^.*\///'`; \
- inst=`echo $$inst | sed '$(transform)'`.$$ext; \
- echo " rm -f '$(DESTDIR)$(man8dir)/$$inst'"; \
- rm -f "$(DESTDIR)$(man8dir)/$$inst"; \
- done
+ @list='$(man8_MANS)'; test -n "$(man8dir)" || exit 0; \
+ files=`{ for i in $$list; do echo "$$i"; done; \
+ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+ test -z "$$files" || { \
+ echo " ( cd '$(DESTDIR)$(man8dir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(man8dir)" && rm -f $$files; }
install-include_racoonHEADERS: $(include_racoon_HEADERS)
@$(NORMAL_INSTALL)
test -z "$(include_racoondir)" || $(MKDIR_P) "$(DESTDIR)$(include_racoondir)"
- @list='$(include_racoon_HEADERS)'; for p in $$list; do \
+ @list='$(include_racoon_HEADERS)'; test -n "$(include_racoondir)" || list=; \
+ for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
- f=$(am__strip_dir) \
- echo " $(include_racoonHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(include_racoondir)/$$f'"; \
- $(include_racoonHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(include_racoondir)/$$f"; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(include_racoondir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(include_racoondir)" || exit $$?; \
done
uninstall-include_racoonHEADERS:
@$(NORMAL_UNINSTALL)
- @list='$(include_racoon_HEADERS)'; for p in $$list; do \
- f=$(am__strip_dir) \
- echo " rm -f '$(DESTDIR)$(include_racoondir)/$$f'"; \
- rm -f "$(DESTDIR)$(include_racoondir)/$$f"; \
- done
+ @list='$(include_racoon_HEADERS)'; test -n "$(include_racoondir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(include_racoondir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(include_racoondir)" && rm -f $$files
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
- $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
mkid -fID $$unique
tags: TAGS
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
- tags=; \
+ set x; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
@@ -720,37 +779,43 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
- if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
- $$tags $$unique; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
fi
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
- tags=; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
- test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
- $$tags $$unique
+ $$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
- && cd $(top_srcdir) \
- && gtags -i $(GTAGS_ARGS) $$here
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
check-TESTS: $(TESTS)
- @failed=0; all=0; xfail=0; xpass=0; skip=0; ws='[ ]'; \
+ @failed=0; all=0; xfail=0; xpass=0; skip=0; \
srcdir=$(srcdir); export srcdir; \
list=' $(TESTS) '; \
+ $(am__tty_colors); \
if test -n "$$list"; then \
for tst in $$list; do \
if test -f ./$$tst; then dir=./; \
@@ -759,49 +824,63 @@ check-TESTS: $(TESTS)
if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \
all=`expr $$all + 1`; \
case " $(XFAIL_TESTS) " in \
- *$$ws$$tst$$ws*) \
+ *[\ \ ]$$tst[\ \ ]*) \
xpass=`expr $$xpass + 1`; \
failed=`expr $$failed + 1`; \
- echo "XPASS: $$tst"; \
+ col=$$red; res=XPASS; \
;; \
*) \
- echo "PASS: $$tst"; \
+ col=$$grn; res=PASS; \
;; \
esac; \
elif test $$? -ne 77; then \
all=`expr $$all + 1`; \
case " $(XFAIL_TESTS) " in \
- *$$ws$$tst$$ws*) \
+ *[\ \ ]$$tst[\ \ ]*) \
xfail=`expr $$xfail + 1`; \
- echo "XFAIL: $$tst"; \
+ col=$$lgn; res=XFAIL; \
;; \
*) \
failed=`expr $$failed + 1`; \
- echo "FAIL: $$tst"; \
+ col=$$red; res=FAIL; \
;; \
esac; \
else \
skip=`expr $$skip + 1`; \
- echo "SKIP: $$tst"; \
+ col=$$blu; res=SKIP; \
fi; \
+ echo "$${col}$$res$${std}: $$tst"; \
done; \
+ if test "$$all" -eq 1; then \
+ tests="test"; \
+ All=""; \
+ else \
+ tests="tests"; \
+ All="All "; \
+ fi; \
if test "$$failed" -eq 0; then \
if test "$$xfail" -eq 0; then \
- banner="All $$all tests passed"; \
+ banner="$$All$$all $$tests passed"; \
else \
- banner="All $$all tests behaved as expected ($$xfail expected failures)"; \
+ if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \
+ banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \
fi; \
else \
if test "$$xpass" -eq 0; then \
- banner="$$failed of $$all tests failed"; \
+ banner="$$failed of $$all $$tests failed"; \
else \
- banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \
+ if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \
+ banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \
fi; \
fi; \
dashes="$$banner"; \
skipped=""; \
if test "$$skip" -ne 0; then \
- skipped="($$skip tests were not run)"; \
+ if test "$$skip" -eq 1; then \
+ skipped="($$skip test was not run)"; \
+ else \
+ skipped="($$skip tests were not run)"; \
+ fi; \
test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
dashes="$$skipped"; \
fi; \
@@ -812,15 +891,32 @@ check-TESTS: $(TESTS)
dashes="$$report"; \
fi; \
dashes=`echo "$$dashes" | sed s/./=/g`; \
- echo "$$dashes"; \
+ if test "$$failed" -eq 0; then \
+ echo "$$grn$$dashes"; \
+ else \
+ echo "$$red$$dashes"; \
+ fi; \
echo "$$banner"; \
test -z "$$skipped" || echo "$$skipped"; \
test -z "$$report" || echo "$$report"; \
- echo "$$dashes"; \
+ echo "$$dashes$$std"; \
test "$$failed" -eq 0; \
else :; fi
distdir: $(DISTFILES)
+ @list='$(MANS)'; if test -n "$$list"; then \
+ list=`for p in $$list; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \
+ if test -n "$$list" && \
+ grep 'ab help2man is required to generate this page' $$list >/dev/null; then \
+ echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \
+ grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \
+ echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \
+ echo " typically \`make maintainer-clean' will remove them" >&2; \
+ exit 1; \
+ else :; fi; \
+ else :; fi
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
@@ -836,13 +932,17 @@ distdir: $(DISTFILES)
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
- cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
- cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
- test -f $(distdir)/$$file \
- || cp -p $$d/$$file $(distdir)/$$file \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
@@ -876,6 +976,7 @@ clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@@ -904,6 +1005,8 @@ dvi-am:
html: html-am
+html-am:
+
info: info-am
info-am:
@@ -912,19 +1015,29 @@ install-data-am: install-include_racoonHEADERS install-man
install-dvi: install-dvi-am
+install-dvi-am:
+
install-exec-am: install-exec-local install-libLTLIBRARIES \
install-sbinPROGRAMS
install-html: install-html-am
+install-html-am:
+
install-info: install-info-am
+install-info-am:
+
install-man: install-man5 install-man8
install-pdf: install-pdf-am
+install-pdf-am:
+
install-ps: install-ps-am
+install-ps-am:
+
installcheck-am:
maintainer-clean: maintainer-clean-am
@@ -950,7 +1063,7 @@ uninstall-am: uninstall-include_racoonHEADERS uninstall-libLTLIBRARIES \
uninstall-man: uninstall-man5 uninstall-man8
-.MAKE: install-am install-strip
+.MAKE: all check check-am install install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-TESTS check-am clean \
clean-generic clean-libLTLIBRARIES clean-libtool \
@@ -995,6 +1108,7 @@ rijndael-alg-fst.o: $(srcdir)/missing/crypto/rijndael/rijndael-alg-fst.c
$(COMPILE) -c $(srcdir)/missing/crypto/rijndael/$*.c
sha2.o: $(srcdir)/missing/crypto/sha2/sha2.c
$(COMPILE) -c $(srcdir)/missing/crypto/sha2/$*.c
+
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
diff --git a/src/racoon/admin.c b/src/racoon/admin.c
index b56dd2c..b0aad88 100644
--- a/src/racoon/admin.c
+++ b/src/racoon/admin.c
@@ -1,11 +1,11 @@
-/* $NetBSD: admin.c,v 1.17.6.3 2009/04/20 13:32:57 tteras Exp $ */
+/* $NetBSD: admin.c,v 1.38 2010/12/08 07:38:35 tteras Exp $ */
/* Id: admin.c,v 1.25 2006/04/06 14:31:04 manubsd Exp */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -17,7 +17,7 @@
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -76,6 +76,7 @@
#include "evt.h"
#include "pfkey.h"
#include "ipsec_doi.h"
+#include "policy.h"
#include "admin.h"
#include "admin_var.h"
#include "isakmp_inf.h"
@@ -93,10 +94,12 @@ mode_t adminsock_mode = 0600;
static struct sockaddr_un sunaddr;
static int admin_process __P((int, char *));
-static int admin_reply __P((int, struct admin_com *, vchar_t *));
+static int admin_reply __P((int, struct admin_com *, int, vchar_t *));
-int
-admin_handler()
+static int
+admin_handler(ctx, fd)
+ void *ctx;
+ int fd;
{
int so2;
struct sockaddr_storage from;
@@ -112,6 +115,7 @@ admin_handler()
strerror(errno));
return -1;
}
+ close_on_exec(so2);
/* get buffer length */
while ((len = recv(so2, (char *)&com, sizeof(com), MSG_PEEK)) < 0) {
@@ -147,22 +151,30 @@ admin_handler()
goto end;
}
- if (com.ac_cmd == ADMIN_RELOAD_CONF) {
- /* reload does not work at all! */
- signal_handler(SIGHUP);
- goto end;
- }
-
error = admin_process(so2, combuf);
- end:
- (void)close(so2);
+end:
+ if (error == -2) {
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "[%d] admin connection established\n", so2);
+ } else {
+ (void)close(so2);
+ }
+
if (combuf)
racoon_free(combuf);
return error;
}
+static int admin_ph1_delete_sa(struct ph1handle *iph1, void *arg)
+{
+ if (iph1->status >= PHASE1ST_ESTABLISHED)
+ isakmp_info_send_d1(iph1);
+ purge_remote(iph1);
+ return 0;
+}
+
/*
* main child's process.
*/
@@ -176,131 +188,140 @@ admin_process(so2, combuf)
vchar_t *id = NULL;
vchar_t *key = NULL;
int idtype = 0;
- int error = -1;
+ int error = 0, l_ac_errno = 0;
+ struct evt_listener_list *event_list = NULL;
- com->ac_errno = 0;
+ if (com->ac_cmd & ADMIN_FLAG_VERSION)
+ com->ac_cmd &= ~ADMIN_FLAG_VERSION;
+ else
+ com->ac_version = 0;
switch (com->ac_cmd) {
case ADMIN_RELOAD_CONF:
- /* don't entered because of proccessing it in other place. */
- plog(LLV_ERROR, LOCATION, NULL, "should never reach here\n");
- goto out;
+ signal_handler(SIGHUP);
+ break;
- case ADMIN_SHOW_SCHED:
- {
+ case ADMIN_SHOW_SCHED: {
caddr_t p = NULL;
int len;
- com->ac_errno = -1;
-
- if (sched_dump(&p, &len) == -1)
- goto out2;
-
- if ((buf = vmalloc(len)) == NULL)
- goto out2;
-
- memcpy(buf->v, p, len);
-
- com->ac_errno = 0;
-out2:
- racoon_free(p);
+ if (sched_dump(&p, &len) != -1) {
+ buf = vmalloc(len);
+ if (buf != NULL)
+ memcpy(buf->v, p, len);
+ else
+ l_ac_errno = ENOMEM;
+ racoon_free(p);
+ } else
+ l_ac_errno = ENOMEM;
break;
}
case ADMIN_SHOW_EVT:
- /* It's not really an error, don't force racoonctl to quit */
- if ((buf = evt_dump()) == NULL)
- com->ac_errno = 0;
+ if (com->ac_version == 0) {
+ buf = evt_dump();
+ l_ac_errno = 0;
+ }
break;
case ADMIN_SHOW_SA:
- case ADMIN_FLUSH_SA:
- {
switch (com->ac_proto) {
case ADMIN_PROTO_ISAKMP:
- switch (com->ac_cmd) {
- case ADMIN_SHOW_SA:
- buf = dumpph1();
- if (buf == NULL)
- com->ac_errno = -1;
- break;
- case ADMIN_FLUSH_SA:
- flushph1();
- break;
- }
+ buf = dumpph1();
+ if (buf == NULL)
+ l_ac_errno = ENOMEM;
break;
case ADMIN_PROTO_IPSEC:
case ADMIN_PROTO_AH:
- case ADMIN_PROTO_ESP:
- switch (com->ac_cmd) {
- case ADMIN_SHOW_SA:
- {
- u_int p;
- p = admin2pfkey_proto(com->ac_proto);
- if (p == -1)
- goto out;
+ case ADMIN_PROTO_ESP: {
+ u_int p;
+ p = admin2pfkey_proto(com->ac_proto);
+ if (p != -1) {
buf = pfkey_dump_sadb(p);
if (buf == NULL)
- com->ac_errno = -1;
- }
- break;
- case ADMIN_FLUSH_SA:
- pfkey_flush_sadb(com->ac_proto);
- break;
- }
+ l_ac_errno = ENOMEM;
+ } else
+ l_ac_errno = EINVAL;
break;
-
+ }
case ADMIN_PROTO_INTERNAL:
- switch (com->ac_cmd) {
- case ADMIN_SHOW_SA:
- buf = NULL; /*XXX dumpph2(&error);*/
- if (buf == NULL)
- com->ac_errno = error;
- break;
- case ADMIN_FLUSH_SA:
- /*XXX flushph2();*/
- com->ac_errno = 0;
- break;
- }
+ default:
+ l_ac_errno = ENOTSUP;
+ break;
+ }
+ break;
+
+ case ADMIN_GET_SA_CERT: {
+ struct admin_com_indexes *ndx;
+ struct sockaddr *src, *dst;
+ struct ph1handle *iph1;
+
+ ndx = (struct admin_com_indexes *) ((caddr_t)com + sizeof(*com));
+ src = (struct sockaddr *) &ndx->src;
+ dst = (struct sockaddr *) &ndx->dst;
+
+ if (com->ac_proto != ADMIN_PROTO_ISAKMP) {
+ l_ac_errno = ENOTSUP;
break;
+ }
+
+ iph1 = getph1byaddr(src, dst, 0);
+ if (iph1 == NULL) {
+ l_ac_errno = ENOENT;
+ break;
+ }
+ if (iph1->cert_p != NULL) {
+ vchar_t tmp;
+ tmp.v = iph1->cert_p->v + 1;
+ tmp.l = iph1->cert_p->l - 1;
+ buf = vdup(&tmp);
+ }
+ break;
+ }
+
+ case ADMIN_FLUSH_SA:
+ switch (com->ac_proto) {
+ case ADMIN_PROTO_ISAKMP:
+ flushph1();
+ break;
+ case ADMIN_PROTO_IPSEC:
+ case ADMIN_PROTO_AH:
+ case ADMIN_PROTO_ESP:
+ pfkey_flush_sadb(com->ac_proto);
+ break;
+ case ADMIN_PROTO_INTERNAL:
+ /*XXX flushph2();*/
default:
- /* ignore */
- com->ac_errno = -1;
+ l_ac_errno = ENOTSUP;
+ break;
}
- }
break;
case ADMIN_DELETE_SA: {
- struct ph1handle *iph1;
- struct sockaddr *dst;
- struct sockaddr *src;
char *loc, *rem;
+ struct ph1selector sel;
- src = (struct sockaddr *)
+ memset(&sel, 0, sizeof(sel));
+ sel.local = (struct sockaddr *)
&((struct admin_com_indexes *)
((caddr_t)com + sizeof(*com)))->src;
- dst = (struct sockaddr *)
+ sel.remote = (struct sockaddr *)
&((struct admin_com_indexes *)
((caddr_t)com + sizeof(*com)))->dst;
- loc = racoon_strdup(saddrwop2str(src));
- rem = racoon_strdup(saddrwop2str(dst));
+ loc = racoon_strdup(saddr2str(sel.local));
+ rem = racoon_strdup(saddr2str(sel.remote));
STRDUP_FATAL(loc);
STRDUP_FATAL(rem);
- if ((iph1 = getph1byaddrwop(src, dst)) == NULL) {
- plog(LLV_ERROR, LOCATION, NULL,
- "phase 1 for %s -> %s not found\n", loc, rem);
- } else {
- if (iph1->status == PHASE1ST_ESTABLISHED)
- isakmp_info_send_d1(iph1);
- purge_remote(iph1);
- }
+ plog(LLV_INFO, LOCATION, NULL,
+ "admin delete-sa %s %s\n", loc, rem);
+ enumph1(&sel, admin_ph1_delete_sa, NULL);
+ remcontacted(sel.remote);
racoon_free(loc);
racoon_free(rem);
-
break;
}
@@ -308,7 +329,7 @@ out2:
case ADMIN_LOGOUT_USER: {
struct ph1handle *iph1;
char user[LOGINLEN+1];
- int found = 0, len = com->ac_len - sizeof(com);
+ int found = 0, len = com->ac_len - sizeof(*com);
if (len > LOGINLEN) {
plog(LLV_ERROR, LOCATION, NULL,
@@ -320,7 +341,7 @@ out2:
user[len] = 0;
found = purgeph1bylogin(user);
- plog(LLV_INFO, LOCATION, NULL,
+ plog(LLV_INFO, LOCATION, NULL,
"deleted %d SA for user \"%s\"\n", found, user);
break;
@@ -339,22 +360,21 @@ out2:
rem = racoon_strdup(saddrwop2str(dst));
STRDUP_FATAL(rem);
- plog(LLV_INFO, LOCATION, NULL,
+ plog(LLV_INFO, LOCATION, NULL,
"Flushing all SAs for peer %s\n", rem);
- while ((iph1 = getph1bydstaddrwop(dst)) != NULL) {
+ while ((iph1 = getph1bydstaddr(dst)) != NULL) {
loc = racoon_strdup(saddrwop2str(iph1->local));
STRDUP_FATAL(loc);
- if (iph1->status == PHASE1ST_ESTABLISHED)
+ if (iph1->status >= PHASE1ST_ESTABLISHED)
isakmp_info_send_d1(iph1);
purge_remote(iph1);
racoon_free(loc);
}
-
- racoon_free(rem);
+ racoon_free(rem);
break;
}
@@ -362,17 +382,15 @@ out2:
struct admin_com_psk *acp;
char *data;
- com->ac_cmd = ADMIN_ESTABLISH_SA;
-
acp = (struct admin_com_psk *)
- ((char *)com + sizeof(*com) +
+ ((char *)com + sizeof(*com) +
sizeof(struct admin_com_indexes));
idtype = acp->id_type;
if ((id = vmalloc(acp->id_len)) == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
- "cannot allocate memory: %s\n",
+ "cannot allocate memory: %s\n",
strerror(errno));
break;
}
@@ -381,7 +399,7 @@ out2:
if ((key = vmalloc(acp->key_len)) == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
- "cannot allocate memory: %s\n",
+ "cannot allocate memory: %s\n",
strerror(errno));
vfree(id);
id = NULL;
@@ -391,56 +409,57 @@ out2:
memcpy(key->v, data, key->l);
}
/* FALLTHROUGH */
- case ADMIN_ESTABLISH_SA:
- {
+ case ADMIN_ESTABLISH_SA: {
+ struct admin_com_indexes *ndx;
struct sockaddr *dst;
struct sockaddr *src;
- src = (struct sockaddr *)
- &((struct admin_com_indexes *)
- ((caddr_t)com + sizeof(*com)))->src;
- dst = (struct sockaddr *)
- &((struct admin_com_indexes *)
- ((caddr_t)com + sizeof(*com)))->dst;
+ char *name = NULL;
+
+ ndx = (struct admin_com_indexes *) ((caddr_t)com + sizeof(*com));
+ src = (struct sockaddr *) &ndx->src;
+ dst = (struct sockaddr *) &ndx->dst;
+
+ if (com->ac_cmd == ADMIN_ESTABLISH_SA &&
+ com->ac_len > sizeof(*com) + sizeof(*ndx))
+ name = (char *) ((caddr_t) ndx + sizeof(*ndx));
switch (com->ac_proto) {
case ADMIN_PROTO_ISAKMP: {
+ struct ph1handle *ph1;
struct remoteconf *rmconf;
- struct sockaddr *remote = NULL;
- struct sockaddr *local = NULL;
u_int16_t port;
- com->ac_errno = -1;
+ l_ac_errno = -1;
+
+ /* connected already? */
+ ph1 = getph1byaddr(src, dst, 0);
+ if (ph1 != NULL) {
+ event_list = &ph1->evt_listeners;
+ if (ph1->status == PHASE1ST_ESTABLISHED)
+ l_ac_errno = EEXIST;
+ else
+ l_ac_errno = 0;
+ break;
+ }
/* search appropreate configuration */
- rmconf = getrmconf(dst);
+ if (name == NULL)
+ rmconf = getrmconf(dst, 0);
+ else
+ rmconf = getrmconf_by_name(name);
if (rmconf == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
"no configuration found "
"for %s\n", saddrwop2str(dst));
- goto out1;
+ break;
}
- /* get remote IP address and port number. */
- if ((remote = dupsaddr(dst)) == NULL)
- goto out1;
-
- port = extract_port(rmconf->remote);
- if (set_port(remote, port) == NULL)
- goto out1;
-
- /* get local address */
- if ((local = dupsaddr(src)) == NULL)
- goto out1;
-
- port = getmyaddrsport(local);
- if (set_port(local, port) == NULL)
- goto out1;
-
#ifdef ENABLE_HYBRID
+ /* XXX This overwrites rmconf information globally. */
/* Set the id and key */
if (id && key) {
if (xauth_rmconf_used(&rmconf->xauth) == -1)
- goto out1;
+ break;
if (rmconf->xauth->login != NULL) {
vfree(rmconf->xauth->login);
@@ -455,43 +474,145 @@ out2:
rmconf->xauth->pass = key;
}
#endif
-
+
plog(LLV_INFO, LOCATION, NULL,
"accept a request to establish IKE-SA: "
- "%s\n", saddrwop2str(remote));
+ "%s\n", saddrwop2str(dst));
/* begin ident mode */
- if (isakmp_ph1begin_i(rmconf, remote, local) < 0)
- goto out1;
-
- com->ac_errno = 0;
-out1:
- if (local != NULL)
- racoon_free(local);
- if (remote != NULL)
- racoon_free(remote);
+ ph1 = isakmp_ph1begin_i(rmconf, dst, src);
+ if (ph1 == NULL)
+ break;
+
+ event_list = &ph1->evt_listeners;
+ l_ac_errno = 0;
break;
}
case ADMIN_PROTO_AH:
- case ADMIN_PROTO_ESP:
+ case ADMIN_PROTO_ESP: {
+ struct ph2handle *iph2;
+ struct secpolicy *sp_out = NULL, *sp_in = NULL;
+ struct policyindex spidx;
+
+ l_ac_errno = -1;
+
+ /* got outbound policy */
+ memset(&spidx, 0, sizeof(spidx));
+ spidx.dir = IPSEC_DIR_OUTBOUND;
+ memcpy(&spidx.src, src, sizeof(spidx.src));
+ memcpy(&spidx.dst, dst, sizeof(spidx.dst));
+ spidx.prefs = ndx->prefs;
+ spidx.prefd = ndx->prefd;
+ spidx.ul_proto = ndx->ul_proto;
+
+ sp_out = getsp_r(&spidx);
+ if (sp_out) {
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "suitable outbound SP found: %s.\n",
+ spidx2str(&sp_out->spidx));
+ } else {
+ l_ac_errno = ENOENT;
+ plog(LLV_NOTIFY, LOCATION, NULL,
+ "no outbound policy found: %s\n",
+ spidx2str(&spidx));
+ break;
+ }
+
+ iph2 = getph2byid(src, dst, sp_out->id);
+ if (iph2 != NULL) {
+ event_list = &iph2->evt_listeners;
+ if (iph2->status == PHASE2ST_ESTABLISHED)
+ l_ac_errno = EEXIST;
+ else
+ l_ac_errno = 0;
+ break;
+ }
+
+ /* get inbound policy */
+ memset(&spidx, 0, sizeof(spidx));
+ spidx.dir = IPSEC_DIR_INBOUND;
+ memcpy(&spidx.src, dst, sizeof(spidx.src));
+ memcpy(&spidx.dst, src, sizeof(spidx.dst));
+ spidx.prefs = ndx->prefd;
+ spidx.prefd = ndx->prefs;
+ spidx.ul_proto = ndx->ul_proto;
+
+ sp_in = getsp_r(&spidx);
+ if (sp_in) {
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "suitable inbound SP found: %s.\n",
+ spidx2str(&sp_in->spidx));
+ } else {
+ l_ac_errno = ENOENT;
+ plog(LLV_NOTIFY, LOCATION, NULL,
+ "no inbound policy found: %s\n",
+ spidx2str(&spidx));
+ break;
+ }
+
+ /* allocate a phase 2 */
+ iph2 = newph2();
+ if (iph2 == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "failed to allocate phase2 entry.\n");
+ break;
+ }
+ iph2->side = INITIATOR;
+ iph2->satype = admin2pfkey_proto(com->ac_proto);
+ iph2->spid = sp_out->id;
+ iph2->seq = pk_getseq();
+ iph2->status = PHASE2ST_STATUS2;
+
+ /* set end addresses of SA */
+ iph2->sa_dst = dupsaddr(dst);
+ iph2->sa_src = dupsaddr(src);
+ iph2->dst = dupsaddr(dst);
+ iph2->src = dupsaddr(src);
+ if (iph2->sa_src == NULL || iph2->sa_dst == NULL ||
+ iph2->dst == NULL || iph2->src == NULL) {
+ delph2(iph2);
+ break;
+ }
+ set_port(iph2->dst, 0);
+ set_port(iph2->src, 0);
+
+ if (isakmp_get_sainfo(iph2, sp_out, sp_in) < 0) {
+ delph2(iph2);
+ break;
+ }
+
+ insph2(iph2);
+ if (isakmp_post_acquire(iph2, NULL, FALSE) < 0) {
+ remph2(iph2);
+ delph2(iph2);
+ break;
+ }
+
+ event_list = &iph2->evt_listeners;
+ l_ac_errno = 0;
break;
+ }
default:
/* ignore */
- com->ac_errno = -1;
+ l_ac_errno = ENOTSUP;
}
- }
break;
+ }
default:
plog(LLV_ERROR, LOCATION, NULL,
"invalid command: %d\n", com->ac_cmd);
- com->ac_errno = -1;
+ l_ac_errno = ENOTSUP;
}
- if ((error = admin_reply(so2, com, buf)) != 0)
+ if ((error = admin_reply(so2, com, l_ac_errno, buf)) != 0)
goto out;
- error = 0;
+ /* start pushing events if so requested */
+ if ((l_ac_errno == 0) &&
+ (com->ac_version >= 1) &&
+ (com->ac_cmd == ADMIN_SHOW_EVT || event_list != NULL))
+ error = evt_subscribe(event_list, so2);
out:
if (buf != NULL)
vfree(buf);
@@ -500,12 +621,13 @@ out:
}
static int
-admin_reply(so, combuf, buf)
- int so;
- struct admin_com *combuf;
+admin_reply(so, req, l_ac_errno, buf)
+ int so, l_ac_errno;
+ struct admin_com *req;
vchar_t *buf;
{
int tlen;
+ struct admin_com *combuf;
char *retbuf = NULL;
if (buf != NULL)
@@ -520,8 +642,17 @@ admin_reply(so, combuf, buf)
return -1;
}
- memcpy(retbuf, combuf, sizeof(*combuf));
- ((struct admin_com *)retbuf)->ac_len = tlen;
+ combuf = (struct admin_com *) retbuf;
+ combuf->ac_len = (u_int16_t) tlen;
+ combuf->ac_cmd = req->ac_cmd & ~ADMIN_FLAG_VERSION;
+ if (tlen != (u_int32_t) combuf->ac_len &&
+ l_ac_errno == 0) {
+ combuf->ac_len_high = tlen >> 16;
+ combuf->ac_cmd |= ADMIN_FLAG_LONG_REPLY;
+ } else {
+ combuf->ac_errno = l_ac_errno;
+ }
+ combuf->ac_proto = req->ac_proto;
if (buf != NULL)
memcpy(retbuf + sizeof(*combuf), buf->v, buf->l);
@@ -577,6 +708,7 @@ admin_init()
"socket: %s\n", strerror(errno));
return -1;
}
+ close_on_exec(lcconf->sock_admin);
unlink(sunaddr.sun_path);
if (bind(lcconf->sock_admin, (struct sockaddr *)&sunaddr,
@@ -589,17 +721,17 @@ admin_init()
}
if (chown(sunaddr.sun_path, adminsock_owner, adminsock_group) != 0) {
- plog(LLV_ERROR, LOCATION, NULL,
- "chown(%s, %d, %d): %s\n",
- sunaddr.sun_path, adminsock_owner,
+ plog(LLV_ERROR, LOCATION, NULL,
+ "chown(%s, %d, %d): %s\n",
+ sunaddr.sun_path, adminsock_owner,
adminsock_group, strerror(errno));
(void)close(lcconf->sock_admin);
return -1;
}
if (chmod(sunaddr.sun_path, adminsock_mode) != 0) {
- plog(LLV_ERROR, LOCATION, NULL,
- "chmod(%s, 0%03o): %s\n",
+ plog(LLV_ERROR, LOCATION, NULL,
+ "chmod(%s, 0%03o): %s\n",
sunaddr.sun_path, adminsock_mode, strerror(errno));
(void)close(lcconf->sock_admin);
return -1;
@@ -612,8 +744,10 @@ admin_init()
(void)close(lcconf->sock_admin);
return -1;
}
+
+ monitor_fd(lcconf->sock_admin, admin_handler, NULL, 0);
plog(LLV_DEBUG, LOCATION, NULL,
- "open %s as racoon management.\n", sunaddr.sun_path);
+ "open %s as racoon management.\n", sunaddr.sun_path);
return 0;
}
@@ -621,8 +755,9 @@ admin_init()
int
admin_close()
{
+ unmonitor_fd(lcconf->sock_admin);
close(lcconf->sock_admin);
return 0;
}
-#endif
+#endif
diff --git a/src/racoon/admin.h b/src/racoon/admin.h
index cbc19e8..8cb9382 100644
--- a/src/racoon/admin.h
+++ b/src/racoon/admin.h
@@ -1,4 +1,4 @@
-/* $NetBSD: admin.h,v 1.4 2006/09/09 16:22:09 manu Exp $ */
+/* $NetBSD: admin.h,v 1.8 2010/11/12 09:08:26 tteras Exp $ */
/* Id: admin.h,v 1.11 2005/06/19 22:37:47 manubsd Exp */
@@ -46,9 +46,22 @@ extern mode_t adminsock_mode;
struct admin_com {
u_int16_t ac_len; /* total packet length including data */
u_int16_t ac_cmd;
- int16_t ac_errno;
+ union {
+ int16_t ac_un_errno;
+ uint16_t ac_un_version;
+ uint16_t ac_un_len_high;
+ } u;
u_int16_t ac_proto;
};
+#define ac_errno u.ac_un_errno
+#define ac_version u.ac_un_version
+#define ac_len_high u.ac_un_len_high
+
+/*
+ * Version field in request is valid.
+ */
+#define ADMIN_FLAG_VERSION 0x8000
+#define ADMIN_FLAG_LONG_REPLY 0x8000
/*
* No data follows as the data.
@@ -72,6 +85,8 @@ struct admin_com {
#define ADMIN_ESTABLISH_SA 0x0202
#define ADMIN_DELETE_ALL_SA_DST 0x0204 /* All SA for a given peer */
+#define ADMIN_GET_SA_CERT 0x0206
+
/*
* The admin_com_indexes and admin_com_psk follow, see below.
*/
diff --git a/src/racoon/admin_var.h b/src/racoon/admin_var.h
index 6d7ba81..f4471a3 100644
--- a/src/racoon/admin_var.h
+++ b/src/racoon/admin_var.h
@@ -1,4 +1,4 @@
-/* $NetBSD: admin_var.h,v 1.4 2006/09/09 16:22:09 manu Exp $ */
+/* $NetBSD: admin_var.h,v 1.5 2008/12/23 14:03:12 tteras Exp $ */
/* Id: admin_var.h,v 1.7 2004/12/30 00:08:30 manubsd Exp */
@@ -34,7 +34,6 @@
#ifndef _ADMIN_VAR_H
#define _ADMIN_VAR_H
-extern int admin_handler __P((void));
extern int admin_init __P((void));
extern int admin_close __P((void));
diff --git a/src/racoon/backupsa.c b/src/racoon/backupsa.c
index 9496000..82d74ca 100644
--- a/src/racoon/backupsa.c
+++ b/src/racoon/backupsa.c
@@ -1,4 +1,4 @@
-/* $NetBSD: backupsa.c,v 1.8.4.1 2007/08/01 11:52:19 vanhu Exp $ */
+/* $NetBSD: backupsa.c,v 1.10 2010/04/02 15:15:00 christos Exp $ */
/* $KAME: backupsa.c,v 1.16 2001/12/31 20:13:40 thorpej Exp $ */
@@ -452,7 +452,7 @@ main()
struct tm tm;
time_t t;
char *buf = "Nov 24 18:22:48 1986 ";
- char *p;
+ const char *p;
memset(&tm, 0, sizeof(tm));
p = str2tmx(buf, &tm);
@@ -460,7 +460,8 @@ main()
t = mktime(&tm);
if (t == -1)
printf("mktime failed.");
- p = ctime(&t);
+ if ((p = ctime(&t)) == NULL)
+ p = "?";
printf("[%s]\n", p);
exit(0);
diff --git a/src/racoon/cfparse.h b/src/racoon/cfparse.h
index 2946b3e..bbf678a 100644
--- a/src/racoon/cfparse.h
+++ b/src/racoon/cfparse.h
@@ -1,24 +1,23 @@
-/* A Bison parser, made by GNU Bison 2.3. */
-/* Skeleton interface for Bison's Yacc-like parsers in C
+/* A Bison parser, made by GNU Bison 2.4.1. */
- Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+/* Skeleton interface for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
+
+ This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
@@ -29,10 +28,11 @@
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
-
+
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
+
/* Tokens. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
@@ -46,161 +46,170 @@
PATH = 262,
PATHTYPE = 263,
INCLUDE = 264,
- IDENTIFIER = 265,
- VENDORID = 266,
- LOGGING = 267,
- LOGLEV = 268,
- PADDING = 269,
- PAD_RANDOMIZE = 270,
- PAD_RANDOMIZELEN = 271,
- PAD_MAXLEN = 272,
- PAD_STRICT = 273,
- PAD_EXCLTAIL = 274,
- LISTEN = 275,
- X_ISAKMP = 276,
- X_ISAKMP_NATT = 277,
- X_ADMIN = 278,
- STRICT_ADDRESS = 279,
- ADMINSOCK = 280,
- DISABLED = 281,
- LDAPCFG = 282,
- LDAP_HOST = 283,
- LDAP_PORT = 284,
- LDAP_PVER = 285,
- LDAP_BASE = 286,
- LDAP_BIND_DN = 287,
- LDAP_BIND_PW = 288,
- LDAP_SUBTREE = 289,
- LDAP_ATTR_USER = 290,
- LDAP_ATTR_ADDR = 291,
- LDAP_ATTR_MASK = 292,
- LDAP_ATTR_GROUP = 293,
- LDAP_ATTR_MEMBER = 294,
- MODECFG = 295,
- CFG_NET4 = 296,
- CFG_MASK4 = 297,
- CFG_DNS4 = 298,
- CFG_NBNS4 = 299,
- CFG_DEFAULT_DOMAIN = 300,
- CFG_AUTH_SOURCE = 301,
- CFG_AUTH_GROUPS = 302,
- CFG_SYSTEM = 303,
- CFG_RADIUS = 304,
- CFG_PAM = 305,
- CFG_LDAP = 306,
- CFG_LOCAL = 307,
- CFG_NONE = 308,
- CFG_GROUP_SOURCE = 309,
- CFG_ACCOUNTING = 310,
- CFG_CONF_SOURCE = 311,
- CFG_MOTD = 312,
- CFG_POOL_SIZE = 313,
- CFG_AUTH_THROTTLE = 314,
- CFG_SPLIT_NETWORK = 315,
- CFG_SPLIT_LOCAL = 316,
- CFG_SPLIT_INCLUDE = 317,
- CFG_SPLIT_DNS = 318,
- CFG_PFS_GROUP = 319,
- CFG_SAVE_PASSWD = 320,
- RETRY = 321,
- RETRY_COUNTER = 322,
- RETRY_INTERVAL = 323,
- RETRY_PERSEND = 324,
- RETRY_PHASE1 = 325,
- RETRY_PHASE2 = 326,
- NATT_KA = 327,
- ALGORITHM_CLASS = 328,
- ALGORITHMTYPE = 329,
- STRENGTHTYPE = 330,
- SAINFO = 331,
- FROM = 332,
- REMOTE = 333,
- ANONYMOUS = 334,
- INHERIT = 335,
- EXCHANGE_MODE = 336,
- EXCHANGETYPE = 337,
- DOI = 338,
- DOITYPE = 339,
- SITUATION = 340,
- SITUATIONTYPE = 341,
- CERTIFICATE_TYPE = 342,
- CERTTYPE = 343,
- PEERS_CERTFILE = 344,
- CA_TYPE = 345,
- VERIFY_CERT = 346,
- SEND_CERT = 347,
- SEND_CR = 348,
- IDENTIFIERTYPE = 349,
- IDENTIFIERQUAL = 350,
- MY_IDENTIFIER = 351,
- PEERS_IDENTIFIER = 352,
- VERIFY_IDENTIFIER = 353,
- DNSSEC = 354,
- CERT_X509 = 355,
- CERT_PLAINRSA = 356,
- NONCE_SIZE = 357,
- DH_GROUP = 358,
- KEEPALIVE = 359,
- PASSIVE = 360,
- INITIAL_CONTACT = 361,
- NAT_TRAVERSAL = 362,
- REMOTE_FORCE_LEVEL = 363,
- PROPOSAL_CHECK = 364,
- PROPOSAL_CHECK_LEVEL = 365,
- GENERATE_POLICY = 366,
- GENERATE_LEVEL = 367,
- SUPPORT_PROXY = 368,
- PROPOSAL = 369,
- EXEC_PATH = 370,
- EXEC_COMMAND = 371,
- EXEC_SUCCESS = 372,
- EXEC_FAILURE = 373,
- GSS_ID = 374,
- GSS_ID_ENC = 375,
- GSS_ID_ENCTYPE = 376,
- COMPLEX_BUNDLE = 377,
- DPD = 378,
- DPD_DELAY = 379,
- DPD_RETRY = 380,
- DPD_MAXFAIL = 381,
- PH1ID = 382,
- XAUTH_LOGIN = 383,
- WEAK_PHASE1_CHECK = 384,
- PREFIX = 385,
- PORT = 386,
- PORTANY = 387,
- UL_PROTO = 388,
- ANY = 389,
- IKE_FRAG = 390,
- ESP_FRAG = 391,
- MODE_CFG = 392,
- PFS_GROUP = 393,
- LIFETIME = 394,
- LIFETYPE_TIME = 395,
- LIFETYPE_BYTE = 396,
- STRENGTH = 397,
- REMOTEID = 398,
- SCRIPT = 399,
- PHASE1_UP = 400,
- PHASE1_DOWN = 401,
- NUMBER = 402,
- SWITCH = 403,
- BOOLEAN = 404,
- HEXSTRING = 405,
- QUOTEDSTRING = 406,
- ADDRSTRING = 407,
- ADDRRANGE = 408,
- UNITTYPE_BYTE = 409,
- UNITTYPE_KBYTES = 410,
- UNITTYPE_MBYTES = 411,
- UNITTYPE_TBYTES = 412,
- UNITTYPE_SEC = 413,
- UNITTYPE_MIN = 414,
- UNITTYPE_HOUR = 415,
- EOS = 416,
- BOC = 417,
- EOC = 418,
- COMMA = 419
+ PFKEY_BUFFER = 265,
+ LOGGING = 266,
+ LOGLEV = 267,
+ PADDING = 268,
+ PAD_RANDOMIZE = 269,
+ PAD_RANDOMIZELEN = 270,
+ PAD_MAXLEN = 271,
+ PAD_STRICT = 272,
+ PAD_EXCLTAIL = 273,
+ LISTEN = 274,
+ X_ISAKMP = 275,
+ X_ISAKMP_NATT = 276,
+ X_ADMIN = 277,
+ STRICT_ADDRESS = 278,
+ ADMINSOCK = 279,
+ DISABLED = 280,
+ LDAPCFG = 281,
+ LDAP_HOST = 282,
+ LDAP_PORT = 283,
+ LDAP_PVER = 284,
+ LDAP_BASE = 285,
+ LDAP_BIND_DN = 286,
+ LDAP_BIND_PW = 287,
+ LDAP_SUBTREE = 288,
+ LDAP_ATTR_USER = 289,
+ LDAP_ATTR_ADDR = 290,
+ LDAP_ATTR_MASK = 291,
+ LDAP_ATTR_GROUP = 292,
+ LDAP_ATTR_MEMBER = 293,
+ RADCFG = 294,
+ RAD_AUTH = 295,
+ RAD_ACCT = 296,
+ RAD_TIMEOUT = 297,
+ RAD_RETRIES = 298,
+ MODECFG = 299,
+ CFG_NET4 = 300,
+ CFG_MASK4 = 301,
+ CFG_DNS4 = 302,
+ CFG_NBNS4 = 303,
+ CFG_DEFAULT_DOMAIN = 304,
+ CFG_AUTH_SOURCE = 305,
+ CFG_AUTH_GROUPS = 306,
+ CFG_SYSTEM = 307,
+ CFG_RADIUS = 308,
+ CFG_PAM = 309,
+ CFG_LDAP = 310,
+ CFG_LOCAL = 311,
+ CFG_NONE = 312,
+ CFG_GROUP_SOURCE = 313,
+ CFG_ACCOUNTING = 314,
+ CFG_CONF_SOURCE = 315,
+ CFG_MOTD = 316,
+ CFG_POOL_SIZE = 317,
+ CFG_AUTH_THROTTLE = 318,
+ CFG_SPLIT_NETWORK = 319,
+ CFG_SPLIT_LOCAL = 320,
+ CFG_SPLIT_INCLUDE = 321,
+ CFG_SPLIT_DNS = 322,
+ CFG_PFS_GROUP = 323,
+ CFG_SAVE_PASSWD = 324,
+ RETRY = 325,
+ RETRY_COUNTER = 326,
+ RETRY_INTERVAL = 327,
+ RETRY_PERSEND = 328,
+ RETRY_PHASE1 = 329,
+ RETRY_PHASE2 = 330,
+ NATT_KA = 331,
+ ALGORITHM_CLASS = 332,
+ ALGORITHMTYPE = 333,
+ STRENGTHTYPE = 334,
+ SAINFO = 335,
+ FROM = 336,
+ REMOTE = 337,
+ ANONYMOUS = 338,
+ CLIENTADDR = 339,
+ INHERIT = 340,
+ REMOTE_ADDRESS = 341,
+ EXCHANGE_MODE = 342,
+ EXCHANGETYPE = 343,
+ DOI = 344,
+ DOITYPE = 345,
+ SITUATION = 346,
+ SITUATIONTYPE = 347,
+ CERTIFICATE_TYPE = 348,
+ CERTTYPE = 349,
+ PEERS_CERTFILE = 350,
+ CA_TYPE = 351,
+ VERIFY_CERT = 352,
+ SEND_CERT = 353,
+ SEND_CR = 354,
+ MATCH_EMPTY_CR = 355,
+ IDENTIFIERTYPE = 356,
+ IDENTIFIERQUAL = 357,
+ MY_IDENTIFIER = 358,
+ PEERS_IDENTIFIER = 359,
+ VERIFY_IDENTIFIER = 360,
+ DNSSEC = 361,
+ CERT_X509 = 362,
+ CERT_PLAINRSA = 363,
+ NONCE_SIZE = 364,
+ DH_GROUP = 365,
+ KEEPALIVE = 366,
+ PASSIVE = 367,
+ INITIAL_CONTACT = 368,
+ NAT_TRAVERSAL = 369,
+ REMOTE_FORCE_LEVEL = 370,
+ PROPOSAL_CHECK = 371,
+ PROPOSAL_CHECK_LEVEL = 372,
+ GENERATE_POLICY = 373,
+ GENERATE_LEVEL = 374,
+ SUPPORT_PROXY = 375,
+ PROPOSAL = 376,
+ EXEC_PATH = 377,
+ EXEC_COMMAND = 378,
+ EXEC_SUCCESS = 379,
+ EXEC_FAILURE = 380,
+ GSS_ID = 381,
+ GSS_ID_ENC = 382,
+ GSS_ID_ENCTYPE = 383,
+ COMPLEX_BUNDLE = 384,
+ DPD = 385,
+ DPD_DELAY = 386,
+ DPD_RETRY = 387,
+ DPD_MAXFAIL = 388,
+ PH1ID = 389,
+ XAUTH_LOGIN = 390,
+ WEAK_PHASE1_CHECK = 391,
+ REKEY = 392,
+ PREFIX = 393,
+ PORT = 394,
+ PORTANY = 395,
+ UL_PROTO = 396,
+ ANY = 397,
+ IKE_FRAG = 398,
+ ESP_FRAG = 399,
+ MODE_CFG = 400,
+ PFS_GROUP = 401,
+ LIFETIME = 402,
+ LIFETYPE_TIME = 403,
+ LIFETYPE_BYTE = 404,
+ STRENGTH = 405,
+ REMOTEID = 406,
+ SCRIPT = 407,
+ PHASE1_UP = 408,
+ PHASE1_DOWN = 409,
+ PHASE1_DEAD = 410,
+ NUMBER = 411,
+ SWITCH = 412,
+ BOOLEAN = 413,
+ HEXSTRING = 414,
+ QUOTEDSTRING = 415,
+ ADDRSTRING = 416,
+ ADDRRANGE = 417,
+ UNITTYPE_BYTE = 418,
+ UNITTYPE_KBYTES = 419,
+ UNITTYPE_MBYTES = 420,
+ UNITTYPE_TBYTES = 421,
+ UNITTYPE_SEC = 422,
+ UNITTYPE_MIN = 423,
+ UNITTYPE_HOUR = 424,
+ EOS = 425,
+ BOC = 426,
+ EOC = 427,
+ COMMA = 428
};
#endif
/* Tokens. */
@@ -211,182 +220,197 @@
#define PATH 262
#define PATHTYPE 263
#define INCLUDE 264
-#define IDENTIFIER 265
-#define VENDORID 266
-#define LOGGING 267
-#define LOGLEV 268
-#define PADDING 269
-#define PAD_RANDOMIZE 270
-#define PAD_RANDOMIZELEN 271
-#define PAD_MAXLEN 272
-#define PAD_STRICT 273
-#define PAD_EXCLTAIL 274
-#define LISTEN 275
-#define X_ISAKMP 276
-#define X_ISAKMP_NATT 277
-#define X_ADMIN 278
-#define STRICT_ADDRESS 279
-#define ADMINSOCK 280
-#define DISABLED 281
-#define LDAPCFG 282
-#define LDAP_HOST 283
-#define LDAP_PORT 284
-#define LDAP_PVER 285
-#define LDAP_BASE 286
-#define LDAP_BIND_DN 287
-#define LDAP_BIND_PW 288
-#define LDAP_SUBTREE 289
-#define LDAP_ATTR_USER 290
-#define LDAP_ATTR_ADDR 291
-#define LDAP_ATTR_MASK 292
-#define LDAP_ATTR_GROUP 293
-#define LDAP_ATTR_MEMBER 294
-#define MODECFG 295
-#define CFG_NET4 296
-#define CFG_MASK4 297
-#define CFG_DNS4 298
-#define CFG_NBNS4 299
-#define CFG_DEFAULT_DOMAIN 300
-#define CFG_AUTH_SOURCE 301
-#define CFG_AUTH_GROUPS 302
-#define CFG_SYSTEM 303
-#define CFG_RADIUS 304
-#define CFG_PAM 305
-#define CFG_LDAP 306
-#define CFG_LOCAL 307
-#define CFG_NONE 308
-#define CFG_GROUP_SOURCE 309
-#define CFG_ACCOUNTING 310
-#define CFG_CONF_SOURCE 311
-#define CFG_MOTD 312
-#define CFG_POOL_SIZE 313
-#define CFG_AUTH_THROTTLE 314
-#define CFG_SPLIT_NETWORK 315
-#define CFG_SPLIT_LOCAL 316
-#define CFG_SPLIT_INCLUDE 317
-#define CFG_SPLIT_DNS 318
-#define CFG_PFS_GROUP 319
-#define CFG_SAVE_PASSWD 320
-#define RETRY 321
-#define RETRY_COUNTER 322
-#define RETRY_INTERVAL 323
-#define RETRY_PERSEND 324
-#define RETRY_PHASE1 325
-#define RETRY_PHASE2 326
-#define NATT_KA 327
-#define ALGORITHM_CLASS 328
-#define ALGORITHMTYPE 329
-#define STRENGTHTYPE 330
-#define SAINFO 331
-#define FROM 332
-#define REMOTE 333
-#define ANONYMOUS 334
-#define INHERIT 335
-#define EXCHANGE_MODE 336
-#define EXCHANGETYPE 337
-#define DOI 338
-#define DOITYPE 339
-#define SITUATION 340
-#define SITUATIONTYPE 341
-#define CERTIFICATE_TYPE 342
-#define CERTTYPE 343
-#define PEERS_CERTFILE 344
-#define CA_TYPE 345
-#define VERIFY_CERT 346
-#define SEND_CERT 347
-#define SEND_CR 348
-#define IDENTIFIERTYPE 349
-#define IDENTIFIERQUAL 350
-#define MY_IDENTIFIER 351
-#define PEERS_IDENTIFIER 352
-#define VERIFY_IDENTIFIER 353
-#define DNSSEC 354
-#define CERT_X509 355
-#define CERT_PLAINRSA 356
-#define NONCE_SIZE 357
-#define DH_GROUP 358
-#define KEEPALIVE 359
-#define PASSIVE 360
-#define INITIAL_CONTACT 361
-#define NAT_TRAVERSAL 362
-#define REMOTE_FORCE_LEVEL 363
-#define PROPOSAL_CHECK 364
-#define PROPOSAL_CHECK_LEVEL 365
-#define GENERATE_POLICY 366
-#define GENERATE_LEVEL 367
-#define SUPPORT_PROXY 368
-#define PROPOSAL 369
-#define EXEC_PATH 370
-#define EXEC_COMMAND 371
-#define EXEC_SUCCESS 372
-#define EXEC_FAILURE 373
-#define GSS_ID 374
-#define GSS_ID_ENC 375
-#define GSS_ID_ENCTYPE 376
-#define COMPLEX_BUNDLE 377
-#define DPD 378
-#define DPD_DELAY 379
-#define DPD_RETRY 380
-#define DPD_MAXFAIL 381
-#define PH1ID 382
-#define XAUTH_LOGIN 383
-#define WEAK_PHASE1_CHECK 384
-#define PREFIX 385
-#define PORT 386
-#define PORTANY 387
-#define UL_PROTO 388
-#define ANY 389
-#define IKE_FRAG 390
-#define ESP_FRAG 391
-#define MODE_CFG 392
-#define PFS_GROUP 393
-#define LIFETIME 394
-#define LIFETYPE_TIME 395
-#define LIFETYPE_BYTE 396
-#define STRENGTH 397
-#define REMOTEID 398
-#define SCRIPT 399
-#define PHASE1_UP 400
-#define PHASE1_DOWN 401
-#define NUMBER 402
-#define SWITCH 403
-#define BOOLEAN 404
-#define HEXSTRING 405
-#define QUOTEDSTRING 406
-#define ADDRSTRING 407
-#define ADDRRANGE 408
-#define UNITTYPE_BYTE 409
-#define UNITTYPE_KBYTES 410
-#define UNITTYPE_MBYTES 411
-#define UNITTYPE_TBYTES 412
-#define UNITTYPE_SEC 413
-#define UNITTYPE_MIN 414
-#define UNITTYPE_HOUR 415
-#define EOS 416
-#define BOC 417
-#define EOC 418
-#define COMMA 419
+#define PFKEY_BUFFER 265
+#define LOGGING 266
+#define LOGLEV 267
+#define PADDING 268
+#define PAD_RANDOMIZE 269
+#define PAD_RANDOMIZELEN 270
+#define PAD_MAXLEN 271
+#define PAD_STRICT 272
+#define PAD_EXCLTAIL 273
+#define LISTEN 274
+#define X_ISAKMP 275
+#define X_ISAKMP_NATT 276
+#define X_ADMIN 277
+#define STRICT_ADDRESS 278
+#define ADMINSOCK 279
+#define DISABLED 280
+#define LDAPCFG 281
+#define LDAP_HOST 282
+#define LDAP_PORT 283
+#define LDAP_PVER 284
+#define LDAP_BASE 285
+#define LDAP_BIND_DN 286
+#define LDAP_BIND_PW 287
+#define LDAP_SUBTREE 288
+#define LDAP_ATTR_USER 289
+#define LDAP_ATTR_ADDR 290
+#define LDAP_ATTR_MASK 291
+#define LDAP_ATTR_GROUP 292
+#define LDAP_ATTR_MEMBER 293
+#define RADCFG 294
+#define RAD_AUTH 295
+#define RAD_ACCT 296
+#define RAD_TIMEOUT 297
+#define RAD_RETRIES 298
+#define MODECFG 299
+#define CFG_NET4 300
+#define CFG_MASK4 301
+#define CFG_DNS4 302
+#define CFG_NBNS4 303
+#define CFG_DEFAULT_DOMAIN 304
+#define CFG_AUTH_SOURCE 305
+#define CFG_AUTH_GROUPS 306
+#define CFG_SYSTEM 307
+#define CFG_RADIUS 308
+#define CFG_PAM 309
+#define CFG_LDAP 310
+#define CFG_LOCAL 311
+#define CFG_NONE 312
+#define CFG_GROUP_SOURCE 313
+#define CFG_ACCOUNTING 314
+#define CFG_CONF_SOURCE 315
+#define CFG_MOTD 316
+#define CFG_POOL_SIZE 317
+#define CFG_AUTH_THROTTLE 318
+#define CFG_SPLIT_NETWORK 319
+#define CFG_SPLIT_LOCAL 320
+#define CFG_SPLIT_INCLUDE 321
+#define CFG_SPLIT_DNS 322
+#define CFG_PFS_GROUP 323
+#define CFG_SAVE_PASSWD 324
+#define RETRY 325
+#define RETRY_COUNTER 326
+#define RETRY_INTERVAL 327
+#define RETRY_PERSEND 328
+#define RETRY_PHASE1 329
+#define RETRY_PHASE2 330
+#define NATT_KA 331
+#define ALGORITHM_CLASS 332
+#define ALGORITHMTYPE 333
+#define STRENGTHTYPE 334
+#define SAINFO 335
+#define FROM 336
+#define REMOTE 337
+#define ANONYMOUS 338
+#define CLIENTADDR 339
+#define INHERIT 340
+#define REMOTE_ADDRESS 341
+#define EXCHANGE_MODE 342
+#define EXCHANGETYPE 343
+#define DOI 344
+#define DOITYPE 345
+#define SITUATION 346
+#define SITUATIONTYPE 347
+#define CERTIFICATE_TYPE 348
+#define CERTTYPE 349
+#define PEERS_CERTFILE 350
+#define CA_TYPE 351
+#define VERIFY_CERT 352
+#define SEND_CERT 353
+#define SEND_CR 354
+#define MATCH_EMPTY_CR 355
+#define IDENTIFIERTYPE 356
+#define IDENTIFIERQUAL 357
+#define MY_IDENTIFIER 358
+#define PEERS_IDENTIFIER 359
+#define VERIFY_IDENTIFIER 360
+#define DNSSEC 361
+#define CERT_X509 362
+#define CERT_PLAINRSA 363
+#define NONCE_SIZE 364
+#define DH_GROUP 365
+#define KEEPALIVE 366
+#define PASSIVE 367
+#define INITIAL_CONTACT 368
+#define NAT_TRAVERSAL 369
+#define REMOTE_FORCE_LEVEL 370
+#define PROPOSAL_CHECK 371
+#define PROPOSAL_CHECK_LEVEL 372
+#define GENERATE_POLICY 373
+#define GENERATE_LEVEL 374
+#define SUPPORT_PROXY 375
+#define PROPOSAL 376
+#define EXEC_PATH 377
+#define EXEC_COMMAND 378
+#define EXEC_SUCCESS 379
+#define EXEC_FAILURE 380
+#define GSS_ID 381
+#define GSS_ID_ENC 382
+#define GSS_ID_ENCTYPE 383
+#define COMPLEX_BUNDLE 384
+#define DPD 385
+#define DPD_DELAY 386
+#define DPD_RETRY 387
+#define DPD_MAXFAIL 388
+#define PH1ID 389
+#define XAUTH_LOGIN 390
+#define WEAK_PHASE1_CHECK 391
+#define REKEY 392
+#define PREFIX 393
+#define PORT 394
+#define PORTANY 395
+#define UL_PROTO 396
+#define ANY 397
+#define IKE_FRAG 398
+#define ESP_FRAG 399
+#define MODE_CFG 400
+#define PFS_GROUP 401
+#define LIFETIME 402
+#define LIFETYPE_TIME 403
+#define LIFETYPE_BYTE 404
+#define STRENGTH 405
+#define REMOTEID 406
+#define SCRIPT 407
+#define PHASE1_UP 408
+#define PHASE1_DOWN 409
+#define PHASE1_DEAD 410
+#define NUMBER 411
+#define SWITCH 412
+#define BOOLEAN 413
+#define HEXSTRING 414
+#define QUOTEDSTRING 415
+#define ADDRSTRING 416
+#define ADDRRANGE 417
+#define UNITTYPE_BYTE 418
+#define UNITTYPE_KBYTES 419
+#define UNITTYPE_MBYTES 420
+#define UNITTYPE_TBYTES 421
+#define UNITTYPE_SEC 422
+#define UNITTYPE_MIN 423
+#define UNITTYPE_HOUR 424
+#define EOS 425
+#define BOC 426
+#define EOC 427
+#define COMMA 428
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
-#line 174 "cfparse.y"
{
+
+/* Line 1676 of yacc.c */
+#line 177 "cfparse.y"
+
unsigned long num;
vchar_t *val;
struct remoteconf *rmconf;
struct sockaddr *saddr;
struct sainfoalg *alg;
-}
-/* Line 1489 of yacc.c. */
-#line 385 "cfparse.h"
- YYSTYPE;
+
+
+
+/* Line 1676 of yacc.c */
+#line 408 "cfparse.h"
+} YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
#endif
extern YYSTYPE yylval;
+
diff --git a/src/racoon/cfparse.y b/src/racoon/cfparse.y
index 540c400..12920d8 100644
--- a/src/racoon/cfparse.y
+++ b/src/racoon/cfparse.y
@@ -1,4 +1,4 @@
-/* $NetBSD: cfparse.y,v 1.18.4.7 2008/07/21 20:45:32 tteras Exp $ */
+/* $NetBSD: cfparse.y,v 1.42 2011/03/14 15:50:36 vanhu Exp $ */
/* Id: cfparse.y,v 1.66 2006/08/22 18:17:17 manubsd Exp */
@@ -94,14 +94,7 @@
#endif
#include "vendorid.h"
#include "rsalist.h"
-
-struct proposalspec {
- time_t lifetime; /* for isakmp/ipsec */
- int lifebyte; /* for isakmp/ipsec */
- struct secprotospec *spspec; /* the head is always current spec. */
- struct proposalspec *next; /* the tail is the most prefered. */
- struct proposalspec *prev;
-};
+#include "crypto_openssl.h"
struct secprotospec {
int prop_no;
@@ -120,7 +113,6 @@ struct secprotospec {
struct secprotospec *next; /* the tail is the most prefiered. */
struct secprotospec *prev;
- struct proposalspec *back;
};
static int num2dhgroup[] = {
@@ -151,24 +143,35 @@ static struct sainfo *cur_sainfo;
static int cur_algclass;
static int oldloglevel = LLV_BASE;
-static struct proposalspec *newprspec __P((void));
-static void insprspec __P((struct proposalspec *, struct proposalspec **));
static struct secprotospec *newspspec __P((void));
-static void insspspec __P((struct secprotospec *, struct proposalspec **));
+static void insspspec __P((struct remoteconf *, struct secprotospec *));
+void dupspspec_list __P((struct remoteconf *dst, struct remoteconf *src));
+void flushspspec __P((struct remoteconf *));
static void adminsock_conf __P((vchar_t *, vchar_t *, vchar_t *, int));
-static int set_isakmp_proposal
- __P((struct remoteconf *, struct proposalspec *));
+static int set_isakmp_proposal __P((struct remoteconf *));
static void clean_tmpalgtype __P((void));
static int expand_isakmpspec __P((int, int, int *,
int, int, time_t, int, int, int, char *, struct remoteconf *));
-static int listen_addr __P((struct sockaddr *addr, int udp_encap));
void freeetypes (struct etypes **etypes);
-#if 0
-static int fix_lifebyte __P((u_long));
-#endif
+static int load_x509(const char *file, char **filenameptr,
+ vchar_t **certptr)
+{
+ char path[PATH_MAX];
+
+ getpathname(path, sizeof(path), LC_PATHTYPE_CERT, file);
+ *certptr = eay_get_x509cert(path);
+ if (*certptr == NULL)
+ return -1;
+
+ *filenameptr = racoon_strdup(file);
+ STRDUP_FATAL(*filenameptr);
+
+ return 0;
+}
+
%}
%union {
@@ -185,8 +188,8 @@ static int fix_lifebyte __P((u_long));
%token PATH PATHTYPE
/* include */
%token INCLUDE
- /* self information */
-%token IDENTIFIER VENDORID
+ /* PFKEY_BUFFER */
+%token PFKEY_BUFFER
/* logging */
%token LOGGING LOGLEV
/* padding */
@@ -196,6 +199,8 @@ static int fix_lifebyte __P((u_long));
/* ldap config */
%token LDAPCFG LDAP_HOST LDAP_PORT LDAP_PVER LDAP_BASE LDAP_BIND_DN LDAP_BIND_PW LDAP_SUBTREE
%token LDAP_ATTR_USER LDAP_ATTR_ADDR LDAP_ATTR_MASK LDAP_ATTR_GROUP LDAP_ATTR_MEMBER
+ /* radius config */
+%token RADCFG RAD_AUTH RAD_ACCT RAD_TIMEOUT RAD_RETRIES
/* modecfg */
%token MODECFG CFG_NET4 CFG_MASK4 CFG_DNS4 CFG_NBNS4 CFG_DEFAULT_DOMAIN
%token CFG_AUTH_SOURCE CFG_AUTH_GROUPS CFG_SYSTEM CFG_RADIUS CFG_PAM CFG_LDAP CFG_LOCAL CFG_NONE
@@ -211,10 +216,10 @@ static int fix_lifebyte __P((u_long));
/* sainfo */
%token SAINFO FROM
/* remote */
-%token REMOTE ANONYMOUS INHERIT
+%token REMOTE ANONYMOUS CLIENTADDR INHERIT REMOTE_ADDRESS
%token EXCHANGE_MODE EXCHANGETYPE DOI DOITYPE SITUATION SITUATIONTYPE
%token CERTIFICATE_TYPE CERTTYPE PEERS_CERTFILE CA_TYPE
-%token VERIFY_CERT SEND_CERT SEND_CR
+%token VERIFY_CERT SEND_CERT SEND_CR MATCH_EMPTY_CR
%token IDENTIFIERTYPE IDENTIFIERQUAL MY_IDENTIFIER
%token PEERS_IDENTIFIER VERIFY_IDENTIFIER
%token DNSSEC CERT_X509 CERT_PLAINRSA
@@ -229,11 +234,12 @@ static int fix_lifebyte __P((u_long));
%token DPD DPD_DELAY DPD_RETRY DPD_MAXFAIL
%token PH1ID
%token XAUTH_LOGIN WEAK_PHASE1_CHECK
+%token REKEY
%token PREFIX PORT PORTANY UL_PROTO ANY IKE_FRAG ESP_FRAG MODE_CFG
%token PFS_GROUP LIFETIME LIFETYPE_TIME LIFETYPE_BYTE STRENGTH REMOTEID
-%token SCRIPT PHASE1_UP PHASE1_DOWN
+%token SCRIPT PHASE1_UP PHASE1_DOWN PHASE1_DEAD
%token NUMBER SWITCH BOOLEAN
%token HEXSTRING QUOTEDSTRING ADDRSTRING ADDRRANGE
@@ -265,12 +271,13 @@ statement
: privsep_statement
| path_statement
| include_statement
+ | pfkey_statement
| gssenc_statement
- | identifier_statement
| logging_statement
| padding_statement
| listen_statement
| ldapcfg_statement
+ | radcfg_statement
| modecfg_statement
| timer_statement
| sainfo_statement
@@ -354,6 +361,13 @@ include_statement
}
;
+ /* pfkey_buffer */
+pfkey_statement
+ : PFKEY_BUFFER NUMBER EOS
+ {
+ lcconf->pfkey_buffer_size = $2;
+ }
+ ;
/* gss_id_enc */
gssenc_statement
: GSS_ID_ENC GSS_ID_ENCTYPE EOS
@@ -366,45 +380,12 @@ gssenc_statement
}
;
- /* self information */
-identifier_statement
- : IDENTIFIER identifier_stmt
- ;
-identifier_stmt
- : VENDORID
- {
- /*XXX to be deleted */
- }
- QUOTEDSTRING EOS
- | IDENTIFIERTYPE QUOTEDSTRING
- {
- /*XXX to be deleted */
- $2->l--; /* nuke '\0' */
- lcconf->ident[$1] = $2;
- if (lcconf->ident[$1] == NULL) {
- yyerror("failed to set my ident: %s",
- strerror(errno));
- return -1;
- }
- }
- EOS
- ;
-
/* logging */
logging_statement
: LOGGING log_level EOS
;
log_level
- : HEXSTRING
- {
- /*
- * XXX ignore it because this specification
- * will be obsoleted.
- */
- yywarn("see racoon.conf(5), such a log specification will be obsoleted.");
- vfree($1);
- }
- | LOGLEV
+ : LOGLEV
{
/*
* set the loglevel to the value specified
@@ -443,23 +424,21 @@ listen_stmts
listen_stmt
: X_ISAKMP ike_addrinfo_port
{
- listen_addr ($2, 0);
+ myaddr_listen($2, FALSE);
+ racoon_free($2);
}
EOS
| X_ISAKMP_NATT ike_addrinfo_port
{
#ifdef ENABLE_NATT
- listen_addr ($2, 1);
+ myaddr_listen($2, TRUE);
+ racoon_free($2);
#else
+ racoon_free($2);
yyerror("NAT-T support not compiled in.");
#endif
}
EOS
- | X_ADMIN
- {
- yyerror("admin directive is obsoleted.");
- }
- PORT EOS
| ADMINSOCK QUOTEDSTRING QUOTEDSTRING QUOTEDSTRING NUMBER
{
#ifdef ENABLE_ADMINPORT
@@ -506,6 +485,122 @@ ike_port
| PORT { $$ = $1; }
;
+ /* radius configuration */
+radcfg_statement
+ : RADCFG {
+#ifndef ENABLE_HYBRID
+ yyerror("racoon not configured with --enable-hybrid");
+ return -1;
+#endif
+#ifndef HAVE_LIBRADIUS
+ yyerror("racoon not configured with --with-libradius");
+ return -1;
+#endif
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBRADIUS
+ xauth_rad_config.timeout = 3;
+ xauth_rad_config.retries = 3;
+#endif
+#endif
+ } BOC radcfg_stmts EOC
+ ;
+radcfg_stmts
+ : /* nothing */
+ | radcfg_stmts radcfg_stmt
+ ;
+radcfg_stmt
+ : RAD_AUTH QUOTEDSTRING QUOTEDSTRING
+ {
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBRADIUS
+ int i = xauth_rad_config.auth_server_count;
+ if (i == RADIUS_MAX_SERVERS) {
+ yyerror("maximum radius auth servers exceeded");
+ return -1;
+ }
+
+ xauth_rad_config.auth_server_list[i].host = vdup($2);
+ xauth_rad_config.auth_server_list[i].secret = vdup($3);
+ xauth_rad_config.auth_server_list[i].port = 0; // default port
+ xauth_rad_config.auth_server_count++;
+#endif
+#endif
+ }
+ EOS
+ | RAD_AUTH QUOTEDSTRING NUMBER QUOTEDSTRING
+ {
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBRADIUS
+ int i = xauth_rad_config.auth_server_count;
+ if (i == RADIUS_MAX_SERVERS) {
+ yyerror("maximum radius auth servers exceeded");
+ return -1;
+ }
+
+ xauth_rad_config.auth_server_list[i].host = vdup($2);
+ xauth_rad_config.auth_server_list[i].secret = vdup($4);
+ xauth_rad_config.auth_server_list[i].port = $3;
+ xauth_rad_config.auth_server_count++;
+#endif
+#endif
+ }
+ EOS
+ | RAD_ACCT QUOTEDSTRING QUOTEDSTRING
+ {
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBRADIUS
+ int i = xauth_rad_config.acct_server_count;
+ if (i == RADIUS_MAX_SERVERS) {
+ yyerror("maximum radius account servers exceeded");
+ return -1;
+ }
+
+ xauth_rad_config.acct_server_list[i].host = vdup($2);
+ xauth_rad_config.acct_server_list[i].secret = vdup($3);
+ xauth_rad_config.acct_server_list[i].port = 0; // default port
+ xauth_rad_config.acct_server_count++;
+#endif
+#endif
+ }
+ EOS
+ | RAD_ACCT QUOTEDSTRING NUMBER QUOTEDSTRING
+ {
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBRADIUS
+ int i = xauth_rad_config.acct_server_count;
+ if (i == RADIUS_MAX_SERVERS) {
+ yyerror("maximum radius account servers exceeded");
+ return -1;
+ }
+
+ xauth_rad_config.acct_server_list[i].host = vdup($2);
+ xauth_rad_config.acct_server_list[i].secret = vdup($4);
+ xauth_rad_config.acct_server_list[i].port = $3;
+ xauth_rad_config.acct_server_count++;
+#endif
+#endif
+ }
+ EOS
+ | RAD_TIMEOUT NUMBER
+ {
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBRADIUS
+ xauth_rad_config.timeout = $2;
+#endif
+#endif
+ }
+ EOS
+ | RAD_RETRIES NUMBER
+ {
+#ifdef ENABLE_HYBRID
+#ifdef HAVE_LIBRADIUS
+ xauth_rad_config.retries = $2;
+#endif
+#endif
+ }
+ EOS
+ ;
+
/* ldap configuration */
ldapcfg_statement
: LDAPCFG {
@@ -1015,12 +1110,16 @@ authgroup
grouplist = racoon_realloc(icc->grouplist,
sizeof(char**)*(icc->groupcount+1));
- if (grouplist == NULL)
+ if (grouplist == NULL) {
yyerror("unable to allocate auth group list");
+ return -1;
+ }
groupname = racoon_malloc($1->l+1);
- if (groupname == NULL)
+ if (groupname == NULL) {
yyerror("unable to allocate auth group name");
+ return -1;
+ }
memcpy(groupname,$1->v,$1->l);
groupname[$1->l]=0;
@@ -1048,8 +1147,10 @@ splitdns
if (!icc->splitdns_len)
{
icc->splitdns_list = racoon_malloc($1->l);
- if(icc->splitdns_list == NULL)
+ if(icc->splitdns_list == NULL) {
yyerror("error allocating splitdns list buffer");
+ return -1;
+ }
memcpy(icc->splitdns_list,$1->v,$1->l);
icc->splitdns_len = $1->l;
}
@@ -1057,8 +1158,10 @@ splitdns
{
int len = icc->splitdns_len + $1->l + 1;
icc->splitdns_list = racoon_realloc(icc->splitdns_list,len);
- if(icc->splitdns_list == NULL)
+ if(icc->splitdns_list == NULL) {
yyerror("error allocating splitdns list buffer");
+ return -1;
+ }
icc->splitdns_list[icc->splitdns_len] = ',';
memcpy(icc->splitdns_list + icc->splitdns_len + 1, $1->v, $1->l);
icc->splitdns_len = len;
@@ -1154,12 +1257,16 @@ sainfo_statement
check = getsainfo(cur_sainfo->idsrc,
cur_sainfo->iddst,
cur_sainfo->id_i,
+ NULL,
cur_sainfo->remoteid);
- if (check && (!check->idsrc && !cur_sainfo->idsrc)) {
+
+ if (check && ((check->idsrc != SAINFO_ANONYMOUS) &&
+ (cur_sainfo->idsrc != SAINFO_ANONYMOUS))) {
yyerror("duplicated sainfo: %s",
sainfo2str(cur_sainfo));
return -1;
}
+
inssainfo(cur_sainfo);
}
EOC
@@ -1167,18 +1274,28 @@ sainfo_statement
sainfo_name
: ANONYMOUS
{
- cur_sainfo->idsrc = NULL;
- cur_sainfo->iddst = NULL;
+ cur_sainfo->idsrc = SAINFO_ANONYMOUS;
+ cur_sainfo->iddst = SAINFO_ANONYMOUS;
+ }
+ | ANONYMOUS CLIENTADDR
+ {
+ cur_sainfo->idsrc = SAINFO_ANONYMOUS;
+ cur_sainfo->iddst = SAINFO_CLIENTADDR;
}
| ANONYMOUS sainfo_id
{
- cur_sainfo->idsrc = NULL;
+ cur_sainfo->idsrc = SAINFO_ANONYMOUS;
cur_sainfo->iddst = $2;
}
| sainfo_id ANONYMOUS
{
cur_sainfo->idsrc = $1;
- cur_sainfo->iddst = NULL;
+ cur_sainfo->iddst = SAINFO_ANONYMOUS;
+ }
+ | sainfo_id CLIENTADDR
+ {
+ cur_sainfo->idsrc = $1;
+ cur_sainfo->iddst = SAINFO_CLIENTADDR;
}
| sainfo_id sainfo_id
{
@@ -1407,16 +1524,6 @@ sainfo_spec
cur_algclass = $1;
}
algorithms EOS
- | IDENTIFIER IDENTIFIERTYPE
- {
- yyerror("it's deprecated to specify a identifier in phase 2");
- }
- EOS
- | MY_IDENTIFIER IDENTIFIERTYPE QUOTEDSTRING
- {
- yyerror("it's deprecated to specify a identifier in phase 2");
- }
- EOS
;
algorithms
@@ -1507,51 +1614,91 @@ keylength
/* remote */
remote_statement
- : REMOTE remote_index INHERIT remote_index
+ : REMOTE QUOTEDSTRING INHERIT QUOTEDSTRING
{
- struct remoteconf *new;
- struct proposalspec *prspec;
+ struct remoteconf *from, *new;
- new = copyrmconf($4);
+ if (getrmconf_by_name($2->v) != NULL) {
+ yyerror("named remoteconf \"%s\" already exists.");
+ return -1;
+ }
+
+ from = getrmconf_by_name($4->v);
+ if (from == NULL) {
+ yyerror("named parent remoteconf \"%s\" does not exist.",
+ $4->v);
+ return -1;
+ }
+
+ new = duprmconf_shallow(from);
if (new == NULL) {
- yyerror("failed to get remoteconf for %s.", saddr2str ($4));
+ yyerror("failed to duplicate remoteconf from \"%s\".",
+ $4->v);
return -1;
}
- new->remote = $2;
- new->inherited_from = getrmconf_strict($4, 1);
- new->proposal = NULL;
- new->prhead = NULL;
+ new->name = racoon_strdup($2->v);
cur_rmconf = new;
- prspec = newprspec();
- if (prspec == NULL || !cur_rmconf->inherited_from
- || !cur_rmconf->inherited_from->proposal)
- return -1;
- prspec->lifetime = cur_rmconf->inherited_from->proposal->lifetime;
- prspec->lifebyte = cur_rmconf->inherited_from->proposal->lifebyte;
- insprspec(prspec, &cur_rmconf->prhead);
+ vfree($2);
+ vfree($4);
}
remote_specs_block
- | REMOTE remote_index
+ | REMOTE QUOTEDSTRING
{
struct remoteconf *new;
- struct proposalspec *prspec;
+
+ if (getrmconf_by_name($2->v) != NULL) {
+ yyerror("Named remoteconf \"%s\" already exists.");
+ return -1;
+ }
new = newrmconf();
if (new == NULL) {
yyerror("failed to get new remoteconf.");
return -1;
}
+ new->name = racoon_strdup($2->v);
+ cur_rmconf = new;
+
+ vfree($2);
+ }
+ remote_specs_block
+ | REMOTE remote_index INHERIT remote_index
+ {
+ struct remoteconf *from, *new;
+
+ from = getrmconf($4, GETRMCONF_F_NO_ANONYMOUS);
+ if (from == NULL) {
+ yyerror("failed to get remoteconf for %s.",
+ saddr2str($4));
+ return -1;
+ }
+ new = duprmconf_shallow(from);
+ if (new == NULL) {
+ yyerror("failed to duplicate remoteconf from %s.",
+ saddr2str($4));
+ return -1;
+ }
+
+ racoon_free($4);
new->remote = $2;
cur_rmconf = new;
+ }
+ remote_specs_block
+ | REMOTE remote_index
+ {
+ struct remoteconf *new;
- prspec = newprspec();
- if (prspec == NULL)
+ new = newrmconf();
+ if (new == NULL) {
+ yyerror("failed to get new remoteconf.");
return -1;
- prspec->lifetime = oakley_get_defaultlifetime();
- insprspec(prspec, &cur_rmconf->prhead);
+ }
+
+ new->remote = $2;
+ cur_rmconf = new;
}
remote_specs_block
;
@@ -1568,7 +1715,6 @@ remote_specs_block
if (cur_rmconf->idvtype == IDTYPE_UNDEFINED)
cur_rmconf->idvtype = IDTYPE_ADDRESS;
-
if (cur_rmconf->idvtype == IDTYPE_ASN1DN) {
if (cur_rmconf->mycertfile) {
if (cur_rmconf->idv)
@@ -1583,17 +1729,24 @@ remote_specs_block
return -1;
}
}
-
- if (cur_rmconf->prhead->spspec == NULL
- && cur_rmconf->inherited_from
- && cur_rmconf->inherited_from->prhead) {
- cur_rmconf->prhead->spspec = cur_rmconf->inherited_from->prhead->spspec;
+
+ if (duprmconf_finish(cur_rmconf))
+ return -1;
+
+#if 0
+ /* this pointer copy will never happen, because duprmconf_shallow
+ * already copied all pointers.
+ */
+ if (cur_rmconf->spspec == NULL &&
+ cur_rmconf->inherited_from != NULL) {
+ cur_rmconf->spspec = cur_rmconf->inherited_from->spspec;
}
- if (set_isakmp_proposal(cur_rmconf, cur_rmconf->prhead) != 0)
+#endif
+ if (set_isakmp_proposal(cur_rmconf) != 0)
return -1;
/* DH group settting if aggressive mode is there. */
- if (check_etypeok(cur_rmconf, ISAKMP_ETYPE_AGG) != NULL) {
+ if (check_etypeok(cur_rmconf, (void*) ISAKMP_ETYPE_AGG)) {
struct isakmpsa *p;
int b = 0;
@@ -1648,7 +1801,16 @@ remote_specs
| remote_specs remote_spec
;
remote_spec
- : EXCHANGE_MODE
+ : REMOTE_ADDRESS ike_addrinfo_port
+ {
+ if (cur_rmconf->remote != NULL) {
+ yyerror("remote_address already specified");
+ return -1;
+ }
+ cur_rmconf->remote = $2;
+ }
+ EOS
+ | EXCHANGE_MODE
{
cur_rmconf->etypes = NULL;
}
@@ -1660,33 +1822,36 @@ remote_spec
{
yywarn("This directive without certtype will be removed!\n");
yywarn("Please use 'peers_certfile x509 \"%s\";' instead\n", $2->v);
- cur_rmconf->getcert_method = ISAKMP_GETCERT_LOCALFILE;
- if (cur_rmconf->peerscertfile != NULL)
- racoon_free(cur_rmconf->peerscertfile);
- cur_rmconf->peerscertfile = racoon_strdup($2->v);
- STRDUP_FATAL(cur_rmconf->peerscertfile);
+ if (cur_rmconf->peerscert != NULL) {
+ yyerror("peers_certfile already defined\n");
+ return -1;
+ }
+
+ if (load_x509($2->v, &cur_rmconf->peerscertfile,
+ &cur_rmconf->peerscert)) {
+ yyerror("failed to load certificate \"%s\"\n",
+ $2->v);
+ return -1;
+ }
+
vfree($2);
}
EOS
- | CA_TYPE CERT_X509 QUOTEDSTRING
- {
- cur_rmconf->cacerttype = $2;
- cur_rmconf->getcacert_method = ISAKMP_GETCERT_LOCALFILE;
- if (cur_rmconf->cacertfile != NULL)
- racoon_free(cur_rmconf->cacertfile);
- cur_rmconf->cacertfile = racoon_strdup($3->v);
- STRDUP_FATAL(cur_rmconf->cacertfile);
- vfree($3);
- }
- EOS
| PEERS_CERTFILE CERT_X509 QUOTEDSTRING
{
- cur_rmconf->getcert_method = ISAKMP_GETCERT_LOCALFILE;
- if (cur_rmconf->peerscertfile != NULL)
- racoon_free(cur_rmconf->peerscertfile);
- cur_rmconf->peerscertfile = racoon_strdup($3->v);
- STRDUP_FATAL(cur_rmconf->peerscertfile);
+ if (cur_rmconf->peerscert != NULL) {
+ yyerror("peers_certfile already defined\n");
+ return -1;
+ }
+
+ if (load_x509($3->v, &cur_rmconf->peerscertfile,
+ &cur_rmconf->peerscert)) {
+ yyerror("failed to load certificate \"%s\"\n",
+ $3->v);
+ return -1;
+ }
+
vfree($3);
}
EOS
@@ -1695,37 +1860,66 @@ remote_spec
char path[MAXPATHLEN];
int ret = 0;
- getpathname(path, sizeof(path),
- LC_PATHTYPE_CERT, $3->v);
- vfree($3);
+ if (cur_rmconf->peerscert != NULL) {
+ yyerror("peers_certfile already defined\n");
+ return -1;
+ }
- if (cur_rmconf->getcert_method == ISAKMP_GETCERT_DNS) {
- yyerror("Different peers_certfile method "
- "already defined: %d!\n",
- cur_rmconf->getcert_method);
+ cur_rmconf->peerscert = vmalloc(1);
+ if (cur_rmconf->peerscert == NULL) {
+ yyerror("failed to allocate peerscert");
return -1;
}
- cur_rmconf->getcert_method = ISAKMP_GETCERT_LOCALFILE;
- if (rsa_parse_file(cur_rmconf->rsa_public, path, RSA_TYPE_PUBLIC)) {
+ cur_rmconf->peerscert->v[0] = ISAKMP_CERT_PLAINRSA;
+
+ getpathname(path, sizeof(path),
+ LC_PATHTYPE_CERT, $3->v);
+ if (rsa_parse_file(cur_rmconf->rsa_public, path,
+ RSA_TYPE_PUBLIC)) {
yyerror("Couldn't parse keyfile.\n", path);
return -1;
}
- plog(LLV_DEBUG, LOCATION, NULL, "Public PlainRSA keyfile parsed: %s\n", path);
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "Public PlainRSA keyfile parsed: %s\n", path);
+
+ vfree($3);
}
EOS
| PEERS_CERTFILE DNSSEC
{
- if (cur_rmconf->getcert_method) {
- yyerror("Different peers_certfile method already defined!\n");
+ if (cur_rmconf->peerscert != NULL) {
+ yyerror("peers_certfile already defined\n");
return -1;
}
- cur_rmconf->getcert_method = ISAKMP_GETCERT_DNS;
- cur_rmconf->peerscertfile = NULL;
+ cur_rmconf->peerscert = vmalloc(1);
+ if (cur_rmconf->peerscert == NULL) {
+ yyerror("failed to allocate peerscert");
+ return -1;
+ }
+ cur_rmconf->peerscert->v[0] = ISAKMP_CERT_DNS;
+ }
+ EOS
+ | CA_TYPE CERT_X509 QUOTEDSTRING
+ {
+ if (cur_rmconf->cacert != NULL) {
+ yyerror("ca_type already defined\n");
+ return -1;
+ }
+
+ if (load_x509($3->v, &cur_rmconf->cacertfile,
+ &cur_rmconf->cacert)) {
+ yyerror("failed to load certificate \"%s\"\n",
+ $3->v);
+ return -1;
+ }
+
+ vfree($3);
}
EOS
| VERIFY_CERT SWITCH { cur_rmconf->verify_cert = $2; } EOS
| SEND_CERT SWITCH { cur_rmconf->send_cert = $2; } EOS
| SEND_CR SWITCH { cur_rmconf->send_cr = $2; } EOS
+ | MATCH_EMPTY_CR SWITCH { cur_rmconf->match_empty_cr = $2; } EOS
| MY_IDENTIFIER IDENTIFIERTYPE identifierstring
{
if (set_identifier(&cur_rmconf->idv, $2, $3) != 0) {
@@ -1830,6 +2024,13 @@ remote_spec
cur_rmconf->script[SCRIPT_PHASE1_DOWN] =
script_path_add(vdup($2));
} EOS
+ | SCRIPT QUOTEDSTRING PHASE1_DEAD {
+ if (cur_rmconf->script[SCRIPT_PHASE1_DEAD] != NULL)
+ vfree(cur_rmconf->script[SCRIPT_PHASE1_DEAD]);
+
+ cur_rmconf->script[SCRIPT_PHASE1_DEAD] =
+ script_path_add(vdup($2));
+ } EOS
| MODE_CFG SWITCH { cur_rmconf->mode_cfg = $2; } EOS
| WEAK_PHASE1_CHECK SWITCH {
cur_rmconf->weak_phase1_check = $2;
@@ -1895,6 +2096,8 @@ remote_spec
#endif
}
EOS
+ | REKEY SWITCH { cur_rmconf->rekey = $2; } EOS
+ | REKEY REMOTE_FORCE_LEVEL { cur_rmconf->rekey = REKEY_FORCE; } EOS
| PH1ID NUMBER
{
cur_rmconf->ph1id = $2;
@@ -1902,7 +2105,7 @@ remote_spec
EOS
| LIFETIME LIFETYPE_TIME NUMBER unittype_time
{
- cur_rmconf->prhead->lifetime = $3 * $4;
+ cur_rmconf->lifetime = $3 * $4;
}
EOS
| PROPOSAL_CHECK PROPOSAL_CHECK_LEVEL { cur_rmconf->pcheck_level = $2; } EOS
@@ -1914,8 +2117,8 @@ remote_spec
#else
yywarn("the lifetime of bytes in phase 1 "
"will be ignored at the moment.");
- cur_rmconf->prhead->lifebyte = fix_lifebyte($3 * $4);
- if (cur_rmconf->prhead->lifebyte == 0)
+ cur_rmconf->lifebyte = fix_lifebyte($3 * $4);
+ if (cur_rmconf->lifebyte == 0)
return -1;
#endif
}
@@ -1927,7 +2130,7 @@ remote_spec
spspec = newspspec();
if (spspec == NULL)
return -1;
- insspspec(spspec, &cur_rmconf->prhead);
+ insspspec(cur_rmconf, spspec);
}
BOC isakmpproposal_specs EOC
;
@@ -1958,16 +2161,22 @@ exchange_types
cert_spec
: CERT_X509 QUOTEDSTRING QUOTEDSTRING
{
- cur_rmconf->certtype = $1;
- if (cur_rmconf->mycertfile != NULL)
- racoon_free(cur_rmconf->mycertfile);
- cur_rmconf->mycertfile = racoon_strdup($2->v);
- STRDUP_FATAL(cur_rmconf->mycertfile);
- vfree($2);
- if (cur_rmconf->myprivfile != NULL)
- racoon_free(cur_rmconf->myprivfile);
+ if (cur_rmconf->mycert != NULL) {
+ yyerror("certificate_type already defined\n");
+ return -1;
+ }
+
+ if (load_x509($2->v, &cur_rmconf->mycertfile,
+ &cur_rmconf->mycert)) {
+ yyerror("failed to load certificate \"%s\"\n",
+ $2->v);
+ return -1;
+ }
+
cur_rmconf->myprivfile = racoon_strdup($3->v);
STRDUP_FATAL(cur_rmconf->myprivfile);
+
+ vfree($2);
vfree($3);
}
EOS
@@ -1976,19 +2185,31 @@ cert_spec
char path[MAXPATHLEN];
int ret = 0;
- getpathname(path, sizeof(path),
- LC_PATHTYPE_CERT, $2->v);
- vfree($2);
+ if (cur_rmconf->mycert != NULL) {
+ yyerror("certificate_type already defined\n");
+ return -1;
+ }
+
+ cur_rmconf->mycert = vmalloc(1);
+ if (cur_rmconf->mycert == NULL) {
+ yyerror("failed to allocate mycert");
+ return -1;
+ }
+ cur_rmconf->mycert->v[0] = ISAKMP_CERT_PLAINRSA;
- cur_rmconf->certtype = $1;
+ getpathname(path, sizeof(path),
+ LC_PATHTYPE_CERT, $2->v);
cur_rmconf->send_cr = FALSE;
cur_rmconf->send_cert = FALSE;
cur_rmconf->verify_cert = FALSE;
- if (rsa_parse_file(cur_rmconf->rsa_private, path, RSA_TYPE_PRIVATE)) {
+ if (rsa_parse_file(cur_rmconf->rsa_private, path,
+ RSA_TYPE_PRIVATE)) {
yyerror("Couldn't parse keyfile.\n", path);
return -1;
}
- plog(LLV_DEBUG, LOCATION, NULL, "Private PlainRSA keyfile parsed: %s\n", path);
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "Private PlainRSA keyfile parsed: %s\n", path);
+ vfree($2);
}
EOS
;
@@ -2022,13 +2243,9 @@ isakmpproposal_specs
| isakmpproposal_specs isakmpproposal_spec
;
isakmpproposal_spec
- : STRENGTH
+ : LIFETIME LIFETYPE_TIME NUMBER unittype_time
{
- yyerror("strength directive is obsoleted.");
- } STRENGTHTYPE EOS
- | LIFETIME LIFETYPE_TIME NUMBER unittype_time
- {
- cur_rmconf->prhead->spspec->lifetime = $3 * $4;
+ cur_rmconf->spspec->lifetime = $3 * $4;
}
EOS
| LIFETIME LIFETYPE_BYTE NUMBER unittype_byte
@@ -2037,28 +2254,28 @@ isakmpproposal_spec
yyerror("byte lifetime support is deprecated");
return -1;
#else
- cur_rmconf->prhead->spspec->lifebyte = fix_lifebyte($3 * $4);
- if (cur_rmconf->prhead->spspec->lifebyte == 0)
+ cur_rmconf->spspec->lifebyte = fix_lifebyte($3 * $4);
+ if (cur_rmconf->spspec->lifebyte == 0)
return -1;
#endif
}
EOS
| DH_GROUP dh_group_num
{
- cur_rmconf->prhead->spspec->algclass[algclass_isakmp_dh] = $2;
+ cur_rmconf->spspec->algclass[algclass_isakmp_dh] = $2;
}
EOS
| GSS_ID QUOTEDSTRING
{
- if (cur_rmconf->prhead->spspec->vendorid != VENDORID_GSSAPI) {
+ if (cur_rmconf->spspec->vendorid != VENDORID_GSSAPI) {
yyerror("wrong Vendor ID for gssapi_id");
return -1;
}
- if (cur_rmconf->prhead->spspec->gssid != NULL)
- racoon_free(cur_rmconf->prhead->spspec->gssid);
- cur_rmconf->prhead->spspec->gssid =
+ if (cur_rmconf->spspec->gssid != NULL)
+ racoon_free(cur_rmconf->spspec->gssid);
+ cur_rmconf->spspec->gssid =
racoon_strdup($2->v);
- STRDUP_FATAL(cur_rmconf->prhead->spspec->gssid);
+ STRDUP_FATAL(cur_rmconf->spspec->gssid);
}
EOS
| ALGORITHM_CLASS ALGORITHMTYPE keylength
@@ -2090,7 +2307,7 @@ isakmpproposal_spec
}
#endif
- cur_rmconf->prhead->spspec->algclass[algclass_isakmp_enc] = doi;
+ cur_rmconf->spspec->algclass[algclass_isakmp_enc] = doi;
defklen = default_keylen($1, $2);
if (defklen == 0) {
if ($3) {
@@ -2104,22 +2321,22 @@ isakmpproposal_spec
}
}
if ($3)
- cur_rmconf->prhead->spspec->encklen = $3;
+ cur_rmconf->spspec->encklen = $3;
else
- cur_rmconf->prhead->spspec->encklen = defklen;
+ cur_rmconf->spspec->encklen = defklen;
break;
case algclass_isakmp_hash:
- cur_rmconf->prhead->spspec->algclass[algclass_isakmp_hash] = doi;
+ cur_rmconf->spspec->algclass[algclass_isakmp_hash] = doi;
break;
case algclass_isakmp_ameth:
- cur_rmconf->prhead->spspec->algclass[algclass_isakmp_ameth] = doi;
+ cur_rmconf->spspec->algclass[algclass_isakmp_ameth] = doi;
/*
* We may have to set the Vendor ID for the
* authentication method we're using.
*/
switch ($2) {
case algtype_gssapikrb:
- if (cur_rmconf->prhead->spspec->vendorid !=
+ if (cur_rmconf->spspec->vendorid !=
VENDORID_UNKNOWN) {
yyerror("Vendor ID mismatch "
"for auth method");
@@ -2129,19 +2346,19 @@ isakmpproposal_spec
* For interoperability with Win2k,
* we set the Vendor ID to "GSSAPI".
*/
- cur_rmconf->prhead->spspec->vendorid =
+ cur_rmconf->spspec->vendorid =
VENDORID_GSSAPI;
break;
case algtype_rsasig:
- if (cur_rmconf->certtype == ISAKMP_CERT_PLAINRSA) {
+ if (oakley_get_certtype(cur_rmconf->peerscert) == ISAKMP_CERT_PLAINRSA) {
if (rsa_list_count(cur_rmconf->rsa_private) == 0) {
yyerror ("Private PlainRSA key not set. "
- "Use directive 'certificate_type plainrsa ...'\n");
+ "Use directive 'certificate_type plainrsa ...'\n");
return -1;
}
if (rsa_list_count(cur_rmconf->rsa_public) == 0) {
yyerror ("Public PlainRSA keys not set. "
- "Use directive 'peers_certfile plainrsa ...'\n");
+ "Use directive 'peers_certfile plainrsa ...'\n");
return -1;
}
}
@@ -2171,32 +2388,6 @@ unittype_byte
;
%%
-static struct proposalspec *
-newprspec()
-{
- struct proposalspec *new;
-
- new = racoon_calloc(1, sizeof(*new));
- if (new == NULL)
- yyerror("failed to allocate proposal");
-
- return new;
-}
-
-/*
- * insert into head of list.
- */
-static void
-insprspec(prspec, head)
- struct proposalspec *prspec;
- struct proposalspec **head;
-{
- if (*head != NULL)
- (*head)->prev = prspec;
- prspec->next = *head;
- *head = prspec;
-}
-
static struct secprotospec *
newspspec()
{
@@ -2224,44 +2415,113 @@ newspspec()
* insert into head of list.
*/
static void
-insspspec(spspec, head)
+insspspec(rmconf, spspec)
+ struct remoteconf *rmconf;
+ struct secprotospec *spspec;
+{
+ if (rmconf->spspec != NULL)
+ rmconf->spspec->prev = spspec;
+ spspec->next = rmconf->spspec;
+ rmconf->spspec = spspec;
+}
+
+static struct secprotospec *
+dupspspec(spspec)
struct secprotospec *spspec;
- struct proposalspec **head;
{
- spspec->back = *head;
+ struct secprotospec *new;
+
+ new = newspspec();
+ if (new == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "dupspspec: malloc failed\n");
+ return NULL;
+ }
+ memcpy(new, spspec, sizeof(*new));
+
+ if (spspec->gssid) {
+ new->gssid = racoon_strdup(spspec->gssid);
+ STRDUP_FATAL(new->gssid);
+ }
+ if (spspec->remote) {
+ new->remote = racoon_malloc(sizeof(*new->remote));
+ if (new->remote == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "dupspspec: malloc failed (remote)\n");
+ return NULL;
+ }
+ memcpy(new->remote, spspec->remote, sizeof(*new->remote));
+ }
- if ((*head)->spspec != NULL)
- (*head)->spspec->prev = spspec;
- spspec->next = (*head)->spspec;
- (*head)->spspec = spspec;
+ return new;
+}
+
+/*
+ * copy the whole list
+ */
+void
+dupspspec_list(dst, src)
+ struct remoteconf *dst, *src;
+{
+ struct secprotospec *p, *new, *last;
+
+ for(p = src->spspec, last = NULL; p; p = p->next, last = new) {
+ new = dupspspec(p);
+ if (new == NULL)
+ exit(1);
+
+ new->prev = last;
+ new->next = NULL; /* not necessary but clean */
+
+ if (last)
+ last->next = new;
+ else /* first element */
+ dst->spspec = new;
+
+ }
+}
+
+/*
+ * delete the whole list
+ */
+void
+flushspspec(rmconf)
+ struct remoteconf *rmconf;
+{
+ struct secprotospec *p;
+
+ while(rmconf->spspec != NULL) {
+ p = rmconf->spspec;
+ rmconf->spspec = p->next;
+ if (p->next != NULL)
+ p->next->prev = NULL; /* not necessary but clean */
+
+ if (p->gssid)
+ racoon_free(p->gssid);
+ if (p->remote)
+ racoon_free(p->remote);
+ racoon_free(p);
+ }
+ rmconf->spspec = NULL;
}
/* set final acceptable proposal */
static int
-set_isakmp_proposal(rmconf, prspec)
+set_isakmp_proposal(rmconf)
struct remoteconf *rmconf;
- struct proposalspec *prspec;
{
- struct proposalspec *p;
struct secprotospec *s;
int prop_no = 1;
int trns_no = 1;
int32_t types[MAXALGCLASS];
- p = prspec;
- if (p->next != 0) {
- plog(LLV_ERROR, LOCATION, NULL,
- "multiple proposal definition.\n");
- return -1;
- }
-
/* mandatory check */
- if (p->spspec == NULL) {
+ if (rmconf->spspec == NULL) {
yyerror("no remote specification found: %s.\n",
saddr2str(rmconf->remote));
return -1;
}
- for (s = p->spspec; s != NULL; s = s->next) {
+ for (s = rmconf->spspec; s != NULL; s = s->next) {
/* XXX need more to check */
if (s->algclass[algclass_isakmp_enc] == 0) {
yyerror("encryption algorithm required.");
@@ -2282,16 +2542,16 @@ set_isakmp_proposal(rmconf, prspec)
}
/* skip to last part */
- for (s = p->spspec; s->next != NULL; s = s->next)
+ for (s = rmconf->spspec; s->next != NULL; s = s->next)
;
while (s != NULL) {
plog(LLV_DEBUG2, LOCATION, NULL,
"lifetime = %ld\n", (long)
- (s->lifetime ? s->lifetime : p->lifetime));
+ (s->lifetime ? s->lifetime : rmconf->lifetime));
plog(LLV_DEBUG2, LOCATION, NULL,
"lifebyte = %d\n",
- s->lifebyte ? s->lifebyte : p->lifebyte);
+ s->lifebyte ? s->lifebyte : rmconf->lifebyte);
plog(LLV_DEBUG2, LOCATION, NULL,
"encklen=%d\n", s->encklen);
@@ -2306,8 +2566,8 @@ set_isakmp_proposal(rmconf, prspec)
clean_tmpalgtype();
trns_no = expand_isakmpspec(prop_no, trns_no, types,
algclass_isakmp_enc, algclass_isakmp_ameth + 1,
- s->lifetime ? s->lifetime : p->lifetime,
- s->lifebyte ? s->lifebyte : p->lifebyte,
+ s->lifetime ? s->lifetime : rmconf->lifetime,
+ s->lifebyte ? s->lifebyte : rmconf->lifebyte,
s->encklen, s->vendorid, s->gssid,
rmconf);
if (trns_no == -1) {
@@ -2412,11 +2672,7 @@ expand_isakmpspec(prop_no, trns_no, types,
}
memcpy(new->gssid->v, gssid, new->gssid->l);
racoon_free(gssid);
-#ifdef ENABLE_HYBRID
- } else if (rmconf->xauth == NULL) {
-#else
} else {
-#endif
/*
* Allocate the default ID so that it gets put
* into a GSS ID attribute during the Phase 1
@@ -2431,30 +2687,6 @@ expand_isakmpspec(prop_no, trns_no, types,
return trns_no;
}
-static int
-listen_addr (struct sockaddr *addr, int udp_encap)
-{
- struct myaddrs *p;
-
- p = newmyaddr();
- if (p == NULL) {
- yyerror("failed to allocate myaddrs");
- return -1;
- }
- p->addr = addr;
- if (p->addr == NULL) {
- yyerror("failed to copy sockaddr ");
- delmyaddr(p);
- return -1;
- }
- p->udp_encap = udp_encap;
-
- insmyaddr(p, &lcconf->myaddrs);
-
- lcconf->autograbaddr = 0;
- return 0;
-}
-
#if 0
/*
* fix lifebyte.
@@ -2479,6 +2711,7 @@ cfparse()
{
int error;
+ yyerrorcount = 0;
yycf_init_buffer();
if (yycf_switch_buffer(lcconf->racoon_conf) != 0) {
diff --git a/src/racoon/cftoken.l b/src/racoon/cftoken.l
index 9950d49..3042796 100644
--- a/src/racoon/cftoken.l
+++ b/src/racoon/cftoken.l
@@ -1,4 +1,4 @@
-/* $NetBSD: cftoken.l,v 1.11.4.2 2007/09/03 18:07:29 mgrooms Exp $ */
+/* $NetBSD: cftoken.l,v 1.23 2011/02/02 15:21:34 vanhu Exp $ */
/* Id: cftoken.l,v 1.53 2006/08/22 18:17:17 manubsd Exp */
@@ -132,7 +132,7 @@ addrstring [a-fA-F0-9:]([a-fA-F0-9:\.]*|[a-fA-F0-9:\.]*%[a-zA-Z0-9]*)
decstring {digit}+
hexstring 0x{hexdigit}+
-%s S_INI S_PRIV S_PTH S_INF S_LOG S_PAD S_LST S_RTRY S_CFG S_LDAP
+%s S_INI S_PRIV S_PTH S_LOG S_PAD S_LST S_RTRY S_CFG S_LDAP S_RAD
%s S_ALGST S_ALGCL
%s S_SAINF S_SAINFS
%s S_RMT S_RMTS S_RMTP
@@ -174,9 +174,8 @@ hexstring 0x{hexdigit}+
/* include */
<S_INI>include { YYDB; return(INCLUDE); }
- /* self information */
-<S_INI>identifier { BEGIN S_INF; YYDB; yywarn("it is obsoleted. use \"my_identifier\" in each remote directives."); return(IDENTIFIER); }
-<S_INF>{semi} { BEGIN S_INI; return(EOS); }
+ /* pfkey_buffer */
+<S_INI>pfkey_buffer { YYDB; return(PFKEY_BUFFER); }
/* special */
<S_INI>complex_bundle { YYDB; return(COMPLEX_BUNDLE); }
@@ -189,8 +188,6 @@ hexstring 0x{hexdigit}+
<S_LOG>info { YYD; yylval.num = LLV_INFO; return(LOGLEV); }
<S_LOG>debug { YYD; yylval.num = LLV_DEBUG; return(LOGLEV); }
<S_LOG>debug2 { YYD; yylval.num = LLV_DEBUG2; return(LOGLEV); }
-<S_LOG>debug3 { YYD; yywarn("it is obsoleted. use \"debug2\""); yylval.num = LLV_DEBUG2; return(LOGLEV); }
-<S_LOG>debug4 { YYD; yywarn("it is obsoleted. use \"debug2\""); yylval.num = LLV_DEBUG2; return(LOGLEV); }
<S_LOG>{semi} { BEGIN S_INI; return(EOS); }
/* padding */
@@ -214,6 +211,15 @@ hexstring 0x{hexdigit}+
<S_LST>strict_address { YYD; return(STRICT_ADDRESS); }
<S_LST>{ecl} { BEGIN S_INI; return(EOC); }
+ /* radius config */
+<S_INI>radiuscfg { BEGIN S_RAD; YYDB; return(RADCFG); }
+<S_RAD>{bcl} { return(BOC); }
+<S_RAD>auth { YYD; return(RAD_AUTH); }
+<S_RAD>acct { YYD; return(RAD_ACCT); }
+<S_RAD>timeout { YYD; return(RAD_TIMEOUT); }
+<S_RAD>retries { YYD; return(RAD_RETRIES); }
+<S_RAD>{ecl} { BEGIN S_INI; return(EOC); }
+
/* ldap config */
<S_INI>ldapcfg { BEGIN S_LDAP; YYDB; return(LDAPCFG); }
<S_LDAP>{bcl} { return(BOC); }
@@ -277,6 +283,7 @@ hexstring 0x{hexdigit}+
/* sainfo */
<S_INI>sainfo { BEGIN S_SAINF; YYDB; return(SAINFO); }
<S_SAINF>anonymous { YYD; return(ANONYMOUS); }
+<S_SAINF>clientaddr { YYD; return(CLIENTADDR); }
<S_SAINF>{blcl}any{elcl} { YYD; return(PORTANY); }
<S_SAINF>any { YYD; return(ANY); }
<S_SAINF>from { YYD; return(FROM); }
@@ -287,7 +294,6 @@ hexstring 0x{hexdigit}+
<S_SAINFS>{ecl} { BEGIN S_INI; return(EOC); }
<S_SAINFS>pfs_group { YYD; return(PFS_GROUP); }
<S_SAINFS>remoteid { YYD; return(REMOTEID); }
-<S_SAINFS>identifier { YYD; yywarn("it is obsoleted. use \"my_identifier\"."); return(IDENTIFIER); }
<S_SAINFS>my_identifier { YYD; return(MY_IDENTIFIER); }
<S_SAINFS>lifetime { YYD; return(LIFETIME); }
<S_SAINFS>time { YYD; return(LIFETYPE_TIME); }
@@ -304,6 +310,7 @@ hexstring 0x{hexdigit}+
/* remote spec */
<S_RMT>{bcl} { BEGIN S_RMTS; return(BOC); }
<S_RMTS>{ecl} { BEGIN S_INI; return(EOC); }
+<S_RMTS>remote_address { YYD; return(REMOTE_ADDRESS); }
<S_RMTS>exchange_mode { YYD; return(EXCHANGE_MODE); }
<S_RMTS>{comma} { YYD; /* XXX ignored, but to be handled. */ ; }
<S_RMTS>base { YYD; yylval.num = ISAKMP_ETYPE_BASE; return(EXCHANGETYPE); }
@@ -315,7 +322,6 @@ hexstring 0x{hexdigit}+
<S_RMTS>identity_only { YYD; yylval.num = IPSECDOI_SIT_IDENTITY_ONLY; return(SITUATIONTYPE); }
<S_RMTS>secrecy { YYD; yylval.num = IPSECDOI_SIT_SECRECY; return(SITUATIONTYPE); }
<S_RMTS>integrity { YYD; yylval.num = IPSECDOI_SIT_INTEGRITY; return(SITUATIONTYPE); }
-<S_RMTS>identifier { YYD; yywarn("it is obsoleted. use \"my_identifier\"."); return(IDENTIFIER); }
<S_RMTS>my_identifier { YYD; return(MY_IDENTIFIER); }
<S_RMTS>xauth_login { YYD; return(XAUTH_LOGIN); /* formerly identifier type login */ }
<S_RMTS>peers_identifier { YYD; return(PEERS_IDENTIFIER); }
@@ -329,12 +335,12 @@ hexstring 0x{hexdigit}+
<S_RMTS>verify_cert { YYD; return(VERIFY_CERT); }
<S_RMTS>send_cert { YYD; return(SEND_CERT); }
<S_RMTS>send_cr { YYD; return(SEND_CR); }
+<S_RMTS>match_empty_cr { YYD; return(MATCH_EMPTY_CR); }
<S_RMTS>dh_group { YYD; return(DH_GROUP); }
<S_RMTS>nonce_size { YYD; return(NONCE_SIZE); }
<S_RMTS>generate_policy { YYD; return(GENERATE_POLICY); }
<S_RMTS>unique { YYD; yylval.num = GENERATE_POLICY_UNIQUE; return(GENERATE_LEVEL); }
<S_RMTS>require { YYD; yylval.num = GENERATE_POLICY_REQUIRE; return(GENERATE_LEVEL); }
-<S_RMTS>support_mip6 { YYD; yywarn("it is obsoleted. use \"support_proxy\"."); return(SUPPORT_PROXY); }
<S_RMTS>support_proxy { YYD; return(SUPPORT_PROXY); }
<S_RMTS>initial_contact { YYD; return(INITIAL_CONTACT); }
<S_RMTS>nat_traversal { YYD; return(NAT_TRAVERSAL); }
@@ -359,8 +365,10 @@ hexstring 0x{hexdigit}+
<S_RMTS>script { YYD; return(SCRIPT); }
<S_RMTS>phase1_up { YYD; return(PHASE1_UP); }
<S_RMTS>phase1_down { YYD; return(PHASE1_DOWN); }
+<S_RMTS>phase1_dead { YYD; return(PHASE1_DEAD); }
<S_RMTS>mode_cfg { YYD; return(MODE_CFG); }
<S_RMTS>weak_phase1_check { YYD; return(WEAK_PHASE1_CHECK); }
+<S_RMTS>rekey { YYD; return(REKEY); }
/* remote proposal */
<S_RMTS>proposal { BEGIN S_RMTP; YYDB; return(PROPOSAL); }
<S_RMTP>{bcl} { return(BOC); }
@@ -427,6 +435,7 @@ icmp { YYD; yylval.num = IPPROTO_ICMP; return(UL_PROTO); }
icmp6 { YYD; yylval.num = IPPROTO_ICMPV6; return(UL_PROTO); }
tcp { YYD; yylval.num = IPPROTO_TCP; return(UL_PROTO); }
udp { YYD; yylval.num = IPPROTO_UDP; return(UL_PROTO); }
+gre { YYD; yylval.num = IPPROTO_GRE; return(UL_PROTO); }
/* algorithm type */
des_iv64 { YYD; yylval.num = algtype_des_iv64; return(ALGORITHMTYPE); }
@@ -543,14 +552,12 @@ xauth_rsa_client {
/* identifier type */
-vendor_id { YYD; yywarn("it is obsoleted."); return(VENDORID); }
user_fqdn { YYD; yylval.num = IDTYPE_USERFQDN; return(IDENTIFIERTYPE); }
fqdn { YYD; yylval.num = IDTYPE_FQDN; return(IDENTIFIERTYPE); }
keyid { YYD; yylval.num = IDTYPE_KEYID; return(IDENTIFIERTYPE); }
address { YYD; yylval.num = IDTYPE_ADDRESS; return(IDENTIFIERTYPE); }
subnet { YYD; yylval.num = IDTYPE_SUBNET; return(IDENTIFIERTYPE); }
asn1dn { YYD; yylval.num = IDTYPE_ASN1DN; return(IDENTIFIERTYPE); }
-certname { YYD; yywarn("certname will be obsoleted in near future."); yylval.num = IDTYPE_ASN1DN; return(IDENTIFIERTYPE); }
/* identifier qualifier */
tag { YYD; yylval.num = IDQUAL_TAG; return(IDENTIFIERQUAL); }
@@ -573,7 +580,7 @@ no { YYD; yylval.num = FALSE; return(BOOLEAN); }
char *bp;
YYD;
- yylval.num = strtol(yytext, &bp, 10);
+ yylval.num = strtoul(yytext, &bp, 10);
return(NUMBER);
}
@@ -631,6 +638,10 @@ no { YYD; yylval.num = FALSE; return(BOOLEAN); }
<<EOF>> {
yy_delete_buffer(YY_CURRENT_BUFFER);
+ fclose (incstack[incstackp].fp);
+ incstack[incstackp].fp = NULL;
+ racoon_free(incstack[incstackp].path);
+ incstack[incstackp].path = NULL;
incstackp--;
nextfile:
if (incstack[incstackp].matchon <
diff --git a/src/racoon/crypto_openssl.c b/src/racoon/crypto_openssl.c
index b6e4c0d..f8a4db9 100644
--- a/src/racoon/crypto_openssl.c
+++ b/src/racoon/crypto_openssl.c
@@ -1,4 +1,4 @@
-/* $NetBSD: crypto_openssl.c,v 1.11.6.6 2009/04/29 10:50:25 tteras Exp $ */
+/* $NetBSD: crypto_openssl.c,v 1.20 2010/10/20 13:40:02 tteras Exp $ */
/* Id: crypto_openssl.c,v 1.47 2006/05/06 20:42:09 manubsd Exp */
@@ -113,6 +113,7 @@ typedef STACK_OF(GENERAL_NAME) GENERAL_NAMES;
#include "crypto_openssl.h"
#include "debug.h"
#include "gcmalloc.h"
+#include "isakmp.h"
/*
* I hate to cast every parameter to des_xx into void *, but it is
@@ -136,9 +137,9 @@ eay_str2asn1dn(str, len)
int len;
{
X509_NAME *name;
- char *buf;
+ char *buf, *dst;
char *field, *value;
- int i, j;
+ int i;
vchar_t *ret = NULL;
caddr_t p;
@@ -154,15 +155,38 @@ eay_str2asn1dn(str, len)
name = X509_NAME_new();
- field = &buf[0];
+ dst = field = &buf[0];
value = NULL;
for (i = 0; i < len; i++) {
+ if (buf[i] == '\\') {
+ /* Escape characters specified in RFC 2253 */
+ if (i < len - 1 &&
+ strchr("\\,=+<>#;", buf[i+1]) != NULL) {
+ *dst++ = buf[++i];
+ continue;
+ } else if (i < len - 2) {
+ /* RFC 2253 hexpair character escape */
+ long u;
+ char esc_str[3];
+ char *endptr;
+
+ esc_str[0] = buf[++i];
+ esc_str[1] = buf[++i];
+ esc_str[2] = '\0';
+ u = strtol(esc_str, &endptr, 16);
+ if (*endptr != '\0' || u < 0 || u > 255)
+ goto err;
+ *dst++ = u;
+ continue;
+ } else
+ goto err;
+ }
if (!value && buf[i] == '=') {
- buf[i] = '\0';
- value = &buf[i + 1];
+ *dst = '\0';
+ dst = value = &buf[i + 1];
continue;
} else if (buf[i] == ',' || buf[i] == '/') {
- buf[i] = '\0';
+ *dst = '\0';
plog(LLV_DEBUG, LOCATION, NULL, "DN: %s=%s\n",
field, value);
@@ -179,16 +203,16 @@ eay_str2asn1dn(str, len)
"%s\n", eay_strerror());
goto err;
}
- for (j = i + 1; j < len; j++) {
- if (buf[j] != ' ')
- break;
- }
- field = &buf[j];
+
+ while (i + 1 < len && buf[i + 1] == ' ') i++;
+ dst = field = &buf[i + 1];
value = NULL;
continue;
+ } else {
+ *dst++ = buf[i];
}
}
- buf[len] = '\0';
+ *dst = '\0';
plog(LLV_DEBUG, LOCATION, NULL, "DN: %s=%s\n",
field, value);
@@ -638,7 +662,7 @@ cb_check_cert_remote(ok, ctx)
}
/*
- * get a subjectAltName from X509 certificate.
+ * get a subjectName from X509 certificate.
*/
vchar_t *
eay_get_x509asn1subjectname(cert)
@@ -649,8 +673,6 @@ eay_get_x509asn1subjectname(cert)
vchar_t *name = NULL;
int len;
- bp = (unsigned char *) cert->v;
-
x509 = mem2x509(cert);
if (x509 == NULL)
goto error;
@@ -784,6 +806,46 @@ end:
return error;
}
+/*
+ * get a issuerName from X509 certificate.
+ */
+vchar_t *
+eay_get_x509asn1issuername(cert)
+ vchar_t *cert;
+{
+ X509 *x509 = NULL;
+ u_char *bp;
+ vchar_t *name = NULL;
+ int len;
+
+ x509 = mem2x509(cert);
+ if (x509 == NULL)
+ goto error;
+
+ /* get the length of the name */
+ len = i2d_X509_NAME(x509->cert_info->issuer, NULL);
+ name = vmalloc(len);
+ if (name == NULL)
+ goto error;
+
+ /* get the name */
+ bp = (unsigned char *) name->v;
+ len = i2d_X509_NAME(x509->cert_info->issuer, &bp);
+
+ X509_free(x509);
+
+ return name;
+
+error:
+ plog(LLV_ERROR, LOCATION, NULL, "%s\n", eay_strerror());
+
+ if (name != NULL)
+ vfree(name);
+ if (x509 != NULL)
+ X509_free(x509);
+
+ return NULL;
+}
/*
* decode a X509 certificate and make a readable text terminated '\n'.
@@ -850,9 +912,9 @@ mem2x509(cert)
{
u_char *bp;
- bp = (unsigned char *) cert->v;
+ bp = (unsigned char *) cert->v + 1;
- x509 = d2i_X509(NULL, (void *)&bp, cert->l);
+ x509 = d2i_X509(NULL, (void *)&bp, cert->l - 1);
}
#else
{
@@ -862,7 +924,7 @@ mem2x509(cert)
bio = BIO_new(BIO_s_mem());
if (bio == NULL)
return NULL;
- len = BIO_write(bio, cert->v, cert->l);
+ len = BIO_write(bio, cert->v + 1, cert->l - 1);
if (len == -1)
return NULL;
x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
@@ -912,12 +974,13 @@ eay_get_x509cert(path)
return NULL;
len = i2d_X509(x509, NULL);
- cert = vmalloc(len);
+ cert = vmalloc(len + 1);
if (cert == NULL) {
X509_free(x509);
return NULL;
}
- bp = (unsigned char *) cert->v;
+ cert->v[0] = ISAKMP_CERT_X509SIGN;
+ bp = (unsigned char *) &cert->v[1];
error = i2d_X509(x509, &bp);
X509_free(x509);
@@ -943,17 +1006,12 @@ eay_check_x509sign(source, sig, cert)
vchar_t *cert;
{
X509 *x509;
- u_char *bp;
EVP_PKEY *evp;
int res;
- bp = (unsigned char *) cert->v;
-
- x509 = d2i_X509(NULL, (void *)&bp, cert->l);
- if (x509 == NULL) {
- plog(LLV_ERROR, LOCATION, NULL, "d2i_X509(): %s\n", eay_strerror());
+ x509 = mem2x509(cert);
+ if (x509 == NULL)
return -1;
- }
evp = X509_get_pubkey(x509);
if (! evp) {
@@ -1807,6 +1865,42 @@ eay_hmac_init(key, md)
return (caddr_t)c;
}
+static vchar_t *eay_hmac_one(key, data, type)
+ vchar_t *key, *data;
+ const EVP_MD *type;
+{
+ vchar_t *res;
+
+ if ((res = vmalloc(EVP_MD_size(type))) == 0)
+ return NULL;
+
+ if (!HMAC(type, (void *) key->v, key->l,
+ (void *) data->v, data->l, (void *) res->v, NULL)) {
+ vfree(res);
+ return NULL;
+ }
+
+ return res;
+}
+
+static vchar_t *eay_digest_one(data, type)
+ vchar_t *data;
+ const EVP_MD *type;
+{
+ vchar_t *res;
+
+ if ((res = vmalloc(EVP_MD_size(type))) == 0)
+ return NULL;
+
+ if (!EVP_Digest((void *) data->v, data->l,
+ (void *) res->v, NULL, type, NULL)) {
+ vfree(res);
+ return NULL;
+ }
+
+ return res;
+}
+
#ifdef WITH_SHA2
/*
* HMAC SHA2-512
@@ -1815,14 +1909,7 @@ vchar_t *
eay_hmacsha2_512_one(key, data)
vchar_t *key, *data;
{
- vchar_t *res;
- caddr_t ctx;
-
- ctx = eay_hmacsha2_512_init(key);
- eay_hmacsha2_512_update(ctx, data);
- res = eay_hmacsha2_512_final(ctx);
-
- return(res);
+ return eay_hmac_one(key, data, EVP_sha2_512());
}
caddr_t
@@ -1872,14 +1959,7 @@ vchar_t *
eay_hmacsha2_384_one(key, data)
vchar_t *key, *data;
{
- vchar_t *res;
- caddr_t ctx;
-
- ctx = eay_hmacsha2_384_init(key);
- eay_hmacsha2_384_update(ctx, data);
- res = eay_hmacsha2_384_final(ctx);
-
- return(res);
+ return eay_hmac_one(key, data, EVP_sha2_384());
}
caddr_t
@@ -1929,14 +2009,7 @@ vchar_t *
eay_hmacsha2_256_one(key, data)
vchar_t *key, *data;
{
- vchar_t *res;
- caddr_t ctx;
-
- ctx = eay_hmacsha2_256_init(key);
- eay_hmacsha2_256_update(ctx, data);
- res = eay_hmacsha2_256_final(ctx);
-
- return(res);
+ return eay_hmac_one(key, data, EVP_sha2_256());
}
caddr_t
@@ -1987,14 +2060,7 @@ vchar_t *
eay_hmacsha1_one(key, data)
vchar_t *key, *data;
{
- vchar_t *res;
- caddr_t ctx;
-
- ctx = eay_hmacsha1_init(key);
- eay_hmacsha1_update(ctx, data);
- res = eay_hmacsha1_final(ctx);
-
- return(res);
+ return eay_hmac_one(key, data, EVP_sha1());
}
caddr_t
@@ -2044,14 +2110,7 @@ vchar_t *
eay_hmacmd5_one(key, data)
vchar_t *key, *data;
{
- vchar_t *res;
- caddr_t ctx;
-
- ctx = eay_hmacmd5_init(key);
- eay_hmacmd5_update(ctx, data);
- res = eay_hmacmd5_final(ctx);
-
- return(res);
+ return eay_hmac_one(key, data, EVP_md5());
}
caddr_t
@@ -2137,14 +2196,7 @@ vchar_t *
eay_sha2_512_one(data)
vchar_t *data;
{
- caddr_t ctx;
- vchar_t *res;
-
- ctx = eay_sha2_512_init();
- eay_sha2_512_update(ctx, data);
- res = eay_sha2_512_final(ctx);
-
- return(res);
+ return eay_digest_one(data, EVP_sha512());
}
int
@@ -2197,14 +2249,7 @@ vchar_t *
eay_sha2_384_one(data)
vchar_t *data;
{
- caddr_t ctx;
- vchar_t *res;
-
- ctx = eay_sha2_384_init();
- eay_sha2_384_update(ctx, data);
- res = eay_sha2_384_final(ctx);
-
- return(res);
+ return eay_digest_one(data, EVP_sha2_384());
}
int
@@ -2257,14 +2302,7 @@ vchar_t *
eay_sha2_256_one(data)
vchar_t *data;
{
- caddr_t ctx;
- vchar_t *res;
-
- ctx = eay_sha2_256_init();
- eay_sha2_256_update(ctx, data);
- res = eay_sha2_256_final(ctx);
-
- return(res);
+ return eay_digest_one(data, EVP_sha2_256());
}
int
@@ -2316,14 +2354,7 @@ vchar_t *
eay_sha1_one(data)
vchar_t *data;
{
- caddr_t ctx;
- vchar_t *res;
-
- ctx = eay_sha1_init();
- eay_sha1_update(ctx, data);
- res = eay_sha1_final(ctx);
-
- return(res);
+ return eay_digest_one(data, EVP_sha1());
}
int
@@ -2374,14 +2405,7 @@ vchar_t *
eay_md5_one(data)
vchar_t *data;
{
- caddr_t ctx;
- vchar_t *res;
-
- ctx = eay_md5_init();
- eay_md5_update(ctx, data);
- res = eay_md5_final(ctx);
-
- return(res);
+ return eay_digest_one(data, EVP_md5());
}
int
diff --git a/src/racoon/crypto_openssl.h b/src/racoon/crypto_openssl.h
index 9a17de8..66fac73 100644
--- a/src/racoon/crypto_openssl.h
+++ b/src/racoon/crypto_openssl.h
@@ -1,4 +1,4 @@
-/* $NetBSD: crypto_openssl.h,v 1.5 2006/10/06 12:02:27 manu Exp $ */
+/* $NetBSD: crypto_openssl.h,v 1.7 2009/08/17 11:59:10 vanhu Exp $ */
/* Id: crypto_openssl.h,v 1.11 2004/11/13 11:28:01 manubsd Exp */
@@ -34,8 +34,6 @@
#ifndef _CRYPTO_OPENSSL_H
#define _CRYPTO_OPENSSL_H
-#include "crypto_openssl.h"
-
#include <openssl/x509v3.h>
#include <openssl/rsa.h>
@@ -55,6 +53,7 @@ extern int eay_cmp_asn1dn __P((vchar_t *, vchar_t *));
extern int eay_check_x509cert __P((vchar_t *, char *, char *, int));
extern vchar_t *eay_get_x509asn1subjectname __P((vchar_t *));
extern int eay_get_x509subjectaltname __P((vchar_t *, char **, int *, int));
+extern vchar_t * eay_get_x509asn1issuername __P((vchar_t *));
extern char *eay_get_x509text __P((vchar_t *));
extern vchar_t *eay_get_x509cert __P((char *));
extern vchar_t *eay_get_x509sign __P((vchar_t *, vchar_t *));
diff --git a/src/racoon/debug.h b/src/racoon/debug.h
index 47c2641..4270b6a 100644
--- a/src/racoon/debug.h
+++ b/src/racoon/debug.h
@@ -1,4 +1,4 @@
-/* $NetBSD: debug.h,v 1.4 2006/09/09 16:22:09 manu Exp $ */
+/* $NetBSD: debug.h,v 1.5 2008/12/23 14:03:12 tteras Exp $ */
/* Id: debug.h,v 1.3 2004/06/11 16:00:16 ludvigm Exp */
@@ -37,5 +37,6 @@
/* define by main.c */
extern int f_local;
extern int vflag;
+extern int dump_config;
#endif /* _DEBUG_H */
diff --git a/src/racoon/dnssec.c b/src/racoon/dnssec.c
index 1fc0bd1..d52a243 100644
--- a/src/racoon/dnssec.c
+++ b/src/racoon/dnssec.c
@@ -1,4 +1,4 @@
-/* $NetBSD: dnssec.c,v 1.4 2006/09/09 16:22:09 manu Exp $ */
+/* $NetBSD: dnssec.c,v 1.5 2009/03/12 10:57:26 tteras Exp $ */
/* $KAME: dnssec.c,v 1.2 2001/08/05 18:46:07 itojun Exp $ */
@@ -55,11 +55,11 @@
extern int h_errno;
-cert_t *
+vchar_t *
dnssec_getcert(id)
vchar_t *id;
{
- cert_t *cert = NULL;
+ vchar_t *cert = NULL;
struct certinfo *res = NULL;
struct ipsecdoi_id_b *id_b;
int type;
@@ -116,39 +116,22 @@ dnssec_getcert(id)
}
/* create cert holder */
- cert = oakley_newcert();
+ cert = vmalloc(res->ci_certlen + 1);
if (cert == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
"failed to get cert buffer.\n");
goto err;
}
- cert->pl = vmalloc(res->ci_certlen + 1);
- if (cert->pl == NULL) {
- plog(LLV_ERROR, LOCATION, NULL,
- "failed to get cert buffer.\n");
- goto err;
- }
- memcpy(cert->pl->v + 1, res->ci_cert, res->ci_certlen);
- cert->pl->v[0] = type;
- cert->cert.v = cert->pl->v + 1;
- cert->cert.l = cert->pl->l - 1;
+ cert->v[0] = type;
+ memcpy(&cert->v[1], res->ci_cert, res->ci_certlen);
plog(LLV_DEBUG, LOCATION, NULL, "created CERT payload:\n");
- plogdump(LLV_DEBUG, cert->pl->v, cert->pl->l);
-
-end:
- if (res)
- freecertinfo(res);
-
- return cert;
+ plogdump(LLV_DEBUG, cert->v, cert->l);
err:
if (name)
racoon_free(name);
- if (cert) {
- oakley_delcert(cert);
- cert = NULL;
- }
-
- goto end;
+ if (res)
+ freecertinfo(res);
+ return cert;
}
diff --git a/src/racoon/dnssec.h b/src/racoon/dnssec.h
index fb1c931..1a03d77 100644
--- a/src/racoon/dnssec.h
+++ b/src/racoon/dnssec.h
@@ -1,4 +1,4 @@
-/* $NetBSD: dnssec.h,v 1.4 2006/09/09 16:22:09 manu Exp $ */
+/* $NetBSD: dnssec.h,v 1.5 2009/03/12 10:57:26 tteras Exp $ */
/* Id: dnssec.h,v 1.3 2004/06/11 16:00:16 ludvigm Exp */
@@ -34,6 +34,6 @@
#ifndef _DNSSEC_H
#define _DNSSEC_H
-extern cert_t *dnssec_getcert __P((vchar_t *));
+extern vchar_t *dnssec_getcert __P((vchar_t *));
#endif /* _DNSSEC_H */
diff --git a/src/racoon/doc/FAQ b/src/racoon/doc/FAQ
index 0ab49f0..cf9c394 100644
--- a/src/racoon/doc/FAQ
+++ b/src/racoon/doc/FAQ
@@ -18,7 +18,7 @@ Q: How can I make racoon interoperate with <IKE/IPsec implementation>?
A:
Configure both ends exactly the same. With just a tiny little
- differnce, you will be in trouble.
+ difference, you will be in trouble.
Q: How to build racoon on my platform?
@@ -109,6 +109,6 @@ A:
Q: Other documents to look at?
A:
- http://www.netbsd.org/Documentation/network/ipsec/
+ http://www.NetBSD.org/docs/network/ipsec/
http://www.kame.net/
http://www.kame.net/newsletter/
diff --git a/src/racoon/doc/README.privsep b/src/racoon/doc/README.privsep
new file mode 100644
index 0000000..e01c820
--- /dev/null
+++ b/src/racoon/doc/README.privsep
@@ -0,0 +1,152 @@
+ Using Racoon with Privilege Separation
+ Tue Mar 25 16:37:09 MDT 2008
+
+
+Racoon can run in a chroot'd environment. When so instructed, it runs as two
+processes, one of which handles a small number of simple requests and runs as
+root in the full native filesystem, and another which runs as a less
+privileged user in a chroot'd environment and which handles all the other and
+very complex business of racoon.
+
+Because racoon does many complex things there are many opportunities for
+coding errors to lead to compromises and so this separation is important. If
+someone breaks into your system using racoon and you have enabled privilege
+separation, they will find themselves in a very limited environment and unable
+to do much damage. They may be able to alter the host's security associations
+or obtain the private keys stored on that system using file descriptors
+available to the unprivileged instance of racoon, and from there they will be
+able to alter security associations on other hosts in disruptive or dangerous
+ways if you have generate_policy enabled on those hosts. But that's because
+in its current form generate_policy is itself dangerous and requires that you
+trust anyone with the credentials to use it.
+
+They will also be able to execute any scripts you have placed in the scripts
+directory, although racoon will prevent them from mis-using the traditional
+environment variables PATH, LD_LIBRARY_PATH, and IFS. But if you have
+introduced vulnerabilities into your scripts you may want to re-visit them.
+The thing to watch for is blindly trusting the environment variables passed
+in by racoon - assume they could be set to anything by a malicious entity and
+check them for suitability before using them.
+
+All these possibilities are present when privilege separation is not enabled,
+and they are greatly reduced when it is enabled because the resources
+available to the attacker are less.
+
+*****
+
+The basic concept with racoon's privilege separation is that a minimal
+environment containing all the files racoon needs to operate - with the
+exception of private keys, scripts, and system-wide authentication services -
+is placed in a stripped-down copy of the original environment. The private
+keys and scripts are left in the original environment where only the
+privileged instance of racoon will have access to them.
+
+Here are basic instructions for setting up racoon to run with privilege
+separation:
+
+
+First, create a user/group for racoon to run under. For example, user:group
+ike:ike. The account should not have a usable password or real home
+directory, so copy the general format of another system-services type account
+such as 'daemon'.
+
+You already have files in, e.g. /usr/local/etc/racoon - perhaps racoon.conf, a
+certs directory containing certificates, a scripts directory, and other
+miscellaneous files such as welcome messages. Perform the following steps:
+
+cd /usr/local/etc/racoon
+mkdir root
+mv certs root
+mkdir certs
+mv root/certs/*.key certs
+
+If you want to be able to switch back and forth between using and not using
+privsep, do this too:
+
+cd /usr/local/etc/racoon/certs
+for i in ../root/certs/*
+do
+ ln -s $i .
+done
+
+Now root/certs contains certificates and certs contains the keys. The idea is
+that the public certificates are in the chroot'd area
+(/usr/local/etc/racoon/root) and the keys are available only to the privileged
+instance of racoon.
+
+Move any other racoon configuration data into /usr/local/etc/racoon/root,
+with the exception of the scripts directory and racoon.conf.
+
+All the files in /usr/local/etc/racoon/root should be owned by root and the
+ike:ike user you created should not have write access to any directories or
+files (unless you are using something like 'path backupsa', but you get the
+idea).
+
+Create the device nodes:
+
+mkdir root/dev
+
+Do whatever your OS requires to populate the new dev directory with a
+minimal set of devices, e.g. mknod, MAKEDEV, or mount devfs... In freebsd
+this is done by adding a line to /etc/fstab:
+
+devfs /usr/local/etc/racoon/root/dev devfs rw 0 0
+
+and then adding a line like this to /etc/rc.conf:
+
+devfs_set_rulesets="/usr/local/etc/racoon/root/dev=devfsrules_basic"
+
+and then adding the following lines to /etc/devfs.rules:
+
+[devfsrules_basic=10]
+add include $devfsrules_hide_all
+add include $devfsrules_unhide_basic
+
+and then either rebooting or entering "mount -a && /etc/rc.d/devfs start".
+
+When done with that:
+
+mkdir -p root/usr/local/etc
+ln -s ../../../ root/usr/local/etc/racoon
+
+This dummy hierarchy keeps the config file consistent between both copies of
+racoon. Of course, you could actually put the certs directory and any other
+configuration data down in the hierarchy but I prefer to leave it at the root
+and link to it as shown. You may end up with something like this:
+
+root# ls -FC /usr/local/etc/racoon/root
+certs/ dev/ usr/
+
+root# ls -l /usr/local/etc/racoon/root/usr/local/etc
+lrwxr-xr-x 1 root wheel 9 Mar 7 22:13 racoon -> ../../../
+
+root# ls -FC /usr/local/etc/racoon/root/usr/local/etc/racoon/
+certs/ dev/ usr/
+
+Presumably your racoon.conf already contains something like:
+
+path certificate "/usr/local/etc/racoon/certs";
+path script "/usr/local/etc/racoon/scripts";
+
+If so, great. If not, add them. Then, finally, add the privsep section:
+
+privsep {
+ user "ike";
+ group "ike";
+ chroot "/usr/local/etc/racoon/root";
+}
+
+Apply the patches posted to the list and rebuild racoon (the patches will be
+incorporated into the release subsequent to the date of this memo, so if you
+use that or a later release you can skip this step).
+
+Restart racoon and hopefully things will work. As of the date of this memo,
+re-loading the configuration file with racoonctl will not work with privsep
+enabled. However, the problem is not insurmountable and if you figure it out
+let us know.
+
+I have not tested privsep with many of racoon's features such as XAUTH or
+scripts, so if you have trouble with them and work anything out please reply
+to the list so that your discoveries may be incorporated into this document.
+
+Last modified: $Date: 2008/03/28 04:18:52 $
diff --git a/src/racoon/eaytest.c b/src/racoon/eaytest.c
index 323ecef..1474bdc 100644
--- a/src/racoon/eaytest.c
+++ b/src/racoon/eaytest.c
@@ -1,4 +1,4 @@
-/* $NetBSD: eaytest.c,v 1.7.6.2 2008/07/15 00:55:48 mgrooms Exp $ */
+/* $NetBSD: eaytest.c,v 1.10 2010/01/17 23:02:48 wiz Exp $ */
/* Id: eaytest.c,v 1.22 2005/06/19 18:02:54 manubsd Exp */
@@ -572,6 +572,7 @@ getcerts(path)
n++;
}
+ closedir(dirp);
p = (char **)realloc(certs, (n + 1) * sizeof(certs));
if (p == NULL)
diff --git a/src/racoon/evt.c b/src/racoon/evt.c
index fc65b20..11d9695 100644
--- a/src/racoon/evt.c
+++ b/src/racoon/evt.c
@@ -1,9 +1,10 @@
-/* $NetBSD: evt.c,v 1.5 2006/09/09 16:22:09 manu Exp $ */
+/* $NetBSD: evt.c,v 1.10 2010/10/21 06:15:28 tteras Exp $ */
/* Id: evt.c,v 1.5 2006/06/22 20:11:35 manubsd Exp */
/*
* Copyright (C) 2004 Emmanuel Dreyfus
+ * Copyright (C) 2008 Timo Teras
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -46,14 +47,55 @@
#include "plog.h"
#include "misc.h"
#include "admin.h"
+#include "handler.h"
+#include "session.h"
#include "gcmalloc.h"
#include "evt.h"
+#include "var.h"
#ifdef ENABLE_ADMINPORT
-struct evtlist evtlist = TAILQ_HEAD_INITIALIZER(evtlist);
-int evtlist_len = 0;
-void
+static EVT_LISTENER_LIST(evt_listeners);
+
+struct evt_message {
+ struct admin_com adm;
+ struct evt_async evt;
+};
+
+struct evt {
+ struct evtdump *dump;
+ TAILQ_ENTRY(evt) next;
+};
+
+TAILQ_HEAD(evtlist, evt);
+
+#define EVTLIST_MAX 32
+
+static struct evtlist evtlist = TAILQ_HEAD_INITIALIZER(evtlist);
+static int evtlist_len = 0;
+static int evtlist_inuse = 0;
+
+static struct {
+ int newtype, oldtype;
+} evttype_map[] = {
+ { EVT_RACOON_QUIT, EVTT_RACOON_QUIT },
+ { EVT_PHASE1_UP, EVTT_PHASE1_UP },
+ { EVT_PHASE1_DOWN, EVTT_PHASE1_DOWN },
+ { EVT_PHASE1_NO_RESPONSE, EVTT_PEER_NO_RESPONSE },
+ { EVT_PHASE1_NO_PROPOSAL, EVTT_PEERPH1_NOPROP },
+ { EVT_PHASE1_AUTH_FAILED, EVTT_PEERPH1AUTH_FAILED },
+ { EVT_PHASE1_DPD_TIMEOUT, EVTT_DPD_TIMEOUT },
+ { EVT_PHASE1_PEER_DELETED, EVTT_PEER_DELETE },
+ { EVT_PHASE1_MODE_CFG, EVTT_ISAKMP_CFG_DONE },
+ { EVT_PHASE1_XAUTH_SUCCESS, EVTT_XAUTH_SUCCESS },
+ { EVT_PHASE1_XAUTH_FAILED, EVTT_XAUTH_FAILED },
+ { EVT_PHASE2_NO_PHASE1, -1 },
+ { EVT_PHASE2_UP, EVTT_PHASE2_UP },
+ { EVT_PHASE2_DOWN, EVTT_PHASE2_DOWN },
+ { EVT_PHASE2_NO_RESPONSE, EVTT_PEER_NO_RESPONSE },
+};
+
+static void
evt_push(src, dst, type, optdata)
struct sockaddr *src;
struct sockaddr *dst;
@@ -63,9 +105,21 @@ evt_push(src, dst, type, optdata)
struct evtdump *evtdump;
struct evt *evt;
size_t len;
+ int i;
/* If admin socket is disabled, silently discard anything */
- if (adminsock_path == NULL)
+ if (adminsock_path == NULL || !evtlist_inuse)
+ return;
+
+ /* Map the event type to old */
+ for (i = 0; i < sizeof(evttype_map) / sizeof(evttype_map[0]); i++)
+ if (evttype_map[i].newtype == type)
+ break;
+ if (i >= sizeof(evttype_map) / sizeof(evttype_map[0]))
+ return;
+
+ type = evttype_map[i].oldtype;
+ if (type < 0)
return;
/* If we are above the limit, don't record anything */
@@ -121,7 +175,7 @@ evt_push(src, dst, type, optdata)
return;
}
-struct evtdump *
+static struct evtdump *
evt_pop(void) {
struct evtdump *evtdump;
struct evt *evt;
@@ -142,6 +196,12 @@ evt_dump(void) {
struct evtdump *evtdump;
vchar_t *buf = NULL;
+ if (!evtlist_inuse) {
+ evtlist_inuse = 1;
+ plog(LLV_ERROR, LOCATION, NULL,
+ "evt_dump: deprecated event polling used\n");
+ }
+
if ((evtdump = evt_pop()) != NULL) {
if ((buf = vmalloc(evtdump->len)) == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
@@ -155,4 +215,185 @@ evt_dump(void) {
return buf;
}
+static struct evt_message *
+evtmsg_create(type, optdata)
+ int type;
+ vchar_t *optdata;
+{
+ struct evt_message *e;
+ size_t len;
+
+ len = sizeof(struct evt_message);
+ if (optdata != NULL)
+ len += optdata->l;
+
+ if ((e = racoon_malloc(len)) == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate event: %s\n",
+ strerror(errno));
+ return NULL;
+ }
+
+ memset(e, 0, sizeof(struct evt_message));
+ e->adm.ac_len = len;
+ e->adm.ac_cmd = ADMIN_SHOW_EVT;
+ e->adm.ac_errno = 0;
+ e->adm.ac_proto = 0;
+ e->evt.ec_type = type;
+ time(&e->evt.ec_timestamp);
+ if (optdata != NULL)
+ memcpy(e + 1, optdata->v, optdata->l);
+
+ return e;
+}
+
+static void
+evt_unsubscribe(l)
+ struct evt_listener *l;
+{
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "[%d] admin connection released\n", l->fd);
+
+ LIST_REMOVE(l, ll_chain);
+ unmonitor_fd(l->fd);
+ close(l->fd);
+ racoon_free(l);
+}
+
+static int
+evt_unsubscribe_cb(ctx, fd)
+ void *ctx;
+ int fd;
+{
+ evt_unsubscribe((struct evt_listener *) ctx);
+ return 0;
+}
+
+static void
+evtmsg_broadcast(ll, e)
+ const struct evt_listener_list *ll;
+ struct evt_message *e;
+{
+ struct evt_listener *l, *nl;
+
+ for (l = LIST_FIRST(ll); l != NULL; l = nl) {
+ nl = LIST_NEXT(l, ll_chain);
+
+ if (send(l->fd, e, e->adm.ac_len, MSG_DONTWAIT) < 0) {
+ plog(LLV_DEBUG, LOCATION, NULL, "Cannot send event to fd: %s\n",
+ strerror(errno));
+ evt_unsubscribe(l);
+ }
+ }
+}
+
+void
+evt_generic(type, optdata)
+ int type;
+ vchar_t *optdata;
+{
+ struct evt_message *e;
+
+ if ((e = evtmsg_create(type, optdata)) == NULL)
+ return;
+
+ evtmsg_broadcast(&evt_listeners, e);
+ evt_push(&e->evt.ec_ph1src, &e->evt.ec_ph1dst, type, optdata);
+
+ racoon_free(e);
+}
+
+void
+evt_phase1(ph1, type, optdata)
+ const struct ph1handle *ph1;
+ int type;
+ vchar_t *optdata;
+{
+ struct evt_message *e;
+
+ if ((e = evtmsg_create(type, optdata)) == NULL)
+ return;
+
+ if (ph1->local)
+ memcpy(&e->evt.ec_ph1src, ph1->local, sysdep_sa_len(ph1->local));
+ if (ph1->remote)
+ memcpy(&e->evt.ec_ph1dst, ph1->remote, sysdep_sa_len(ph1->remote));
+
+ evtmsg_broadcast(&ph1->evt_listeners, e);
+ evtmsg_broadcast(&evt_listeners, e);
+ evt_push(&e->evt.ec_ph1src, &e->evt.ec_ph1dst, type, optdata);
+
+ racoon_free(e);
+}
+
+void
+evt_phase2(ph2, type, optdata)
+ const struct ph2handle *ph2;
+ int type;
+ vchar_t *optdata;
+{
+ struct evt_message *e;
+ struct ph1handle *ph1 = ph2->ph1;
+
+ if ((e = evtmsg_create(type, optdata)) == NULL)
+ return;
+
+ if (ph1) {
+ if (ph1->local)
+ memcpy(&e->evt.ec_ph1src, ph1->local, sysdep_sa_len(ph1->local));
+ if (ph1->remote)
+ memcpy(&e->evt.ec_ph1dst, ph1->remote, sysdep_sa_len(ph1->remote));
+ }
+ e->evt.ec_ph2msgid = ph2->msgid;
+
+ evtmsg_broadcast(&ph2->evt_listeners, e);
+ if (ph1)
+ evtmsg_broadcast(&ph1->evt_listeners, e);
+ evtmsg_broadcast(&evt_listeners, e);
+ evt_push(&e->evt.ec_ph1src, &e->evt.ec_ph1dst, type, optdata);
+
+ racoon_free(e);
+}
+
+int
+evt_subscribe(list, fd)
+ struct evt_listener_list *list;
+ int fd;
+{
+ struct evt_listener *l;
+
+ if ((l = racoon_malloc(sizeof(*l))) == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "Cannot allocate event listener: %s\n",
+ strerror(errno));
+ return errno;
+ }
+
+ if (list == NULL)
+ list = &evt_listeners;
+
+ LIST_INSERT_HEAD(list, l, ll_chain);
+ l->fd = fd;
+ monitor_fd(l->fd, evt_unsubscribe_cb, l, 0);
+
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "[%d] admin connection is polling events\n", fd);
+
+ return -2;
+}
+
+void
+evt_list_init(list)
+ struct evt_listener_list *list;
+{
+ LIST_INIT(list);
+}
+
+void
+evt_list_cleanup(list)
+ struct evt_listener_list *list;
+{
+ while (!LIST_EMPTY(list))
+ evt_unsubscribe(LIST_FIRST(list));
+}
+
#endif /* ENABLE_ADMINPORT */
diff --git a/src/racoon/evt.h b/src/racoon/evt.h
index 88ee366..42e14d7 100644
--- a/src/racoon/evt.h
+++ b/src/racoon/evt.h
@@ -1,9 +1,10 @@
-/* $NetBSD: evt.h,v 1.4 2006/09/09 16:22:09 manu Exp $ */
+/* $NetBSD: evt.h,v 1.7 2008/12/23 14:03:12 tteras Exp $ */
/* Id: evt.h,v 1.5 2006/01/19 10:24:09 fredsen Exp */
/*
* Copyright (C) 2004 Emmanuel Dreyfus
+ * Copyright (C) 2008 Timo Teras
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,6 +35,10 @@
#ifndef _EVT_H
#define _EVT_H
+/*
+ * Old style (deprecated) events which are polled.
+ */
+
struct evtdump {
size_t len;
struct sockaddr_storage src;
@@ -64,25 +69,78 @@ struct evtdump {
#define EVTT_PEERPH1_NOPROP 14 /* NO_PROPOSAL_CHOSEN & friends */
#define EVTT_NO_ISAKMP_CFG 15 /* no need to wait for mode_cfg */
-struct evt {
- struct evtdump *dump;
- TAILQ_ENTRY(evt) next;
+/*
+ * New style, asynchronous events.
+ */
+
+struct evt_async {
+ uint32_t ec_type;
+ time_t ec_timestamp;
+
+ struct sockaddr_storage ec_ph1src;
+ struct sockaddr_storage ec_ph1dst;
+ u_int32_t ec_ph2msgid;
+
+ /*
+ * Optionnal list of struct isakmp_data
+ * for type EVTT_ISAKMP_CFG_DONE
+ */
};
-TAILQ_HEAD(evtlist, evt);
+/* type */
+#define EVT_RACOON_QUIT 0x0001
+
+#define EVT_PHASE1_UP 0x0100
+#define EVT_PHASE1_DOWN 0x0101
+#define EVT_PHASE1_NO_RESPONSE 0x0102
+#define EVT_PHASE1_NO_PROPOSAL 0x0103
+#define EVT_PHASE1_AUTH_FAILED 0x0104
+#define EVT_PHASE1_DPD_TIMEOUT 0x0105
+#define EVT_PHASE1_PEER_DELETED 0x0106
+#define EVT_PHASE1_MODE_CFG 0x0107
+#define EVT_PHASE1_XAUTH_SUCCESS 0x0108
+#define EVT_PHASE1_XAUTH_FAILED 0x0109
-#define EVTLIST_MAX 32
+#define EVT_PHASE2_NO_PHASE1 0x0200
+#define EVT_PHASE2_UP 0x0201
+#define EVT_PHASE2_DOWN 0x0202
+#define EVT_PHASE2_NO_RESPONSE 0x0203
#ifdef ENABLE_ADMINPORT
-struct evtdump *evt_pop(void);
-vchar_t *evt_dump(void);
-void evt_push(struct sockaddr *, struct sockaddr *, int, vchar_t *);
-#endif
-#ifdef ENABLE_ADMINPORT
-#define EVT_PUSH(src, dst, type, optdata) evt_push(src, dst, type, optdata);
+struct ph1handle;
+struct ph2handle;
+
+struct evt_listener {
+ LIST_ENTRY(evt_listener) ll_chain;
+ int fd;
+};
+LIST_HEAD(evt_listener_list, evt_listener);
+#define EVT_LISTENER_LIST(x) struct evt_listener_list x
+
+void evt_generic __P((int type, vchar_t *optdata));
+void evt_phase1 __P((const struct ph1handle *ph1, int type, vchar_t *optdata));
+void evt_phase2 __P((const struct ph2handle *ph2, int type, vchar_t *optdata));
+vchar_t *evt_dump __P((void));
+
+int evt_subscribe __P((struct evt_listener_list *list, int fd));
+void evt_list_init __P((struct evt_listener_list *list));
+void evt_list_cleanup __P((struct evt_listener_list *list));
+
#else
-#define EVT_PUSH(src, dst, type, optdata) ;
-#endif
+
+#define EVT_LISTENER_LIST(x)
+
+#define evt_generic(type, optdata) ;
+#define evt_phase1(ph1, type, optdata) ;
+#define evt_phase2(ph2, type, optdata) ;
+
+#define evt_subscribe(eventlist, fd) ;
+#define evt_list_init(eventlist) ;
+#define evt_list_cleanup(eventlist) ;
+#define evt_get_fdmask(nfds, fdset) nfds
+#define evt_handle_fdmask(fdset) ;
+
+#endif /* ENABLE_ADMINPORT */
#endif /* _EVT_H */
diff --git a/src/racoon/grabmyaddr.c b/src/racoon/grabmyaddr.c
index 8155001..29b913c 100644
--- a/src/racoon/grabmyaddr.c
+++ b/src/racoon/grabmyaddr.c
@@ -1,9 +1,7 @@
-/* $NetBSD: grabmyaddr.c,v 1.4.6.3 2008/06/18 07:30:18 mgrooms Exp $ */
-
-/* Id: grabmyaddr.c,v 1.27 2006/04/06 16:27:05 manubsd Exp */
-
+/* $NetBSD: grabmyaddr.c,v 1.28 2011/03/14 17:18:12 tteras Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * Copyright (C) 2008 Timo Teras <timo.teras@iki.fi>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -33,40 +31,32 @@
#include "config.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
#include <sys/types.h>
-#include <sys/param.h>
+#include <sys/queue.h>
#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <net/if.h>
-#if defined(__FreeBSD__) && __FreeBSD__ >= 3
-#include <net/if_var.h>
-#endif
-#if defined(__NetBSD__) || defined(__FreeBSD__) || \
- (defined(__APPLE__) && defined(__MACH__))
-#include <netinet/in.h>
-#include <netinet6/in6_var.h>
-#endif
+#ifdef __linux__
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#define USE_NETLINK
+#else
#include <net/route.h>
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <netdb.h>
-#ifdef HAVE_GETIFADDRS
-#include <ifaddrs.h>
#include <net/if.h>
-#endif
+#include <net/if_dl.h>
+#include <sys/sysctl.h>
+#define USE_ROUTE
+#endif
#include "var.h"
#include "misc.h"
#include "vmbuf.h"
#include "plog.h"
#include "sockmisc.h"
+#include "session.h"
#include "debug.h"
#include "localconf.h"
@@ -77,841 +67,803 @@
#include "gcmalloc.h"
#include "nattraversal.h"
-#ifdef __linux__
-#include <linux/types.h>
-#include <linux/rtnetlink.h>
-#ifndef HAVE_GETIFADDRS
-#define HAVE_GETIFADDRS
-#define NEED_LINUX_GETIFADDRS
-#endif
-#endif
-
-#ifndef HAVE_GETIFADDRS
-static unsigned int if_maxindex __P((void));
-#endif
-static struct myaddrs *find_myaddr __P((struct myaddrs *, struct myaddrs *));
-static int suitable_ifaddr __P((const char *, const struct sockaddr *));
-#ifdef INET6
-static int suitable_ifaddr6 __P((const char *, const struct sockaddr *));
-#endif
+static int kernel_receive __P((void *ctx, int fd));
+static int kernel_open_socket __P((void));
+static void kernel_sync __P((void));
-#ifdef NEED_LINUX_GETIFADDRS
+struct myaddr {
+ LIST_ENTRY(myaddr) chain;
+ struct sockaddr_storage addr;
+ int fd;
+ int udp_encap;
+};
-/* We could do this _much_ better. kame racoon in its current form
- * will esentially die at frequent changes of address configuration.
- */
+static LIST_HEAD(_myaddr_list_, myaddr) configured, opened;
-struct ifaddrs
+static void
+myaddr_delete(my)
+ struct myaddr *my;
{
- struct ifaddrs *ifa_next;
- char ifa_name[16];
- int ifa_ifindex;
- struct sockaddr *ifa_addr;
- struct sockaddr_storage ifa_addrbuf;
-};
+ if (my->fd != -1)
+ isakmp_close(my->fd);
+ LIST_REMOVE(my, chain);
+ racoon_free(my);
+}
-static int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)
+static int
+myaddr_configured(addr)
+ struct sockaddr *addr;
{
- while (RTA_OK(rta, len)) {
- if (rta->rta_type <= max)
- tb[rta->rta_type] = rta;
- rta = RTA_NEXT(rta,len);
+ struct myaddr *cfg;
+
+ if (LIST_EMPTY(&configured))
+ return TRUE;
+
+ LIST_FOREACH(cfg, &configured, chain) {
+ if (cmpsaddr(addr, (struct sockaddr *) &cfg->addr) <= CMPSADDR_WILDPORT_MATCH)
+ return TRUE;
}
- return 0;
+
+ return FALSE;
}
-static void recvaddrs(int fd, struct ifaddrs **ifa, __u32 seq)
+static int
+myaddr_open(addr, udp_encap)
+ struct sockaddr *addr;
+ int udp_encap;
{
- char buf[8192];
- struct sockaddr_nl nladdr;
- struct iovec iov = { buf, sizeof(buf) };
- struct ifaddrmsg *m;
- struct rtattr * rta_tb[IFA_MAX+1];
- struct ifaddrs *I;
-
- while (1) {
- int status;
- struct nlmsghdr *h;
+ struct myaddr *my;
- struct msghdr msg = {
- (void*)&nladdr, sizeof(nladdr),
- &iov, 1,
- NULL, 0,
- 0
- };
-
- status = recvmsg(fd, &msg, 0);
+ /* Already open? */
+ LIST_FOREACH(my, &opened, chain) {
+ if (cmpsaddr(addr, (struct sockaddr *) &my->addr) <= CMPSADDR_WILDPORT_MATCH)
+ return TRUE;
+ }
- if (status < 0)
- continue;
+ my = racoon_calloc(1, sizeof(struct myaddr));
+ if (my == NULL)
+ return FALSE;
- if (status == 0)
- return;
+ memcpy(&my->addr, addr, sysdep_sa_len(addr));
+ my->fd = isakmp_open(addr, udp_encap);
+ if (my->fd < 0) {
+ racoon_free(my);
+ return FALSE;
+ }
+ my->udp_encap = udp_encap;
+ LIST_INSERT_HEAD(&opened, my, chain);
+ return TRUE;
+}
- if (nladdr.nl_pid) /* Message not from kernel */
- continue;
+static int
+myaddr_open_all_configured(addr)
+ struct sockaddr *addr;
+{
+ /* create all configured, not already opened addresses */
+ struct myaddr *cfg, *my;
- h = (struct nlmsghdr*)buf;
- while (NLMSG_OK(h, status)) {
- if (h->nlmsg_seq != seq)
- goto skip_it;
-
- if (h->nlmsg_type == NLMSG_DONE)
- return;
-
- if (h->nlmsg_type == NLMSG_ERROR)
- return;
-
- if (h->nlmsg_type != RTM_NEWADDR)
- goto skip_it;
-
- m = NLMSG_DATA(h);
-
- if (m->ifa_family != AF_INET &&
- m->ifa_family != AF_INET6)
- goto skip_it;
-
- if (m->ifa_flags&IFA_F_TENTATIVE)
- goto skip_it;
-
- memset(rta_tb, 0, sizeof(rta_tb));
- parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(m), h->nlmsg_len - NLMSG_LENGTH(sizeof(*m)));
-
- if (rta_tb[IFA_LOCAL] == NULL)
- rta_tb[IFA_LOCAL] = rta_tb[IFA_ADDRESS];
- if (rta_tb[IFA_LOCAL] == NULL)
- goto skip_it;
-
- I = malloc(sizeof(struct ifaddrs));
- if (!I)
- return;
- memset(I, 0, sizeof(*I));
-
- I->ifa_ifindex = m->ifa_index;
- I->ifa_addr = (struct sockaddr*)&I->ifa_addrbuf;
- I->ifa_addr->sa_family = m->ifa_family;
- if (m->ifa_family == AF_INET) {
- struct sockaddr_in *sin = (void*)I->ifa_addr;
- memcpy(&sin->sin_addr, RTA_DATA(rta_tb[IFA_LOCAL]), 4);
- } else {
- struct sockaddr_in6 *sin = (void*)I->ifa_addr;
- memcpy(&sin->sin6_addr, RTA_DATA(rta_tb[IFA_LOCAL]), 16);
- if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr))
- sin->sin6_scope_id = I->ifa_ifindex;
- }
- I->ifa_next = *ifa;
- *ifa = I;
-
-skip_it:
- h = NLMSG_NEXT(h, status);
+ if (addr != NULL) {
+ switch (addr->sa_family) {
+ case AF_INET:
+#ifdef INET6
+ case AF_INET6:
+#endif
+ break;
+ default:
+ return FALSE;
}
- if (msg.msg_flags & MSG_TRUNC)
+ }
+
+ LIST_FOREACH(cfg, &configured, chain) {
+ if (addr != NULL &&
+ cmpsaddr(addr, (struct sockaddr *) &cfg->addr) > CMPSADDR_WILDPORT_MATCH)
continue;
+ if (!myaddr_open((struct sockaddr *) &cfg->addr, cfg->udp_encap))
+ return FALSE;
+ }
+ if (LIST_EMPTY(&configured)) {
+#ifdef ENABLE_HYBRID
+ /* Exclude any address we got through ISAKMP mode config */
+ if (exclude_cfg_addr(addr) == 0)
+ return FALSE;
+#endif
+ set_port(addr, lcconf->port_isakmp);
+ myaddr_open(addr, FALSE);
+#ifdef ENABLE_NATT
+ set_port(addr, lcconf->port_isakmp_natt);
+ myaddr_open(addr, TRUE);
+#endif
}
- return;
+ return TRUE;
}
-static int getifaddrs(struct ifaddrs **ifa0)
+static void
+myaddr_close_all_open(addr)
+ struct sockaddr *addr;
{
- struct {
- struct nlmsghdr nlh;
- struct rtgenmsg g;
- } req;
- struct sockaddr_nl nladdr;
- static __u32 seq;
- struct ifaddrs *i;
- int fd;
+ /* delete all matching open sockets */
+ struct myaddr *my, *next;
- fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
- if (fd < 0)
- return -1;
+ for (my = LIST_FIRST(&opened); my; my = next) {
+ next = LIST_NEXT(my, chain);
- memset(&nladdr, 0, sizeof(nladdr));
- nladdr.nl_family = AF_NETLINK;
+ if (cmpsaddr((struct sockaddr *) addr,
+ (struct sockaddr *) &my->addr)
+ <= CMPSADDR_WOP_MATCH)
+ myaddr_delete(my);
+ }
+}
- req.nlh.nlmsg_len = sizeof(req);
- req.nlh.nlmsg_type = RTM_GETADDR;
- req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST;
- req.nlh.nlmsg_pid = 0;
- req.nlh.nlmsg_seq = ++seq;
- req.g.rtgen_family = AF_UNSPEC;
+static void
+myaddr_flush_list(list)
+ struct _myaddr_list_ *list;
+{
+ struct myaddr *my, *next;
- if (sendto(fd, (void*)&req, sizeof(req), 0, (struct sockaddr*)&nladdr, sizeof(nladdr)) < 0) {
- close(fd);
- return -1;
+ for (my = LIST_FIRST(list); my; my = next) {
+ next = LIST_NEXT(my, chain);
+ myaddr_delete(my);
}
+}
- *ifa0 = NULL;
+void
+myaddr_flush()
+{
+ myaddr_flush_list(&configured);
+}
- recvaddrs(fd, ifa0, seq);
+int
+myaddr_listen(addr, udp_encap)
+ struct sockaddr *addr;
+ int udp_encap;
+{
+ struct myaddr *my;
- close(fd);
+ if (sysdep_sa_len(addr) > sizeof(my->addr)) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "sockaddr size larger than sockaddr_storage\n");
+ return -1;
+ }
- fd = socket(AF_INET, SOCK_DGRAM, 0);
+ my = racoon_calloc(1, sizeof(struct myaddr));
+ if (my == NULL)
+ return -1;
- for (i=*ifa0; i; i = i->ifa_next) {
- struct ifreq ifr;
- ifr.ifr_ifindex = i->ifa_ifindex;
- ioctl(fd, SIOCGIFNAME, (void*)&ifr);
- memcpy(i->ifa_name, ifr.ifr_name, 16);
- }
- close(fd);
+ memcpy(&my->addr, addr, sysdep_sa_len(addr));
+ my->udp_encap = udp_encap;
+ my->fd = -1;
+ LIST_INSERT_HEAD(&configured, my, chain);
return 0;
}
-static void freeifaddrs(struct ifaddrs *ifa0)
+void
+myaddr_sync()
{
- struct ifaddrs *i;
+ struct myaddr *my, *next;
- while (ifa0) {
- i = ifa0;
- ifa0 = i->ifa_next;
- free(i);
- }
-}
-
-#endif
+ if (!lcconf->strict_address) {
+ kernel_sync();
-#ifndef HAVE_GETIFADDRS
-static unsigned int
-if_maxindex()
-{
- struct if_nameindex *p, *p0;
- unsigned int max = 0;
+ /* delete all existing listeners which are not configured */
+ for (my = LIST_FIRST(&opened); my; my = next) {
+ next = LIST_NEXT(my, chain);
- p0 = if_nameindex();
- for (p = p0; p && p->if_index && p->if_name; p++) {
- if (max < p->if_index)
- max = p->if_index;
+ if (!myaddr_configured((struct sockaddr *) &my->addr))
+ myaddr_delete(my);
+ }
}
- if_freenameindex(p0);
- return max;
}
-#endif
-void
-clear_myaddr(db)
- struct myaddrs **db;
+int
+myaddr_getfd(addr)
+ struct sockaddr *addr;
{
- struct myaddrs *p;
+ struct myaddr *my;
- while (*db) {
- p = (*db)->next;
- delmyaddr(*db);
- *db = p;
+ LIST_FOREACH(my, &opened, chain) {
+ if (cmpsaddr((struct sockaddr *) &my->addr, addr) <= CMPSADDR_WILDPORT_MATCH)
+ return my->fd;
}
+
+ return -1;
}
-
-static struct myaddrs *
-find_myaddr(db, p)
- struct myaddrs *db;
- struct myaddrs *p;
-{
- struct myaddrs *q;
- char h1[NI_MAXHOST], h2[NI_MAXHOST];
- if (getnameinfo(p->addr, sysdep_sa_len(p->addr), h1, sizeof(h1), NULL, 0,
- NI_NUMERICHOST | niflags) != 0)
- return NULL;
+int
+myaddr_getsport(addr)
+ struct sockaddr *addr;
+{
+ struct myaddr *my;
- for (q = db; q; q = q->next) {
- if (p->addr->sa_family != q->addr->sa_family)
- continue;
- if (getnameinfo(q->addr, sysdep_sa_len(q->addr), h2, sizeof(h2),
- NULL, 0, NI_NUMERICHOST | niflags) != 0)
- return NULL;
- if (strcmp(h1, h2) == 0)
- return q;
+ LIST_FOREACH(my, &opened, chain) {
+ if (cmpsaddr((struct sockaddr *) &my->addr, addr) <= CMPSADDR_WILDPORT_MATCH)
+ return extract_port((struct sockaddr *) &my->addr);
}
- return NULL;
+ return PORT_ISAKMP;
}
void
-grab_myaddrs()
+myaddr_init_lists()
{
-#ifdef HAVE_GETIFADDRS
- struct myaddrs *p, *q, *old;
- struct ifaddrs *ifa0, *ifap;
-#ifdef INET6
- struct sockaddr_in6 *sin6;
-#endif
-
- char addr1[NI_MAXHOST];
+ LIST_INIT(&configured);
+ LIST_INIT(&opened);
+}
- if (getifaddrs(&ifa0)) {
- plog(LLV_ERROR, LOCATION, NULL,
- "getifaddrs failed: %s\n", strerror(errno));
- exit(1);
- /*NOTREACHED*/
+int
+myaddr_init()
+{
+ if (!lcconf->strict_address) {
+ lcconf->rtsock = kernel_open_socket();
+ if (lcconf->rtsock < 0)
+ return -1;
+ monitor_fd(lcconf->rtsock, kernel_receive, NULL, 0);
+ } else {
+ lcconf->rtsock = -1;
+ if (!myaddr_open_all_configured(NULL))
+ return -1;
}
+ return 0;
+}
- old = lcconf->myaddrs;
-
- for (ifap = ifa0; ifap; ifap = ifap->ifa_next) {
- if (! ifap->ifa_addr)
- continue;
-
- if (ifap->ifa_addr->sa_family != AF_INET
-#ifdef INET6
- && ifap->ifa_addr->sa_family != AF_INET6
-#endif
- )
- continue;
-
- if (!suitable_ifaddr(ifap->ifa_name, ifap->ifa_addr)) {
- plog(LLV_ERROR, LOCATION, NULL,
- "unsuitable address: %s %s\n",
- ifap->ifa_name,
- saddrwop2str(ifap->ifa_addr));
- continue;
- }
-
- p = newmyaddr();
- if (p == NULL) {
- exit(1);
- /*NOTREACHED*/
- }
- p->addr = dupsaddr(ifap->ifa_addr);
- if (p->addr == NULL) {
- exit(1);
- /*NOTREACHED*/
- }
-#ifdef INET6
-#ifdef __KAME__
- if (ifap->ifa_addr->sa_family == AF_INET6) {
- sin6 = (struct sockaddr_in6 *)p->addr;
- if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)
- || IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) {
- sin6->sin6_scope_id =
- ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]);
- sin6->sin6_addr.s6_addr[2] = 0;
- sin6->sin6_addr.s6_addr[3] = 0;
- }
- }
-#else /* !__KAME__ */
- if (ifap->ifa_addr->sa_family == AF_INET6) {
- sin6 = (struct sockaddr_in6 *)p->addr;
- if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)
- || IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) {
- sin6->sin6_scope_id =
- if_nametoindex(ifap->ifa_name);
- }
- }
-
-#endif
-#endif
- if (getnameinfo(p->addr, sysdep_sa_len(p->addr),
- addr1, sizeof(addr1),
- NULL, 0,
- NI_NUMERICHOST | niflags))
- strlcpy(addr1, "(invalid)", sizeof(addr1));
- plog(LLV_DEBUG, LOCATION, NULL,
- "my interface: %s (%s)\n",
- addr1, ifap->ifa_name);
- q = find_myaddr(old, p);
- if (q)
- p->sock = q->sock;
- else
- p->sock = -1;
- p->next = lcconf->myaddrs;
- lcconf->myaddrs = p;
+void
+myaddr_close()
+{
+ myaddr_flush_list(&configured);
+ myaddr_flush_list(&opened);
+ if (lcconf->rtsock != -1) {
+ unmonitor_fd(lcconf->rtsock);
+ close(lcconf->rtsock);
}
+}
- freeifaddrs(ifa0);
-
- clear_myaddr(&old);
-
-#else /*!HAVE_GETIFADDRS*/
- int s;
- unsigned int maxif;
- int len;
- struct ifreq *iflist;
- struct ifconf ifconf;
- struct ifreq *ifr, *ifr_end;
- struct myaddrs *p, *q, *old;
-#ifdef INET6
-#ifdef __KAME__
- struct sockaddr_in6 *sin6;
-#endif
-#endif
-
- char addr1[NI_MAXHOST];
+#if defined(USE_NETLINK)
- maxif = if_maxindex() + 1;
- len = maxif * sizeof(struct sockaddr_storage) * 4; /* guess guess */
+static int netlink_fd = -1;
- iflist = (struct ifreq *)racoon_malloc(len);
- if (!iflist) {
- plog(LLV_ERROR, LOCATION, NULL,
- "failed to allocate buffer\n");
- exit(1);
- /*NOTREACHED*/
- }
+#define NLMSG_TAIL(nmsg) \
+ ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
- if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
- plog(LLV_ERROR, LOCATION, NULL,
- "socket(SOCK_DGRAM) failed: %s\n",
- strerror(errno));
- exit(1);
- /*NOTREACHED*/
- }
- memset(&ifconf, 0, sizeof(ifconf));
- ifconf.ifc_req = iflist;
- ifconf.ifc_len = len;
- if (ioctl(s, SIOCGIFCONF, &ifconf) < 0) {
- close(s);
- plog(LLV_ERROR, LOCATION, NULL,
- "ioctl(SIOCGIFCONF) failed: %s\n",
- strerror(errno));
- exit(1);
- /*NOTREACHED*/
+static void
+parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)
+{
+ memset(tb, 0, sizeof(struct rtattr *) * (max + 1));
+ while (RTA_OK(rta, len)) {
+ if (rta->rta_type <= max)
+ tb[rta->rta_type] = rta;
+ rta = RTA_NEXT(rta,len);
}
- close(s);
-
- old = lcconf->myaddrs;
+}
- /* Look for this interface in the list */
- ifr_end = (struct ifreq *) (ifconf.ifc_buf + ifconf.ifc_len);
+static int
+netlink_add_rtattr_l(struct nlmsghdr *n, int maxlen, int type,
+ const void *data, int alen)
+{
+ int len = RTA_LENGTH(alen);
+ struct rtattr *rta;
+
+ if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen)
+ return FALSE;
+
+ rta = NLMSG_TAIL(n);
+ rta->rta_type = type;
+ rta->rta_len = len;
+ memcpy(RTA_DATA(rta), data, alen);
+ n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
+ return TRUE;
+}
-#define _IFREQ_LEN(p) \
- (sizeof((p)->ifr_name) + sysdep_sa_len(&(p)->ifr_addr) > sizeof(struct ifreq) \
- ? sizeof((p)->ifr_name) + sysdep_sa_len(&(p)->ifr_addr) : sizeof(struct ifreq))
+static int
+netlink_enumerate(fd, family, type)
+ int fd;
+ int family;
+ int type;
+{
+ struct {
+ struct nlmsghdr nlh;
+ struct rtgenmsg g;
+ } req;
+ struct sockaddr_nl addr;
+ static __u32 seq = 0;
- for (ifr = ifconf.ifc_req;
- ifr < ifr_end;
- ifr = (struct ifreq *)((caddr_t)ifr + _IFREQ_LEN(ifr))) {
+ memset(&addr, 0, sizeof(addr));
+ addr.nl_family = AF_NETLINK;
- switch (ifr->ifr_addr.sa_family) {
- case AF_INET:
-#ifdef INET6
- case AF_INET6:
-#endif
- if (!suitable_ifaddr(ifr->ifr_name, &ifr->ifr_addr)) {
- plog(LLV_ERROR, LOCATION, NULL,
- "unsuitable address: %s %s\n",
- ifr->ifr_name,
- saddrwop2str(&ifr->ifr_addr));
- continue;
- }
-
- p = newmyaddr();
- if (p == NULL) {
- exit(1);
- /*NOTREACHED*/
- }
- p->addr = dupsaddr(&ifr->ifr_addr);
- if (p->addr == NULL) {
- exit(1);
- /*NOTREACHED*/
- }
-#ifdef INET6
-#ifdef __KAME__
- sin6 = (struct sockaddr_in6 *)p->addr;
- if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)
- || IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) {
- sin6->sin6_scope_id =
- ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]);
- sin6->sin6_addr.s6_addr[2] = 0;
- sin6->sin6_addr.s6_addr[3] = 0;
- }
-#endif
-#endif
- if (getnameinfo(p->addr, sysdep_sa_len(p->addr),
- addr1, sizeof(addr1),
- NULL, 0,
- NI_NUMERICHOST | niflags))
- strlcpy(addr1, "(invalid)", sizeof(addr1));
- plog(LLV_DEBUG, LOCATION, NULL,
- "my interface: %s (%s)\n",
- addr1, ifr->ifr_name);
- q = find_myaddr(old, p);
- if (q)
- p->sock = q->sock;
- else
- p->sock = -1;
- p->next = lcconf->myaddrs;
- lcconf->myaddrs = p;
- break;
- default:
- break;
- }
- }
-
- clear_myaddr(&old);
+ memset(&req, 0, sizeof(req));
+ req.nlh.nlmsg_len = sizeof(req);
+ req.nlh.nlmsg_type = type;
+ req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
+ req.nlh.nlmsg_pid = 0;
+ req.nlh.nlmsg_seq = ++seq;
+ req.g.rtgen_family = family;
- racoon_free(iflist);
-#endif /*HAVE_GETIFADDRS*/
+ return sendto(fd, (void *) &req, sizeof(req), 0,
+ (struct sockaddr *) &addr, sizeof(addr)) >= 0;
}
-/*
- * check the interface is suitable or not
- */
-static int
-suitable_ifaddr(ifname, ifaddr)
- const char *ifname;
- const struct sockaddr *ifaddr;
+static void
+netlink_add_del_address(int add, struct sockaddr *saddr)
{
-#ifdef ENABLE_HYBRID
- /* Exclude any address we got through ISAKMP mode config */
- if (exclude_cfg_addr(ifaddr) == 0)
- return 0;
-#endif
- switch(ifaddr->sa_family) {
- case AF_INET:
- return 1;
-#ifdef INET6
- case AF_INET6:
- return suitable_ifaddr6(ifname, ifaddr);
-#endif
- default:
- return 0;
- }
- /*NOTREACHED*/
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "Netlink: address %s %s\n",
+ saddrwop2str((struct sockaddr *) saddr),
+ add ? "added" : "deleted");
+
+ if (add)
+ myaddr_open_all_configured(saddr);
+ else
+ myaddr_close_all_open(saddr);
}
#ifdef INET6
static int
-suitable_ifaddr6(ifname, ifaddr)
- const char *ifname;
- const struct sockaddr *ifaddr;
+netlink_process_addr(struct nlmsghdr *h)
{
-#ifndef __linux__
- struct in6_ifreq ifr6;
- int s;
-#endif
+ struct sockaddr_storage addr;
+ struct ifaddrmsg *ifa;
+ struct rtattr *rta[IFA_MAX+1];
+ struct sockaddr_in6 *sin6;
- if (ifaddr->sa_family != AF_INET6)
+ ifa = NLMSG_DATA(h);
+ parse_rtattr(rta, IFA_MAX, IFA_RTA(ifa), IFA_PAYLOAD(h));
+
+ if (ifa->ifa_family != AF_INET6)
+ return 0;
+ if (ifa->ifa_flags & IFA_F_TENTATIVE)
+ return 0;
+ if (rta[IFA_LOCAL] == NULL)
+ rta[IFA_LOCAL] = rta[IFA_ADDRESS];
+ if (rta[IFA_LOCAL] == NULL)
return 0;
-#ifndef __linux__
- s = socket(PF_INET6, SOCK_DGRAM, 0);
- if (s == -1) {
- plog(LLV_ERROR, LOCATION, NULL,
- "socket(SOCK_DGRAM) failed:%s\n", strerror(errno));
+ memset(&addr, 0, sizeof(addr));
+ addr.ss_family = ifa->ifa_family;
+ sin6 = (struct sockaddr_in6 *) &addr;
+ memcpy(&sin6->sin6_addr, RTA_DATA(rta[IFA_LOCAL]),
+ sizeof(sin6->sin6_addr));
+ if (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
return 0;
- }
+ sin6->sin6_scope_id = ifa->ifa_index;
- memset(&ifr6, 0, sizeof(ifr6));
- strncpy(ifr6.ifr_name, ifname, strlen(ifname));
+ netlink_add_del_address(h->nlmsg_type == RTM_NEWADDR,
+ (struct sockaddr *) &addr);
- ifr6.ifr_addr = *(const struct sockaddr_in6 *)ifaddr;
+ return 0;
+}
+#endif
- if (ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) < 0) {
- plog(LLV_ERROR, LOCATION, NULL,
- "ioctl(SIOCGIFAFLAG_IN6) failed:%s\n", strerror(errno));
- close(s);
- return 0;
- }
+static int
+netlink_route_is_local(int family, const unsigned char *addr, size_t addr_len)
+{
+ struct {
+ struct nlmsghdr n;
+ struct rtmsg r;
+ char buf[1024];
+ } req;
+ struct rtmsg *r = NLMSG_DATA(&req.n);
+ struct rtattr *rta[RTA_MAX+1];
+ struct sockaddr_nl nladdr;
+ ssize_t rlen;
- close(s);
+ memset(&req, 0, sizeof(req));
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
+ req.n.nlmsg_flags = NLM_F_REQUEST;
+ req.n.nlmsg_type = RTM_GETROUTE;
+ req.r.rtm_family = family;
+ netlink_add_rtattr_l(&req.n, sizeof(req), RTA_DST,
+ addr, addr_len);
+ req.r.rtm_dst_len = addr_len * 8;
- if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DUPLICATED
- || ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DETACHED
- || ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_ANYCAST)
+ memset(&nladdr, 0, sizeof(nladdr));
+ nladdr.nl_family = AF_NETLINK;
+
+ if (sendto(netlink_fd, &req, sizeof(req), 0,
+ (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0)
+ return 0;
+ rlen = recv(netlink_fd, &req, sizeof(req), 0);
+ if (rlen < 0)
return 0;
-#endif
- /* suitable */
- return 1;
+ return req.n.nlmsg_type == RTM_NEWROUTE &&
+ req.r.rtm_type == RTN_LOCAL;
}
-#endif
-int
-update_myaddrs()
+static int
+netlink_process_route(struct nlmsghdr *h)
{
-#ifdef __linux__
- char msg[BUFSIZ];
- int len;
- struct nlmsghdr *h = (void*)msg;
- len = read(lcconf->rtsock, msg, sizeof(msg));
- if (len < 0)
- return errno == ENOBUFS;
- if (len < sizeof(*h))
- return 0;
- if (h->nlmsg_pid) /* not from kernel! */
- return 0;
- if (h->nlmsg_type == RTM_NEWLINK)
- return 0;
- plog(LLV_DEBUG, LOCATION, NULL,
- "netlink signals update interface address list\n");
- return 1;
-#else
- char msg[BUFSIZ];
- int len;
- struct rt_msghdr *rtm;
+ struct sockaddr_storage addr;
+ struct rtmsg *rtm;
+ struct rtattr *rta[RTA_MAX+1];
+ struct sockaddr_in *sin;
+#ifdef INET6
+ struct sockaddr_in6 *sin6;
+#endif
- len = read(lcconf->rtsock, msg, sizeof(msg));
- if (len < 0) {
- plog(LLV_ERROR, LOCATION, NULL,
- "read(PF_ROUTE) failed: %s\n",
- strerror(errno));
- return 0;
- }
- rtm = (struct rt_msghdr *)msg;
- if (len < rtm->rtm_msglen) {
- plog(LLV_ERROR, LOCATION, NULL,
- "read(PF_ROUTE) short read\n");
- return 0;
- }
- if (rtm->rtm_version != RTM_VERSION) {
- plog(LLV_ERROR, LOCATION, NULL,
- "routing socket version mismatch\n");
- close(lcconf->rtsock);
- lcconf->rtsock = -1;
+ rtm = NLMSG_DATA(h);
+
+ /* local IP addresses get local route in the local table */
+ if (rtm->rtm_type != RTN_LOCAL ||
+ rtm->rtm_table != RT_TABLE_LOCAL)
return 0;
- }
- switch (rtm->rtm_type) {
- case RTM_NEWADDR:
- case RTM_DELADDR:
- case RTM_DELETE:
- case RTM_IFINFO:
+
+ parse_rtattr(rta, IFA_MAX, RTM_RTA(rtm), IFA_PAYLOAD(h));
+ if (rta[RTA_DST] == NULL)
+ return 0;
+
+ /* setup the socket address */
+ memset(&addr, 0, sizeof(addr));
+ addr.ss_family = rtm->rtm_family;
+ switch (rtm->rtm_family) {
+ case AF_INET:
+ sin = (struct sockaddr_in *) &addr;
+ memcpy(&sin->sin_addr, RTA_DATA(rta[RTA_DST]),
+ sizeof(sin->sin_addr));
break;
- case RTM_MISS:
- /* ignore this message silently */
- return 0;
+#ifdef INET6
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *) &addr;
+ memcpy(&sin6->sin6_addr, RTA_DATA(rta[RTA_DST]),
+ sizeof(sin6->sin6_addr));
+ /* Link-local addresses are handled with RTM_NEWADDR
+ * notifications */
+ if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
+ return 0;
+ break;
+#endif
default:
+ return 0;
+ }
+
+ /* If local route was deleted, check if there is still local
+ * route for the same IP on another interface */
+ if (h->nlmsg_type == RTM_DELROUTE &&
+ netlink_route_is_local(rtm->rtm_family,
+ RTA_DATA(rta[RTA_DST]),
+ RTA_PAYLOAD(rta[RTA_DST]))) {
plog(LLV_DEBUG, LOCATION, NULL,
- "msg %d not interesting\n", rtm->rtm_type);
+ "Netlink: not deleting %s yet, it exists still\n",
+ saddrwop2str((struct sockaddr *) &addr));
return 0;
}
- /* XXX more filters here? */
- plog(LLV_DEBUG, LOCATION, NULL,
- "caught rtm:%d, need update interface address list\n",
- rtm->rtm_type);
- return 1;
-#endif /* __linux__ */
+ netlink_add_del_address(h->nlmsg_type == RTM_NEWROUTE,
+ (struct sockaddr *) &addr);
+ return 0;
}
-/*
- * initialize default port for ISAKMP to send, if no "listen"
- * directive is specified in config file.
- *
- * DO NOT listen to wildcard addresses. if you receive packets to
- * wildcard address, you'll be in trouble (DoS attack possible by
- * broadcast storm).
- */
-int
-autoconf_myaddrsport()
+static int
+netlink_process(struct nlmsghdr *h)
{
- struct myaddrs *p;
- int n;
-
- plog(LLV_DEBUG, LOCATION, NULL,
- "configuring default isakmp port.\n");
-
-#ifdef ENABLE_NATT
- if (natt_enabled_in_rmconf ()) {
- plog(LLV_NOTIFY, LOCATION, NULL, "NAT-T is enabled, autoconfiguring ports\n");
- for (p = lcconf->myaddrs; p; p = p->next) {
- struct myaddrs *new;
- if (! p->udp_encap) {
- new = dupmyaddr(p);
- new->udp_encap = 1;
- }
- }
- }
+ switch (h->nlmsg_type) {
+#ifdef INET6
+ case RTM_NEWADDR:
+ case RTM_DELADDR:
+ return netlink_process_addr(h);
#endif
-
- for (p = lcconf->myaddrs, n = 0; p; p = p->next, n++) {
- set_port (p->addr, p->udp_encap ? lcconf->port_isakmp_natt : lcconf->port_isakmp);
+ case RTM_NEWROUTE:
+ case RTM_DELROUTE:
+ return netlink_process_route(h);
}
- plog(LLV_DEBUG, LOCATION, NULL,
- "%d addrs are configured successfully\n", n);
-
return 0;
}
-/*
- * get a port number to which racoon binded.
- */
-u_short
-getmyaddrsport(local)
- struct sockaddr *local;
+static int
+kernel_receive(ctx, fd)
+ void *ctx;
+ int fd;
{
- struct myaddrs *p, *bestmatch = NULL;
- u_short bestmatch_port = PORT_ISAKMP;
-
- /* get a relative port */
- for (p = lcconf->myaddrs; p; p = p->next) {
- if (!p->addr)
- continue;
- if (cmpsaddrwop(local, p->addr))
- continue;
-
- /* use first matching address regardless of port */
- if (!bestmatch) {
- bestmatch = p;
+ struct sockaddr_nl nladdr;
+ struct iovec iov;
+ struct msghdr msg = {
+ .msg_name = &nladdr,
+ .msg_namelen = sizeof(nladdr),
+ .msg_iov = &iov,
+ .msg_iovlen = 1,
+ };
+ struct nlmsghdr *h;
+ int len, status;
+ char buf[16*1024];
+
+ iov.iov_base = buf;
+ while (1) {
+ iov.iov_len = sizeof(buf);
+ status = recvmsg(fd, &msg, MSG_DONTWAIT);
+ if (status < 0) {
+ if (errno == EINTR)
+ continue;
+ if (errno == EAGAIN)
+ return FALSE;
continue;
}
+ if (status == 0)
+ return FALSE;
- /* matching address with port PORT_ISAKMP */
- if (extract_port(p->addr) == PORT_ISAKMP) {
- bestmatch = p;
- bestmatch_port = PORT_ISAKMP;
+ h = (struct nlmsghdr *) buf;
+ while (NLMSG_OK(h, status)) {
+ netlink_process(h);
+ h = NLMSG_NEXT(h, status);
}
}
- return bestmatch_port;
+ return TRUE;
}
-struct myaddrs *
-newmyaddr()
+static int
+netlink_open_socket()
{
- struct myaddrs *new;
+ int fd;
- new = racoon_calloc(1, sizeof(*new));
- if (new == NULL) {
+ fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+ if (fd < 0) {
plog(LLV_ERROR, LOCATION, NULL,
- "failed to allocate buffer for myaddrs.\n");
- return NULL;
+ "socket(PF_NETLINK) failed: %s",
+ strerror(errno));
+ return -1;
}
+ close_on_exec(fd);
+ if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1)
+ plog(LLV_WARNING, LOCATION, NULL,
+ "failed to put socket in non-blocking mode\n");
- new->next = NULL;
- new->addr = NULL;
-
- return new;
+ return fd;
}
-struct myaddrs *
-dupmyaddr(struct myaddrs *old)
+static int
+kernel_open_socket()
{
- struct myaddrs *new;
+ struct sockaddr_nl nl;
+ int fd;
- new = racoon_calloc(1, sizeof(*new));
- if (new == NULL) {
+ if (netlink_fd < 0) {
+ netlink_fd = netlink_open_socket();
+ if (netlink_fd < 0)
+ return -1;
+ }
+
+ fd = netlink_open_socket();
+ if (fd < 0)
+ return fd;
+
+ /* We monitor IPv4 addresses using RTMGRP_IPV4_ROUTE group
+ * the get the RTN_LOCAL routes which are automatically added
+ * by kernel. This is because:
+ * - Linux kernel has a bug that calling bind() immediately
+ * after IPv4 RTM_NEWADDR event can fail
+ * - if IP is configured in multiple interfaces, we get
+ * RTM_DELADDR for each of them. RTN_LOCAL gets deleted only
+ * after the last IP address is deconfigured.
+ * The latter reason is also why I chose to use route
+ * notifications for IPv6. However, we do need to use RTM_NEWADDR
+ * for the link-local IPv6 addresses to get the interface index
+ * that is needed in bind().
+ */
+ memset(&nl, 0, sizeof(nl));
+ nl.nl_family = AF_NETLINK;
+ nl.nl_groups = RTMGRP_IPV4_ROUTE
+#ifdef INET6
+ | RTMGRP_IPV6_IFADDR | RTMGRP_IPV6_ROUTE
+#endif
+ ;
+ if (bind(fd, (struct sockaddr*) &nl, sizeof(nl)) < 0) {
plog(LLV_ERROR, LOCATION, NULL,
- "failed to allocate buffer for myaddrs.\n");
- return NULL;
+ "bind(PF_NETLINK) failed: %s\n",
+ strerror(errno));
+ close(fd);
+ return -1;
}
+ return fd;
+}
- /* Copy the whole structure and set the differences. */
- memcpy (new, old, sizeof (*new));
- new->addr = dupsaddr (old->addr);
- if (new->addr == NULL) {
+static void
+kernel_sync()
+{
+ int fd = lcconf->rtsock;
+
+ /* refresh addresses */
+ if (!netlink_enumerate(fd, PF_UNSPEC, RTM_GETROUTE)) {
plog(LLV_ERROR, LOCATION, NULL,
- "failed to allocate buffer for myaddrs.\n");
- racoon_free(new);
- return NULL;
+ "unable to enumerate addresses: %s\n",
+ strerror(errno));
}
- new->next = old->next;
- old->next = new;
+ while (kernel_receive(NULL, fd) == TRUE);
- return new;
+#ifdef INET6
+ if (!netlink_enumerate(fd, PF_INET6, RTM_GETADDR)) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "unable to enumerate addresses: %s\n",
+ strerror(errno));
+ }
+ while (kernel_receive(NULL, fd) == TRUE);
+#endif
}
-void
-insmyaddr(new, head)
- struct myaddrs *new;
- struct myaddrs **head;
+#elif defined(USE_ROUTE)
+
+#define ROUNDUP(a) \
+ ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
+
+#define SAROUNDUP(X) ROUNDUP(((struct sockaddr *)(X))->sa_len)
+
+static size_t
+parse_address(start, end, dest)
+ caddr_t start;
+ caddr_t end;
+ struct sockaddr_storage *dest;
{
- new->next = *head;
- *head = new;
+ int len;
+
+ if (start >= end)
+ return 0;
+
+ len = SAROUNDUP(start);
+ if (start + len > end)
+ return end - start;
+
+ if (dest != NULL && len <= sizeof(struct sockaddr_storage))
+ memcpy(dest, start, len);
+
+ return len;
}
-void
-delmyaddr(myaddr)
- struct myaddrs *myaddr;
+static void
+parse_addresses(start, end, flags, addr)
+ caddr_t start;
+ caddr_t end;
+ int flags;
+ struct sockaddr_storage *addr;
{
- if (myaddr->addr)
- racoon_free(myaddr->addr);
- racoon_free(myaddr);
+ memset(addr, 0, sizeof(*addr));
+ if (flags & RTA_DST)
+ start += parse_address(start, end, NULL);
+ if (flags & RTA_GATEWAY)
+ start += parse_address(start, end, NULL);
+ if (flags & RTA_NETMASK)
+ start += parse_address(start, end, NULL);
+ if (flags & RTA_GENMASK)
+ start += parse_address(start, end, NULL);
+ if (flags & RTA_IFP)
+ start += parse_address(start, end, NULL);
+ if (flags & RTA_IFA)
+ start += parse_address(start, end, addr);
+ if (flags & RTA_AUTHOR)
+ start += parse_address(start, end, NULL);
+ if (flags & RTA_BRD)
+ start += parse_address(start, end, NULL);
}
-int
-initmyaddr()
+static void
+kernel_handle_message(msg)
+ caddr_t msg;
{
- /* initialize routing socket */
- lcconf->rtsock = socket(PF_ROUTE, SOCK_RAW, PF_UNSPEC);
- if (lcconf->rtsock < 0) {
- plog(LLV_ERROR, LOCATION, NULL,
- "socket(PF_ROUTE) failed: %s",
- strerror(errno));
- return -1;
+ struct rt_msghdr *rtm = (struct rt_msghdr *) msg;
+ struct ifa_msghdr *ifa = (struct ifa_msghdr *) msg;
+ struct sockaddr_storage addr;
+
+ switch (rtm->rtm_type) {
+ case RTM_NEWADDR:
+ parse_addresses(ifa + 1, msg + ifa->ifam_msglen,
+ ifa->ifam_addrs, &addr);
+ myaddr_open_all_configured((struct sockaddr *) &addr);
+ break;
+ case RTM_DELADDR:
+ parse_addresses(ifa + 1, msg + ifa->ifam_msglen,
+ ifa->ifam_addrs, &addr);
+ myaddr_close_all_open((struct sockaddr *) &addr);
+ break;
+ case RTM_ADD:
+ case RTM_DELETE:
+ case RTM_CHANGE:
+ case RTM_MISS:
+ case RTM_IFINFO:
+#ifdef RTM_OIFINFO
+ case RTM_OIFINFO:
+#endif
+#ifdef RTM_NEWMADDR
+ case RTM_NEWMADDR:
+ case RTM_DELMADDR:
+#endif
+#ifdef RTM_IFANNOUNCE
+ case RTM_IFANNOUNCE:
+#endif
+ break;
+ default:
+ plog(LLV_WARNING, LOCATION, NULL,
+ "unrecognized route message with rtm_type: %d",
+ rtm->rtm_type);
+ break;
}
+}
-#ifdef __linux__
- {
- struct sockaddr_nl nl;
- u_int addr_len;
+static int
+kernel_receive(ctx, fd)
+ void *ctx;
+ int fd;
+{
+ char buf[16*1024];
+ struct rt_msghdr *rtm = (struct rt_msghdr *) buf;
+ int len;
- memset(&nl, 0, sizeof(nl));
- nl.nl_family = AF_NETLINK;
- nl.nl_groups = RTMGRP_IPV4_IFADDR|RTMGRP_LINK|RTMGRP_IPV6_IFADDR;
+ len = read(fd, &buf, sizeof(buf));
+ if (len <= 0) {
+ if (len < 0 && errno != EWOULDBLOCK && errno != EAGAIN)
+ plog(LLV_WARNING, LOCATION, NULL,
+ "routing socket error: %s", strerror(errno));
+ return FALSE;
+ }
- if (bind(lcconf->rtsock, (struct sockaddr*)&nl, sizeof(nl)) < 0) {
- plog(LLV_ERROR, LOCATION, NULL,
- "bind(PF_NETLINK) failed: %s\n",
- strerror(errno));
- return -1;
+ if (rtm->rtm_msglen != len) {
+ plog(LLV_WARNING, LOCATION, NULL,
+ "kernel_receive: rtm->rtm_msglen %d, len %d, type %d\n",
+ rtm->rtm_msglen, len, rtm->rtm_type);
+ return FALSE;
}
- addr_len = sizeof(nl);
- if (getsockname(lcconf->rtsock, (struct sockaddr*)&nl, &addr_len) < 0) {
+
+ kernel_handle_message(buf);
+ return TRUE;
+}
+
+static int
+kernel_open_socket()
+{
+ int fd;
+
+ fd = socket(PF_ROUTE, SOCK_RAW, 0);
+ if (fd < 0) {
plog(LLV_ERROR, LOCATION, NULL,
- "getsockname(PF_NETLINK) failed: %s\n",
- strerror(errno));
+ "socket(PF_ROUTE) failed: %s",
+ strerror(errno));
return -1;
}
- }
-#endif
+ close_on_exec(fd);
+ if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1)
+ plog(LLV_WARNING, LOCATION, NULL,
+ "failed to put socket in non-blocking mode\n");
- if (lcconf->myaddrs == NULL && lcconf->autograbaddr == 1) {
- grab_myaddrs();
+ return fd;
+}
- if (autoconf_myaddrsport() < 0)
- return -1;
+static void
+kernel_sync()
+{
+ caddr_t ref, buf, end;
+ size_t bufsiz;
+ struct if_msghdr *ifm;
+ struct interface *ifp;
+
+#define MIBSIZ 6
+ int mib[MIBSIZ] = {
+ CTL_NET,
+ PF_ROUTE,
+ 0,
+ 0, /* AF_INET & AF_INET6 */
+ NET_RT_IFLIST,
+ 0
+ };
+
+ if (sysctl(mib, MIBSIZ, NULL, &bufsiz, NULL, 0) < 0) {
+ plog(LLV_WARNING, LOCATION, NULL,
+ "sysctl() error: %s", strerror(errno));
+ return;
+ }
+
+ ref = buf = racoon_malloc(bufsiz);
+
+ if (sysctl(mib, MIBSIZ, buf, &bufsiz, NULL, 0) >= 0) {
+ /* Parse both interfaces and addresses. */
+ for (end = buf + bufsiz; buf < end; buf += ifm->ifm_msglen) {
+ ifm = (struct if_msghdr *) buf;
+ kernel_handle_message(buf);
+ }
+ } else {
+ plog(LLV_WARNING, LOCATION, NULL,
+ "sysctl() error: %s", strerror(errno));
}
- return 0;
+ racoon_free(ref);
}
-/* select the socket to be sent */
-/* should implement other method. */
-int
-getsockmyaddr(my)
- struct sockaddr *my;
-{
- struct myaddrs *p, *lastresort = NULL;
-#if defined(INET6) && defined(__linux__)
- struct myaddrs *match_wo_scope_id = NULL;
- int check_wo_scope_id = (my->sa_family == AF_INET6) &&
- IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)my)->sin6_addr);
-#endif
+#else
- for (p = lcconf->myaddrs; p; p = p->next) {
- if (p->addr == NULL)
- continue;
- if (my->sa_family == p->addr->sa_family) {
- lastresort = p;
- } else continue;
- if (sysdep_sa_len(my) == sysdep_sa_len(p->addr)
- && memcmp(my, p->addr, sysdep_sa_len(my)) == 0) {
- break;
- }
-#if defined(INET6) && defined(__linux__)
- if (check_wo_scope_id && IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)p->addr)->sin6_addr) &&
- /* XXX: this depends on sin6_scope_id to be last
- * item in struct sockaddr_in6 */
- memcmp(my, p->addr,
- sysdep_sa_len(my) - sizeof(uint32_t)) == 0) {
- match_wo_scope_id = p;
- }
-#endif
- }
-#if defined(INET6) && defined(__linux__)
- if (!p)
- p = match_wo_scope_id;
-#endif
- if (!p)
- p = lastresort;
- if (!p) {
- plog(LLV_ERROR, LOCATION, NULL,
- "no socket matches address family %d\n",
- my->sa_family);
- return -1;
- }
+#error No supported interface to monitor local addresses.
- return p->sock;
-}
+#endif
diff --git a/src/racoon/grabmyaddr.h b/src/racoon/grabmyaddr.h
index ac74b46..a105d8f 100644
--- a/src/racoon/grabmyaddr.h
+++ b/src/racoon/grabmyaddr.h
@@ -1,4 +1,4 @@
-/* $NetBSD: grabmyaddr.h,v 1.4 2006/09/09 16:22:09 manu Exp $ */
+/* $NetBSD: grabmyaddr.h,v 1.6 2009/04/21 18:38:32 tteras Exp $ */
/* Id: grabmyaddr.h,v 1.5 2004/06/11 16:00:16 ludvigm Exp */
@@ -34,23 +34,15 @@
#ifndef _GRABMYADDR_H
#define _GRABMYADDR_H
-struct myaddrs {
- struct myaddrs *next;
- struct sockaddr *addr;
- int sock;
- int udp_encap;
-};
+extern void myaddr_init_lists __P((void));
+extern int myaddr_init __P((void));
+extern void myaddr_close __P((void));
-extern void clear_myaddr __P((struct myaddrs **));
-extern void grab_myaddrs __P((void));
-extern int update_myaddrs __P((void));
-extern int autoconf_myaddrsport __P((void));
-extern u_short getmyaddrsport __P((struct sockaddr *));
-extern struct myaddrs *newmyaddr __P((void));
-extern struct myaddrs *dupmyaddr __P((struct myaddrs *));
-extern void insmyaddr __P((struct myaddrs *, struct myaddrs **));
-extern void delmyaddr __P((struct myaddrs *));
-extern int initmyaddr __P((void));
-extern int getsockmyaddr __P((struct sockaddr *));
+extern void myaddr_flush __P((void));
+extern int myaddr_listen __P((struct sockaddr *, int));
+extern void myaddr_sync __P((void));
+
+extern int myaddr_getfd __P((struct sockaddr *));
+extern int myaddr_getsport __P((struct sockaddr *));
#endif /* _GRABMYADDR_H */
diff --git a/src/racoon/handler.c b/src/racoon/handler.c
index b643256..a795ee6 100644
--- a/src/racoon/handler.c
+++ b/src/racoon/handler.c
@@ -1,11 +1,11 @@
-/* $NetBSD: handler.c,v 1.9.6.8 2009/04/20 13:25:27 tteras Exp $ */
+/* $NetBSD: handler.c,v 1.39 2011/03/14 17:18:12 tteras Exp $ */
/* Id: handler.c,v 1.28 2006/05/26 12:17:29 manubsd Exp */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -17,7 +17,7 @@
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -64,7 +64,7 @@
#include "evt.h"
#include "isakmp.h"
#ifdef ENABLE_HYBRID
-#include "isakmp_xauth.h"
+#include "isakmp_xauth.h"
#include "isakmp_cfg.h"
#endif
#include "isakmp_inf.h"
@@ -85,10 +85,10 @@ static LIST_HEAD(_ph1tree_, ph1handle) ph1tree;
static LIST_HEAD(_ph2tree_, ph2handle) ph2tree;
static LIST_HEAD(_ctdtree_, contacted) ctdtree;
static LIST_HEAD(_rcptree_, recvdpkt) rcptree;
+static struct sched sc_sweep = SCHED_INITIALIZER();
static void del_recvdpkt __P((struct recvdpkt *));
static void rem_recvdpkt __P((struct recvdpkt *));
-static void sweep_recvdpkt __P((void *));
/*
* functions about management of the isakmp status table
@@ -100,6 +100,41 @@ static void sweep_recvdpkt __P((void *));
extern caddr_t val2str(const char *, size_t);
+/*
+ * Enumerate the Phase 1 tree.
+ * If enum_func() internally return a non-zero value, this specific
+ * error value is returned. 0 is returned if everything went right.
+ *
+ * Note that it is ok for enum_func() to call insph1(). Those inserted
+ * Phase 1 will not interfere with current enumeration process.
+ */
+int
+enumph1(sel, enum_func, enum_arg)
+ struct ph1selector *sel;
+ int (* enum_func)(struct ph1handle *iph1, void *arg);
+ void *enum_arg;
+{
+ struct ph1handle *p;
+ int ret;
+
+ LIST_FOREACH(p, &ph1tree, chain) {
+ if (sel != NULL) {
+ if (sel->local != NULL &&
+ cmpsaddr(sel->local, p->local) > CMPSADDR_WILDPORT_MATCH)
+ continue;
+
+ if (sel->remote != NULL &&
+ cmpsaddr(sel->remote, p->remote) > CMPSADDR_WILDPORT_MATCH)
+ continue;
+ }
+
+ if ((ret = enum_func(p, enum_arg)) != 0)
+ return ret;
+ }
+
+ return 0;
+}
+
struct ph1handle *
getph1byindex(index)
isakmp_index *index;
@@ -107,7 +142,7 @@ getph1byindex(index)
struct ph1handle *p;
LIST_FOREACH(p, &ph1tree, chain) {
- if (p->status == PHASE1ST_EXPIRED)
+ if (p->status >= PHASE1ST_EXPIRED)
continue;
if (memcmp(&p->index, index, sizeof(*index)) == 0)
return p;
@@ -127,7 +162,7 @@ getph1byindex0(index)
struct ph1handle *p;
LIST_FOREACH(p, &ph1tree, chain) {
- if (p->status == PHASE1ST_EXPIRED)
+ if (p->status >= PHASE1ST_EXPIRED)
continue;
if (memcmp(&p->index, index, sizeof(cookie_t)) == 0)
return p;
@@ -142,31 +177,57 @@ getph1byindex0(index)
* with phase 2's destinaion.
*/
struct ph1handle *
-getph1byaddr(local, remote, established)
+getph1(ph1hint, local, remote, flags)
+ struct ph1handle *ph1hint;
struct sockaddr *local, *remote;
- int established;
+ int flags;
{
struct ph1handle *p;
- plog(LLV_DEBUG2, LOCATION, NULL, "getph1byaddr: start\n");
+ plog(LLV_DEBUG2, LOCATION, NULL, "getph1: start\n");
plog(LLV_DEBUG2, LOCATION, NULL, "local: %s\n", saddr2str(local));
plog(LLV_DEBUG2, LOCATION, NULL, "remote: %s\n", saddr2str(remote));
LIST_FOREACH(p, &ph1tree, chain) {
- if (p->status == PHASE1ST_EXPIRED)
+ if (p->status >= PHASE1ST_DYING)
continue;
+
plog(LLV_DEBUG2, LOCATION, NULL, "p->local: %s\n", saddr2str(p->local));
plog(LLV_DEBUG2, LOCATION, NULL, "p->remote: %s\n", saddr2str(p->remote));
- if(established && p->status != PHASE1ST_ESTABLISHED){
- plog(LLV_DEBUG2, LOCATION, NULL, "status %d, skipping\n", p->status);
+ if ((flags & GETPH1_F_ESTABLISHED) &&
+ (p->status != PHASE1ST_ESTABLISHED)) {
+ plog(LLV_DEBUG2, LOCATION, NULL,
+ "status %d, skipping\n", p->status);
continue;
}
- if (CMPSADDR(local, p->local) == 0
- && CMPSADDR(remote, p->remote) == 0){
- plog(LLV_DEBUG2, LOCATION, NULL, "matched\n");
- return p;
+
+ if (local != NULL && cmpsaddr(local, p->local) == CMPSADDR_MISMATCH)
+ continue;
+
+ if (remote != NULL && cmpsaddr(remote, p->remote) == CMPSADDR_MISMATCH)
+ continue;
+
+ if (ph1hint != NULL) {
+ if (ph1hint->id && ph1hint->id->l && p->id && p->id->l &&
+ (ph1hint->id->l != p->id->l ||
+ memcmp(ph1hint->id->v, p->id->v, p->id->l) != 0)) {
+ plog(LLV_DEBUG2, LOCATION, NULL,
+ "local identity does match hint\n");
+ continue;
+ }
+ if (ph1hint->id_p && ph1hint->id_p->l &&
+ p->id_p && p->id_p->l &&
+ (ph1hint->id_p->l != p->id_p->l ||
+ memcmp(ph1hint->id_p->v, p->id_p->v, p->id_p->l) != 0)) {
+ plog(LLV_DEBUG2, LOCATION, NULL,
+ "remote identity does match hint\n");
+ continue;
+ }
}
+
+ plog(LLV_DEBUG2, LOCATION, NULL, "matched\n");
+ return p;
}
plog(LLV_DEBUG2, LOCATION, NULL, "no match\n");
@@ -174,44 +235,78 @@ getph1byaddr(local, remote, established)
return NULL;
}
-struct ph1handle *
-getph1byaddrwop(local, remote)
- struct sockaddr *local, *remote;
+int
+resolveph1rmconf(iph1)
+ struct ph1handle *iph1;
{
- struct ph1handle *p;
+ struct remoteconf *rmconf;
- LIST_FOREACH(p, &ph1tree, chain) {
- if (p->status == PHASE1ST_EXPIRED)
- continue;
- if (cmpsaddrwop(local, p->local) == 0
- && cmpsaddrwop(remote, p->remote) == 0)
- return p;
+ /* INITIATOR is always expected to know the exact rmconf. */
+ if (iph1->side == INITIATOR)
+ return 0;
+
+ rmconf = getrmconf_by_ph1(iph1);
+ if (rmconf == NULL)
+ return -1;
+ if (rmconf == RMCONF_ERR_MULTIPLE)
+ return 1;
+
+ if (iph1->rmconf != NULL) {
+ if (rmconf != iph1->rmconf) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "unexpected rmconf switch; killing ph1\n");
+ return -1;
+ }
+ } else {
+ iph1->rmconf = rmconf;
}
- return NULL;
+ return 0;
}
+
/*
- * search for isakmpsa handler by remote address.
- * don't use port number to search because this function search
- * with phase 2's destinaion.
+ * move phase2s from old_iph1 to new_iph1
*/
-struct ph1handle *
-getph1bydstaddrwop(remote)
- struct sockaddr *remote;
+void
+migrate_ph12(old_iph1, new_iph1)
+ struct ph1handle *old_iph1, *new_iph1;
+{
+ struct ph2handle *p, *next;
+
+ /* Relocate phase2s to better phase1s or request a new phase1. */
+ for (p = LIST_FIRST(&old_iph1->ph2tree); p; p = next) {
+ next = LIST_NEXT(p, ph1bind);
+
+ if (p->status != PHASE2ST_ESTABLISHED)
+ continue;
+
+ unbindph12(p);
+ bindph12(new_iph1, p);
+ }
+}
+
+/*
+ * the iph1 is new, migrate all phase2s that belong to a dying or dead ph1
+ */
+void migrate_dying_ph12(iph1)
+ struct ph1handle *iph1;
{
struct ph1handle *p;
LIST_FOREACH(p, &ph1tree, chain) {
- if (p->status == PHASE1ST_EXPIRED)
+ if (p == iph1)
+ continue;
+ if (p->status < PHASE1ST_DYING)
continue;
- if (cmpsaddrwop(remote, p->remote) == 0)
- return p;
- }
- return NULL;
+ if (cmpsaddr(iph1->local, p->local) == CMPSADDR_MATCH
+ && cmpsaddr(iph1->remote, p->remote) == CMPSADDR_MATCH)
+ migrate_ph12(p, iph1);
+ }
}
+
/*
* dump isakmp-sa
*/
@@ -268,11 +363,10 @@ newph1()
#ifdef ENABLE_DPD
iph1->dpd_support = 0;
- iph1->dpd_lastack = 0;
iph1->dpd_seq = 0;
iph1->dpd_fails = 0;
- iph1->dpd_r_u = NULL;
#endif
+ evt_list_init(&iph1->evt_listeners);
return iph1;
}
@@ -289,8 +383,7 @@ delph1(iph1)
/* SA down shell script hook */
script_hook(iph1, SCRIPT_PHASE1_DOWN);
-
- EVT_PUSH(iph1->local, iph1->remote, EVTT_PHASE1_DOWN, NULL);
+ evt_list_cleanup(&iph1->evt_listeners);
#ifdef ENABLE_NATT
if (iph1->natt_flags & NAT_KA_QUEUED)
@@ -308,8 +401,10 @@ delph1(iph1)
#endif
#ifdef ENABLE_DPD
- SCHED_KILL(iph1->dpd_r_u);
+ sched_cancel(&iph1->dpd_r_u);
#endif
+ sched_cancel(&iph1->sce);
+ sched_cancel(&iph1->scr);
if (iph1->remote) {
racoon_free(iph1->remote);
@@ -325,13 +420,7 @@ delph1(iph1)
}
VPTRINIT(iph1->authstr);
-
- sched_scrub_param(iph1);
- iph1->sce = NULL;
- iph1->scr = NULL;
-
VPTRINIT(iph1->sendbuf);
-
VPTRINIT(iph1->dhpriv);
VPTRINIT(iph1->dhpub);
VPTRINIT(iph1->dhpub_p);
@@ -346,14 +435,10 @@ delph1(iph1)
VPTRINIT(iph1->hash);
VPTRINIT(iph1->sig);
VPTRINIT(iph1->sig_p);
- oakley_delcert(iph1->cert);
- iph1->cert = NULL;
- oakley_delcert(iph1->cert_p);
- iph1->cert_p = NULL;
- oakley_delcert(iph1->crl_p);
- iph1->crl_p = NULL;
- oakley_delcert(iph1->cr_p);
- iph1->cr_p = NULL;
+ VPTRINIT(iph1->cert);
+ VPTRINIT(iph1->cert_p);
+ VPTRINIT(iph1->crl_p);
+ VPTRINIT(iph1->cr_p);
VPTRINIT(iph1->id);
VPTRINIT(iph1->id_p);
@@ -415,7 +500,7 @@ flushph1()
next = LIST_NEXT(p, chain);
/* send delete information */
- if (p->status == PHASE1ST_ESTABLISHED)
+ if (p->status >= PHASE1ST_ESTABLISHED)
isakmp_info_send_d1(p);
remph1(p);
@@ -429,26 +514,52 @@ initph1tree()
LIST_INIT(&ph1tree);
}
+int
+ph1_rekey_enabled(iph1)
+ struct ph1handle *iph1;
+{
+ if (iph1->rmconf == NULL)
+ return 0;
+ if (iph1->rmconf->rekey == REKEY_FORCE)
+ return 1;
+#ifdef ENABLE_DPD
+ if (iph1->rmconf->rekey == REKEY_ON && iph1->dpd_support &&
+ iph1->rmconf->dpd_interval)
+ return 1;
+#endif
+ return 0;
+}
+
/* %%% management phase 2 handler */
-/*
- * search ph2handle with policy id.
- */
-struct ph2handle *
-getph2byspid(spid)
- u_int32_t spid;
+
+int
+enumph2(sel, enum_func, enum_arg)
+ struct ph2selector *sel;
+ int (*enum_func)(struct ph2handle *ph2, void *arg);
+ void *enum_arg;
{
struct ph2handle *p;
+ int ret;
LIST_FOREACH(p, &ph2tree, chain) {
- /*
- * there are ph2handle independent on policy
- * such like informational exchange.
- */
- if (p->spid == spid)
- return p;
+ if (sel != NULL) {
+ if (sel->spid != 0 && sel->spid != p->spid)
+ continue;
+
+ if (sel->src != NULL &&
+ cmpsaddr(sel->src, p->src) != CMPSADDR_MATCH)
+ continue;
+
+ if (sel->dst != NULL &&
+ cmpsaddr(sel->dst, p->dst) != CMPSADDR_MATCH)
+ continue;
+ }
+
+ if ((ret = enum_func(p, enum_arg)) != 0)
+ return ret;
}
- return NULL;
+ return 0;
}
/*
@@ -478,7 +589,7 @@ getph2bymsgid(iph1, msgid)
{
struct ph2handle *p;
- LIST_FOREACH(p, &ph2tree, chain) {
+ LIST_FOREACH(p, &iph1->ph2tree, ph1bind) {
if (p->msgid == msgid && p->ph1 == iph1)
return p;
}
@@ -486,6 +597,15 @@ getph2bymsgid(iph1, msgid)
return NULL;
}
+/* Note that src and dst are not the selectors of the SP
+ * but the source and destination addresses used for
+ * for SA negotiation (best example is tunnel mode SA
+ * where src and dst are the endpoints). There is at most
+ * a unique match because racoon does not support bundles
+ * which makes that there is at most a single established
+ * SA for a given spid. One could say that src and dst
+ * are in fact useless ...
+ */
struct ph2handle *
getph2byid(src, dst, spid)
struct sockaddr *src, *dst;
@@ -495,8 +615,8 @@ getph2byid(src, dst, spid)
LIST_FOREACH(p, &ph2tree, chain) {
if (spid == p->spid &&
- CMPSADDR(src, p->src) == 0 &&
- CMPSADDR(dst, p->dst) == 0){
+ cmpsaddr(src, p->src) <= CMPSADDR_WILDPORT_MATCH &&
+ cmpsaddr(dst, p->dst) <= CMPSADDR_WILDPORT_MATCH){
/* Sanity check to detect zombie handlers
* XXX Sould be done "somewhere" more interesting,
* because we have lots of getph2byxxxx(), but this one
@@ -504,7 +624,7 @@ getph2byid(src, dst, spid)
*/
if(p->status < PHASE2ST_ESTABLISHED &&
p->retry_counter == 0
- && p->sce == NULL && p->scr == NULL){
+ && p->sce.func == NULL && p->scr.func == NULL) {
plog(LLV_DEBUG, LOCATION, NULL,
"Zombie ph2 found, expiring it\n");
isakmp_ph2expire(p);
@@ -523,8 +643,8 @@ getph2bysaddr(src, dst)
struct ph2handle *p;
LIST_FOREACH(p, &ph2tree, chain) {
- if (cmpsaddrstrict(src, p->src) == 0 &&
- cmpsaddrstrict(dst, p->dst) == 0)
+ if (cmpsaddr(src, p->src) <= CMPSADDR_WILDPORT_MATCH &&
+ cmpsaddr(dst, p->dst) <= CMPSADDR_WILDPORT_MATCH)
return p;
}
@@ -582,6 +702,7 @@ newph2()
return NULL;
iph2->status = PHASE1ST_SPAWN;
+ evt_list_init(&iph2->evt_listeners);
return iph2;
}
@@ -595,9 +716,11 @@ void
initph2(iph2)
struct ph2handle *iph2;
{
- sched_scrub_param(iph2);
- iph2->sce = NULL;
- iph2->scr = NULL;
+ evt_list_cleanup(&iph2->evt_listeners);
+ unbindph12(iph2);
+
+ sched_cancel(&iph2->sce);
+ sched_cancel(&iph2->scr);
VPTRINIT(iph2->sendbuf);
VPTRINIT(iph2->msg1);
@@ -642,6 +765,17 @@ initph2(iph2)
oakley_delivm(iph2->ivm);
iph2->ivm = NULL;
}
+
+#ifdef ENABLE_NATT
+ if (iph2->natoa_src) {
+ racoon_free(iph2->natoa_src);
+ iph2->natoa_src = NULL;
+ }
+ if (iph2->natoa_dst) {
+ racoon_free(iph2->natoa_dst);
+ iph2->natoa_dst = NULL;
+ }
+#endif
}
/*
@@ -661,14 +795,24 @@ delph2(iph2)
racoon_free(iph2->dst);
iph2->dst = NULL;
}
- if (iph2->src_id) {
- racoon_free(iph2->src_id);
- iph2->src_id = NULL;
+ if (iph2->sa_src) {
+ racoon_free(iph2->sa_src);
+ iph2->sa_src = NULL;
+ }
+ if (iph2->sa_dst) {
+ racoon_free(iph2->sa_dst);
+ iph2->sa_dst = NULL;
+ }
+#ifdef ENABLE_NATT
+ if (iph2->natoa_src) {
+ racoon_free(iph2->natoa_src);
+ iph2->natoa_src = NULL;
}
- if (iph2->dst_id) {
- racoon_free(iph2->dst_id);
- iph2->dst_id = NULL;
+ if (iph2->natoa_dst) {
+ racoon_free(iph2->natoa_dst);
+ iph2->natoa_dst = NULL;
}
+#endif
if (iph2->proposal) {
flushsaprop(iph2->proposal);
@@ -694,6 +838,7 @@ void
remph2(iph2)
struct ph2handle *iph2;
{
+ unbindph12(iph2);
LIST_REMOVE(iph2, chain);
}
@@ -725,7 +870,6 @@ flushph2()
}
delete_spd(p, 0);
- unbindph12(p);
remph2(p);
delph2(p);
}
@@ -763,7 +907,6 @@ deleteallph2(src, dst, proto_id)
}
continue;
zap_it:
- unbindph12(iph2);
remph2(iph2);
delph2(iph2);
}
@@ -775,7 +918,10 @@ bindph12(iph1, iph2)
struct ph1handle *iph1;
struct ph2handle *iph2;
{
+ unbindph12(iph2);
+
iph2->ph1 = iph1;
+ iph1->ph2cnt++;
LIST_INSERT_HEAD(&iph1->ph2tree, iph2, ph1bind);
}
@@ -784,8 +930,9 @@ unbindph12(iph2)
struct ph2handle *iph2;
{
if (iph2->ph1 != NULL) {
- iph2->ph1 = NULL;
LIST_REMOVE(iph2, ph1bind);
+ iph2->ph1->ph2cnt--;
+ iph2->ph1 = NULL;
}
}
@@ -800,7 +947,7 @@ getcontacted(remote)
struct contacted *p;
LIST_FOREACH(p, &ctdtree, chain) {
- if (cmpsaddrstrict(remote, p->remote) == 0)
+ if (cmpsaddr(remote, p->remote) <= CMPSADDR_WILDPORT_MATCH)
return p;
}
@@ -835,6 +982,22 @@ inscontacted(remote)
}
void
+remcontacted(remote)
+ struct sockaddr *remote;
+{
+ struct contacted *p;
+
+ LIST_FOREACH(p, &ctdtree, chain) {
+ if (cmpsaddr(remote, p->remote) <= CMPSADDR_WILDPORT_MATCH) {
+ LIST_REMOVE(p, chain);
+ racoon_free(p->remote);
+ racoon_free(p);
+ break;
+ }
+ }
+}
+
+void
initctdtree()
{
LIST_INIT(&ctdtree);
@@ -856,12 +1019,9 @@ check_recvdpkt(remote, local, rbuf)
{
vchar_t *hash;
struct recvdpkt *r;
- time_t t;
+ struct timeval now, diff;
int len, s;
- /* set current time */
- t = time(NULL);
-
hash = eay_md5_one(rbuf);
if (!hash) {
plog(LLV_ERROR, LOCATION, NULL,
@@ -882,7 +1042,7 @@ check_recvdpkt(remote, local, rbuf)
/*
* the packet was processed before, but the remote address mismatches.
*/
- if (cmpsaddrstrict(remote, r->remote) != 0)
+ if (cmpsaddr(remote, r->remote) != CMPSADDR_MATCH)
return 2;
/*
@@ -891,7 +1051,9 @@ check_recvdpkt(remote, local, rbuf)
*/
/* check the previous time to send */
- if (t - r->time_send < 1) {
+ sched_get_monotonic_time(&now);
+ timersub(&now, &r->time_send, &diff);
+ if (diff.tv_sec == 0) {
plog(LLV_WARNING, LOCATION, NULL,
"the packet retransmitted in a short time from %s\n",
saddr2str(remote));
@@ -899,7 +1061,7 @@ check_recvdpkt(remote, local, rbuf)
}
/* select the socket to be sent */
- s = getsockmyaddr(r->local);
+ s = myaddr_getfd(r->local);
if (s == -1)
return -1;
@@ -920,7 +1082,7 @@ check_recvdpkt(remote, local, rbuf)
"deleted the retransmission packet to %s.\n",
saddr2str(remote));
} else
- r->time_send = t;
+ r->time_send = now;
return 1;
}
@@ -977,8 +1139,7 @@ add_recvdpkt(remote, local, sbuf, rbuf)
}
new->retry_counter = lcconf->retry_counter;
- new->time_send = 0;
- new->created = time(NULL);
+ sched_get_monotonic_time(&new->time_send);
LIST_INSERT_HEAD(&rcptree, new, chain);
@@ -1007,29 +1168,30 @@ rem_recvdpkt(r)
LIST_REMOVE(r, chain);
}
-void
+static void
sweep_recvdpkt(dummy)
- void *dummy;
+ struct sched *dummy;
{
struct recvdpkt *r, *next;
- time_t t, lt;
+ struct timeval now, diff, sweep;
- /* set current time */
- t = time(NULL);
+ sched_get_monotonic_time(&now);
- /* set the lifetime of the retransmission */
- lt = lcconf->retry_counter * lcconf->retry_interval;
+ /* calculate sweep time; delete entries older than this */
+ diff.tv_sec = lcconf->retry_counter * lcconf->retry_interval;
+ diff.tv_usec = 0;
+ timersub(&now, &diff, &sweep);
for (r = LIST_FIRST(&rcptree); r; r = next) {
next = LIST_NEXT(r, chain);
- if (t - r->created > lt) {
+ if (timercmp(&r->time_send, &sweep, <)) {
rem_recvdpkt(r);
del_recvdpkt(r);
}
}
- sched_new(lt, sweep_recvdpkt, NULL);
+ sched_schedule(&sc_sweep, diff.tv_sec, sweep_recvdpkt);
}
void
@@ -1039,11 +1201,11 @@ init_recvdpkt()
LIST_INIT(&rcptree);
- sched_new(lt, sweep_recvdpkt, NULL);
+ sched_schedule(&sc_sweep, lt, sweep_recvdpkt);
}
#ifdef ENABLE_HYBRID
-/*
+/*
* Retruns 0 if the address was obtained by ISAKMP mode config, 1 otherwise
* This should be in isakmp_cfg.c but ph1tree being private, it must be there
*/
@@ -1070,7 +1232,7 @@ exclude_cfg_addr(addr)
-/*
+/*
* Reload conf code
*/
static int revalidate_ph2(struct ph2handle *iph2){
@@ -1080,19 +1242,19 @@ static int revalidate_ph2(struct ph2handle *iph2){
struct saprop *approval;
struct ph1handle *iph1;
- /*
+ /*
* Get the new sainfo using values of the old one
*/
if (iph2->sainfo != NULL) {
- iph2->sainfo = getsainfo(iph2->sainfo->idsrc,
+ iph2->sainfo = getsainfo(iph2->sainfo->idsrc,
iph2->sainfo->iddst, iph2->sainfo->id_i,
- iph2->sainfo->remoteid);
+ NULL, iph2->sainfo->remoteid);
}
approval = iph2->approval;
sainfo = iph2->sainfo;
if (sainfo == NULL) {
- /*
+ /*
* Sainfo has been removed
*/
plog(LLV_DEBUG, LOCATION, NULL,
@@ -1107,7 +1269,7 @@ static int revalidate_ph2(struct ph2handle *iph2){
plog(LLV_DEBUG, LOCATION, NULL,
"No approval found !\n");
return 0;
- }
+ }
/*
* Don't care about proposals, should we do something ?
@@ -1206,7 +1368,7 @@ static int revalidate_ph2(struct ph2handle *iph2){
}
found = 0;
- for (alg = sainfo->algs[algclass_ipsec_enc];
+ for (alg = sainfo->algs[algclass_ipsec_enc];
(found == 0 && alg != NULL); alg = alg->next) {
plog(LLV_DEBUG, LOCATION, NULL,
"Reload: next ph2 enc alg...\n");
@@ -1239,7 +1401,7 @@ static int revalidate_ph2(struct ph2handle *iph2){
break;
default:
- plog(LLV_ERROR, LOCATION, NULL,
+ plog(LLV_ERROR, LOCATION, NULL,
"unexpected check_level\n");
continue;
break;
@@ -1263,7 +1425,7 @@ static int revalidate_ph2(struct ph2handle *iph2){
}
-static void
+static void
remove_ph2(struct ph2handle *iph2)
{
u_int32_t spis[2];
@@ -1289,7 +1451,6 @@ remove_ph2(struct ph2handle *iph2)
purge_ipsec_spi(iph2->dst, iph2->approval->head->proto_id,
spis, 2);
}else{
- unbindph12(iph2);
remph2(iph2);
delph2(iph2);
}
@@ -1304,197 +1465,41 @@ static void remove_ph1(struct ph1handle *iph1){
plog(LLV_DEBUG, LOCATION, NULL,
"Removing PH1...\n");
- if (iph1->status == PHASE1ST_ESTABLISHED){
+ if (iph1->status == PHASE1ST_ESTABLISHED ||
+ iph1->status == PHASE1ST_DYING) {
for (iph2 = LIST_FIRST(&iph1->ph2tree); iph2; iph2 = iph2_next) {
- iph2_next = LIST_NEXT(iph2, chain);
+ iph2_next = LIST_NEXT(iph2, ph1bind);
remove_ph2(iph2);
}
isakmp_info_send_d1(iph1);
}
iph1->status = PHASE1ST_EXPIRED;
- iph1->sce = sched_new(1, isakmp_ph1delete_stub, iph1);
+ /* directly call isakmp_ph1delete to avoid as possible a race
+ * condition where we'll try to access iph1->rmconf after it has
+ * freed
+ */
+ isakmp_ph1delete(iph1);
}
-static int revalidate_ph1tree_rmconf(void){
+static int revalidate_ph1tree_rmconf(void)
+{
struct ph1handle *p, *next;
- struct remoteconf *newrmconf;
+ struct remoteconf *rmconf;
for (p = LIST_FIRST(&ph1tree); p; p = next) {
next = LIST_NEXT(p, chain);
- if (p->status == PHASE1ST_EXPIRED)
+ if (p->status >= PHASE1ST_EXPIRED)
continue;
-
- newrmconf=getrmconf(p->remote);
- if(newrmconf == NULL){
- p->rmconf = NULL;
- remove_ph1(p);
- }else{
- /* Do not free old rmconf, it is just a pointer to an entry in rmtree
- */
- p->rmconf=newrmconf;
- if(p->approval != NULL){
- struct isakmpsa *tmpsa;
-
- tmpsa=dupisakmpsa(p->approval);
- if(tmpsa != NULL){
- delisakmpsa(p->approval);
- p->approval=tmpsa;
- p->approval->rmconf=newrmconf;
- }
- }
- }
- }
-
- return 1;
-}
-
-
-/* rmconf is already updated here
- */
-static int revalidate_ph1(struct ph1handle *iph1){
- struct isakmpsa *p, *approval;
- struct etypes *e;
-
- if(iph1 == NULL ||
- iph1->approval == NULL ||
- iph1->rmconf == NULL)
- return 0;
-
- approval=iph1->approval;
-
- for (e = iph1->rmconf->etypes; e != NULL; e = e->next){
- if (iph1->etype == e->type)
- break;
- }
-
- if (e == NULL){
- plog(LLV_DEBUG, LOCATION, NULL,
- "Reload: Exchange type mismatch\n");
- return 0;
- }
-
- if (iph1->etype == ISAKMP_ETYPE_AGG &&
- approval->dh_group != iph1->rmconf->dh_group){
- plog(LLV_DEBUG, LOCATION, NULL,
- "Reload: DH mismatch\n");
- return 0;
- }
-
- for (p=iph1->rmconf->proposal; p != NULL; p=p->next){
- plog(LLV_DEBUG, LOCATION, NULL,
- "Reload: Trying next proposal...\n");
-
- if(approval->authmethod != p->authmethod){
- plog(LLV_DEBUG, LOCATION, NULL,
- "Reload: Authmethod mismatch\n");
+ if (p->rmconf == NULL)
continue;
- }
- if(approval->enctype != p->enctype){
- plog(LLV_DEBUG, LOCATION, NULL,
- "Reload: enctype mismatch\n");
- continue;
- }
-
- switch (iph1->rmconf->pcheck_level) {
- case PROP_CHECK_OBEY:
- plog(LLV_DEBUG, LOCATION, NULL,
- "Reload: OBEY pcheck level, ok...\n");
- return 1;
- break;
-
- case PROP_CHECK_CLAIM:
- /* FALLTHROUGH */
- case PROP_CHECK_STRICT:
- if (approval->encklen < p->encklen) {
- plog(LLV_DEBUG, LOCATION, NULL,
- "Reload: encklen mismatch\n");
- continue;
- }
-
- if (approval->lifetime > p->lifetime) {
- plog(LLV_DEBUG, LOCATION, NULL,
- "Reload: lifetime mismatch\n");
- continue;
- }
-
-#if 0
- /* Lifebyte is deprecated, just ignore it
- */
- if (approval->lifebyte > p->lifebyte) {
- plog(LLV_DEBUG, LOCATION, NULL,
- "Reload: lifebyte mismatch\n");
- continue;
- }
-#endif
- break;
-
- case PROP_CHECK_EXACT:
- if (approval->encklen != p->encklen) {
- plog(LLV_DEBUG, LOCATION, NULL,
- "Reload: encklen mismatch\n");
- continue;
- }
-
- if (approval->lifetime != p->lifetime) {
- plog(LLV_DEBUG, LOCATION, NULL,
- "Reload: lifetime mismatch\n");
- continue;
- }
-
-#if 0
- /* Lifebyte is deprecated, just ignore it
- */
- if (approval->lifebyte != p->lifebyte) {
- plog(LLV_DEBUG, LOCATION, NULL,
- "Reload: lifebyte mismatch\n");
- continue;
- }
-#endif
- break;
-
- default:
- plog(LLV_ERROR, LOCATION, NULL,
- "unexpected check_level\n");
- continue;
- break;
- }
-
- if (approval->hashtype != p->hashtype) {
- plog(LLV_DEBUG, LOCATION, NULL,
- "Reload: hashtype mismatch\n");
- continue;
- }
-
- if (iph1->etype != ISAKMP_ETYPE_AGG &&
- approval->dh_group != p->dh_group) {
- plog(LLV_DEBUG, LOCATION, NULL,
- "Reload: dhgroup mismatch\n");
- continue;
- }
-
- plog(LLV_DEBUG, LOCATION, NULL, "Reload: Conf ok\n");
- return 1;
- }
-
- plog(LLV_DEBUG, LOCATION, NULL, "Reload: No valid conf found\n");
- return 0;
-}
-
-
-static int revalidate_ph1tree(void){
- struct ph1handle *p, *next;
-
- for (p = LIST_FIRST(&ph1tree); p; p = next) {
- next = LIST_NEXT(p, chain);
-
- if (p->status == PHASE1ST_EXPIRED)
- continue;
-
- if(!revalidate_ph1(p))
+ rmconf = getrmconf_by_ph1(p);
+ if (rmconf == NULL || rmconf == RMCONF_ERR_MULTIPLE)
remove_ph1(p);
+ else
+ p->rmconf = rmconf;
}
return 1;
@@ -1519,14 +1524,12 @@ static int revalidate_ph2tree(void){
return 1;
}
-int
+int
revalidate_ph12(void)
{
revalidate_ph1tree_rmconf();
-
revalidate_ph2tree();
- revalidate_ph1tree();
return 1;
}
@@ -1559,7 +1562,10 @@ purgeph1bylogin(login)
if (p->mode_cfg == NULL)
continue;
if (strncmp(p->mode_cfg->login, login, LOGINLEN) == 0) {
- if (p->status == PHASE1ST_ESTABLISHED)
+ if (p->status >= PHASE1ST_EXPIRED)
+ continue;
+
+ if (p->status >= PHASE1ST_ESTABLISHED)
isakmp_info_send_d1(p);
purge_remote(p);
found++;
diff --git a/src/racoon/handler.h b/src/racoon/handler.h
index a52dc6c..45d596e 100644
--- a/src/racoon/handler.h
+++ b/src/racoon/handler.h
@@ -1,11 +1,11 @@
-/* $NetBSD: handler.h,v 1.9.6.1 2008/01/11 14:12:01 vanhu Exp $ */
+/* $NetBSD: handler.h,v 1.25 2010/11/17 10:40:41 tteras Exp $ */
/* Id: handler.h,v 1.19 2006/02/25 08:25:12 manubsd Exp */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -17,7 +17,7 @@
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -41,6 +41,8 @@
#include "isakmp_var.h"
#include "oakley.h"
+#include "schedule.h"
+#include "evt.h"
/* Phase 1 handler */
/*
@@ -93,8 +95,9 @@
#define PHASE1ST_MSG3SENT 7
#define PHASE1ST_MSG4RECEIVED 8
#define PHASE1ST_ESTABLISHED 9
-#define PHASE1ST_EXPIRED 10
-#define PHASE1ST_MAX 11
+#define PHASE1ST_DYING 10
+#define PHASE1ST_EXPIRED 11
+#define PHASE1ST_MAX 12
/* About address semantics in each case.
* initiator(addr=I) responder(addr=R)
@@ -131,6 +134,7 @@ struct ph1handle {
u_int8_t flags; /* Flags */
u_int32_t msgid; /* message id */
+ u_int32_t vendorid_mask; /* bitmask of received supported vendor ids*/
#ifdef ENABLE_NATT
struct ph1natt_options *natt_options; /* Selected NAT-T IKE version */
u_int32_t natt_flags; /* NAT-T related flags */
@@ -140,9 +144,9 @@ struct ph1handle {
struct isakmp_frag_item *frag_chain; /* Received fragments */
#endif
- struct sched *sce; /* schedule for expire */
+ struct sched sce; /* schedule for expire */
- struct sched *scr; /* schedule for resend */
+ struct sched scr; /* schedule for resend */
int retry_counter; /* for resend. */
vchar_t *sendbuf; /* buffer for re-sending */
@@ -160,10 +164,10 @@ struct ph1handle {
vchar_t *hash; /* HASH minus general header */
vchar_t *sig; /* SIG minus general header */
vchar_t *sig_p; /* peer's SIG minus general header */
- cert_t *cert; /* CERT minus general header */
- cert_t *cert_p; /* peer's CERT minus general header */
- cert_t *crl_p; /* peer's CRL minus general header */
- cert_t *cr_p; /* peer's CR not including general */
+ vchar_t *cert; /* CERT minus general header */
+ vchar_t *cert_p; /* peer's CERT minus general header */
+ vchar_t *crl_p; /* peer's CRL minus general header */
+ vchar_t *cr_p; /* peer's CR not including general */
RSA *rsa; /* my RSA key */
RSA *rsa_p; /* peer's RSA key */
struct genlist *rsa_candidates; /* possible candidates for peer's RSA key */
@@ -190,6 +194,7 @@ struct ph1handle {
struct isakmp_pl_hash *pl_hash; /* pointer to hash payload */
time_t created; /* timestamp for establish */
+ int initial_contact_received; /* set if initial contact received */
#ifdef ENABLE_STATS
struct timeval start;
struct timeval end;
@@ -197,10 +202,10 @@ struct ph1handle {
#ifdef ENABLE_DPD
int dpd_support; /* Does remote supports DPD ? */
- time_t dpd_lastack; /* Last ack received */
- u_int16_t dpd_seq; /* DPD seq number to receive */
+ u_int32_t dpd_last_ack;
+ u_int32_t dpd_seq; /* DPD seq number to receive */
u_int8_t dpd_fails; /* number of failures */
- struct sched *dpd_r_u;
+ struct sched dpd_r_u;
#endif
u_int32_t msgid2; /* msgid counter for Phase 2 */
@@ -210,8 +215,14 @@ struct ph1handle {
LIST_ENTRY(ph1handle) chain;
#ifdef ENABLE_HYBRID
struct isakmp_cfg_state *mode_cfg; /* ISAKMP mode config state */
-#endif
+#endif
+ EVT_LISTENER_LIST(evt_listeners);
+};
+/* For limiting enumeration of ph1 tree */
+struct ph1selector {
+ struct sockaddr *local;
+ struct sockaddr *remote;
};
/* Phase 2 handler */
@@ -244,23 +255,44 @@ struct ph1handle {
#define PHASE2ST_MAX 11
struct ph2handle {
- struct sockaddr *src; /* my address of SA. */
- struct sockaddr *dst; /* peer's address of SA. */
+ /* source and destination addresses used for IKE exchange. Might
+ * differ from source and destination of SA. On the initiator,
+ * they are tweaked if a hint is available in the SPD (set by
+ * MIGRATE for instance). Otherwise they are the source and
+ * destination of SA for transport mode and the tunnel endpoints
+ * for tunnel mode */
+ struct sockaddr *src;
+ struct sockaddr *dst;
+
+ /* source and destination addresses of the SA in the case addresses
+ * used for IKE exchanges (src and dst) do differ. On the initiator,
+ * they are set (if needed) in pk_recvacquire(). On the responder,
+ * they are _derived_ from the local and remote parameters of the
+ * SP, if available. */
+ struct sockaddr *sa_src;
+ struct sockaddr *sa_dst;
+
+ /* Store our Phase 2 ID and the peer ID (ID minus general header).
+ * On the initiator, they are set during ACQUIRE processing.
+ * On the responder, they are set from the content of ID payload
+ * in quick_r1recv(). Then, if they are of type address or
+ * tunnel, they are compared to sainfo selectors.
+ */
+ vchar_t *id; /* ID minus gen header */
+ vchar_t *id_p; /* peer's ID minus general header */
- /*
- * copy ip address from ID payloads when ID type is ip address.
- * In other case, they must be null.
- */
- struct sockaddr *src_id;
- struct sockaddr *dst_id;
+#ifdef ENABLE_NATT
+ struct sockaddr *natoa_src; /* peer's view of my address */
+ struct sockaddr *natoa_dst; /* peer's view of his address */
+#endif
u_int32_t spid; /* policy id by kernel */
int status; /* ipsec sa status */
u_int8_t side; /* INITIATOR or RESPONDER */
- struct sched *sce; /* schedule for expire */
- struct sched *scr; /* schedule for resend */
+ struct sched sce; /* schedule for expire */
+ struct sched scr; /* schedule for resend */
int retry_counter; /* for resend. */
vchar_t *sendbuf; /* buffer for re-sending */
vchar_t *msg1; /* buffer for re-sending */
@@ -288,6 +320,8 @@ struct ph2handle {
struct sainfo *sainfo; /* place holder of sainfo */
struct saprop *proposal; /* SA(s) proposal. */
struct saprop *approval; /* SA(s) approved. */
+ u_int32_t lifetime_secs; /* responder lifetime (seconds) */
+ u_int32_t lifetime_kb; /* responder lifetime (kbytes) */
caddr_t spidx_gen; /* policy from peer's proposal */
struct dhgroup *pfsgrp; /* DH; prime number */
@@ -295,8 +329,6 @@ struct ph2handle {
vchar_t *dhpub; /* DH; public value */
vchar_t *dhpub_p; /* DH; partner's public value */
vchar_t *dhgxy; /* DH; shared secret */
- vchar_t *id; /* ID minus gen header */
- vchar_t *id_p; /* peer's ID minus general header */
vchar_t *nonce; /* nonce value in phase 2 */
vchar_t *nonce_p; /* partner's nonce value in phase 2 */
@@ -320,6 +352,14 @@ struct ph2handle {
LIST_ENTRY(ph2handle) chain;
LIST_ENTRY(ph2handle) ph1bind; /* chain to ph1handle */
+ EVT_LISTENER_LIST(evt_listeners);
+};
+
+/* For limiting enumeration of ph2 tree */
+struct ph2selector {
+ u_int32_t spid;
+ struct sockaddr *src;
+ struct sockaddr *dst;
};
/*
@@ -339,10 +379,7 @@ struct recvdpkt {
vchar_t *hash; /* hash of the received packet */
vchar_t *sendbuf; /* buffer for the response */
int retry_counter; /* how many times to send */
- time_t time_send; /* timestamp to send a packet */
- time_t created; /* timestamp to create a queue */
-
- struct sched *scr; /* schedule for resend, may not used */
+ struct timeval time_send; /* timestamp of previous send */
LIST_ENTRY(recvdpkt) chain;
};
@@ -413,7 +450,7 @@ struct ph1dump {
struct sockaddr_storage remote;
struct sockaddr_storage local;
u_int8_t version;
- u_int8_t etype;
+ u_int8_t etype;
time_t created;
int ph2cnt;
};
@@ -425,25 +462,42 @@ struct policyindex;
extern struct ph1handle *getph1byindex __P((isakmp_index *));
extern struct ph1handle *getph1byindex0 __P((isakmp_index *));
-extern struct ph1handle *getph1byaddr __P((struct sockaddr *,
- struct sockaddr *, int));
-extern struct ph1handle *getph1byaddrwop __P((struct sockaddr *,
- struct sockaddr *));
-extern struct ph1handle *getph1bydstaddrwop __P((struct sockaddr *));
+
+extern int enumph1 __P((struct ph1selector *ph1sel,
+ int (* enum_func)(struct ph1handle *iph1, void *arg),
+ void *enum_arg));
+
+#define GETPH1_F_ESTABLISHED 0x0001
+
+extern struct ph1handle *getph1 __P((struct ph1handle *ph1hint,
+ struct sockaddr *local,
+ struct sockaddr *remote,
+ int flags));
+
+#define getph1byaddr(local, remote, est) \
+ getph1(NULL, local, remote, est ? GETPH1_F_ESTABLISHED : 0)
+#define getph1bydstaddr(remote) \
+ getph1(NULL, NULL, remote, 0)
+
#ifdef ENABLE_HYBRID
struct ph1handle *getph1bylogin __P((char *));
int purgeph1bylogin __P((char *));
#endif
+extern void migrate_ph12 __P((struct ph1handle *old_iph1, struct ph1handle *new_iph1));
+extern void migrate_dying_ph12 __P((struct ph1handle *iph1));
extern vchar_t *dumpph1 __P((void));
extern struct ph1handle *newph1 __P((void));
extern void delph1 __P((struct ph1handle *));
extern int insph1 __P((struct ph1handle *));
extern void remph1 __P((struct ph1handle *));
+extern int resolveph1rmconf __P((struct ph1handle *));
extern void flushph1 __P((void));
extern void initph1tree __P((void));
+extern int ph1_rekey_enabled __P((struct ph1handle *));
-extern struct ph2handle *getph2byspidx __P((struct policyindex *));
-extern struct ph2handle *getph2byspid __P((u_int32_t));
+extern int enumph2 __P((struct ph2selector *ph2sel,
+ int (* enum_func)(struct ph2handle *iph2, void *arg),
+ void *enum_arg));
extern struct ph2handle *getph2byseq __P((u_int32_t));
extern struct ph2handle *getph2bysaddr __P((struct sockaddr *,
struct sockaddr *));
@@ -466,6 +520,7 @@ extern void unbindph12 __P((struct ph2handle *));
extern struct contacted *getcontacted __P((struct sockaddr *));
extern int inscontacted __P((struct sockaddr *));
+extern void remcontacted __P((struct sockaddr *));
extern void initctdtree __P((void));
extern int check_recvdpkt __P((struct sockaddr *,
diff --git a/src/racoon/ipsec_doi-0.7.3.c b/src/racoon/ipsec_doi-0.7.3.c
new file mode 100644
index 0000000..7ae9f67
--- /dev/null
+++ b/src/racoon/ipsec_doi-0.7.3.c
@@ -0,0 +1,5022 @@
+/* $NetBSD: ipsec_doi.c,v 1.23.4.10 2009/06/19 07:32:52 tteras Exp $ */
+
+/* Id: ipsec_doi.c,v 1.55 2006/08/17 09:20:41 vanhu Exp */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+
+#include PATH_IPSEC_H
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <netdb.h>
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+
+#include "var.h"
+#include "vmbuf.h"
+#include "misc.h"
+#include "plog.h"
+#include "debug.h"
+
+#include "cfparse_proto.h"
+#include "isakmp_var.h"
+#include "isakmp.h"
+#include "ipsec_doi.h"
+#include "oakley.h"
+#include "remoteconf.h"
+#include "localconf.h"
+#include "sockmisc.h"
+#include "handler.h"
+#include "policy.h"
+#include "algorithm.h"
+#include "sainfo.h"
+#include "proposal.h"
+#include "crypto_openssl.h"
+#include "strnames.h"
+#include "gcmalloc.h"
+
+#ifdef ENABLE_NATT
+#include "nattraversal.h"
+#endif
+#ifdef ENABLE_HYBRID
+static int switch_authmethod(int);
+#endif
+
+#ifdef HAVE_GSSAPI
+#include <iconv.h>
+#include "gssapi.h"
+#ifdef HAVE_ICONV_2ND_CONST
+#define __iconv_const const
+#else
+#define __iconv_const
+#endif
+#endif
+
+int verbose_proposal_check = 1;
+
+static vchar_t *get_ph1approval __P((struct ph1handle *, struct prop_pair **));
+static struct isakmpsa *get_ph1approvalx __P((struct prop_pair *,
+ struct isakmpsa *, struct isakmpsa *, int));
+static void print_ph1mismatched __P((struct prop_pair *, struct isakmpsa *));
+static int t2isakmpsa __P((struct isakmp_pl_t *, struct isakmpsa *));
+static int cmp_aproppair_i __P((struct prop_pair *, struct prop_pair *));
+static struct prop_pair *get_ph2approval __P((struct ph2handle *,
+ struct prop_pair **));
+static struct prop_pair *get_ph2approvalx __P((struct ph2handle *,
+ struct prop_pair *));
+static void free_proppair0 __P((struct prop_pair *));
+
+static int get_transform
+ __P((struct isakmp_pl_p *, struct prop_pair **, int *));
+static u_int32_t ipsecdoi_set_ld __P((vchar_t *));
+
+static int check_doi __P((u_int32_t));
+static int check_situation __P((u_int32_t));
+
+static int check_prot_main __P((int));
+static int check_prot_quick __P((int));
+static int (*check_protocol[]) __P((int)) = {
+ check_prot_main, /* IPSECDOI_TYPE_PH1 */
+ check_prot_quick, /* IPSECDOI_TYPE_PH2 */
+};
+
+static int check_spi_size __P((int, int));
+
+static int check_trns_isakmp __P((int));
+static int check_trns_ah __P((int));
+static int check_trns_esp __P((int));
+static int check_trns_ipcomp __P((int));
+static int (*check_transform[]) __P((int)) = {
+ 0,
+ check_trns_isakmp, /* IPSECDOI_PROTO_ISAKMP */
+ check_trns_ah, /* IPSECDOI_PROTO_IPSEC_AH */
+ check_trns_esp, /* IPSECDOI_PROTO_IPSEC_ESP */
+ check_trns_ipcomp, /* IPSECDOI_PROTO_IPCOMP */
+};
+
+static int check_attr_isakmp __P((struct isakmp_pl_t *));
+static int check_attr_ah __P((struct isakmp_pl_t *));
+static int check_attr_esp __P((struct isakmp_pl_t *));
+static int check_attr_ipsec __P((int, struct isakmp_pl_t *));
+static int check_attr_ipcomp __P((struct isakmp_pl_t *));
+static int (*check_attributes[]) __P((struct isakmp_pl_t *)) = {
+ 0,
+ check_attr_isakmp, /* IPSECDOI_PROTO_ISAKMP */
+ check_attr_ah, /* IPSECDOI_PROTO_IPSEC_AH */
+ check_attr_esp, /* IPSECDOI_PROTO_IPSEC_ESP */
+ check_attr_ipcomp, /* IPSECDOI_PROTO_IPCOMP */
+};
+
+static int setph1prop __P((struct isakmpsa *, caddr_t));
+static int setph1trns __P((struct isakmpsa *, caddr_t));
+static int setph1attr __P((struct isakmpsa *, caddr_t));
+static vchar_t *setph2proposal0 __P((const struct ph2handle *,
+ const struct saprop *, const struct saproto *));
+
+static vchar_t *getidval __P((int, vchar_t *));
+
+#ifdef HAVE_GSSAPI
+static struct isakmpsa *fixup_initiator_sa __P((struct isakmpsa *,
+ struct isakmpsa *));
+#endif
+
+/*%%%*/
+/*
+ * check phase 1 SA payload.
+ * make new SA payload to be replyed not including general header.
+ * the pointer to one of isakmpsa in proposal is set into iph1->approval.
+ * OUT:
+ * positive: the pointer to new buffer of SA payload.
+ * network byte order.
+ * NULL : error occurd.
+ */
+int
+ipsecdoi_checkph1proposal(sa, iph1)
+ vchar_t *sa;
+ struct ph1handle *iph1;
+{
+ vchar_t *newsa; /* new SA payload approved. */
+ struct prop_pair **pair;
+
+ /* get proposal pair */
+ pair = get_proppair(sa, IPSECDOI_TYPE_PH1);
+ if (pair == NULL)
+ return -1;
+
+ /* check and get one SA for use */
+ newsa = get_ph1approval(iph1, pair);
+
+ free_proppair(pair);
+
+ if (newsa == NULL)
+ return -1;
+
+ iph1->sa_ret = newsa;
+
+ return 0;
+}
+
+/*
+ * acceptable check for remote configuration.
+ * return a new SA payload to be reply to peer.
+ */
+static vchar_t *
+get_ph1approval(iph1, pair)
+ struct ph1handle *iph1;
+ struct prop_pair **pair;
+{
+ vchar_t *newsa;
+ struct isakmpsa *sa, tsa;
+ struct prop_pair *s, *p;
+ int prophlen;
+ int i;
+
+ if (iph1->approval) {
+ delisakmpsa(iph1->approval);
+ iph1->approval = NULL;
+ }
+
+ for (i = 0; i < MAXPROPPAIRLEN; i++) {
+ if (pair[i] == NULL)
+ continue;
+ for (s = pair[i]; s; s = s->next) {
+ prophlen =
+ sizeof(struct isakmp_pl_p) + s->prop->spi_size;
+
+ /* compare proposal and select one */
+ for (p = s; p; p = p->tnext) {
+ if ((sa = get_ph1approvalx(p,
+ iph1->rmconf->proposal, &tsa,
+ iph1->rmconf->pcheck_level)) != NULL)
+ goto found;
+ }
+ }
+ }
+
+ /*
+ * if there is no suitable proposal, racoon complains about all of
+ * mismatched items in those proposal.
+ */
+ if (verbose_proposal_check) {
+ for (i = 0; i < MAXPROPPAIRLEN; i++) {
+ if (pair[i] == NULL)
+ continue;
+ for (s = pair[i]; s; s = s->next) {
+ prophlen = sizeof(struct isakmp_pl_p)
+ + s->prop->spi_size;
+ for (p = s; p; p = p->tnext) {
+ print_ph1mismatched(p,
+ iph1->rmconf->proposal);
+ }
+ }
+ }
+ }
+ plog(LLV_ERROR, LOCATION, NULL, "no suitable proposal found.\n");
+
+ return NULL;
+
+found:
+ plog(LLV_DEBUG, LOCATION, NULL, "an acceptable proposal found.\n");
+
+ /* check DH group settings */
+ if (sa->dhgrp) {
+ if (sa->dhgrp->prime && sa->dhgrp->gen1) {
+ /* it's ok */
+ goto saok;
+ }
+ plog(LLV_WARNING, LOCATION, NULL,
+ "invalid DH parameter found, use default.\n");
+ oakley_dhgrp_free(sa->dhgrp);
+ sa->dhgrp=NULL;
+ }
+
+ if (oakley_setdhgroup(sa->dh_group, &sa->dhgrp) == -1) {
+ sa->dhgrp = NULL;
+ racoon_free(sa);
+ return NULL;
+ }
+
+saok:
+#ifdef HAVE_GSSAPI
+ if (sa->gssid != NULL)
+ plog(LLV_DEBUG, LOCATION, NULL, "gss id in new sa '%.*s'\n",
+ (int)sa->gssid->l, sa->gssid->v);
+ if (iph1-> side == INITIATOR) {
+ if (iph1->rmconf->proposal->gssid != NULL)
+ iph1->gi_i = vdup(iph1->rmconf->proposal->gssid);
+ if (tsa.gssid != NULL)
+ iph1->gi_r = vdup(tsa.gssid);
+ iph1->approval = fixup_initiator_sa(sa, &tsa);
+ } else {
+ if (tsa.gssid != NULL) {
+ iph1->gi_r = vdup(tsa.gssid);
+ iph1->gi_i = gssapi_get_id(iph1);
+ if (sa->gssid == NULL && iph1->gi_i != NULL)
+ sa->gssid = vdup(iph1->gi_i);
+ }
+ iph1->approval = sa;
+ }
+ if (iph1->gi_i != NULL)
+ plog(LLV_DEBUG, LOCATION, NULL, "GIi is %.*s\n",
+ (int)iph1->gi_i->l, iph1->gi_i->v);
+ if (iph1->gi_r != NULL)
+ plog(LLV_DEBUG, LOCATION, NULL, "GIr is %.*s\n",
+ (int)iph1->gi_r->l, iph1->gi_r->v);
+#else
+ iph1->approval = sa;
+#endif
+ if(iph1->approval) {
+ plog(LLV_DEBUG, LOCATION, NULL, "agreed on %s auth.\n",
+ s_oakley_attr_method(iph1->approval->authmethod));
+ }
+
+ newsa = get_sabyproppair(p, iph1);
+ if (newsa == NULL){
+ delisakmpsa(iph1->approval);
+ iph1->approval = NULL;
+ }
+
+ return newsa;
+}
+
+/*
+ * compare peer's single proposal and all of my proposal.
+ * and select one if suiatable.
+ * p : one of peer's proposal.
+ * proposal: my proposals.
+ */
+static struct isakmpsa *
+get_ph1approvalx(p, proposal, sap, check_level)
+ struct prop_pair *p;
+ struct isakmpsa *proposal, *sap;
+ int check_level;
+{
+ struct isakmp_pl_p *prop = p->prop;
+ struct isakmp_pl_t *trns = p->trns;
+ struct isakmpsa sa, *s, *tsap;
+ int authmethod;
+
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "prop#=%d, prot-id=%s, spi-size=%d, #trns=%d\n",
+ prop->p_no, s_ipsecdoi_proto(prop->proto_id),
+ prop->spi_size, prop->num_t);
+
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "trns#=%d, trns-id=%s\n",
+ trns->t_no,
+ s_ipsecdoi_trns(prop->proto_id, trns->t_id));
+
+ tsap = sap != NULL ? sap : &sa;
+
+ memset(tsap, 0, sizeof(*tsap));
+ if (t2isakmpsa(trns, tsap) < 0)
+ return NULL;
+ for (s = proposal; s != NULL; s = s->next) {
+#ifdef ENABLE_HYBRID
+ authmethod = switch_authmethod(s->authmethod);
+#else
+ authmethod = s->authmethod;
+#endif
+ plog(LLV_DEBUG, LOCATION, NULL, "Compared: DB:Peer\n");
+ plog(LLV_DEBUG, LOCATION, NULL, "(lifetime = %ld:%ld)\n",
+ (long)s->lifetime, (long)tsap->lifetime);
+ plog(LLV_DEBUG, LOCATION, NULL, "(lifebyte = %zu:%zu)\n",
+ s->lifebyte, tsap->lifebyte);
+ plog(LLV_DEBUG, LOCATION, NULL, "enctype = %s:%s\n",
+ s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG,
+ s->enctype),
+ s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG,
+ tsap->enctype));
+ plog(LLV_DEBUG, LOCATION, NULL, "(encklen = %d:%d)\n",
+ s->encklen, tsap->encklen);
+ plog(LLV_DEBUG, LOCATION, NULL, "hashtype = %s:%s\n",
+ s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG,
+ s->hashtype),
+ s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG,
+ tsap->hashtype));
+ plog(LLV_DEBUG, LOCATION, NULL, "authmethod = %s:%s\n",
+ s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD,
+ s->authmethod),
+ s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD,
+ tsap->authmethod));
+ plog(LLV_DEBUG, LOCATION, NULL, "dh_group = %s:%s\n",
+ s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC,
+ s->dh_group),
+ s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC,
+ tsap->dh_group));
+#if 0
+ /* XXX to be considered ? */
+ if (tsap->lifebyte > s->lifebyte) ;
+#endif
+ /*
+ * if responder side and peer's key length in proposal
+ * is bigger than mine, it might be accepted.
+ */
+ if(tsap->enctype == s->enctype &&
+ tsap->authmethod == authmethod &&
+ tsap->hashtype == s->hashtype &&
+ tsap->dh_group == s->dh_group &&
+ tsap->encklen == s->encklen) {
+ switch(check_level) {
+ case PROP_CHECK_OBEY:
+ goto found;
+ break;
+
+ case PROP_CHECK_STRICT:
+ if ((tsap->lifetime > s->lifetime) ||
+ (tsap->lifebyte > s->lifebyte))
+ continue;
+ goto found;
+ break;
+
+ case PROP_CHECK_CLAIM:
+ if (tsap->lifetime < s->lifetime)
+ s->lifetime = tsap->lifetime;
+ if (tsap->lifebyte < s->lifebyte)
+ s->lifebyte = tsap->lifebyte;
+ goto found;
+ break;
+
+ case PROP_CHECK_EXACT:
+ if ((tsap->lifetime != s->lifetime) ||
+ (tsap->lifebyte != s->lifebyte))
+ continue;
+ goto found;
+ break;
+
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "Unexpected proposal_check value\n");
+ continue;
+ break;
+ }
+ }
+ }
+
+found:
+ if (tsap->dhgrp != NULL){
+ oakley_dhgrp_free(tsap->dhgrp);
+ tsap->dhgrp = NULL;
+ }
+
+ if ((s = dupisakmpsa(s)) != NULL) {
+ switch(check_level) {
+ case PROP_CHECK_OBEY:
+ s->lifetime = tsap->lifetime;
+ s->lifebyte = tsap->lifebyte;
+ break;
+
+ case PROP_CHECK_STRICT:
+ s->lifetime = tsap->lifetime;
+ s->lifebyte = tsap->lifebyte;
+ break;
+
+ case PROP_CHECK_CLAIM:
+ if (tsap->lifetime < s->lifetime)
+ s->lifetime = tsap->lifetime;
+ if (tsap->lifebyte < s->lifebyte)
+ s->lifebyte = tsap->lifebyte;
+ break;
+
+ default:
+ break;
+ }
+ }
+ return s;
+}
+
+/*
+ * print all of items in peer's proposal which are mismatched to my proposal.
+ * p : one of peer's proposal.
+ * proposal: my proposals.
+ */
+static void
+print_ph1mismatched(p, proposal)
+ struct prop_pair *p;
+ struct isakmpsa *proposal;
+{
+ struct isakmpsa sa, *s;
+
+ memset(&sa, 0, sizeof(sa));
+ if (t2isakmpsa(p->trns, &sa) < 0)
+ return;
+ for (s = proposal; s ; s = s->next) {
+ if (sa.enctype != s->enctype) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "rejected enctype: "
+ "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
+ "%s:%s\n",
+ s->prop_no, s->trns_no,
+ p->prop->p_no, p->trns->t_no,
+ s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG,
+ s->enctype),
+ s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG,
+ sa.enctype));
+ }
+ if (sa.authmethod != s->authmethod) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "rejected authmethod: "
+ "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
+ "%s:%s\n",
+ s->prop_no, s->trns_no,
+ p->prop->p_no, p->trns->t_no,
+ s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD,
+ s->authmethod),
+ s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD,
+ sa.authmethod));
+ }
+ if (sa.hashtype != s->hashtype) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "rejected hashtype: "
+ "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
+ "%s:%s\n",
+ s->prop_no, s->trns_no,
+ p->prop->p_no, p->trns->t_no,
+ s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG,
+ s->hashtype),
+ s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG,
+ sa.hashtype));
+ }
+ if (sa.dh_group != s->dh_group) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "rejected dh_group: "
+ "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
+ "%s:%s\n",
+ s->prop_no, s->trns_no,
+ p->prop->p_no, p->trns->t_no,
+ s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC,
+ s->dh_group),
+ s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC,
+ sa.dh_group));
+ }
+ }
+
+ if (sa.dhgrp != NULL){
+ oakley_dhgrp_free(sa.dhgrp);
+ sa.dhgrp=NULL;
+ }
+}
+
+/*
+ * get ISAKMP data attributes
+ */
+static int
+t2isakmpsa(trns, sa)
+ struct isakmp_pl_t *trns;
+ struct isakmpsa *sa;
+{
+ struct isakmp_data *d, *prev;
+ int flag, type;
+ int error = -1;
+ int life_t;
+ int keylen = 0;
+ vchar_t *val = NULL;
+ int len, tlen;
+ u_char *p;
+
+ tlen = ntohs(trns->h.len) - sizeof(*trns);
+ prev = (struct isakmp_data *)NULL;
+ d = (struct isakmp_data *)(trns + 1);
+
+ /* default */
+ life_t = OAKLEY_ATTR_SA_LD_TYPE_DEFAULT;
+ sa->lifetime = OAKLEY_ATTR_SA_LD_SEC_DEFAULT;
+ sa->lifebyte = 0;
+ sa->dhgrp = racoon_calloc(1, sizeof(struct dhgroup));
+ if (!sa->dhgrp)
+ goto err;
+
+ while (tlen > 0) {
+
+ type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
+ flag = ntohs(d->type) & ISAKMP_GEN_MASK;
+
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "type=%s, flag=0x%04x, lorv=%s\n",
+ s_oakley_attr(type), flag,
+ s_oakley_attr_v(type, ntohs(d->lorv)));
+
+ /* get variable-sized item */
+ switch (type) {
+ case OAKLEY_ATTR_GRP_PI:
+ case OAKLEY_ATTR_GRP_GEN_ONE:
+ case OAKLEY_ATTR_GRP_GEN_TWO:
+ case OAKLEY_ATTR_GRP_CURVE_A:
+ case OAKLEY_ATTR_GRP_CURVE_B:
+ case OAKLEY_ATTR_SA_LD:
+ case OAKLEY_ATTR_GRP_ORDER:
+ if (flag) { /*TV*/
+ len = 2;
+ p = (u_char *)&d->lorv;
+ } else { /*TLV*/
+ len = ntohs(d->lorv);
+ p = (u_char *)(d + 1);
+ }
+ val = vmalloc(len);
+ if (!val)
+ return -1;
+ memcpy(val->v, p, len);
+ break;
+
+ default:
+ break;
+ }
+
+ switch (type) {
+ case OAKLEY_ATTR_ENC_ALG:
+ sa->enctype = (u_int16_t)ntohs(d->lorv);
+ break;
+
+ case OAKLEY_ATTR_HASH_ALG:
+ sa->hashtype = (u_int16_t)ntohs(d->lorv);
+ break;
+
+ case OAKLEY_ATTR_AUTH_METHOD:
+ sa->authmethod = ntohs(d->lorv);
+ break;
+
+ case OAKLEY_ATTR_GRP_DESC:
+ sa->dh_group = (u_int16_t)ntohs(d->lorv);
+ break;
+
+ case OAKLEY_ATTR_GRP_TYPE:
+ {
+ int type = (int)ntohs(d->lorv);
+ if (type == OAKLEY_ATTR_GRP_TYPE_MODP)
+ sa->dhgrp->type = type;
+ else
+ return -1;
+ break;
+ }
+ case OAKLEY_ATTR_GRP_PI:
+ sa->dhgrp->prime = val;
+ break;
+
+ case OAKLEY_ATTR_GRP_GEN_ONE:
+ vfree(val);
+ if (!flag)
+ sa->dhgrp->gen1 = ntohs(d->lorv);
+ else {
+ int len = ntohs(d->lorv);
+ sa->dhgrp->gen1 = 0;
+ if (len > 4)
+ return -1;
+ memcpy(&sa->dhgrp->gen1, d + 1, len);
+ sa->dhgrp->gen1 = ntohl(sa->dhgrp->gen1);
+ }
+ break;
+
+ case OAKLEY_ATTR_GRP_GEN_TWO:
+ vfree(val);
+ if (!flag)
+ sa->dhgrp->gen2 = ntohs(d->lorv);
+ else {
+ int len = ntohs(d->lorv);
+ sa->dhgrp->gen2 = 0;
+ if (len > 4)
+ return -1;
+ memcpy(&sa->dhgrp->gen2, d + 1, len);
+ sa->dhgrp->gen2 = ntohl(sa->dhgrp->gen2);
+ }
+ break;
+
+ case OAKLEY_ATTR_GRP_CURVE_A:
+ sa->dhgrp->curve_a = val;
+ break;
+
+ case OAKLEY_ATTR_GRP_CURVE_B:
+ sa->dhgrp->curve_b = val;
+ break;
+
+ case OAKLEY_ATTR_SA_LD_TYPE:
+ {
+ int type = (int)ntohs(d->lorv);
+ switch (type) {
+ case OAKLEY_ATTR_SA_LD_TYPE_SEC:
+ case OAKLEY_ATTR_SA_LD_TYPE_KB:
+ life_t = type;
+ break;
+ default:
+ life_t = OAKLEY_ATTR_SA_LD_TYPE_DEFAULT;
+ break;
+ }
+ break;
+ }
+ case OAKLEY_ATTR_SA_LD:
+ if (!prev
+ || (ntohs(prev->type) & ~ISAKMP_GEN_MASK) !=
+ OAKLEY_ATTR_SA_LD_TYPE) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "life duration must follow ltype\n");
+ break;
+ }
+
+ switch (life_t) {
+ case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
+ sa->lifetime = ipsecdoi_set_ld(val);
+ vfree(val);
+ if (sa->lifetime == 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid life duration.\n");
+ goto err;
+ }
+ break;
+ case IPSECDOI_ATTR_SA_LD_TYPE_KB:
+ sa->lifebyte = ipsecdoi_set_ld(val);
+ vfree(val);
+ if (sa->lifebyte == 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid life duration.\n");
+ goto err;
+ }
+ break;
+ default:
+ vfree(val);
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid life type: %d\n", life_t);
+ goto err;
+ }
+ break;
+
+ case OAKLEY_ATTR_KEY_LEN:
+ {
+ int len = ntohs(d->lorv);
+ if (len % 8 != 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "keylen %d: not multiple of 8\n",
+ len);
+ goto err;
+ }
+ sa->encklen = (u_int16_t)len;
+ keylen++;
+ break;
+ }
+ case OAKLEY_ATTR_PRF:
+ case OAKLEY_ATTR_FIELD_SIZE:
+ /* unsupported */
+ break;
+
+ case OAKLEY_ATTR_GRP_ORDER:
+ sa->dhgrp->order = val;
+ break;
+#ifdef HAVE_GSSAPI
+ case OAKLEY_ATTR_GSS_ID:
+ {
+ int error = -1;
+ iconv_t cd = (iconv_t) -1;
+ size_t srcleft, dstleft, rv;
+ __iconv_const char *src;
+ char *dst;
+ int len = ntohs(d->lorv);
+
+ /*
+ * Older verions of racoon just placed the
+ * ISO-Latin-1 string on the wire directly.
+ * Check to see if we are configured to be
+ * compatible with this behavior.
+ */
+ if (lcconf->gss_id_enc == LC_GSSENC_LATIN1) {
+ if ((sa->gssid = vmalloc(len)) == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "failed to allocate memory\n");
+ goto out;
+ }
+ memcpy(sa->gssid->v, d + 1, len);
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "received old-style gss "
+ "id '%.*s' (len %zu)\n",
+ (int)sa->gssid->l, sa->gssid->v,
+ sa->gssid->l);
+ error = 0;
+ goto out;
+ }
+
+ /*
+ * For Windows 2000 compatibility, we expect
+ * the GSS ID attribute on the wire to be
+ * encoded in UTF-16LE. Internally, we work
+ * in ISO-Latin-1. Therefore, we should need
+ * 1/2 the specified length, which should always
+ * be a multiple of 2 octets.
+ */
+ cd = iconv_open("latin1", "utf-16le");
+ if (cd == (iconv_t) -1) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "unable to initialize utf-16le -> latin1 "
+ "conversion descriptor: %s\n",
+ strerror(errno));
+ goto out;
+ }
+
+ if ((sa->gssid = vmalloc(len / 2)) == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "failed to allocate memory\n");
+ goto out;
+ }
+
+ src = (__iconv_const char *)(d + 1);
+ srcleft = len;
+
+ dst = sa->gssid->v;
+ dstleft = len / 2;
+
+ rv = iconv(cd, (__iconv_const char **)&src, &srcleft,
+ &dst, &dstleft);
+ if (rv != 0) {
+ if (rv == -1) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "unable to convert GSS ID from "
+ "utf-16le -> latin1: %s\n",
+ strerror(errno));
+ } else {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "%zd character%s in GSS ID cannot "
+ "be represented in latin1\n",
+ rv, rv == 1 ? "" : "s");
+ }
+ goto out;
+ }
+
+ /* XXX dstleft should always be 0; assert it? */
+ sa->gssid->l = (len / 2) - dstleft;
+
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "received gss id '%.*s' (len %zu)\n",
+ (int)sa->gssid->l, sa->gssid->v, sa->gssid->l);
+
+ error = 0;
+out:
+ if (cd != (iconv_t)-1)
+ (void)iconv_close(cd);
+
+ if ((error != 0) && (sa->gssid != NULL)) {
+ vfree(sa->gssid);
+ sa->gssid = NULL;
+ }
+ break;
+ }
+#endif /* HAVE_GSSAPI */
+
+ default:
+ break;
+ }
+
+ prev = d;
+ if (flag) {
+ tlen -= sizeof(*d);
+ d = (struct isakmp_data *)((char *)d + sizeof(*d));
+ } else {
+ tlen -= (sizeof(*d) + ntohs(d->lorv));
+ d = (struct isakmp_data *)((char *)d + sizeof(*d) + ntohs(d->lorv));
+ }
+ }
+
+ /* key length must not be specified on some algorithms */
+ if (keylen) {
+ if (sa->enctype == OAKLEY_ATTR_ENC_ALG_DES
+#ifdef HAVE_OPENSSL_IDEA_H
+ || sa->enctype == OAKLEY_ATTR_ENC_ALG_IDEA
+#endif
+ || sa->enctype == OAKLEY_ATTR_ENC_ALG_3DES) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "keylen must not be specified "
+ "for encryption algorithm %d\n",
+ sa->enctype);
+ return -1;
+ }
+ }
+
+ return 0;
+err:
+ return error;
+}
+
+/*%%%*/
+/*
+ * check phase 2 SA payload and select single proposal.
+ * make new SA payload to be replyed not including general header.
+ * This function is called by responder only.
+ * OUT:
+ * 0: succeed.
+ * -1: error occured.
+ */
+int
+ipsecdoi_selectph2proposal(iph2)
+ struct ph2handle *iph2;
+{
+ struct prop_pair **pair;
+ struct prop_pair *ret;
+
+ /* get proposal pair */
+ pair = get_proppair(iph2->sa, IPSECDOI_TYPE_PH2);
+ if (pair == NULL)
+ return -1;
+
+ /* check and select a proposal. */
+ ret = get_ph2approval(iph2, pair);
+ free_proppair(pair);
+ if (ret == NULL)
+ return -1;
+
+ /* make a SA to be replayed. */
+ /* SPI must be updated later. */
+ iph2->sa_ret = get_sabyproppair(ret, iph2->ph1);
+ free_proppair0(ret);
+ if (iph2->sa_ret == NULL)
+ return -1;
+
+ return 0;
+}
+
+/*
+ * check phase 2 SA payload returned from responder.
+ * This function is called by initiator only.
+ * OUT:
+ * 0: valid.
+ * -1: invalid.
+ */
+int
+ipsecdoi_checkph2proposal(iph2)
+ struct ph2handle *iph2;
+{
+ struct prop_pair **rpair = NULL, **spair = NULL;
+ struct prop_pair *p;
+ int i, n, num;
+ int error = -1;
+ vchar_t *sa_ret = NULL;
+
+ /* get proposal pair of SA sent. */
+ spair = get_proppair(iph2->sa, IPSECDOI_TYPE_PH2);
+ if (spair == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "failed to get prop pair.\n");
+ goto end;
+ }
+
+ /* XXX should check the number of transform */
+
+ /* get proposal pair of SA replayed */
+ rpair = get_proppair(iph2->sa_ret, IPSECDOI_TYPE_PH2);
+ if (rpair == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "failed to get prop pair.\n");
+ goto end;
+ }
+
+ /* check proposal is only one ? */
+ n = 0;
+ num = 0;
+ for (i = 0; i < MAXPROPPAIRLEN; i++) {
+ if (rpair[i]) {
+ n = i;
+ num++;
+ }
+ }
+ if (num == 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "no proposal received.\n");
+ goto end;
+ }
+ if (num != 1) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "some proposals received.\n");
+ goto end;
+ }
+
+ if (spair[n] == NULL) {
+ plog(LLV_WARNING, LOCATION, NULL,
+ "invalid proposal number:%d received.\n", i);
+ }
+
+
+ if (rpair[n]->tnext != NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "multi transforms replyed.\n");
+ goto end;
+ }
+
+ if (cmp_aproppair_i(rpair[n], spair[n])) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "proposal mismathed.\n");
+ goto end;
+ }
+
+ /*
+ * check and select a proposal.
+ * ensure that there is no modification of the proposal by
+ * cmp_aproppair_i()
+ */
+ p = get_ph2approval(iph2, rpair);
+ if (p == NULL)
+ goto end;
+
+ /* make a SA to be replayed. */
+ sa_ret = iph2->sa_ret;
+ iph2->sa_ret = get_sabyproppair(p, iph2->ph1);
+ free_proppair0(p);
+ if (iph2->sa_ret == NULL)
+ goto end;
+
+ error = 0;
+
+end:
+ if (rpair)
+ free_proppair(rpair);
+ if (spair)
+ free_proppair(spair);
+ if (sa_ret)
+ vfree(sa_ret);
+
+ return error;
+}
+
+/*
+ * compare two prop_pair which is assumed to have same proposal number.
+ * the case of bundle or single SA, NOT multi transforms.
+ * a: a proposal that is multi protocols and single transform, usually replyed.
+ * b: a proposal that is multi protocols and multi transform, usually sent.
+ * NOTE: this function is for initiator.
+ * OUT
+ * 0: equal
+ * 1: not equal
+ * XXX cannot understand the comment!
+ */
+static int
+cmp_aproppair_i(a, b)
+ struct prop_pair *a, *b;
+{
+ struct prop_pair *p, *q, *r;
+ int len;
+
+ for (p = a, q = b; p && q; p = p->next, q = q->next) {
+ for (r = q; r; r = r->tnext) {
+ /* compare trns */
+ if (p->trns->t_no == r->trns->t_no)
+ break;
+ }
+ if (!r) {
+ /* no suitable transform found */
+ plog(LLV_ERROR, LOCATION, NULL,
+ "no suitable transform found.\n");
+ return -1;
+ }
+
+ /* compare prop */
+ if (p->prop->p_no != r->prop->p_no) {
+ plog(LLV_WARNING, LOCATION, NULL,
+ "proposal #%d mismatched, "
+ "expected #%d.\n",
+ r->prop->p_no, p->prop->p_no);
+ /*FALLTHROUGH*/
+ }
+
+ if (p->prop->proto_id != r->prop->proto_id) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "proto_id mismathed: my:%d peer:%d\n",
+ r->prop->proto_id, p->prop->proto_id);
+ return -1;
+ }
+
+ if (p->prop->spi_size != r->prop->spi_size) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid spi size: %d.\n",
+ p->prop->spi_size);
+ return -1;
+ }
+
+ /* check #of transforms */
+ if (p->prop->num_t != 1) {
+ plog(LLV_WARNING, LOCATION, NULL,
+ "#of transform is %d, "
+ "but expected 1.\n", p->prop->num_t);
+ /*FALLTHROUGH*/
+ }
+
+ if (p->trns->t_id != r->trns->t_id) {
+ plog(LLV_WARNING, LOCATION, NULL,
+ "transform number has been modified.\n");
+ /*FALLTHROUGH*/
+ }
+ if (p->trns->reserved != r->trns->reserved) {
+ plog(LLV_WARNING, LOCATION, NULL,
+ "reserved field should be zero.\n");
+ /*FALLTHROUGH*/
+ }
+
+ /* compare attribute */
+ len = ntohs(r->trns->h.len) - sizeof(*p->trns);
+ if (memcmp(p->trns + 1, r->trns + 1, len) != 0) {
+ plog(LLV_WARNING, LOCATION, NULL,
+ "attribute has been modified.\n");
+ /*FALLTHROUGH*/
+ }
+ }
+ if ((p && !q) || (!p && q)) {
+ /* # of protocols mismatched */
+ plog(LLV_ERROR, LOCATION, NULL,
+ "#of protocols mismatched.\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * acceptable check for policy configuration.
+ * return a new SA payload to be reply to peer.
+ */
+static struct prop_pair *
+get_ph2approval(iph2, pair)
+ struct ph2handle *iph2;
+ struct prop_pair **pair;
+{
+ struct prop_pair *ret;
+ int i;
+
+ iph2->approval = NULL;
+
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "begin compare proposals.\n");
+
+ for (i = 0; i < MAXPROPPAIRLEN; i++) {
+ if (pair[i] == NULL)
+ continue;
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "pair[%d]: %p\n", i, pair[i]);
+ print_proppair(LLV_DEBUG, pair[i]);;
+
+ /* compare proposal and select one */
+ ret = get_ph2approvalx(iph2, pair[i]);
+ if (ret != NULL) {
+ /* found */
+ return ret;
+ }
+ }
+
+ plog(LLV_ERROR, LOCATION, NULL, "no suitable policy found.\n");
+
+ return NULL;
+}
+
+/*
+ * compare my proposal and peers just one proposal.
+ * set a approval.
+ */
+static struct prop_pair *
+get_ph2approvalx(iph2, pp)
+ struct ph2handle *iph2;
+ struct prop_pair *pp;
+{
+ struct prop_pair *ret = NULL;
+ struct saprop *pr0, *pr = NULL;
+ struct saprop *q1, *q2;
+
+ pr0 = aproppair2saprop(pp);
+ if (pr0 == NULL)
+ return NULL;
+
+ for (q1 = pr0; q1; q1 = q1->next) {
+ for (q2 = iph2->proposal; q2; q2 = q2->next) {
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "peer's single bundle:\n");
+ printsaprop0(LLV_DEBUG, q1);
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "my single bundle:\n");
+ printsaprop0(LLV_DEBUG, q2);
+
+ pr = cmpsaprop_alloc(iph2->ph1, q1, q2, iph2->side);
+ if (pr != NULL)
+ goto found;
+
+ plog(LLV_ERROR, LOCATION, NULL,
+ "not matched\n");
+ }
+ }
+ /* no proposal matching */
+err:
+ flushsaprop(pr0);
+ return NULL;
+
+found:
+ flushsaprop(pr0);
+ plog(LLV_DEBUG, LOCATION, NULL, "matched\n");
+ iph2->approval = pr;
+
+ {
+ struct saproto *sp;
+ struct prop_pair *p, *x;
+ struct prop_pair *n = NULL;
+
+ ret = NULL;
+
+ for (p = pp; p; p = p->next) {
+ /*
+ * find a proposal with matching proto_id.
+ * we have analyzed validity already, in cmpsaprop_alloc().
+ */
+ for (sp = pr->head; sp; sp = sp->next) {
+ if (sp->proto_id == p->prop->proto_id)
+ break;
+ }
+ if (!sp)
+ goto err;
+ if (sp->head->next)
+ goto err; /* XXX */
+
+ for (x = p; x; x = x->tnext)
+ if (sp->head->trns_no == x->trns->t_no)
+ break;
+ if (!x)
+ goto err; /* XXX */
+
+ n = racoon_calloc(1, sizeof(struct prop_pair));
+ if (n == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "failed to get buffer.\n");
+ goto err;
+ }
+
+ n->prop = x->prop;
+ n->trns = x->trns;
+
+ /* need to preserve the order */
+ for (x = ret; x && x->next; x = x->next)
+ ;
+ if (x && x->prop == n->prop) {
+ for (/*nothing*/; x && x->tnext; x = x->tnext)
+ ;
+ x->tnext = n;
+ } else {
+ if (x)
+ x->next = n;
+ else {
+ ret = n;
+ }
+ }
+
+ /* #of transforms should be updated ? */
+ }
+ }
+
+ return ret;
+}
+
+void
+free_proppair(pair)
+ struct prop_pair **pair;
+{
+ int i;
+
+ for (i = 0; i < MAXPROPPAIRLEN; i++) {
+ free_proppair0(pair[i]);
+ pair[i] = NULL;
+ }
+ racoon_free(pair);
+}
+
+static void
+free_proppair0(pair)
+ struct prop_pair *pair;
+{
+ struct prop_pair *p, *q, *r, *s;
+
+ p = pair;
+ while (p) {
+ q = p->next;
+ r = p;
+ while (r) {
+ s = r->tnext;
+ racoon_free(r);
+ r = s;
+ }
+ p = q;
+ }
+}
+
+/*
+ * get proposal pairs from SA payload.
+ * tiny check for proposal payload.
+ */
+struct prop_pair **
+get_proppair(sa, mode)
+ vchar_t *sa;
+ int mode;
+{
+ struct prop_pair **pair = NULL;
+ int num_p = 0; /* number of proposal for use */
+ int tlen;
+ caddr_t bp;
+ int i;
+ struct ipsecdoi_sa_b *sab = (struct ipsecdoi_sa_b *)sa->v;
+
+ plog(LLV_DEBUG, LOCATION, NULL, "total SA len=%zu\n", sa->l);
+ plogdump(LLV_DEBUG, sa->v, sa->l);
+
+ /* check SA payload size */
+ if (sa->l < sizeof(*sab)) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "Invalid SA length = %zu.\n", sa->l);
+ goto bad;
+ }
+
+ /* check DOI */
+ if (check_doi(ntohl(sab->doi)) < 0)
+ goto bad;
+
+ /* check SITUATION */
+ if (check_situation(ntohl(sab->sit)) < 0)
+ goto bad;
+
+ pair = racoon_calloc(1, MAXPROPPAIRLEN * sizeof(*pair));
+ if (pair == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "failed to get buffer.\n");
+ goto bad;
+ }
+ memset(pair, 0, sizeof(pair));
+
+ bp = (caddr_t)(sab + 1);
+ tlen = sa->l - sizeof(*sab);
+
+ {
+ struct isakmp_pl_p *prop;
+ int proplen;
+ vchar_t *pbuf = NULL;
+ struct isakmp_parse_t *pa;
+
+ pbuf = isakmp_parsewoh(ISAKMP_NPTYPE_P, (struct isakmp_gen *)bp, tlen);
+ if (pbuf == NULL)
+ goto bad;
+
+ for (pa = (struct isakmp_parse_t *)pbuf->v;
+ pa->type != ISAKMP_NPTYPE_NONE;
+ pa++) {
+ /* check the value of next payload */
+ if (pa->type != ISAKMP_NPTYPE_P) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "Invalid payload type=%u\n", pa->type);
+ vfree(pbuf);
+ goto bad;
+ }
+
+ prop = (struct isakmp_pl_p *)pa->ptr;
+ proplen = pa->len;
+
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "proposal #%u len=%d\n", prop->p_no, proplen);
+
+ if (proplen == 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid proposal with length %d\n", proplen);
+ vfree(pbuf);
+ goto bad;
+ }
+
+ /* check Protocol ID */
+ if (!check_protocol[mode]) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "unsupported mode %d\n", mode);
+ continue;
+ }
+
+ if (check_protocol[mode](prop->proto_id) < 0)
+ continue;
+
+ /* check SPI length when IKE. */
+ if (check_spi_size(prop->proto_id, prop->spi_size) < 0)
+ continue;
+
+ /* get transform */
+ if (get_transform(prop, pair, &num_p) < 0) {
+ vfree(pbuf);
+ goto bad;
+ }
+ }
+ vfree(pbuf);
+ pbuf = NULL;
+ }
+
+ {
+ int notrans, nprop;
+ struct prop_pair *p, *q;
+
+ /* check for proposals with no transforms */
+ for (i = 0; i < MAXPROPPAIRLEN; i++) {
+ if (!pair[i])
+ continue;
+
+ plog(LLV_DEBUG, LOCATION, NULL, "pair %d:\n", i);
+ print_proppair(LLV_DEBUG, pair[i]);
+
+ notrans = nprop = 0;
+ for (p = pair[i]; p; p = p->next) {
+ if (p->trns == NULL) {
+ notrans++;
+ break;
+ }
+ for (q = p; q; q = q->tnext)
+ nprop++;
+ }
+
+#if 0
+ /*
+ * XXX at this moment, we cannot accept proposal group
+ * with multiple proposals. this should be fixed.
+ */
+ if (pair[i]->next) {
+ plog(LLV_WARNING, LOCATION, NULL,
+ "proposal #%u ignored "
+ "(multiple proposal not supported)\n",
+ pair[i]->prop->p_no);
+ notrans++;
+ }
+#endif
+
+ if (notrans) {
+ for (p = pair[i]; p; p = q) {
+ q = p->next;
+ racoon_free(p);
+ }
+ pair[i] = NULL;
+ num_p--;
+ } else {
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "proposal #%u: %d transform\n",
+ pair[i]->prop->p_no, nprop);
+ }
+ }
+ }
+
+ /* bark if no proposal is found. */
+ if (num_p <= 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "no Proposal found.\n");
+ goto bad;
+ }
+
+ return pair;
+bad:
+ if (pair != NULL)
+ racoon_free(pair);
+ return NULL;
+}
+
+/*
+ * check transform payload.
+ * OUT:
+ * positive: return the pointer to the payload of valid transform.
+ * 0 : No valid transform found.
+ */
+static int
+get_transform(prop, pair, num_p)
+ struct isakmp_pl_p *prop;
+ struct prop_pair **pair;
+ int *num_p;
+{
+ int tlen; /* total length of all transform in a proposal */
+ caddr_t bp;
+ struct isakmp_pl_t *trns;
+ int trnslen;
+ vchar_t *pbuf = NULL;
+ struct isakmp_parse_t *pa;
+ struct prop_pair *p = NULL, *q;
+ int num_t;
+
+ bp = (caddr_t)prop + sizeof(struct isakmp_pl_p) + prop->spi_size;
+ tlen = ntohs(prop->h.len)
+ - (sizeof(struct isakmp_pl_p) + prop->spi_size);
+ pbuf = isakmp_parsewoh(ISAKMP_NPTYPE_T, (struct isakmp_gen *)bp, tlen);
+ if (pbuf == NULL)
+ return -1;
+
+ /* check and get transform for use */
+ num_t = 0;
+ for (pa = (struct isakmp_parse_t *)pbuf->v;
+ pa->type != ISAKMP_NPTYPE_NONE;
+ pa++) {
+
+ num_t++;
+
+ /* check the value of next payload */
+ if (pa->type != ISAKMP_NPTYPE_T) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "Invalid payload type=%u\n", pa->type);
+ break;
+ }
+
+ trns = (struct isakmp_pl_t *)pa->ptr;
+ trnslen = pa->len;
+
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "transform #%u len=%u\n", trns->t_no, trnslen);
+
+ /* check transform ID */
+ if (prop->proto_id >= ARRAYLEN(check_transform)) {
+ plog(LLV_WARNING, LOCATION, NULL,
+ "unsupported proto_id %u\n",
+ prop->proto_id);
+ continue;
+ }
+ if (prop->proto_id >= ARRAYLEN(check_attributes)) {
+ plog(LLV_WARNING, LOCATION, NULL,
+ "unsupported proto_id %u\n",
+ prop->proto_id);
+ continue;
+ }
+
+ if (!check_transform[prop->proto_id]
+ || !check_attributes[prop->proto_id]) {
+ plog(LLV_WARNING, LOCATION, NULL,
+ "unsupported proto_id %u\n",
+ prop->proto_id);
+ continue;
+ }
+ if (check_transform[prop->proto_id](trns->t_id) < 0)
+ continue;
+
+ /* check data attributes */
+ if (check_attributes[prop->proto_id](trns) != 0)
+ continue;
+
+ p = racoon_calloc(1, sizeof(*p));
+ if (p == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "failed to get buffer.\n");
+ vfree(pbuf);
+ return -1;
+ }
+ p->prop = prop;
+ p->trns = trns;
+
+ /* need to preserve the order */
+ for (q = pair[prop->p_no]; q && q->next; q = q->next)
+ ;
+ if (q && q->prop == p->prop) {
+ for (/*nothing*/; q && q->tnext; q = q->tnext)
+ ;
+ q->tnext = p;
+ } else {
+ if (q)
+ q->next = p;
+ else {
+ pair[prop->p_no] = p;
+ (*num_p)++;
+ }
+ }
+ }
+
+ vfree(pbuf);
+
+ return 0;
+}
+
+/*
+ * make a new SA payload from prop_pair.
+ * NOTE: this function make spi value clear.
+ */
+vchar_t *
+get_sabyproppair(pair, iph1)
+ struct prop_pair *pair;
+ struct ph1handle *iph1;
+{
+ vchar_t *newsa;
+ int newtlen;
+ u_int8_t *np_p = NULL;
+ struct prop_pair *p;
+ int prophlen, trnslen;
+ caddr_t bp;
+
+ newtlen = sizeof(struct ipsecdoi_sa_b);
+ for (p = pair; p; p = p->next) {
+ newtlen += sizeof(struct isakmp_pl_p);
+ newtlen += p->prop->spi_size;
+ newtlen += ntohs(p->trns->h.len);
+ }
+
+ newsa = vmalloc(newtlen);
+ if (newsa == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL, "failed to get newsa.\n");
+ return NULL;
+ }
+ bp = newsa->v;
+
+ ((struct isakmp_gen *)bp)->len = htons(newtlen);
+
+ /* update some of values in SA header */
+ ((struct ipsecdoi_sa_b *)bp)->doi = htonl(iph1->rmconf->doitype);
+ ((struct ipsecdoi_sa_b *)bp)->sit = htonl(iph1->rmconf->sittype);
+ bp += sizeof(struct ipsecdoi_sa_b);
+
+ /* create proposal payloads */
+ for (p = pair; p; p = p->next) {
+ prophlen = sizeof(struct isakmp_pl_p)
+ + p->prop->spi_size;
+ trnslen = ntohs(p->trns->h.len);
+
+ if (np_p)
+ *np_p = ISAKMP_NPTYPE_P;
+
+ /* create proposal */
+
+ memcpy(bp, p->prop, prophlen);
+ ((struct isakmp_pl_p *)bp)->h.np = ISAKMP_NPTYPE_NONE;
+ ((struct isakmp_pl_p *)bp)->h.len = htons(prophlen + trnslen);
+ ((struct isakmp_pl_p *)bp)->num_t = 1;
+ np_p = &((struct isakmp_pl_p *)bp)->h.np;
+ memset(bp + sizeof(struct isakmp_pl_p), 0, p->prop->spi_size);
+ bp += prophlen;
+
+ /* create transform */
+ memcpy(bp, p->trns, trnslen);
+ ((struct isakmp_pl_t *)bp)->h.np = ISAKMP_NPTYPE_NONE;
+ ((struct isakmp_pl_t *)bp)->h.len = htons(trnslen);
+ bp += trnslen;
+ }
+
+ return newsa;
+}
+
+/*
+ * update responder's spi
+ */
+int
+ipsecdoi_updatespi(iph2)
+ struct ph2handle *iph2;
+{
+ struct prop_pair **pair, *p;
+ struct saprop *pp;
+ struct saproto *pr;
+ int i;
+ int error = -1;
+ u_int8_t *spi;
+
+ pair = get_proppair(iph2->sa_ret, IPSECDOI_TYPE_PH2);
+ if (pair == NULL)
+ return -1;
+ for (i = 0; i < MAXPROPPAIRLEN; i++) {
+ if (pair[i])
+ break;
+ }
+ if (i == MAXPROPPAIRLEN || pair[i]->tnext) {
+ /* multiple transform must be filtered by selectph2proposal.*/
+ goto end;
+ }
+
+ pp = iph2->approval;
+
+ /* create proposal payloads */
+ for (p = pair[i]; p; p = p->next) {
+ /*
+ * find a proposal/transform with matching proto_id/t_id.
+ * we have analyzed validity already, in cmpsaprop_alloc().
+ */
+ for (pr = pp->head; pr; pr = pr->next) {
+ if (p->prop->proto_id == pr->proto_id &&
+ p->trns->t_id == pr->head->trns_id) {
+ break;
+ }
+ }
+ if (!pr)
+ goto end;
+
+ /*
+ * XXX SPI bits are left-filled, for use with IPComp.
+ * we should be switching to variable-length spi field...
+ */
+ spi = (u_int8_t *)&pr->spi;
+ spi += sizeof(pr->spi);
+ spi -= pr->spisize;
+ memcpy((caddr_t)p->prop + sizeof(*p->prop), spi, pr->spisize);
+ }
+
+ error = 0;
+end:
+ free_proppair(pair);
+ return error;
+}
+
+/*
+ * make a new SA payload from prop_pair.
+ */
+vchar_t *
+get_sabysaprop(pp0, sa0)
+ struct saprop *pp0;
+ vchar_t *sa0;
+{
+ struct prop_pair **pair = NULL;
+ vchar_t *newsa = NULL;
+ int newtlen;
+ u_int8_t *np_p = NULL;
+ struct prop_pair *p = NULL;
+ struct saprop *pp;
+ struct saproto *pr;
+ struct satrns *tr;
+ int prophlen, trnslen;
+ caddr_t bp;
+ int error = -1;
+
+ /* get proposal pair */
+ pair = get_proppair(sa0, IPSECDOI_TYPE_PH2);
+ if (pair == NULL)
+ goto out;
+
+ newtlen = sizeof(struct ipsecdoi_sa_b);
+ for (pp = pp0; pp; pp = pp->next) {
+
+ if (pair[pp->prop_no] == NULL)
+ goto out;
+
+ for (pr = pp->head; pr; pr = pr->next) {
+ newtlen += (sizeof(struct isakmp_pl_p)
+ + pr->spisize);
+
+ for (tr = pr->head; tr; tr = tr->next) {
+ for (p = pair[pp->prop_no]; p; p = p->tnext) {
+ if (tr->trns_no == p->trns->t_no)
+ break;
+ }
+ if (p == NULL)
+ goto out;
+
+ newtlen += ntohs(p->trns->h.len);
+ }
+ }
+ }
+
+ newsa = vmalloc(newtlen);
+ if (newsa == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL, "failed to get newsa.\n");
+ goto out;
+ }
+ bp = newsa->v;
+
+ /* some of values of SA must be updated in the out of this function */
+ ((struct isakmp_gen *)bp)->len = htons(newtlen);
+ bp += sizeof(struct ipsecdoi_sa_b);
+
+ /* create proposal payloads */
+ for (pp = pp0; pp; pp = pp->next) {
+
+ for (pr = pp->head; pr; pr = pr->next) {
+ prophlen = sizeof(struct isakmp_pl_p)
+ + p->prop->spi_size;
+
+ for (tr = pr->head; tr; tr = tr->next) {
+ for (p = pair[pp->prop_no]; p; p = p->tnext) {
+ if (tr->trns_no == p->trns->t_no)
+ break;
+ }
+ if (p == NULL)
+ goto out;
+
+ trnslen = ntohs(p->trns->h.len);
+
+ if (np_p)
+ *np_p = ISAKMP_NPTYPE_P;
+
+ /* create proposal */
+
+ memcpy(bp, p->prop, prophlen);
+ ((struct isakmp_pl_p *)bp)->h.np = ISAKMP_NPTYPE_NONE;
+ ((struct isakmp_pl_p *)bp)->h.len = htons(prophlen + trnslen);
+ ((struct isakmp_pl_p *)bp)->num_t = 1;
+ np_p = &((struct isakmp_pl_p *)bp)->h.np;
+ bp += prophlen;
+
+ /* create transform */
+ memcpy(bp, p->trns, trnslen);
+ ((struct isakmp_pl_t *)bp)->h.np = ISAKMP_NPTYPE_NONE;
+ ((struct isakmp_pl_t *)bp)->h.len = htons(trnslen);
+ bp += trnslen;
+ }
+ }
+ }
+
+ error = 0;
+out:
+ if (pair != NULL)
+ racoon_free(pair);
+
+ if (error != 0) {
+ if (newsa != NULL) {
+ vfree(newsa);
+ newsa = NULL;
+ }
+ }
+
+ return newsa;
+}
+
+/*
+ * If some error happens then return 0. Although 0 means that lifetime is zero,
+ * such a value should not be accepted.
+ * Also 0 of lifebyte should not be included in a packet although 0 means not
+ * to care of it.
+ */
+static u_int32_t
+ipsecdoi_set_ld(buf)
+ vchar_t *buf;
+{
+ u_int32_t ld;
+
+ if (buf == 0)
+ return 0;
+
+ switch (buf->l) {
+ case 2:
+ ld = ntohs(*(u_int16_t *)buf->v);
+ break;
+ case 4:
+ ld = ntohl(*(u_int32_t *)buf->v);
+ break;
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "length %zu of life duration "
+ "isn't supported.\n", buf->l);
+ return 0;
+ }
+
+ return ld;
+}
+
+/*%%%*/
+/*
+ * check DOI
+ */
+static int
+check_doi(doi)
+ u_int32_t doi;
+{
+ switch (doi) {
+ case IPSEC_DOI:
+ return 0;
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid value of DOI 0x%08x.\n", doi);
+ return -1;
+ }
+ /* NOT REACHED */
+}
+
+/*
+ * check situation
+ */
+static int
+check_situation(sit)
+ u_int32_t sit;
+{
+ switch (sit) {
+ case IPSECDOI_SIT_IDENTITY_ONLY:
+ return 0;
+
+ case IPSECDOI_SIT_SECRECY:
+ case IPSECDOI_SIT_INTEGRITY:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "situation 0x%08x unsupported yet.\n", sit);
+ return -1;
+
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid situation 0x%08x.\n", sit);
+ return -1;
+ }
+ /* NOT REACHED */
+}
+
+/*
+ * check protocol id in main mode
+ */
+static int
+check_prot_main(proto_id)
+ int proto_id;
+{
+ switch (proto_id) {
+ case IPSECDOI_PROTO_ISAKMP:
+ return 0;
+
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "Illegal protocol id=%u.\n", proto_id);
+ return -1;
+ }
+ /* NOT REACHED */
+}
+
+/*
+ * check protocol id in quick mode
+ */
+static int
+check_prot_quick(proto_id)
+ int proto_id;
+{
+ switch (proto_id) {
+ case IPSECDOI_PROTO_IPSEC_AH:
+ case IPSECDOI_PROTO_IPSEC_ESP:
+ return 0;
+
+ case IPSECDOI_PROTO_IPCOMP:
+ return 0;
+
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid protocol id %d.\n", proto_id);
+ return -1;
+ }
+ /* NOT REACHED */
+}
+
+static int
+check_spi_size(proto_id, size)
+ int proto_id, size;
+{
+ switch (proto_id) {
+ case IPSECDOI_PROTO_ISAKMP:
+ if (size != 0) {
+ /* WARNING */
+ plog(LLV_WARNING, LOCATION, NULL,
+ "SPI size isn't zero, but IKE proposal.\n");
+ }
+ return 0;
+
+ case IPSECDOI_PROTO_IPSEC_AH:
+ case IPSECDOI_PROTO_IPSEC_ESP:
+ if (size != 4) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid SPI size=%d for IPSEC proposal.\n",
+ size);
+ return -1;
+ }
+ return 0;
+
+ case IPSECDOI_PROTO_IPCOMP:
+ if (size != 2 && size != 4) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid SPI size=%d for IPCOMP proposal.\n",
+ size);
+ return -1;
+ }
+ return 0;
+
+ default:
+ /* ??? */
+ return -1;
+ }
+ /* NOT REACHED */
+}
+
+/*
+ * check transform ID in ISAKMP.
+ */
+static int
+check_trns_isakmp(t_id)
+ int t_id;
+{
+ switch (t_id) {
+ case IPSECDOI_KEY_IKE:
+ return 0;
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid transform-id=%u in proto_id=%u.\n",
+ t_id, IPSECDOI_KEY_IKE);
+ return -1;
+ }
+ /* NOT REACHED */
+}
+
+/*
+ * check transform ID in AH.
+ */
+static int
+check_trns_ah(t_id)
+ int t_id;
+{
+ switch (t_id) {
+ case IPSECDOI_AH_MD5:
+ case IPSECDOI_AH_SHA:
+ case IPSECDOI_AH_SHA256:
+ case IPSECDOI_AH_SHA384:
+ case IPSECDOI_AH_SHA512:
+ return 0;
+ case IPSECDOI_AH_DES:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "not support transform-id=%u in AH.\n", t_id);
+ return -1;
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid transform-id=%u in AH.\n", t_id);
+ return -1;
+ }
+ /* NOT REACHED */
+}
+
+/*
+ * check transform ID in ESP.
+ */
+static int
+check_trns_esp(t_id)
+ int t_id;
+{
+ switch (t_id) {
+ case IPSECDOI_ESP_DES:
+ case IPSECDOI_ESP_3DES:
+ case IPSECDOI_ESP_NULL:
+ case IPSECDOI_ESP_RC5:
+ case IPSECDOI_ESP_CAST:
+ case IPSECDOI_ESP_BLOWFISH:
+ case IPSECDOI_ESP_AES:
+ case IPSECDOI_ESP_TWOFISH:
+ case IPSECDOI_ESP_CAMELLIA:
+ return 0;
+ case IPSECDOI_ESP_DES_IV32:
+ case IPSECDOI_ESP_DES_IV64:
+ case IPSECDOI_ESP_IDEA:
+ case IPSECDOI_ESP_3IDEA:
+ case IPSECDOI_ESP_RC4:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "not support transform-id=%u in ESP.\n", t_id);
+ return -1;
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid transform-id=%u in ESP.\n", t_id);
+ return -1;
+ }
+ /* NOT REACHED */
+}
+
+/*
+ * check transform ID in IPCOMP.
+ */
+static int
+check_trns_ipcomp(t_id)
+ int t_id;
+{
+ switch (t_id) {
+ case IPSECDOI_IPCOMP_OUI:
+ case IPSECDOI_IPCOMP_DEFLATE:
+ case IPSECDOI_IPCOMP_LZS:
+ return 0;
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid transform-id=%u in IPCOMP.\n", t_id);
+ return -1;
+ }
+ /* NOT REACHED */
+}
+
+/*
+ * check data attributes in IKE.
+ */
+static int
+check_attr_isakmp(trns)
+ struct isakmp_pl_t *trns;
+{
+ struct isakmp_data *d;
+ int tlen;
+ int flag, type;
+ u_int16_t lorv;
+
+ tlen = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t);
+ d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
+
+ while (tlen > 0) {
+ type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
+ flag = ntohs(d->type) & ISAKMP_GEN_MASK;
+ lorv = ntohs(d->lorv);
+
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "type=%s, flag=0x%04x, lorv=%s\n",
+ s_oakley_attr(type), flag,
+ s_oakley_attr_v(type, lorv));
+
+ /*
+ * some of the attributes must be encoded in TV.
+ * see RFC2409 Appendix A "Attribute Classes".
+ */
+ switch (type) {
+ case OAKLEY_ATTR_ENC_ALG:
+ case OAKLEY_ATTR_HASH_ALG:
+ case OAKLEY_ATTR_AUTH_METHOD:
+ case OAKLEY_ATTR_GRP_DESC:
+ case OAKLEY_ATTR_GRP_TYPE:
+ case OAKLEY_ATTR_SA_LD_TYPE:
+ case OAKLEY_ATTR_PRF:
+ case OAKLEY_ATTR_KEY_LEN:
+ case OAKLEY_ATTR_FIELD_SIZE:
+ if (!flag) { /* TLV*/
+ plog(LLV_ERROR, LOCATION, NULL,
+ "oakley attribute %d must be TV.\n",
+ type);
+ return -1;
+ }
+ break;
+ }
+
+ /* sanity check for TLV. length must be specified. */
+ if (!flag && lorv == 0) { /*TLV*/
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid length %d for TLV attribute %d.\n",
+ lorv, type);
+ return -1;
+ }
+
+ switch (type) {
+ case OAKLEY_ATTR_ENC_ALG:
+ if (!alg_oakley_encdef_ok(lorv)) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalied encryption algorithm=%d.\n",
+ lorv);
+ return -1;
+ }
+ break;
+
+ case OAKLEY_ATTR_HASH_ALG:
+ if (!alg_oakley_hashdef_ok(lorv)) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalied hash algorithm=%d.\n",
+ lorv);
+ return -1;
+ }
+ break;
+
+ case OAKLEY_ATTR_AUTH_METHOD:
+ switch (lorv) {
+ case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
+ case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
+#ifdef ENABLE_HYBRID
+ case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
+#if 0 /* Clashes with OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB */
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I:
+#endif
+#endif
+ case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
+ break;
+ case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
+#ifdef ENABLE_HYBRID
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
+ case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
+ case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
+ case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I:
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I:
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
+#endif
+ case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
+ case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "auth method %s isn't supported.\n",
+ s_oakley_attr_method(lorv));
+ return -1;
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid auth method %d.\n",
+ lorv);
+ return -1;
+ }
+ break;
+
+ case OAKLEY_ATTR_GRP_DESC:
+ if (!alg_oakley_dhdef_ok(lorv)) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid DH group %d.\n",
+ lorv);
+ return -1;
+ }
+ break;
+
+ case OAKLEY_ATTR_GRP_TYPE:
+ switch (lorv) {
+ case OAKLEY_ATTR_GRP_TYPE_MODP:
+ break;
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "unsupported DH group type %d.\n",
+ lorv);
+ return -1;
+ }
+ break;
+
+ case OAKLEY_ATTR_GRP_PI:
+ case OAKLEY_ATTR_GRP_GEN_ONE:
+ /* sanity checks? */
+ break;
+
+ case OAKLEY_ATTR_GRP_GEN_TWO:
+ case OAKLEY_ATTR_GRP_CURVE_A:
+ case OAKLEY_ATTR_GRP_CURVE_B:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "attr type=%u isn't supported.\n", type);
+ return -1;
+
+ case OAKLEY_ATTR_SA_LD_TYPE:
+ switch (lorv) {
+ case OAKLEY_ATTR_SA_LD_TYPE_SEC:
+ case OAKLEY_ATTR_SA_LD_TYPE_KB:
+ break;
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid life type %d.\n", lorv);
+ return -1;
+ }
+ break;
+
+ case OAKLEY_ATTR_SA_LD:
+ /* should check the value */
+ break;
+
+ case OAKLEY_ATTR_PRF:
+ case OAKLEY_ATTR_KEY_LEN:
+ break;
+
+ case OAKLEY_ATTR_FIELD_SIZE:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "attr type=%u isn't supported.\n", type);
+ return -1;
+
+ case OAKLEY_ATTR_GRP_ORDER:
+ break;
+
+ case OAKLEY_ATTR_GSS_ID:
+ break;
+
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid attribute type %d.\n", type);
+ return -1;
+ }
+
+ if (flag) {
+ tlen -= sizeof(*d);
+ d = (struct isakmp_data *)((char *)d
+ + sizeof(*d));
+ } else {
+ tlen -= (sizeof(*d) + lorv);
+ d = (struct isakmp_data *)((char *)d
+ + sizeof(*d) + lorv);
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * check data attributes in IPSEC AH/ESP.
+ */
+static int
+check_attr_ah(trns)
+ struct isakmp_pl_t *trns;
+{
+ return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_AH, trns);
+}
+
+static int
+check_attr_esp(trns)
+ struct isakmp_pl_t *trns;
+{
+ return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_ESP, trns);
+}
+
+static int
+check_attr_ipsec(proto_id, trns)
+ int proto_id;
+ struct isakmp_pl_t *trns;
+{
+ struct isakmp_data *d;
+ int tlen;
+ int flag, type = 0;
+ u_int16_t lorv;
+ int attrseen[16]; /* XXX magic number */
+
+ tlen = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t);
+ d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
+ memset(attrseen, 0, sizeof(attrseen));
+
+ while (tlen > 0) {
+ type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
+ flag = ntohs(d->type) & ISAKMP_GEN_MASK;
+ lorv = ntohs(d->lorv);
+
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "type=%s, flag=0x%04x, lorv=%s\n",
+ s_ipsecdoi_attr(type), flag,
+ s_ipsecdoi_attr_v(type, lorv));
+
+ if (type < sizeof(attrseen)/sizeof(attrseen[0]))
+ attrseen[type]++;
+
+ switch (type) {
+ case IPSECDOI_ATTR_ENC_MODE:
+ if (! flag) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "must be TV when ENC_MODE.\n");
+ return -1;
+ }
+
+ switch (lorv) {
+ case IPSECDOI_ATTR_ENC_MODE_TUNNEL:
+ case IPSECDOI_ATTR_ENC_MODE_TRNS:
+ break;
+#ifdef ENABLE_NATT
+ case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC:
+ case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC:
+ case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT:
+ case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT:
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "UDP encapsulation requested\n");
+ break;
+#endif
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid encryption mode=%u.\n",
+ lorv);
+ return -1;
+ }
+ break;
+
+ case IPSECDOI_ATTR_AUTH:
+ if (! flag) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "must be TV when AUTH.\n");
+ return -1;
+ }
+
+ switch (lorv) {
+ case IPSECDOI_ATTR_AUTH_HMAC_MD5:
+ if (proto_id == IPSECDOI_PROTO_IPSEC_AH &&
+ trns->t_id != IPSECDOI_AH_MD5) {
+ahmismatch:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "auth algorithm %u conflicts "
+ "with transform %u.\n",
+ lorv, trns->t_id);
+ return -1;
+ }
+ break;
+ case IPSECDOI_ATTR_AUTH_HMAC_SHA1:
+ if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
+ if (trns->t_id != IPSECDOI_AH_SHA)
+ goto ahmismatch;
+ }
+ break;
+ case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256:
+ if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
+ if (trns->t_id != IPSECDOI_AH_SHA256)
+ goto ahmismatch;
+ }
+ break;
+ case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384:
+ if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
+ if (trns->t_id != IPSECDOI_AH_SHA384)
+ goto ahmismatch;
+ }
+ break;
+ case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512:
+ if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
+ if (trns->t_id != IPSECDOI_AH_SHA512)
+ goto ahmismatch;
+ }
+ break;
+ case IPSECDOI_ATTR_AUTH_DES_MAC:
+ case IPSECDOI_ATTR_AUTH_KPDK:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "auth algorithm %u isn't supported.\n",
+ lorv);
+ return -1;
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid auth algorithm=%u.\n",
+ lorv);
+ return -1;
+ }
+ break;
+
+ case IPSECDOI_ATTR_SA_LD_TYPE:
+ if (! flag) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "must be TV when LD_TYPE.\n");
+ return -1;
+ }
+
+ switch (lorv) {
+ case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
+ case IPSECDOI_ATTR_SA_LD_TYPE_KB:
+ break;
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid life type %d.\n", lorv);
+ return -1;
+ }
+ break;
+
+ case IPSECDOI_ATTR_SA_LD:
+ if (flag) {
+ /* i.e. ISAKMP_GEN_TV */
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "life duration was in TLV.\n");
+ } else {
+ /* i.e. ISAKMP_GEN_TLV */
+ if (lorv == 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid length of LD\n");
+ return -1;
+ }
+ }
+ break;
+
+ case IPSECDOI_ATTR_GRP_DESC:
+ if (! flag) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "must be TV when GRP_DESC.\n");
+ return -1;
+ }
+
+ if (!alg_oakley_dhdef_ok(lorv)) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid group description=%u.\n",
+ lorv);
+ return -1;
+ }
+ break;
+
+ case IPSECDOI_ATTR_KEY_LENGTH:
+ if (! flag) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "must be TV when KEY_LENGTH.\n");
+ return -1;
+ }
+ break;
+
+#ifdef HAVE_SECCTX
+ case IPSECDOI_ATTR_SECCTX:
+ if (flag) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "SECCTX must be in TLV.\n");
+ return -1;
+ }
+ break;
+#endif
+
+ case IPSECDOI_ATTR_KEY_ROUNDS:
+ case IPSECDOI_ATTR_COMP_DICT_SIZE:
+ case IPSECDOI_ATTR_COMP_PRIVALG:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "attr type=%u isn't supported.\n", type);
+ return -1;
+
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid attribute type %d.\n", type);
+ return -1;
+ }
+
+ if (flag) {
+ tlen -= sizeof(*d);
+ d = (struct isakmp_data *)((char *)d
+ + sizeof(*d));
+ } else {
+ tlen -= (sizeof(*d) + lorv);
+ d = (struct isakmp_data *)((caddr_t)d
+ + sizeof(*d) + lorv);
+ }
+ }
+
+ if (proto_id == IPSECDOI_PROTO_IPSEC_AH &&
+ !attrseen[IPSECDOI_ATTR_AUTH]) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "attr AUTH must be present for AH.\n");
+ return -1;
+ }
+
+ if (proto_id == IPSECDOI_PROTO_IPSEC_ESP &&
+ trns->t_id == IPSECDOI_ESP_NULL &&
+ !attrseen[IPSECDOI_ATTR_AUTH]) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "attr AUTH must be present for ESP NULL encryption.\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+check_attr_ipcomp(trns)
+ struct isakmp_pl_t *trns;
+{
+ struct isakmp_data *d;
+ int tlen;
+ int flag, type = 0;
+ u_int16_t lorv;
+ int attrseen[16]; /* XXX magic number */
+
+ tlen = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t);
+ d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t));
+ memset(attrseen, 0, sizeof(attrseen));
+
+ while (tlen > 0) {
+ type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
+ flag = ntohs(d->type) & ISAKMP_GEN_MASK;
+ lorv = ntohs(d->lorv);
+
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "type=%d, flag=0x%04x, lorv=0x%04x\n",
+ type, flag, lorv);
+
+ if (type < sizeof(attrseen)/sizeof(attrseen[0]))
+ attrseen[type]++;
+
+ switch (type) {
+ case IPSECDOI_ATTR_ENC_MODE:
+ if (! flag) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "must be TV when ENC_MODE.\n");
+ return -1;
+ }
+
+ switch (lorv) {
+ case IPSECDOI_ATTR_ENC_MODE_TUNNEL:
+ case IPSECDOI_ATTR_ENC_MODE_TRNS:
+ break;
+#ifdef ENABLE_NATT
+ case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC:
+ case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC:
+ case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT:
+ case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT:
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "UDP encapsulation requested\n");
+ break;
+#endif
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid encryption mode=%u.\n",
+ lorv);
+ return -1;
+ }
+ break;
+
+ case IPSECDOI_ATTR_SA_LD_TYPE:
+ if (! flag) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "must be TV when LD_TYPE.\n");
+ return -1;
+ }
+
+ switch (lorv) {
+ case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
+ case IPSECDOI_ATTR_SA_LD_TYPE_KB:
+ break;
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid life type %d.\n", lorv);
+ return -1;
+ }
+ break;
+
+ case IPSECDOI_ATTR_SA_LD:
+ if (flag) {
+ /* i.e. ISAKMP_GEN_TV */
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "life duration was in TLV.\n");
+ } else {
+ /* i.e. ISAKMP_GEN_TLV */
+ if (lorv == 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid length of LD\n");
+ return -1;
+ }
+ }
+ break;
+
+ case IPSECDOI_ATTR_GRP_DESC:
+ if (! flag) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "must be TV when GRP_DESC.\n");
+ return -1;
+ }
+
+ if (!alg_oakley_dhdef_ok(lorv)) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid group description=%u.\n",
+ lorv);
+ return -1;
+ }
+ break;
+
+ case IPSECDOI_ATTR_AUTH:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid attr type=%u.\n", type);
+ return -1;
+
+ case IPSECDOI_ATTR_KEY_LENGTH:
+ case IPSECDOI_ATTR_KEY_ROUNDS:
+ case IPSECDOI_ATTR_COMP_DICT_SIZE:
+ case IPSECDOI_ATTR_COMP_PRIVALG:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "attr type=%u isn't supported.\n", type);
+ return -1;
+
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid attribute type %d.\n", type);
+ return -1;
+ }
+
+ if (flag) {
+ tlen -= sizeof(*d);
+ d = (struct isakmp_data *)((char *)d
+ + sizeof(*d));
+ } else {
+ tlen -= (sizeof(*d) + lorv);
+ d = (struct isakmp_data *)((caddr_t)d
+ + sizeof(*d) + lorv);
+ }
+ }
+
+#if 0
+ if (proto_id == IPSECDOI_PROTO_IPCOMP &&
+ !attrseen[IPSECDOI_ATTR_AUTH]) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "attr AUTH must be present for AH.\n", type);
+ return -1;
+ }
+#endif
+
+ return 0;
+}
+
+/* %%% */
+/*
+ * create phase1 proposal from remote configuration.
+ * NOT INCLUDING isakmp general header of SA payload
+ */
+vchar_t *
+ipsecdoi_setph1proposal(rmconf, props)
+ struct remoteconf *rmconf;
+ struct isakmpsa *props;
+{
+ vchar_t *mysa;
+ int sablen;
+
+ /* count total size of SA minus isakmp general header */
+ /* not including isakmp general header of SA payload */
+ sablen = sizeof(struct ipsecdoi_sa_b);
+ sablen += setph1prop(props, NULL);
+
+ mysa = vmalloc(sablen);
+ if (mysa == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "failed to allocate my sa buffer\n");
+ return NULL;
+ }
+
+ /* create SA payload */
+ /* not including isakmp general header */
+ ((struct ipsecdoi_sa_b *)mysa->v)->doi = htonl(rmconf->doitype);
+ ((struct ipsecdoi_sa_b *)mysa->v)->sit = htonl(rmconf->sittype);
+
+ (void)setph1prop(props, mysa->v + sizeof(struct ipsecdoi_sa_b));
+
+ return mysa;
+}
+
+static int
+setph1prop(props, buf)
+ struct isakmpsa *props;
+ caddr_t buf;
+{
+ struct isakmp_pl_p *prop = NULL;
+ struct isakmpsa *s = NULL;
+ int proplen, trnslen;
+ u_int8_t *np_t; /* pointer next trns type in previous header */
+ int trns_num;
+ caddr_t p = buf;
+
+ proplen = sizeof(*prop);
+ if (buf) {
+ /* create proposal */
+ prop = (struct isakmp_pl_p *)p;
+ prop->h.np = ISAKMP_NPTYPE_NONE;
+ prop->p_no = props->prop_no;
+ prop->proto_id = IPSECDOI_PROTO_ISAKMP;
+ prop->spi_size = 0;
+ p += sizeof(*prop);
+ }
+
+ np_t = NULL;
+ trns_num = 0;
+
+ for (s = props; s != NULL; s = s->next) {
+ if (np_t)
+ *np_t = ISAKMP_NPTYPE_T;
+
+ trnslen = setph1trns(s, p);
+ proplen += trnslen;
+ if (buf) {
+ /* save buffer to pre-next payload */
+ np_t = &((struct isakmp_pl_t *)p)->h.np;
+ p += trnslen;
+
+ /* count up transform length */
+ trns_num++;
+ }
+ }
+
+ /* update proposal length */
+ if (buf) {
+ prop->h.len = htons(proplen);
+ prop->num_t = trns_num;
+ }
+
+ return proplen;
+}
+
+static int
+setph1trns(sa, buf)
+ struct isakmpsa *sa;
+ caddr_t buf;
+{
+ struct isakmp_pl_t *trns = NULL;
+ int trnslen, attrlen;
+ caddr_t p = buf;
+
+ trnslen = sizeof(*trns);
+ if (buf) {
+ /* create transform */
+ trns = (struct isakmp_pl_t *)p;
+ trns->h.np = ISAKMP_NPTYPE_NONE;
+ trns->t_no = sa->trns_no;
+ trns->t_id = IPSECDOI_KEY_IKE;
+ p += sizeof(*trns);
+ }
+
+ attrlen = setph1attr(sa, p);
+ trnslen += attrlen;
+ if (buf)
+ p += attrlen;
+
+ if (buf)
+ trns->h.len = htons(trnslen);
+
+ return trnslen;
+}
+
+static int
+setph1attr(sa, buf)
+ struct isakmpsa *sa;
+ caddr_t buf;
+{
+ caddr_t p = buf;
+ int attrlen = 0;
+
+ if (sa->lifetime) {
+ u_int32_t lifetime = htonl((u_int32_t)sa->lifetime);
+
+ attrlen += sizeof(struct isakmp_data)
+ + sizeof(struct isakmp_data);
+ if (sa->lifetime > 0xffff)
+ attrlen += sizeof(lifetime);
+ if (buf) {
+ p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD_TYPE,
+ OAKLEY_ATTR_SA_LD_TYPE_SEC);
+ if (sa->lifetime > 0xffff) {
+ p = isakmp_set_attr_v(p, OAKLEY_ATTR_SA_LD,
+ (caddr_t)&lifetime,
+ sizeof(lifetime));
+ } else {
+ p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD,
+ sa->lifetime);
+ }
+ }
+ }
+
+ if (sa->lifebyte) {
+ u_int32_t lifebyte = htonl((u_int32_t)sa->lifebyte);
+
+ attrlen += sizeof(struct isakmp_data)
+ + sizeof(struct isakmp_data);
+ if (sa->lifebyte > 0xffff)
+ attrlen += sizeof(lifebyte);
+ if (buf) {
+ p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD_TYPE,
+ OAKLEY_ATTR_SA_LD_TYPE_KB);
+ if (sa->lifebyte > 0xffff) {
+ p = isakmp_set_attr_v(p, OAKLEY_ATTR_SA_LD,
+ (caddr_t)&lifebyte,
+ sizeof(lifebyte));
+ } else {
+ p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD,
+ sa->lifebyte);
+ }
+ }
+ }
+
+ if (sa->enctype) {
+ attrlen += sizeof(struct isakmp_data);
+ if (buf)
+ p = isakmp_set_attr_l(p, OAKLEY_ATTR_ENC_ALG, sa->enctype);
+ }
+ if (sa->encklen) {
+ attrlen += sizeof(struct isakmp_data);
+ if (buf)
+ p = isakmp_set_attr_l(p, OAKLEY_ATTR_KEY_LEN, sa->encklen);
+ }
+ if (sa->authmethod) {
+ int authmethod;
+
+#ifdef ENABLE_HYBRID
+ authmethod = switch_authmethod(sa->authmethod);
+#else
+ authmethod = sa->authmethod;
+#endif
+ attrlen += sizeof(struct isakmp_data);
+ if (buf)
+ p = isakmp_set_attr_l(p, OAKLEY_ATTR_AUTH_METHOD, authmethod);
+ }
+ if (sa->hashtype) {
+ attrlen += sizeof(struct isakmp_data);
+ if (buf)
+ p = isakmp_set_attr_l(p, OAKLEY_ATTR_HASH_ALG, sa->hashtype);
+ }
+ switch (sa->dh_group) {
+ case OAKLEY_ATTR_GRP_DESC_MODP768:
+ case OAKLEY_ATTR_GRP_DESC_MODP1024:
+ case OAKLEY_ATTR_GRP_DESC_MODP1536:
+ case OAKLEY_ATTR_GRP_DESC_MODP2048:
+ case OAKLEY_ATTR_GRP_DESC_MODP3072:
+ case OAKLEY_ATTR_GRP_DESC_MODP4096:
+ case OAKLEY_ATTR_GRP_DESC_MODP6144:
+ case OAKLEY_ATTR_GRP_DESC_MODP8192:
+ /* don't attach group type for known groups */
+ attrlen += sizeof(struct isakmp_data);
+ if (buf) {
+ p = isakmp_set_attr_l(p, OAKLEY_ATTR_GRP_DESC,
+ sa->dh_group);
+ }
+ break;
+ case OAKLEY_ATTR_GRP_DESC_EC2N155:
+ case OAKLEY_ATTR_GRP_DESC_EC2N185:
+ /* don't attach group type for known groups */
+ attrlen += sizeof(struct isakmp_data);
+ if (buf) {
+ p = isakmp_set_attr_l(p, OAKLEY_ATTR_GRP_TYPE,
+ OAKLEY_ATTR_GRP_TYPE_EC2N);
+ }
+ break;
+ case 0:
+ default:
+ break;
+ }
+
+#ifdef HAVE_GSSAPI
+ if (sa->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB &&
+ sa->gssid != NULL) {
+ attrlen += sizeof(struct isakmp_data);
+ /*
+ * Older versions of racoon just placed the ISO-Latin-1
+ * string on the wire directly. Check to see if we are
+ * configured to be compatible with this behavior. Otherwise,
+ * we encode the GSS ID as UTF-16LE for Windows 2000
+ * compatibility, which requires twice the number of octets.
+ */
+ if (lcconf->gss_id_enc == LC_GSSENC_LATIN1)
+ attrlen += sa->gssid->l;
+ else
+ attrlen += sa->gssid->l * 2;
+ if (buf) {
+ plog(LLV_DEBUG, LOCATION, NULL, "gss id attr: len %zu, "
+ "val '%.*s'\n", sa->gssid->l, (int)sa->gssid->l,
+ sa->gssid->v);
+ if (lcconf->gss_id_enc == LC_GSSENC_LATIN1) {
+ p = isakmp_set_attr_v(p, OAKLEY_ATTR_GSS_ID,
+ (caddr_t)sa->gssid->v,
+ sa->gssid->l);
+ } else {
+ size_t dstleft = sa->gssid->l * 2;
+ size_t srcleft = sa->gssid->l;
+ const char *src = (const char *)sa->gssid->v;
+ char *odst, *dst = racoon_malloc(dstleft);
+ iconv_t cd;
+ size_t rv;
+
+ cd = iconv_open("utf-16le", "latin1");
+ if (cd == (iconv_t) -1) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "unable to initialize "
+ "latin1 -> utf-16le "
+ "converstion descriptor: %s\n",
+ strerror(errno));
+ attrlen -= sa->gssid->l * 2;
+ goto gssid_done;
+ }
+ odst = dst;
+ rv = iconv(cd, (__iconv_const char **)&src,
+ &srcleft, &dst, &dstleft);
+ if (rv != 0) {
+ if (rv == -1) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "unable to convert GSS ID "
+ "from latin1 -> utf-16le: "
+ "%s\n", strerror(errno));
+ } else {
+ /* should never happen */
+ plog(LLV_ERROR, LOCATION, NULL,
+ "%zd character%s in GSS ID "
+ "cannot be represented "
+ "in utf-16le\n",
+ rv, rv == 1 ? "" : "s");
+ }
+ (void) iconv_close(cd);
+ attrlen -= sa->gssid->l * 2;
+ goto gssid_done;
+ }
+ (void) iconv_close(cd);
+
+ /* XXX Check srcleft and dstleft? */
+
+ p = isakmp_set_attr_v(p, OAKLEY_ATTR_GSS_ID,
+ odst, sa->gssid->l * 2);
+
+ racoon_free(odst);
+ }
+ }
+ }
+ gssid_done:
+#endif /* HAVE_GSSAPI */
+
+ return attrlen;
+}
+
+static vchar_t *
+setph2proposal0(iph2, pp, pr)
+ const struct ph2handle *iph2;
+ const struct saprop *pp;
+ const struct saproto *pr;
+{
+ vchar_t *p;
+ struct isakmp_pl_p *prop;
+ struct isakmp_pl_t *trns;
+ struct satrns *tr;
+ int attrlen;
+ size_t trnsoff;
+ caddr_t x0, x;
+ u_int8_t *np_t; /* pointer next trns type in previous header */
+ const u_int8_t *spi;
+#ifdef HAVE_SECCTX
+ int truectxlen = 0;
+#endif
+
+ p = vmalloc(sizeof(*prop) + sizeof(pr->spi));
+ if (p == NULL)
+ return NULL;
+
+ /* create proposal */
+ prop = (struct isakmp_pl_p *)p->v;
+ prop->h.np = ISAKMP_NPTYPE_NONE;
+ prop->p_no = pp->prop_no;
+ prop->proto_id = pr->proto_id;
+ prop->num_t = 1;
+
+ spi = (const u_int8_t *)&pr->spi;
+ switch (pr->proto_id) {
+ case IPSECDOI_PROTO_IPCOMP:
+ /*
+ * draft-shacham-ippcp-rfc2393bis-05.txt:
+ * construct 16bit SPI (CPI).
+ * XXX we may need to provide a configuration option to
+ * generate 32bit SPI. otherwise we cannot interoeprate
+ * with nodes that uses 32bit SPI, in case we are initiator.
+ */
+ prop->spi_size = sizeof(u_int16_t);
+ spi += sizeof(pr->spi) - sizeof(u_int16_t);
+ p->l -= sizeof(pr->spi);
+ p->l += sizeof(u_int16_t);
+ break;
+ default:
+ prop->spi_size = sizeof(pr->spi);
+ break;
+ }
+ memcpy(prop + 1, spi, prop->spi_size);
+
+ /* create transform */
+ trnsoff = sizeof(*prop) + prop->spi_size;
+ np_t = NULL;
+
+ for (tr = pr->head; tr; tr = tr->next) {
+
+ switch (pr->proto_id) {
+ case IPSECDOI_PROTO_IPSEC_ESP:
+ /*
+ * don't build a null encryption
+ * with no authentication transform.
+ */
+ if (tr->trns_id == IPSECDOI_ESP_NULL &&
+ tr->authtype == IPSECDOI_ATTR_AUTH_NONE)
+ continue;
+ break;
+ }
+
+ if (np_t) {
+ *np_t = ISAKMP_NPTYPE_T;
+ prop->num_t++;
+ }
+
+ /* get attribute length */
+ attrlen = 0;
+ if (pp->lifetime) {
+ attrlen += sizeof(struct isakmp_data)
+ + sizeof(struct isakmp_data);
+ if (pp->lifetime > 0xffff)
+ attrlen += sizeof(u_int32_t);
+ }
+ if (pp->lifebyte && pp->lifebyte != IPSECDOI_ATTR_SA_LD_KB_MAX) {
+ attrlen += sizeof(struct isakmp_data)
+ + sizeof(struct isakmp_data);
+ if (pp->lifebyte > 0xffff)
+ attrlen += sizeof(u_int32_t);
+ }
+ attrlen += sizeof(struct isakmp_data); /* enc mode */
+ if (tr->encklen)
+ attrlen += sizeof(struct isakmp_data);
+
+ switch (pr->proto_id) {
+ case IPSECDOI_PROTO_IPSEC_ESP:
+ /* non authentication mode ? */
+ if (tr->authtype != IPSECDOI_ATTR_AUTH_NONE)
+ attrlen += sizeof(struct isakmp_data);
+ break;
+ case IPSECDOI_PROTO_IPSEC_AH:
+ if (tr->authtype == IPSECDOI_ATTR_AUTH_NONE) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "no authentication algorithm found "
+ "but protocol is AH.\n");
+ vfree(p);
+ return NULL;
+ }
+ attrlen += sizeof(struct isakmp_data);
+ break;
+ case IPSECDOI_PROTO_IPCOMP:
+ break;
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid protocol: %d\n", pr->proto_id);
+ vfree(p);
+ return NULL;
+ }
+
+ if (alg_oakley_dhdef_ok(iph2->sainfo->pfs_group))
+ attrlen += sizeof(struct isakmp_data);
+
+#ifdef HAVE_SECCTX
+ /* ctx_str is defined as char ctx_str[MAX_CTXSTR_SIZ].
+ * The string may be smaller than MAX_CTXSTR_SIZ.
+ */
+ if (*pp->sctx.ctx_str) {
+ truectxlen = sizeof(struct security_ctx) -
+ (MAX_CTXSTR_SIZE - pp->sctx.ctx_strlen);
+ attrlen += sizeof(struct isakmp_data) + truectxlen;
+ }
+#endif /* HAVE_SECCTX */
+
+ p = vrealloc(p, p->l + sizeof(*trns) + attrlen);
+ if (p == NULL)
+ return NULL;
+ prop = (struct isakmp_pl_p *)p->v;
+
+ /* set transform's values */
+ trns = (struct isakmp_pl_t *)(p->v + trnsoff);
+ trns->h.np = ISAKMP_NPTYPE_NONE;
+ trns->t_no = tr->trns_no;
+ trns->t_id = tr->trns_id;
+
+ /* set attributes */
+ x = x0 = p->v + trnsoff + sizeof(*trns);
+
+ if (pp->lifetime) {
+ x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD_TYPE,
+ IPSECDOI_ATTR_SA_LD_TYPE_SEC);
+ if (pp->lifetime > 0xffff) {
+ u_int32_t v = htonl((u_int32_t)pp->lifetime);
+ x = isakmp_set_attr_v(x, IPSECDOI_ATTR_SA_LD,
+ (caddr_t)&v, sizeof(v));
+ } else {
+ x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD,
+ pp->lifetime);
+ }
+ }
+
+ if (pp->lifebyte && pp->lifebyte != IPSECDOI_ATTR_SA_LD_KB_MAX) {
+ x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD_TYPE,
+ IPSECDOI_ATTR_SA_LD_TYPE_KB);
+ if (pp->lifebyte > 0xffff) {
+ u_int32_t v = htonl((u_int32_t)pp->lifebyte);
+ x = isakmp_set_attr_v(x, IPSECDOI_ATTR_SA_LD,
+ (caddr_t)&v, sizeof(v));
+ } else {
+ x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD,
+ pp->lifebyte);
+ }
+ }
+
+ x = isakmp_set_attr_l(x, IPSECDOI_ATTR_ENC_MODE, pr->encmode);
+
+ if (tr->encklen)
+ x = isakmp_set_attr_l(x, IPSECDOI_ATTR_KEY_LENGTH, tr->encklen);
+
+ /* mandatory check has done above. */
+ if ((pr->proto_id == IPSECDOI_PROTO_IPSEC_ESP && tr->authtype != IPSECDOI_ATTR_AUTH_NONE)
+ || pr->proto_id == IPSECDOI_PROTO_IPSEC_AH)
+ x = isakmp_set_attr_l(x, IPSECDOI_ATTR_AUTH, tr->authtype);
+
+ if (alg_oakley_dhdef_ok(iph2->sainfo->pfs_group))
+ x = isakmp_set_attr_l(x, IPSECDOI_ATTR_GRP_DESC,
+ iph2->sainfo->pfs_group);
+
+#ifdef HAVE_SECCTX
+ if (*pp->sctx.ctx_str) {
+ struct security_ctx secctx;
+ secctx = pp->sctx;
+ secctx.ctx_strlen = htons(pp->sctx.ctx_strlen);
+ x = isakmp_set_attr_v(x, IPSECDOI_ATTR_SECCTX,
+ (caddr_t)&secctx, truectxlen);
+ }
+#endif
+ /* update length of this transform. */
+ trns = (struct isakmp_pl_t *)(p->v + trnsoff);
+ trns->h.len = htons(sizeof(*trns) + attrlen);
+
+ /* save buffer to pre-next payload */
+ np_t = &trns->h.np;
+
+ trnsoff += (sizeof(*trns) + attrlen);
+ }
+
+ if (np_t == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "no suitable proposal was created.\n");
+ return NULL;
+ }
+
+ /* update length of this protocol. */
+ prop->h.len = htons(p->l);
+
+ return p;
+}
+
+/*
+ * create phase2 proposal from policy configuration.
+ * NOT INCLUDING isakmp general header of SA payload.
+ * This function is called by initiator only.
+ */
+int
+ipsecdoi_setph2proposal(iph2)
+ struct ph2handle *iph2;
+{
+ struct saprop *proposal, *a;
+ struct saproto *b = NULL;
+ vchar_t *q;
+ struct ipsecdoi_sa_b *sab;
+ struct isakmp_pl_p *prop;
+ size_t propoff; /* for previous field of type of next payload. */
+
+ proposal = iph2->proposal;
+
+ iph2->sa = vmalloc(sizeof(*sab));
+ if (iph2->sa == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "failed to allocate my sa buffer\n");
+ return -1;
+ }
+
+ /* create SA payload */
+ sab = (struct ipsecdoi_sa_b *)iph2->sa->v;
+ sab->doi = htonl(IPSEC_DOI);
+ sab->sit = htonl(IPSECDOI_SIT_IDENTITY_ONLY); /* XXX configurable ? */
+
+ prop = NULL;
+ propoff = 0;
+ for (a = proposal; a; a = a->next) {
+ for (b = a->head; b; b = b->next) {
+#ifdef ENABLE_NATT
+ if (iph2->ph1->natt_flags & NAT_DETECTED) {
+ int udp_diff = iph2->ph1->natt_options->mode_udp_diff;
+ plog (LLV_INFO, LOCATION, NULL,
+ "NAT detected -> UDP encapsulation "
+ "(ENC_MODE %d->%d).\n",
+ b->encmode,
+ b->encmode+udp_diff);
+ /* Tunnel -> UDP-Tunnel, Transport -> UDP_Transport */
+ b->encmode += udp_diff;
+ b->udp_encap = 1;
+ }
+#endif
+
+ q = setph2proposal0(iph2, a, b);
+ if (q == NULL) {
+ VPTRINIT(iph2->sa);
+ return -1;
+ }
+
+ iph2->sa = vrealloc(iph2->sa, iph2->sa->l + q->l);
+ if (iph2->sa == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "failed to allocate my sa buffer\n");
+ if (q)
+ vfree(q);
+ return -1;
+ }
+ memcpy(iph2->sa->v + iph2->sa->l - q->l, q->v, q->l);
+ if (propoff != 0) {
+ prop = (struct isakmp_pl_p *)(iph2->sa->v +
+ propoff);
+ prop->h.np = ISAKMP_NPTYPE_P;
+ }
+ propoff = iph2->sa->l - q->l;
+
+ vfree(q);
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * return 1 if all of the given protocols are transport mode.
+ */
+int
+ipsecdoi_transportmode(pp)
+ struct saprop *pp;
+{
+ struct saproto *pr = NULL;
+
+ for (; pp; pp = pp->next) {
+ for (pr = pp->head; pr; pr = pr->next) {
+ if (pr->encmode != IPSECDOI_ATTR_ENC_MODE_TRNS)
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+int
+ipsecdoi_get_defaultlifetime()
+{
+ return IPSECDOI_ATTR_SA_LD_SEC_DEFAULT;
+}
+
+int
+ipsecdoi_checkalgtypes(proto_id, enc, auth, comp)
+ int proto_id, enc, auth, comp;
+{
+#define TMPALGTYPE2STR(n) s_algtype(algclass_ipsec_##n, n)
+ switch (proto_id) {
+ case IPSECDOI_PROTO_IPSEC_ESP:
+ if (enc == 0 || comp != 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "illegal algorithm defined "
+ "ESP enc=%s auth=%s comp=%s.\n",
+ TMPALGTYPE2STR(enc),
+ TMPALGTYPE2STR(auth),
+ TMPALGTYPE2STR(comp));
+ return -1;
+ }
+ break;
+ case IPSECDOI_PROTO_IPSEC_AH:
+ if (enc != 0 || auth == 0 || comp != 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "illegal algorithm defined "
+ "AH enc=%s auth=%s comp=%s.\n",
+ TMPALGTYPE2STR(enc),
+ TMPALGTYPE2STR(auth),
+ TMPALGTYPE2STR(comp));
+ return -1;
+ }
+ break;
+ case IPSECDOI_PROTO_IPCOMP:
+ if (enc != 0 || auth != 0 || comp == 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "illegal algorithm defined "
+ "IPcomp enc=%s auth=%s comp=%s.\n",
+ TMPALGTYPE2STR(enc),
+ TMPALGTYPE2STR(auth),
+ TMPALGTYPE2STR(comp));
+ return -1;
+ }
+ break;
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid ipsec protocol %d\n", proto_id);
+ return -1;
+ }
+#undef TMPALGTYPE2STR
+ return 0;
+}
+
+int
+ipproto2doi(proto)
+ int proto;
+{
+ switch (proto) {
+ case IPPROTO_AH:
+ return IPSECDOI_PROTO_IPSEC_AH;
+ case IPPROTO_ESP:
+ return IPSECDOI_PROTO_IPSEC_ESP;
+ case IPPROTO_IPCOMP:
+ return IPSECDOI_PROTO_IPCOMP;
+ }
+ return -1; /* XXX */
+}
+
+int
+doi2ipproto(proto)
+ int proto;
+{
+ switch (proto) {
+ case IPSECDOI_PROTO_IPSEC_AH:
+ return IPPROTO_AH;
+ case IPSECDOI_PROTO_IPSEC_ESP:
+ return IPPROTO_ESP;
+ case IPSECDOI_PROTO_IPCOMP:
+ return IPPROTO_IPCOMP;
+ }
+ return -1; /* XXX */
+}
+
+/*
+ * Check if a subnet id is valid for comparison
+ * with an address id ( address length mask )
+ * and compare them
+ * Return value
+ * = 0 for match
+ * = 1 for mismatch
+ */
+
+int
+ipsecdoi_subnetisaddr_v4( subnet, address )
+ const vchar_t *subnet;
+ const vchar_t *address;
+{
+ struct in_addr *mask;
+
+ if (address->l != sizeof(struct in_addr))
+ return 1;
+
+ if (subnet->l != (sizeof(struct in_addr)*2))
+ return 1;
+
+ mask = (struct in_addr*)(subnet->v + sizeof(struct in_addr));
+
+ if (mask->s_addr!=0xffffffff)
+ return 1;
+
+ return memcmp(subnet->v,address->v,address->l);
+}
+
+#ifdef INET6
+
+int
+ipsecdoi_subnetisaddr_v6( subnet, address )
+ const vchar_t *subnet;
+ const vchar_t *address;
+{
+ struct in6_addr *mask;
+ int i;
+
+ if (address->l != sizeof(struct in6_addr))
+ return 1;
+
+ if (subnet->l != (sizeof(struct in6_addr)*2))
+ return 1;
+
+ mask = (struct in6_addr*)(subnet->v + sizeof(struct in6_addr));
+
+ for (i=0; i<16; i++)
+ if(mask->s6_addr[i]!=0xff)
+ return 1;
+
+ return memcmp(subnet->v,address->v,address->l);
+}
+
+#endif
+
+/*
+ * Check and Compare two IDs
+ * - specify 0 for exact if wildcards are allowed
+ * Return value
+ * = 0 for match
+ * = 1 for misatch
+ * = -1 for integrity error
+ */
+
+int
+ipsecdoi_chkcmpids( idt, ids, exact )
+ const vchar_t *idt; /* id cmp target */
+ const vchar_t *ids; /* id cmp source */
+ int exact;
+{
+ struct ipsecdoi_id_b *id_bt;
+ struct ipsecdoi_id_b *id_bs;
+ vchar_t ident_t;
+ vchar_t ident_s;
+ int result;
+
+ /* handle wildcard IDs */
+
+ if (idt == NULL || ids == NULL)
+ {
+ if( !exact )
+ {
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "check and compare ids : values matched (ANONYMOUS)\n" );
+ return 0;
+ }
+ else
+ {
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "check and compare ids : value mismatch (ANONYMOUS)\n" );
+ return -1;
+ }
+ }
+
+ /* make sure the ids are of the same type */
+
+ id_bt = (struct ipsecdoi_id_b *) idt->v;
+ id_bs = (struct ipsecdoi_id_b *) ids->v;
+
+ ident_t.v = idt->v + sizeof(*id_bt);
+ ident_t.l = idt->l - sizeof(*id_bt);
+ ident_s.v = ids->v + sizeof(*id_bs);
+ ident_s.l = ids->l - sizeof(*id_bs);
+
+ if (id_bs->type != id_bt->type)
+ {
+ /*
+ * special exception for comparing
+ * address to subnet id types when
+ * the netmask is address length
+ */
+
+ if ((id_bs->type == IPSECDOI_ID_IPV4_ADDR)&&
+ (id_bt->type == IPSECDOI_ID_IPV4_ADDR_SUBNET)) {
+ result = ipsecdoi_subnetisaddr_v4(&ident_t,&ident_s);
+ goto cmpid_result;
+ }
+
+ if ((id_bs->type == IPSECDOI_ID_IPV4_ADDR_SUBNET)&&
+ (id_bt->type == IPSECDOI_ID_IPV4_ADDR)) {
+ result = ipsecdoi_subnetisaddr_v4(&ident_s,&ident_t);
+ goto cmpid_result;
+ }
+
+#ifdef INET6
+ if ((id_bs->type == IPSECDOI_ID_IPV6_ADDR)&&
+ (id_bt->type == IPSECDOI_ID_IPV6_ADDR_SUBNET)) {
+ result = ipsecdoi_subnetisaddr_v6(&ident_t,&ident_s);
+ goto cmpid_result;
+ }
+
+ if ((id_bs->type == IPSECDOI_ID_IPV6_ADDR_SUBNET)&&
+ (id_bt->type == IPSECDOI_ID_IPV6_ADDR)) {
+ result = ipsecdoi_subnetisaddr_v6(&ident_s,&ident_t);
+ goto cmpid_result;
+ }
+#endif
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "check and compare ids : id type mismatch %s != %s\n",
+ s_ipsecdoi_ident(id_bs->type),
+ s_ipsecdoi_ident(id_bt->type));
+
+ return 1;
+ }
+
+ if(id_bs->proto_id != id_bt->proto_id){
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "check and compare ids : proto_id mismatch %d != %d\n",
+ id_bs->proto_id, id_bt->proto_id);
+
+ return 1;
+ }
+
+ /* compare the ID data. */
+
+ switch (id_bt->type) {
+ case IPSECDOI_ID_DER_ASN1_DN:
+ case IPSECDOI_ID_DER_ASN1_GN:
+ /* compare asn1 ids */
+ result = eay_cmp_asn1dn(&ident_t, &ident_s);
+ goto cmpid_result;
+
+ case IPSECDOI_ID_IPV4_ADDR:
+ /* validate lengths */
+ if ((ident_t.l != sizeof(struct in_addr))||
+ (ident_s.l != sizeof(struct in_addr)))
+ goto cmpid_invalid;
+ break;
+
+ case IPSECDOI_ID_IPV4_ADDR_SUBNET:
+ case IPSECDOI_ID_IPV4_ADDR_RANGE:
+ /* validate lengths */
+ if ((ident_t.l != (sizeof(struct in_addr)*2))||
+ (ident_s.l != (sizeof(struct in_addr)*2)))
+ goto cmpid_invalid;
+ break;
+
+#ifdef INET6
+ case IPSECDOI_ID_IPV6_ADDR:
+ /* validate lengths */
+ if ((ident_t.l != sizeof(struct in6_addr))||
+ (ident_s.l != sizeof(struct in6_addr)))
+ goto cmpid_invalid;
+ break;
+
+ case IPSECDOI_ID_IPV6_ADDR_SUBNET:
+ case IPSECDOI_ID_IPV6_ADDR_RANGE:
+ /* validate lengths */
+ if ((ident_t.l != (sizeof(struct in6_addr)*2))||
+ (ident_s.l != (sizeof(struct in6_addr)*2)))
+ goto cmpid_invalid;
+ break;
+#endif
+ case IPSECDOI_ID_FQDN:
+ case IPSECDOI_ID_USER_FQDN:
+ case IPSECDOI_ID_KEY_ID:
+ break;
+
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "Unhandled id type %i specified for comparison\n",
+ id_bt->type);
+ return -1;
+ }
+
+ /* validate matching data and length */
+ if (ident_t.l == ident_s.l)
+ result = memcmp(ident_t.v,ident_s.v,ident_t.l);
+ else
+ result = 1;
+
+cmpid_result:
+
+ /* debug level output */
+ if(loglevel >= LLV_DEBUG) {
+ char *idstrt = ipsecdoi_id2str(idt);
+ char *idstrs = ipsecdoi_id2str(ids);
+
+ if (!result)
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "check and compare ids : values matched (%s)\n",
+ s_ipsecdoi_ident(id_bs->type) );
+ else
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "check and compare ids : value mismatch (%s)\n",
+ s_ipsecdoi_ident(id_bs->type));
+
+ plog(LLV_DEBUG, LOCATION, NULL, "cmpid target: \'%s\'\n", idstrt );
+ plog(LLV_DEBUG, LOCATION, NULL, "cmpid source: \'%s\'\n", idstrs );
+
+ racoon_free(idstrs);
+ racoon_free(idstrt);
+ }
+
+ /* return result */
+ if( !result )
+ return 0;
+ else
+ return 1;
+
+cmpid_invalid:
+
+ /* id integrity error */
+ plog(LLV_DEBUG, LOCATION, NULL, "check and compare ids : %s integrity error\n",
+ s_ipsecdoi_ident(id_bs->type));
+ plog(LLV_DEBUG, LOCATION, NULL, "cmpid target: length = \'%zu\'\n", ident_t.l );
+ plog(LLV_DEBUG, LOCATION, NULL, "cmpid source: length = \'%zu\'\n", ident_s.l );
+
+ return -1;
+}
+
+/*
+ * check the following:
+ * - In main mode with pre-shared key, only address type can be used.
+ * - if proper type for phase 1 ?
+ * - if phase 1 ID payload conformed RFC2407 4.6.2.
+ * (proto, port) must be (0, 0), (udp, 500) or (udp, [specified]).
+ * - if ID payload sent from peer is equal to the ID expected by me.
+ *
+ * both of "id" and "id_p" should be ID payload without general header,
+ */
+int
+ipsecdoi_checkid1(iph1)
+ struct ph1handle *iph1;
+{
+ struct ipsecdoi_id_b *id_b;
+ struct sockaddr *sa;
+ caddr_t sa1, sa2;
+
+ if (iph1->id_p == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid iph1 passed id_p == NULL\n");
+ return ISAKMP_INTERNAL_ERROR;
+ }
+ if (iph1->id_p->l < sizeof(*id_b)) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid value passed as \"ident\" (len=%lu)\n",
+ (u_long)iph1->id_p->l);
+ return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
+ }
+
+ id_b = (struct ipsecdoi_id_b *)iph1->id_p->v;
+
+ /* In main mode with pre-shared key, only address type can be used. */
+ if (iph1->etype == ISAKMP_ETYPE_IDENT &&
+ iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_PSKEY) {
+ if (id_b->type != IPSECDOI_ID_IPV4_ADDR
+ && id_b->type != IPSECDOI_ID_IPV6_ADDR) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "Expecting IP address type in main mode, "
+ "but %s.\n", s_ipsecdoi_ident(id_b->type));
+ return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
+ }
+ }
+
+ /* if proper type for phase 1 ? */
+ switch (id_b->type) {
+ case IPSECDOI_ID_IPV4_ADDR_SUBNET:
+ case IPSECDOI_ID_IPV6_ADDR_SUBNET:
+ case IPSECDOI_ID_IPV4_ADDR_RANGE:
+ case IPSECDOI_ID_IPV6_ADDR_RANGE:
+ plog(LLV_WARNING, LOCATION, NULL,
+ "such ID type %s is not proper.\n",
+ s_ipsecdoi_ident(id_b->type));
+ /*FALLTHROUGH*/
+ }
+
+ /* if phase 1 ID payload conformed RFC2407 4.6.2. */
+ if (id_b->type == IPSECDOI_ID_IPV4_ADDR ||
+ id_b->type == IPSECDOI_ID_IPV6_ADDR) {
+
+ if (id_b->proto_id == 0 && ntohs(id_b->port) != 0) {
+ plog(LLV_WARNING, LOCATION, NULL,
+ "protocol ID and Port mismatched. "
+ "proto_id:%d port:%d\n",
+ id_b->proto_id, ntohs(id_b->port));
+ /*FALLTHROUGH*/
+
+ } else if (id_b->proto_id == IPPROTO_UDP) {
+ /*
+ * copmaring with expecting port.
+ * always permit if port is equal to PORT_ISAKMP
+ */
+ if (ntohs(id_b->port) != PORT_ISAKMP) {
+ u_int16_t port;
+
+ port = extract_port(iph1->remote);
+ if (ntohs(id_b->port) != port) {
+ plog(LLV_WARNING, LOCATION, NULL,
+ "port %d expected, but %d\n",
+ port, ntohs(id_b->port));
+ /*FALLTHROUGH*/
+ }
+ }
+ }
+ }
+
+ /* compare with the ID if specified. */
+ if (genlist_next(iph1->rmconf->idvl_p, 0)) {
+ vchar_t *ident0 = NULL;
+ vchar_t ident;
+ struct idspec *id;
+ struct genlist_entry *gpb;
+
+ for (id = genlist_next (iph1->rmconf->idvl_p, &gpb); id; id = genlist_next (0, &gpb)) {
+ /* check the type of both IDs */
+ if (id->idtype != doi2idtype(id_b->type))
+ continue; /* ID type mismatch */
+ if (id->id == 0)
+ goto matched;
+
+ /* compare defined ID with the ID sent by peer. */
+ if (ident0 != NULL)
+ vfree(ident0);
+ ident0 = getidval(id->idtype, id->id);
+
+ switch (id->idtype) {
+ case IDTYPE_ASN1DN:
+ ident.v = iph1->id_p->v + sizeof(*id_b);
+ ident.l = iph1->id_p->l - sizeof(*id_b);
+ if (eay_cmp_asn1dn(ident0, &ident) == 0)
+ goto matched;
+ break;
+ case IDTYPE_ADDRESS:
+ sa = (struct sockaddr *)ident0->v;
+ sa2 = (caddr_t)(id_b + 1);
+ switch (sa->sa_family) {
+ case AF_INET:
+ if (iph1->id_p->l - sizeof(*id_b) != sizeof(struct in_addr))
+ continue; /* ID value mismatch */
+ sa1 = (caddr_t)&((struct sockaddr_in *)sa)->sin_addr;
+ if (memcmp(sa1, sa2, sizeof(struct in_addr)) == 0)
+ goto matched;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ if (iph1->id_p->l - sizeof(*id_b) != sizeof(struct in6_addr))
+ continue; /* ID value mismatch */
+ sa1 = (caddr_t)&((struct sockaddr_in6 *)sa)->sin6_addr;
+ if (memcmp(sa1, sa2, sizeof(struct in6_addr)) == 0)
+ goto matched;
+ break;
+#endif
+ default:
+ break;
+ }
+ break;
+ default:
+ if (memcmp(ident0->v, id_b + 1, ident0->l) == 0)
+ goto matched;
+ break;
+ }
+ }
+ if (ident0 != NULL) {
+ vfree(ident0);
+ ident0 = NULL;
+ }
+ plog(LLV_WARNING, LOCATION, NULL, "No ID match.\n");
+ if (iph1->rmconf->verify_identifier)
+ return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
+matched: /* ID value match */
+ if (ident0 != NULL)
+ vfree(ident0);
+ }
+
+ return 0;
+}
+
+/*
+ * create ID payload for phase 1 and set into iph1->id.
+ * NOT INCLUDING isakmp general header.
+ * see, RFC2407 4.6.2.1
+ */
+int
+ipsecdoi_setid1(iph1)
+ struct ph1handle *iph1;
+{
+ vchar_t *ret = NULL;
+ struct ipsecdoi_id_b id_b;
+ vchar_t *ident = NULL;
+ struct sockaddr *ipid = NULL;
+
+ /* init */
+ id_b.proto_id = 0;
+ id_b.port = 0;
+ ident = NULL;
+
+ switch (iph1->rmconf->idvtype) {
+ case IDTYPE_FQDN:
+ id_b.type = IPSECDOI_ID_FQDN;
+ ident = getidval(iph1->rmconf->idvtype, iph1->rmconf->idv);
+ break;
+ case IDTYPE_USERFQDN:
+ id_b.type = IPSECDOI_ID_USER_FQDN;
+ ident = getidval(iph1->rmconf->idvtype, iph1->rmconf->idv);
+ break;
+ case IDTYPE_KEYID:
+ id_b.type = IPSECDOI_ID_KEY_ID;
+ ident = getidval(iph1->rmconf->idvtype, iph1->rmconf->idv);
+ break;
+ case IDTYPE_ASN1DN:
+ id_b.type = IPSECDOI_ID_DER_ASN1_DN;
+ if (iph1->rmconf->idv) {
+ /* XXX it must be encoded to asn1dn. */
+ ident = vdup(iph1->rmconf->idv);
+ } else {
+ if (oakley_getmycert(iph1) < 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "failed to get own CERT.\n");
+ goto err;
+ }
+ ident = eay_get_x509asn1subjectname(iph1->cert);
+ }
+ break;
+ case IDTYPE_ADDRESS:
+ /*
+ * if the value of the id type was set by the configuration
+ * file, then use it. otherwise the value is get from local
+ * ip address by using ike negotiation.
+ */
+ if (iph1->rmconf->idv)
+ ipid = (struct sockaddr *)iph1->rmconf->idv->v;
+ /*FALLTHROUGH*/
+ default:
+ {
+ int l;
+ caddr_t p;
+
+ if (ipid == NULL)
+ ipid = iph1->local;
+
+ /* use IP address */
+ switch (ipid->sa_family) {
+ case AF_INET:
+ id_b.type = IPSECDOI_ID_IPV4_ADDR;
+ l = sizeof(struct in_addr);
+ p = (caddr_t)&((struct sockaddr_in *)ipid)->sin_addr;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ id_b.type = IPSECDOI_ID_IPV6_ADDR;
+ l = sizeof(struct in6_addr);
+ p = (caddr_t)&((struct sockaddr_in6 *)ipid)->sin6_addr;
+ break;
+#endif
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid address family.\n");
+ goto err;
+ }
+ id_b.proto_id = IPPROTO_UDP;
+ id_b.port = htons(PORT_ISAKMP);
+ ident = vmalloc(l);
+ if (!ident) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "failed to get ID buffer.\n");
+ return 0;
+ }
+ memcpy(ident->v, p, ident->l);
+ }
+ }
+ if (!ident) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "failed to get ID buffer.\n");
+ return 0;
+ }
+
+ ret = vmalloc(sizeof(id_b) + ident->l);
+ if (ret == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "failed to get ID buffer.\n");
+ goto err;
+ }
+
+ memcpy(ret->v, &id_b, sizeof(id_b));
+ memcpy(ret->v + sizeof(id_b), ident->v, ident->l);
+
+ iph1->id = ret;
+
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "use ID type of %s\n", s_ipsecdoi_ident(id_b.type));
+ if (ident)
+ vfree(ident);
+ return 0;
+
+err:
+ if (ident)
+ vfree(ident);
+ plog(LLV_ERROR, LOCATION, NULL, "failed get my ID\n");
+ return -1;
+}
+
+static vchar_t *
+getidval(type, val)
+ int type;
+ vchar_t *val;
+{
+ vchar_t *new = NULL;
+
+ if (val)
+ new = vdup(val);
+ return new;
+}
+
+/* it's only called by cfparse.y. */
+int
+set_identifier(vpp, type, value)
+ vchar_t **vpp, *value;
+ int type;
+{
+ return set_identifier_qual(vpp, type, value, IDQUAL_UNSPEC);
+}
+
+int
+set_identifier_qual(vpp, type, value, qual)
+ vchar_t **vpp, *value;
+ int type;
+ int qual;
+{
+ vchar_t *new = NULL;
+
+ /* simply return if value is null. */
+ if (!value){
+ if( type == IDTYPE_FQDN || type == IDTYPE_USERFQDN){
+ plog(LLV_ERROR, LOCATION, NULL,
+ "No %s\n", type == IDTYPE_FQDN ? "fqdn":"user fqdn");
+ return -1;
+ }
+ return 0;
+ }
+
+ switch (type) {
+ case IDTYPE_FQDN:
+ case IDTYPE_USERFQDN:
+ if(value->l <= 1){
+ plog(LLV_ERROR, LOCATION, NULL,
+ "Empty %s\n", type == IDTYPE_FQDN ? "fqdn":"user fqdn");
+ return -1;
+ }
+ /* length is adjusted since QUOTEDSTRING teminates NULL. */
+ new = vmalloc(value->l - 1);
+ if (new == NULL)
+ return -1;
+ memcpy(new->v, value->v, new->l);
+ break;
+ case IDTYPE_KEYID:
+ /*
+ * If no qualifier is specified: IDQUAL_UNSPEC. It means
+ * to use a file for backward compatibility sake.
+ */
+ switch(qual) {
+ case IDQUAL_FILE:
+ case IDQUAL_UNSPEC: {
+ FILE *fp;
+ char b[512];
+ int tlen, len;
+
+ fp = fopen(value->v, "r");
+ if (fp == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "can not open %s\n", value->v);
+ return -1;
+ }
+ tlen = 0;
+ while ((len = fread(b, 1, sizeof(b), fp)) != 0) {
+ new = vrealloc(new, tlen + len);
+ if (!new) {
+ fclose(fp);
+ return -1;
+ }
+ memcpy(new->v + tlen, b, len);
+ tlen += len;
+ }
+ fclose(fp);
+ break;
+ }
+
+ case IDQUAL_TAG:
+ new = vmalloc(value->l - 1);
+ if (new == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "can not allocate memory");
+ return -1;
+ }
+ memcpy(new->v, value->v, new->l);
+ break;
+
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "unknown qualifier");
+ return -1;
+ }
+ break;
+
+ case IDTYPE_ADDRESS: {
+ struct sockaddr *sa;
+
+ /* length is adjusted since QUOTEDSTRING teminates NULL. */
+ if (value->l == 0)
+ break;
+
+ sa = str2saddr(value->v, NULL);
+ if (sa == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid ip address %s\n", value->v);
+ return -1;
+ }
+
+ new = vmalloc(sysdep_sa_len(sa));
+ if (new == NULL) {
+ racoon_free(sa);
+ return -1;
+ }
+ memcpy(new->v, sa, new->l);
+ racoon_free(sa);
+ break;
+ }
+ case IDTYPE_ASN1DN:
+ if (value->v[0] == '~')
+ /* Hex-encoded ASN1 strings */
+ new = eay_hex2asn1dn(value->v + 1, - 1);
+ else
+ /* DN encoded strings */
+ new = eay_str2asn1dn(value->v, value->l - 1);
+
+ if (new == NULL)
+ return -1;
+
+ if (loglevel >= LLV_DEBUG) {
+ X509_NAME *xn;
+ BIO *bio;
+ unsigned char *ptr = (unsigned char *) new->v, *buf;
+ size_t len;
+ char save;
+
+ xn = d2i_X509_NAME(NULL, (void *)&ptr, new->l);
+ bio = BIO_new(BIO_s_mem());
+
+ X509_NAME_print_ex(bio, xn, 0, 0);
+ len = BIO_get_mem_data(bio, &ptr);
+ save = ptr[len];
+ ptr[len] = 0;
+ plog(LLV_DEBUG, LOCATION, NULL, "Parsed DN: %s\n", ptr);
+ ptr[len] = save;
+ X509_NAME_free(xn);
+ BIO_free(bio);
+ }
+
+ break;
+ }
+
+ *vpp = new;
+
+ return 0;
+}
+
+/*
+ * create ID payload for phase 2, and set into iph2->id and id_p. There are
+ * NOT INCLUDING isakmp general header.
+ * this function is for initiator. responder will get to copy from payload.
+ * responder ID type is always address type.
+ * see, RFC2407 4.6.2.1
+ */
+int
+ipsecdoi_setid2(iph2)
+ struct ph2handle *iph2;
+{
+ struct secpolicy *sp;
+
+ /* check there is phase 2 handler ? */
+ sp = getspbyspid(iph2->spid);
+ if (sp == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "no policy found for spid:%u.\n", iph2->spid);
+ return -1;
+ }
+
+ iph2->id = ipsecdoi_sockaddr2id((struct sockaddr *)&sp->spidx.src,
+ sp->spidx.prefs, sp->spidx.ul_proto);
+ if (iph2->id == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "failed to get ID for %s\n",
+ spidx2str(&sp->spidx));
+ return -1;
+ }
+ plog(LLV_DEBUG, LOCATION, NULL, "use local ID type %s\n",
+ s_ipsecdoi_ident(((struct ipsecdoi_id_b *)iph2->id->v)->type));
+
+ /* remote side */
+ iph2->id_p = ipsecdoi_sockaddr2id((struct sockaddr *)&sp->spidx.dst,
+ sp->spidx.prefd, sp->spidx.ul_proto);
+ if (iph2->id_p == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "failed to get ID for %s\n",
+ spidx2str(&sp->spidx));
+ VPTRINIT(iph2->id);
+ return -1;
+ }
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "use remote ID type %s\n",
+ s_ipsecdoi_ident(((struct ipsecdoi_id_b *)iph2->id_p->v)->type));
+
+ return 0;
+}
+
+/*
+ * set address type of ID.
+ * NOT INCLUDING general header.
+ */
+vchar_t *
+ipsecdoi_sockaddr2id(saddr, prefixlen, ul_proto)
+ struct sockaddr *saddr;
+ u_int prefixlen;
+ u_int ul_proto;
+{
+ vchar_t *new;
+ int type, len1, len2;
+ caddr_t sa;
+ u_short port;
+
+ /*
+ * Q. When type is SUBNET, is it allowed to be ::1/128.
+ * A. Yes. (consensus at bake-off)
+ */
+ switch (saddr->sa_family) {
+ case AF_INET:
+ len1 = sizeof(struct in_addr);
+ if (prefixlen == (sizeof(struct in_addr) << 3)) {
+ type = IPSECDOI_ID_IPV4_ADDR;
+ len2 = 0;
+ } else {
+ type = IPSECDOI_ID_IPV4_ADDR_SUBNET;
+ len2 = sizeof(struct in_addr);
+ }
+ sa = (caddr_t)&((struct sockaddr_in *)(saddr))->sin_addr;
+ port = ((struct sockaddr_in *)(saddr))->sin_port;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ len1 = sizeof(struct in6_addr);
+ if (prefixlen == (sizeof(struct in6_addr) << 3)) {
+ type = IPSECDOI_ID_IPV6_ADDR;
+ len2 = 0;
+ } else {
+ type = IPSECDOI_ID_IPV6_ADDR_SUBNET;
+ len2 = sizeof(struct in6_addr);
+ }
+ sa = (caddr_t)&((struct sockaddr_in6 *)(saddr))->sin6_addr;
+ port = ((struct sockaddr_in6 *)(saddr))->sin6_port;
+ break;
+#endif
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid family: %d.\n", saddr->sa_family);
+ return NULL;
+ }
+
+ /* get ID buffer */
+ new = vmalloc(sizeof(struct ipsecdoi_id_b) + len1 + len2);
+ if (new == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "failed to get ID buffer.\n");
+ return NULL;
+ }
+
+ memset(new->v, 0, new->l);
+
+ /* set the part of header. */
+ ((struct ipsecdoi_id_b *)new->v)->type = type;
+
+ /* set ul_proto and port */
+ /*
+ * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
+ * because 0 means port number of 0. Instead of 0, we use IPSEC_*_ANY.
+ */
+ ((struct ipsecdoi_id_b *)new->v)->proto_id =
+ ul_proto == IPSEC_ULPROTO_ANY ? 0 : ul_proto;
+ ((struct ipsecdoi_id_b *)new->v)->port =
+ port == IPSEC_PORT_ANY ? 0 : port;
+ memcpy(new->v + sizeof(struct ipsecdoi_id_b), sa, len1);
+
+ /* set address */
+
+ /* set prefix */
+ if (len2) {
+ u_char *p = (unsigned char *) new->v +
+ sizeof(struct ipsecdoi_id_b) + len1;
+ u_int bits = prefixlen;
+
+ while (bits >= 8) {
+ *p++ = 0xff;
+ bits -= 8;
+ }
+
+ if (bits > 0)
+ *p = ~((1 << (8 - bits)) - 1);
+ }
+
+ return new;
+}
+
+vchar_t *
+ipsecdoi_sockrange2id(laddr, haddr, ul_proto)
+ struct sockaddr *laddr, *haddr;
+ u_int ul_proto;
+{
+ vchar_t *new;
+ int type, len1, len2;
+ u_short port;
+
+ if (laddr->sa_family != haddr->sa_family) {
+ plog(LLV_ERROR, LOCATION, NULL, "Address family mismatch\n");
+ return NULL;
+ }
+
+ switch (laddr->sa_family) {
+ case AF_INET:
+ type = IPSECDOI_ID_IPV4_ADDR_RANGE;
+ len1 = sizeof(struct in_addr);
+ len2 = sizeof(struct in_addr);
+ break;
+#ifdef INET6
+ case AF_INET6:
+ type = IPSECDOI_ID_IPV6_ADDR_RANGE;
+ len1 = sizeof(struct in6_addr);
+ len2 = sizeof(struct in6_addr);
+ break;
+#endif
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid family: %d.\n", laddr->sa_family);
+ return NULL;
+ }
+
+ /* get ID buffer */
+ new = vmalloc(sizeof(struct ipsecdoi_id_b) + len1 + len2);
+ if (new == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "failed to get ID buffer.\n");
+ return NULL;
+ }
+
+ memset(new->v, 0, new->l);
+ /* set the part of header. */
+ ((struct ipsecdoi_id_b *)new->v)->type = type;
+
+ /* set ul_proto and port */
+ /*
+ * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
+ * because 0 means port number of 0. Instead of 0, we use IPSEC_*_ANY.
+ */
+ ((struct ipsecdoi_id_b *)new->v)->proto_id =
+ ul_proto == IPSEC_ULPROTO_ANY ? 0 : ul_proto;
+ port = ((struct sockaddr_in *)(laddr))->sin_port;
+ ((struct ipsecdoi_id_b *)new->v)->port =
+ port == IPSEC_PORT_ANY ? 0 : port;
+ memcpy(new->v + sizeof(struct ipsecdoi_id_b),
+ (caddr_t)&((struct sockaddr_in *)(laddr))->sin_addr,
+ len1);
+ memcpy(new->v + sizeof(struct ipsecdoi_id_b) + len1,
+ (caddr_t)&((struct sockaddr_in *)haddr)->sin_addr,
+ len2);
+ return new;
+}
+
+
+/*
+ * create sockaddr structure from ID payload (buf).
+ * buffers (saddr, prefixlen, ul_proto) must be allocated.
+ * see, RFC2407 4.6.2.1
+ */
+int
+ipsecdoi_id2sockaddr(buf, saddr, prefixlen, ul_proto)
+ vchar_t *buf;
+ struct sockaddr *saddr;
+ u_int8_t *prefixlen;
+ u_int16_t *ul_proto;
+{
+ struct ipsecdoi_id_b *id_b = (struct ipsecdoi_id_b *)buf->v;
+ u_int plen = 0;
+
+ /*
+ * When a ID payload of subnet type with a IP address of full bit
+ * masked, it has to be processed as host address.
+ * e.g. below 2 type are same.
+ * type = ipv6 subnet, data = 2001::1/128
+ * type = ipv6 address, data = 2001::1
+ */
+ switch (id_b->type) {
+ case IPSECDOI_ID_IPV4_ADDR:
+ case IPSECDOI_ID_IPV4_ADDR_SUBNET:
+#ifndef __linux__
+ saddr->sa_len = sizeof(struct sockaddr_in);
+#endif
+ saddr->sa_family = AF_INET;
+ ((struct sockaddr_in *)saddr)->sin_port =
+ (id_b->port == 0
+ ? IPSEC_PORT_ANY
+ : id_b->port); /* see sockaddr2id() */
+ memcpy(&((struct sockaddr_in *)saddr)->sin_addr,
+ buf->v + sizeof(*id_b), sizeof(struct in_addr));
+ break;
+#ifdef INET6
+ case IPSECDOI_ID_IPV6_ADDR:
+ case IPSECDOI_ID_IPV6_ADDR_SUBNET:
+#ifndef __linux__
+ saddr->sa_len = sizeof(struct sockaddr_in6);
+#endif
+ saddr->sa_family = AF_INET6;
+ ((struct sockaddr_in6 *)saddr)->sin6_port =
+ (id_b->port == 0
+ ? IPSEC_PORT_ANY
+ : id_b->port); /* see sockaddr2id() */
+ memcpy(&((struct sockaddr_in6 *)saddr)->sin6_addr,
+ buf->v + sizeof(*id_b), sizeof(struct in6_addr));
+ break;
+#endif
+ default:
+ do_plog(LLV_INFO, "XXXXXXXXXXXXXXXXXXXXXX error\n");
+ plog(LLV_ERROR, LOCATION, NULL,
+ "unsupported ID type %d\n", id_b->type);
+ return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
+ }
+
+ /* get prefix length */
+ switch (id_b->type) {
+ case IPSECDOI_ID_IPV4_ADDR:
+ plen = sizeof(struct in_addr) << 3;
+ break;
+#ifdef INET6
+ case IPSECDOI_ID_IPV6_ADDR:
+ plen = sizeof(struct in6_addr) << 3;
+ break;
+#endif
+ case IPSECDOI_ID_IPV4_ADDR_SUBNET:
+#ifdef INET6
+ case IPSECDOI_ID_IPV6_ADDR_SUBNET:
+#endif
+ {
+ u_char *p;
+ u_int max;
+ int alen = sizeof(struct in_addr);
+
+ switch (id_b->type) {
+ case IPSECDOI_ID_IPV4_ADDR_SUBNET:
+ alen = sizeof(struct in_addr);
+ break;
+#ifdef INET6
+ case IPSECDOI_ID_IPV6_ADDR_SUBNET:
+ alen = sizeof(struct in6_addr);
+ break;
+#endif
+ }
+
+ /* sanity check */
+ if (buf->l < alen)
+ return ISAKMP_INTERNAL_ERROR;
+
+ /* get subnet mask length */
+ plen = 0;
+ max = alen <<3;
+
+ p = (unsigned char *) buf->v
+ + sizeof(struct ipsecdoi_id_b)
+ + alen;
+
+ for (; *p == 0xff; p++) {
+ plen += 8;
+ if (plen >= max)
+ break;
+ }
+
+ if (plen < max) {
+ u_int l = 0;
+ u_char b = ~(*p);
+
+ while (b) {
+ b >>= 1;
+ l++;
+ }
+
+ l = 8 - l;
+ plen += l;
+ }
+ }
+ break;
+ }
+
+ *prefixlen = plen;
+ *ul_proto = id_b->proto_id == 0
+ ? IPSEC_ULPROTO_ANY
+ : id_b->proto_id; /* see sockaddr2id() */
+
+ return 0;
+}
+
+/*
+ * make printable string from ID payload except of general header.
+ */
+char *
+ipsecdoi_id2str(id)
+ const vchar_t *id;
+{
+#define BUFLEN 512
+ char * ret = NULL;
+ int len = 0;
+ char *dat;
+ static char buf[BUFLEN];
+ struct ipsecdoi_id_b *id_b = (struct ipsecdoi_id_b *)id->v;
+ struct sockaddr_storage saddr_storage;
+ struct sockaddr *saddr;
+ struct sockaddr_in *saddr_in;
+ struct sockaddr_in6 *saddr_in6;
+ u_int plen = 0;
+
+ saddr = (struct sockaddr *)&saddr_storage;
+ saddr_in = (struct sockaddr_in *)&saddr_storage;
+ saddr_in6 = (struct sockaddr_in6 *)&saddr_storage;
+
+
+ switch (id_b->type) {
+ case IPSECDOI_ID_IPV4_ADDR:
+ case IPSECDOI_ID_IPV4_ADDR_SUBNET:
+ case IPSECDOI_ID_IPV4_ADDR_RANGE:
+
+#ifndef __linux__
+ saddr->sa_len = sizeof(struct sockaddr_in);
+#endif
+ saddr->sa_family = AF_INET;
+
+ saddr_in->sin_port = IPSEC_PORT_ANY;
+ memcpy(&saddr_in->sin_addr,
+ id->v + sizeof(*id_b), sizeof(struct in_addr));
+ break;
+#ifdef INET6
+ case IPSECDOI_ID_IPV6_ADDR:
+ case IPSECDOI_ID_IPV6_ADDR_SUBNET:
+ case IPSECDOI_ID_IPV6_ADDR_RANGE:
+
+#ifndef __linux__
+ saddr->sa_len = sizeof(struct sockaddr_in6);
+#endif
+ saddr->sa_family = AF_INET6;
+
+ saddr_in6->sin6_port = IPSEC_PORT_ANY;
+ memcpy(&saddr_in6->sin6_addr,
+ id->v + sizeof(*id_b), sizeof(struct in6_addr));
+ saddr_in6->sin6_scope_id =
+ (IN6_IS_ADDR_LINKLOCAL(&saddr_in6->sin6_addr)
+ ? ((struct sockaddr_in6 *)id_b)->sin6_scope_id
+ : 0);
+ break;
+#endif
+ }
+
+ switch (id_b->type) {
+ case IPSECDOI_ID_IPV4_ADDR:
+#ifdef INET6
+ case IPSECDOI_ID_IPV6_ADDR:
+#endif
+ len = snprintf( buf, BUFLEN, "%s", saddrwop2str(saddr));
+ break;
+
+ case IPSECDOI_ID_IPV4_ADDR_SUBNET:
+#ifdef INET6
+ case IPSECDOI_ID_IPV6_ADDR_SUBNET:
+#endif
+ {
+ u_char *p;
+ u_int max;
+ int alen = sizeof(struct in_addr);
+
+ switch (id_b->type) {
+ case IPSECDOI_ID_IPV4_ADDR_SUBNET:
+ alen = sizeof(struct in_addr);
+ break;
+#ifdef INET6
+ case IPSECDOI_ID_IPV6_ADDR_SUBNET:
+ alen = sizeof(struct in6_addr);
+ break;
+#endif
+ }
+
+ /* sanity check */
+ if (id->l < alen) {
+ len = 0;
+ break;
+ }
+
+ /* get subnet mask length */
+ plen = 0;
+ max = alen <<3;
+
+ p = (unsigned char *) id->v
+ + sizeof(struct ipsecdoi_id_b)
+ + alen;
+
+ for (; *p == 0xff; p++) {
+ plen += 8;
+ if (plen >= max)
+ break;
+ }
+
+ if (plen < max) {
+ u_int l = 0;
+ u_char b = ~(*p);
+
+ while (b) {
+ b >>= 1;
+ l++;
+ }
+
+ l = 8 - l;
+ plen += l;
+ }
+
+ len = snprintf( buf, BUFLEN, "%s/%i", saddrwop2str(saddr), plen);
+ }
+ break;
+
+ case IPSECDOI_ID_IPV4_ADDR_RANGE:
+
+ len = snprintf( buf, BUFLEN, "%s-", saddrwop2str(saddr));
+
+#ifndef __linux__
+ saddr->sa_len = sizeof(struct sockaddr_in);
+#endif
+ saddr->sa_family = AF_INET;
+ saddr_in->sin_port = IPSEC_PORT_ANY;
+ memcpy(&saddr_in->sin_addr,
+ id->v + sizeof(*id_b) + sizeof(struct in_addr),
+ sizeof(struct in_addr));
+
+ len += snprintf( buf + len, BUFLEN - len, "%s", saddrwop2str(saddr));
+
+ break;
+
+#ifdef INET6
+ case IPSECDOI_ID_IPV6_ADDR_RANGE:
+
+ len = snprintf( buf, BUFLEN, "%s-", saddrwop2str(saddr));
+
+#ifndef __linux__
+ saddr->sa_len = sizeof(struct sockaddr_in6);
+#endif
+ saddr->sa_family = AF_INET6;
+ saddr_in6->sin6_port = IPSEC_PORT_ANY;
+ memcpy(&saddr_in6->sin6_addr,
+ id->v + sizeof(*id_b) + sizeof(struct in6_addr),
+ sizeof(struct in6_addr));
+ saddr_in6->sin6_scope_id =
+ (IN6_IS_ADDR_LINKLOCAL(&saddr_in6->sin6_addr)
+ ? ((struct sockaddr_in6 *)id_b)->sin6_scope_id
+ : 0);
+
+ len += snprintf( buf + len, BUFLEN - len, "%s", saddrwop2str(saddr));
+
+ break;
+#endif
+
+ case IPSECDOI_ID_FQDN:
+ case IPSECDOI_ID_USER_FQDN:
+ len = id->l - sizeof(*id_b);
+ if (len > BUFLEN)
+ len = BUFLEN;
+ memcpy(buf, id->v + sizeof(*id_b), len);
+ break;
+
+ case IPSECDOI_ID_DER_ASN1_DN:
+ case IPSECDOI_ID_DER_ASN1_GN:
+ {
+ X509_NAME *xn = NULL;
+
+ dat = id->v + sizeof(*id_b);
+ len = id->l - sizeof(*id_b);
+
+ if (d2i_X509_NAME(&xn, (void*) &dat, len) != NULL) {
+ BIO *bio = BIO_new(BIO_s_mem());
+ X509_NAME_print_ex(bio, xn, 0, 0);
+ len = BIO_get_mem_data(bio, &dat);
+ if (len > BUFLEN)
+ len = BUFLEN;
+ memcpy(buf,dat,len);
+ BIO_free(bio);
+ X509_NAME_free(xn);
+ } else {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "unable to extract asn1dn from id\n");
+
+ len = sprintf(buf, "<ASN1-DN>");
+ }
+
+ break;
+ }
+
+ /* currently unhandled id types */
+ case IPSECDOI_ID_KEY_ID:
+ len = sprintf( buf, "<KEY-ID>");
+ break;
+
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "unknown ID type %d\n", id_b->type);
+ }
+
+ if (!len)
+ len = sprintf( buf, "<?>");
+
+ ret = racoon_malloc(len+1);
+ if (ret != NULL) {
+ memcpy(ret,buf,len);
+ ret[len]=0;
+ }
+
+ return ret;
+}
+
+/*
+ * set IPsec data attributes into a proposal.
+ * NOTE: MUST called per a transform.
+ */
+int
+ipsecdoi_t2satrns(t, pp, pr, tr)
+ struct isakmp_pl_t *t;
+ struct saprop *pp;
+ struct saproto *pr;
+ struct satrns *tr;
+{
+ struct isakmp_data *d, *prev;
+ int flag, type;
+ int error = -1;
+ int life_t;
+ int tlen;
+
+ tr->trns_no = t->t_no;
+ tr->trns_id = t->t_id;
+
+ tlen = ntohs(t->h.len) - sizeof(*t);
+ prev = (struct isakmp_data *)NULL;
+ d = (struct isakmp_data *)(t + 1);
+
+ /* default */
+ life_t = IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT;
+ pp->lifetime = IPSECDOI_ATTR_SA_LD_SEC_DEFAULT;
+ pp->lifebyte = 0;
+ tr->authtype = IPSECDOI_ATTR_AUTH_NONE;
+
+ while (tlen > 0) {
+
+ type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
+ flag = ntohs(d->type) & ISAKMP_GEN_MASK;
+
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "type=%s, flag=0x%04x, lorv=%s\n",
+ s_ipsecdoi_attr(type), flag,
+ s_ipsecdoi_attr_v(type, ntohs(d->lorv)));
+
+ switch (type) {
+ case IPSECDOI_ATTR_SA_LD_TYPE:
+ {
+ int type = ntohs(d->lorv);
+ switch (type) {
+ case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
+ case IPSECDOI_ATTR_SA_LD_TYPE_KB:
+ life_t = type;
+ break;
+ default:
+ plog(LLV_WARNING, LOCATION, NULL,
+ "invalid life duration type. "
+ "use default\n");
+ life_t = IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT;
+ break;
+ }
+ break;
+ }
+ case IPSECDOI_ATTR_SA_LD:
+ if (prev == NULL
+ || (ntohs(prev->type) & ~ISAKMP_GEN_MASK) !=
+ IPSECDOI_ATTR_SA_LD_TYPE) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "life duration must follow ltype\n");
+ break;
+ }
+
+ {
+ u_int32_t t;
+ vchar_t *ld_buf = NULL;
+
+ if (flag) {
+ /* i.e. ISAKMP_GEN_TV */
+ ld_buf = vmalloc(sizeof(d->lorv));
+ if (ld_buf == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "failed to get LD buffer.\n");
+ goto end;
+ }
+ memcpy(ld_buf->v, &d->lorv, sizeof(d->lorv));
+ } else {
+ int len = ntohs(d->lorv);
+ /* i.e. ISAKMP_GEN_TLV */
+ ld_buf = vmalloc(len);
+ if (ld_buf == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "failed to get LD buffer.\n");
+ goto end;
+ }
+ memcpy(ld_buf->v, d + 1, len);
+ }
+ switch (life_t) {
+ case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
+ t = ipsecdoi_set_ld(ld_buf);
+ vfree(ld_buf);
+ if (t == 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid life duration.\n");
+ goto end;
+ }
+ /* lifetime must be equal in a proposal. */
+ if (pp->lifetime == IPSECDOI_ATTR_SA_LD_SEC_DEFAULT)
+ pp->lifetime = t;
+ else if (pp->lifetime != t) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "lifetime mismatched "
+ "in a proposal, "
+ "prev:%ld curr:%u.\n",
+ (long)pp->lifetime, t);
+ goto end;
+ }
+ break;
+ case IPSECDOI_ATTR_SA_LD_TYPE_KB:
+ t = ipsecdoi_set_ld(ld_buf);
+ vfree(ld_buf);
+ if (t == 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid life duration.\n");
+ goto end;
+ }
+ /* lifebyte must be equal in a proposal. */
+ if (pp->lifebyte == 0)
+ pp->lifebyte = t;
+ else if (pp->lifebyte != t) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "lifebyte mismatched "
+ "in a proposal, "
+ "prev:%d curr:%u.\n",
+ pp->lifebyte, t);
+ goto end;
+ }
+ break;
+ default:
+ vfree(ld_buf);
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid life type: %d\n", life_t);
+ goto end;
+ }
+ }
+ break;
+
+ case IPSECDOI_ATTR_GRP_DESC:
+ /*
+ * RFC2407: 4.5 IPSEC Security Association Attributes
+ * Specifies the Oakley Group to be used in a PFS QM
+ * negotiation. For a list of supported values, see
+ * Appendix A of [IKE].
+ */
+ if (pp->pfs_group == 0)
+ pp->pfs_group = (u_int16_t)ntohs(d->lorv);
+ else if (pp->pfs_group != (u_int16_t)ntohs(d->lorv)) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "pfs_group mismatched "
+ "in a proposal.\n");
+ goto end;
+ }
+ break;
+
+ case IPSECDOI_ATTR_ENC_MODE:
+ if (pr->encmode &&
+ pr->encmode != (u_int16_t)ntohs(d->lorv)) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "multiple encmode exist "
+ "in a transform.\n");
+ goto end;
+ }
+ pr->encmode = (u_int16_t)ntohs(d->lorv);
+ break;
+
+ case IPSECDOI_ATTR_AUTH:
+ if (tr->authtype != IPSECDOI_ATTR_AUTH_NONE) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "multiple authtype exist "
+ "in a transform.\n");
+ goto end;
+ }
+ tr->authtype = (u_int16_t)ntohs(d->lorv);
+ break;
+
+ case IPSECDOI_ATTR_KEY_LENGTH:
+ if (pr->proto_id != IPSECDOI_PROTO_IPSEC_ESP) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "key length defined but not ESP");
+ goto end;
+ }
+ tr->encklen = ntohs(d->lorv);
+ break;
+#ifdef HAVE_SECCTX
+ case IPSECDOI_ATTR_SECCTX:
+ {
+ int len = ntohs(d->lorv);
+ memcpy(&pp->sctx, d + 1, len);
+ pp->sctx.ctx_strlen = ntohs(pp->sctx.ctx_strlen);
+ break;
+ }
+#endif /* HAVE_SECCTX */
+ case IPSECDOI_ATTR_KEY_ROUNDS:
+ case IPSECDOI_ATTR_COMP_DICT_SIZE:
+ case IPSECDOI_ATTR_COMP_PRIVALG:
+ default:
+ break;
+ }
+
+ prev = d;
+ if (flag) {
+ tlen -= sizeof(*d);
+ d = (struct isakmp_data *)((char *)d + sizeof(*d));
+ } else {
+ tlen -= (sizeof(*d) + ntohs(d->lorv));
+ d = (struct isakmp_data *)((caddr_t)d + sizeof(*d) + ntohs(d->lorv));
+ }
+ }
+
+ error = 0;
+end:
+ return error;
+}
+
+int
+ipsecdoi_authalg2trnsid(alg)
+ int alg;
+{
+ switch (alg) {
+ case IPSECDOI_ATTR_AUTH_HMAC_MD5:
+ return IPSECDOI_AH_MD5;
+ case IPSECDOI_ATTR_AUTH_HMAC_SHA1:
+ return IPSECDOI_AH_SHA;
+ case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256:
+ return IPSECDOI_AH_SHA256;
+ case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384:
+ return IPSECDOI_AH_SHA384;
+ case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512:
+ return IPSECDOI_AH_SHA512;
+ case IPSECDOI_ATTR_AUTH_DES_MAC:
+ return IPSECDOI_AH_DES;
+ case IPSECDOI_ATTR_AUTH_KPDK:
+ return IPSECDOI_AH_MD5; /* XXX */
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid authentication algorithm:%d\n", alg);
+ }
+ return -1;
+}
+
+#ifdef HAVE_GSSAPI
+struct isakmpsa *
+fixup_initiator_sa(match, received)
+ struct isakmpsa *match, *received;
+{
+ if (received->gssid != NULL)
+ match->gssid = vdup(received->gssid);
+
+ return match;
+}
+#endif
+
+static int rm_idtype2doi[] = {
+ 255, /* IDTYPE_UNDEFINED, 0 */
+ IPSECDOI_ID_FQDN, /* IDTYPE_FQDN, 1 */
+ IPSECDOI_ID_USER_FQDN, /* IDTYPE_USERFQDN, 2 */
+ IPSECDOI_ID_KEY_ID, /* IDTYPE_KEYID, 3 */
+ 255, /* IDTYPE_ADDRESS, 4
+ * it expands into 4 types by another function. */
+ IPSECDOI_ID_DER_ASN1_DN, /* IDTYPE_ASN1DN, 5 */
+};
+
+/*
+ * convert idtype to DOI value.
+ * OUT 255 : NG
+ * other: converted.
+ */
+int
+idtype2doi(idtype)
+ int idtype;
+{
+ if (ARRAYLEN(rm_idtype2doi) > idtype)
+ return rm_idtype2doi[idtype];
+ return 255;
+}
+
+int
+doi2idtype(doi)
+ int doi;
+{
+ switch(doi) {
+ case IPSECDOI_ID_FQDN:
+ return(IDTYPE_FQDN);
+ case IPSECDOI_ID_USER_FQDN:
+ return(IDTYPE_USERFQDN);
+ case IPSECDOI_ID_KEY_ID:
+ return(IDTYPE_KEYID);
+ case IPSECDOI_ID_DER_ASN1_DN:
+ return(IDTYPE_ASN1DN);
+ case IPSECDOI_ID_IPV4_ADDR:
+ case IPSECDOI_ID_IPV4_ADDR_SUBNET:
+ case IPSECDOI_ID_IPV6_ADDR:
+ case IPSECDOI_ID_IPV6_ADDR_SUBNET:
+ return(IDTYPE_ADDRESS);
+ default:
+ plog(LLV_WARNING, LOCATION, NULL,
+ "Inproper idtype:%s in this function.\n",
+ s_ipsecdoi_ident(doi));
+ return(IDTYPE_ADDRESS); /* XXX */
+ }
+ /*NOTREACHED*/
+}
+
+#ifdef ENABLE_HYBRID
+static int
+switch_authmethod(authmethod)
+ int authmethod;
+{
+ switch(authmethod) {
+ case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
+ authmethod = OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I;
+ break;
+ case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
+ authmethod = OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I;
+ break;
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
+ authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I;
+ break;
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
+ authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I;
+ break;
+ /* Those are not implemented */
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
+ authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I;
+ break;
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
+ authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I;
+ break;
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
+ authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I;
+ break;
+ default:
+ break;
+ }
+
+ return authmethod;
+}
+#endif
+
+/*
+ * parse responder-lifetime attributes from payload
+ */
+int
+ipsecdoi_parse_responder_lifetime(notify, lifetime_sec, lifetime_kb)
+ struct isakmp_pl_n *notify;
+ u_int32_t *lifetime_sec;
+ u_int32_t *lifetime_kb;
+{
+ struct isakmp_data *d;
+ int flag, type, tlen, ld_type = -1;
+ u_int16_t lorv;
+ u_int32_t value;
+
+ tlen = ntohs(notify->h.len) - sizeof(*notify) - notify->spi_size;
+ d = (struct isakmp_data *)((char *)(notify + 1) +
+ notify->spi_size);
+
+ while (tlen >= sizeof(struct isakmp_data)) {
+ type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
+ flag = ntohs(d->type) & ISAKMP_GEN_MASK;
+ lorv = ntohs(d->lorv);
+
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "type=%s, flag=0x%04x, lorv=%s\n",
+ s_ipsecdoi_attr(type), flag,
+ s_ipsecdoi_attr_v(type, lorv));
+
+ switch (type) {
+ case IPSECDOI_ATTR_SA_LD_TYPE:
+ if (! flag) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "must be TV when LD_TYPE.\n");
+ return -1;
+ }
+ ld_type = lorv;
+ break;
+ case IPSECDOI_ATTR_SA_LD:
+ if (flag)
+ value = lorv;
+ else if (lorv == 2)
+ value = ntohs(*(u_int16_t *)(d + 1));
+ else if (lorv == 4)
+ value = ntohl(*(u_int32_t *)(d + 1));
+ else {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "payload length %d for lifetime "
+ "data length is unsupported.\n", lorv);
+ return -1;
+ }
+
+ switch (ld_type) {
+ case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
+ if (lifetime_sec != NULL)
+ *lifetime_sec = value;
+ plog(LLV_INFO, LOCATION, NULL,
+ "received RESPONDER-LIFETIME: %d "
+ "seconds\n", value);
+ break;
+ case IPSECDOI_ATTR_SA_LD_TYPE_KB:
+ if (lifetime_kb != NULL)
+ *lifetime_kb = value;
+ plog(LLV_INFO, LOCATION, NULL,
+ "received RESPONDER-LIFETIME: %d "
+ "kbytes\n", value);
+ break;
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "lifetime data received without "
+ "lifetime data type.\n");
+ return -1;
+ }
+ break;
+ }
+
+ if (flag) {
+ tlen -= sizeof(*d);
+ d = (struct isakmp_data *)((char *)d
+ + sizeof(*d));
+ } else {
+ tlen -= (sizeof(*d) + lorv);
+ d = (struct isakmp_data *)((char *)d
+ + sizeof(*d) + lorv);
+ }
+ }
+
+ return 0;
+}
diff --git a/src/racoon/ipsec_doi.c b/src/racoon/ipsec_doi.c
index d0d289b..5890314 100644
--- a/src/racoon/ipsec_doi.c
+++ b/src/racoon/ipsec_doi.c
@@ -1,11 +1,11 @@
-/* $NetBSD: ipsec_doi.c,v 1.23.4.10 2009/06/19 07:32:52 tteras Exp $ */
+/* $NetBSD: ipsec_doi.c,v 1.46 2010/12/14 17:57:31 tteras Exp $ */
/* Id: ipsec_doi.c,v 1.55 2006/08/17 09:20:41 vanhu Exp */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -17,7 +17,7 @@
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -83,9 +83,6 @@
#ifdef ENABLE_NATT
#include "nattraversal.h"
#endif
-#ifdef ENABLE_HYBRID
-static int switch_authmethod(int);
-#endif
#ifdef HAVE_GSSAPI
#include <iconv.h>
@@ -97,19 +94,19 @@ static int switch_authmethod(int);
#endif
#endif
-int verbose_proposal_check = 1;
+static vchar_t *get_ph1approval __P((struct ph1handle *, u_int32_t, u_int32_t,
+ struct prop_pair **));
+static int get_ph1approvalx __P((struct remoteconf *, void *));
-static vchar_t *get_ph1approval __P((struct ph1handle *, struct prop_pair **));
-static struct isakmpsa *get_ph1approvalx __P((struct prop_pair *,
- struct isakmpsa *, struct isakmpsa *, int));
-static void print_ph1mismatched __P((struct prop_pair *, struct isakmpsa *));
-static int t2isakmpsa __P((struct isakmp_pl_t *, struct isakmpsa *));
+static int t2isakmpsa __P((struct isakmp_pl_t *, struct isakmpsa *, u_int32_t));
static int cmp_aproppair_i __P((struct prop_pair *, struct prop_pair *));
static struct prop_pair *get_ph2approval __P((struct ph2handle *,
struct prop_pair **));
static struct prop_pair *get_ph2approvalx __P((struct ph2handle *,
struct prop_pair *));
static void free_proppair0 __P((struct prop_pair *));
+static struct prop_pair ** get_proppair_and_doi_sit __P((vchar_t *, int,
+ u_int32_t *, u_int32_t *));
static int get_transform
__P((struct isakmp_pl_p *, struct prop_pair **, int *));
@@ -158,12 +155,10 @@ static int setph1attr __P((struct isakmpsa *, caddr_t));
static vchar_t *setph2proposal0 __P((const struct ph2handle *,
const struct saprop *, const struct saproto *));
-static vchar_t *getidval __P((int, vchar_t *));
-
-#ifdef HAVE_GSSAPI
-static struct isakmpsa *fixup_initiator_sa __P((struct isakmpsa *,
- struct isakmpsa *));
-#endif
+struct ph1approvalx_ctx {
+ struct prop_pair *p;
+ struct isakmpsa *sa;
+};
/*%%%*/
/*
@@ -182,40 +177,82 @@ ipsecdoi_checkph1proposal(sa, iph1)
{
vchar_t *newsa; /* new SA payload approved. */
struct prop_pair **pair;
+ u_int32_t doitype, sittype;
/* get proposal pair */
- pair = get_proppair(sa, IPSECDOI_TYPE_PH1);
+ pair = get_proppair_and_doi_sit(sa, IPSECDOI_TYPE_PH1,
+ &doitype, &sittype);
if (pair == NULL)
return -1;
/* check and get one SA for use */
- newsa = get_ph1approval(iph1, pair);
-
+ newsa = get_ph1approval(iph1, doitype, sittype, pair);
free_proppair(pair);
if (newsa == NULL)
return -1;
iph1->sa_ret = newsa;
-
return 0;
}
+static void
+print_ph1proposal(pair, s)
+ struct prop_pair *pair;
+ struct isakmpsa *s;
+{
+ struct isakmp_pl_p *prop = pair->prop;
+ struct isakmp_pl_t *trns = pair->trns;
+
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "prop#=%d, prot-id=%s, spi-size=%d, #trns=%d\n",
+ prop->p_no, s_ipsecdoi_proto(prop->proto_id),
+ prop->spi_size, prop->num_t);
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "trns#=%d, trns-id=%s\n",
+ trns->t_no, s_ipsecdoi_trns(prop->proto_id, trns->t_id));
+ plog(LLV_DEBUG, LOCATION, NULL,
+ " lifetime = %ld\n", (long) s->lifetime);
+ plog(LLV_DEBUG, LOCATION, NULL,
+ " lifebyte = %zu\n", s->lifebyte);
+ plog(LLV_DEBUG, LOCATION, NULL,
+ " enctype = %s\n",
+ s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG, s->enctype));
+ plog(LLV_DEBUG, LOCATION, NULL,
+ " encklen = %d\n", s->encklen);
+ plog(LLV_DEBUG, LOCATION, NULL,
+ " hashtype = %s\n",
+ s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG, s->hashtype));
+ plog(LLV_DEBUG, LOCATION, NULL,
+ " authmethod = %s\n",
+ s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD, s->authmethod));
+ plog(LLV_DEBUG, LOCATION, NULL,
+ " dh_group = %s\n",
+ s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC, s->dh_group));
+}
+
+
/*
* acceptable check for remote configuration.
* return a new SA payload to be reply to peer.
*/
+
static vchar_t *
-get_ph1approval(iph1, pair)
+get_ph1approval(iph1, doitype, sittype, pair)
struct ph1handle *iph1;
+ u_int32_t doitype, sittype;
struct prop_pair **pair;
{
vchar_t *newsa;
- struct isakmpsa *sa, tsa;
+ struct ph1approvalx_ctx ctx;
struct prop_pair *s, *p;
- int prophlen;
+ struct rmconfselector rmsel;
+ struct isakmpsa *sa;
int i;
+ memset(&rmsel, 0, sizeof(rmsel));
+ rmsel.remote = iph1->remote;
+
if (iph1->approval) {
delisakmpsa(iph1->approval);
iph1->approval = NULL;
@@ -225,42 +262,35 @@ get_ph1approval(iph1, pair)
if (pair[i] == NULL)
continue;
for (s = pair[i]; s; s = s->next) {
- prophlen =
- sizeof(struct isakmp_pl_p) + s->prop->spi_size;
-
/* compare proposal and select one */
for (p = s; p; p = p->tnext) {
- if ((sa = get_ph1approvalx(p,
- iph1->rmconf->proposal, &tsa,
- iph1->rmconf->pcheck_level)) != NULL)
- goto found;
- }
- }
- }
+ struct isakmp_pl_p *prop = p->prop;
- /*
- * if there is no suitable proposal, racoon complains about all of
- * mismatched items in those proposal.
- */
- if (verbose_proposal_check) {
- for (i = 0; i < MAXPROPPAIRLEN; i++) {
- if (pair[i] == NULL)
- continue;
- for (s = pair[i]; s; s = s->next) {
- prophlen = sizeof(struct isakmp_pl_p)
- + s->prop->spi_size;
- for (p = s; p; p = p->tnext) {
- print_ph1mismatched(p,
- iph1->rmconf->proposal);
+ sa = newisakmpsa();
+ ctx.p = p;
+ ctx.sa = sa;
+ if (t2isakmpsa(p->trns, sa,
+ iph1->vendorid_mask) < 0)
+ continue;
+ print_ph1proposal(p, sa);
+ if (iph1->rmconf != NULL) {
+ if (get_ph1approvalx(iph1->rmconf, &ctx))
+ goto found;
+ } else {
+ if (enumrmconf(&rmsel, get_ph1approvalx, &ctx))
+ goto found;
}
+ delisakmpsa(sa);
}
}
}
+
plog(LLV_ERROR, LOCATION, NULL, "no suitable proposal found.\n");
return NULL;
found:
+ sa = ctx.sa;
plog(LLV_DEBUG, LOCATION, NULL, "an acceptable proposal found.\n");
/* check DH group settings */
@@ -277,7 +307,7 @@ found:
if (oakley_setdhgroup(sa->dh_group, &sa->dhgrp) == -1) {
sa->dhgrp = NULL;
- racoon_free(sa);
+ delisakmpsa(sa);
return NULL;
}
@@ -286,20 +316,16 @@ saok:
if (sa->gssid != NULL)
plog(LLV_DEBUG, LOCATION, NULL, "gss id in new sa '%.*s'\n",
(int)sa->gssid->l, sa->gssid->v);
- if (iph1-> side == INITIATOR) {
+ if (iph1->side == INITIATOR) {
if (iph1->rmconf->proposal->gssid != NULL)
iph1->gi_i = vdup(iph1->rmconf->proposal->gssid);
- if (tsa.gssid != NULL)
- iph1->gi_r = vdup(tsa.gssid);
- iph1->approval = fixup_initiator_sa(sa, &tsa);
+ if (sa->gssid != NULL)
+ iph1->gi_r = vdup(sa->gssid);
} else {
- if (tsa.gssid != NULL) {
- iph1->gi_r = vdup(tsa.gssid);
+ if (sa->gssid != NULL) {
+ iph1->gi_r = vdup(sa->gssid);
iph1->gi_i = gssapi_get_id(iph1);
- if (sa->gssid == NULL && iph1->gi_i != NULL)
- sa->gssid = vdup(iph1->gi_i);
}
- iph1->approval = sa;
}
if (iph1->gi_i != NULL)
plog(LLV_DEBUG, LOCATION, NULL, "GIi is %.*s\n",
@@ -307,19 +333,15 @@ saok:
if (iph1->gi_r != NULL)
plog(LLV_DEBUG, LOCATION, NULL, "GIr is %.*s\n",
(int)iph1->gi_r->l, iph1->gi_r->v);
-#else
- iph1->approval = sa;
#endif
- if(iph1->approval) {
- plog(LLV_DEBUG, LOCATION, NULL, "agreed on %s auth.\n",
- s_oakley_attr_method(iph1->approval->authmethod));
- }
+ plog(LLV_DEBUG, LOCATION, NULL, "agreed on %s auth.\n",
+ s_oakley_attr_method(sa->authmethod));
- newsa = get_sabyproppair(p, iph1);
- if (newsa == NULL){
- delisakmpsa(iph1->approval);
- iph1->approval = NULL;
- }
+ newsa = get_sabyproppair(doitype, sittype, p);
+ if (newsa == NULL)
+ delisakmpsa(sa);
+ else
+ iph1->approval = sa;
return newsa;
}
@@ -327,228 +349,57 @@ saok:
/*
* compare peer's single proposal and all of my proposal.
* and select one if suiatable.
- * p : one of peer's proposal.
- * proposal: my proposals.
*/
-static struct isakmpsa *
-get_ph1approvalx(p, proposal, sap, check_level)
- struct prop_pair *p;
- struct isakmpsa *proposal, *sap;
- int check_level;
+static int
+get_ph1approvalx(rmconf, ctx)
+ struct remoteconf *rmconf;
+ void *ctx;
{
- struct isakmp_pl_p *prop = p->prop;
- struct isakmp_pl_t *trns = p->trns;
- struct isakmpsa sa, *s, *tsap;
- int authmethod;
-
- plog(LLV_DEBUG, LOCATION, NULL,
- "prop#=%d, prot-id=%s, spi-size=%d, #trns=%d\n",
- prop->p_no, s_ipsecdoi_proto(prop->proto_id),
- prop->spi_size, prop->num_t);
-
- plog(LLV_DEBUG, LOCATION, NULL,
- "trns#=%d, trns-id=%s\n",
- trns->t_no,
- s_ipsecdoi_trns(prop->proto_id, trns->t_id));
-
- tsap = sap != NULL ? sap : &sa;
-
- memset(tsap, 0, sizeof(*tsap));
- if (t2isakmpsa(trns, tsap) < 0)
- return NULL;
- for (s = proposal; s != NULL; s = s->next) {
-#ifdef ENABLE_HYBRID
- authmethod = switch_authmethod(s->authmethod);
-#else
- authmethod = s->authmethod;
-#endif
- plog(LLV_DEBUG, LOCATION, NULL, "Compared: DB:Peer\n");
- plog(LLV_DEBUG, LOCATION, NULL, "(lifetime = %ld:%ld)\n",
- (long)s->lifetime, (long)tsap->lifetime);
- plog(LLV_DEBUG, LOCATION, NULL, "(lifebyte = %zu:%zu)\n",
- s->lifebyte, tsap->lifebyte);
- plog(LLV_DEBUG, LOCATION, NULL, "enctype = %s:%s\n",
- s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG,
- s->enctype),
- s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG,
- tsap->enctype));
- plog(LLV_DEBUG, LOCATION, NULL, "(encklen = %d:%d)\n",
- s->encklen, tsap->encklen);
- plog(LLV_DEBUG, LOCATION, NULL, "hashtype = %s:%s\n",
- s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG,
- s->hashtype),
- s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG,
- tsap->hashtype));
- plog(LLV_DEBUG, LOCATION, NULL, "authmethod = %s:%s\n",
- s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD,
- s->authmethod),
- s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD,
- tsap->authmethod));
- plog(LLV_DEBUG, LOCATION, NULL, "dh_group = %s:%s\n",
- s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC,
- s->dh_group),
- s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC,
- tsap->dh_group));
-#if 0
- /* XXX to be considered ? */
- if (tsap->lifebyte > s->lifebyte) ;
-#endif
- /*
- * if responder side and peer's key length in proposal
- * is bigger than mine, it might be accepted.
- */
- if(tsap->enctype == s->enctype &&
- tsap->authmethod == authmethod &&
- tsap->hashtype == s->hashtype &&
- tsap->dh_group == s->dh_group &&
- tsap->encklen == s->encklen) {
- switch(check_level) {
- case PROP_CHECK_OBEY:
- goto found;
- break;
-
- case PROP_CHECK_STRICT:
- if ((tsap->lifetime > s->lifetime) ||
- (tsap->lifebyte > s->lifebyte))
- continue;
- goto found;
- break;
-
- case PROP_CHECK_CLAIM:
- if (tsap->lifetime < s->lifetime)
- s->lifetime = tsap->lifetime;
- if (tsap->lifebyte < s->lifebyte)
- s->lifebyte = tsap->lifebyte;
- goto found;
- break;
+ struct ph1approvalx_ctx *pctx = (struct ph1approvalx_ctx *) ctx;
+ struct isakmpsa *sa;
- case PROP_CHECK_EXACT:
- if ((tsap->lifetime != s->lifetime) ||
- (tsap->lifebyte != s->lifebyte))
- continue;
- goto found;
- break;
+ /* do the hard work */
+ sa = checkisakmpsa(rmconf->pcheck_level, pctx->sa, rmconf->proposal);
+ if (sa == NULL)
+ return 0;
- default:
- plog(LLV_ERROR, LOCATION, NULL,
- "Unexpected proposal_check value\n");
- continue;
- break;
- }
- }
- }
+ /* duplicate and modify the found SA to match proposal */
+ sa = dupisakmpsa(sa);
-found:
- if (tsap->dhgrp != NULL){
- oakley_dhgrp_free(tsap->dhgrp);
- tsap->dhgrp = NULL;
+ switch (rmconf->pcheck_level) {
+ case PROP_CHECK_OBEY:
+ sa->lifetime = pctx->sa->lifetime;
+ sa->lifebyte = pctx->sa->lifebyte;
+ sa->encklen = pctx->sa->encklen;
+ break;
+ case PROP_CHECK_CLAIM:
+ case PROP_CHECK_STRICT:
+ if (pctx->sa->lifetime < sa->lifetime)
+ sa->lifetime = pctx->sa->lifetime;
+ if (pctx->sa->lifebyte < sa->lifebyte)
+ sa->lifebyte = pctx->sa->lifebyte;
+ if (pctx->sa->encklen > sa->encklen)
+ sa->encklen = pctx->sa->encklen;
+ break;
+ default:
+ break;
}
- if ((s = dupisakmpsa(s)) != NULL) {
- switch(check_level) {
- case PROP_CHECK_OBEY:
- s->lifetime = tsap->lifetime;
- s->lifebyte = tsap->lifebyte;
- break;
-
- case PROP_CHECK_STRICT:
- s->lifetime = tsap->lifetime;
- s->lifebyte = tsap->lifebyte;
- break;
-
- case PROP_CHECK_CLAIM:
- if (tsap->lifetime < s->lifetime)
- s->lifetime = tsap->lifetime;
- if (tsap->lifebyte < s->lifebyte)
- s->lifebyte = tsap->lifebyte;
- break;
+ /* replace the proposal with our approval sa */
+ delisakmpsa(pctx->sa);
+ pctx->sa = sa;
- default:
- break;
- }
- }
- return s;
-}
-
-/*
- * print all of items in peer's proposal which are mismatched to my proposal.
- * p : one of peer's proposal.
- * proposal: my proposals.
- */
-static void
-print_ph1mismatched(p, proposal)
- struct prop_pair *p;
- struct isakmpsa *proposal;
-{
- struct isakmpsa sa, *s;
-
- memset(&sa, 0, sizeof(sa));
- if (t2isakmpsa(p->trns, &sa) < 0)
- return;
- for (s = proposal; s ; s = s->next) {
- if (sa.enctype != s->enctype) {
- plog(LLV_ERROR, LOCATION, NULL,
- "rejected enctype: "
- "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
- "%s:%s\n",
- s->prop_no, s->trns_no,
- p->prop->p_no, p->trns->t_no,
- s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG,
- s->enctype),
- s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG,
- sa.enctype));
- }
- if (sa.authmethod != s->authmethod) {
- plog(LLV_ERROR, LOCATION, NULL,
- "rejected authmethod: "
- "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
- "%s:%s\n",
- s->prop_no, s->trns_no,
- p->prop->p_no, p->trns->t_no,
- s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD,
- s->authmethod),
- s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD,
- sa.authmethod));
- }
- if (sa.hashtype != s->hashtype) {
- plog(LLV_ERROR, LOCATION, NULL,
- "rejected hashtype: "
- "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
- "%s:%s\n",
- s->prop_no, s->trns_no,
- p->prop->p_no, p->trns->t_no,
- s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG,
- s->hashtype),
- s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG,
- sa.hashtype));
- }
- if (sa.dh_group != s->dh_group) {
- plog(LLV_ERROR, LOCATION, NULL,
- "rejected dh_group: "
- "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = "
- "%s:%s\n",
- s->prop_no, s->trns_no,
- p->prop->p_no, p->trns->t_no,
- s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC,
- s->dh_group),
- s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC,
- sa.dh_group));
- }
- }
-
- if (sa.dhgrp != NULL){
- oakley_dhgrp_free(sa.dhgrp);
- sa.dhgrp=NULL;
- }
+ return 1;
}
/*
* get ISAKMP data attributes
*/
static int
-t2isakmpsa(trns, sa)
+t2isakmpsa(trns, sa, vendorid_mask)
struct isakmp_pl_t *trns;
struct isakmpsa *sa;
+ u_int32_t vendorid_mask;
{
struct isakmp_data *d, *prev;
int flag, type;
@@ -618,6 +469,11 @@ t2isakmpsa(trns, sa)
case OAKLEY_ATTR_AUTH_METHOD:
sa->authmethod = ntohs(d->lorv);
+#ifdef HAVE_GSSAPI
+ if (sa->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB_REAL &&
+ (vendorid_mask & VENDORID_GSSAPI_MASK))
+ sa->authmethod = OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB;
+#endif
break;
case OAKLEY_ATTR_GRP_DESC:
@@ -770,7 +626,7 @@ t2isakmpsa(trns, sa)
plog(LLV_DEBUG, LOCATION, NULL,
"received old-style gss "
"id '%.*s' (len %zu)\n",
- (int)sa->gssid->l, sa->gssid->v,
+ (int)sa->gssid->l, sa->gssid->v,
sa->gssid->l);
error = 0;
goto out;
@@ -805,7 +661,7 @@ t2isakmpsa(trns, sa)
dst = sa->gssid->v;
dstleft = len / 2;
- rv = iconv(cd, (__iconv_const char **)&src, &srcleft,
+ rv = iconv(cd, (__iconv_const char **)&src, &srcleft,
&dst, &dstleft);
if (rv != 0) {
if (rv == -1) {
@@ -891,9 +747,11 @@ ipsecdoi_selectph2proposal(iph2)
{
struct prop_pair **pair;
struct prop_pair *ret;
+ u_int32_t doitype, sittype;
/* get proposal pair */
- pair = get_proppair(iph2->sa, IPSECDOI_TYPE_PH2);
+ pair = get_proppair_and_doi_sit(iph2->sa, IPSECDOI_TYPE_PH2,
+ &doitype, &sittype);
if (pair == NULL)
return -1;
@@ -905,7 +763,7 @@ ipsecdoi_selectph2proposal(iph2)
/* make a SA to be replayed. */
/* SPI must be updated later. */
- iph2->sa_ret = get_sabyproppair(ret, iph2->ph1);
+ iph2->sa_ret = get_sabyproppair(doitype, sittype, ret);
free_proppair0(ret);
if (iph2->sa_ret == NULL)
return -1;
@@ -929,9 +787,11 @@ ipsecdoi_checkph2proposal(iph2)
int i, n, num;
int error = -1;
vchar_t *sa_ret = NULL;
+ u_int32_t doitype, sittype;
/* get proposal pair of SA sent. */
- spair = get_proppair(iph2->sa, IPSECDOI_TYPE_PH2);
+ spair = get_proppair_and_doi_sit(iph2->sa, IPSECDOI_TYPE_PH2,
+ &doitype, &sittype);
if (spair == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
"failed to get prop pair.\n");
@@ -972,7 +832,7 @@ ipsecdoi_checkph2proposal(iph2)
plog(LLV_WARNING, LOCATION, NULL,
"invalid proposal number:%d received.\n", i);
}
-
+
if (rpair[n]->tnext != NULL) {
plog(LLV_ERROR, LOCATION, NULL,
@@ -997,7 +857,7 @@ ipsecdoi_checkph2proposal(iph2)
/* make a SA to be replayed. */
sa_ret = iph2->sa_ret;
- iph2->sa_ret = get_sabyproppair(p, iph2->ph1);
+ iph2->sa_ret = get_sabyproppair(doitype, sittype, p);
free_proppair0(p);
if (iph2->sa_ret == NULL)
goto end;
@@ -1282,10 +1142,11 @@ free_proppair0(pair)
* get proposal pairs from SA payload.
* tiny check for proposal payload.
*/
-struct prop_pair **
-get_proppair(sa, mode)
+static struct prop_pair **
+get_proppair_and_doi_sit(sa, mode, doitype, sittype)
vchar_t *sa;
int mode;
+ u_int32_t *doitype, *sittype;
{
struct prop_pair **pair = NULL;
int num_p = 0; /* number of proposal for use */
@@ -1307,10 +1168,14 @@ get_proppair(sa, mode)
/* check DOI */
if (check_doi(ntohl(sab->doi)) < 0)
goto bad;
+ if (doitype != NULL)
+ *doitype = ntohl(sab->doi);
/* check SITUATION */
if (check_situation(ntohl(sab->sit)) < 0)
goto bad;
+ if (sittype != NULL)
+ *sittype = ntohl(sab->sit);
pair = racoon_calloc(1, MAXPROPPAIRLEN * sizeof(*pair));
if (pair == NULL) {
@@ -1446,6 +1311,15 @@ bad:
return NULL;
}
+struct prop_pair **
+get_proppair(sa, mode)
+ vchar_t *sa;
+ int mode;
+{
+ return get_proppair_and_doi_sit(sa, mode, NULL, NULL);
+}
+
+
/*
* check transform payload.
* OUT:
@@ -1560,9 +1434,9 @@ get_transform(prop, pair, num_p)
* NOTE: this function make spi value clear.
*/
vchar_t *
-get_sabyproppair(pair, iph1)
+get_sabyproppair(doitype, sittype, pair)
+ u_int32_t doitype, sittype;
struct prop_pair *pair;
- struct ph1handle *iph1;
{
vchar_t *newsa;
int newtlen;
@@ -1588,8 +1462,8 @@ get_sabyproppair(pair, iph1)
((struct isakmp_gen *)bp)->len = htons(newtlen);
/* update some of values in SA header */
- ((struct ipsecdoi_sa_b *)bp)->doi = htonl(iph1->rmconf->doitype);
- ((struct ipsecdoi_sa_b *)bp)->sit = htonl(iph1->rmconf->sittype);
+ ((struct ipsecdoi_sa_b *)bp)->doi = htonl(doitype);
+ ((struct ipsecdoi_sa_b *)bp)->sit = htonl(sittype);
bp += sizeof(struct ipsecdoi_sa_b);
/* create proposal payloads */
@@ -1824,6 +1698,96 @@ ipsecdoi_set_ld(buf)
return ld;
}
+/*
+ * parse responder-lifetime attributes from payload
+ */
+int
+ipsecdoi_parse_responder_lifetime(notify, lifetime_sec, lifetime_kb)
+ struct isakmp_pl_n *notify;
+ u_int32_t *lifetime_sec;
+ u_int32_t *lifetime_kb;
+{
+ struct isakmp_data *d;
+ int flag, type, tlen, ld_type = -1;
+ u_int16_t lorv;
+ u_int32_t value;
+
+ tlen = ntohs(notify->h.len) - sizeof(*notify) - notify->spi_size;
+ d = (struct isakmp_data *)((char *)(notify + 1) +
+ notify->spi_size);
+
+ while (tlen >= sizeof(struct isakmp_data)) {
+ type = ntohs(d->type) & ~ISAKMP_GEN_MASK;
+ flag = ntohs(d->type) & ISAKMP_GEN_MASK;
+ lorv = ntohs(d->lorv);
+
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "type=%s, flag=0x%04x, lorv=%s\n",
+ s_ipsecdoi_attr(type), flag,
+ s_ipsecdoi_attr_v(type, lorv));
+
+ switch (type) {
+ case IPSECDOI_ATTR_SA_LD_TYPE:
+ if (! flag) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "must be TV when LD_TYPE.\n");
+ return -1;
+ }
+ ld_type = lorv;
+ break;
+ case IPSECDOI_ATTR_SA_LD:
+ if (flag)
+ value = lorv;
+ else if (lorv == 2)
+ value = ntohs(*(u_int16_t *)(d + 1));
+ else if (lorv == 4)
+ value = ntohl(*(u_int32_t *)(d + 1));
+ else {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "payload length %d for lifetime "
+ "data length is unsupported.\n", lorv);
+ return -1;
+ }
+
+ switch (ld_type) {
+ case IPSECDOI_ATTR_SA_LD_TYPE_SEC:
+ if (lifetime_sec != NULL)
+ *lifetime_sec = value;
+ plog(LLV_INFO, LOCATION, NULL,
+ "received RESPONDER-LIFETIME: %d "
+ "seconds\n", value);
+ break;
+ case IPSECDOI_ATTR_SA_LD_TYPE_KB:
+ if (lifetime_kb != NULL)
+ *lifetime_kb = value;
+ plog(LLV_INFO, LOCATION, NULL,
+ "received RESPONDER-LIFETIME: %d "
+ "kbytes\n", value);
+ break;
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "lifetime data received without "
+ "lifetime data type.\n");
+ return -1;
+ }
+ break;
+ }
+
+ if (flag) {
+ tlen -= sizeof(*d);
+ d = (struct isakmp_data *)((char *)d
+ + sizeof(*d));
+ } else {
+ tlen -= (sizeof(*d) + lorv);
+ d = (struct isakmp_data *)((char *)d
+ + sizeof(*d) + lorv);
+ }
+ }
+
+ return 0;
+}
+
+
/*%%%*/
/*
* check DOI
@@ -2130,11 +2094,12 @@ check_attr_isakmp(trns)
#ifdef ENABLE_HYBRID
case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
-#if 0 /* Clashes with OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB */
- case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I:
#endif
+#if defined(ENABLE_HYBRID) || defined(HAVE_GSSAPI)
+ /* These two authentication method IDs overlap. */
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I:
+ /*case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:*/
#endif
- case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
break;
case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
#ifdef ENABLE_HYBRID
@@ -2351,7 +2316,7 @@ ahmismatch:
if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
if (trns->t_id != IPSECDOI_AH_SHA256)
goto ahmismatch;
- }
+ }
break;
case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384:
if (proto_id == IPSECDOI_PROTO_IPSEC_AH) {
@@ -2638,7 +2603,8 @@ check_attr_ipcomp(trns)
* NOT INCLUDING isakmp general header of SA payload
*/
vchar_t *
-ipsecdoi_setph1proposal(props)
+ipsecdoi_setph1proposal(rmconf, props)
+ struct remoteconf *rmconf;
struct isakmpsa *props;
{
vchar_t *mysa;
@@ -2658,8 +2624,8 @@ ipsecdoi_setph1proposal(props)
/* create SA payload */
/* not including isakmp general header */
- ((struct ipsecdoi_sa_b *)mysa->v)->doi = htonl(props->rmconf->doitype);
- ((struct ipsecdoi_sa_b *)mysa->v)->sit = htonl(props->rmconf->sittype);
+ ((struct ipsecdoi_sa_b *)mysa->v)->doi = htonl(rmconf->doitype);
+ ((struct ipsecdoi_sa_b *)mysa->v)->sit = htonl(rmconf->sittype);
(void)setph1prop(props, mysa->v + sizeof(struct ipsecdoi_sa_b));
@@ -2767,7 +2733,7 @@ setph1attr(sa, buf)
OAKLEY_ATTR_SA_LD_TYPE_SEC);
if (sa->lifetime > 0xffff) {
p = isakmp_set_attr_v(p, OAKLEY_ATTR_SA_LD,
- (caddr_t)&lifetime,
+ (caddr_t)&lifetime,
sizeof(lifetime));
} else {
p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD,
@@ -2778,7 +2744,7 @@ setph1attr(sa, buf)
if (sa->lifebyte) {
u_int32_t lifebyte = htonl((u_int32_t)sa->lifebyte);
-
+
attrlen += sizeof(struct isakmp_data)
+ sizeof(struct isakmp_data);
if (sa->lifebyte > 0xffff)
@@ -2810,11 +2776,8 @@ setph1attr(sa, buf)
if (sa->authmethod) {
int authmethod;
-#ifdef ENABLE_HYBRID
- authmethod = switch_authmethod(sa->authmethod);
-#else
- authmethod = sa->authmethod;
-#endif
+ authmethod = isakmpsa_switch_authmethod(sa->authmethod);
+ authmethod &= 0xffff;
attrlen += sizeof(struct isakmp_data);
if (buf)
p = isakmp_set_attr_l(p, OAKLEY_ATTR_AUTH_METHOD, authmethod);
@@ -2896,7 +2859,7 @@ setph1attr(sa, buf)
goto gssid_done;
}
odst = dst;
- rv = iconv(cd, (__iconv_const char **)&src,
+ rv = iconv(cd, (__iconv_const char **)&src,
&srcleft, &dst, &dstleft);
if (rv != 0) {
if (rv == -1) {
@@ -2989,7 +2952,7 @@ setph2proposal0(iph2, pp, pr)
np_t = NULL;
for (tr = pr->head; tr; tr = tr->next) {
-
+
switch (pr->proto_id) {
case IPSECDOI_PROTO_IPSEC_ESP:
/*
@@ -3237,7 +3200,9 @@ ipsecdoi_transportmode(pp)
for (; pp; pp = pp->next) {
for (pr = pp->head; pr; pr = pr->next) {
- if (pr->encmode != IPSECDOI_ATTR_ENC_MODE_TRNS)
+ if (pr->encmode != IPSECDOI_ATTR_ENC_MODE_TRNS &&
+ pr->encmode != IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC &&
+ pr->encmode != IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT)
return 0;
}
}
@@ -3597,8 +3562,6 @@ ipsecdoi_checkid1(iph1)
struct ph1handle *iph1;
{
struct ipsecdoi_id_b *id_b;
- struct sockaddr *sa;
- caddr_t sa1, sa2;
if (iph1->id_p == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
@@ -3614,7 +3577,6 @@ ipsecdoi_checkid1(iph1)
id_b = (struct ipsecdoi_id_b *)iph1->id_p->v;
-#ifndef ANDROID_PATCHED
/* In main mode with pre-shared key, only address type can be used. */
if (iph1->etype == ISAKMP_ETYPE_IDENT &&
iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_PSKEY) {
@@ -3626,7 +3588,6 @@ ipsecdoi_checkid1(iph1)
return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
}
}
-#endif
/* if proper type for phase 1 ? */
switch (id_b->type) {
@@ -3670,73 +3631,12 @@ ipsecdoi_checkid1(iph1)
}
}
- /* compare with the ID if specified. */
- if (genlist_next(iph1->rmconf->idvl_p, 0)) {
- vchar_t *ident0 = NULL;
- vchar_t ident;
- struct idspec *id;
- struct genlist_entry *gpb;
-
- for (id = genlist_next (iph1->rmconf->idvl_p, &gpb); id; id = genlist_next (0, &gpb)) {
- /* check the type of both IDs */
- if (id->idtype != doi2idtype(id_b->type))
- continue; /* ID type mismatch */
- if (id->id == 0)
- goto matched;
-
- /* compare defined ID with the ID sent by peer. */
- if (ident0 != NULL)
- vfree(ident0);
- ident0 = getidval(id->idtype, id->id);
-
- switch (id->idtype) {
- case IDTYPE_ASN1DN:
- ident.v = iph1->id_p->v + sizeof(*id_b);
- ident.l = iph1->id_p->l - sizeof(*id_b);
- if (eay_cmp_asn1dn(ident0, &ident) == 0)
- goto matched;
- break;
- case IDTYPE_ADDRESS:
- sa = (struct sockaddr *)ident0->v;
- sa2 = (caddr_t)(id_b + 1);
- switch (sa->sa_family) {
- case AF_INET:
- if (iph1->id_p->l - sizeof(*id_b) != sizeof(struct in_addr))
- continue; /* ID value mismatch */
- sa1 = (caddr_t)&((struct sockaddr_in *)sa)->sin_addr;
- if (memcmp(sa1, sa2, sizeof(struct in_addr)) == 0)
- goto matched;
- break;
-#ifdef INET6
- case AF_INET6:
- if (iph1->id_p->l - sizeof(*id_b) != sizeof(struct in6_addr))
- continue; /* ID value mismatch */
- sa1 = (caddr_t)&((struct sockaddr_in6 *)sa)->sin6_addr;
- if (memcmp(sa1, sa2, sizeof(struct in6_addr)) == 0)
- goto matched;
- break;
-#endif
- default:
- break;
- }
- break;
- default:
- if (memcmp(ident0->v, id_b + 1, ident0->l) == 0)
- goto matched;
- break;
- }
- }
- if (ident0 != NULL) {
- vfree(ident0);
- ident0 = NULL;
- }
- plog(LLV_WARNING, LOCATION, NULL, "No ID match.\n");
- if (iph1->rmconf->verify_identifier)
- return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
-matched: /* ID value match */
- if (ident0 != NULL)
- vfree(ident0);
- }
+ /* resolve remote configuration if not done yet */
+ if (resolveph1rmconf(iph1) < 0)
+ return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
+
+ if (iph1->rmconf == NULL)
+ return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
return 0;
}
@@ -3763,15 +3663,15 @@ ipsecdoi_setid1(iph1)
switch (iph1->rmconf->idvtype) {
case IDTYPE_FQDN:
id_b.type = IPSECDOI_ID_FQDN;
- ident = getidval(iph1->rmconf->idvtype, iph1->rmconf->idv);
+ ident = vdup(iph1->rmconf->idv);
break;
case IDTYPE_USERFQDN:
id_b.type = IPSECDOI_ID_USER_FQDN;
- ident = getidval(iph1->rmconf->idvtype, iph1->rmconf->idv);
+ ident = vdup(iph1->rmconf->idv);
break;
case IDTYPE_KEYID:
id_b.type = IPSECDOI_ID_KEY_ID;
- ident = getidval(iph1->rmconf->idvtype, iph1->rmconf->idv);
+ ident = vdup(iph1->rmconf->idv);
break;
case IDTYPE_ASN1DN:
id_b.type = IPSECDOI_ID_DER_ASN1_DN;
@@ -3784,7 +3684,7 @@ ipsecdoi_setid1(iph1)
"failed to get own CERT.\n");
goto err;
}
- ident = eay_get_x509asn1subjectname(&iph1->cert->cert);
+ ident = eay_get_x509asn1subjectname(iph1->cert);
}
break;
case IDTYPE_ADDRESS:
@@ -3829,7 +3729,7 @@ ipsecdoi_setid1(iph1)
if (!ident) {
plog(LLV_ERROR, LOCATION, NULL,
"failed to get ID buffer.\n");
- return 0;
+ return -1;
}
memcpy(ident->v, p, ident->l);
}
@@ -3837,7 +3737,7 @@ ipsecdoi_setid1(iph1)
if (!ident) {
plog(LLV_ERROR, LOCATION, NULL,
"failed to get ID buffer.\n");
- return 0;
+ return -1;
}
ret = vmalloc(sizeof(id_b) + ident->l);
@@ -3865,21 +3765,6 @@ err:
return -1;
}
-static vchar_t *
-getidval(type, val)
- int type;
- vchar_t *val;
-{
- vchar_t *new = NULL;
-
- if (val)
- new = vdup(val);
- else if (lcconf->ident[type])
- new = vdup(lcconf->ident[type]);
-
- return new;
-}
-
/* it's only called by cfparse.y. */
int
set_identifier(vpp, type, value)
@@ -3922,9 +3807,9 @@ set_identifier_qual(vpp, type, value, qual)
memcpy(new->v, value->v, new->l);
break;
case IDTYPE_KEYID:
- /*
+ /*
* If no qualifier is specified: IDQUAL_UNSPEC. It means
- * to use a file for backward compatibility sake.
+ * to use a file for backward compatibility sake.
*/
switch(qual) {
case IDQUAL_FILE:
@@ -3969,7 +3854,7 @@ set_identifier_qual(vpp, type, value, qual)
return -1;
}
break;
-
+
case IDTYPE_ADDRESS: {
struct sockaddr *sa;
@@ -4013,7 +3898,7 @@ set_identifier_qual(vpp, type, value, qual)
xn = d2i_X509_NAME(NULL, (void *)&ptr, new->l);
bio = BIO_new(BIO_s_mem());
-
+
X509_NAME_print_ex(bio, xn, 0, 0);
len = BIO_get_mem_data(bio, &ptr);
save = ptr[len];
@@ -4053,8 +3938,25 @@ ipsecdoi_setid2(iph2)
return -1;
}
- iph2->id = ipsecdoi_sockaddr2id((struct sockaddr *)&sp->spidx.src,
- sp->spidx.prefs, sp->spidx.ul_proto);
+ if (!ipsecdoi_transportmode(iph2->proposal))
+ iph2->id = ipsecdoi_sockaddr2id((struct sockaddr *)&sp->spidx.src,
+ sp->spidx.prefs, sp->spidx.ul_proto);
+ else if (iph2->sa_src != NULL) {
+ /* He have a specific hint indicating that the transport
+ * mode SA will be negotiated using addresses that differ
+ * with the one from the SA. We need to indicate that to
+ * our peer by setting the SA address as ID.
+ * This is typically the case for the bootstrapping of the
+ * transport mode SA protecting BU/BA for MIPv6 traffic
+ *
+ * --arno*/
+ iph2->id = ipsecdoi_sockaddr2id(iph2->sa_src,
+ IPSECDOI_PREFIX_HOST,
+ sp->spidx.ul_proto);
+ } else
+ iph2->id = ipsecdoi_sockaddr2id(iph2->src, IPSECDOI_PREFIX_HOST,
+ sp->spidx.ul_proto);
+
if (iph2->id == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
"failed to get ID for %s\n",
@@ -4065,8 +3967,18 @@ ipsecdoi_setid2(iph2)
s_ipsecdoi_ident(((struct ipsecdoi_id_b *)iph2->id->v)->type));
/* remote side */
- iph2->id_p = ipsecdoi_sockaddr2id((struct sockaddr *)&sp->spidx.dst,
+ if (!ipsecdoi_transportmode(iph2->proposal))
+ iph2->id_p = ipsecdoi_sockaddr2id((struct sockaddr *)&sp->spidx.dst,
sp->spidx.prefd, sp->spidx.ul_proto);
+ else if (iph2->sa_dst != NULL) {
+ /* See comment above for local side. */
+ iph2->id_p = ipsecdoi_sockaddr2id(iph2->sa_dst,
+ IPSECDOI_PREFIX_HOST,
+ sp->spidx.ul_proto);
+ } else
+ iph2->id_p = ipsecdoi_sockaddr2id(iph2->dst, IPSECDOI_PREFIX_HOST,
+ sp->spidx.ul_proto);
+
if (iph2->id_p == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
"failed to get ID for %s\n",
@@ -4103,7 +4015,7 @@ ipsecdoi_sockaddr2id(saddr, prefixlen, ul_proto)
switch (saddr->sa_family) {
case AF_INET:
len1 = sizeof(struct in_addr);
- if (prefixlen == (sizeof(struct in_addr) << 3)) {
+ if (prefixlen >= (sizeof(struct in_addr) << 3)) {
type = IPSECDOI_ID_IPV4_ADDR;
len2 = 0;
} else {
@@ -4116,7 +4028,7 @@ ipsecdoi_sockaddr2id(saddr, prefixlen, ul_proto)
#ifdef INET6
case AF_INET6:
len1 = sizeof(struct in6_addr);
- if (prefixlen == (sizeof(struct in6_addr) << 3)) {
+ if (prefixlen >= (sizeof(struct in6_addr) << 3)) {
type = IPSECDOI_ID_IPV6_ADDR;
len2 = 0;
} else {
@@ -4161,7 +4073,7 @@ ipsecdoi_sockaddr2id(saddr, prefixlen, ul_proto)
/* set prefix */
if (len2) {
- u_char *p = (unsigned char *) new->v +
+ u_char *p = (unsigned char *) new->v +
sizeof(struct ipsecdoi_id_b) + len1;
u_int bits = prefixlen;
@@ -4232,10 +4144,10 @@ ipsecdoi_sockrange2id(laddr, haddr, ul_proto)
port = ((struct sockaddr_in *)(laddr))->sin_port;
((struct ipsecdoi_id_b *)new->v)->port =
port == IPSEC_PORT_ANY ? 0 : port;
- memcpy(new->v + sizeof(struct ipsecdoi_id_b),
- (caddr_t)&((struct sockaddr_in *)(laddr))->sin_addr,
+ memcpy(new->v + sizeof(struct ipsecdoi_id_b),
+ (caddr_t)&((struct sockaddr_in *)(laddr))->sin_addr,
len1);
- memcpy(new->v + sizeof(struct ipsecdoi_id_b) + len1,
+ memcpy(new->v + sizeof(struct ipsecdoi_id_b) + len1,
(caddr_t)&((struct sockaddr_in *)haddr)->sin_addr,
len2);
return new;
@@ -4254,9 +4166,14 @@ ipsecdoi_id2sockaddr(buf, saddr, prefixlen, ul_proto)
u_int8_t *prefixlen;
u_int16_t *ul_proto;
{
- struct ipsecdoi_id_b *id_b = (struct ipsecdoi_id_b *)buf->v;
+ struct ipsecdoi_id_b *id_b = NULL;
u_int plen = 0;
+ if (buf == NULL)
+ return ISAKMP_INTERNAL_ERROR;
+
+ id_b = (struct ipsecdoi_id_b *)buf->v;
+
/*
* When a ID payload of subnet type with a IP address of full bit
* masked, it has to be processed as host address.
@@ -4291,6 +4208,11 @@ ipsecdoi_id2sockaddr(buf, saddr, prefixlen, ul_proto)
: id_b->port); /* see sockaddr2id() */
memcpy(&((struct sockaddr_in6 *)saddr)->sin6_addr,
buf->v + sizeof(*id_b), sizeof(struct in6_addr));
+ ((struct sockaddr_in6 *)saddr)->sin6_scope_id =
+ (IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)saddr)->sin6_addr)
+ ? ((struct sockaddr_in6 *)id_b)->sin6_scope_id
+ : 0);
+
break;
#endif
default:
@@ -4384,29 +4306,20 @@ ipsecdoi_id2str(id)
char *dat;
static char buf[BUFLEN];
struct ipsecdoi_id_b *id_b = (struct ipsecdoi_id_b *)id->v;
- struct sockaddr_storage saddr_storage;
- struct sockaddr *saddr;
- struct sockaddr_in *saddr_in;
- struct sockaddr_in6 *saddr_in6;
+ union sockaddr_any saddr;
u_int plen = 0;
- saddr = (struct sockaddr *)&saddr_storage;
- saddr_in = (struct sockaddr_in *)&saddr_storage;
- saddr_in6 = (struct sockaddr_in6 *)&saddr_storage;
-
-
switch (id_b->type) {
case IPSECDOI_ID_IPV4_ADDR:
case IPSECDOI_ID_IPV4_ADDR_SUBNET:
case IPSECDOI_ID_IPV4_ADDR_RANGE:
#ifndef __linux__
- saddr->sa_len = sizeof(struct sockaddr_in);
+ saddr.sa.sa_len = sizeof(struct sockaddr_in);
#endif
- saddr->sa_family = AF_INET;
-
- saddr_in->sin_port = IPSEC_PORT_ANY;
- memcpy(&saddr_in->sin_addr,
+ saddr.sa.sa_family = AF_INET;
+ saddr.sin.sin_port = IPSEC_PORT_ANY;
+ memcpy(&saddr.sin.sin_addr,
id->v + sizeof(*id_b), sizeof(struct in_addr));
break;
#ifdef INET6
@@ -4415,15 +4328,14 @@ ipsecdoi_id2str(id)
case IPSECDOI_ID_IPV6_ADDR_RANGE:
#ifndef __linux__
- saddr->sa_len = sizeof(struct sockaddr_in6);
+ saddr.sa.sa_len = sizeof(struct sockaddr_in6);
#endif
- saddr->sa_family = AF_INET6;
-
- saddr_in6->sin6_port = IPSEC_PORT_ANY;
- memcpy(&saddr_in6->sin6_addr,
+ saddr.sa.sa_family = AF_INET6;
+ saddr.sin6.sin6_port = IPSEC_PORT_ANY;
+ memcpy(&saddr.sin6.sin6_addr,
id->v + sizeof(*id_b), sizeof(struct in6_addr));
- saddr_in6->sin6_scope_id =
- (IN6_IS_ADDR_LINKLOCAL(&saddr_in6->sin6_addr)
+ saddr.sin6.sin6_scope_id =
+ (IN6_IS_ADDR_LINKLOCAL(&saddr.sin6.sin6_addr)
? ((struct sockaddr_in6 *)id_b)->sin6_scope_id
: 0);
break;
@@ -4435,7 +4347,7 @@ ipsecdoi_id2str(id)
#ifdef INET6
case IPSECDOI_ID_IPV6_ADDR:
#endif
- len = snprintf( buf, BUFLEN, "%s", saddrwop2str(saddr));
+ len = snprintf( buf, BUFLEN, "%s", saddrwop2str(&saddr.sa));
break;
case IPSECDOI_ID_IPV4_ADDR_SUBNET:
@@ -4491,47 +4403,44 @@ ipsecdoi_id2str(id)
plen += l;
}
- len = snprintf( buf, BUFLEN, "%s/%i", saddrwop2str(saddr), plen);
+ len = snprintf( buf, BUFLEN, "%s/%i", saddrwop2str(&saddr.sa), plen);
}
break;
case IPSECDOI_ID_IPV4_ADDR_RANGE:
- len = snprintf( buf, BUFLEN, "%s-", saddrwop2str(saddr));
+ len = snprintf( buf, BUFLEN, "%s-", saddrwop2str(&saddr.sa));
#ifndef __linux__
- saddr->sa_len = sizeof(struct sockaddr_in);
+ saddr.sa.sa_len = sizeof(struct sockaddr_in);
#endif
- saddr->sa_family = AF_INET;
- saddr_in->sin_port = IPSEC_PORT_ANY;
- memcpy(&saddr_in->sin_addr,
+ saddr.sa.sa_family = AF_INET;
+ saddr.sin.sin_port = IPSEC_PORT_ANY;
+ memcpy(&saddr.sin.sin_addr,
id->v + sizeof(*id_b) + sizeof(struct in_addr),
sizeof(struct in_addr));
- len += snprintf( buf + len, BUFLEN - len, "%s", saddrwop2str(saddr));
-
+ len += snprintf(buf + len, BUFLEN - len, "%s", saddrwop2str(&saddr.sa));
break;
#ifdef INET6
case IPSECDOI_ID_IPV6_ADDR_RANGE:
-
- len = snprintf( buf, BUFLEN, "%s-", saddrwop2str(saddr));
+ len = snprintf( buf, BUFLEN, "%s-", saddrwop2str(&saddr.sa));
#ifndef __linux__
- saddr->sa_len = sizeof(struct sockaddr_in6);
+ saddr.sa.sa_len = sizeof(struct sockaddr_in6);
#endif
- saddr->sa_family = AF_INET6;
- saddr_in6->sin6_port = IPSEC_PORT_ANY;
- memcpy(&saddr_in6->sin6_addr,
+ saddr.sa.sa_family = AF_INET6;
+ saddr.sin6.sin6_port = IPSEC_PORT_ANY;
+ memcpy(&saddr.sin6.sin6_addr,
id->v + sizeof(*id_b) + sizeof(struct in6_addr),
sizeof(struct in6_addr));
- saddr_in6->sin6_scope_id =
- (IN6_IS_ADDR_LINKLOCAL(&saddr_in6->sin6_addr)
+ saddr.sin6.sin6_scope_id =
+ (IN6_IS_ADDR_LINKLOCAL(&saddr.sin6.sin6_addr)
? ((struct sockaddr_in6 *)id_b)->sin6_scope_id
: 0);
- len += snprintf( buf + len, BUFLEN - len, "%s", saddrwop2str(saddr));
-
+ len += snprintf(buf + len, BUFLEN - len, "%s", saddrwop2str(&saddr.sa));
break;
#endif
@@ -4836,24 +4745,12 @@ ipsecdoi_authalg2trnsid(alg)
return -1;
}
-#ifdef HAVE_GSSAPI
-struct isakmpsa *
-fixup_initiator_sa(match, received)
- struct isakmpsa *match, *received;
-{
- if (received->gssid != NULL)
- match->gssid = vdup(received->gssid);
-
- return match;
-}
-#endif
-
static int rm_idtype2doi[] = {
255, /* IDTYPE_UNDEFINED, 0 */
IPSECDOI_ID_FQDN, /* IDTYPE_FQDN, 1 */
IPSECDOI_ID_USER_FQDN, /* IDTYPE_USERFQDN, 2 */
IPSECDOI_ID_KEY_ID, /* IDTYPE_KEYID, 3 */
- 255, /* IDTYPE_ADDRESS, 4
+ 255, /* IDTYPE_ADDRESS, 4
* it expands into 4 types by another function. */
IPSECDOI_ID_DER_ASN1_DN, /* IDTYPE_ASN1DN, 5 */
};
@@ -4898,39 +4795,3 @@ doi2idtype(doi)
}
/*NOTREACHED*/
}
-
-#ifdef ENABLE_HYBRID
-static int
-switch_authmethod(authmethod)
- int authmethod;
-{
- switch(authmethod) {
- case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
- authmethod = OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I;
- break;
- case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
- authmethod = OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I;
- break;
- case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
- authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I;
- break;
- case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
- authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I;
- break;
- /* Those are not implemented */
- case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
- authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I;
- break;
- case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
- authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I;
- break;
- case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
- authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I;
- break;
- default:
- break;
- }
-
- return authmethod;
-}
-#endif
diff --git a/src/racoon/ipsec_doi.h b/src/racoon/ipsec_doi.h
index 21dd93d..19a861a 100644
--- a/src/racoon/ipsec_doi.h
+++ b/src/racoon/ipsec_doi.h
@@ -1,4 +1,4 @@
-/* $NetBSD: ipsec_doi.h,v 1.9 2006/12/09 05:52:57 manu Exp $ */
+/* $NetBSD: ipsec_doi.h,v 1.12 2009/03/12 10:57:26 tteras Exp $ */
/* Id: ipsec_doi.h,v 1.15 2006/08/11 16:06:30 vanhu Exp */
@@ -34,6 +34,8 @@
#ifndef _IPSEC_DOI_H
#define _IPSEC_DOI_H
+#include "isakmp.h"
+
/* refered to RFC2407 */
#define IPSEC_DOI 1
@@ -197,6 +199,12 @@ struct ipsecdoi_pl_id {
#define IPSECDOI_TYPE_PH1 0
#define IPSECDOI_TYPE_PH2 1
+/*
+ * Prefix that will make ipsecdoi_sockaddr2id() generate address type
+ * identities without knowning the exact length of address.
+ */
+#define IPSECDOI_PREFIX_HOST 0xff
+
struct isakmpsa;
struct ipsecdoi_pl_sa;
struct saprop;
@@ -209,7 +217,11 @@ extern int ipsecdoi_selectph2proposal __P((struct ph2handle *));
extern int ipsecdoi_checkph2proposal __P((struct ph2handle *));
extern struct prop_pair **get_proppair __P((vchar_t *, int));
+#ifdef ANDROID_PATCHED
extern vchar_t *get_sabyproppair __P((struct prop_pair *, struct ph1handle *));
+#else
+extern vchar_t *get_sabyproppair __P((u_int32_t, u_int32_t, struct prop_pair *));
+#endif
extern int ipsecdoi_updatespi __P((struct ph2handle *iph2));
extern vchar_t *get_sabysaprop __P((struct saprop *, vchar_t *));
extern int ipsecdoi_chkcmpids( const vchar_t *, const vchar_t *, int );
@@ -225,7 +237,8 @@ extern char *ipsecdoi_id2str __P((const vchar_t *));
extern vchar_t *ipsecdoi_sockrange2id __P(( struct sockaddr *,
struct sockaddr *, u_int));
-extern vchar_t *ipsecdoi_setph1proposal __P((struct isakmpsa *));
+extern vchar_t *ipsecdoi_setph1proposal __P((struct remoteconf *,
+ struct isakmpsa *));
extern int ipsecdoi_setph2proposal __P((struct ph2handle *));
extern int ipsecdoi_transportmode __P((struct saprop *));
extern int ipsecdoi_get_defaultlifetime __P((void));
@@ -239,5 +252,8 @@ extern int ipsecdoi_authalg2trnsid __P((int));
extern int idtype2doi __P((int));
extern int doi2idtype __P((int));
+extern int ipsecdoi_parse_responder_lifetime __P((struct isakmp_pl_n *notify,
+ u_int32_t *lifetime_sec, u_int32_t *liftime_kb));
+
#endif /* _IPSEC_DOI_H */
diff --git a/src/racoon/isakmp.c b/src/racoon/isakmp.c
index 12eb5a0..048ca71 100644
--- a/src/racoon/isakmp.c
+++ b/src/racoon/isakmp.c
@@ -1,11 +1,11 @@
-/* $NetBSD: isakmp.c,v 1.20.6.13 2008/09/25 09:34:39 vanhu Exp $ */
+/* $NetBSD: isakmp.c,v 1.71 2011/03/15 13:20:14 vanhu Exp $ */
/* Id: isakmp.c,v 1.74 2006/05/07 21:32:59 manubsd Exp */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -17,7 +17,7 @@
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -72,6 +72,7 @@
#include "plog.h"
#include "sockmisc.h"
#include "schedule.h"
+#include "session.h"
#include "debug.h"
#include "remoteconf.h"
@@ -88,6 +89,9 @@
#include "pfkey.h"
#include "crypto_openssl.h"
#include "policy.h"
+#include "algorithm.h"
+#include "proposal.h"
+#include "sainfo.h"
#include "isakmp_ident.h"
#include "isakmp_agg.h"
#include "isakmp_base.h"
@@ -116,9 +120,6 @@
# ifndef SOL_UDP
# define SOL_UDP 17
# endif
-#ifdef ANDROID_CHANGES
-#define __linux
-#endif
# endif /* __linux__ */
# if defined(__NetBSD__) || defined(__FreeBSD__) || \
(defined(__APPLE__) && defined(__MACH__))
@@ -137,34 +138,34 @@ extern caddr_t val2str(const char *, size_t);
static int (*ph1exchange[][2][PHASE1ST_MAX])
__P((struct ph1handle *, vchar_t *)) = {
/* error */
- { {}, {}, },
+ { { 0 }, { 0 }, },
/* Identity Protection exchange */
{
{ nostate1, ident_i1send, nostate1, ident_i2recv, ident_i2send,
- ident_i3recv, ident_i3send, ident_i4recv, ident_i4send, nostate1, },
+ ident_i3recv, ident_i3send, ident_i4recv, ident_i4send, nostate1, nostate1,},
{ nostate1, ident_r1recv, ident_r1send, ident_r2recv, ident_r2send,
- ident_r3recv, ident_r3send, nostate1, nostate1, nostate1, },
+ ident_r3recv, ident_r3send, nostate1, nostate1, nostate1, nostate1, },
},
/* Aggressive exchange */
{
{ nostate1, agg_i1send, nostate1, agg_i2recv, agg_i2send,
- nostate1, nostate1, nostate1, nostate1, nostate1, },
+ nostate1, nostate1, nostate1, nostate1, nostate1, nostate1, },
{ nostate1, agg_r1recv, agg_r1send, agg_r2recv, agg_r2send,
- nostate1, nostate1, nostate1, nostate1, nostate1, },
+ nostate1, nostate1, nostate1, nostate1, nostate1, nostate1, },
},
/* Base exchange */
{
{ nostate1, base_i1send, nostate1, base_i2recv, base_i2send,
- base_i3recv, base_i3send, nostate1, nostate1, nostate1, },
+ base_i3recv, base_i3send, nostate1, nostate1, nostate1, nostate1, },
{ nostate1, base_r1recv, base_r1send, base_r2recv, base_r2send,
- nostate1, nostate1, nostate1, nostate1, nostate1, },
+ nostate1, nostate1, nostate1, nostate1, nostate1, nostate1, },
},
};
static int (*ph2exchange[][2][PHASE2ST_MAX])
__P((struct ph2handle *, vchar_t *)) = {
/* error */
- { {}, {}, },
+ { { 0 }, { 0 }, },
/* Quick mode for IKE */
{
{ nostate2, nostate2, quick_i1prep, nostate2, quick_i1send,
@@ -175,7 +176,7 @@ static int (*ph2exchange[][2][PHASE2ST_MAX])
};
static u_char r_ck0[] = { 0,0,0,0,0,0,0,0 }; /* used to verify the r_ck. */
-
+
static int isakmp_main __P((vchar_t *, struct sockaddr *, struct sockaddr *));
static int ph1_main __P((struct ph1handle *, vchar_t *));
static int quick_main __P((struct ph2handle *, vchar_t *));
@@ -185,29 +186,35 @@ static int isakmp_ph2begin_i __P((struct ph1handle *, struct ph2handle *));
static int isakmp_ph2begin_r __P((struct ph1handle *, vchar_t *));
static int etypesw1 __P((int));
static int etypesw2 __P((int));
+static int isakmp_ph1resend __P((struct ph1handle *));
+static int isakmp_ph2resend __P((struct ph2handle *));
+
#ifdef ENABLE_FRAG
-static int frag_handler(struct ph1handle *,
+static int frag_handler(struct ph1handle *,
vchar_t *, struct sockaddr *, struct sockaddr *);
#endif
/*
* isakmp packet handler
*/
-int
-isakmp_handler(so_isakmp)
+static int
+isakmp_handler(ctx, so_isakmp)
+ void *ctx;
int so_isakmp;
{
struct isakmp isakmp;
union {
char buf[sizeof (isakmp) + 4];
u_int32_t non_esp[2];
- char lbuf[sizeof(struct udphdr) +
+ struct {
+ struct udphdr udp;
#ifdef __linux
- sizeof(struct iphdr) +
+ struct iphdr ip;
#else
- sizeof(struct ip) +
+ struct ip ip;
#endif
- sizeof(isakmp) + 4];
+ char buf[sizeof(isakmp) + 4];
+ } lbuf;
} x;
struct sockaddr_storage remote;
struct sockaddr_storage local;
@@ -243,34 +250,25 @@ isakmp_handler(so_isakmp)
/* Lucent IKE in UDP encapsulation */
{
- struct udphdr *udp;
#ifdef __linux__
- struct iphdr *ip;
-
- udp = (struct udphdr *)&x.lbuf[0];
- if (ntohs(udp->dest) == 501) {
- ip = (struct iphdr *)(x.lbuf + sizeof(*udp));
- extralen += sizeof(*udp) + ip->ihl;
+ if (ntohs(x.lbuf.udp.dest) == 501) {
+ extralen += sizeof(x.lbuf.udp) + x.lbuf.ip.ihl;
}
#else
- struct ip *ip;
-
- udp = (struct udphdr *)&x.lbuf[0];
- if (ntohs(udp->uh_dport) == 501) {
- ip = (struct ip *)(x.lbuf + sizeof(*udp));
- extralen += sizeof(*udp) + ip->ip_hl;
+ if (ntohs(x.lbuf.udp.uh_dport) == 501) {
+ extralen += sizeof(x.lbuf.udp) + x.lbuf.ip.ip_hl;
}
#endif
- }
+ }
#ifdef ENABLE_NATT
- /* we don't know about portchange yet,
+ /* we don't know about portchange yet,
look for non-esp marker instead */
if (x.non_esp[0] == 0 && x.non_esp[1] != 0)
extralen = NON_ESP_MARKER_LEN;
#endif
- /* now we know if there is an extra non-esp
+ /* now we know if there is an extra non-esp
marker at the beginning or not */
memcpy ((char *)&isakmp, x.buf + extralen, sizeof (isakmp));
@@ -311,7 +309,7 @@ isakmp_handler(so_isakmp)
if ((len = recvfrom(so_isakmp, (char *)&isakmp, sizeof(isakmp),
0, (struct sockaddr *)&remote, &remote_len)) < 0) {
plog(LLV_ERROR, LOCATION, NULL,
- "failed to receive isakmp packet: %s\n",
+ "failed to receive isakmp packet: %s\n",
strerror (errno));
}
goto end;
@@ -334,11 +332,11 @@ isakmp_handler(so_isakmp)
(len - extralen));
goto end;
}
-
+
memcpy (buf->v, tmpbuf->v + extralen, buf->l);
len -= extralen;
-
+
if (len != buf->l) {
plog(LLV_ERROR, LOCATION, (struct sockaddr *)&remote,
"received invalid length (%d != %zu), why ?\n",
@@ -349,7 +347,7 @@ isakmp_handler(so_isakmp)
plog(LLV_DEBUG, LOCATION, NULL, "===\n");
plog(LLV_DEBUG, LOCATION, NULL,
"%d bytes message received %s\n",
- len, saddr2str_fromto("from %s to %s",
+ len, saddr2str_fromto("from %s to %s",
(struct sockaddr *)&remote,
(struct sockaddr *)&local));
plogdump(LLV_DEBUG, buf->v, buf->l);
@@ -386,8 +384,7 @@ end:
vfree(tmpbuf);
if (buf != NULL)
vfree(buf);
-
- return(error);
+ return error;
}
/*
@@ -471,8 +468,8 @@ isakmp_main(msg, remote, local)
/* Floating ports for NAT-T */
if (NATT_AVAILABLE(iph1) &&
! (iph1->natt_flags & NAT_PORTS_CHANGED) &&
- ((cmpsaddrstrict(iph1->remote, remote) != 0) ||
- (cmpsaddrstrict(iph1->local, local) != 0)))
+ ((cmpsaddr(iph1->remote, remote) != CMPSADDR_MATCH) ||
+ (cmpsaddr(iph1->local, local) != CMPSADDR_MATCH)))
{
/* prevent memory leak */
racoon_free(iph1->remote);
@@ -499,12 +496,12 @@ isakmp_main(msg, remote, local)
}
/* set the flag to prevent further port floating
- (FIXME: should we allow it? E.g. when the NAT gw
+ (FIXME: should we allow it? E.g. when the NAT gw
is rebooted?) */
iph1->natt_flags |= NAT_PORTS_CHANGED | NAT_ADD_NON_ESP_MARKER;
-
+
/* print some neat info */
- plog (LLV_INFO, LOCATION, NULL,
+ plog (LLV_INFO, LOCATION, NULL,
"NAT-T: ports changed to: %s\n",
saddr2str_fromto ("%s<->%s", iph1->remote, iph1->local));
@@ -513,7 +510,7 @@ isakmp_main(msg, remote, local)
#endif
/* must be same addresses in one stream of a phase at least. */
- if (cmpsaddrstrict(iph1->remote, remote) != 0) {
+ if (cmpsaddr(iph1->remote, remote) != CMPSADDR_MATCH) {
char *saddr_db, *saddr_act;
saddr_db = racoon_strdup(saddr2str(iph1->remote));
@@ -639,7 +636,7 @@ isakmp_main(msg, remote, local)
"exchange received.\n");
return -1;
}
- if (cmpsaddrstrict(iph1->remote, remote) != 0) {
+ if (cmpsaddr(iph1->remote, remote) != CMPSADDR_MATCH) {
plog(LLV_WARNING, LOCATION, remote,
"remote address mismatched. "
"db=%s\n",
@@ -671,7 +668,7 @@ isakmp_main(msg, remote, local)
return -1;
}
#ifdef ENABLE_HYBRID
- /* Reinit the IVM if it's still there */
+ /* Reinit the IVM if it's still there */
if (iph1->mode_cfg && iph1->mode_cfg->ivm) {
oakley_delivm(iph1->mode_cfg->ivm);
iph1->mode_cfg->ivm = NULL;
@@ -683,7 +680,8 @@ isakmp_main(msg, remote, local)
#endif
/* check status of phase 1 whether negotiated or not. */
- if (iph1->status != PHASE1ST_ESTABLISHED) {
+ if (iph1->status != PHASE1ST_ESTABLISHED &&
+ iph1->status != PHASE1ST_DYING) {
plog(LLV_ERROR, LOCATION, remote,
"can't start the quick mode, "
"there is no valid ISAKMP-SA, %s\n",
@@ -715,7 +713,6 @@ isakmp_main(msg, remote, local)
if (quick_main(iph2, msg) < 0) {
plog(LLV_ERROR, LOCATION, iph1->remote,
"phase2 negotiation failed.\n");
- unbindph12(iph2);
remph2(iph2);
delph2(iph2);
return -1;
@@ -756,7 +753,7 @@ isakmp_main(msg, remote, local)
isakmp_cfg_r(iph1, msg);
break;
-#endif
+#endif
case ISAKMP_ETYPE_NONE:
default:
@@ -783,7 +780,7 @@ ph1_main(iph1, msg)
#endif
/* ignore a packet */
- if (iph1->status == PHASE1ST_ESTABLISHED)
+ if (iph1->status >= PHASE1ST_ESTABLISHED)
return 0;
#ifdef ENABLE_STATS
@@ -813,7 +810,8 @@ ph1_main(iph1, msg)
if (iph1->side == RESPONDER && iph1->status == PHASE1ST_START) {
plog(LLV_ERROR, LOCATION, iph1->remote,
- "failed to pre-process packet.\n");
+ "failed to pre-process ph1 packet (side: %d, status %d).\n",
+ iph1->side, iph1->status);
return -1;
} else {
/* ignore the error and keep phase 1 handler */
@@ -825,7 +823,7 @@ ph1_main(iph1, msg)
/* free resend buffer */
if (iph1->sendbuf == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
- "no buffer found as sendbuf\n");
+ "no buffer found as sendbuf\n");
return -1;
}
#endif
@@ -833,7 +831,7 @@ ph1_main(iph1, msg)
VPTRINIT(iph1->sendbuf);
/* turn off schedule */
- SCHED_KILL(iph1->scr);
+ sched_cancel(&iph1->scr);
/* send */
plog(LLV_DEBUG, LOCATION, NULL, "===\n");
@@ -841,7 +839,8 @@ ph1_main(iph1, msg)
[iph1->side]
[iph1->status])(iph1, msg) != 0) {
plog(LLV_ERROR, LOCATION, iph1->remote,
- "failed to process packet.\n");
+ "failed to process ph1 packet (side: %d, status: %d).\n",
+ iph1->side, iph1->status);
return -1;
}
@@ -863,12 +862,23 @@ ph1_main(iph1, msg)
/* save created date. */
(void)time(&iph1->created);
+ /* migrate ph2s from dying ph1s */
+ migrate_dying_ph12(iph1);
+
/* add to the schedule to expire, and seve back pointer. */
- iph1->sce = sched_new(iph1->approval->lifetime,
- isakmp_ph1expire_stub, iph1);
+ if (ph1_rekey_enabled(iph1)) {
+ sched_schedule(&iph1->sce,
+ iph1->approval->lifetime *
+ PFKEY_SOFT_LIFETIME_RATE / 100,
+ isakmp_ph1dying_stub);
+ } else {
+ sched_schedule(&iph1->sce, iph1->approval->lifetime,
+ isakmp_ph1expire_stub);
+ }
+
#ifdef ENABLE_HYBRID
if (iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) {
- switch(AUTHMETHOD(iph1)) {
+ switch (iph1->approval->authmethod) {
case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
@@ -905,18 +915,20 @@ ph1_main(iph1, msg)
/* ignore */
}
}
+ if (iph1->initial_contact_received)
+ isakmp_info_recv_initialcontact(iph1, NULL);
log_ph1established(iph1);
plog(LLV_DEBUG, LOCATION, NULL, "===\n");
- /*
+ /*
* SA up shell script hook: do it now,except if
* ISAKMP mode config was requested. In the later
* case it is done when we receive the configuration.
*/
if ((iph1->status == PHASE1ST_ESTABLISHED) &&
- !iph1->rmconf->mode_cfg) {
- switch (AUTHMETHOD(iph1)) {
+ !iph1->rmconf->mode_cfg) {
+ switch (iph1->approval->authmethod) {
#ifdef ENABLE_HYBRID
case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
@@ -974,7 +986,8 @@ quick_main(iph2, msg)
[iph2->status])(iph2, msg);
if (error != 0) {
plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
- "failed to pre-process packet.\n");
+ "failed to pre-process ph2 packet (side: %d, status %d).\n",
+ iph2->side, iph2->status);
if (error == ISAKMP_INTERNAL_ERROR)
return 0;
isakmp_info_send_n1(iph2->ph1, error, NULL);
@@ -988,13 +1001,13 @@ quick_main(iph2, msg)
/* free resend buffer */
if (iph2->sendbuf == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
- "no buffer found as sendbuf\n");
+ "no buffer found as sendbuf\n");
return -1;
}
VPTRINIT(iph2->sendbuf);
/* turn off schedule */
- SCHED_KILL(iph2->scr);
+ sched_cancel(&iph2->scr);
/* send */
plog(LLV_DEBUG, LOCATION, NULL, "===\n");
@@ -1002,7 +1015,8 @@ quick_main(iph2, msg)
[iph2->side]
[iph2->status])(iph2, msg) != 0) {
plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
- "failed to process packet.\n");
+ "failed to process ph2 packet (side: %d, status: %d).\n",
+ iph2->side, iph2->status);
return -1;
}
@@ -1018,7 +1032,7 @@ quick_main(iph2, msg)
}
/* new negotiation of phase 1 for initiator */
-int
+struct ph1handle *
isakmp_ph1begin_i(rmconf, remote, local)
struct remoteconf *rmconf;
struct sockaddr *remote, *local;
@@ -1031,7 +1045,7 @@ isakmp_ph1begin_i(rmconf, remote, local)
/* get new entry to isakmp status table. */
iph1 = newph1();
if (iph1 == NULL)
- return -1;
+ return NULL;
iph1->status = PHASE1ST_START;
iph1->rmconf = rmconf;
@@ -1046,7 +1060,7 @@ isakmp_ph1begin_i(rmconf, remote, local)
#ifdef ENABLE_HYBRID
if ((iph1->mode_cfg = isakmp_cfg_mkstate()) == NULL) {
delph1(iph1);
- return -1;
+ return NULL;
}
#endif
#ifdef ENABLE_FRAG
@@ -1062,7 +1076,7 @@ isakmp_ph1begin_i(rmconf, remote, local)
/* XXX copy remote address */
if (copy_ph1addresses(iph1, rmconf, remote, local) < 0) {
delph1(iph1);
- return -1;
+ return NULL;
}
(void)insph1(iph1);
@@ -1098,7 +1112,7 @@ isakmp_ph1begin_i(rmconf, remote, local)
remph1(iph1);
delph1(iph1);
- return -1;
+ return NULL;
}
#ifdef ENABLE_STATS
@@ -1109,7 +1123,7 @@ isakmp_ph1begin_i(rmconf, remote, local)
timedelta(&start, &end));
#endif
- return 0;
+ return iph1;
}
/* new negotiation of phase 1 for responder */
@@ -1120,27 +1134,19 @@ isakmp_ph1begin_r(msg, remote, local, etype)
u_int8_t etype;
{
struct isakmp *isakmp = (struct isakmp *)msg->v;
- struct remoteconf *rmconf;
struct ph1handle *iph1;
- struct etypes *etypeok;
+ struct rmconfselector rmsel;
#ifdef ENABLE_STATS
struct timeval start, end;
#endif
- /* look for my configuration */
- rmconf = getrmconf(remote);
- if (rmconf == NULL) {
+ /* check if this etype is allowed */
+ memset(&rmsel, 0, sizeof(rmsel));
+ rmsel.remote = remote;
+ if (enumrmconf(&rmsel, check_etypeok, (void *) (intptr_t) etype) == 0) {
plog(LLV_ERROR, LOCATION, remote,
- "couldn't find "
- "configuration.\n");
- return -1;
- }
-
- /* check to be acceptable exchange type */
- etypeok = check_etypeok(rmconf, etype);
- if (etypeok == NULL) {
- plog(LLV_ERROR, LOCATION, remote,
- "not acceptable %s mode\n", s_isakmp_etype(etype));
+ "exchange %s not allowed in any applicable rmconf.\n",
+ s_isakmp_etype(etype));
return -1;
}
@@ -1151,10 +1157,9 @@ isakmp_ph1begin_r(msg, remote, local, etype)
memcpy(&iph1->index.i_ck, &isakmp->i_ck, sizeof(iph1->index.i_ck));
iph1->status = PHASE1ST_START;
- iph1->rmconf = rmconf;
iph1->flags = 0;
iph1->side = RESPONDER;
- iph1->etype = etypeok->type;
+ iph1->etype = etype;
iph1->version = isakmp->v;
iph1->msgid = 0;
#ifdef HAVE_GSSAPI
@@ -1181,8 +1186,9 @@ isakmp_ph1begin_r(msg, remote, local, etype)
iph1->natt_flags |= (NAT_PORTS_CHANGED);
#endif
- /* copy remote address */
- if (copy_ph1addresses(iph1, rmconf, remote, local) < 0) {
+ /* copy remote address; remote and local always contain
+ * port numbers so rmconf is not needed */
+ if (copy_ph1addresses(iph1, NULL, remote, local) < 0) {
delph1(iph1);
return -1;
}
@@ -1218,7 +1224,8 @@ isakmp_ph1begin_r(msg, remote, local, etype)
[iph1->side]
[iph1->status])(iph1, msg) < 0) {
plog(LLV_ERROR, LOCATION, remote,
- "failed to process packet.\n");
+ "failed to process ph1 packet (side: %d, status: %d).\n",
+ iph1->side, iph1->status);
remph1(iph1);
delph1(iph1);
return -1;
@@ -1260,6 +1267,12 @@ isakmp_ph2begin_i(iph1, iph2)
}
#endif
+ /* fixup ph2 ports for this ph1 */
+ if (extract_port(iph2->src) == 0)
+ set_port(iph2->src, extract_port(iph1->local));
+ if (extract_port(iph2->dst) == 0)
+ set_port(iph2->dst, extract_port(iph1->remote));
+
/* found ISAKMP-SA. */
plog(LLV_DEBUG, LOCATION, NULL, "===\n");
plog(LLV_DEBUG, LOCATION, NULL, "begin QUICK mode.\n");
@@ -1277,14 +1290,13 @@ isakmp_ph2begin_i(iph1, iph2)
#ifdef ENABLE_STATS
gettimeofday(&iph2->start, NULL);
#endif
- /* found isakmp-sa */
- bindph12(iph1, iph2);
+ if (iph2->status != PHASE2ST_EXPIRED) /* Phase 1 is already bound (ongoing rekeying) */
+ bindph12(iph1, iph2);
iph2->status = PHASE2ST_STATUS2;
if ((ph2exchange[etypesw2(ISAKMP_ETYPE_QUICK)]
[iph2->side]
[iph2->status])(iph2, NULL) < 0) {
- unbindph12(iph2);
/* release ipsecsa handler due to internal error. */
remph2(iph2);
return -1;
@@ -1319,7 +1331,6 @@ isakmp_ph2begin_r(iph1, msg)
return -1;
}
- iph2->ph1 = iph1;
iph2->side = RESPONDER;
iph2->status = PHASE2ST_START;
iph2->flags = isakmp->flags;
@@ -1340,15 +1351,6 @@ isakmp_ph2begin_r(iph1, msg)
delph2(iph2);
return -1;
}
-#if (!defined(ENABLE_NATT)) || (defined(BROKEN_NATT))
- if (set_port(iph2->dst, 0) == NULL ||
- set_port(iph2->src, 0) == NULL) {
- plog(LLV_ERROR, LOCATION, NULL,
- "invalid family: %d\n", iph2->dst->sa_family);
- delph2(iph2);
- return -1;
- }
-#endif
/* add new entry to isakmp status table */
insph2(iph2);
@@ -1376,14 +1378,14 @@ isakmp_ph2begin_r(iph1, msg)
[iph2->status])(iph2, msg);
if (error != 0) {
plog(LLV_ERROR, LOCATION, iph1->remote,
- "failed to pre-process packet.\n");
+ "failed to pre-process ph2 packet (side: %d, status: %d).\n",
+ iph2->side, iph2->status);
if (error != ISAKMP_INTERNAL_ERROR)
isakmp_info_send_n1(iph2->ph1, error, NULL);
/*
* release handler because it's wrong that ph2handle is kept
* after failed to check message for responder's.
*/
- unbindph12(iph2);
remph2(iph2);
delph2(iph2);
return -1;
@@ -1395,7 +1397,8 @@ isakmp_ph2begin_r(iph1, msg)
[iph2->side]
[iph2->status])(iph2, msg) < 0) {
plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
- "failed to process packet.\n");
+ "failed to process ph2 packet (side: %d, status: %d).\n",
+ iph2->side, iph2->status);
/* don't release handler */
return -1;
}
@@ -1526,14 +1529,7 @@ isakmp_init()
initctdtree();
init_recvdpkt();
- if (isakmp_open() < 0)
- goto err;
-
- return(0);
-
-err:
- isakmp_close();
- return(-1);
+ return 0;
}
/*
@@ -1572,211 +1568,172 @@ isakmp_pindex(index, msgid)
/* open ISAKMP sockets. */
int
-isakmp_open()
+isakmp_open(struct sockaddr *addr, int udp_encap)
{
const int yes = 1;
- int ifnum = 0, encap_ifnum = 0;
+ int ifnum = 0, encap_ifnum = 0, fd;
+ struct sockaddr_in *sin = (struct sockaddr_in *) addr;
#ifdef INET6
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) addr;
int pktinfo;
#endif
- struct myaddrs *p;
-
- for (p = lcconf->myaddrs; p; p = p->next) {
- if (!p->addr)
- continue;
-
- /* warn if wildcard address - should we forbid this? */
- switch (p->addr->sa_family) {
- case AF_INET:
- if (((struct sockaddr_in *)p->addr)->sin_addr.s_addr == 0)
- plog(LLV_WARNING, LOCATION, NULL,
- "listening to wildcard address,"
- "broadcast IKE packet may kill you\n");
- break;
-#ifdef INET6
- case AF_INET6:
- if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)p->addr)->sin6_addr))
- plog(LLV_WARNING, LOCATION, NULL,
- "listening to wildcard address, "
- "broadcast IKE packet may kill you\n");
- break;
+#ifdef ENABLE_NATT
+ int option = -1;
#endif
- default:
- plog(LLV_ERROR, LOCATION, NULL,
- "unsupported address family %d\n",
- lcconf->default_af);
- goto err_and_next;
- }
+ /* warn if wildcard address - should we forbid this? */
+ switch (addr->sa_family) {
+ case AF_INET:
+ if (sin->sin_addr.s_addr == 0)
+ plog(LLV_WARNING, LOCATION, NULL,
+ "listening to wildcard address,"
+ "broadcast IKE packet may kill you\n");
+ break;
#ifdef INET6
- if (p->addr->sa_family == AF_INET6 &&
- IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *)
- p->addr)->sin6_addr))
- {
- plog(LLV_DEBUG, LOCATION, NULL,
- "Ignoring multicast address %s\n",
- saddr2str(p->addr));
- racoon_free(p->addr);
- p->addr = NULL;
- continue;
- }
-#endif
-
- if ((p->sock = socket(p->addr->sa_family, SOCK_DGRAM, 0)) < 0) {
- plog(LLV_ERROR, LOCATION, NULL,
- "socket (%s)\n", strerror(errno));
- goto err_and_next;
+ case AF_INET6:
+ if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "ignoring multicast address %s\n",
+ saddr2str(addr));
+ return -1;
}
- if (fcntl(p->sock, F_SETFL, O_NONBLOCK) == -1)
+ if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
plog(LLV_WARNING, LOCATION, NULL,
- "failed to put socket in non-blocking mode\n");
+ "listening to wildcard address, "
+ "broadcast IKE packet may kill you\n");
+ break;
+#endif
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "unsupported address family %d\n",
+ addr->sa_family);
+ return -1;
+ }
- /* receive my interface address on inbound packets. */
- switch (p->addr->sa_family) {
- case AF_INET:
- if (setsockopt(p->sock, IPPROTO_IP,
+ if ((fd = privsep_socket(addr->sa_family, SOCK_DGRAM, 0)) < 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "socket(%s)\n", strerror(errno));
+ return -1;
+ }
+ close_on_exec(fd);
+ if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1)
+ plog(LLV_WARNING, LOCATION, NULL,
+ "failed to put socket in non-blocking mode\n");
+
+ /* receive my interface address on inbound packets. */
+ switch (addr->sa_family) {
+ case AF_INET:
+ if (setsockopt(fd, IPPROTO_IP,
#ifdef __linux__
- IP_PKTINFO,
+ IP_PKTINFO,
#else
- IP_RECVDSTADDR,
+ IP_RECVDSTADDR,
#endif
- (const void *)&yes, sizeof(yes)) < 0) {
- plog(LLV_ERROR, LOCATION, NULL,
- "setsockopt IP_RECVDSTADDR (%s)\n",
- strerror(errno));
- goto err_and_next;
- }
+ (const void *) &yes, sizeof(yes)) < 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "setsockopt IP_RECVDSTADDR (%s)\n",
+ strerror(errno));
+ goto err;
+ }
+
+#ifdef ENABLE_NATT
+ if (udp_encap)
+ option = UDP_ENCAP_ESPINUDP;
+#if defined(ENABLE_NATT_00) || defined(ENABLE_NATT_01)
+ else
+ option = UDP_ENCAP_ESPINUDP_NON_IKE;
+#endif
+ if (option == -1)
break;
+
+ if (setsockopt(fd, SOL_UDP,
+ UDP_ENCAP, &option,
+ sizeof(option)) < 0) {
+ plog(LLV_WARNING, LOCATION, NULL,
+ "setsockopt(%s): UDP_ENCAP %s\n",
+ option == UDP_ENCAP_ESPINUDP ? "UDP_ENCAP_ESPINUDP" : "UDP_ENCAP_ESPINUDP_NON_IKE",
+ strerror(errno));
+ } else {
+ plog(LLV_INFO, LOCATION, NULL,
+ "%s used for NAT-T\n",
+ saddr2str(addr));
+ }
+#endif
+ break;
+
#ifdef INET6
- case AF_INET6:
-#ifdef INET6_ADVAPI
+ case AF_INET6:
+#if defined(INET6_ADVAPI)
#ifdef IPV6_RECVPKTINFO
- pktinfo = IPV6_RECVPKTINFO;
+ pktinfo = IPV6_RECVPKTINFO;
#else /* old adv. API */
- pktinfo = IPV6_PKTINFO;
+ pktinfo = IPV6_PKTINFO;
#endif /* IPV6_RECVPKTINFO */
#else
- pktinfo = IPV6_RECVDSTADDR;
-#endif
- if (setsockopt(p->sock, IPPROTO_IPV6, pktinfo,
- (const void *)&yes, sizeof(yes)) < 0)
- {
- plog(LLV_ERROR, LOCATION, NULL,
- "setsockopt IPV6_RECVDSTADDR (%d):%s\n",
- pktinfo, strerror(errno));
- goto err_and_next;
- }
- break;
+ pktinfo = IPV6_RECVDSTADDR;
#endif
+ if (setsockopt(fd, IPPROTO_IPV6, pktinfo,
+ (const void *) &yes, sizeof(yes)) < 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "setsockopt IPV6_RECVDSTADDR (%d):%s\n",
+ pktinfo, strerror(errno));
+ goto err;
}
#ifdef IPV6_USE_MIN_MTU
- if (p->addr->sa_family == AF_INET6 &&
- setsockopt(p->sock, IPPROTO_IPV6, IPV6_USE_MIN_MTU,
- (void *)&yes, sizeof(yes)) < 0) {
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_USE_MIN_MTU,
+ (void *) &yes, sizeof(yes)) < 0) {
plog(LLV_ERROR, LOCATION, NULL,
- "setsockopt IPV6_USE_MIN_MTU (%s)\n",
- strerror(errno));
- return -1;
+ "setsockopt IPV6_USE_MIN_MTU (%s)\n",
+ strerror(errno));
+ goto err;
}
#endif
-
- if (setsockopt_bypass(p->sock, p->addr->sa_family) < 0)
- goto err_and_next;
-
- if (bind(p->sock, p->addr, sysdep_sa_len(p->addr)) < 0) {
- plog(LLV_ERROR, LOCATION, p->addr,
- "failed to bind to address %s (%s).\n",
- saddr2str(p->addr), strerror(errno));
- close(p->sock);
- goto err_and_next;
- }
-
- ifnum++;
-
- plog(LLV_INFO, LOCATION, NULL,
- "%s used as isakmp port (fd=%d)\n",
- saddr2str(p->addr), p->sock);
-
-#ifdef ENABLE_NATT
- if (p->addr->sa_family == AF_INET) {
- int option = -1;
-
-
- if(p->udp_encap)
- option = UDP_ENCAP_ESPINUDP;
-#if defined(ENABLE_NATT_00) || defined(ENABLE_NATT_01)
- else
- option = UDP_ENCAP_ESPINUDP_NON_IKE;
-#endif
- if(option != -1){
- if (setsockopt (p->sock, SOL_UDP,
- UDP_ENCAP, &option, sizeof (option)) < 0) {
- plog(LLV_WARNING, LOCATION, NULL,
- "setsockopt(%s): UDP_ENCAP %s\n",
- option == UDP_ENCAP_ESPINUDP ? "UDP_ENCAP_ESPINUDP" : "UDP_ENCAP_ESPINUDP_NON_IKE",
- strerror(errno));
- goto skip_encap;
- }
- else {
- plog(LLV_INFO, LOCATION, NULL,
- "%s used for NAT-T\n",
- saddr2str(p->addr));
- encap_ifnum++;
- }
- }
- }
-skip_encap:
+ break;
#endif
- continue;
-
- err_and_next:
- racoon_free(p->addr);
- p->addr = NULL;
- if (! lcconf->autograbaddr && lcconf->strict_address)
- return -1;
- continue;
}
- if (!ifnum) {
+ if (setsockopt(fd, SOL_SOCKET,
+#ifdef __linux__
+ SO_REUSEADDR,
+#else
+ SO_REUSEPORT,
+#endif
+ (void *) &yes, sizeof(yes)) < 0) {
plog(LLV_ERROR, LOCATION, NULL,
- "no address could be bound.\n");
- return -1;
+ "failed to set REUSE flag on %s (%s).\n",
+ saddr2str(addr), strerror(errno));
+ goto err;
}
-#ifdef ENABLE_NATT
- if (natt_enabled_in_rmconf() && !encap_ifnum) {
- plog(LLV_WARNING, LOCATION, NULL,
- "NAT-T is enabled in at least one remote{} section,\n");
- plog(LLV_WARNING, LOCATION, NULL,
- "but no 'isakmp_natt' address was specified!\n");
+ if (setsockopt_bypass(fd, addr->sa_family) < 0)
+ goto err;
+
+ if (privsep_bind(fd, addr, sysdep_sa_len(addr)) < 0) {
+ plog(LLV_ERROR, LOCATION, addr,
+ "failed to bind to address %s (%s).\n",
+ saddr2str(addr), strerror(errno));
+ goto err;
}
-#endif
- return 0;
+ plog(LLV_INFO, LOCATION, NULL,
+ "%s used as isakmp port (fd=%d)\n",
+ saddr2str(addr), fd);
+
+ monitor_fd(fd, isakmp_handler, NULL, 1);
+ return fd;
+
+err:
+ close(fd);
+ return -1;
}
void
-isakmp_close()
+isakmp_close(int fd)
{
-#ifndef ANDROID_PATCHED
- struct myaddrs *p, *next;
-
- for (p = lcconf->myaddrs; p; p = next) {
- next = p->next;
-
- if (!p->addr) {
- racoon_free(p);
- continue;
- }
- close(p->sock);
- racoon_free(p->addr);
- racoon_free(p);
- }
-
- lcconf->myaddrs = NULL;
-#endif
+ unmonitor_fd(fd);
+ close(fd);
}
int
@@ -1798,23 +1755,23 @@ isakmp_send(iph1, sbuf)
extralen = 0;
#ifdef ENABLE_FRAG
- /*
+ /*
* Do not add the non ESP marker for a packet that will
- * be fragmented. The non ESP marker should appear in
+ * be fragmented. The non ESP marker should appear in
* all fragment's packets, but not in the fragmented packet
*/
- if (iph1->frag && sbuf->l > ISAKMP_FRAG_MAXLEN)
+ if (iph1->frag && sbuf->l > ISAKMP_FRAG_MAXLEN)
extralen = 0;
#endif
if (extralen)
plog (LLV_DEBUG, LOCATION, NULL, "Adding NON-ESP marker\n");
- /* If NAT-T port floating is in use, 4 zero bytes (non-ESP marker)
- must added just before the packet itself. For this we must
+ /* If NAT-T port floating is in use, 4 zero bytes (non-ESP marker)
+ must added just before the packet itself. For this we must
allocate a new buffer and release it at the end. */
if (extralen) {
if ((vbuf = vmalloc (sbuf->l + extralen)) == NULL) {
- plog(LLV_ERROR, LOCATION, NULL,
+ plog(LLV_ERROR, LOCATION, NULL,
"vbuf allocation failed\n");
return -1;
}
@@ -1831,22 +1788,21 @@ isakmp_send(iph1, sbuf)
#endif
/* select the socket to be sent */
- s = getsockmyaddr(iph1->local);
- if (s == -1){
+ s = myaddr_getfd(iph1->local);
+ if (s == -1)
return -1;
- }
- plog (LLV_DEBUG, LOCATION, NULL, "%zu bytes %s\n", sbuf->l,
+ plog (LLV_DEBUG, LOCATION, NULL, "%zu bytes %s\n", sbuf->l,
saddr2str_fromto("from %s to %s", iph1->local, iph1->remote));
#ifdef ENABLE_FRAG
if (iph1->frag && sbuf->l > ISAKMP_FRAG_MAXLEN) {
if (isakmp_sendfrags(iph1, sbuf) == -1) {
- plog(LLV_ERROR, LOCATION, NULL,
+ plog(LLV_ERROR, LOCATION, NULL,
"isakmp_sendfrags failed\n");
return -1;
}
- } else
+ } else
#endif
{
len = sendfromto(s, sbuf->v, sbuf->l,
@@ -1857,32 +1813,24 @@ isakmp_send(iph1, sbuf)
return -1;
}
}
-
+
return 0;
}
/* called from scheduler */
-void
+static void
isakmp_ph1resend_stub(p)
- void *p;
+ struct sched *p;
{
- struct ph1handle *iph1;
-
- iph1=(struct ph1handle *)p;
- if(isakmp_ph1resend(iph1) < 0){
- if(iph1->scr != NULL){
- /* Should not happen...
- */
- sched_kill(iph1->scr);
- iph1->scr=NULL;
- }
+ struct ph1handle *iph1 = container_of(p, struct ph1handle, scr);
+ if (isakmp_ph1resend(iph1) < 0) {
remph1(iph1);
delph1(iph1);
}
}
-int
+static int
isakmp_ph1resend(iph1)
struct ph1handle *iph1;
{
@@ -1892,8 +1840,9 @@ isakmp_ph1resend(iph1)
plog(LLV_ERROR, LOCATION, NULL,
"phase1 negotiation failed due to time up. %s\n",
isakmp_pindex(&iph1->index, iph1->msgid));
- EVT_PUSH(iph1->local, iph1->remote,
- EVTT_PEER_NO_RESPONSE, NULL);
+ /* XXX is the peer really "dead" here ??? */
+ script_hook(iph1, SCRIPT_PHASE1_DEAD);
+ evt_phase1(iph1, EVT_PHASE1_NO_RESPONSE, NULL);
return -1;
}
@@ -1902,8 +1851,7 @@ isakmp_ph1resend(iph1)
plog(LLV_ERROR, LOCATION, NULL,
"phase1 negotiation failed due to send error. %s\n",
isakmp_pindex(&iph1->index, iph1->msgid));
- EVT_PUSH(iph1->local, iph1->remote,
- EVTT_PEER_NO_RESPONSE, NULL);
+ evt_phase1(iph1, EVT_PHASE1_NO_RESPONSE, NULL);
return -1;
}
@@ -1913,35 +1861,40 @@ isakmp_ph1resend(iph1)
iph1->retry_counter--;
- iph1->scr = sched_new(iph1->rmconf->retry_interval,
- isakmp_ph1resend_stub, iph1);
+ sched_schedule(&iph1->scr, lcconf->retry_interval,
+ isakmp_ph1resend_stub);
return 0;
}
+int
+isakmp_ph1send(iph1)
+ struct ph1handle *iph1;
+{
+ iph1->retry_counter = lcconf->retry_counter;
+ return isakmp_ph1resend(iph1);
+}
+
/* called from scheduler */
-void
+static void
isakmp_ph2resend_stub(p)
- void *p;
+ struct sched *p;
{
- struct ph2handle *iph2;
-
- iph2=(struct ph2handle *)p;
+ struct ph2handle *iph2 = container_of(p, struct ph2handle, scr);
- if(isakmp_ph2resend(iph2) < 0){
- unbindph12(iph2);
+ if (isakmp_ph2resend(iph2) < 0) {
remph2(iph2);
delph2(iph2);
}
}
-int
+static int
isakmp_ph2resend(iph2)
struct ph2handle *iph2;
{
/* Note: NEVER do the unbind/rem/del here, it will be done by the caller or by the _stub function
*/
- if (iph2->ph1->status == PHASE1ST_EXPIRED){
+ if (iph2->ph1->status >= PHASE1ST_EXPIRED) {
plog(LLV_ERROR, LOCATION, NULL,
"phase2 negotiation failed due to phase1 expired. %s\n",
isakmp_pindex(&iph2->ph1->index, iph2->msgid));
@@ -1952,7 +1905,7 @@ isakmp_ph2resend(iph2)
plog(LLV_ERROR, LOCATION, NULL,
"phase2 negotiation failed due to time up. %s\n",
isakmp_pindex(&iph2->ph1->index, iph2->msgid));
- EVT_PUSH(iph2->src, iph2->dst, EVTT_PEER_NO_RESPONSE, NULL);
+ evt_phase2(iph2, EVT_PHASE2_NO_RESPONSE, NULL);
unbindph12(iph2);
return -1;
}
@@ -1961,8 +1914,7 @@ isakmp_ph2resend(iph2)
plog(LLV_ERROR, LOCATION, NULL,
"phase2 negotiation failed due to send error. %s\n",
isakmp_pindex(&iph2->ph1->index, iph2->msgid));
- EVT_PUSH(iph2->src, iph2->dst, EVTT_PEER_NO_RESPONSE, NULL);
-
+ evt_phase2(iph2, EVT_PHASE2_NO_RESPONSE, NULL);
return -1;
}
@@ -1972,19 +1924,77 @@ isakmp_ph2resend(iph2)
iph2->retry_counter--;
- iph2->scr = sched_new(iph2->ph1->rmconf->retry_interval,
- isakmp_ph2resend_stub, iph2);
+ sched_schedule(&iph2->scr, lcconf->retry_interval,
+ isakmp_ph2resend_stub);
return 0;
}
+int
+isakmp_ph2send(iph2)
+ struct ph2handle *iph2;
+{
+ iph2->retry_counter = lcconf->retry_counter;
+ return isakmp_ph2resend(iph2);
+}
+
/* called from scheduler */
void
-isakmp_ph1expire_stub(p)
- void *p;
+isakmp_ph1dying_stub(p)
+ struct sched *p;
+{
+
+ isakmp_ph1dying(container_of(p, struct ph1handle, sce));
+}
+
+void
+isakmp_ph1dying(iph1)
+ struct ph1handle *iph1;
{
+ struct ph1handle *new_iph1;
+ struct ph2handle *p;
+ struct remoteconf *rmconf;
+
+ if (iph1->status >= PHASE1ST_DYING)
+ return;
+
+ /* Going away in after a while... */
+ iph1->status = PHASE1ST_DYING;
+
+ /* Any fresh phase1s? */
+ new_iph1 = getph1(iph1, iph1->local, iph1->remote, 1);
+ if (new_iph1 == NULL) {
+ LIST_FOREACH(p, &iph1->ph2tree, ph1bind) {
+ if (p->status != PHASE2ST_ESTABLISHED)
+ continue;
+
+ plog(LLV_INFO, LOCATION, NULL,
+ "renegotiating phase1 to %s due to "
+ "active phase2\n",
+ saddrwop2str(iph1->remote));
- isakmp_ph1expire((struct ph1handle *)p);
+ if (iph1->side == INITIATOR)
+ isakmp_ph1begin_i(iph1->rmconf, iph1->remote,
+ iph1->local);
+
+ break;
+ }
+ } else {
+ migrate_ph12(iph1, new_iph1);
+ }
+
+ /* Schedule for expiration */
+ sched_schedule(&iph1->sce, iph1->approval->lifetime *
+ (100 - PFKEY_SOFT_LIFETIME_RATE) / 100,
+ isakmp_ph1expire_stub);
+}
+
+/* called from scheduler */
+void
+isakmp_ph1expire_stub(p)
+ struct sched *p;
+{
+ isakmp_ph1expire(container_of(p, struct ph1handle, sce));
}
void
@@ -1993,9 +2003,7 @@ isakmp_ph1expire(iph1)
{
char *src, *dst;
- SCHED_KILL(iph1->sce);
-
- if(iph1->status != PHASE1ST_EXPIRED){
+ if (iph1->status < PHASE1ST_EXPIRED) {
src = racoon_strdup(saddr2str(iph1->local));
dst = racoon_strdup(saddr2str(iph1->remote));
STRDUP_FATAL(src);
@@ -2010,41 +2018,44 @@ isakmp_ph1expire(iph1)
iph1->status = PHASE1ST_EXPIRED;
}
- /*
- * the phase1 deletion is postponed until there is no phase2.
- */
- if (LIST_FIRST(&iph1->ph2tree) != NULL) {
- iph1->sce = sched_new(1, isakmp_ph1expire_stub, iph1);
- return;
- }
-
- iph1->sce = sched_new(1, isakmp_ph1delete_stub, iph1);
+ isakmp_ph1delete(iph1);
}
/* called from scheduler */
void
isakmp_ph1delete_stub(p)
- void *p;
+ struct sched *p;
{
- isakmp_ph1delete((struct ph1handle *)p);
+ isakmp_ph1delete(container_of(p, struct ph1handle, sce));
}
void
isakmp_ph1delete(iph1)
struct ph1handle *iph1;
{
+ struct ph2handle *p, *next;
+ struct ph1handle *new_iph1;
char *src, *dst;
- SCHED_KILL(iph1->sce);
-
- if (LIST_FIRST(&iph1->ph2tree) != NULL) {
- iph1->sce = sched_new(1, isakmp_ph1delete_stub, iph1);
- return;
+ /* Migrate established phase2s. Any fresh phase1s? */
+ new_iph1 = getph1(iph1, iph1->local, iph1->remote, 1);
+ if (new_iph1 != NULL)
+ migrate_ph12(iph1, new_iph1);
+
+ /* Discard any left phase2s */
+ for (p = LIST_FIRST(&iph1->ph2tree); p; p = next) {
+ next = LIST_NEXT(p, ph1bind);
+ if (p->status == PHASE2ST_ESTABLISHED)
+ isakmp_info_send_d2(p);
+ /* remove all ph2 handles,
+ * as ph1handle will be expired soon
+ */
+ delete_spd(p, 1);
+ remph2(p);
+ delph2(p);
}
- /* don't re-negosiation when the phase 1 SA expires. */
-
src = racoon_strdup(saddr2str(iph1->local));
dst = racoon_strdup(saddr2str(iph1->remote));
STRDUP_FATAL(src);
@@ -2053,14 +2064,16 @@ isakmp_ph1delete(iph1)
plog(LLV_INFO, LOCATION, NULL,
"ISAKMP-SA deleted %s-%s spi:%s\n",
src, dst, isakmp_pindex(&iph1->index, 0));
- EVT_PUSH(iph1->local, iph1->remote, EVTT_PHASE1_DOWN, NULL);
+
+ evt_phase1(iph1, EVT_PHASE1_DOWN, NULL);
+ if (new_iph1 == NULL && ph1_rekey_enabled(iph1))
+ script_hook(iph1, SCRIPT_PHASE1_DEAD);
+
racoon_free(src);
racoon_free(dst);
remph1(iph1);
delph1(iph1);
-
- return;
}
/* called from scheduler.
@@ -2071,10 +2084,10 @@ isakmp_ph1delete(iph1)
*/
void
isakmp_ph2expire_stub(p)
- void *p;
+ struct sched *p;
{
- isakmp_ph2expire((struct ph2handle *)p);
+ isakmp_ph2expire(container_of(p, struct ph2handle, sce));
}
void
@@ -2083,8 +2096,6 @@ isakmp_ph2expire(iph2)
{
char *src, *dst;
- SCHED_KILL(iph2->sce);
-
src = racoon_strdup(saddrwop2str(iph2->src));
dst = racoon_strdup(saddrwop2str(iph2->dst));
STRDUP_FATAL(src);
@@ -2096,19 +2107,16 @@ isakmp_ph2expire(iph2)
racoon_free(dst);
iph2->status = PHASE2ST_EXPIRED;
-
- iph2->sce = sched_new(1, isakmp_ph2delete_stub, iph2);
-
- return;
+ sched_schedule(&iph2->sce, 1, isakmp_ph2delete_stub);
}
/* called from scheduler */
void
isakmp_ph2delete_stub(p)
- void *p;
+ struct sched *p;
{
- isakmp_ph2delete((struct ph2handle *)p);
+ isakmp_ph2delete(container_of(p, struct ph2handle, sce));
}
void
@@ -2117,8 +2125,6 @@ isakmp_ph2delete(iph2)
{
char *src, *dst;
- SCHED_KILL(iph2->sce);
-
src = racoon_strdup(saddrwop2str(iph2->src));
dst = racoon_strdup(saddrwop2str(iph2->dst));
STRDUP_FATAL(src);
@@ -2129,7 +2135,6 @@ isakmp_ph2delete(iph2)
racoon_free(src);
racoon_free(dst);
- unbindph12(iph2);
remph2(iph2);
delph2(iph2);
@@ -2144,25 +2149,39 @@ isakmp_ph2delete(iph2)
* if phase1 has been finished, begin phase2.
*/
int
-isakmp_post_acquire(iph2)
+isakmp_post_acquire(iph2, iph1hint, nopassive)
struct ph2handle *iph2;
+ struct ph1handle *iph1hint;
+ int nopassive;
{
struct remoteconf *rmconf;
struct ph1handle *iph1 = NULL;
-
+
plog(LLV_DEBUG, LOCATION, NULL, "in post_acquire\n");
- /* search appropreate configuration with masking port. */
- rmconf = getrmconf(iph2->dst);
- if (rmconf == NULL) {
- plog(LLV_ERROR, LOCATION, NULL,
- "no configuration found for %s.\n",
- saddrwop2str(iph2->dst));
- return -1;
+ /* Search appropriate configuration with masking port. Note that
+ * we always use iph2->dst, and not iph2->sa_dst.
+ *
+ * XXX One possible need for using iph2->sa_dst if not NULL would
+ * be for selecting a remote configuration based on a stable
+ * address of a mobile node (not a CoA provided by MIGRATE/KMADDRESS
+ * as iph2->dst hint). This scenario would require additional changes,
+ * so no need to bother yet. --arno */
+
+ if (iph1hint == NULL || iph1hint->rmconf == NULL) {
+ rmconf = getrmconf(iph2->dst, nopassive ? GETRMCONF_F_NO_PASSIVE : 0);
+ if (rmconf == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "no configuration found for %s.\n",
+ saddrwop2str(iph2->dst));
+ return -1;
+ }
+ } else {
+ rmconf = iph1hint->rmconf;
}
/* if passive mode, ignore the acquire message */
- if (rmconf->passive) {
+ if (nopassive && rmconf->passive) {
plog(LLV_DEBUG, LOCATION, NULL,
"because of passive mode, "
"ignore the acquire message for %s.\n",
@@ -2170,38 +2189,25 @@ isakmp_post_acquire(iph2)
return 0;
}
- /*
- * Search isakmp status table by address and port
- * If NAT-T is in use, consider null ports as a
- * wildcard and use IKE ports instead.
+ /*
+ * XXX Searching by IP addresses + ports might fail on
+ * some cases, we should use the ISAKMP identity to search
+ * matching ISAKMP.
*/
-#ifdef ENABLE_NATT
- if (!extract_port(iph2->src) && !extract_port(iph2->dst)) {
- if ((iph1 = getph1byaddrwop(iph2->src, iph2->dst)) != NULL) {
- set_port(iph2->src, extract_port(iph1->local));
- set_port(iph2->dst, extract_port(iph1->remote));
- }
- } else {
- iph1 = getph1byaddr(iph2->src, iph2->dst, 0);
- }
-#else
- iph1 = getph1byaddr(iph2->src, iph2->dst, 0);
-#endif
+ iph1 = getph1(iph1hint, iph2->src, iph2->dst, 0);
/* no ISAKMP-SA found. */
if (iph1 == NULL) {
- struct sched *sc;
-
iph2->retry_checkph1 = lcconf->retry_checkph1;
- sc = sched_new(1, isakmp_chkph1there_stub, iph2);
+ sched_schedule(&iph2->sce, 1, isakmp_chkph1there_stub);
plog(LLV_INFO, LOCATION, NULL,
"IPsec-SA request for %s queued "
"due to no phase1 found.\n",
saddrwop2str(iph2->dst));
/* start phase 1 negotiation as a initiator. */
- if (isakmp_ph1begin_i(rmconf, iph2->dst, iph2->src) < 0) {
- SCHED_KILL(sc);
+ if (isakmp_ph1begin_i(rmconf, iph2->dst, iph2->src) == NULL) {
+ sched_cancel(&iph2->sce);
return -1;
}
@@ -2210,9 +2216,9 @@ isakmp_post_acquire(iph2)
}
/* found ISAKMP-SA, but on negotiation. */
- if (iph1->status != PHASE1ST_ESTABLISHED) {
+ if (iph1->status < PHASE1ST_ESTABLISHED) {
iph2->retry_checkph1 = lcconf->retry_checkph1;
- sched_new(1, isakmp_chkph1there_stub, iph2);
+ sched_schedule(&iph2->sce, 1, isakmp_chkph1there_stub);
plog(LLV_INFO, LOCATION, iph2->dst,
"request for establishing IPsec-SA was queued "
"due to no phase1 found.\n");
@@ -2233,6 +2239,69 @@ isakmp_post_acquire(iph2)
return 0;
}
+int
+isakmp_get_sainfo(iph2, sp_out, sp_in)
+ struct ph2handle *iph2;
+ struct secpolicy *sp_out, *sp_in;
+{
+ struct remoteconf *conf;
+ uint32_t remoteid = 0;
+
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "new acquire %s\n", spidx2str(&sp_out->spidx));
+
+ /* get sainfo */
+ {
+ vchar_t *idsrc, *iddst;
+
+ idsrc = ipsecdoi_sockaddr2id((struct sockaddr *)&sp_out->spidx.src,
+ sp_out->spidx.prefs, sp_out->spidx.ul_proto);
+ if (idsrc == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "failed to get ID for %s\n",
+ spidx2str(&sp_out->spidx));
+ return -1;
+ }
+ iddst = ipsecdoi_sockaddr2id((struct sockaddr *)&sp_out->spidx.dst,
+ sp_out->spidx.prefd, sp_out->spidx.ul_proto);
+ if (iddst == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "failed to get ID for %s\n",
+ spidx2str(&sp_out->spidx));
+ vfree(idsrc);
+ return -1;
+ }
+
+ conf = getrmconf(iph2->dst, 0);
+ if (conf != NULL)
+ remoteid = conf->ph1id;
+ else
+ plog(LLV_DEBUG, LOCATION, NULL, "Warning: no valid rmconf !\n");
+
+ iph2->sainfo = getsainfo(idsrc, iddst, NULL, NULL, remoteid);
+ vfree(idsrc);
+ vfree(iddst);
+ if (iph2->sainfo == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "failed to get sainfo.\n");
+ return -1;
+ /* XXX should use the algorithm list from register message */
+ }
+
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "selected sainfo: %s\n", sainfo2str(iph2->sainfo));
+ }
+
+ if (set_proposal_from_policy(iph2, sp_out, sp_in) < 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "failed to create saprop.\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+
/*
* receive GETSPI from kernel.
*/
@@ -2245,7 +2314,7 @@ isakmp_post_getspi(iph2)
#endif
/* don't process it because there is no suitable phase1-sa. */
- if (iph2->ph1->status == PHASE1ST_EXPIRED) {
+ if (iph2->ph1->status >= PHASE1ST_EXPIRED) {
plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
"the negotiation is stopped, "
"because there is no suitable ISAKMP-SA.\n");
@@ -2273,9 +2342,9 @@ isakmp_post_getspi(iph2)
/* called by scheduler */
void
isakmp_chkph1there_stub(p)
- void *p;
+ struct sched *p;
{
- isakmp_chkph1there((struct ph2handle *)p);
+ isakmp_chkph1there(container_of(p, struct ph2handle, sce));
}
void
@@ -2297,33 +2366,14 @@ isakmp_chkph1there(iph2)
/* send acquire to kernel as error */
pk_sendeacquire(iph2);
- unbindph12(iph2);
remph2(iph2);
delph2(iph2);
return;
}
- /*
- * Search isakmp status table by address and port
- * If NAT-T is in use, consider null ports as a
- * wildcard and use IKE ports instead.
- */
-#ifdef ENABLE_NATT
- if (!extract_port(iph2->src) && !extract_port(iph2->dst)) {
- plog(LLV_DEBUG2, LOCATION, NULL, "CHKPH1THERE: extract_port.\n");
- if( (iph1 = getph1byaddrwop(iph2->src, iph2->dst)) != NULL){
- plog(LLV_DEBUG2, LOCATION, NULL, "CHKPH1THERE: found a ph1 wop.\n");
- }
- } else {
- plog(LLV_DEBUG2, LOCATION, NULL, "CHKPH1THERE: searching byaddr.\n");
- iph1 = getph1byaddr(iph2->src, iph2->dst, 0);
- if(iph1 != NULL)
- plog(LLV_DEBUG2, LOCATION, NULL, "CHKPH1THERE: found byaddr.\n");
- }
-#else
+ /* Search isakmp status table by address and port */
iph1 = getph1byaddr(iph2->src, iph2->dst, 0);
-#endif
/* XXX Even if ph1 as responder is there, should we not start
* phase 2 negotiation ? */
@@ -2351,7 +2401,7 @@ isakmp_chkph1there(iph2)
plog(LLV_DEBUG2, LOCATION, NULL, "CHKPH1THERE: no established ph1 handler found\n");
/* no isakmp-sa found */
- sched_new(1, isakmp_chkph1there_stub, iph2);
+ sched_schedule(&iph2->sce, 1, isakmp_chkph1there_stub);
return;
}
@@ -2874,7 +2924,9 @@ copy_ph1addresses(iph1, rmconf, remote, local)
* respect content of "remote".
*/
if (extract_port(iph1->remote) == 0) {
- port = extract_port(rmconf->remote);
+ port = 0;
+ if (rmconf != NULL)
+ port = extract_port(rmconf->remote);
if (port == 0)
port = PORT_ISAKMP;
set_port(iph1->remote, port);
@@ -2887,8 +2939,12 @@ copy_ph1addresses(iph1, rmconf, remote, local)
if (iph1->local == NULL)
return -1;
- if (extract_port(iph1->local) == 0)
+ if (extract_port(iph1->local) == 0) {
+ port = myaddr_getsport(iph1->local);
+ if (port == 0)
+ port = PORT_ISAKMP;
set_port(iph1->local, PORT_ISAKMP);
+ }
#ifdef ENABLE_NATT
if (extract_port(iph1->local) == lcconf->port_isakmp_natt) {
@@ -2935,10 +2991,10 @@ log_ph1established(iph1)
"ISAKMP-SA established %s-%s spi:%s\n",
src, dst,
isakmp_pindex(&iph1->index, 0));
-
- EVT_PUSH(iph1->local, iph1->remote, EVTT_PHASE1_UP, NULL);
+
+ evt_phase1(iph1, EVT_PHASE1_UP, NULL);
if(!iph1->rmconf->mode_cfg)
- EVT_PUSH(iph1->local, iph1->remote, EVTT_NO_ISAKMP_CFG, NULL);
+ evt_phase1(iph1, EVT_PHASE1_MODE_CFG, NULL);
racoon_free(src);
racoon_free(dst);
@@ -2947,7 +3003,8 @@ log_ph1established(iph1)
}
struct payload_list *
-isakmp_plist_append (struct payload_list *plist, vchar_t *payload, int payload_type)
+isakmp_plist_append_full (struct payload_list *plist, vchar_t *payload,
+ u_int8_t payload_type, u_int8_t free_payload)
{
if (! plist) {
plist = racoon_malloc (sizeof (struct payload_list));
@@ -2962,11 +3019,12 @@ isakmp_plist_append (struct payload_list *plist, vchar_t *payload, int payload_t
plist->next = NULL;
plist->payload = payload;
plist->payload_type = payload_type;
+ plist->free_payload = free_payload;
return plist;
}
-vchar_t *
+vchar_t *
isakmp_plist_set_all (struct payload_list **plist, struct ph1handle *iph1)
{
struct payload_list *ptr = *plist, *first;
@@ -2977,7 +3035,7 @@ isakmp_plist_set_all (struct payload_list **plist, struct ph1handle *iph1)
/* Seek to the first item. */
while (ptr->prev) ptr = ptr->prev;
first = ptr;
-
+
/* Compute the whole length. */
while (ptr) {
tlen += ptr->payload->l + sizeof (struct isakmp_gen);
@@ -3002,6 +3060,8 @@ isakmp_plist_set_all (struct payload_list **plist, struct ph1handle *iph1)
p = set_isakmp_payload (p, ptr->payload, ptr->next ? ptr->next->payload_type : ISAKMP_NPTYPE_NONE);
first = ptr;
ptr = ptr->next;
+ if (first->free_payload)
+ vfree(first->payload);
racoon_free (first);
/* ptr->prev = NULL; first = NULL; ... omitted. */
n++;
@@ -3017,7 +3077,7 @@ end:
}
#ifdef ENABLE_FRAG
-int
+int
frag_handler(iph1, msg, remote, local)
struct ph1handle *iph1;
vchar_t *msg;
@@ -3028,7 +3088,7 @@ frag_handler(iph1, msg, remote, local)
if (isakmp_frag_extract(iph1, msg) == 1) {
if ((newmsg = isakmp_frag_reassembly(iph1)) == NULL) {
- plog(LLV_ERROR, LOCATION, remote,
+ plog(LLV_ERROR, LOCATION, remote,
"Packet reassembly failed\n");
return -1;
}
@@ -3050,7 +3110,6 @@ script_hook(iph1, script)
char portstr[PORT_MAX];
char **envp = NULL;
int envc = 1;
- struct sockaddr_in *sin;
char **c;
if (iph1 == NULL ||
@@ -3063,9 +3122,7 @@ script_hook(iph1, script)
#endif
/* local address */
- sin = (struct sockaddr_in *)iph1->local;
- inet_ntop(sin->sin_family, &sin->sin_addr, addrstr, IP_MAX);
- snprintf(portstr, PORT_MAX, "%d", ntohs(sin->sin_port));
+ GETNAMEINFO(iph1->local, addrstr, portstr);
if (script_env_append(&envp, &envc, "LOCAL_ADDR", addrstr) != 0) {
plog(LLV_ERROR, LOCATION, NULL, "Cannot set LOCAL_ADDR\n");
@@ -3079,9 +3136,7 @@ script_hook(iph1, script)
/* Peer address */
if (iph1->remote != NULL) {
- sin = (struct sockaddr_in *)iph1->remote;
- inet_ntop(sin->sin_family, &sin->sin_addr, addrstr, IP_MAX);
- snprintf(portstr, PORT_MAX, "%d", ntohs(sin->sin_port));
+ GETNAMEINFO(iph1->remote, addrstr, portstr);
if (script_env_append(&envp, &envc,
"REMOTE_ADDR", addrstr) != 0) {
@@ -3098,6 +3153,16 @@ script_hook(iph1, script)
}
}
+ /* Peer identity. */
+ if (iph1->id_p != NULL) {
+ if (script_env_append(&envp, &envc, "REMOTE_ID",
+ ipsecdoi_id2str(iph1->id_p)) != 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "Cannot set REMOTE_ID\n");
+ goto out;
+ }
+ }
+
if (privsep_script_exec(iph1->rmconf->script[script]->v,
script, envp) != 0)
plog(LLV_ERROR, LOCATION, NULL,
@@ -3160,7 +3225,7 @@ script_exec(script, name, envp)
argv[1] = script_names[name];
argv[2] = NULL;
- switch (fork()) {
+ switch (fork()) {
case 0:
execve(argv[0], argv, envp);
plog(LLV_ERROR, LOCATION, NULL,
@@ -3175,7 +3240,7 @@ script_exec(script, name, envp)
break;
default:
break;
- }
+ }
return 0;
}
@@ -3201,7 +3266,7 @@ purge_remote(iph1)
iph1->status = PHASE1ST_EXPIRED;
/* Check if we have another, still valid, phase1 SA. */
- new_iph1 = getph1byaddr(iph1->local, iph1->remote, 1);
+ new_iph1 = getph1(iph1, iph1->local, iph1->remote, GETPH1_F_ESTABLISHED);
/*
* Delete all orphaned or binded to the deleting ph1handle phase2 SAs.
@@ -3240,6 +3305,7 @@ purge_remote(iph1)
msg = next;
continue;
}
+ pk_fixup_sa_addresses(mhp);
src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
@@ -3255,8 +3321,10 @@ purge_remote(iph1)
* Select only SAs where src == local and dst == remote (outgoing)
* or src == remote and dst == local (incoming).
*/
- if ((CMPSADDR(iph1->local, src) || CMPSADDR(iph1->remote, dst)) &&
- (CMPSADDR(iph1->local, dst) || CMPSADDR(iph1->remote, src))) {
+ if ((cmpsaddr(iph1->local, src) != CMPSADDR_MATCH ||
+ cmpsaddr(iph1->remote, dst) != CMPSADDR_MATCH) &&
+ (cmpsaddr(iph1->local, dst) != CMPSADDR_MATCH ||
+ cmpsaddr(iph1->remote, src) != CMPSADDR_MATCH)) {
msg = next;
continue;
}
@@ -3274,7 +3342,7 @@ purge_remote(iph1)
ntohl(sa->sadb_sa_spi));
}else{
- /*
+ /*
* If we have a new ph1, do not purge IPsec-SAs binded
* to a different ISAKMP-SA
*/
@@ -3286,7 +3354,7 @@ purge_remote(iph1)
/* If the ph2handle is established, do not purge IPsec-SA */
if (iph2->status == PHASE2ST_ESTABLISHED ||
iph2->status == PHASE2ST_EXPIRED) {
-
+
plog(LLV_INFO, LOCATION, NULL,
"keeping IPsec-SA spi=%u - found valid ISAKMP-SA spi=%s.\n",
ntohl(sa->sadb_sa_spi),
@@ -3297,7 +3365,7 @@ purge_remote(iph1)
}
}
-
+
pfkey_send_delete(lcconf->sock_pfkey,
msg->sadb_msg_satype,
IPSEC_MODE_ANY,
@@ -3306,7 +3374,6 @@ purge_remote(iph1)
/* delete a relative phase 2 handle. */
if (iph2 != NULL) {
delete_spd(iph2, 0);
- unbindph12(iph2);
remph2(iph2);
delph2(iph2);
}
@@ -3326,12 +3393,10 @@ purge_remote(iph1)
"purged ISAKMP-SA spi=%s.\n",
isakmp_pindex(&(iph1->index), iph1->msgid));
- SCHED_KILL(iph1->sce);
-
- iph1->sce = sched_new(1, isakmp_ph1delete_stub, iph1);
+ isakmp_ph1delete(iph1);
}
-void
+void
delete_spd(iph2, created)
struct ph2handle *iph2;
u_int64_t created;
@@ -3356,23 +3421,23 @@ delete_spd(iph2, created)
dst = iph2->dst;
plog(LLV_INFO, LOCATION, NULL,
- "generated policy, deleting it.\n");
-
+ "deleting a generated policy.\n");
+
memset(&spidx, 0, sizeof(spidx));
iph2->spidx_gen = (caddr_t )&spidx;
-
+
/* make inbound policy */
iph2->src = dst;
iph2->dst = src;
spidx.dir = IPSEC_DIR_INBOUND;
spidx.ul_proto = 0;
-
- /*
+
+ /*
* Note: code from get_proposal_r
*/
-
+
#define _XIDT(d) ((struct ipsecdoi_id_b *)(d)->v)->type
-
+
/*
* make destination address in spidx from either ID payload
* or phase 1 address into a address in spidx.
@@ -3388,48 +3453,48 @@ delete_spd(iph2, created)
&spidx.prefd, &spidx.ul_proto);
if (error)
goto purge;
-
+
#ifdef INET6
/*
* get scopeid from the SA address.
* note that the phase 1 source address is used as
- * a destination address to search for a inbound
+ * a destination address to search for a inbound
* policy entry because rcoon is responder.
*/
if (_XIDT(iph2->id) == IPSECDOI_ID_IPV6_ADDR) {
- if ((error =
+ if ((error =
setscopeid((struct sockaddr *)&spidx.dst,
iph2->src)) != 0)
goto purge;
}
#endif
-
+
if (_XIDT(iph2->id) == IPSECDOI_ID_IPV4_ADDR
|| _XIDT(iph2->id) == IPSECDOI_ID_IPV6_ADDR)
idi2type = _XIDT(iph2->id);
-
+
} else {
-
+
plog(LLV_DEBUG, LOCATION, NULL,
"get a destination address of SP index "
"from phase1 address "
"due to no ID payloads found "
"OR because ID type is not address.\n");
-
+
/*
- * copy the SOURCE address of IKE into the
- * DESTINATION address of the key to search the
+ * copy the SOURCE address of IKE into the
+ * DESTINATION address of the key to search the
* SPD because the direction of policy is inbound.
*/
memcpy(&spidx.dst, iph2->src, sysdep_sa_len(iph2->src));
switch (spidx.dst.ss_family) {
case AF_INET:
- spidx.prefd =
+ spidx.prefd =
sizeof(struct in_addr) << 3;
break;
#ifdef INET6
case AF_INET6:
- spidx.prefd =
+ spidx.prefd =
sizeof(struct in6_addr) << 3;
break;
#endif
@@ -3438,8 +3503,8 @@ delete_spd(iph2, created)
break;
}
}
-
- /* make source address in spidx */
+
+ /* make source address in spidx */
if (iph2->id_p != NULL
&& (_XIDT(iph2->id_p) == IPSECDOI_ID_IPV4_ADDR
|| _XIDT(iph2->id_p) == IPSECDOI_ID_IPV6_ADDR
@@ -3447,8 +3512,8 @@ delete_spd(iph2, created)
|| _XIDT(iph2->id_p) == IPSECDOI_ID_IPV6_ADDR_SUBNET)) {
/* get a source address of inbound SA */
error = ipsecdoi_id2sockaddr(iph2->id_p,
- (struct sockaddr *)&spidx.src,
- &spidx.prefs, &spidx.ul_proto);
+ (struct sockaddr *)&spidx.src,
+ &spidx.prefs, &spidx.ul_proto);
if (error)
goto purge;
@@ -3458,7 +3523,7 @@ delete_spd(iph2, created)
* for more detail, see above of this function.
*/
if (_XIDT(iph2->id_p) == IPSECDOI_ID_IPV6_ADDR) {
- error =
+ error =
setscopeid((struct sockaddr *)&spidx.src,
iph2->dst);
if (error)
@@ -3466,19 +3531,19 @@ delete_spd(iph2, created)
}
#endif
- /* make id[src,dst] if both ID types are IP address and same */
+ /* make sa_[src,dst] if both ID types are IP address and same */
if (_XIDT(iph2->id_p) == idi2type
&& spidx.dst.ss_family == spidx.src.ss_family) {
- iph2->src_id =
+ iph2->sa_src =
dupsaddr((struct sockaddr *)&spidx.dst);
- if (iph2->src_id == NULL) {
+ if (iph2->sa_src == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
"allocation failed\n");
goto purge;
}
- iph2->dst_id =
+ iph2->sa_dst =
dupsaddr((struct sockaddr *)&spidx.src);
- if (iph2->dst_id == NULL) {
+ if (iph2->sa_dst == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
"allocation failed\n");
goto purge;
@@ -3496,12 +3561,12 @@ delete_spd(iph2, created)
memcpy(&spidx.src, iph2->dst, sysdep_sa_len(iph2->dst));
switch (spidx.src.ss_family) {
case AF_INET:
- spidx.prefs =
+ spidx.prefs =
sizeof(struct in_addr) << 3;
break;
#ifdef INET6
case AF_INET6:
- spidx.prefs =
+ spidx.prefs =
sizeof(struct in6_addr) << 3;
break;
#endif
@@ -3539,7 +3604,7 @@ delete_spd(iph2, created)
*/
if( created ){
struct secpolicy *p;
-
+
p = getsp(&spidx);
if(p != NULL){
/* just do no test if p is NULL, because this probably just means
@@ -3604,7 +3669,7 @@ setscopeid(sp_addr0, sa_addr0)
struct sockaddr *sp_addr0, *sa_addr0;
{
struct sockaddr_in6 *sp_addr, *sa_addr;
-
+
sp_addr = (struct sockaddr_in6 *)sp_addr0;
sa_addr = (struct sockaddr_in6 *)sa_addr0;
diff --git a/src/racoon/isakmp.h b/src/racoon/isakmp.h
index d0fd242..16986a9 100644
--- a/src/racoon/isakmp.h
+++ b/src/racoon/isakmp.h
@@ -1,4 +1,4 @@
-/* $NetBSD: isakmp.h,v 1.4 2006/09/09 16:22:09 manu Exp $ */
+/* $NetBSD: isakmp.h,v 1.7 2009/05/20 07:54:50 vanhu Exp $ */
/* Id: isakmp.h,v 1.11 2005/04/25 22:19:39 manubsd Exp */
@@ -36,8 +36,8 @@
/* refer to RFC 2408 */
-/* must include <netinet/in.h> first. */
-/* must include "isakmp_var.h" first. */
+#include <netinet/in.h>
+#include "isakmp_var.h"
#define INITIATOR 0 /* synonym sender */
#define RESPONDER 1 /* synonym receiver */
@@ -133,7 +133,7 @@ struct isakmp {
/* Exchange Type */
#define ISAKMP_ETYPE_NONE 0 /* NONE */
#define ISAKMP_ETYPE_BASE 1 /* Base */
-#define ISAKMP_ETYPE_IDENT 2 /* Identity Proteciton */
+#define ISAKMP_ETYPE_IDENT 2 /* Identity Protection */
#define ISAKMP_ETYPE_AUTH 3 /* Authentication Only */
#define ISAKMP_ETYPE_AGG 4 /* Aggressive */
#define ISAKMP_ETYPE_INFO 5 /* Informational */
@@ -270,11 +270,6 @@ struct isakmp_pl_cert {
#define ISAKMP_CERT_X509ATTR 10
#define ISAKMP_CERT_PLAINRSA 11
-/* the method to get peers certificate */
-#define ISAKMP_GETCERT_PAYLOAD 1
-#define ISAKMP_GETCERT_LOCALFILE 2
-#define ISAKMP_GETCERT_DNS 3
-
/* 3.10 Certificate Request Payload */
struct isakmp_pl_cr {
struct isakmp_gen h;
@@ -384,7 +379,8 @@ struct isakmp_pl_d {
struct payload_list {
struct payload_list *next, *prev;
vchar_t *payload;
- int payload_type;
+ u_int8_t payload_type;
+ u_int8_t free_payload;
};
diff --git a/src/racoon/isakmp_agg.c b/src/racoon/isakmp_agg.c
index 0d43883..2e387fb 100644
--- a/src/racoon/isakmp_agg.c
+++ b/src/racoon/isakmp_agg.c
@@ -1,11 +1,11 @@
-/* $NetBSD: isakmp_agg.c,v 1.9 2006/09/30 21:49:37 manu Exp $ */
+/* $NetBSD: isakmp_agg.c,v 1.16 2009/09/18 10:31:11 tteras Exp $ */
/* Id: isakmp_agg.c,v 1.28 2006/04/06 16:46:08 manubsd Exp */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -17,7 +17,7 @@
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -113,8 +113,6 @@ agg_i1send(iph1, msg)
vchar_t *msg; /* must be null */
{
struct payload_list *plist = NULL;
- int need_cr = 0;
- vchar_t *cr = NULL;
int error = -1;
#ifdef ENABLE_NATT
vchar_t *vid_natt[MAX_NATT_VID_COUNT] = { NULL };
@@ -135,7 +133,6 @@ agg_i1send(iph1, msg)
vchar_t *vid_dpd = NULL;
#endif
-
/* validity check */
if (msg != NULL) {
plog(LLV_ERROR, LOCATION, NULL,
@@ -157,7 +154,7 @@ agg_i1send(iph1, msg)
goto end;
/* create SA payload for my proposal */
- iph1->sa = ipsecdoi_setph1proposal(iph1->rmconf->proposal);
+ iph1->sa = ipsecdoi_setph1proposal(iph1->rmconf, iph1->rmconf->proposal);
if (iph1->sa == NULL)
goto end;
@@ -180,8 +177,8 @@ agg_i1send(iph1, msg)
#ifdef ENABLE_HYBRID
/* Do we need Xauth VID? */
- switch (RMAUTHMETHOD(iph1)) {
- case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I:
+ switch (iph1->rmconf->proposal->authmethod) {
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I:
case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
@@ -189,10 +186,10 @@ agg_i1send(iph1, msg)
case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I:
case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I:
if ((vid_xauth = set_vendorid(VENDORID_XAUTH)) == NULL)
- plog(LLV_ERROR, LOCATION, NULL,
+ plog(LLV_ERROR, LOCATION, NULL,
"Xauth vendor ID generation failed\n");
if ((vid_unity = set_vendorid(VENDORID_UNITY)) == NULL)
- plog(LLV_ERROR, LOCATION, NULL,
+ plog(LLV_ERROR, LOCATION, NULL,
"Unity vendor ID generation failed\n");
break;
default:
@@ -209,26 +206,13 @@ agg_i1send(iph1, msg)
if (vid_frag == NULL)
plog(LLV_ERROR, LOCATION, NULL,
"Frag vendorID construction failed\n");
- }
-#endif
-
- /* create CR if need */
- if (iph1->rmconf->send_cr
- && oakley_needcr(iph1->rmconf->proposal->authmethod)
- && iph1->rmconf->peerscertfile == NULL) {
- need_cr = 1;
- cr = oakley_getcr(iph1);
- if (cr == NULL) {
- plog(LLV_ERROR, LOCATION, NULL,
- "failed to get cr buffer.\n");
- goto end;
- }
}
+#endif
plog(LLV_DEBUG, LOCATION, NULL, "authmethod is %s\n",
s_oakley_attr_method(iph1->rmconf->proposal->authmethod));
#ifdef HAVE_GSSAPI
- if (RMAUTHMETHOD(iph1) == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB)
+ if (iph1->rmconf->proposal->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB)
gssapi_get_itoken(iph1, &len);
#endif
@@ -245,33 +229,37 @@ agg_i1send(iph1, msg)
plist = isakmp_plist_append(plist, iph1->id, ISAKMP_NPTYPE_ID);
#ifdef HAVE_GSSAPI
- if (RMAUTHMETHOD(iph1) == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB) {
- gssapi_get_token_to_send(iph1, &gsstoken);
+ if (iph1->rmconf->proposal->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB) {
+ if (gssapi_get_token_to_send(iph1, &gsstoken) < 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "Failed to get gssapi token.\n");
+ goto end;
+ }
plist = isakmp_plist_append(plist, gsstoken, ISAKMP_NPTYPE_GSS);
}
#endif
/* create isakmp CR payload */
- if (need_cr)
- plist = isakmp_plist_append(plist, cr, ISAKMP_NPTYPE_CR);
+ if (oakley_needcr(iph1->rmconf->proposal->authmethod))
+ plist = oakley_append_cr(plist, iph1);
#ifdef ENABLE_FRAG
if (vid_frag)
plist = isakmp_plist_append(plist, vid_frag, ISAKMP_NPTYPE_VID);
#endif
#ifdef ENABLE_NATT
- /*
- * set VID payload for NAT-T if NAT-T
- * support allowed in the config file
+ /*
+ * set VID payload for NAT-T if NAT-T
+ * support allowed in the config file
*/
- if (iph1->rmconf->nat_traversal)
+ if (iph1->rmconf->nat_traversal)
plist = isakmp_plist_append_natt_vids(plist, vid_natt);
#endif
#ifdef ENABLE_HYBRID
if (vid_xauth)
- plist = isakmp_plist_append(plist,
+ plist = isakmp_plist_append(plist,
vid_xauth, ISAKMP_NPTYPE_VID);
if (vid_unity)
- plist = isakmp_plist_append(plist,
+ plist = isakmp_plist_append(plist,
vid_unity, ISAKMP_NPTYPE_VID);
#endif
#ifdef ENABLE_DPD
@@ -289,8 +277,7 @@ agg_i1send(iph1, msg)
#endif
/* send the packet, add to the schedule to resend */
- iph1->retry_counter = iph1->rmconf->retry_counter;
- if (isakmp_ph1resend(iph1) == -1)
+ if (isakmp_ph1send(iph1) == -1)
goto end;
iph1->status = PHASE1ST_MSG1SENT;
@@ -298,8 +285,6 @@ agg_i1send(iph1, msg)
error = 0;
end:
- if (cr)
- vfree(cr);
#ifdef HAVE_GSSAPI
if (gsstoken)
vfree(gsstoken);
@@ -343,7 +328,6 @@ agg_i2recv(iph1, msg)
struct isakmp_parse_t *pa;
vchar_t *satmp = NULL;
int error = -1;
- int vid_numeric;
int ptype;
#ifdef ENABLE_HYBRID
vchar_t *unity_vid;
@@ -425,37 +409,12 @@ agg_i2recv(iph1, msg)
goto end;
break;
case ISAKMP_NPTYPE_VID:
- vid_numeric = check_vendorid(pa->ptr);
-#ifdef ENABLE_NATT
- if (iph1->rmconf->nat_traversal &&
- natt_vendorid(vid_numeric))
- natt_handle_vendorid(iph1, vid_numeric);
-#endif
-#ifdef ENABLE_HYBRID
- switch (vid_numeric) {
- case VENDORID_XAUTH:
- iph1->mode_cfg->flags |=
- ISAKMP_CFG_VENDORID_XAUTH;
- break;
-
- case VENDORID_UNITY:
- iph1->mode_cfg->flags |=
- ISAKMP_CFG_VENDORID_UNITY;
- break;
- default:
- break;
- }
-#endif
-#ifdef ENABLE_DPD
- if (vid_numeric == VENDORID_DPD && iph1->rmconf->dpd) {
- iph1->dpd_support=1;
- plog(LLV_DEBUG, LOCATION, NULL,
- "remote supports DPD\n");
- }
-#endif
+ handle_vendorid(iph1, pa->ptr);
break;
case ISAKMP_NPTYPE_N:
- isakmp_check_notify(pa->ptr, iph1);
+ isakmp_log_notify(iph1,
+ (struct isakmp_pl_n *) pa->ptr,
+ "aggressive exchange");
break;
#ifdef HAVE_GSSAPI
case ISAKMP_NPTYPE_GSS:
@@ -529,7 +488,7 @@ agg_i2recv(iph1, msg)
if (NATT_AVAILABLE(iph1)) {
struct natd_payload *natd = NULL;
int natd_verified;
-
+
plog(LLV_INFO, LOCATION, iph1->remote,
"Selected NAT-T version: %s\n",
vid_string_by_id(iph1->natt_options->version));
@@ -537,9 +496,9 @@ agg_i2recv(iph1, msg)
/* set both bits first so that we can clear them
upon verifying hashes */
iph1->natt_flags |= NAT_DETECTED;
-
+
while ((natd = TAILQ_FIRST(&natd_tree)) != NULL) {
- /* this function will clear appropriate bits bits
+ /* this function will clear appropriate bits bits
from iph1->natt_flags */
natd_verified = natt_compare_addr_hash (iph1,
natd->payload, natd->seq);
@@ -547,7 +506,7 @@ agg_i2recv(iph1, msg)
plog (LLV_INFO, LOCATION, NULL, "NAT-D payload #%d %s\n",
natd->seq - 1,
natd_verified ? "verified" : "doesn't match");
-
+
vfree (natd->payload);
TAILQ_REMOVE(&natd_tree, natd, chain);
@@ -555,7 +514,7 @@ agg_i2recv(iph1, msg)
}
plog (LLV_INFO, LOCATION, NULL, "NAT %s %s%s\n",
- iph1->natt_flags & NAT_DETECTED ?
+ iph1->natt_flags & NAT_DETECTED ?
"detected:" : "not detected",
iph1->natt_flags & NAT_DETECTED_ME ? "ME " : "",
iph1->natt_flags & NAT_DETECTED_PEER ? "PEER" : "");
@@ -587,8 +546,7 @@ agg_i2recv(iph1, msg)
/* message printed inner oakley_validate_auth() */
goto end;
}
- EVT_PUSH(iph1->local, iph1->remote,
- EVTT_PEERPH1AUTH_FAILED, NULL);
+ evt_phase1(iph1, EVT_PHASE1_AUTH_FAILED, NULL);
isakmp_info_send_n1(iph1, ptype, NULL);
goto end;
}
@@ -616,13 +574,10 @@ end:
VPTRINIT(iph1->dhpub_p);
VPTRINIT(iph1->nonce_p);
VPTRINIT(iph1->id_p);
- oakley_delcert(iph1->cert_p);
- iph1->cert_p = NULL;
- oakley_delcert(iph1->crl_p);
- iph1->crl_p = NULL;
+ VPTRINIT(iph1->cert_p);
+ VPTRINIT(iph1->crl_p);
VPTRINIT(iph1->sig_p);
- oakley_delcert(iph1->cr_p);
- iph1->cr_p = NULL;
+ VPTRINIT(iph1->cr_p);
}
return error;
@@ -669,15 +624,15 @@ agg_i2send(iph1, msg)
goto end;
}
- switch (AUTHMETHOD(iph1)) {
+ switch (iph1->approval->authmethod) {
case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
#ifdef ENABLE_HYBRID
- case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I:
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I:
case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
-#endif
+#endif
/* set HASH payload */
- plist = isakmp_plist_append(plist,
+ plist = isakmp_plist_append(plist,
iph1->hash, ISAKMP_NPTYPE_HASH);
break;
@@ -700,11 +655,11 @@ agg_i2send(iph1, msg)
/* add CERT payload if there */
if (need_cert)
- plist = isakmp_plist_append(plist,
- iph1->cert->pl, ISAKMP_NPTYPE_CERT);
+ plist = isakmp_plist_append(plist, iph1->cert,
+ ISAKMP_NPTYPE_CERT);
/* add SIG payload */
- plist = isakmp_plist_append(plist,
+ plist = isakmp_plist_append(plist,
iph1->sig, ISAKMP_NPTYPE_SIG);
break;
@@ -726,7 +681,7 @@ agg_i2send(iph1, msg)
goto end;
}
- plist = isakmp_plist_append(plist,
+ plist = isakmp_plist_append(plist,
gsshash, ISAKMP_NPTYPE_HASH);
break;
#endif
@@ -737,26 +692,26 @@ agg_i2send(iph1, msg)
if (NATT_AVAILABLE(iph1)) {
vchar_t *natd[2] = { NULL, NULL };
- plog(LLV_INFO, LOCATION,
+ plog(LLV_INFO, LOCATION,
NULL, "Adding remote and local NAT-D payloads.\n");
if ((natd[0] = natt_hash_addr (iph1, iph1->remote)) == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
- "NAT-D hashing failed for %s\n",
+ "NAT-D hashing failed for %s\n",
saddr2str(iph1->remote));
goto end;
}
if ((natd[1] = natt_hash_addr (iph1, iph1->local)) == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
- "NAT-D hashing failed for %s\n",
+ "NAT-D hashing failed for %s\n",
saddr2str(iph1->local));
goto end;
}
- plist = isakmp_plist_append(plist,
+ plist = isakmp_plist_append(plist,
natd[0], iph1->natt_options->payload_nat_d);
- plist = isakmp_plist_append(plist,
+ plist = isakmp_plist_append(plist,
natd[1], iph1->natt_options->payload_nat_d);
}
#endif
@@ -860,37 +815,7 @@ agg_r1recv(iph1, msg)
goto end;
break;
case ISAKMP_NPTYPE_VID:
- vid_numeric = check_vendorid(pa->ptr);
-
-#ifdef ENABLE_NATT
- if (iph1->rmconf->nat_traversal &&
- natt_vendorid(vid_numeric)) {
- natt_handle_vendorid(iph1, vid_numeric);
- break;
- }
-#endif
-#ifdef ENABLE_HYBRID
- switch (vid_numeric) {
- case VENDORID_XAUTH:
- iph1->mode_cfg->flags |=
- ISAKMP_CFG_VENDORID_XAUTH;
- break;
-
- case VENDORID_UNITY:
- iph1->mode_cfg->flags |=
- ISAKMP_CFG_VENDORID_UNITY;
- break;
- default:
- break;
- }
-#endif
-#ifdef ENABLE_DPD
- if (vid_numeric == VENDORID_DPD && iph1->rmconf->dpd) {
- iph1->dpd_support=1;
- plog(LLV_DEBUG, LOCATION, NULL,
- "remote supports DPD\n");
- }
-#endif
+ vid_numeric = handle_vendorid(iph1, pa->ptr);
#ifdef ENABLE_FRAG
if ((vid_numeric == VENDORID_FRAG) &&
(vendorid_frag_cap(pa->ptr) & VENDORID_FRAG_AGG))
@@ -970,8 +895,7 @@ end:
VPTRINIT(iph1->dhpub_p);
VPTRINIT(iph1->nonce_p);
VPTRINIT(iph1->id_p);
- oakley_delcert(iph1->cr_p);
- iph1->cr_p = NULL;
+ VPTRINIT(iph1->cr_p);
}
return error;
@@ -991,9 +915,7 @@ agg_r1send(iph1, msg)
vchar_t *msg;
{
struct payload_list *plist = NULL;
- int need_cr = 0;
int need_cert = 0;
- vchar_t *cr = NULL;
int error = -1;
#ifdef ENABLE_HYBRID
vchar_t *xauth_vid = NULL;
@@ -1057,7 +979,7 @@ agg_r1send(iph1, msg)
goto end;
#ifdef HAVE_GSSAPI
- if (RMAUTHMETHOD(iph1) == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB)
+ if (iph1->rmconf->proposal->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB)
gssapi_get_rtoken(iph1, &gsslen);
#endif
@@ -1073,19 +995,6 @@ agg_r1send(iph1, msg)
goto end;
}
- /* create CR if need */
- if (iph1->rmconf->send_cr
- && oakley_needcr(iph1->approval->authmethod)
- && iph1->rmconf->peerscertfile == NULL) {
- need_cr = 1;
- cr = oakley_getcr(iph1);
- if (cr == NULL) {
- plog(LLV_ERROR, LOCATION, NULL,
- "failed to get cr buffer.\n");
- goto end;
- }
- }
-
#ifdef ENABLE_NATT
/* Has the peer announced NAT-T? */
if (NATT_AVAILABLE(iph1)) {
@@ -1124,35 +1033,34 @@ agg_r1send(iph1, msg)
}
#endif
- switch (AUTHMETHOD(iph1)) {
+ switch (iph1->approval->authmethod) {
case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
#ifdef ENABLE_HYBRID
case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
#endif
/* set SA payload to reply */
- plist = isakmp_plist_append(plist,
+ plist = isakmp_plist_append(plist,
iph1->sa_ret, ISAKMP_NPTYPE_SA);
/* create isakmp KE payload */
- plist = isakmp_plist_append(plist,
+ plist = isakmp_plist_append(plist,
iph1->dhpub, ISAKMP_NPTYPE_KE);
/* create isakmp NONCE payload */
- plist = isakmp_plist_append(plist,
+ plist = isakmp_plist_append(plist,
iph1->nonce, ISAKMP_NPTYPE_NONCE);
/* create isakmp ID payload */
- plist = isakmp_plist_append(plist,
+ plist = isakmp_plist_append(plist,
iph1->id, ISAKMP_NPTYPE_ID);
/* create isakmp HASH payload */
- plist = isakmp_plist_append(plist,
+ plist = isakmp_plist_append(plist,
iph1->hash, ISAKMP_NPTYPE_HASH);
/* create isakmp CR payload if needed */
- if (need_cr)
- plist = isakmp_plist_append(plist,
- cr, ISAKMP_NPTYPE_CR);
+ if (oakley_needcr(iph1->approval->authmethod))
+ plist = oakley_append_cr(plist, iph1);
break;
case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
@@ -1174,34 +1082,33 @@ agg_r1send(iph1, msg)
need_cert = 1;
/* set SA payload to reply */
- plist = isakmp_plist_append(plist,
+ plist = isakmp_plist_append(plist,
iph1->sa_ret, ISAKMP_NPTYPE_SA);
/* create isakmp KE payload */
- plist = isakmp_plist_append(plist,
+ plist = isakmp_plist_append(plist,
iph1->dhpub, ISAKMP_NPTYPE_KE);
/* create isakmp NONCE payload */
- plist = isakmp_plist_append(plist,
+ plist = isakmp_plist_append(plist,
iph1->nonce, ISAKMP_NPTYPE_NONCE);
/* add ID payload */
- plist = isakmp_plist_append(plist,
+ plist = isakmp_plist_append(plist,
iph1->id, ISAKMP_NPTYPE_ID);
/* add CERT payload if there */
if (need_cert)
- plist = isakmp_plist_append(plist,
- iph1->cert->pl, ISAKMP_NPTYPE_CERT);
+ plist = isakmp_plist_append(plist, iph1->cert,
+ ISAKMP_NPTYPE_CERT);
/* add SIG payload */
- plist = isakmp_plist_append(plist,
+ plist = isakmp_plist_append(plist,
iph1->sig, ISAKMP_NPTYPE_SIG);
/* create isakmp CR payload if needed */
- if (need_cr)
- plist = isakmp_plist_append(plist,
- cr, ISAKMP_NPTYPE_CR);
+ if (oakley_needcr(iph1->approval->authmethod))
+ plist = oakley_append_cr(plist, iph1);
break;
case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
@@ -1219,9 +1126,9 @@ agg_r1send(iph1, msg)
plog(LLV_ERROR, LOCATION, NULL,
"failed to wrap hash\n");
/*
- * This is probably due to the GSS
- * roundtrips not being finished yet.
- * Return this error in the hope that
+ * This is probably due to the GSS
+ * roundtrips not being finished yet.
+ * Return this error in the hope that
* a fallback to main mode will be done.
*/
isakmp_info_send_n1(iph1,
@@ -1229,8 +1136,8 @@ agg_r1send(iph1, msg)
goto end;
}
if (iph1->approval->gssid != NULL)
- gss_sa =
- ipsecdoi_setph1proposal(iph1->approval);
+ gss_sa = ipsecdoi_setph1proposal(iph1->rmconf,
+ iph1->approval);
else
gss_sa = iph1->sa_ret;
@@ -1238,28 +1145,32 @@ agg_r1send(iph1, msg)
free_gss_sa = 1;
/* set SA payload to reply */
- plist = isakmp_plist_append(plist,
+ plist = isakmp_plist_append(plist,
gss_sa, ISAKMP_NPTYPE_SA);
/* create isakmp KE payload */
- plist = isakmp_plist_append(plist,
+ plist = isakmp_plist_append(plist,
iph1->dhpub, ISAKMP_NPTYPE_KE);
/* create isakmp NONCE payload */
- plist = isakmp_plist_append(plist,
+ plist = isakmp_plist_append(plist,
iph1->nonce, ISAKMP_NPTYPE_NONCE);
/* create isakmp ID payload */
- plist = isakmp_plist_append(plist,
+ plist = isakmp_plist_append(plist,
iph1->id, ISAKMP_NPTYPE_ID);
/* create GSS payload */
- gssapi_get_token_to_send(iph1, &gsstoken);
- plist = isakmp_plist_append(plist,
+ if (gssapi_get_token_to_send(iph1, &gsstoken) < 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "Failed to get gssapi token.\n");
+ goto end;
+ }
+ plist = isakmp_plist_append(plist,
gsstoken, ISAKMP_NPTYPE_GSS);
/* create isakmp HASH payload */
- plist = isakmp_plist_append(plist,
+ plist = isakmp_plist_append(plist,
gsshash, ISAKMP_NPTYPE_HASH);
/* append vendor id, if needed */
@@ -1275,7 +1186,7 @@ agg_r1send(iph1, msg)
"Cannot create Xauth vendor ID\n");
goto end;
}
- plist = isakmp_plist_append(plist,
+ plist = isakmp_plist_append(plist,
xauth_vid, ISAKMP_NPTYPE_VID);
}
@@ -1285,7 +1196,7 @@ agg_r1send(iph1, msg)
"Cannot create Unity vendor ID\n");
goto end;
}
- plist = isakmp_plist_append(plist,
+ plist = isakmp_plist_append(plist,
unity_vid, ISAKMP_NPTYPE_VID);
}
#endif
@@ -1318,8 +1229,7 @@ agg_r1send(iph1, msg)
#endif
/* send the packet, add to the schedule to resend */
- iph1->retry_counter = iph1->rmconf->retry_counter;
- if (isakmp_ph1resend(iph1) == -1)
+ if (isakmp_ph1send(iph1) == -1)
goto end;
/* the sending message is added to the received-list. */
@@ -1334,8 +1244,6 @@ agg_r1send(iph1, msg)
error = 0;
end:
- if (cr)
- vfree(cr);
#ifdef ENABLE_HYBRID
if (xauth_vid)
vfree(xauth_vid);
@@ -1378,9 +1286,7 @@ agg_r2recv(iph1, msg0)
vchar_t *msg = NULL;
vchar_t *pbuf = NULL;
struct isakmp_parse_t *pa;
- int error = -1;
- int ptype;
-
+ int error = -1, ptype;
#ifdef ENABLE_NATT
int natd_seq = 0;
#endif
@@ -1418,7 +1324,7 @@ agg_r2recv(iph1, msg0)
iph1->pl_hash = (struct isakmp_pl_hash *)pa->ptr;
break;
case ISAKMP_NPTYPE_VID:
- (void)check_vendorid(pa->ptr);
+ handle_vendorid(iph1, pa->ptr);
break;
case ISAKMP_NPTYPE_CERT:
if (oakley_savecert(iph1, pa->ptr) < 0)
@@ -1429,7 +1335,9 @@ agg_r2recv(iph1, msg0)
goto end;
break;
case ISAKMP_NPTYPE_N:
- isakmp_check_notify(pa->ptr, iph1);
+ isakmp_log_notify(iph1,
+ (struct isakmp_pl_n *) pa->ptr,
+ "aggressive exchange");
break;
#ifdef ENABLE_NATT
@@ -1440,20 +1348,20 @@ agg_r2recv(iph1, msg0)
{
vchar_t *natd_received = NULL;
int natd_verified;
-
+
if (isakmp_p2ph (&natd_received, pa->ptr) < 0)
goto end;
-
+
if (natd_seq == 0)
iph1->natt_flags |= NAT_DETECTED;
-
+
natd_verified = natt_compare_addr_hash (iph1,
natd_received, natd_seq++);
-
+
plog (LLV_INFO, LOCATION, NULL, "NAT-D payload #%d %s\n",
natd_seq - 1,
natd_verified ? "verified" : "doesn't match");
-
+
vfree (natd_received);
break;
}
@@ -1473,7 +1381,7 @@ agg_r2recv(iph1, msg0)
#ifdef ENABLE_NATT
if (NATT_AVAILABLE(iph1))
plog (LLV_INFO, LOCATION, NULL, "NAT %s %s%s\n",
- iph1->natt_flags & NAT_DETECTED ?
+ iph1->natt_flags & NAT_DETECTED ?
"detected:" : "not detected",
iph1->natt_flags & NAT_DETECTED_ME ? "ME " : "",
iph1->natt_flags & NAT_DETECTED_PEER ? "PEER" : "");
@@ -1486,8 +1394,7 @@ agg_r2recv(iph1, msg0)
/* message printed inner oakley_validate_auth() */
goto end;
}
- EVT_PUSH(iph1->local, iph1->remote,
- EVTT_PEERPH1AUTH_FAILED, NULL);
+ evt_phase1(iph1, EVT_PHASE1_AUTH_FAILED, NULL);
isakmp_info_send_n1(iph1, ptype, NULL);
goto end;
}
@@ -1502,10 +1409,8 @@ end:
if (msg)
vfree(msg);
if (error) {
- oakley_delcert(iph1->cert_p);
- iph1->cert_p = NULL;
- oakley_delcert(iph1->crl_p);
- iph1->crl_p = NULL;
+ VPTRINIT(iph1->cert_p);
+ VPTRINIT(iph1->crl_p);
VPTRINIT(iph1->sig_p);
}
diff --git a/src/racoon/isakmp_base.c b/src/racoon/isakmp_base.c
index 3ac0b72..f37d51e 100644
--- a/src/racoon/isakmp_base.c
+++ b/src/racoon/isakmp_base.c
@@ -1,4 +1,4 @@
-/* $NetBSD: isakmp_base.c,v 1.7 2006/10/02 21:51:33 manu Exp $ */
+/* $NetBSD: isakmp_base.c,v 1.12 2009/03/12 10:57:26 tteras Exp $ */
/* $KAME: isakmp_base.c,v 1.49 2003/11/13 02:30:20 sakane Exp $ */
@@ -143,7 +143,8 @@ base_i1send(iph1, msg)
goto end;
/* create SA payload for my proposal */
- iph1->sa = ipsecdoi_setph1proposal(iph1->rmconf->proposal);
+ iph1->sa = ipsecdoi_setph1proposal(iph1->rmconf,
+ iph1->rmconf->proposal);
if (iph1->sa == NULL)
goto end;
@@ -154,8 +155,8 @@ base_i1send(iph1, msg)
#ifdef ENABLE_HYBRID
/* Do we need Xauth VID? */
- switch (RMAUTHMETHOD(iph1)) {
- case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I:
+ switch (iph1->rmconf->proposal->authmethod) {
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I:
case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
@@ -250,8 +251,7 @@ base_i1send(iph1, msg)
#endif
/* send the packet, add to the schedule to resend */
- iph1->retry_counter = iph1->rmconf->retry_counter;
- if (isakmp_ph1resend(iph1) == -1)
+ if (isakmp_ph1send(iph1) == -1)
goto end;
iph1->status = PHASE1ST_MSG1SENT;
@@ -297,7 +297,6 @@ base_i2recv(iph1, msg)
struct isakmp_parse_t *pa;
vchar_t *satmp = NULL;
int error = -1;
- int vid_numeric;
#ifdef ENABLE_HYBRID
vchar_t *unity_vid;
vchar_t *xauth_vid;
@@ -342,34 +341,7 @@ base_i2recv(iph1, msg)
goto end;
break;
case ISAKMP_NPTYPE_VID:
- vid_numeric = check_vendorid(pa->ptr);
-#ifdef ENABLE_NATT
- if (iph1->rmconf->nat_traversal && natt_vendorid(vid_numeric))
- natt_handle_vendorid(iph1, vid_numeric);
-#endif
-#ifdef ENABLE_HYBRID
- switch (vid_numeric) {
- case VENDORID_XAUTH:
- iph1->mode_cfg->flags |=
- ISAKMP_CFG_VENDORID_XAUTH;
- break;
-
- case VENDORID_UNITY:
- iph1->mode_cfg->flags |=
- ISAKMP_CFG_VENDORID_UNITY;
- break;
-
- default:
- break;
- }
-#endif
-#ifdef ENABLE_DPD
- if (vid_numeric == VENDORID_DPD && iph1->rmconf->dpd) {
- iph1->dpd_support=1;
- plog(LLV_DEBUG, LOCATION, NULL,
- "remote supports DPD\n");
- }
-#endif
+ handle_vendorid(iph1, pa->ptr);
break;
default:
/* don't send information, see ident_r1recv() */
@@ -462,7 +434,7 @@ base_i2send(iph1, msg)
goto end;
/* generate SKEYID to compute hash if not signature mode */
- switch (AUTHMETHOD(iph1)) {
+ switch (iph1->approval->authmethod) {
case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
#ifdef ENABLE_HYBRID
@@ -484,10 +456,10 @@ base_i2send(iph1, msg)
iph1->hash = oakley_ph1hash_base_i(iph1, GENERATE);
if (iph1->hash == NULL)
goto end;
- switch (AUTHMETHOD(iph1)) {
+ switch (iph1->approval->authmethod) {
case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
#ifdef ENABLE_HYBRID
- case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I:
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I:
case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
#endif
@@ -521,16 +493,16 @@ base_i2send(iph1, msg)
need_cert = 1;
/* create isakmp KE payload */
- plist = isakmp_plist_append(plist,
- iph1->dhpub, ISAKMP_NPTYPE_KE);
+ plist = isakmp_plist_append(plist, iph1->dhpub,
+ ISAKMP_NPTYPE_KE);
/* add CERT payload if there */
if (need_cert)
- plist = isakmp_plist_append(plist,
- iph1->cert->pl, ISAKMP_NPTYPE_CERT);
+ plist = isakmp_plist_append(plist, iph1->cert,
+ ISAKMP_NPTYPE_CERT);
/* add SIG payload */
- plist = isakmp_plist_append(plist,
+ plist = isakmp_plist_append(plist,
iph1->sig, ISAKMP_NPTYPE_SIG);
break;
@@ -579,8 +551,7 @@ base_i2send(iph1, msg)
#endif
/* send the packet, add to the schedule to resend */
- iph1->retry_counter = iph1->rmconf->retry_counter;
- if (isakmp_ph1resend(iph1) == -1)
+ if (isakmp_ph1send(iph1) == -1)
goto end;
/* the sending message is added to the received-list. */
@@ -614,8 +585,7 @@ base_i3recv(iph1, msg)
{
vchar_t *pbuf = NULL;
struct isakmp_parse_t *pa;
- int error = -1;
- int ptype;
+ int error = -1, ptype;
#ifdef ENABLE_NATT
vchar_t *natd_received;
int natd_seq = 0, natd_verified;
@@ -654,7 +624,7 @@ base_i3recv(iph1, msg)
goto end;
break;
case ISAKMP_NPTYPE_VID:
- (void)check_vendorid(pa->ptr);
+ handle_vendorid(iph1, pa->ptr);
break;
#ifdef ENABLE_NATT
@@ -716,8 +686,7 @@ base_i3recv(iph1, msg)
/* message printed inner oakley_validate_auth() */
goto end;
}
- EVT_PUSH(iph1->local, iph1->remote,
- EVTT_PEERPH1AUTH_FAILED, NULL);
+ evt_phase1(iph1, EVT_PHASE1_AUTH_FAILED, NULL);
isakmp_info_send_n1(iph1, ptype, NULL);
goto end;
}
@@ -728,7 +697,7 @@ base_i3recv(iph1, msg)
goto end;
/* generate SKEYID to compute hash if signature mode */
- switch (AUTHMETHOD(iph1)) {
+ switch (iph1->approval->authmethod) {
case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
#ifdef ENABLE_HYBRID
@@ -769,10 +738,8 @@ end:
if (error) {
VPTRINIT(iph1->dhpub_p);
- oakley_delcert(iph1->cert_p);
- iph1->cert_p = NULL;
- oakley_delcert(iph1->crl_p);
- iph1->crl_p = NULL;
+ VPTRINIT(iph1->cert_p);
+ VPTRINIT(iph1->crl_p);
VPTRINIT(iph1->sig_p);
}
@@ -829,9 +796,6 @@ base_r1recv(iph1, msg)
}
/* validate the type of next payload */
- /*
- * NOTE: XXX even if multiple VID, we'll silently ignore those.
- */
pbuf = isakmp_parse(msg);
if (pbuf == NULL)
goto end;
@@ -863,39 +827,12 @@ base_r1recv(iph1, msg)
goto end;
break;
case ISAKMP_NPTYPE_VID:
- vid_numeric = check_vendorid(pa->ptr);
-#ifdef ENABLE_NATT
- if (iph1->rmconf->nat_traversal && natt_vendorid(vid_numeric))
- natt_handle_vendorid(iph1, vid_numeric);
-#endif
+ vid_numeric = handle_vendorid(iph1, pa->ptr);
#ifdef ENABLE_FRAG
if ((vid_numeric == VENDORID_FRAG) &&
(vendorid_frag_cap(pa->ptr) & VENDORID_FRAG_BASE))
iph1->frag = 1;
#endif
-#ifdef ENABLE_HYBRID
- switch (vid_numeric) {
- case VENDORID_XAUTH:
- iph1->mode_cfg->flags |=
- ISAKMP_CFG_VENDORID_XAUTH;
- break;
-
- case VENDORID_UNITY:
- iph1->mode_cfg->flags |=
- ISAKMP_CFG_VENDORID_UNITY;
- break;
-
- default:
- break;
- }
-#endif
-#ifdef ENABLE_DPD
- if (vid_numeric == VENDORID_DPD && iph1->rmconf->dpd) {
- iph1->dpd_support=1;
- plog(LLV_DEBUG, LOCATION, NULL,
- "remote supports DPD\n");
- }
-#endif
break;
default:
/* don't send information, see ident_r1recv() */
@@ -1073,8 +1010,7 @@ base_r1send(iph1, msg)
#endif
/* send the packet, add to the schedule to resend */
- iph1->retry_counter = iph1->rmconf->retry_counter;
- if (isakmp_ph1resend(iph1) == -1) {
+ if (isakmp_ph1send(iph1) == -1) {
iph1 = NULL;
goto end;
}
@@ -1130,8 +1066,7 @@ base_r2recv(iph1, msg)
{
vchar_t *pbuf = NULL;
struct isakmp_parse_t *pa;
- int error = -1;
- int ptype;
+ int error = -1, ptype;
#ifdef ENABLE_NATT
int natd_seq = 0;
#endif
@@ -1171,7 +1106,7 @@ base_r2recv(iph1, msg)
goto end;
break;
case ISAKMP_NPTYPE_VID:
- (void)check_vendorid(pa->ptr);
+ handle_vendorid(iph1, pa->ptr);
break;
#ifdef ENABLE_NATT
@@ -1242,8 +1177,7 @@ base_r2recv(iph1, msg)
/* message printed inner oakley_validate_auth() */
goto end;
}
- EVT_PUSH(iph1->local, iph1->remote,
- EVTT_PEERPH1AUTH_FAILED, NULL);
+ evt_phase1(iph1, EVT_PHASE1_AUTH_FAILED, NULL);
isakmp_info_send_n1(iph1, ptype, NULL);
goto end;
}
@@ -1258,10 +1192,8 @@ end:
if (error) {
VPTRINIT(iph1->dhpub_p);
- oakley_delcert(iph1->cert_p);
- iph1->cert_p = NULL;
- oakley_delcert(iph1->crl_p);
- iph1->crl_p = NULL;
+ VPTRINIT(iph1->cert_p);
+ VPTRINIT(iph1->crl_p);
VPTRINIT(iph1->sig_p);
}
@@ -1294,7 +1226,7 @@ base_r2send(iph1, msg)
/* generate HASH to send */
plog(LLV_DEBUG, LOCATION, NULL, "generate HASH_I\n");
- switch (AUTHMETHOD(iph1)) {
+ switch (iph1->approval->authmethod) {
case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
#ifdef ENABLE_HYBRID
case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
@@ -1329,7 +1261,7 @@ base_r2send(iph1, msg)
if (iph1->hash == NULL)
goto end;
- switch (AUTHMETHOD(iph1)) {
+ switch (iph1->approval->authmethod) {
case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
#ifdef ENABLE_HYBRID
case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
@@ -1369,16 +1301,17 @@ base_r2send(iph1, msg)
need_cert = 1;
/* create isakmp KE payload */
- plist = isakmp_plist_append(plist,
- iph1->dhpub, ISAKMP_NPTYPE_KE);
+ plist = isakmp_plist_append(plist, iph1->dhpub,
+ ISAKMP_NPTYPE_KE);
/* add CERT payload if there */
if (need_cert)
- plist = isakmp_plist_append(plist,
- iph1->cert->pl, ISAKMP_NPTYPE_CERT);
+ plist = isakmp_plist_append(plist, iph1->cert,
+ ISAKMP_NPTYPE_CERT);
+
/* add SIG payload */
- plist = isakmp_plist_append(plist,
- iph1->sig, ISAKMP_NPTYPE_SIG);
+ plist = isakmp_plist_append(plist, iph1->sig,
+ ISAKMP_NPTYPE_SIG);
break;
#ifdef HAVE_GSSAPI
case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
diff --git a/src/racoon/isakmp_cfg.c b/src/racoon/isakmp_cfg.c
index 52862c4..0ec30ee 100644
--- a/src/racoon/isakmp_cfg.c
+++ b/src/racoon/isakmp_cfg.c
@@ -1,4 +1,4 @@
-/* $NetBSD: isakmp_cfg.c,v 1.12.6.4 2008/11/27 15:25:20 vanhu Exp $ */
+/* $NetBSD: isakmp_cfg.c,v 1.24 2010/09/21 13:14:17 vanhu Exp $ */
/* Id: isakmp_cfg.c,v 1.55 2006/08/22 18:17:17 manubsd Exp */
@@ -38,7 +38,7 @@
#include <sys/socket.h>
#include <sys/queue.h>
-#include <utmp.h>
+#include <utmpx.h>
#if defined(__APPLE__) && defined(__MACH__)
#include <util.h>
#endif
@@ -114,6 +114,8 @@ static vchar_t *isakmp_cfg_void(struct ph1handle *, struct isakmp_data *);
#endif
static vchar_t *isakmp_cfg_addr4(struct ph1handle *,
struct isakmp_data *, in_addr_t *);
+static vchar_t *isakmp_cfg_addrnet4(struct ph1handle *,
+ struct isakmp_data *, in_addr_t *, in_addr_t *);
static void isakmp_cfg_getaddr4(struct isakmp_data *, struct in_addr *);
static vchar_t *isakmp_cfg_addr4_list(struct ph1handle *,
struct isakmp_data *, in_addr_t *, int);
@@ -446,8 +448,8 @@ isakmp_cfg_reply(iph1, attrpl)
if ((iph1->status == PHASE1ST_ESTABLISHED) &&
iph1->rmconf->mode_cfg) {
- switch (AUTHMETHOD(iph1)) {
- case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I:
+ switch (iph1->approval->authmethod) {
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I:
case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
/* Unimplemented */
case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
@@ -473,8 +475,7 @@ isakmp_cfg_reply(iph1, attrpl)
"Cannot allocate memory: %s\n", strerror(errno));
} else {
memcpy(buf->v, attrpl + 1, buf->l);
- EVT_PUSH(iph1->local, iph1->remote,
- EVTT_ISAKMP_CFG_DONE, buf);
+ evt_phase1(iph1, EVT_PHASE1_MODE_CFG, buf);
vfree(buf);
}
}
@@ -629,7 +630,7 @@ isakmp_cfg_request(iph1, attrpl)
ISAKMP_NPTYPE_ATTR, ISAKMP_FLAG_E, 0);
if (iph1->status == PHASE1ST_ESTABLISHED) {
- switch (AUTHMETHOD(iph1)) {
+ switch (iph1->approval->authmethod) {
case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
/* Unimplemented */
@@ -731,7 +732,8 @@ isakmp_cfg_set(iph1, attrpl)
ISAKMP_NPTYPE_ATTR, ISAKMP_FLAG_E, 0);
if (iph1->mode_cfg->flags & ISAKMP_CFG_DELETE_PH1) {
- if (iph1->status == PHASE1ST_ESTABLISHED)
+ if (iph1->status == PHASE1ST_ESTABLISHED ||
+ iph1->status == PHASE1ST_DYING)
isakmp_info_send_d1(iph1);
remph1(iph1);
delph1(iph1);
@@ -901,8 +903,15 @@ retry_source:
break;
case INTERNAL_IP4_SUBNET:
- return isakmp_cfg_addr4(iph1,
- attr, &isakmp_cfg_config.network4);
+ if(isakmp_cfg_config.splitnet_count > 0){
+ return isakmp_cfg_addrnet4(iph1, attr,
+ &isakmp_cfg_config.splitnet_list->network.addr4.s_addr,
+ &isakmp_cfg_config.splitnet_list->network.mask4.s_addr);
+ }else{
+ plog(LLV_INFO, LOCATION, NULL,
+ "%s requested but no splitnet in configuration\n",
+ s_isakmp_cfg_type(type));
+ }
break;
default:
@@ -1042,6 +1051,36 @@ isakmp_cfg_addr4(iph1, attr, addr)
}
static vchar_t *
+isakmp_cfg_addrnet4(iph1, attr, addr, mask)
+ struct ph1handle *iph1;
+ struct isakmp_data *attr;
+ in_addr_t *addr;
+ in_addr_t *mask;
+{
+ vchar_t *buffer;
+ struct isakmp_data *new;
+ size_t len;
+ in_addr_t netbuff[2];
+
+ len = sizeof(netbuff);
+ if ((buffer = vmalloc(sizeof(*attr) + len)) == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
+ return NULL;
+ }
+
+ new = (struct isakmp_data *)buffer->v;
+
+ new->type = attr->type;
+ new->lorv = htons(len);
+ netbuff[0]=*addr;
+ netbuff[1]=*mask;
+ memcpy(new + 1, netbuff, len);
+
+ return buffer;
+}
+
+
+static vchar_t *
isakmp_cfg_addr4_list(iph1, attr, addr, nbr)
struct ph1handle *iph1;
struct isakmp_data *attr;
@@ -1127,7 +1166,7 @@ isakmp_cfg_send(iph1, payload, np, flags, new_exchange)
struct isakmp_cfg_state *ics = iph1->mode_cfg;
/* Check if phase 1 is established */
- if ((iph1->status != PHASE1ST_ESTABLISHED) ||
+ if ((iph1->status < PHASE1ST_ESTABLISHED) ||
(iph1->local == NULL) ||
(iph1->remote == NULL)) {
plog(LLV_ERROR, LOCATION, NULL,
@@ -1151,16 +1190,6 @@ isakmp_cfg_send(iph1, payload, np, flags, new_exchange)
goto end;
}
-#if (!defined(ENABLE_NATT)) || (defined(BROKEN_NATT))
- if (set_port(iph2->dst, 0) == NULL ||
- set_port(iph2->src, 0) == NULL) {
- plog(LLV_ERROR, LOCATION, NULL,
- "invalid family: %d\n", iph1->remote->sa_family);
- delph2(iph2);
- goto end;
- }
-#endif
- iph2->ph1 = iph1;
iph2->side = INITIATOR;
iph2->status = PHASE2ST_START;
@@ -1179,7 +1208,7 @@ isakmp_cfg_send(iph1, payload, np, flags, new_exchange)
}
/* generate HASH(1) */
- hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, payload);
+ hash = oakley_compute_hash1(iph1, iph2->msgid, payload);
if (hash == NULL) {
delph2(iph2);
goto end;
@@ -1278,7 +1307,6 @@ err:
if (iph2->sendbuf != NULL)
vfree(iph2->sendbuf);
- unbindph12(iph2);
remph2(iph2);
delph2(iph2);
end:
@@ -1492,24 +1520,6 @@ isakmp_cfg_accounting_radius(iph1, inout)
struct ph1handle *iph1;
int inout;
{
- /* For first time use, initialize Radius */
- if (radius_acct_state == NULL) {
- if ((radius_acct_state = rad_acct_open()) == NULL) {
- plog(LLV_ERROR, LOCATION, NULL,
- "Cannot init librradius\n");
- return -1;
- }
-
- if (rad_config(radius_acct_state, NULL) != 0) {
- plog(LLV_ERROR, LOCATION, NULL,
- "Cannot open librarius config file: %s\n",
- rad_strerror(radius_acct_state));
- rad_close(radius_acct_state);
- radius_acct_state = NULL;
- return -1;
- }
- }
-
if (rad_create_request(radius_acct_state,
RAD_ACCOUNTING_REQUEST) != 0) {
plog(LLV_ERROR, LOCATION, NULL,
@@ -1651,8 +1661,7 @@ isakmp_cfg_accounting_system(port, raddr, usr, inout)
int inout;
{
int error = 0;
- struct utmp ut;
- char term[UT_LINESIZE];
+ struct utmpx ut;
char addr[NI_MAXHOST];
if (usr == NULL || usr[0]=='\0') {
@@ -1661,36 +1670,33 @@ isakmp_cfg_accounting_system(port, raddr, usr, inout)
return -1;
}
- sprintf(term, TERMSPEC, port);
+ memset(&ut, 0, sizeof ut);
+ gettimeofday((struct timeval *)&ut.ut_tv, NULL);
+ snprintf(ut.ut_id, sizeof ut.ut_id, TERMSPEC, port);
switch (inout) {
case ISAKMP_CFG_LOGIN:
- strncpy(ut.ut_name, usr, UT_NAMESIZE);
- ut.ut_name[UT_NAMESIZE - 1] = '\0';
-
- strncpy(ut.ut_line, term, UT_LINESIZE);
- ut.ut_line[UT_LINESIZE - 1] = '\0';
+ ut.ut_type = USER_PROCESS;
+ strncpy(ut.ut_user, usr, sizeof ut.ut_user);
GETNAMEINFO_NULL(raddr, addr);
- strncpy(ut.ut_host, addr, UT_HOSTSIZE);
- ut.ut_host[UT_HOSTSIZE - 1] = '\0';
+ strncpy(ut.ut_host, addr, sizeof ut.ut_host);
- ut.ut_time = time(NULL);
-
plog(LLV_INFO, LOCATION, NULL,
"Accounting : '%s' logging on '%s' from %s.\n",
- ut.ut_name, ut.ut_line, ut.ut_host);
+ ut.ut_user, ut.ut_id, addr);
- login(&ut);
+ pututxline(&ut);
break;
case ISAKMP_CFG_LOGOUT:
+ ut.ut_type = DEAD_PROCESS;
plog(LLV_INFO, LOCATION, NULL,
"Accounting : '%s' unlogging from '%s'.\n",
- usr, term);
+ usr, ut.ut_id);
- logout(term);
+ pututxline(&ut);
break;
default:
@@ -1865,6 +1871,7 @@ isakmp_cfg_setenv(iph1, envp, envc)
char addrstr[IP_MAX];
char addrlist[IP_MAX * MAXNS + MAXNS];
char *splitlist = addrlist;
+ char *splitlist_cidr;
char defdom[MAXPATHLEN + 1];
int cidr, tmp;
char cidrstr[4];
@@ -2005,10 +2012,14 @@ isakmp_cfg_setenv(iph1, envp, envc)
}
/* Split networks */
- if (iph1->mode_cfg->flags & ISAKMP_CFG_GOT_SPLIT_INCLUDE)
- splitlist = splitnet_list_2str(iph1->mode_cfg->split_include);
- else {
+ if (iph1->mode_cfg->flags & ISAKMP_CFG_GOT_SPLIT_INCLUDE) {
+ splitlist =
+ splitnet_list_2str(iph1->mode_cfg->split_include, NETMASK);
+ splitlist_cidr =
+ splitnet_list_2str(iph1->mode_cfg->split_include, CIDR);
+ } else {
splitlist = addrlist;
+ splitlist_cidr = addrlist;
addrlist[0] = '\0';
}
@@ -2016,13 +2027,25 @@ isakmp_cfg_setenv(iph1, envp, envc)
plog(LLV_ERROR, LOCATION, NULL, "Cannot set SPLIT_INCLUDE\n");
return -1;
}
+ if (script_env_append(envp, envc,
+ "SPLIT_INCLUDE_CIDR", splitlist_cidr) != 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "Cannot set SPLIT_INCLUDE_CIDR\n");
+ return -1;
+ }
if (splitlist != addrlist)
racoon_free(splitlist);
-
- if (iph1->mode_cfg->flags & ISAKMP_CFG_GOT_SPLIT_LOCAL)
- splitlist = splitnet_list_2str(iph1->mode_cfg->split_local);
- else {
+ if (splitlist_cidr != addrlist)
+ racoon_free(splitlist_cidr);
+
+ if (iph1->mode_cfg->flags & ISAKMP_CFG_GOT_SPLIT_LOCAL) {
+ splitlist =
+ splitnet_list_2str(iph1->mode_cfg->split_local, NETMASK);
+ splitlist_cidr =
+ splitnet_list_2str(iph1->mode_cfg->split_local, CIDR);
+ } else {
splitlist = addrlist;
+ splitlist_cidr = addrlist;
addrlist[0] = '\0';
}
@@ -2030,8 +2053,16 @@ isakmp_cfg_setenv(iph1, envp, envc)
plog(LLV_ERROR, LOCATION, NULL, "Cannot set SPLIT_LOCAL\n");
return -1;
}
+ if (script_env_append(envp, envc,
+ "SPLIT_LOCAL_CIDR", splitlist_cidr) != 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "Cannot set SPLIT_LOCAL_CIDR\n");
+ return -1;
+ }
if (splitlist != addrlist)
racoon_free(splitlist);
+ if (splitlist_cidr != addrlist)
+ racoon_free(splitlist_cidr);
return 0;
}
diff --git a/src/racoon/isakmp_frag.c b/src/racoon/isakmp_frag.c
index 6fac6a2..ebba34b 100644
--- a/src/racoon/isakmp_frag.c
+++ b/src/racoon/isakmp_frag.c
@@ -1,4 +1,4 @@
-/* $NetBSD: isakmp_frag.c,v 1.4.6.1 2009/04/22 11:25:35 tteras Exp $ */
+/* $NetBSD: isakmp_frag.c,v 1.5 2009/04/22 11:24:20 tteras Exp $ */
/* Id: isakmp_frag.c,v 1.4 2004/11/13 17:31:36 manubsd Exp */
diff --git a/src/racoon/isakmp_ident.c b/src/racoon/isakmp_ident.c
index 1e00dc4..a9c3a01 100644
--- a/src/racoon/isakmp_ident.c
+++ b/src/racoon/isakmp_ident.c
@@ -1,11 +1,11 @@
-/* $NetBSD: isakmp_ident.c,v 1.6 2006/10/02 21:41:59 manu Exp $ */
+/* $NetBSD: isakmp_ident.c,v 1.13 2009/09/18 10:31:11 tteras Exp $ */
/* Id: isakmp_ident.c,v 1.21 2006/04/06 16:46:08 manubsd Exp */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -17,7 +17,7 @@
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -86,12 +86,13 @@
#include "isakmp_xauth.h"
#include "isakmp_cfg.h"
#endif
-#ifdef ENABLE_FRAG
+#ifdef ENABLE_FRAG
#include "isakmp_frag.h"
#endif
static vchar_t *ident_ir2mx __P((struct ph1handle *));
static vchar_t *ident_ir3mx __P((struct ph1handle *));
+static int ident_recv_n __P((struct ph1handle *, struct isakmp_gen *));
/* %%%
* begin Identity Protection Mode as initiator.
@@ -114,13 +115,13 @@ ident_i1send(iph1, msg)
vchar_t *vid_natt[MAX_NATT_VID_COUNT] = { NULL };
int i;
#endif
-#ifdef ENABLE_HYBRID
+#ifdef ENABLE_HYBRID
vchar_t *vid_xauth = NULL;
vchar_t *vid_unity = NULL;
#endif
-#ifdef ENABLE_FRAG
+#ifdef ENABLE_FRAG
vchar_t *vid_frag = NULL;
-#endif
+#endif
#ifdef ENABLE_DPD
vchar_t *vid_dpd = NULL;
#endif
@@ -141,7 +142,8 @@ ident_i1send(iph1, msg)
isakmp_newcookie((caddr_t)&iph1->index, iph1->remote, iph1->local);
/* create SA payload for my proposal */
- iph1->sa = ipsecdoi_setph1proposal(iph1->rmconf->proposal);
+ iph1->sa = ipsecdoi_setph1proposal(iph1->rmconf,
+ iph1->rmconf->proposal);
if (iph1->sa == NULL)
goto end;
@@ -150,13 +152,13 @@ ident_i1send(iph1, msg)
#ifdef ENABLE_NATT
/* set VID payload for NAT-T if NAT-T support allowed in the config file */
- if (iph1->rmconf->nat_traversal)
+ if (iph1->rmconf->nat_traversal)
plist = isakmp_plist_append_natt_vids(plist, vid_natt);
#endif
#ifdef ENABLE_HYBRID
/* Do we need Xauth VID? */
- switch (RMAUTHMETHOD(iph1)) {
- case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I:
+ switch (iph1->rmconf->proposal->authmethod) {
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I:
case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
@@ -169,12 +171,12 @@ ident_i1send(iph1, msg)
else
plist = isakmp_plist_append(plist,
vid_xauth, ISAKMP_NPTYPE_VID);
-
+
if ((vid_unity = set_vendorid(VENDORID_UNITY)) == NULL)
plog(LLV_ERROR, LOCATION, NULL,
"Unity vendor ID generation failed\n");
else
- plist = isakmp_plist_append(plist,
+ plist = isakmp_plist_append(plist,
vid_unity, ISAKMP_NPTYPE_VID);
break;
default:
@@ -189,7 +191,7 @@ ident_i1send(iph1, msg)
} else {
vid_frag = isakmp_frag_addcap(vid_frag,
VENDORID_FRAG_IDENT);
- plist = isakmp_plist_append(plist,
+ plist = isakmp_plist_append(plist,
vid_frag, ISAKMP_NPTYPE_VID);
}
}
@@ -210,8 +212,7 @@ ident_i1send(iph1, msg)
#endif
/* send the packet, add to the schedule to resend */
- iph1->retry_counter = iph1->rmconf->retry_counter;
- if (isakmp_ph1resend(iph1) == -1)
+ if (isakmp_ph1send(iph1) == -1)
goto end;
iph1->status = PHASE1ST_MSG1SENT;
@@ -220,9 +221,9 @@ ident_i1send(iph1, msg)
end:
#ifdef ENABLE_FRAG
- if (vid_frag)
+ if (vid_frag)
vfree(vid_frag);
-#endif
+#endif
#ifdef ENABLE_NATT
for (i = 0; i < MAX_NATT_VID_COUNT && vid_natt[i] != NULL; i++)
vfree(vid_natt[i]);
@@ -257,7 +258,6 @@ ident_i2recv(iph1, msg)
struct isakmp_parse_t *pa;
vchar_t *satmp = NULL;
int error = -1;
- int vid_numeric;
/* validity check */
if (iph1->status != PHASE1ST_MSG1SENT) {
@@ -299,31 +299,7 @@ ident_i2recv(iph1, msg)
switch (pa->type) {
case ISAKMP_NPTYPE_VID:
- vid_numeric = check_vendorid(pa->ptr);
-#ifdef ENABLE_NATT
- if (iph1->rmconf->nat_traversal && natt_vendorid(vid_numeric))
- natt_handle_vendorid(iph1, vid_numeric);
-#endif
-#ifdef ENABLE_HYBRID
- switch (vid_numeric) {
- case VENDORID_XAUTH:
- iph1->mode_cfg->flags |=
- ISAKMP_CFG_VENDORID_XAUTH;
- break;
-
- case VENDORID_UNITY:
- iph1->mode_cfg->flags |=
- ISAKMP_CFG_VENDORID_UNITY;
- break;
-
- default:
- break;
- }
-#endif
-#ifdef ENABLE_DPD
- if (vid_numeric == VENDORID_DPD && iph1->rmconf->dpd)
- iph1->dpd_support=1;
-#endif
+ handle_vendorid(iph1, pa->ptr);
break;
default:
/* don't send information, see ident_r1recv() */
@@ -401,7 +377,7 @@ ident_i2send(iph1, msg)
goto end;
#ifdef HAVE_GSSAPI
- if (AUTHMETHOD(iph1) == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB &&
+ if (iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB &&
gssapi_get_itoken(iph1, NULL) < 0)
goto end;
#endif
@@ -416,8 +392,7 @@ ident_i2send(iph1, msg)
#endif
/* send the packet, add to the schedule to resend */
- iph1->retry_counter = iph1->rmconf->retry_counter;
- if (isakmp_ph1resend(iph1) == -1)
+ if (isakmp_ph1send(iph1) == -1)
goto end;
/* the sending message is added to the received-list. */
@@ -485,7 +460,7 @@ ident_i3recv(iph1, msg)
goto end;
break;
case ISAKMP_NPTYPE_VID:
- (void)check_vendorid(pa->ptr);
+ handle_vendorid(iph1, pa->ptr);
break;
case ISAKMP_NPTYPE_CR:
if (oakley_savecr(iph1, pa->ptr) < 0)
@@ -507,21 +482,21 @@ ident_i3recv(iph1, msg)
natd_received = NULL;
if (isakmp_p2ph (&natd_received, pa->ptr) < 0)
goto end;
-
+
/* set both bits first so that we can clear them
upon verifying hashes */
if (natd_seq == 0)
iph1->natt_flags |= NAT_DETECTED;
-
- /* this function will clear appropriate bits bits
+
+ /* this function will clear appropriate bits bits
from iph1->natt_flags */
natd_verified = natt_compare_addr_hash (iph1,
natd_received, natd_seq++);
-
+
plog (LLV_INFO, LOCATION, NULL, "NAT-D payload #%d %s\n",
natd_seq - 1,
natd_verified ? "verified" : "doesn't match");
-
+
vfree (natd_received);
break;
}
@@ -541,7 +516,7 @@ ident_i3recv(iph1, msg)
#ifdef ENABLE_NATT
if (NATT_AVAILABLE(iph1)) {
plog (LLV_INFO, LOCATION, NULL, "NAT %s %s%s\n",
- iph1->natt_flags & NAT_DETECTED ?
+ iph1->natt_flags & NAT_DETECTED ?
"detected:" : "not detected",
iph1->natt_flags & NAT_DETECTED_ME ? "ME " : "",
iph1->natt_flags & NAT_DETECTED_PEER ? "PEER" : "");
@@ -577,8 +552,7 @@ end:
VPTRINIT(iph1->dhpub_p);
VPTRINIT(iph1->nonce_p);
VPTRINIT(iph1->id_p);
- oakley_delcert(iph1->cr_p);
- iph1->cr_p = NULL;
+ VPTRINIT(iph1->cr_p);
}
return error;
@@ -630,7 +604,7 @@ ident_i3send(iph1, msg0)
goto end;
#ifdef HAVE_GSSAPI
- if (AUTHMETHOD(iph1) == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB &&
+ if (iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB &&
gssapi_more_tokens(iph1)) {
plog(LLV_DEBUG, LOCATION, NULL, "calling get_itoken\n");
if (gssapi_get_itoken(iph1, &len) < 0)
@@ -657,8 +631,7 @@ ident_i3send(iph1, msg0)
goto end;
/* send the packet, add to the schedule to resend */
- iph1->retry_counter = iph1->rmconf->retry_counter;
- if (isakmp_ph1resend(iph1) == -1)
+ if (isakmp_ph1send(iph1) == -1)
goto end;
/* the sending message is added to the received-list. */
@@ -754,10 +727,10 @@ ident_i4recv(iph1, msg0)
break;
#endif
case ISAKMP_NPTYPE_VID:
- (void)check_vendorid(pa->ptr);
+ handle_vendorid(iph1, pa->ptr);
break;
case ISAKMP_NPTYPE_N:
- isakmp_check_notify(pa->ptr, iph1);
+ ident_recv_n(iph1, pa->ptr);
break;
default:
/* don't send information, see ident_r1recv() */
@@ -788,8 +761,7 @@ ident_i4recv(iph1, msg0)
/* msg printed inner oakley_validate_auth() */
goto end;
}
- EVT_PUSH(iph1->local, iph1->remote,
- EVTT_PEERPH1AUTH_FAILED, NULL);
+ evt_phase1(iph1, EVT_PHASE1_AUTH_FAILED, NULL);
isakmp_info_send_n1(iph1, type, NULL);
goto end;
}
@@ -812,7 +784,7 @@ ident_i4recv(iph1, msg0)
* If we got a GSS token, we need to this roundtrip again.
*/
#ifdef HAVE_GSSAPI
- iph1->status = gsstoken != 0 ? PHASE1ST_MSG3RECEIVED :
+ iph1->status = gsstoken != 0 ? PHASE1ST_MSG3RECEIVED :
PHASE1ST_MSG4RECEIVED;
#else
iph1->status = PHASE1ST_MSG4RECEIVED;
@@ -832,10 +804,8 @@ end:
if (error) {
VPTRINIT(iph1->id_p);
- oakley_delcert(iph1->cert_p);
- iph1->cert_p = NULL;
- oakley_delcert(iph1->crl_p);
- iph1->crl_p = NULL;
+ VPTRINIT(iph1->cert_p);
+ VPTRINIT(iph1->crl_p);
VPTRINIT(iph1->sig_p);
}
@@ -921,35 +891,11 @@ ident_r1recv(iph1, msg)
switch (pa->type) {
case ISAKMP_NPTYPE_VID:
- vid_numeric = check_vendorid(pa->ptr);
-#ifdef ENABLE_NATT
- if (iph1->rmconf->nat_traversal && natt_vendorid(vid_numeric))
- natt_handle_vendorid(iph1, vid_numeric);
-#endif
+ vid_numeric = handle_vendorid(iph1, pa->ptr);
#ifdef ENABLE_FRAG
if ((vid_numeric == VENDORID_FRAG) &&
(vendorid_frag_cap(pa->ptr) & VENDORID_FRAG_IDENT))
iph1->frag = 1;
-#endif
-#ifdef ENABLE_HYBRID
- switch (vid_numeric) {
- case VENDORID_XAUTH:
- iph1->mode_cfg->flags |=
- ISAKMP_CFG_VENDORID_XAUTH;
- break;
-
- case VENDORID_UNITY:
- iph1->mode_cfg->flags |=
- ISAKMP_CFG_VENDORID_UNITY;
- break;
-
- default:
- break;
- }
-#endif
-#ifdef ENABLE_DPD
- if (vid_numeric == VENDORID_DPD && iph1->rmconf->dpd)
- iph1->dpd_support=1;
#endif
break;
default:
@@ -1021,13 +967,13 @@ ident_r1send(iph1, msg)
#ifdef ENABLE_HYBRID
vchar_t *vid_xauth = NULL;
vchar_t *vid_unity = NULL;
-#endif
+#endif
#ifdef ENABLE_DPD
vchar_t *vid_dpd = NULL;
#endif
-#ifdef ENABLE_FRAG
+#ifdef ENABLE_FRAG
vchar_t *vid_frag = NULL;
-#endif
+#endif
/* validity check */
if (iph1->status != PHASE1ST_MSG1RECEIVED) {
@@ -1041,10 +987,10 @@ ident_r1send(iph1, msg)
#ifdef HAVE_GSSAPI
if (iph1->approval->gssid != NULL) {
- gss_sa = ipsecdoi_setph1proposal(iph1->approval);
+ gss_sa = ipsecdoi_setph1proposal(iph1->rmconf, iph1->approval);
if (gss_sa != iph1->sa_ret)
free_gss_sa = 1;
- } else
+ } else
#endif
gss_sa = iph1->sa_ret;
@@ -1082,8 +1028,7 @@ ident_r1send(iph1, msg)
plist = isakmp_plist_append(plist, vid_natt, ISAKMP_NPTYPE_VID);
#endif
#ifdef ENABLE_DPD
- /* XXX only send DPD VID if remote sent it ? */
- if(iph1->rmconf->dpd){
+ if (iph1->dpd_support) {
vid_dpd = set_vendorid(VENDORID_DPD);
if (vid_dpd != NULL)
plist = isakmp_plist_append(plist, vid_dpd, ISAKMP_NPTYPE_VID);
@@ -1099,7 +1044,7 @@ ident_r1send(iph1, msg)
plog(LLV_ERROR, LOCATION, NULL,
"Frag vendorID construction failed\n");
else
- plist = isakmp_plist_append(plist,
+ plist = isakmp_plist_append(plist,
vid_frag, ISAKMP_NPTYPE_VID);
}
#endif
@@ -1111,10 +1056,8 @@ ident_r1send(iph1, msg)
#endif
/* send the packet, add to the schedule to resend */
- iph1->retry_counter = iph1->rmconf->retry_counter;
- if (isakmp_ph1resend(iph1) == -1) {
+ if (isakmp_ph1send(iph1) == -1)
goto end;
- }
/* the sending message is added to the received-list. */
if (add_recvdpkt(iph1->remote, iph1->local, iph1->sendbuf, msg) == -1) {
@@ -1203,7 +1146,7 @@ ident_r2recv(iph1, msg)
goto end;
break;
case ISAKMP_NPTYPE_VID:
- (void)check_vendorid(pa->ptr);
+ handle_vendorid(iph1, pa->ptr);
break;
case ISAKMP_NPTYPE_CR:
plog(LLV_WARNING, LOCATION, iph1->remote,
@@ -1226,20 +1169,20 @@ ident_r2recv(iph1, msg)
{
vchar_t *natd_received = NULL;
int natd_verified;
-
+
if (isakmp_p2ph (&natd_received, pa->ptr) < 0)
goto end;
-
+
if (natd_seq == 0)
iph1->natt_flags |= NAT_DETECTED;
-
+
natd_verified = natt_compare_addr_hash (iph1,
natd_received, natd_seq++);
-
+
plog (LLV_INFO, LOCATION, NULL, "NAT-D payload #%d %s\n",
natd_seq - 1,
natd_verified ? "verified" : "doesn't match");
-
+
vfree (natd_received);
break;
}
@@ -1259,7 +1202,7 @@ ident_r2recv(iph1, msg)
#ifdef ENABLE_NATT
if (NATT_AVAILABLE(iph1))
plog (LLV_INFO, LOCATION, NULL, "NAT %s %s%s\n",
- iph1->natt_flags & NAT_DETECTED ?
+ iph1->natt_flags & NAT_DETECTED ?
"detected:" : "not detected",
iph1->natt_flags & NAT_DETECTED_ME ? "ME " : "",
iph1->natt_flags & NAT_DETECTED_PEER ? "PEER" : "");
@@ -1321,12 +1264,12 @@ ident_r2send(iph1, msg)
goto end;
/* generate NONCE value */
- iph1->nonce = eay_set_random(iph1->rmconf->nonce_size);
+ iph1->nonce = eay_set_random(RMCONF_NONCE_SIZE(iph1->rmconf));
if (iph1->nonce == NULL)
goto end;
#ifdef HAVE_GSSAPI
- if (AUTHMETHOD(iph1) == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB)
+ if (iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB)
gssapi_get_rtoken(iph1, NULL);
#endif
@@ -1340,8 +1283,7 @@ ident_r2send(iph1, msg)
#endif
/* send the packet, add to the schedule to resend */
- iph1->retry_counter = iph1->rmconf->retry_counter;
- if (isakmp_ph1resend(iph1) == -1)
+ if (isakmp_ph1send(iph1) == -1)
goto end;
/* the sending message is added to the received-list. */
@@ -1429,6 +1371,8 @@ ident_r3recv(iph1, msg0)
case ISAKMP_NPTYPE_ID:
if (isakmp_p2ph(&iph1->id_p, pa->ptr) < 0)
goto end;
+ if (resolveph1rmconf(iph1) < 0)
+ goto end;
break;
case ISAKMP_NPTYPE_HASH:
iph1->pl_hash = (struct isakmp_pl_hash *)pa->ptr;
@@ -1453,10 +1397,10 @@ ident_r3recv(iph1, msg0)
break;
#endif
case ISAKMP_NPTYPE_VID:
- (void)check_vendorid(pa->ptr);
+ handle_vendorid(iph1, pa->ptr);
break;
case ISAKMP_NPTYPE_N:
- isakmp_check_notify(pa->ptr, iph1);
+ ident_recv_n(iph1, pa->ptr);
break;
default:
/* don't send information, see ident_r1recv() */
@@ -1473,7 +1417,7 @@ ident_r3recv(iph1, msg0)
{
int ng = 0;
- switch (AUTHMETHOD(iph1)) {
+ switch (iph1->approval->authmethod) {
case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
#ifdef ENABLE_HYBRID
case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
@@ -1537,8 +1481,7 @@ ident_r3recv(iph1, msg0)
/* msg printed inner oakley_validate_auth() */
goto end;
}
- EVT_PUSH(iph1->local, iph1->remote,
- EVTT_PEERPH1AUTH_FAILED, NULL);
+ evt_phase1(iph1, EVT_PHASE1_AUTH_FAILED, NULL);
isakmp_info_send_n1(iph1, type, NULL);
goto end;
}
@@ -1583,13 +1526,10 @@ end:
if (error) {
VPTRINIT(iph1->id_p);
- oakley_delcert(iph1->cert_p);
- iph1->cert_p = NULL;
- oakley_delcert(iph1->crl_p);
- iph1->crl_p = NULL;
+ VPTRINIT(iph1->cert_p);
+ VPTRINIT(iph1->crl_p);
VPTRINIT(iph1->sig_p);
- oakley_delcert(iph1->cr_p);
- iph1->cr_p = NULL;
+ VPTRINIT(iph1->cr_p);
}
return error;
@@ -1626,7 +1566,7 @@ ident_r3send(iph1, msg)
goto end;
#ifdef HAVE_GSSAPI
- if (AUTHMETHOD(iph1) == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB &&
+ if (iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB &&
gssapi_more_tokens(iph1)) {
gssapi_get_rtoken(iph1, &len);
if (len != 0)
@@ -1694,8 +1634,6 @@ ident_ir2mx(iph1)
{
vchar_t *buf = 0;
struct payload_list *plist = NULL;
- int need_cr = 0;
- vchar_t *cr = NULL;
vchar_t *vid = NULL;
int error = -1;
#ifdef HAVE_GSSAPI
@@ -1705,23 +1643,14 @@ ident_ir2mx(iph1)
vchar_t *natd[2] = { NULL, NULL };
#endif
- /* create CR if need */
- if (iph1->side == RESPONDER
- && iph1->rmconf->send_cr
- && oakley_needcr(iph1->approval->authmethod)
- && iph1->rmconf->peerscertfile == NULL) {
- need_cr = 1;
- cr = oakley_getcr(iph1);
- if (cr == NULL) {
+#ifdef HAVE_GSSAPI
+ if (iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB) {
+ if (gssapi_get_token_to_send(iph1, &gsstoken) < 0) {
plog(LLV_ERROR, LOCATION, NULL,
- "failed to get cr buffer.\n");
+ "Failed to get gssapi token.\n");
goto end;
}
}
-
-#ifdef HAVE_GSSAPI
- if (AUTHMETHOD(iph1) == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB)
- gssapi_get_token_to_send(iph1, &gsstoken);
#endif
/* create isakmp KE payload */
@@ -1731,7 +1660,7 @@ ident_ir2mx(iph1)
plist = isakmp_plist_append(plist, iph1->nonce, ISAKMP_NPTYPE_NONCE);
#ifdef HAVE_GSSAPI
- if (AUTHMETHOD(iph1) == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB)
+ if (iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB)
plist = isakmp_plist_append(plist, gsstoken, ISAKMP_NPTYPE_GSS);
#endif
@@ -1739,9 +1668,10 @@ ident_ir2mx(iph1)
if (vid)
plist = isakmp_plist_append(plist, vid, ISAKMP_NPTYPE_VID);
- /* create isakmp CR payload if needed */
- if (need_cr)
- plist = isakmp_plist_append(plist, cr, ISAKMP_NPTYPE_CR);
+ /* create CR if need */
+ if (iph1->side == RESPONDER &&
+ oakley_needcr(iph1->approval->authmethod))
+ plist = oakley_append_cr(plist, iph1);
#ifdef ENABLE_NATT
/* generate and append NAT-D payloads */
@@ -1764,9 +1694,9 @@ ident_ir2mx(iph1)
plist = isakmp_plist_append(plist, natd[1], iph1->natt_options->payload_nat_d);
}
#endif
-
+
buf = isakmp_plist_set_all (&plist, iph1);
-
+
error = 0;
end:
@@ -1774,8 +1704,6 @@ end:
vfree(buf);
buf = NULL;
}
- if (cr)
- vfree(cr);
#ifdef HAVE_GSSAPI
if (gsstoken)
vfree(gsstoken);
@@ -1814,9 +1742,7 @@ ident_ir3mx(iph1)
{
struct payload_list *plist = NULL;
vchar_t *buf = NULL, *new = NULL;
- int need_cr = 0;
int need_cert = 0;
- vchar_t *cr = NULL;
int error = -1;
#ifdef HAVE_GSSAPI
int nptype;
@@ -1824,10 +1750,10 @@ ident_ir3mx(iph1)
vchar_t *gsshash = NULL;
#endif
- switch (AUTHMETHOD(iph1)) {
+ switch (iph1->approval->authmethod) {
case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
#ifdef ENABLE_HYBRID
- case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I:
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I:
case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
@@ -1847,27 +1773,13 @@ ident_ir3mx(iph1)
case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
-#endif
+#endif
if (oakley_getmycert(iph1) < 0)
goto end;
if (oakley_getsign(iph1) < 0)
goto end;
- /* create CR if need */
- if (iph1->side == INITIATOR
- && iph1->rmconf->send_cr
- && oakley_needcr(iph1->approval->authmethod)
- && iph1->rmconf->peerscertfile == NULL) {
- need_cr = 1;
- cr = oakley_getcr(iph1);
- if (cr == NULL) {
- plog(LLV_ERROR, LOCATION, NULL,
- "failed to get cr buffer.\n");
- goto end;
- }
- }
-
if (iph1->cert != NULL && iph1->rmconf->send_cert)
need_cert = 1;
@@ -1876,13 +1788,15 @@ ident_ir3mx(iph1)
/* add CERT payload if there */
if (need_cert)
- plist = isakmp_plist_append(plist, iph1->cert->pl, ISAKMP_NPTYPE_CERT);
+ plist = isakmp_plist_append(plist, iph1->cert,
+ ISAKMP_NPTYPE_CERT);
/* add SIG payload */
plist = isakmp_plist_append(plist, iph1->sig, ISAKMP_NPTYPE_SIG);
/* create isakmp CR payload */
- if (need_cr)
- plist = isakmp_plist_append(plist, cr, ISAKMP_NPTYPE_CR);
+ if (iph1->side == INITIATOR &&
+ oakley_needcr(iph1->approval->authmethod))
+ plist = oakley_append_cr(plist, iph1);
break;
#ifdef HAVE_GSSAPI
case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
@@ -1891,7 +1805,11 @@ ident_ir3mx(iph1)
if (gsshash == NULL)
goto end;
} else {
- gssapi_get_token_to_send(iph1, &gsstoken);
+ if (gssapi_get_token_to_send(iph1, &gsstoken) < 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "Failed to get gssapi token.\n");
+ goto end;
+ }
}
if (!gssapi_id_sent(iph1)) {
@@ -1927,7 +1845,7 @@ ident_ir3mx(iph1)
}
buf = isakmp_plist_set_all (&plist, iph1);
-
+
#ifdef HAVE_PRINT_ISAKMP_C
isakmp_printpacket(buf, iph1->local, iph1->remote, 1);
#endif
@@ -1948,8 +1866,6 @@ end:
if (gsstoken)
vfree(gsstoken);
#endif
- if (cr)
- vfree(cr);
if (error && buf != NULL) {
vfree(buf);
buf = NULL;
@@ -1957,3 +1873,28 @@ end:
return buf;
}
+
+/*
+ * handle a notification payload inside identity exchange.
+ * called only when the packet has been verified to be encrypted.
+ */
+static int
+ident_recv_n(iph1, gen)
+ struct ph1handle *iph1;
+ struct isakmp_gen *gen;
+{
+ struct isakmp_pl_n *notify = (struct isakmp_pl_n *) gen;
+ u_int type;
+
+ type = ntohs(notify->type);
+ switch (type) {
+ case ISAKMP_NTYPE_INITIAL_CONTACT:
+ iph1->initial_contact_received = TRUE;
+ break;
+ default:
+ isakmp_log_notify(iph1, notify, "identity exchange");
+ break;
+ }
+ return 0;
+}
+
diff --git a/src/racoon/isakmp_inf.c b/src/racoon/isakmp_inf.c
index 5f487d2..9bf81c6 100644
--- a/src/racoon/isakmp_inf.c
+++ b/src/racoon/isakmp_inf.c
@@ -1,4 +1,4 @@
-/* $NetBSD: isakmp_inf.c,v 1.14.4.17 2009/05/18 17:07:46 tteras Exp $ */
+/* $NetBSD: isakmp_inf.c,v 1.47 2011/03/15 13:20:14 vanhu Exp $ */
/* Id: isakmp_inf.c,v 1.44 2006/05/06 20:45:52 manubsd Exp */
@@ -107,11 +107,10 @@ static int isakmp_info_recv_r_u __P((struct ph1handle *,
struct isakmp_pl_ru *, u_int32_t));
static int isakmp_info_recv_r_u_ack __P((struct ph1handle *,
struct isakmp_pl_ru *, u_int32_t));
-static void isakmp_info_send_r_u __P((void *));
+static void isakmp_info_send_r_u __P((struct sched *));
#endif
static void purge_isakmp_spi __P((int, isakmp_index *, size_t));
-static void info_recv_initialcontact __P((struct ph1handle *));
/* %%%
* Information Exchange
@@ -168,7 +167,8 @@ isakmp_info_recv(iph1, msg0)
if (msg->l < sizeof(*isakmp) + sizeof(*gen)) {
plog(LLV_ERROR, LOCATION, NULL,
"ignore information because the "
- "message is way too short - %zu byte(s).\n", msg->l);
+ "message is way too short - %zu byte(s).\n",
+ msg->l);
goto end;
}
@@ -179,14 +179,15 @@ isakmp_info_recv(iph1, msg0)
if (encrypted) {
if (isakmp->np != ISAKMP_NPTYPE_HASH) {
plog(LLV_ERROR, LOCATION, NULL,
- "ignore information because the"
+ "ignore information because the "
"message has no hash payload.\n");
goto end;
}
- if (iph1->status != PHASE1ST_ESTABLISHED) {
+ if (iph1->status != PHASE1ST_ESTABLISHED &&
+ iph1->status != PHASE1ST_DYING) {
plog(LLV_ERROR, LOCATION, NULL,
- "ignore information because ISAKMP-SA"
+ "ignore information because ISAKMP-SA "
"has not been established yet.\n");
goto end;
}
@@ -195,7 +196,8 @@ isakmp_info_recv(iph1, msg0)
if (msg->l < sizeof(*isakmp) + ntohs(gen->len) + sizeof(*nd)) {
plog(LLV_ERROR, LOCATION, NULL,
"ignore information because the "
- "message is too short - %zu byte(s).\n", msg->l);
+ "message is too short - %zu byte(s).\n",
+ msg->l);
goto end;
}
@@ -323,6 +325,65 @@ isakmp_info_recv(iph1, msg0)
return error;
}
+
+/*
+ * log unhandled / unallowed Notification payload
+ */
+int
+isakmp_log_notify(iph1, notify, exchange)
+ struct ph1handle *iph1;
+ struct isakmp_pl_n *notify;
+ const char *exchange;
+{
+ u_int type;
+ char *nraw, *ndata, *nhex;
+ size_t l;
+
+ type = ntohs(notify->type);
+ if (ntohs(notify->h.len) < sizeof(*notify) + notify->spi_size) {
+ plog(LLV_ERROR, LOCATION, iph1->remote,
+ "invalid spi_size in %s notification in %s.\n",
+ s_isakmp_notify_msg(type), exchange);
+ return -1;
+ }
+
+ plog(LLV_ERROR, LOCATION, iph1->remote,
+ "notification %s received in %s.\n",
+ s_isakmp_notify_msg(type), exchange);
+
+ nraw = ((char*) notify) + sizeof(*notify) + notify->spi_size;
+ l = ntohs(notify->h.len) - sizeof(*notify) - notify->spi_size;
+ if (l > 0) {
+ if (type >= ISAKMP_NTYPE_MINERROR &&
+ type <= ISAKMP_NTYPE_MAXERROR) {
+ ndata = binsanitize(nraw, l);
+ if (ndata != NULL) {
+ plog(LLV_ERROR, LOCATION, iph1->remote,
+ "error message: '%s'.\n",
+ ndata);
+ racoon_free(ndata);
+ } else {
+ plog(LLV_ERROR, LOCATION, iph1->remote,
+ "Cannot allocate memory\n");
+ }
+ } else {
+ nhex = val2str(nraw, l);
+ if (nhex != NULL) {
+ plog(LLV_ERROR, LOCATION, iph1->remote,
+ "notification payload: %s.\n",
+ nhex);
+ racoon_free(nhex);
+ } else {
+ plog(LLV_ERROR, LOCATION, iph1->remote,
+ "Cannot allocate memory\n");
+ }
+ }
+ }
+
+ return 0;
+}
+
+
/*
* handling of Notification payload
*/
@@ -334,13 +395,8 @@ isakmp_info_recv_n(iph1, notify, msgid, encrypted)
int encrypted;
{
u_int type;
- vchar_t *pbuf;
- char *nraw, *ndata;
- size_t l;
- char *spi;
type = ntohs(notify->type);
-
switch (type) {
case ISAKMP_NTYPE_CONNECTED:
case ISAKMP_NTYPE_RESPONDER_LIFETIME:
@@ -352,8 +408,7 @@ isakmp_info_recv_n(iph1, notify, msgid, encrypted)
break;
case ISAKMP_NTYPE_INITIAL_CONTACT:
if (encrypted)
- info_recv_initialcontact(iph1);
- return 0;
+ return isakmp_info_recv_initialcontact(iph1, NULL);
break;
#ifdef ENABLE_DPD
case ISAKMP_NTYPE_R_U_THERE:
@@ -367,76 +422,23 @@ isakmp_info_recv_n(iph1, notify, msgid, encrypted)
(struct isakmp_pl_ru *)notify, msgid);
break;
#endif
- default:
- {
- /* XXX there is a potential of dos attack. */
- if(type >= ISAKMP_NTYPE_MINERROR &&
- type <= ISAKMP_NTYPE_MAXERROR) {
- if (msgid == 0) {
- /* don't think this realy deletes ph1 ? */
- plog(LLV_ERROR, LOCATION, iph1->remote,
- "delete phase1 handle.\n");
- return -1;
- } else {
- if (getph2bymsgid(iph1, msgid) == NULL) {
- plog(LLV_ERROR, LOCATION, iph1->remote,
- "fatal %s notify messsage, "
- "phase1 should be deleted.\n",
- s_isakmp_notify_msg(type));
- } else {
- plog(LLV_ERROR, LOCATION, iph1->remote,
- "fatal %s notify messsage, "
- "phase2 should be deleted.\n",
- s_isakmp_notify_msg(type));
- }
- }
- } else {
- plog(LLV_ERROR, LOCATION, iph1->remote,
- "unhandled notify message %s, "
- "no phase2 handle found.\n",
- s_isakmp_notify_msg(type));
- }
- }
- break;
}
- /* get spi if specified and allocate */
- if(notify->spi_size > 0) {
- if (ntohs(notify->h.len) < sizeof(*notify) + notify->spi_size) {
- plog(LLV_ERROR, LOCATION, iph1->remote,
- "invalid spi_size in notification payload.\n");
- return -1;
- }
- spi = val2str((char *)(notify + 1), notify->spi_size);
-
- plog(LLV_DEBUG, LOCATION, iph1->remote,
- "notification message %d:%s, "
- "doi=%d proto_id=%d spi=%s(size=%d).\n",
- type, s_isakmp_notify_msg(type),
- ntohl(notify->doi), notify->proto_id, spi, notify->spi_size);
-
- racoon_free(spi);
- }
+ /* If we receive a error notification we should delete the related
+ * phase1 / phase2 handle, and send an event to racoonctl.
+ * However, since phase1 error notifications are not encrypted and
+ * can not be authenticated, it would allow a DoS attack possibility
+ * to handle them.
+ * Phase2 error notifications should be encrypted, so we could handle
+ * those, but it needs implementing (the old code didn't implement
+ * that either).
+ * So we are good to just log the messages here.
+ */
+ if (encrypted)
+ isakmp_log_notify(iph1, notify, "informational exchange");
+ else
+ isakmp_log_notify(iph1, notify, "unencrypted informational exchange");
- /* Send the message data to the logs */
- if(type >= ISAKMP_NTYPE_MINERROR &&
- type <= ISAKMP_NTYPE_MAXERROR) {
- l = ntohs(notify->h.len) - sizeof(*notify) - notify->spi_size;
- if (l > 0) {
- nraw = (char*)notify;
- nraw += sizeof(*notify) + notify->spi_size;
- ndata = binsanitize(nraw, l);
- if (ndata != NULL) {
- plog(LLV_ERROR, LOCATION, iph1->remote,
- "Message: '%s'.\n",
- ndata);
- racoon_free(ndata);
- } else {
- plog(LLV_ERROR, LOCATION, iph1->remote,
- "Cannot allocate memory\n");
- }
- }
- }
return 0;
}
@@ -510,16 +512,16 @@ isakmp_info_recv_d(iph1, delete, msgid, encrypted)
del_ph1=getph1byindex((isakmp_index *)(delete + 1));
if(del_ph1 != NULL){
- EVT_PUSH(del_ph1->local, del_ph1->remote,
- EVTT_PEERPH1_NOPROP, NULL);
- if (del_ph1->scr)
- SCHED_KILL(del_ph1->scr);
+ evt_phase1(iph1, EVT_PHASE1_PEER_DELETED, NULL);
+ sched_cancel(&del_ph1->scr);
/*
- * Do not delete IPsec SAs when receiving an IKE delete notification.
- * Just delete the IKE SA.
+ * Delete also IPsec-SAs if rekeying is enabled.
*/
- isakmp_ph1expire(del_ph1);
+ if (ph1_rekey_enabled(del_ph1))
+ purge_remote(del_ph1);
+ else
+ isakmp_ph1expire(del_ph1);
}
break;
@@ -532,8 +534,6 @@ isakmp_info_recv_d(iph1, delete, msgid, encrypted)
delete->spi_size, delete->proto_id);
return 0;
}
- EVT_PUSH(iph1->local, iph1->remote,
- EVTT_PEER_DELETE, NULL);
purge_ipsec_spi(iph1->remote, delete->proto_id,
(u_int32_t *)(delete + 1), num_spi);
break;
@@ -636,7 +636,7 @@ isakmp_info_send_d2(iph2)
* don't send delete information if there is no phase 1 handler.
* It's nonsensical to negotiate phase 1 to send the information.
*/
- iph1 = getph1byaddr(iph2->src, iph2->dst, 0);
+ iph1 = getph1byaddr(iph2->src, iph2->dst, 0);
if (iph1 == NULL){
plog(LLV_DEBUG2, LOCATION, NULL,
"No ph1 handler found, could not send DELETE_SA\n");
@@ -696,21 +696,12 @@ isakmp_info_send_nx(isakmp, remote, local, type, data)
vchar_t *data;
{
struct ph1handle *iph1 = NULL;
- struct remoteconf *rmconf;
vchar_t *payload = NULL;
int tlen;
int error = -1;
struct isakmp_pl_n *n;
int spisiz = 0; /* see below */
- /* search appropreate configuration */
- rmconf = getrmconf(remote);
- if (rmconf == NULL) {
- plog(LLV_ERROR, LOCATION, remote,
- "no configuration found for peer address.\n");
- goto end;
- }
-
/* add new entry to isakmp status table. */
iph1 = newph1();
if (iph1 == NULL)
@@ -719,7 +710,6 @@ isakmp_info_send_nx(isakmp, remote, local, type, data)
memcpy(&iph1->index.i_ck, &isakmp->i_ck, sizeof(cookie_t));
isakmp_newcookie((char *)&iph1->index.r_ck, remote, local);
iph1->status = PHASE1ST_START;
- iph1->rmconf = rmconf;
iph1->side = INITIATOR;
iph1->version = isakmp->v;
iph1->flags = 0;
@@ -734,7 +724,7 @@ isakmp_info_send_nx(isakmp, remote, local, type, data)
#endif
/* copy remote address */
- if (copy_ph1addresses(iph1, rmconf, remote, local) < 0)
+ if (copy_ph1addresses(iph1, NULL, remote, local) < 0)
goto end;
tlen = sizeof(*n) + spisiz;
@@ -911,16 +901,6 @@ isakmp_info_send_common(iph1, payload, np, flags)
delph2(iph2);
goto end;
}
-#if (!defined(ENABLE_NATT)) || (defined(BROKEN_NATT))
- if (set_port(iph2->dst, 0) == NULL ||
- set_port(iph2->src, 0) == NULL) {
- plog(LLV_ERROR, LOCATION, NULL,
- "invalid family: %d\n", iph1->remote->sa_family);
- delph2(iph2);
- goto end;
- }
-#endif
- iph2->ph1 = iph1;
iph2->side = INITIATOR;
iph2->status = PHASE2ST_START;
iph2->msgid = isakmp_newmsgid2(iph1);
@@ -934,7 +914,7 @@ isakmp_info_send_common(iph1, payload, np, flags)
}
/* generate HASH(1) */
- hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, payload);
+ hash = oakley_compute_hash1(iph1, iph2->msgid, payload);
if (hash == NULL) {
delph2(iph2);
goto end;
@@ -1035,7 +1015,6 @@ end:
return error;
err:
- unbindph12(iph2);
remph2(iph2);
delph2(iph2);
goto end;
@@ -1114,9 +1093,8 @@ purge_isakmp_spi(proto, spi, n)
s_ipsecdoi_proto(proto),
isakmp_pindex(&spi[i], 0));
- SCHED_KILL(iph1->sce);
iph1->status = PHASE1ST_EXPIRED;
- iph1->sce = sched_new(1, isakmp_ph1delete_stub, iph1);
+ isakmp_ph1delete(iph1);
}
}
@@ -1138,10 +1116,6 @@ purge_ipsec_spi(dst0, proto, spi, n)
u_int64_t created;
size_t i;
caddr_t mhp[SADB_EXT_MAX + 1];
-#ifdef ENABLE_NATT
- struct sadb_x_nat_t_type *natt_type;
- struct sadb_x_nat_t_port *natt_port;
-#endif
plog(LLV_DEBUG2, LOCATION, NULL,
"purge_ipsec_spi:\n");
@@ -1181,6 +1155,7 @@ purge_ipsec_spi(dst0, proto, spi, n)
msg = next;
continue;
}
+ pk_fixup_sa_addresses(mhp);
src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
lt = (struct sadb_lifetime*)mhp[SADB_EXT_LIFETIME_HARD];
@@ -1194,25 +1169,7 @@ purge_ipsec_spi(dst0, proto, spi, n)
msg = next;
continue;
}
-#ifdef ENABLE_NATT
- natt_type = (void *)mhp[SADB_X_EXT_NAT_T_TYPE];
- if (natt_type && natt_type->sadb_x_nat_t_type_type) {
- /* NAT-T is enabled for this SADB entry; copy
- * the ports from NAT-T extensions */
- natt_port = (void *)mhp[SADB_X_EXT_NAT_T_SPORT];
- if (extract_port(src) == 0 && natt_port != NULL)
- set_port(src, ntohs(natt_port->sadb_x_nat_t_port_port));
-
- natt_port = (void *)mhp[SADB_X_EXT_NAT_T_DPORT];
- if (extract_port(dst) == 0 && natt_port != NULL)
- set_port(dst, ntohs(natt_port->sadb_x_nat_t_port_port));
- }else{
- /* Force default UDP ports, so CMPSADDR will match SAs with NO encapsulation
- */
- set_port(src, PORT_ISAKMP);
- set_port(dst, PORT_ISAKMP);
- }
-#endif
+
plog(LLV_DEBUG2, LOCATION, NULL, "src: %s\n", saddr2str(src));
plog(LLV_DEBUG2, LOCATION, NULL, "dst: %s\n", saddr2str(dst));
@@ -1220,20 +1177,11 @@ purge_ipsec_spi(dst0, proto, spi, n)
/* don't delete inbound SAs at the moment */
/* XXX should we remove SAs with opposite direction as well? */
- if (CMPSADDR(dst0, dst)) {
+ if (cmpsaddr(dst0, dst) != CMPSADDR_MATCH) {
msg = next;
continue;
}
-#ifdef ENABLE_NATT
- if (natt_type == NULL ||
- ! natt_type->sadb_x_nat_t_type_type) {
- /* Set back port to 0 if it was forced to default UDP port
- */
- set_port(src, 0);
- set_port(dst, 0);
- }
-#endif
for (i = 0; i < n; i++) {
plog(LLV_DEBUG, LOCATION, NULL,
"check spi(packet)=%u spi(db)=%u.\n",
@@ -1254,7 +1202,6 @@ purge_ipsec_spi(dst0, proto, spi, n)
iph2 = getph2bysaidx(src, dst, proto, spi[i]);
if(iph2 != NULL){
delete_spd(iph2, created);
- unbindph12(iph2);
remph2(iph2);
delph2(iph2);
}
@@ -1273,15 +1220,17 @@ purge_ipsec_spi(dst0, proto, spi, n)
}
/*
- * delete all phase2 sa relatived to the destination address.
+ * delete all phase2 sa relatived to the destination address
+ * (except the phase2 within which the INITIAL-CONTACT was received).
* Don't delete Phase 1 handlers on INITIAL-CONTACT, and don't ignore
* an INITIAL-CONTACT if we have contacted the peer. This matches the
* Sun IKE behavior, and makes rekeying work much better when the peer
* restarts.
*/
-static void
-info_recv_initialcontact(iph1)
+int
+isakmp_info_recv_initialcontact(iph1, protectedph2)
struct ph1handle *iph1;
+ struct ph2handle *protectedph2;
{
vchar_t *buf = NULL;
struct sadb_msg *msg, *next, *end;
@@ -1294,8 +1243,10 @@ info_recv_initialcontact(iph1)
char *loc, *rem;
#endif
+ plog(LLV_INFO, LOCATION, iph1->remote, "received INITIAL-CONTACT\n");
+
if (f_local)
- return;
+ return 0;
#if 0
loc = racoon_strdup(saddrwop2str(iph1->local));
@@ -1344,7 +1295,7 @@ info_recv_initialcontact(iph1)
racoon_free(loc);
racoon_free(rem);
- return;
+ return 0;
the_hard_way:
racoon_free(loc);
@@ -1355,43 +1306,39 @@ info_recv_initialcontact(iph1)
if (buf == NULL) {
plog(LLV_DEBUG, LOCATION, NULL,
"pfkey_dump_sadb returned nothing.\n");
- return;
+ return 0;
}
msg = (struct sadb_msg *)buf->v;
end = (struct sadb_msg *)(buf->v + buf->l);
- while (msg < end) {
+ for (; msg < end; msg = next) {
if ((msg->sadb_msg_len << 3) < sizeof(*msg))
break;
+
next = (struct sadb_msg *)((caddr_t)msg + (msg->sadb_msg_len << 3));
- if (msg->sadb_msg_type != SADB_DUMP) {
- msg = next;
+ if (msg->sadb_msg_type != SADB_DUMP)
continue;
- }
if (pfkey_align(msg, mhp) || pfkey_check(mhp)) {
plog(LLV_ERROR, LOCATION, NULL,
"pfkey_check (%s)\n", ipsec_strerror());
- msg = next;
continue;
}
if (mhp[SADB_EXT_SA] == NULL
|| mhp[SADB_EXT_ADDRESS_SRC] == NULL
- || mhp[SADB_EXT_ADDRESS_DST] == NULL) {
- msg = next;
+ || mhp[SADB_EXT_ADDRESS_DST] == NULL)
continue;
- }
+
sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
+ pk_fixup_sa_addresses(mhp);
src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
if (sa->sadb_sa_state != SADB_SASTATE_MATURE
- && sa->sadb_sa_state != SADB_SASTATE_DYING) {
- msg = next;
+ && sa->sadb_sa_state != SADB_SASTATE_DYING)
continue;
- }
/*
* RFC2407 4.6.3.3 INITIAL-CONTACT is the message that
@@ -1401,39 +1348,18 @@ info_recv_initialcontact(iph1)
* racoon only deletes SA which is matched both the
* source address and the destination accress.
*/
-#ifdef ENABLE_NATT
- /*
- * XXX RFC 3947 says that whe MUST NOT use IP+port to find old SAs
- * from this peer !
- */
- if(iph1->natt_flags & NAT_DETECTED){
- if (CMPSADDR(iph1->local, src) == 0 &&
- CMPSADDR(iph1->remote, dst) == 0)
- ;
- else if (CMPSADDR(iph1->remote, src) == 0 &&
- CMPSADDR(iph1->local, dst) == 0)
- ;
- else {
- msg = next;
- continue;
- }
- } else
-#endif
- /* If there is no NAT-T, we don't have to check addr + port...
- * XXX what about a configuration with a remote peers which is not
- * NATed, but which NATs some other peers ?
- * Here, the INITIAl-CONTACT would also flush all those NATed peers !!
- */
- if (cmpsaddrwop(iph1->local, src) == 0 &&
- cmpsaddrwop(iph1->remote, dst) == 0)
- ;
- else if (cmpsaddrwop(iph1->remote, src) == 0 &&
- cmpsaddrwop(iph1->local, dst) == 0)
- ;
- else {
- msg = next;
+
+ /*
+ * Check that the IP and port match. But this is not optimal,
+ * since NAT-T can make the peer have multiple different
+ * ports. Correct thing to do is delete all entries with
+ * same identity. -TT
+ */
+ if ((cmpsaddr(iph1->local, src) != CMPSADDR_MATCH ||
+ cmpsaddr(iph1->remote, dst) != CMPSADDR_MATCH) &&
+ (cmpsaddr(iph1->local, dst) != CMPSADDR_MATCH ||
+ cmpsaddr(iph1->remote, src) != CMPSADDR_MATCH))
continue;
- }
/*
* Make sure this is an SATYPE that we manage.
@@ -1445,10 +1371,8 @@ info_recv_initialcontact(iph1)
msg->sadb_msg_satype)
break;
}
- if (i == pfkey_nsatypes) {
- msg = next;
+ if (i == pfkey_nsatypes)
continue;
- }
plog(LLV_INFO, LOCATION, NULL,
"purging spi=%u.\n", ntohl(sa->sadb_sa_spi));
@@ -1463,54 +1387,15 @@ info_recv_initialcontact(iph1)
*/
proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype);
iph2 = getph2bysaidx(src, dst, proto_id, sa->sadb_sa_spi);
- if (iph2) {
+ if (iph2 && iph2 != protectedph2) {
delete_spd(iph2, 0);
- unbindph12(iph2);
remph2(iph2);
delph2(iph2);
}
-
- msg = next;
}
vfree(buf);
-}
-
-void
-isakmp_check_notify(gen, iph1)
- struct isakmp_gen *gen; /* points to Notify payload */
- struct ph1handle *iph1;
-{
- struct isakmp_pl_n *notify = (struct isakmp_pl_n *)gen;
-
- plog(LLV_DEBUG, LOCATION, iph1->remote,
- "Notify Message received\n");
-
- switch (ntohs(notify->type)) {
- case ISAKMP_NTYPE_CONNECTED:
- case ISAKMP_NTYPE_RESPONDER_LIFETIME:
- case ISAKMP_NTYPE_REPLAY_STATUS:
- case ISAKMP_NTYPE_HEARTBEAT:
-#ifdef ENABLE_HYBRID
- case ISAKMP_NTYPE_UNITY_HEARTBEAT:
-#endif
- plog(LLV_WARNING, LOCATION, iph1->remote,
- "ignore %s notification.\n",
- s_isakmp_notify_msg(ntohs(notify->type)));
- break;
- case ISAKMP_NTYPE_INITIAL_CONTACT:
- plog(LLV_WARNING, LOCATION, iph1->remote,
- "ignore INITIAL-CONTACT notification, "
- "because it is only accepted after phase1.\n");
- break;
- default:
- isakmp_info_send_n1(iph1, ISAKMP_NTYPE_INVALID_PAYLOAD_TYPE, NULL);
- plog(LLV_ERROR, LOCATION, iph1->remote,
- "received unknown notification type %s.\n",
- s_isakmp_notify_msg(ntohs(notify->type)));
- }
-
- return;
+ return 0;
}
@@ -1567,17 +1452,16 @@ isakmp_info_recv_r_u_ack (iph1, ru, msgid)
struct isakmp_pl_ru *ru;
u_int32_t msgid;
{
+ u_int32_t seq;
plog(LLV_DEBUG, LOCATION, iph1->remote,
"DPD R-U-There-Ack received\n");
- /* XXX Maintain window of acceptable sequence numbers ?
- * => ru->data <= iph2->dpd_seq &&
- * ru->data >= iph2->dpd_seq - iph2->dpd_fails ? */
- if (ntohl(ru->data) != iph1->dpd_seq-1) {
+ seq = ntohl(ru->data);
+ if (seq <= iph1->dpd_last_ack || seq > iph1->dpd_seq) {
plog(LLV_ERROR, LOCATION, iph1->remote,
- "Wrong DPD sequence number (%d, %d expected).\n",
- ntohl(ru->data), iph1->dpd_seq-1);
+ "Wrong DPD sequence number (%d; last_ack=%d, seq=%d).\n",
+ seq, iph1->dpd_last_ack, iph1->dpd_seq);
return 0;
}
@@ -1589,12 +1473,8 @@ isakmp_info_recv_r_u_ack (iph1, ru, msgid)
}
iph1->dpd_fails = 0;
-
- /* Useless ??? */
- iph1->dpd_lastack = time(NULL);
-
- SCHED_KILL(iph1->dpd_r_u);
-
+ iph1->dpd_last_ack = seq;
+ sched_cancel(&iph1->dpd_r_u);
isakmp_sched_r_u(iph1, 0);
plog(LLV_DEBUG, LOCATION, NULL, "received an R-U-THERE-ACK\n");
@@ -1609,10 +1489,10 @@ isakmp_info_recv_r_u_ack (iph1, ru, msgid)
* send DPD R-U-THERE payload in Informational exchange.
*/
static void
-isakmp_info_send_r_u(arg)
- void *arg;
+isakmp_info_send_r_u(sc)
+ struct sched *sc;
{
- struct ph1handle *iph1 = arg;
+ struct ph1handle *iph1 = container_of(sc, struct ph1handle, dpd_r_u);
/* create R-U-THERE payload */
struct isakmp_pl_ru *ru;
@@ -1622,7 +1502,14 @@ isakmp_info_send_r_u(arg)
plog(LLV_DEBUG, LOCATION, iph1->remote, "DPD monitoring....\n");
- iph1->dpd_r_u=NULL;
+ if (iph1->status == PHASE1ST_EXPIRED) {
+ /* This can happen after removing tunnels from the
+ * config file and then reloading.
+ * Such iph1 have rmconf=NULL, so return before the if
+ * block below.
+ */
+ return;
+ }
if (iph1->dpd_fails >= iph1->rmconf->dpd_maxfails) {
@@ -1630,7 +1517,8 @@ isakmp_info_send_r_u(arg)
"DPD: remote (ISAKMP-SA spi=%s) seems to be dead.\n",
isakmp_pindex(&iph1->index, 0));
- EVT_PUSH(iph1->local, iph1->remote, EVTT_DPD_TIMEOUT, NULL);
+ script_hook(iph1, SCRIPT_PHASE1_DEAD);
+ evt_phase1(iph1, EVT_PHASE1_DPD_TIMEOUT, NULL);
purge_remote(iph1);
/* Do not reschedule here: phase1 is deleted,
@@ -1659,12 +1547,13 @@ isakmp_info_send_r_u(arg)
memcpy(ru->i_ck, iph1->index.i_ck, sizeof(cookie_t));
memcpy(ru->r_ck, iph1->index.r_ck, sizeof(cookie_t));
- if (iph1->dpd_seq == 0){
+ if (iph1->dpd_seq == 0) {
/* generate a random seq which is not too big */
- srand(time(NULL));
- iph1->dpd_seq = rand() & 0x0fff;
+ iph1->dpd_seq = iph1->dpd_last_ack = rand() & 0x0fff;
}
+ iph1->dpd_seq++;
+ iph1->dpd_fails++;
ru->data = htonl(iph1->dpd_seq);
error = isakmp_info_send_common(iph1, payload, ISAKMP_NPTYPE_N, 0);
@@ -1673,12 +1562,6 @@ isakmp_info_send_r_u(arg)
plog(LLV_DEBUG, LOCATION, iph1->remote,
"DPD R-U-There sent (%d)\n", error);
- /* will be decreased if ACK received... */
- iph1->dpd_fails++;
-
- /* XXX should be increased only when ACKed ? */
- iph1->dpd_seq++;
-
/* Reschedule the r_u_there with a short delay,
* will be deleted/rescheduled if ACK received before */
isakmp_sched_r_u(iph1, 1);
@@ -1703,11 +1586,11 @@ isakmp_sched_r_u(iph1, retry)
return 0;
if(retry)
- iph1->dpd_r_u = sched_new(iph1->rmconf->dpd_retry,
- isakmp_info_send_r_u, iph1);
+ sched_schedule(&iph1->dpd_r_u, iph1->rmconf->dpd_retry,
+ isakmp_info_send_r_u);
else
- iph1->dpd_r_u = sched_new(iph1->rmconf->dpd_interval,
- isakmp_info_send_r_u, iph1);
+ sched_schedule(&iph1->dpd_r_u, iph1->rmconf->dpd_interval,
+ isakmp_info_send_r_u);
return 0;
}
diff --git a/src/racoon/isakmp_inf.h b/src/racoon/isakmp_inf.h
index c7682d9..40cdc02 100644
--- a/src/racoon/isakmp_inf.h
+++ b/src/racoon/isakmp_inf.h
@@ -1,4 +1,4 @@
-/* $NetBSD: isakmp_inf.h,v 1.4 2006/09/09 16:22:09 manu Exp $ */
+/* $NetBSD: isakmp_inf.h,v 1.5 2008/07/14 05:40:13 tteras Exp $ */
/* Id: isakmp_inf.h,v 1.6 2005/05/07 14:15:59 manubsd Exp */
@@ -48,7 +48,8 @@ extern int isakmp_info_send_common __P((struct ph1handle *,
extern vchar_t * isakmp_add_pl_n __P((vchar_t *, u_int8_t **, int,
struct saproto *, vchar_t *));
-extern void isakmp_check_notify __P((struct isakmp_gen *, struct ph1handle *));
+extern int isakmp_log_notify __P((struct ph1handle *, struct isakmp_pl_n *, const char *exchange));
+extern int isakmp_info_recv_initialcontact __P((struct ph1handle *, struct ph2handle *));
#ifdef ENABLE_DPD
extern int isakmp_sched_r_u __P((struct ph1handle *, int));
diff --git a/src/racoon/isakmp_quick.c b/src/racoon/isakmp_quick.c
index 963438d..056e905 100644
--- a/src/racoon/isakmp_quick.c
+++ b/src/racoon/isakmp_quick.c
@@ -1,4 +1,4 @@
-/* $NetBSD: isakmp_quick.c,v 1.11.4.1 2007/08/01 11:52:21 vanhu Exp $ */
+/* $NetBSD: isakmp_quick.c,v 1.29 2011/03/14 17:18:13 tteras Exp $ */
/* Id: isakmp_quick.c,v 1.29 2006/08/22 18:17:17 manubsd Exp */
@@ -53,9 +53,6 @@
# include <time.h>
# endif
#endif
-#ifdef ENABLE_HYBRID
-#include <resolv.h>
-#endif
#include PATH_IPSEC_H
@@ -87,10 +84,47 @@
#include "admin.h"
#include "strnames.h"
+#ifdef ENABLE_HYBRID
+#include <resolv.h>
+#include "isakmp_xauth.h"
+#include "isakmp_cfg.h"
+#endif
+
+#ifdef ENABLE_NATT
+#include "nattraversal.h"
+#endif
+
/* quick mode */
static vchar_t *quick_ir1mx __P((struct ph2handle *, vchar_t *, vchar_t *));
static int get_sainfo_r __P((struct ph2handle *));
static int get_proposal_r __P((struct ph2handle *));
+static int ph2_recv_n __P((struct ph2handle *, struct isakmp_gen *));
+static void quick_timeover_stub __P((struct sched *));
+static void quick_timeover __P((struct ph2handle *));
+
+/* called from scheduler */
+static void
+quick_timeover_stub(p)
+ struct sched *p;
+{
+ quick_timeover(container_of(p, struct ph2handle, sce));
+}
+
+static void
+quick_timeover(iph2)
+ struct ph2handle *iph2;
+{
+ plog(LLV_ERROR, LOCATION, NULL,
+ "%s give up to get IPsec-SA due to time up to wait.\n",
+ saddrwop2str(iph2->dst));
+
+ /* If initiator side, send error to kernel by SADB_ACQUIRE. */
+ if (iph2->side == INITIATOR)
+ pk_sendeacquire(iph2);
+
+ remph2(iph2);
+ delph2(iph2);
+}
/* %%%
* Quick Mode
@@ -131,8 +165,8 @@ quick_i1prep(iph2, msg)
plog(LLV_DEBUG, LOCATION, NULL, "pfkey getspi sent.\n");
- iph2->sce = sched_new(lcconf->wait_ph2complete,
- pfkey_timeover_stub, iph2);
+ sched_schedule(&iph2->sce, lcconf->wait_ph2complete,
+ quick_timeover_stub);
error = 0;
@@ -142,7 +176,7 @@ end:
/*
* send to responder
- * HDR*, HASH(1), SA, Ni [, KE ] [, IDi2, IDr2 ]
+ * HDR*, HASH(1), SA, Ni [, KE ] [, IDi2, IDr2 ] [, NAT-OAi, NAT-OAr ]
*/
int
quick_i1send(iph2, msg)
@@ -155,9 +189,14 @@ quick_i1send(iph2, msg)
char *p;
int tlen;
int error = ISAKMP_INTERNAL_ERROR;
+ int natoa = ISAKMP_NPTYPE_NONE;
int pfsgroup, idci, idcr;
int np;
struct ipsecdoi_id_b *id, *id_p;
+#ifdef ENABLE_NATT
+ vchar_t *nat_oai = NULL;
+ vchar_t *nat_oar = NULL;
+#endif
/* validity check */
if (msg != NULL) {
@@ -217,17 +256,49 @@ quick_i1send(iph2, msg)
* - no MIP6 or proxy
* - id payload suggests to encrypt all the traffic (no specific
* protocol type)
+ * - SA endpoints and IKE addresses for the nego are the same
+ * (iph2->src/dst)
*/
id = (struct ipsecdoi_id_b *)iph2->id->v;
id_p = (struct ipsecdoi_id_b *)iph2->id_p->v;
- if (id->proto_id == 0
- && id_p->proto_id == 0
- && iph2->ph1->rmconf->support_proxy == 0
- && ipsecdoi_transportmode(iph2->proposal)) {
+ if (id->proto_id == 0 &&
+ id_p->proto_id == 0 &&
+ iph2->ph1->rmconf->support_proxy == 0 &&
+ iph2->sa_src == NULL && iph2->sa_dst == NULL &&
+ ipsecdoi_transportmode(iph2->proposal)) {
idci = idcr = 0;
} else
idci = idcr = 1;
+#ifdef ENABLE_NATT
+ /*
+ * RFC3947 5.2. if we propose UDP-Encapsulated-Transport
+ * we should send NAT-OA
+ */
+ if (ipsecdoi_transportmode(iph2->proposal)
+ && (iph2->ph1->natt_flags & NAT_DETECTED)) {
+ natoa = iph2->ph1->natt_options->payload_nat_oa;
+
+ nat_oai = ipsecdoi_sockaddr2id(iph2->src,
+ IPSECDOI_PREFIX_HOST, IPSEC_ULPROTO_ANY);
+ nat_oar = ipsecdoi_sockaddr2id(iph2->dst,
+ IPSECDOI_PREFIX_HOST, IPSEC_ULPROTO_ANY);
+
+ if (nat_oai == NULL || nat_oar == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "failed to generate NAT-OA payload.\n");
+ goto end;
+ }
+
+ plog(LLV_DEBUG, LOCATION, NULL, "NAT-OAi:\n");
+ plogdump(LLV_DEBUG, nat_oai->v, nat_oai->l);
+ plog(LLV_DEBUG, LOCATION, NULL, "NAT-OAr:\n");
+ plogdump(LLV_DEBUG, nat_oar->v, nat_oar->l);
+ } else {
+ natoa = ISAKMP_NPTYPE_NONE;
+ }
+#endif
+
/* create SA;NONCE payload, and KE if need, and IDii, IDir. */
tlen = + sizeof(*gen) + iph2->sa->l
+ sizeof(*gen) + iph2->nonce->l;
@@ -237,6 +308,10 @@ quick_i1send(iph2, msg)
tlen += sizeof(*gen) + iph2->id->l;
if (idcr)
tlen += sizeof(*gen) + iph2->id_p->l;
+#ifdef ENABLE_NATT
+ if (natoa != ISAKMP_NPTYPE_NONE)
+ tlen += 2 * sizeof(*gen) + nat_oai->l + nat_oar->l;
+#endif
body = vmalloc(tlen);
if (body == NULL) {
@@ -256,22 +331,30 @@ quick_i1send(iph2, msg)
else if (idci || idcr)
np = ISAKMP_NPTYPE_ID;
else
- np = ISAKMP_NPTYPE_NONE;
+ np = natoa;
p = set_isakmp_payload(p, iph2->nonce, np);
/* add KE payload if need. */
- np = (idci || idcr) ? ISAKMP_NPTYPE_ID : ISAKMP_NPTYPE_NONE;
+ np = (idci || idcr) ? ISAKMP_NPTYPE_ID : natoa;
if (pfsgroup)
p = set_isakmp_payload(p, iph2->dhpub, np);
/* IDci */
- np = (idcr) ? ISAKMP_NPTYPE_ID : ISAKMP_NPTYPE_NONE;
+ np = (idcr) ? ISAKMP_NPTYPE_ID : natoa;
if (idci)
p = set_isakmp_payload(p, iph2->id, np);
/* IDcr */
if (idcr)
- p = set_isakmp_payload(p, iph2->id_p, ISAKMP_NPTYPE_NONE);
+ p = set_isakmp_payload(p, iph2->id_p, natoa);
+
+#ifdef ENABLE_NATT
+ /* NAT-OA */
+ if (natoa != ISAKMP_NPTYPE_NONE) {
+ p = set_isakmp_payload(p, nat_oai, natoa);
+ p = set_isakmp_payload(p, nat_oar, ISAKMP_NPTYPE_NONE);
+ }
+#endif
/* generate HASH(1) */
hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, body);
@@ -284,8 +367,7 @@ quick_i1send(iph2, msg)
goto end;
/* send the packet, add to the schedule to resend */
- iph2->retry_counter = iph2->ph1->rmconf->retry_counter;
- if (isakmp_ph2resend(iph2) == -1)
+ if (isakmp_ph2send(iph2) == -1)
goto end;
/* change status of isakmp status entry */
@@ -298,13 +380,19 @@ end:
vfree(body);
if (hash != NULL)
vfree(hash);
+#ifdef ENABLE_NATT
+ if (nat_oai != NULL)
+ vfree(nat_oai);
+ if (nat_oar != NULL)
+ vfree(nat_oar);
+#endif
return error;
}
/*
* receive from responder
- * HDR*, HASH(2), SA, Nr [, KE ] [, IDi2, IDr2 ]
+ * HDR*, HASH(2), SA, Nr [, KE ] [, IDi2, IDr2 ] [, NAT-OAi, NAT-OAr ]
*/
int
quick_i2recv(iph2, msg0)
@@ -314,10 +402,11 @@ quick_i2recv(iph2, msg0)
vchar_t *msg = NULL;
vchar_t *hbuf = NULL; /* for hash computing. */
vchar_t *pbuf = NULL; /* for payload parsing */
+ vchar_t *idci = NULL;
+ vchar_t *idcr = NULL;
struct isakmp_parse_t *pa;
struct isakmp *isakmp = (struct isakmp *)msg0->v;
struct isakmp_pl_hash *hash = NULL;
- int f_id;
char *p;
int tlen;
int error = ISAKMP_INTERNAL_ERROR;
@@ -391,7 +480,6 @@ quick_i2recv(iph2, msg0)
* copy non-HASH payloads into hbuf, so that we can validate HASH.
*/
iph2->sa_ret = NULL;
- f_id = 0; /* flag to use checking ID */
tlen = 0; /* count payload length except of HASH payload. */
for (; pa->type; pa++) {
@@ -407,54 +495,84 @@ quick_i2recv(iph2, msg0)
"isn't supported.\n");
break;
}
- if (isakmp_p2ph(&iph2->sa_ret, pa->ptr) < 0)
+ if (isakmp_p2ph(&iph2->sa_ret, pa->ptr) < 0) {
+ plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
+ "duplicate ISAKMP_NPTYPE_SA.\n");
goto end;
+ }
break;
case ISAKMP_NPTYPE_NONCE:
- if (isakmp_p2ph(&iph2->nonce_p, pa->ptr) < 0)
+ if (isakmp_p2ph(&iph2->nonce_p, pa->ptr) < 0) {
+ plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
+ "duplicate ISAKMP_NPTYPE_NONCE.\n");
goto end;
+ }
break;
case ISAKMP_NPTYPE_KE:
- if (isakmp_p2ph(&iph2->dhpub_p, pa->ptr) < 0)
+ if (isakmp_p2ph(&iph2->dhpub_p, pa->ptr) < 0) {
+ plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
+ "duplicate ISAKMP_NPTYPE_KE.\n");
goto end;
+ }
break;
case ISAKMP_NPTYPE_ID:
- {
- vchar_t *vp;
-
- /* check ID value */
- if (f_id == 0) {
- /* for IDci */
- f_id = 1;
- vp = iph2->id;
+ if (idci == NULL) {
+ if (isakmp_p2ph(&idci, pa->ptr) < 0)
+ goto end;
+ } else if (idcr == NULL) {
+ if (isakmp_p2ph(&idcr, pa->ptr) < 0)
+ goto end;
} else {
- /* for IDcr */
- vp = iph2->id_p;
- }
-
-#ifndef ANDROID_PATCHED
- if (memcmp(vp->v, (caddr_t)pa->ptr + sizeof(struct isakmp_gen), vp->l)) {
-
- plog(LLV_ERROR, LOCATION, NULL,
- "mismatched ID was returned.\n");
- error = ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED;
+ plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
+ "too many ISAKMP_NPTYPE_ID payloads.\n");
goto end;
}
-#endif
- }
break;
case ISAKMP_NPTYPE_N:
- isakmp_check_notify(pa->ptr, iph2->ph1);
+ ph2_recv_n(iph2, pa->ptr);
break;
#ifdef ENABLE_NATT
case ISAKMP_NPTYPE_NATOA_DRAFT:
case ISAKMP_NPTYPE_NATOA_RFC:
- /* Ignore original source/destination messages */
+ {
+ struct sockaddr_storage addr;
+ struct sockaddr *daddr;
+ u_int8_t prefix;
+ u_int16_t ul_proto;
+ vchar_t *vp = NULL;
+
+ if (isakmp_p2ph(&vp, pa->ptr) < 0)
+ goto end;
+
+ error = ipsecdoi_id2sockaddr(vp,
+ (struct sockaddr *) &addr,
+ &prefix, &ul_proto);
+
+ vfree(vp);
+
+ if (error)
+ goto end;
+
+ daddr = dupsaddr((struct sockaddr *) &addr);
+ if (daddr == NULL)
+ goto end;
+
+ if (iph2->natoa_src == NULL)
+ iph2->natoa_src = daddr;
+ else if (iph2->natoa_dst == NULL)
+ iph2->natoa_dst = daddr;
+ else {
+ racoon_free(daddr);
+ plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
+ "too many ISAKMP_NPTYPE_NATOA payloads.\n");
+ goto end;
+ }
+ }
break;
#endif
@@ -480,6 +598,118 @@ quick_i2recv(iph2, msg0)
goto end;
}
+#ifdef ANDROID_PATCHED
+ if (idcr != NULL) {
+ struct ipsecdoi_id_b *id_b = idcr->v;
+ if (id_b->type != IPSECDOI_ID_IPV4_ADDR &&
+ id_b->type != IPSECDOI_ID_IPV4_ADDR_SUBNET &&
+ id_b->type != IPSECDOI_ID_IPV6_ADDR &&
+ id_b->type != IPSECDOI_ID_IPV6_ADDR_SUBNET) {
+ vfree(idcr);
+ idcr = NULL;
+ }
+ }
+#endif
+
+ /* identity check */
+ if (idci != NULL) {
+ struct sockaddr_storage proposed_addr, got_addr;
+ u_int8_t proposed_prefix, got_prefix;
+ u_int16_t proposed_ulproto, got_ulproto;
+
+ error = ipsecdoi_id2sockaddr(iph2->id,
+ (struct sockaddr *) &proposed_addr,
+ &proposed_prefix, &proposed_ulproto);
+ if (error)
+ goto end;
+
+ error = ipsecdoi_id2sockaddr(idci,
+ (struct sockaddr *) &got_addr,
+ &got_prefix, &got_ulproto);
+ if (error)
+ goto end;
+
+ if (proposed_prefix != got_prefix
+ || proposed_ulproto != got_ulproto) {
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "IDci prefix/ulproto does not match proposal.\n");
+ error = ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED;
+ goto end;
+ }
+#ifdef ENABLE_NATT
+ set_port(iph2->natoa_src,
+ extract_port((struct sockaddr *) &proposed_addr));
+#endif
+
+ if (cmpsaddr((struct sockaddr *) &proposed_addr,
+ (struct sockaddr *) &got_addr) == CMPSADDR_MATCH) {
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "IDci matches proposal.\n");
+#ifdef ENABLE_NATT
+ } else if (iph2->natoa_src != NULL
+ && cmpsaddr(iph2->natoa_src,
+ (struct sockaddr *) &got_addr) == 0) {
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "IDci matches NAT-OAi.\n");
+#endif
+#ifndef ANDROID_PATCHED
+ } else {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "mismatched IDci was returned.\n");
+ error = ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED;
+ goto end;
+#endif
+ }
+ }
+ if (idcr != NULL) {
+ struct sockaddr_storage proposed_addr, got_addr;
+ u_int8_t proposed_prefix, got_prefix;
+ u_int16_t proposed_ulproto, got_ulproto;
+
+ error = ipsecdoi_id2sockaddr(iph2->id_p,
+ (struct sockaddr *) &proposed_addr,
+ &proposed_prefix, &proposed_ulproto);
+ if (error)
+ goto end;
+
+ error = ipsecdoi_id2sockaddr(idcr,
+ (struct sockaddr *) &got_addr,
+ &got_prefix, &got_ulproto);
+ if (error)
+ goto end;
+
+ if (proposed_prefix != got_prefix
+ || proposed_ulproto != got_ulproto) {
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "IDcr prefix/ulproto does not match proposal.\n");
+ error = ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED;
+ goto end;
+ }
+
+#ifdef ENABLE_NATT
+ set_port(iph2->natoa_dst,
+ extract_port((struct sockaddr *) &proposed_addr));
+#endif
+
+ if (cmpsaddr((struct sockaddr *) &proposed_addr,
+ (struct sockaddr *) &got_addr) == CMPSADDR_MATCH) {
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "IDcr matches proposal.\n");
+#ifdef ENABLE_NATT
+ } else if (iph2->natoa_dst != NULL
+ && cmpsaddr(iph2->natoa_dst,
+ (struct sockaddr *) &got_addr) == CMPSADDR_MATCH) {
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "IDcr matches NAT-OAr.\n");
+#endif
+ } else {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "mismatched IDcr was returned.\n");
+ error = ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED;
+ goto end;
+ }
+ }
+
/* Fixed buffer for calculating HASH */
memcpy(hbuf->v, iph2->nonce->v, iph2->nonce->l);
plog(LLV_DEBUG, LOCATION, NULL,
@@ -516,6 +746,8 @@ quick_i2recv(iph2, msg0)
/* validity check SA payload sent from responder */
if (ipsecdoi_checkph2proposal(iph2) < 0) {
+ plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
+ "proposal check failed.\n");
error = ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN;
goto end;
}
@@ -532,6 +764,10 @@ end:
vfree(pbuf);
if (msg)
vfree(msg);
+ if (idci)
+ vfree(idci);
+ if (idcr)
+ vfree(idcr);
if (error) {
VPTRINIT(iph2->sa_ret);
@@ -539,6 +775,16 @@ end:
VPTRINIT(iph2->dhpub_p);
VPTRINIT(iph2->id);
VPTRINIT(iph2->id_p);
+#ifdef ENABLE_NATT
+ if (iph2->natoa_src) {
+ racoon_free(iph2->natoa_src);
+ iph2->natoa_src = NULL;
+ }
+ if (iph2->natoa_dst) {
+ racoon_free(iph2->natoa_dst);
+ iph2->natoa_dst = NULL;
+ }
+#endif
}
return error;
@@ -619,8 +865,7 @@ quick_i2send(iph2, msg0)
/* if there is commit bit, need resending */
if (ISSET(iph2->flags, ISAKMP_FLAG_C)) {
/* send the packet, add to the schedule to resend */
- iph2->retry_counter = iph2->ph1->rmconf->retry_counter;
- if (isakmp_ph2resend(iph2) == -1)
+ if (isakmp_ph2send(iph2) == -1)
goto end;
} else {
/* send the packet */
@@ -735,7 +980,7 @@ quick_i3recv(iph2, msg0)
"Ignoring multiples notifications\n");
break;
}
- isakmp_check_notify(pa->ptr, iph2->ph1);
+ ph2_recv_n(iph2, pa->ptr);
notify = vmalloc(pa->len);
if (notify == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
@@ -828,7 +1073,7 @@ end:
/*
* receive from initiator
- * HDR*, HASH(1), SA, Ni [, KE ] [, IDi2, IDr2 ]
+ * HDR*, HASH(1), SA, Ni [, KE ] [, IDi2, IDr2 ] [, NAT-OAi, NAT-OAr ]
*/
int
quick_r1recv(iph2, msg0)
@@ -862,8 +1107,11 @@ quick_r1recv(iph2, msg0)
}
/* decrypt packet */
msg = oakley_do_decrypt(iph2->ph1, msg0, iph2->ivm->iv, iph2->ivm->ive);
- if (msg == NULL)
+ if (msg == NULL) {
+ plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
+ "Packet decryption failed.\n");
goto end;
+ }
/* create buffer for using to validate HASH(1) */
/*
@@ -947,18 +1195,27 @@ quick_r1recv(iph2, msg0)
"Multi SAs isn't supported.\n");
goto end;
}
- if (isakmp_p2ph(&iph2->sa, pa->ptr) < 0)
+ if (isakmp_p2ph(&iph2->sa, pa->ptr) < 0) {
+ plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
+ "duplicate ISAKMP_NPTYPE_SA.\n");
goto end;
+ }
break;
case ISAKMP_NPTYPE_NONCE:
- if (isakmp_p2ph(&iph2->nonce_p, pa->ptr) < 0)
+ if (isakmp_p2ph(&iph2->nonce_p, pa->ptr) < 0) {
+ plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
+ "duplicate ISAKMP_NPTYPE_NONCE.\n");
goto end;
+ }
break;
case ISAKMP_NPTYPE_KE:
- if (isakmp_p2ph(&iph2->dhpub_p, pa->ptr) < 0)
+ if (isakmp_p2ph(&iph2->dhpub_p, pa->ptr) < 0) {
+ plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
+ "duplicate ISAKMP_NPTYPE_KE.\n");
goto end;
+ }
break;
case ISAKMP_NPTYPE_ID:
@@ -991,13 +1248,47 @@ quick_r1recv(iph2, msg0)
break;
case ISAKMP_NPTYPE_N:
- isakmp_check_notify(pa->ptr, iph2->ph1);
+ ph2_recv_n(iph2, pa->ptr);
break;
#ifdef ENABLE_NATT
case ISAKMP_NPTYPE_NATOA_DRAFT:
case ISAKMP_NPTYPE_NATOA_RFC:
- /* Ignore original source/destination messages */
+ {
+ struct sockaddr_storage addr;
+ struct sockaddr *daddr;
+ u_int8_t prefix;
+ u_int16_t ul_proto;
+ vchar_t *vp = NULL;
+
+ if (isakmp_p2ph(&vp, pa->ptr) < 0)
+ goto end;
+
+ error = ipsecdoi_id2sockaddr(vp,
+ (struct sockaddr *) &addr,
+ &prefix, &ul_proto);
+
+ vfree(vp);
+
+ if (error)
+ goto end;
+
+ daddr = dupsaddr((struct sockaddr *) &addr);
+ if (daddr == NULL)
+ goto end;
+
+ if (iph2->natoa_dst == NULL)
+ iph2->natoa_dst = daddr;
+ else if (iph2->natoa_src == NULL)
+ iph2->natoa_src = daddr;
+ else {
+ racoon_free(daddr);
+ plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
+ "received too many NAT-OA payloads.\n");
+ error = ISAKMP_NTYPE_PAYLOAD_MALFORMED;
+ goto end;
+ }
+ }
break;
#endif
@@ -1080,12 +1371,15 @@ quick_r1recv(iph2, msg0)
plog(LLV_ERROR, LOCATION, NULL,
"failed to generate a proposal template "
"from client's proposal.\n");
- return ISAKMP_INTERNAL_ERROR;
+ error = ISAKMP_INTERNAL_ERROR;
+ goto end;
}
/*FALLTHROUGH*/
case 0:
/* select single proposal or reject it. */
if (ipsecdoi_selectph2proposal(iph2) < 0) {
+ plog(LLV_ERROR, LOCATION, iph2->ph1->remote,
+ "no proposal chosen.\n");
error = ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN;
goto end;
}
@@ -1135,6 +1429,16 @@ end:
VPTRINIT(iph2->dhpub_p);
VPTRINIT(iph2->id);
VPTRINIT(iph2->id_p);
+#ifdef ENABLE_NATT
+ if (iph2->natoa_src) {
+ racoon_free(iph2->natoa_src);
+ iph2->natoa_src = NULL;
+ }
+ if (iph2->natoa_dst) {
+ racoon_free(iph2->natoa_dst);
+ iph2->natoa_dst = NULL;
+ }
+#endif
}
return error;
@@ -1165,8 +1469,8 @@ quick_r1prep(iph2, msg)
plog(LLV_DEBUG, LOCATION, NULL, "pfkey getspi sent.\n");
- iph2->sce = sched_new(lcconf->wait_ph2complete,
- pfkey_timeover_stub, iph2);
+ sched_schedule(&iph2->sce, lcconf->wait_ph2complete,
+ quick_timeover_stub);
error = 0;
@@ -1176,7 +1480,7 @@ end:
/*
* send to initiator
- * HDR*, HASH(2), SA, Nr [, KE ] [, IDi2, IDr2 ]
+ * HDR*, HASH(2), SA, Nr [, KE ] [, IDi2, IDr2 ] [, NAT-OAi, NAT-OAr ]
*/
int
quick_r2send(iph2, msg)
@@ -1189,8 +1493,13 @@ quick_r2send(iph2, msg)
char *p;
int tlen;
int error = ISAKMP_INTERNAL_ERROR;
+ int natoa = ISAKMP_NPTYPE_NONE;
int pfsgroup;
u_int8_t *np_p = NULL;
+#ifdef ENABLE_NATT
+ vchar_t *nat_oai = NULL;
+ vchar_t *nat_oar = NULL;
+#endif
/* validity check */
if (msg != NULL) {
@@ -1231,6 +1540,33 @@ quick_r2send(iph2, msg)
}
}
+#ifdef ENABLE_NATT
+ /*
+ * RFC3947 5.2. if we chose UDP-Encapsulated-Transport
+ * we should send NAT-OA
+ */
+ if (ipsecdoi_transportmode(iph2->proposal)
+ && (iph2->ph1->natt_flags & NAT_DETECTED)) {
+ natoa = iph2->ph1->natt_options->payload_nat_oa;
+
+ nat_oai = ipsecdoi_sockaddr2id(iph2->dst,
+ IPSECDOI_PREFIX_HOST, IPSEC_ULPROTO_ANY);
+ nat_oar = ipsecdoi_sockaddr2id(iph2->src,
+ IPSECDOI_PREFIX_HOST, IPSEC_ULPROTO_ANY);
+
+ if (nat_oai == NULL || nat_oar == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "failed to generate NAT-OA payload.\n");
+ goto end;
+ }
+
+ plog(LLV_DEBUG, LOCATION, NULL, "NAT-OAi:\n");
+ plogdump(LLV_DEBUG, nat_oai->v, nat_oai->l);
+ plog(LLV_DEBUG, LOCATION, NULL, "NAT-OAr:\n");
+ plogdump(LLV_DEBUG, nat_oar->v, nat_oar->l);
+ }
+#endif
+
/* create SA;NONCE payload, and KE and ID if need */
tlen = sizeof(*gen) + iph2->sa_ret->l
+ sizeof(*gen) + iph2->nonce->l;
@@ -1239,6 +1575,10 @@ quick_r2send(iph2, msg)
if (iph2->id_p != NULL)
tlen += (sizeof(*gen) + iph2->id_p->l
+ sizeof(*gen) + iph2->id->l);
+#ifdef ENABLE_NATT
+ if (natoa != ISAKMP_NPTYPE_NONE)
+ tlen += 2 * sizeof(*gen) + nat_oai->l + nat_oar->l;
+#endif
body = vmalloc(tlen);
if (body == NULL) {
@@ -1258,14 +1598,14 @@ quick_r2send(iph2, msg)
? ISAKMP_NPTYPE_KE
: (iph2->id_p != NULL
? ISAKMP_NPTYPE_ID
- : ISAKMP_NPTYPE_NONE));
+ : natoa));
/* add KE payload if need. */
if (iph2->dhpub_p != NULL && pfsgroup != 0) {
np_p = &((struct isakmp_gen *)p)->np; /* XXX */
p = set_isakmp_payload(p, iph2->dhpub,
(iph2->id_p == NULL)
- ? ISAKMP_NPTYPE_NONE
+ ? natoa
: ISAKMP_NPTYPE_ID);
}
@@ -1275,9 +1615,17 @@ quick_r2send(iph2, msg)
p = set_isakmp_payload(p, iph2->id_p, ISAKMP_NPTYPE_ID);
/* IDcr */
np_p = &((struct isakmp_gen *)p)->np; /* XXX */
- p = set_isakmp_payload(p, iph2->id, ISAKMP_NPTYPE_NONE);
+ p = set_isakmp_payload(p, iph2->id, natoa);
}
+#ifdef ENABLE_NATT
+ /* NAT-OA */
+ if (natoa != ISAKMP_NPTYPE_NONE) {
+ p = set_isakmp_payload(p, nat_oai, natoa);
+ p = set_isakmp_payload(p, nat_oar, ISAKMP_NPTYPE_NONE);
+ }
+#endif
+
/* add a RESPONDER-LIFETIME notify payload if needed */
{
vchar_t *data = NULL;
@@ -1350,8 +1698,7 @@ quick_r2send(iph2, msg)
goto end;
/* send the packet, add to the schedule to resend */
- iph2->retry_counter = iph2->ph1->rmconf->retry_counter;
- if (isakmp_ph2resend(iph2) == -1)
+ if (isakmp_ph2send(iph2) == -1)
goto end;
/* the sending message is added to the received-list. */
@@ -1371,6 +1718,12 @@ end:
vfree(body);
if (hash != NULL)
vfree(hash);
+#ifdef ENABLE_NATT
+ if (nat_oai != NULL)
+ vfree(nat_oai);
+ if (nat_oar != NULL)
+ vfree(nat_oar);
+#endif
return error;
}
@@ -1378,6 +1731,7 @@ end:
/*
* receive from initiator
* HDR*, HASH(3)
+
*/
int
quick_r3recv(iph2, msg0)
@@ -1421,7 +1775,7 @@ quick_r3recv(iph2, msg0)
hash = (struct isakmp_pl_hash *)pa->ptr;
break;
case ISAKMP_NPTYPE_N:
- isakmp_check_notify(pa->ptr, iph2->ph1);
+ ph2_recv_n(iph2, pa->ptr);
break;
default:
/* don't send information, see ident_r1recv() */
@@ -1802,25 +2156,11 @@ static int
get_sainfo_r(iph2)
struct ph2handle *iph2;
{
- vchar_t *idsrc = NULL, *iddst = NULL;
- int prefixlen;
+ vchar_t *idsrc = NULL, *iddst = NULL, *client = NULL;
int error = ISAKMP_INTERNAL_ERROR;
- int remoteid = 0;
if (iph2->id == NULL) {
- switch (iph2->src->sa_family) {
- case AF_INET:
- prefixlen = sizeof(struct in_addr) << 3;
- break;
- case AF_INET6:
- prefixlen = sizeof(struct in6_addr) << 3;
- break;
- default:
- plog(LLV_ERROR, LOCATION, NULL,
- "invalid family: %d\n", iph2->src->sa_family);
- goto end;
- }
- idsrc = ipsecdoi_sockaddr2id(iph2->src, prefixlen,
+ idsrc = ipsecdoi_sockaddr2id(iph2->src, IPSECDOI_PREFIX_HOST,
IPSEC_ULPROTO_ANY);
} else {
idsrc = vdup(iph2->id);
@@ -1832,19 +2172,7 @@ get_sainfo_r(iph2)
}
if (iph2->id_p == NULL) {
- switch (iph2->dst->sa_family) {
- case AF_INET:
- prefixlen = sizeof(struct in_addr) << 3;
- break;
- case AF_INET6:
- prefixlen = sizeof(struct in6_addr) << 3;
- break;
- default:
- plog(LLV_ERROR, LOCATION, NULL,
- "invalid family: %d\n", iph2->dst->sa_family);
- goto end;
- }
- iddst = ipsecdoi_sockaddr2id(iph2->dst, prefixlen,
+ iddst = ipsecdoi_sockaddr2id(iph2->dst, IPSECDOI_PREFIX_HOST,
IPSEC_ULPROTO_ANY);
} else {
iddst = vdup(iph2->id_p);
@@ -1855,19 +2183,34 @@ get_sainfo_r(iph2)
goto end;
}
- {
- struct remoteconf *conf;
- conf = getrmconf(iph2->dst);
- if (conf != NULL)
- remoteid=conf->ph1id;
- else{
- plog(LLV_DEBUG, LOCATION, NULL, "Warning: no valid rmconf !\n");
- remoteid=0;
+#ifdef ENABLE_HYBRID
+
+ /* clientaddr check : obtain modecfg address */
+ if (iph2->ph1->mode_cfg != NULL) {
+ if ((iph2->ph1->mode_cfg->flags & ISAKMP_CFG_ADDR4_EXTERN) ||
+ (iph2->ph1->mode_cfg->flags & ISAKMP_CFG_ADDR4_LOCAL)){
+ struct sockaddr saddr;
+ saddr.sa_family = AF_INET;
+#ifndef __linux__
+ saddr.sa_len = sizeof(struct sockaddr_in);
+#endif
+ ((struct sockaddr_in *)&saddr)->sin_port = IPSEC_PORT_ANY;
+ memcpy(&((struct sockaddr_in *)&saddr)->sin_addr,
+ &iph2->ph1->mode_cfg->addr4, sizeof(struct in_addr));
+ client = ipsecdoi_sockaddr2id(&saddr, 32, IPSEC_ULPROTO_ANY);
}
-
}
- iph2->sainfo = getsainfo(idsrc, iddst, iph2->ph1->id_p, remoteid);
+ /* clientaddr check, fallback to peer address */
+ if (client == NULL)
+ {
+ client = ipsecdoi_sockaddr2id(iph2->dst, IPSECDOI_PREFIX_HOST,
+ IPSEC_ULPROTO_ANY);
+ }
+#endif
+
+ /* obtain a matching sainfo section */
+ iph2->sainfo = getsainfo(idsrc, iddst, iph2->ph1->id_p, client, iph2->ph1->rmconf->ph1id);
if (iph2->sainfo == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
"failed to get sainfo.\n");
@@ -1890,6 +2233,8 @@ end:
vfree(idsrc);
if (iddst)
vfree(iddst);
+ if (client)
+ vfree(client);
return error;
}
@@ -1921,8 +2266,8 @@ get_proposal_r(iph2)
return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
}
- /* make sure if id[src,dst] is null. */
- if (iph2->src_id || iph2->dst_id) {
+ /* make sure if sa_[src, dst] are null. */
+ if (iph2->sa_src || iph2->sa_dst) {
plog(LLV_ERROR, LOCATION, NULL,
"Why do ID[src,dst] exist already.\n");
return ISAKMP_INTERNAL_ERROR;
@@ -2026,29 +2371,45 @@ get_proposal_r(iph2)
}
#endif
- /* make id[src,dst] if both ID types are IP address and same */
- if (_XIDT(iph2->id_p) == idi2type
- && spidx.dst.ss_family == spidx.src.ss_family) {
- iph2->src_id = dupsaddr((struct sockaddr *)&spidx.dst);
- if (iph2->src_id == NULL) {
+ /* Before setting iph2->[sa_src, sa_dst] with the addresses
+ * provided in ID payloads, we check:
+ * - they are both addresses of same family
+ * - sainfo has not been selected only based on ID payload
+ * information but also based on specific Phase 1
+ * credentials (iph2->sainfo->id_i is defined), i.e.
+ * local configuration _explicitly_ expect that user
+ * (e.g. from asn1dn "C=FR, ...") with those IDs) */
+ if (_XIDT(iph2->id_p) == idi2type &&
+ spidx.dst.ss_family == spidx.src.ss_family &&
+ iph2->sainfo && iph2->sainfo->id_i) {
+
+ iph2->sa_src = dupsaddr((struct sockaddr *)&spidx.dst);
+ if (iph2->sa_src == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
"buffer allocation failed.\n");
return ISAKMP_INTERNAL_ERROR;
}
- iph2->dst_id = dupsaddr((struct sockaddr *)&spidx.src);
- if (iph2->dst_id == NULL) {
+
+ iph2->sa_dst = dupsaddr((struct sockaddr *)&spidx.src);
+ if (iph2->sa_dst == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
"buffer allocation failed.\n");
return ISAKMP_INTERNAL_ERROR;
}
+ } else {
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "Either family (%d - %d), types (%d - %d) of ID "
+ "from initiator differ or matching sainfo "
+ "has no id_i defined for the peer. Not filling "
+ "iph2->sa_src and iph2->sa_dst.\n",
+ spidx.src.ss_family, spidx.dst.ss_family,
+ _XIDT(iph2->id_p),idi2type);
}
-
} else {
plog(LLV_DEBUG, LOCATION, NULL,
- "get a source address of SP index "
- "from phase1 address "
- "due to no ID payloads found "
- "OR because ID type is not address.\n");
+ "get a source address of SP index from Phase 1"
+ "addresses due to no ID payloads found"
+ "OR because ID type is not address.\n");
/* see above comment. */
memcpy(&spidx.src, iph2->dst, sysdep_sa_len(iph2->dst));
@@ -2070,7 +2431,7 @@ get_proposal_r(iph2)
#undef _XIDT
plog(LLV_DEBUG, LOCATION, NULL,
- "get a src address from ID payload "
+ "get src address from ID payload "
"%s prefixlen=%u ul_proto=%u\n",
saddr2str((struct sockaddr *)&spidx.src),
spidx.prefs, spidx.ul_proto);
@@ -2184,6 +2545,76 @@ get_proposal_r(iph2)
}
#endif /* HAVE_SECCTX */
+ iph2->spid = sp_in->id;
+
+ return 0;
+}
+
+/*
+ * handle a notification payload inside phase2 exchange.
+ * phase2 is always encrypted, so it does not need to be checked
+ * for explicitely.
+ */
+static int
+ph2_recv_n(iph2, gen)
+ struct ph2handle *iph2;
+ struct isakmp_gen *gen;
+{
+ struct ph1handle *iph1 = iph2->ph1;
+ struct isakmp_pl_n *notify = (struct isakmp_pl_n *) gen;
+ u_int type;
+ int check_level;
+
+ type = ntohs(notify->type);
+ switch (type) {
+ case ISAKMP_NTYPE_CONNECTED:
+ break;
+ case ISAKMP_NTYPE_INITIAL_CONTACT:
+ return isakmp_info_recv_initialcontact(iph1, iph2);
+ case ISAKMP_NTYPE_RESPONDER_LIFETIME:
+ ipsecdoi_parse_responder_lifetime(notify,
+ &iph2->lifetime_secs, &iph2->lifetime_kb);
+
+ if (iph1 != NULL && iph1->rmconf != NULL) {
+ check_level = iph1->rmconf->pcheck_level;
+ } else {
+ if (iph1 != NULL)
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "No phase1 rmconf found !\n");
+ else
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "No phase1 found !\n");
+ check_level = PROP_CHECK_EXACT;
+ }
+
+ switch (check_level) {
+ case PROP_CHECK_OBEY:
+ break;
+ case PROP_CHECK_STRICT:
+ case PROP_CHECK_CLAIM:
+ if (iph2->sainfo == NULL
+ || iph2->sainfo->lifetime <= iph2->lifetime_secs) {
+ plog(LLV_WARNING, LOCATION, NULL,
+ "RESPONDER-LIFETIME: lifetime mismatch\n");
+ iph2->lifetime_secs = 0;
+ }
+ break;
+ case PROP_CHECK_EXACT:
+ if (iph2->sainfo == NULL
+ || iph2->sainfo->lifetime != iph2->lifetime_secs) {
+ plog(LLV_WARNING, LOCATION, NULL,
+ "RESPONDER-LIFETIME: lifetime mismatch\n");
+ iph2->lifetime_secs = 0;
+ }
+ break;
+ }
+ break;
+ default:
+ isakmp_log_notify(iph2->ph1, notify, "phase2 exchange");
+ isakmp_info_send_n2(iph2, ISAKMP_NTYPE_INVALID_PAYLOAD_TYPE,
+ NULL);
+ break;
+ }
return 0;
}
diff --git a/src/racoon/isakmp_unity.c b/src/racoon/isakmp_unity.c
index 9873f59..a1bf793 100644
--- a/src/racoon/isakmp_unity.c
+++ b/src/racoon/isakmp_unity.c
@@ -1,4 +1,4 @@
-/* $NetBSD: isakmp_unity.c,v 1.7 2006/10/09 06:17:20 manu Exp $ */
+/* $NetBSD: isakmp_unity.c,v 1.9 2007/10/19 03:37:19 manu Exp $ */
/* Id: isakmp_unity.c,v 1.10 2006/07/31 04:49:23 manubsd Exp */
@@ -305,32 +305,41 @@ int splitnet_list_add(list, network, count)
struct unity_network * network;
int *count;
{
- struct unity_netentry * newentry;
+ struct unity_netentry * nentry;
+
+ /*
+ * search for network in current list
+ * to avoid adding duplicates
+ */
+ for (nentry = *list; nentry != NULL; nentry = nentry->next)
+ if (memcmp(&nentry->network, network,
+ sizeof(struct unity_network)) == 0)
+ return 0; /* it's a dupe */
/*
* allocate new netentry and copy
- * new splitnet network data
+ * new splitnet network data
*/
- newentry = (struct unity_netentry *)
+ nentry = (struct unity_netentry *)
racoon_malloc(sizeof(struct unity_netentry));
- if (newentry == NULL)
+ if (nentry == NULL)
return -1;
- memcpy(&newentry->network,network,
+ memcpy(&nentry->network,network,
sizeof(struct unity_network));
- newentry->next = NULL;
+ nentry->next = NULL;
/*
* locate the last netentry in our
* splitnet list and add our entry
*/
if (*list == NULL)
- *list = newentry;
+ *list = nentry;
else {
struct unity_netentry * tmpentry = *list;
while (tmpentry->next != NULL)
tmpentry = tmpentry->next;
- tmpentry->next = newentry;
+ tmpentry->next = nentry;
}
(*count)++;
@@ -354,8 +363,9 @@ void splitnet_list_free(list, count)
}
}
-char * splitnet_list_2str(list)
+char * splitnet_list_2str(list, splitnet_ipaddr)
struct unity_netentry * list;
+ enum splinet_ipaddr splitnet_ipaddr;
{
struct unity_netentry * netentry;
char tmp1[40];
@@ -389,8 +399,17 @@ char * splitnet_list_2str(list)
inet_ntop(AF_INET, &netentry->network.addr4, tmp1, 40);
inet_ntop(AF_INET, &netentry->network.mask4, tmp2, 40);
-
- len += sprintf(str+len, "%s/%s ", tmp1, tmp2);
+ if (splitnet_ipaddr == CIDR) {
+ uint32_t tmp3;
+ int cidrmask;
+
+ tmp3 = ntohl(netentry->network.mask4.s_addr);
+ for (cidrmask = 0; tmp3 != 0; cidrmask++)
+ tmp3 <<= 1;
+ len += sprintf(str+len, "%s/%d ", tmp1, cidrmask);
+ } else {
+ len += sprintf(str+len, "%s/%s ", tmp1, tmp2);
+ }
netentry = netentry->next;
}
diff --git a/src/racoon/isakmp_unity.h b/src/racoon/isakmp_unity.h
index b52f02c..3667d0d 100644
--- a/src/racoon/isakmp_unity.h
+++ b/src/racoon/isakmp_unity.h
@@ -1,4 +1,4 @@
-/* $NetBSD: isakmp_unity.h,v 1.4 2006/09/09 16:22:09 manu Exp $ */
+/* $NetBSD: isakmp_unity.h,v 1.5 2007/10/19 03:37:19 manu Exp $ */
/* $KAME$ */
@@ -31,6 +31,8 @@
* SUCH DAMAGE.
*/
+enum splinet_ipaddr { NETMASK, CIDR };
+
/* ISAKMP notifies specific to the Unity vendor Id */
/* Sent during xauth if the user types his password too slowly */
#define ISAKMP_NTYPE_UNITY_HEARTBEAT 40500
@@ -66,7 +68,7 @@ struct unity_netentry {
int splitnet_list_add(struct unity_netentry **, struct unity_network *, int *);
void splitnet_list_free(struct unity_netentry *, int *);
-char * splitnet_list_2str(struct unity_netentry *);
+char * splitnet_list_2str(struct unity_netentry *, enum splinet_ipaddr);
vchar_t *isakmp_unity_req(struct ph1handle *, struct isakmp_data *);
void isakmp_unity_reply(struct ph1handle *, struct isakmp_data *);
diff --git a/src/racoon/isakmp_var.h b/src/racoon/isakmp_var.h
index f4ef45d..09e4e7f 100644
--- a/src/racoon/isakmp_var.h
+++ b/src/racoon/isakmp_var.h
@@ -1,11 +1,11 @@
-/* $NetBSD: isakmp_var.h,v 1.6.6.1 2007/02/20 09:08:49 vanhu Exp $ */
+/* $NetBSD: isakmp_var.h,v 1.17 2010/11/12 10:36:37 tteras Exp $ */
/* Id: isakmp_var.h,v 1.12 2005/05/07 14:45:31 manubsd Exp */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -17,7 +17,7 @@
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -35,6 +35,7 @@
#define _ISAKMP_VAR_H
#include "vmbuf.h"
+#include "policy.h"
#define PORT_ISAKMP 500
#define PORT_ISAKMP_NATT 4500
@@ -56,40 +57,39 @@ struct sockaddr;
struct ph1handle;
struct ph2handle;
struct remoteconf;
-struct isakmp_gen;
struct ipsecdoi_pl_id; /* XXX */
struct isakmp_pl_ke; /* XXX */
struct isakmp_pl_nonce; /* XXX */
-extern int isakmp_handler __P((int));
-extern int isakmp_ph1begin_i __P((struct remoteconf *, struct sockaddr *,
- struct sockaddr *));
+extern struct ph1handle *isakmp_ph1begin_i __P((struct remoteconf *,
+ struct sockaddr *, struct sockaddr *));
extern vchar_t *isakmp_parsewoh __P((int, struct isakmp_gen *, int));
extern vchar_t *isakmp_parse __P((vchar_t *));
extern int isakmp_init __P((void));
extern const char *isakmp_pindex __P((const isakmp_index *, const u_int32_t));
-extern int isakmp_open __P((void));
-extern void isakmp_close __P((void));
+extern int isakmp_open __P((struct sockaddr *, int));
+extern void isakmp_close __P((int fd));
extern int isakmp_send __P((struct ph1handle *, vchar_t *));
-extern void isakmp_ph1resend_stub __P((void *));
-extern int isakmp_ph1resend __P((struct ph1handle *));
-extern void isakmp_ph2resend_stub __P((void *));
-extern int isakmp_ph2resend __P((struct ph2handle *));
-extern void isakmp_ph1expire_stub __P((void *));
+extern int isakmp_ph1send __P((struct ph1handle *));
+extern int isakmp_ph2send __P((struct ph2handle *));
+extern void isakmp_ph1dying_stub __P((struct sched *));
+extern void isakmp_ph1dying __P((struct ph1handle *));
+extern void isakmp_ph1expire_stub __P((struct sched *));
extern void isakmp_ph1expire __P((struct ph1handle *));
-extern void isakmp_ph1delete_stub __P((void *));
+extern void isakmp_ph1delete_stub __P((struct sched *));
extern void isakmp_ph1delete __P((struct ph1handle *));
-extern void isakmp_ph2expire_stub __P((void *));
+extern void isakmp_ph2expire_stub __P((struct sched *));
extern void isakmp_ph2expire __P((struct ph2handle *));
-extern void isakmp_ph2delete_stub __P((void *));
+extern void isakmp_ph2delete_stub __P((struct sched *));
extern void isakmp_ph2delete __P((struct ph2handle *));
-extern int isakmp_post_acquire __P((struct ph2handle *));
+extern int isakmp_get_sainfo __P((struct ph2handle *, struct secpolicy *, struct secpolicy *));
+extern int isakmp_post_acquire __P((struct ph2handle *, struct ph1handle *, int));
extern int isakmp_post_getspi __P((struct ph2handle *));
-extern void isakmp_chkph1there_stub __P((void *));
+extern void isakmp_chkph1there_stub __P((struct sched *));
extern void isakmp_chkph1there __P((struct ph2handle *));
extern caddr_t isakmp_set_attr_v __P((caddr_t, int, caddr_t, int));
@@ -106,8 +106,19 @@ extern caddr_t set_isakmp_header1 __P((vchar_t *, struct ph1handle *, int));
extern caddr_t set_isakmp_header2 __P((vchar_t *, struct ph2handle *, int));
extern caddr_t set_isakmp_payload __P((caddr_t, vchar_t *, int));
-extern struct payload_list *isakmp_plist_append __P((struct payload_list *plist,
- vchar_t *payload, int payload_type));
+extern struct payload_list *isakmp_plist_append_full __P((
+ struct payload_list *plist, vchar_t *payload,
+ u_int8_t payload_type, u_int8_t free));
+
+static inline struct payload_list *isakmp_plist_append(plist, payload, payload_type)
+ struct payload_list *plist;
+ vchar_t *payload;
+ u_int8_t payload_type;
+{
+ return isakmp_plist_append_full(plist, payload, payload_type, 0);
+}
+
+
extern vchar_t *isakmp_plist_set_all __P((struct payload_list **plist,
struct ph1handle *iph1));
@@ -120,7 +131,7 @@ extern int copy_ph1addresses __P(( struct ph1handle *,
struct remoteconf *, struct sockaddr *, struct sockaddr *));
extern void log_ph1established __P((const struct ph1handle *));
-extern void script_hook __P((struct ph1handle *, int));
+extern void script_hook __P((struct ph1handle *, int));
extern int script_env_append __P((char ***, int *, char *, char *));
extern int script_exec __P((char *, int, char * const *));
@@ -129,4 +140,5 @@ void delete_spd __P((struct ph2handle *, u_int64_t));
#ifdef INET6
u_int32_t setscopeid __P((struct sockaddr *, struct sockaddr *));
#endif
+
#endif /* _ISAKMP_VAR_H */
diff --git a/src/racoon/isakmp_xauth.c b/src/racoon/isakmp_xauth.c
index 12e5ef6..853caaa 100644
--- a/src/racoon/isakmp_xauth.c
+++ b/src/racoon/isakmp_xauth.c
@@ -1,4 +1,4 @@
-/* $NetBSD: isakmp_xauth.c,v 1.11.6.2 2009/04/20 13:35:36 tteras Exp $ */
+/* $NetBSD: isakmp_xauth.c,v 1.22 2011/03/14 15:50:36 vanhu Exp $ */
/* Id: isakmp_xauth.c,v 1.38 2006/08/22 18:17:17 manubsd Exp */
@@ -40,6 +40,7 @@
#include <netinet/in.h>
+#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -95,9 +96,9 @@
#ifdef HAVE_LIBRADIUS
#include <radlib.h>
-
struct rad_handle *radius_auth_state = NULL;
struct rad_handle *radius_acct_state = NULL;
+struct xauth_rad_config xauth_rad_config;
#endif
#ifdef HAVE_LIBPAM
@@ -129,7 +130,7 @@ xauth_sendreq(iph1)
size_t tlen;
/* Status checks */
- if (iph1->status != PHASE1ST_ESTABLISHED) {
+ if (iph1->status < PHASE1ST_ESTABLISHED) {
plog(LLV_ERROR, LOCATION, NULL,
"Xauth request while phase 1 is not completed\n");
return;
@@ -311,7 +312,7 @@ xauth_attr_reply(iph1, attr, id)
* On failure, throttle the connexion for the remote host
* in order to make password attacks more difficult.
*/
- throttle_delay = throttle_host(iph1->remote, res) - time(NULL);
+ throttle_delay = throttle_host(iph1->remote, res);
if (throttle_delay > 0) {
char *str;
@@ -329,7 +330,7 @@ skip_auth:
if (throttle_delay != 0) {
struct xauth_reply_arg *xra;
- if ((xra = racoon_malloc(sizeof(*xra))) == NULL) {
+ if ((xra = racoon_calloc(1, sizeof(*xra))) == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
"malloc failed, bypass throttling\n");
return xauth_reply(iph1, port, id, res);
@@ -344,7 +345,8 @@ skip_auth:
xra->port = port;
xra->id = id;
xra->res = res;
- sched_new(throttle_delay, xauth_reply_stub, xra);
+ sched_schedule(&xra->sc, throttle_delay,
+ xauth_reply_stub);
} else {
return xauth_reply(iph1, port, id, res);
}
@@ -354,10 +356,10 @@ skip_auth:
}
void
-xauth_reply_stub(args)
- void *args;
+xauth_reply_stub(sc)
+ struct sched *sc;
{
- struct xauth_reply_arg *xra = (struct xauth_reply_arg *)args;
+ struct xauth_reply_arg *xra = container_of(sc, struct xauth_reply_arg, sc);
struct ph1handle *iph1;
if ((iph1 = getph1byindex(&xra->index)) != NULL)
@@ -367,7 +369,6 @@ xauth_reply_stub(args)
"Delayed Xauth reply: phase 1 no longer exists.\n");
racoon_free(xra);
- return;
}
int
@@ -390,7 +391,7 @@ xauth_reply(iph1, port, id, res)
xst->status = XAUTHST_NOTYET;
/* Delete Phase 1 SA */
- if (iph1->status == PHASE1ST_ESTABLISHED)
+ if (iph1->status >= PHASE1ST_ESTABLISHED)
isakmp_info_send_d1(iph1);
remph1(iph1);
delph1(iph1);
@@ -447,6 +448,31 @@ xauth_sendstatus(iph1, status, id)
#ifdef HAVE_LIBRADIUS
int
+xauth_radius_init_conf(int free)
+{
+ /* free radius config resources */
+ if (free) {
+ int i;
+ for (i = 0; i < xauth_rad_config.auth_server_count; i++) {
+ vfree(xauth_rad_config.auth_server_list[i].host);
+ vfree(xauth_rad_config.auth_server_list[i].secret);
+ }
+ for (i = 0; i < xauth_rad_config.acct_server_count; i++) {
+ vfree(xauth_rad_config.acct_server_list[i].host);
+ vfree(xauth_rad_config.acct_server_list[i].secret);
+ }
+ if (radius_auth_state != NULL)
+ rad_close(radius_auth_state);
+ if (radius_acct_state != NULL)
+ rad_close(radius_acct_state);
+ }
+
+ /* initialize radius config */
+ memset(&xauth_rad_config, 0, sizeof(xauth_rad_config));
+ return 0;
+}
+
+int
xauth_radius_init(void)
{
/* For first time use, initialize Radius */
@@ -458,13 +484,35 @@ xauth_radius_init(void)
return -1;
}
- if (rad_config(radius_auth_state, NULL) != 0) {
- plog(LLV_ERROR, LOCATION, NULL,
- "Cannot open librarius config file: %s\n",
- rad_strerror(radius_auth_state));
- rad_close(radius_auth_state);
- radius_auth_state = NULL;
- return -1;
+ int auth_count = xauth_rad_config.auth_server_count;
+ int auth_added = 0;
+ if (auth_count) {
+ int i;
+ for (i = 0; i < auth_count; i++) {
+ if(!rad_add_server(
+ radius_auth_state,
+ xauth_rad_config.auth_server_list[i].host->v,
+ xauth_rad_config.auth_server_list[i].port,
+ xauth_rad_config.auth_server_list[i].secret->v,
+ xauth_rad_config.timeout,
+ xauth_rad_config.retries ))
+ auth_added++;
+ else
+ plog(LLV_WARNING, LOCATION, NULL,
+ "could not add radius auth server %s\n",
+ xauth_rad_config.auth_server_list[i].host->v);
+ }
+ }
+
+ if (!auth_added) {
+ if (rad_config(radius_auth_state, NULL) != 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "Cannot open libradius config file: %s\n",
+ rad_strerror(radius_auth_state));
+ rad_close(radius_auth_state);
+ radius_auth_state = NULL;
+ return -1;
+ }
}
}
@@ -476,13 +524,35 @@ xauth_radius_init(void)
return -1;
}
- if (rad_config(radius_acct_state, NULL) != 0) {
- plog(LLV_ERROR, LOCATION, NULL,
- "Cannot open librarius config file: %s\n",
- rad_strerror(radius_acct_state));
- rad_close(radius_acct_state);
- radius_acct_state = NULL;
- return -1;
+ int acct_count = xauth_rad_config.acct_server_count;
+ int acct_added = 0;
+ if (acct_count) {
+ int i;
+ for (i = 0; i < acct_count; i++) {
+ if(!rad_add_server(
+ radius_acct_state,
+ xauth_rad_config.acct_server_list[i].host->v,
+ xauth_rad_config.acct_server_list[i].port,
+ xauth_rad_config.acct_server_list[i].secret->v,
+ xauth_rad_config.timeout,
+ xauth_rad_config.retries ))
+ acct_added++;
+ else
+ plog(LLV_WARNING, LOCATION, NULL,
+ "could not add radius account server %s\n",
+ xauth_rad_config.acct_server_list[i].host->v);
+ }
+ }
+
+ if (!acct_added) {
+ if (rad_config(radius_acct_state, NULL) != 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "Cannot open libradius config file: %s\n",
+ rad_strerror(radius_acct_state));
+ rad_close(radius_acct_state);
+ radius_acct_state = NULL;
+ return -1;
+ }
}
}
@@ -670,7 +740,7 @@ xauth_login_pam(port, raddr, usr, pwd)
"cannot allocate memory: %s\n", strerror(errno));
goto out;
}
-
+
if ((error = pam_set_item(pam, PAM_RHOST, remote)) != 0) {
plog(LLV_ERROR, LOCATION, NULL,
"pam_set_item failed: %s\n",
@@ -678,6 +748,13 @@ xauth_login_pam(port, raddr, usr, pwd)
goto out;
}
+ if ((error = pam_set_item(pam, PAM_RUSER, usr)) != 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "pam_set_item failed: %s\n",
+ pam_strerror(pam, error));
+ goto out;
+ }
+
PAM_usr = usr;
PAM_pwd = pwd;
error = pam_authenticate(pam, 0);
@@ -720,7 +797,7 @@ out:
#ifdef HAVE_LIBLDAP
int
-xauth_ldap_init(void)
+xauth_ldap_init_conf(void)
{
int tmplen;
int error = -1;
@@ -1255,7 +1332,7 @@ xauth_check(iph1)
* status. It does it if the chose authmethod is using Xauth.
* On the client side (roadwarrior), we don't check anything.
*/
- switch (AUTHMETHOD(iph1)) {
+ switch (iph1->approval->authmethod) {
case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
@@ -1546,9 +1623,9 @@ isakmp_xauth_set(iph1, attr)
* when running as a client (initiator).
*/
xst = &iph1->mode_cfg->xauth;
- switch(AUTHMETHOD(iph1)) {
+ switch (iph1->approval->authmethod) {
case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
- case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I:
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I:
case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
/* Not implemented ... */
case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
@@ -1568,13 +1645,11 @@ isakmp_xauth_set(iph1, attr)
plog(LLV_ERROR, LOCATION, NULL,
"Xauth authentication failed\n");
- EVT_PUSH(iph1->local, iph1->remote,
- EVTT_XAUTH_FAILED, NULL);
+ evt_phase1(iph1, EVT_PHASE1_XAUTH_FAILED, NULL);
iph1->mode_cfg->flags |= ISAKMP_CFG_DELETE_PH1;
} else {
- EVT_PUSH(iph1->local, iph1->remote,
- EVTT_XAUTH_SUCCESS, NULL);
+ evt_phase1(iph1, EVT_PHASE1_XAUTH_SUCCESS, NULL);
}
@@ -1689,3 +1764,42 @@ xauth_rmconf_delete(xauth_rmconf)
return;
}
+
+struct xauth_rmconf *
+xauth_rmconf_dup(xauth_rmconf)
+ struct xauth_rmconf *xauth_rmconf;
+{
+ struct xauth_rmconf *new;
+
+ if (xauth_rmconf != NULL) {
+ new = racoon_malloc(sizeof(*new));
+ if (new == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "xauth_rmconf_dup: malloc failed\n");
+ return NULL;
+ }
+
+ memcpy(new, xauth_rmconf, sizeof(*new));
+
+ if (xauth_rmconf->login != NULL) {
+ new->login = vdup(xauth_rmconf->login);
+ if (new->login == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "xauth_rmconf_dup: malloc failed (login)\n");
+ return NULL;
+ }
+ }
+ if (xauth_rmconf->pass != NULL) {
+ new->pass = vdup(xauth_rmconf->pass);
+ if (new->pass == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "xauth_rmconf_dup: malloc failed (password)\n");
+ return NULL;
+ }
+ }
+
+ return new;
+ }
+
+ return NULL;
+}
diff --git a/src/racoon/isakmp_xauth.h b/src/racoon/isakmp_xauth.h
index ebb5214..f9e778f 100644
--- a/src/racoon/isakmp_xauth.h
+++ b/src/racoon/isakmp_xauth.h
@@ -1,4 +1,4 @@
-/* $NetBSD: isakmp_xauth.h,v 1.4 2006/09/09 16:22:09 manu Exp $ */
+/* $NetBSD: isakmp_xauth.h,v 1.7 2011/03/14 15:50:36 vanhu Exp $ */
/* $KAME$ */
@@ -34,6 +34,8 @@
#ifndef _ISAKMP_XAUTH_H
#define _ISAKMP_XAUTH_H
+#include "schedule.h"
+
/* ISAKMP mode config attribute types specific to the Xauth vendor ID */
#define XAUTH_TYPE 16520
#define XAUTH_USER_NAME 16521
@@ -90,6 +92,7 @@ struct xauth_rmconf {
#define XAUTHST_OK 2
struct xauth_reply_arg {
+ struct sched sc;
isakmp_index index;
int port;
int id;
@@ -107,18 +110,41 @@ int group_check(struct ph1handle *, char **, int);
vchar_t *isakmp_xauth_req(struct ph1handle *, struct isakmp_data *);
vchar_t *isakmp_xauth_set(struct ph1handle *, struct isakmp_data *);
void xauth_rmstate(struct xauth_state *);
-void xauth_reply_stub(void *);
+void xauth_reply_stub(struct sched *);
int xauth_reply(struct ph1handle *, int, int, int);
int xauth_rmconf_used(struct xauth_rmconf **);
void xauth_rmconf_delete(struct xauth_rmconf **);
+struct xauth_rmconf * xauth_rmconf_dup(struct xauth_rmconf *);
+
+#ifdef HAVE_LIBPAM
+int xauth_login_pam(int, struct sockaddr *, char *, char *);
+#endif
#ifdef HAVE_LIBRADIUS
-int xauth_login_radius(struct ph1handle *, char *, char *);
+
+#define RADIUS_MAX_SERVERS 5
+
+struct rad_serv {
+ vchar_t *host;
+ int port;
+ vchar_t *secret;
+};
+
+struct xauth_rad_config {
+ struct rad_serv auth_server_list[RADIUS_MAX_SERVERS];
+ int auth_server_count;
+ struct rad_serv acct_server_list[RADIUS_MAX_SERVERS];
+ int acct_server_count;
+ int timeout;
+ int retries;
+};
+
+extern struct xauth_rad_config xauth_rad_config;
+
+int xauth_radius_init_conf(int free);
int xauth_radius_init(void);
-#endif
+int xauth_login_radius(struct ph1handle *, char *, char *);
-#ifdef HAVE_LIBPAM
-int xauth_login_pam(int, struct sockaddr *, char *, char *);
#endif
#ifdef HAVE_LIBLDAP
@@ -148,8 +174,9 @@ struct xauth_ldap_config {
extern struct xauth_ldap_config xauth_ldap_config;
-int xauth_ldap_init(void);
+int xauth_ldap_init_conf(void);
int xauth_login_ldap(struct ph1handle *, char *, char *);
+
#endif
#endif /* _ISAKMP_XAUTH_H */
diff --git a/src/racoon/kmpstat.c b/src/racoon/kmpstat.c
index c59e43a..50c478d 100644
--- a/src/racoon/kmpstat.c
+++ b/src/racoon/kmpstat.c
@@ -1,4 +1,4 @@
-/* $NetBSD: kmpstat.c,v 1.4.6.2 2007/11/06 16:41:33 vanhu Exp $ */
+/* $NetBSD: kmpstat.c,v 1.7 2010/11/12 09:08:26 tteras Exp $ */
/* $KAME: kmpstat.c,v 1.33 2004/08/16 08:20:28 itojun Exp $ */
@@ -138,7 +138,7 @@ com_recv(combufp)
{
struct admin_com h, *com;
caddr_t buf;
- int len;
+ int len, rlen;
int l = 0;
caddr_t p;
@@ -153,19 +153,25 @@ com_recv(combufp)
if (len < sizeof(h))
goto bad1;
- if (h.ac_errno) {
+ if (h.ac_errno && !(h.ac_cmd & ADMIN_FLAG_LONG_REPLY)) {
errno = h.ac_errno;
goto bad1;
}
+ /* real length */
+ if (h.ac_cmd & ADMIN_FLAG_LONG_REPLY)
+ rlen = ((u_int32_t)h.ac_len) + (((u_int32_t)h.ac_len_high) << 16);
+ else
+ rlen = h.ac_len;
+
/* allocate buffer */
- if ((*combufp = vmalloc(h.ac_len)) == NULL)
+ if ((*combufp = vmalloc(rlen)) == NULL)
goto bad1;
/* read real message */
p = (*combufp)->v;
- while (l < len) {
- if ((len = recv(so, p, h.ac_len, 0)) < 0) {
+ while (l < rlen) {
+ if ((len = recv(so, p, rlen - l, 0)) < 0) {
perror("recv");
goto bad2;
}
diff --git a/src/racoon/localconf.c b/src/racoon/localconf.c
index ede1d9b..a512953 100644
--- a/src/racoon/localconf.c
+++ b/src/racoon/localconf.c
@@ -1,4 +1,4 @@
-/* $NetBSD: localconf.c,v 1.4 2006/09/09 16:22:09 manu Exp $ */
+/* $NetBSD: localconf.c,v 1.7 2008/12/23 14:04:42 tteras Exp $ */
/* $KAME: localconf.c,v 1.33 2001/08/09 07:32:19 sakane Exp $ */
@@ -85,18 +85,14 @@ flushlcconf()
int i;
setdefault();
- clear_myaddr(&lcconf->myaddrs);
+ myaddr_flush();
+
for (i = 0; i < LC_PATHTYPE_MAX; i++) {
if (lcconf->pathinfo[i]) {
racoon_free(lcconf->pathinfo[i]);
lcconf->pathinfo[i] = NULL;
}
}
- for (i = 0; i < LC_IDENTTYPE_MAX; i++) {
- if (lcconf->ident[i])
- vfree(lcconf->ident[i]);
- lcconf->ident[i] = NULL;
- }
}
static void
@@ -105,7 +101,6 @@ setdefault()
lcconf->uid = 0;
lcconf->gid = 0;
lcconf->chroot = NULL;
- lcconf->autograbaddr = 1;
lcconf->port_isakmp = PORT_ISAKMP;
lcconf->port_isakmp_natt = PORT_ISAKMP_NATT;
lcconf->default_af = AF_INET;
@@ -124,6 +119,7 @@ setdefault()
lcconf->complex_bundle = TRUE; /*XXX FALSE;*/
lcconf->gss_id_enc = LC_GSSENC_UTF16LE; /* Windows compatibility */
lcconf->natt_ka_interval = LC_DEFAULT_NATT_KA_INTERVAL;
+ lcconf->pfkey_buffer_size = LC_DEFAULT_PFKEY_BUFFER_SIZE;
}
/*
@@ -340,21 +336,12 @@ saverestore_params(f)
int f;
{
static u_int16_t s_port_isakmp;
-#ifdef ENABLE_ADMINPORT
- static u_int16_t s_port_admin;
-#endif
/* 0: save, 1: restore */
if (f) {
lcconf->port_isakmp = s_port_isakmp;
-#ifdef ENABLE_ADMINPORT
- lcconf->port_admin = s_port_admin;
-#endif
} else {
s_port_isakmp = lcconf->port_isakmp;
-#ifdef ENABLE_ADMINPORT
- s_port_admin = lcconf->port_admin;
-#endif
}
}
diff --git a/src/racoon/localconf.h b/src/racoon/localconf.h
index f7cf33a..04ac8e4 100644
--- a/src/racoon/localconf.h
+++ b/src/racoon/localconf.h
@@ -1,4 +1,4 @@
-/* $NetBSD: localconf.h,v 1.4 2006/09/09 16:22:09 manu Exp $ */
+/* $NetBSD: localconf.h,v 1.7 2008/12/23 14:04:42 tteras Exp $ */
/* Id: localconf.h,v 1.13 2005/11/06 18:13:18 monas Exp */
@@ -57,11 +57,10 @@
#define LC_DEFAULT_RETRY_CHECKPH1 30
#define LC_DEFAULT_WAIT_PH2COMPLETE 30
#define LC_DEFAULT_NATT_KA_INTERVAL 20
+#define LC_DEFAULT_PFKEY_BUFFER_SIZE 0
#define LC_DEFAULT_SECRETSIZE 16 /* 128 bits */
-#define LC_IDENTTYPE_MAX 5 /* XXX */
-
#define LC_GSSENC_UTF16LE 0 /* GSS ID in UTF-16LE */
#define LC_GSSENC_LATIN1 1 /* GSS ID in ISO-Latin-1 */
#define LC_GSSENC_MAX 2
@@ -74,18 +73,13 @@ struct localconf {
char *chroot; /* chroot path */
u_int16_t port_isakmp; /* port for isakmp as default */
u_int16_t port_isakmp_natt; /* port for NAT-T use */
- u_int16_t port_admin; /* port for admin */
int default_af; /* default address family */
int sock_admin;
int sock_pfkey;
int rtsock; /* routing socket */
- int autograbaddr;
- struct myaddrs *myaddrs;
-
char *pathinfo[LC_PATHTYPE_MAX];
- vchar_t *ident[LC_IDENTTYPE_MAX]; /* base of Identifier payload. */
int pad_random;
int pad_randomlen;
@@ -118,6 +112,7 @@ struct localconf {
*/
int gss_id_enc; /* GSS ID encoding to use */
+ int pfkey_buffer_size; /* Set socket buffer size for pfkey */
};
extern struct localconf *lcconf;
diff --git a/src/racoon/main.c b/src/racoon/main.c
index 094026e..ab71b3e 100644
--- a/src/racoon/main.c
+++ b/src/racoon/main.c
@@ -1,4 +1,4 @@
-/* $NetBSD: main.c,v 1.6.6.2 2008/11/27 15:25:26 vanhu Exp $ */
+/* $NetBSD: main.c,v 1.12 2009/01/26 18:13:06 tteras Exp $ */
/* Id: main.c,v 1.25 2006/06/20 20:31:34 manubsd Exp */
@@ -66,12 +66,6 @@
#include "cfparse_proto.h"
#include "isakmp_var.h"
-#ifdef ENABLE_HYBRID
-#include <resolv.h>
-#include "isakmp.h"
-#include "isakmp_xauth.h"
-#include "isakmp_cfg.h"
-#endif
#include "remoteconf.h"
#include "localconf.h"
#include "session.h"
@@ -84,10 +78,10 @@
#include "package_version.h"
+int dump_config = 0; /* dump parsed config file. */
int f_local = 0; /* local test mode. behave like a wall. */
int vflag = 1; /* for print-isakmp.c */
static int loading_sa = 0; /* install sa when racoon boots up. */
-static int dump_config = 0; /* dump parsed config file. */
#ifdef TOP_PACKAGE
static char version[] = "@(#)" TOP_PACKAGE_STRING " (" TOP_PACKAGE_URL ")";
@@ -95,197 +89,77 @@ static char version[] = "@(#)" TOP_PACKAGE_STRING " (" TOP_PACKAGE_URL ")";
static char version[] = "@(#) racoon / IPsec-tools";
#endif /* TOP_PACKAGE */
-int main __P((int, char **));
-static void usage __P((void));
-static void parse __P((int, char **));
-#if 0
-static void cleanup_pidfile __P((void));
-#endif
-
-void
-usage()
+static void
+print_version()
{
- printf("usage: racoon [-BdFv%s] %s[-f (file)] [-l (file)] [-p (port)]\n",
+ printf("%s\n"
+ "\n"
+ "Compiled with:\n"
+ "- %s (http://www.openssl.org/)\n"
#ifdef INET6
- "46",
-#else
- "",
+ "- IPv6 support\n"
#endif
-#ifdef ENABLE_ADMINPORT
- "[-a (port)] "
-#else
- ""
-#endif
- );
- printf(" -B: install SA to the kernel from the file "
- "specified by the configuration file.\n");
- printf(" -d: debug level, more -d will generate more debug message.\n");
- printf(" -C: dump parsed config file.\n");
- printf(" -L: include location in debug messages\n");
- printf(" -F: run in foreground, do not become daemon.\n");
- printf(" -v: be more verbose\n");
-#ifdef INET6
- printf(" -4: IPv4 mode.\n");
- printf(" -6: IPv6 mode.\n");
-#endif
-#ifdef ENABLE_ADMINPORT
- printf(" -a: port number for admin port.\n");
-#endif
- printf(" -f: pathname for configuration file.\n");
- printf(" -l: pathname for log file.\n");
- printf(" -p: port number for isakmp (default: %d).\n", PORT_ISAKMP);
- printf(" -P: port number for NAT-T (default: %d).\n", PORT_ISAKMP_NATT);
- exit(1);
-}
-
-int
-main(ac, av)
- int ac;
- char **av;
-{
- int error;
-
- if (geteuid() != 0) {
- errx(1, "must be root to invoke this program.");
- /* NOTREACHED*/
- }
-
- /*
- * Don't let anyone read files I write. Although some files (such as
- * the PID file) can be other readable, we dare to use the global mask,
- * because racoon uses fopen(3), which can't specify the permission
- * at the creation time.
- */
- umask(077);
- if (umask(077) != 077) {
- errx(1, "could not set umask");
- /* NOTREACHED*/
- }
-
-#ifdef DEBUG_RECORD_MALLOCATION
- DRM_init();
+#ifdef ENABLE_DPD
+ "- Dead Peer Detection\n"
#endif
-
-#ifdef HAVE_SECCTX
- init_avc();
+#ifdef ENABLE_FRAG
+ "- IKE fragmentation\n"
#endif
- eay_init();
- initlcconf();
- initrmconf();
- oakley_dhinit();
- compute_vendorids();
-
- parse(ac, av);
-
- ploginit();
-
- plog(LLV_INFO, LOCATION, NULL, "%s\n", version);
- plog(LLV_INFO, LOCATION, NULL, "@(#)"
- "This product linked %s (http://www.openssl.org/)"
- "\n", eay_version());
- plog(LLV_INFO, LOCATION, NULL, "Reading configuration from \"%s\"\n",
- lcconf->racoon_conf);
-
- if (pfkey_init() < 0) {
- errx(1, "something error happened "
- "while pfkey initializing.");
- /* NOTREACHED*/
- }
-
#ifdef ENABLE_HYBRID
- if (isakmp_cfg_init(ISAKMP_CFG_INIT_COLD))
- errx(1, "could not initialize ISAKMP mode config structures");
+ "- Hybrid authentication\n"
#endif
-
-#ifdef HAVE_LIBLDAP
- if (xauth_ldap_init() != 0)
- errx(1, "could not initialize libldap");
+#ifdef ENABLE_GSSAPI
+ "- GSS-API authentication\n"
#endif
-
- /*
- * in order to prefer the parameters by command line,
- * saving some parameters before parsing configuration file.
- */
- save_params();
- error = cfparse();
- if (error != 0)
- errx(1, "failed to parse configuration file.");
- restore_params();
-
-#ifdef ENABLE_HYBRID
- if(isakmp_cfg_config.network4 && isakmp_cfg_config.pool_size == 0)
- if ((error = isakmp_cfg_resize_pool(ISAKMP_CFG_MAX_CNX)) != 0)
- return error;
+#ifdef ENABLE_NATT
+ "- NAT Traversal\n"
#endif
-
- if (dump_config)
- dumprmconf ();
-
-#ifdef HAVE_LIBRADIUS
- if (xauth_radius_init() != 0) {
- errx(1, "could not initialize libradius");
- /* NOTREACHED*/
- }
+#ifdef ENABLE_STATS
+ "- Timing statistics\n"
#endif
-
- /*
- * install SAs from the specified file. If the file is not specified
- * by the configuration file, racoon will exit.
- */
- if (loading_sa && !f_local) {
- if (backupsa_from_file() != 0)
- errx(1, "something error happened "
- "SA recovering.");
- }
-
- if (f_foreground)
- close(0);
- else {
- if (daemon(0, 0) < 0) {
- errx(1, "failed to be daemon. (%s)",
- strerror(errno));
- }
-#ifndef __linux__
- /*
- * In case somebody has started inetd manually, we need to
- * clear the logname, so that old servers run as root do not
- * get the user's logname..
- */
- if (setlogin("") < 0) {
- plog(LLV_ERROR, LOCATION, NULL,
- "cannot clear logname: %s\n", strerror(errno));
- /* no big deal if it fails.. */
- }
+#ifdef ENABLE_ADMINPORT
+ "- Admin port\n"
#endif
- if (!f_local) {
-#if 0
- if (atexit(cleanup_pidfile) < 0) {
- plog(LLV_ERROR, LOCATION, NULL,
- "cannot register pidfile cleanup");
- }
+#ifdef HAVE_CLOCK_MONOTONIC
+ "- Monotonic clock\n"
#endif
- }
- }
-
- session();
-
+#ifdef HAVE_SECCTX
+ "- Security context\n"
+#endif
+ "\n",
+ version,
+ eay_version());
exit(0);
}
-#if 0
static void
-cleanup_pidfile()
+usage()
{
- pid_t p = getpid();
-
- /* if it's not child process, clean everything */
- if (racoon_pid == p) {
- const char *pid_file = _PATH_VARRUN "racoon.pid";
-
- (void) unlink(pid_file);
- }
-}
+ printf("usage: racoon [-BdFv"
+#ifdef INET6
+ "46"
#endif
+ "] [-f (file)] [-l (file)] [-p (port)] [-P (natt port)]\n"
+ " -B: install SA to the kernel from the file "
+ "specified by the configuration file.\n"
+ " -d: debug level, more -d will generate more debug message.\n"
+ " -C: dump parsed config file.\n"
+ " -L: include location in debug messages\n"
+ " -F: run in foreground, do not become daemon.\n"
+ " -v: be more verbose\n"
+ " -V: print version and exit\n"
+#ifdef INET6
+ " -4: IPv4 mode.\n"
+ " -6: IPv6 mode.\n"
+#endif
+ " -f: pathname for configuration file.\n"
+ " -l: pathname for log file.\n"
+ " -p: port number for isakmp (default: %d).\n"
+ " -P: port number for NAT-T (default: %d).\n"
+ "\n",
+ PORT_ISAKMP, PORT_ISAKMP_NATT);
+ exit(1);
+}
static void
parse(ac, av)
@@ -305,7 +179,7 @@ parse(ac, av)
else
pname = *av;
- while ((c = getopt(ac, av, "dLFp:P:a:f:l:vZBC"
+ while ((c = getopt(ac, av, "dLFp:P:f:l:vVZBC"
#ifdef YYDEBUG
"y"
#endif
@@ -330,15 +204,6 @@ parse(ac, av)
case 'P':
lcconf->port_isakmp_natt = atoi(optarg);
break;
- case 'a':
-#ifdef ENABLE_ADMINPORT
- lcconf->port_admin = atoi(optarg);
- break;
-#else
- fprintf(stderr, "%s: the option is disabled "
- "in the configuration\n", pname);
- exit(1);
-#endif
case 'f':
lcconf->racoon_conf = optarg;
break;
@@ -348,6 +213,9 @@ parse(ac, av)
case 'v':
vflag++;
break;
+ case 'V':
+ print_version();
+ break;
case 'Z':
/*
* only local test.
@@ -393,6 +261,89 @@ parse(ac, av)
usage();
/* NOTREACHED */
}
+}
+
+int
+main(ac, av)
+ int ac;
+ char **av;
+{
+ int error;
+
+ initlcconf();
+ parse(ac, av);
+
+ if (geteuid() != 0) {
+ errx(1, "must be root to invoke this program.");
+ /* NOTREACHED*/
+ }
+
+ /*
+ * Don't let anyone read files I write. Although some files (such as
+ * the PID file) can be other readable, we dare to use the global mask,
+ * because racoon uses fopen(3), which can't specify the permission
+ * at the creation time.
+ */
+ umask(077);
+ if (umask(077) != 077) {
+ errx(1, "could not set umask");
+ /* NOTREACHED*/
+ }
+
+#ifdef DEBUG_RECORD_MALLOCATION
+ DRM_init();
+#endif
+
+#ifdef HAVE_SECCTX
+ init_avc();
+#endif
+ eay_init();
+ initrmconf();
+ oakley_dhinit();
+ compute_vendorids();
+
+ ploginit();
+
+ plog(LLV_INFO, LOCATION, NULL, "%s\n", version);
+ plog(LLV_INFO, LOCATION, NULL, "@(#)"
+ "This product linked %s (http://www.openssl.org/)"
+ "\n", eay_version());
+ plog(LLV_INFO, LOCATION, NULL, "Reading configuration from \"%s\"\n",
+ lcconf->racoon_conf);
+
+ /*
+ * install SAs from the specified file. If the file is not specified
+ * by the configuration file, racoon will exit.
+ */
+ if (loading_sa && !f_local) {
+ if (backupsa_from_file() != 0)
+ errx(1, "something error happened "
+ "SA recovering.");
+ }
+
+ if (f_foreground)
+ close(0);
+ else {
+ if (daemon(0, 0) < 0) {
+ errx(1, "failed to be daemon. (%s)",
+ strerror(errno));
+ }
+#ifndef __linux__
+ /*
+ * In case somebody has started inetd manually, we need to
+ * clear the logname, so that old servers run as root do not
+ * get the user's logname..
+ */
+ if (setlogin("") < 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "cannot clear logname: %s\n", strerror(errno));
+ /* no big deal if it fails.. */
+ }
+#endif
+ }
- return;
+ session();
+
+ return 0;
}
+
diff --git a/src/racoon/misc.c b/src/racoon/misc.c
index 4daa0ed..91b8e77 100644
--- a/src/racoon/misc.c
+++ b/src/racoon/misc.c
@@ -1,4 +1,4 @@
-/* $NetBSD: misc.c,v 1.4.6.1 2008/07/15 00:55:48 mgrooms Exp $ */
+/* $NetBSD: misc.c,v 1.6 2008/07/15 00:47:09 mgrooms Exp $ */
/* $KAME: misc.c,v 1.23 2001/08/16 14:37:29 itojun Exp $ */
@@ -44,6 +44,7 @@
#include <errno.h>
#include <syslog.h>
#include <ctype.h>
+#include <fcntl.h>
#include "var.h"
#include "misc.h"
@@ -154,6 +155,16 @@ getfsize(path)
}
/*
+ * set the close-on-exec flag for file descriptor fd.
+ */
+void
+close_on_exec(fd)
+ int fd;
+{
+ fcntl(fd, F_SETFD, FD_CLOEXEC);
+}
+
+/*
* calculate the difference between two times.
* t1: start
* t2: end
diff --git a/src/racoon/misc.h b/src/racoon/misc.h
index 66e42b1..3e758d9 100644
--- a/src/racoon/misc.h
+++ b/src/racoon/misc.h
@@ -1,4 +1,4 @@
-/* $NetBSD: misc.h,v 1.4.6.1 2008/07/15 00:55:48 mgrooms Exp $ */
+/* $NetBSD: misc.h,v 1.6 2008/07/15 00:47:09 mgrooms Exp $ */
/* Id: misc.h,v 1.9 2006/04/06 14:00:06 manubsd Exp */
@@ -50,6 +50,7 @@ extern int getfsize __P((char *));
struct timeval;
extern double timedelta __P((struct timeval *, struct timeval *));
char *strdup __P((const char *));
+extern void close_on_exec __P((int fd));
#if defined(__APPLE__) && defined(__MACH__)
#define RACOON_TAILQ_FOREACH_REVERSE(var, head, headname ,field) \
diff --git a/src/racoon/nattraversal.c b/src/racoon/nattraversal.c
index 9fd4bcd..b04cc1b 100644
--- a/src/racoon/nattraversal.c
+++ b/src/racoon/nattraversal.c
@@ -1,4 +1,4 @@
-/* $NetBSD: nattraversal.c,v 1.6.6.2 2009/05/18 17:01:07 tteras Exp $ */
+/* $NetBSD: nattraversal.c,v 1.14 2011/03/14 17:18:13 tteras Exp $ */
/*
* Copyright (C) 2004 SuSE Linux AG, Nuernberg, Germany.
@@ -77,6 +77,7 @@ struct natt_ka_addrs {
};
static TAILQ_HEAD(_natt_ka_addrs, natt_ka_addrs) ka_tree;
+static struct sched sc_natt = SCHED_INITIALIZER();
/*
* check if the given vid is NAT-T.
@@ -126,10 +127,14 @@ natt_hash_addr (struct ph1handle *iph1, struct sockaddr *addr)
char *ptr;
void *addr_ptr, *addr_port;
size_t buf_size, addr_size;
+ int natt_force = 0;
+
+ if (iph1->rmconf != NULL && iph1->rmconf->nat_traversal == NATT_FORCE)
+ natt_force = 1;
plog (LLV_INFO, LOCATION, addr, "Hashing %s with algo #%d %s\n",
saddr2str(addr), iph1->approval->hashtype,
- (iph1->rmconf->nat_traversal == NATT_FORCE)?"(NAT-T forced)":"");
+ natt_force?"(NAT-T forced)":"");
if (addr->sa_family == AF_INET) {
addr_size = sizeof (struct in_addr); /* IPv4 address */
@@ -163,7 +168,7 @@ natt_hash_addr (struct ph1handle *iph1, struct sockaddr *addr)
ptr += sizeof (cookie_t);
/* Copy-in Address (or zeroes if NATT_FORCE) */
- if (iph1->rmconf->nat_traversal == NATT_FORCE)
+ if (natt_force)
memset (ptr, 0, addr_size);
else
memcpy (ptr, addr_ptr, addr_size);
@@ -186,7 +191,8 @@ natt_compare_addr_hash (struct ph1handle *iph1, vchar_t *natd_received,
u_int32_t flag;
int verified = 0;
- if (iph1->rmconf->nat_traversal == NATT_FORCE)
+ if (iph1->rmconf != NULL &&
+ iph1->rmconf->nat_traversal == NATT_FORCE)
return verified;
if (natd_seq == 0) {
@@ -302,9 +308,28 @@ natt_float_ports (struct ph1handle *iph1)
natt_keepalive_add_ph1 (iph1);
}
+static int
+natt_is_enabled (struct remoteconf *rmconf, void *args)
+{
+ if (rmconf->nat_traversal)
+ return 1;
+ return 0;
+}
+
void
natt_handle_vendorid (struct ph1handle *iph1, int vid_numeric)
{
+ if (iph1->rmconf == NULL) {
+ /* Check if any candidate remote conf allows nat-t */
+ struct rmconfselector rmconf;
+ rmconf_selector_from_ph1(&rmconf, iph1);
+ if (enumrmconf(&rmconf, natt_is_enabled, NULL) == 0)
+ return;
+ } else {
+ if (!iph1->rmconf->nat_traversal)
+ return;
+ }
+
if (! iph1->natt_options)
iph1->natt_options = racoon_calloc (1, sizeof (*iph1->natt_options));
@@ -330,7 +355,7 @@ natt_keepalive_delete (struct natt_ka_addrs *ka)
/* NAT keepalive functions */
static void
-natt_keepalive_send (void *param)
+natt_keepalive_send (struct sched *param)
{
struct natt_ka_addrs *ka, *next = NULL;
char keepalive_packet[] = { 0xff };
@@ -340,7 +365,7 @@ natt_keepalive_send (void *param)
for (ka = TAILQ_FIRST(&ka_tree); ka; ka = next) {
next = TAILQ_NEXT(ka, chain);
- s = getsockmyaddr(ka->src);
+ s = myaddr_getfd(ka->src);
if (s == -1) {
natt_keepalive_delete(ka);
continue;
@@ -354,7 +379,7 @@ natt_keepalive_send (void *param)
strerror (errno));
}
- sched_new (lcconf->natt_ka_interval, natt_keepalive_send, NULL);
+ sched_schedule (&sc_natt, lcconf->natt_ka_interval, natt_keepalive_send);
}
void
@@ -364,7 +389,7 @@ natt_keepalive_init (void)
/* To disable sending KAs set natt_ka_interval=0 */
if (lcconf->natt_ka_interval > 0)
- sched_new (lcconf->natt_ka_interval, natt_keepalive_send, NULL);
+ sched_schedule (&sc_natt, lcconf->natt_ka_interval, natt_keepalive_send);
}
int
@@ -373,8 +398,8 @@ natt_keepalive_add (struct sockaddr *src, struct sockaddr *dst)
struct natt_ka_addrs *ka = NULL, *new_addr;
TAILQ_FOREACH (ka, &ka_tree, chain) {
- if (cmpsaddrstrict(ka->src, src) == 0 &&
- cmpsaddrstrict(ka->dst, dst) == 0) {
+ if (cmpsaddr(ka->src, src) == CMPSADDR_MATCH &&
+ cmpsaddr(ka->dst, dst) == CMPSADDR_MATCH) {
ka->in_use++;
plog (LLV_INFO, LOCATION, NULL, "KA found: %s (in_use=%u)\n",
saddr2str_fromto("%s->%s", src, dst), ka->in_use);
@@ -437,8 +462,8 @@ natt_keepalive_remove (struct sockaddr *src, struct sockaddr *dst)
plog (LLV_DEBUG, LOCATION, NULL, "KA tree dump: %s (in_use=%u)\n",
saddr2str_fromto("%s->%s", src, dst), ka->in_use);
- if (cmpsaddrstrict(ka->src, src) == 0 &&
- cmpsaddrstrict(ka->dst, dst) == 0 &&
+ if (cmpsaddr(ka->src, src) == CMPSADDR_MATCH &&
+ cmpsaddr(ka->dst, dst) == CMPSADDR_MATCH &&
-- ka->in_use <= 0) {
plog (LLV_DEBUG, LOCATION, NULL, "KA removing this one...\n");
@@ -451,16 +476,16 @@ natt_keepalive_remove (struct sockaddr *src, struct sockaddr *dst)
}
}
-static struct remoteconf *
+static int
natt_enabled_in_rmconf_stub (struct remoteconf *rmconf, void *data)
{
- return (rmconf->nat_traversal ? rmconf : NULL);
+ return rmconf->nat_traversal ? 1 : 0;
}
int
natt_enabled_in_rmconf ()
{
- return foreachrmconf (natt_enabled_in_rmconf_stub, NULL) != NULL;
+ return enumrmconf(NULL, natt_enabled_in_rmconf_stub, NULL) != 0;
}
diff --git a/src/racoon/nattraversal.h b/src/racoon/nattraversal.h
index cec5815..3b0b03b 100644
--- a/src/racoon/nattraversal.h
+++ b/src/racoon/nattraversal.h
@@ -1,4 +1,4 @@
-/* $NetBSD: nattraversal.h,v 1.6 2006/09/09 16:22:09 manu Exp $ */
+/* $NetBSD: nattraversal.h,v 1.7 2010/09/22 07:34:51 vanhu Exp $ */
/*
* Copyright (C) 2004 SuSE Linux AG, Nuernberg, Germany.
@@ -42,12 +42,12 @@
#define NAT_KA_QUEUED (1L<<4)
#define NAT_ADD_NON_ESP_MARKER (1L<<5)
-#define NATT_AVAILABLE(ph1) ((iph1)->natt_flags & NAT_ANNOUNCED)
+#define NATT_AVAILABLE(_ph1) ((_ph1)->natt_flags & NAT_ANNOUNCED)
#define NAT_DETECTED (NAT_DETECTED_ME | NAT_DETECTED_PEER)
#define NON_ESP_MARKER_LEN sizeof(u_int32_t)
-#define NON_ESP_MARKER_USE(iph1) ((iph1)->natt_flags & NAT_ADD_NON_ESP_MARKER)
+#define NON_ESP_MARKER_USE(_ph1) ((_ph1)->natt_flags & NAT_ADD_NON_ESP_MARKER)
/* These are the values from parsing "remote {}"
block of the config file. */
diff --git a/src/racoon/oakley.c b/src/racoon/oakley.c
index 183ac2f..4a106df 100644
--- a/src/racoon/oakley.c
+++ b/src/racoon/oakley.c
@@ -1,4 +1,4 @@
-/* $NetBSD: oakley.c,v 1.9.6.4 2009/08/13 09:18:45 vanhu Exp $ */
+/* $NetBSD: oakley.c,v 1.22 2011/03/17 14:42:58 vanhu Exp $ */
/* Id: oakley.c,v 1.32 2006/05/26 12:19:46 manubsd Exp */
@@ -123,13 +123,63 @@ struct dhgroup dh_modp8192;
static int oakley_check_dh_pub __P((vchar_t *, vchar_t **));
static int oakley_compute_keymat_x __P((struct ph2handle *, int, int));
-static int get_cert_fromlocal __P((struct ph1handle *, int));
-static int get_plainrsa_fromlocal __P((struct ph1handle *, int));
static int oakley_check_certid __P((struct ph1handle *iph1));
static int check_typeofcertname __P((int, int));
-static cert_t *save_certbuf __P((struct isakmp_gen *));
-static cert_t *save_certx509 __P((X509 *));
static int oakley_padlen __P((int, int));
+static int get_plainrsa_fromlocal __P((struct ph1handle *, int));
+
+int oakley_get_certtype(cert)
+ vchar_t *cert;
+{
+ if (cert == NULL)
+ return ISAKMP_CERT_NONE;
+
+ return cert->v[0];
+}
+
+static vchar_t *
+dump_isakmp_payload(gen)
+ struct isakmp_gen *gen;
+{
+ vchar_t p;
+
+ if (ntohs(gen->len) <= sizeof(*gen)) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "Len is too small !!.\n");
+ return NULL;
+ }
+
+ p.v = (caddr_t) (gen + 1);
+ p.l = ntohs(gen->len) - sizeof(*gen);
+
+ return vdup(&p);
+}
+
+static vchar_t *
+dump_x509(cert)
+ X509 *cert;
+{
+ vchar_t *pl;
+ u_char *bp;
+ int len;
+
+ len = i2d_X509(cert, NULL);
+
+ pl = vmalloc(len + 1);
+ if (pl == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "Failed to copy CERT from packet.\n");
+ return NULL;
+ }
+
+ pl->v[0] = ISAKMP_CERT_X509SIGN;
+ bp = (u_char *) &pl->v[1];
+ i2d_X509(cert, &bp);
+
+ return pl;
+}
+
+
int
oakley_get_defaultlifetime()
@@ -418,7 +468,7 @@ oakley_hash(buf, iph1)
res = alg_oakley_hashdef_one(type, buf);
if (res == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
- "invalid hash algoriym %d.\n", type);
+ "invalid hash algorithm %d.\n", type);
return NULL;
}
@@ -858,7 +908,7 @@ oakley_ph1hash_common(iph1, sw)
+ (sw == GENERATE ? iph1->id->l : iph1->id_p->l);
#ifdef HAVE_GSSAPI
- if (AUTHMETHOD(iph1) == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB) {
+ if (iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB) {
if (iph1->gi_i != NULL && iph1->gi_r != NULL) {
bp = (sw == GENERATE ? iph1->gi_i : iph1->gi_r);
len += bp->l;
@@ -919,7 +969,7 @@ oakley_ph1hash_common(iph1, sw)
p += bp->l;
#ifdef HAVE_GSSAPI
- if (AUTHMETHOD(iph1) == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB) {
+ if (iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB) {
if (iph1->gi_i != NULL && iph1->gi_r != NULL) {
bp = (sw == GENERATE ? iph1->gi_i : iph1->gi_r);
memcpy(p, bp->v, bp->l);
@@ -980,7 +1030,7 @@ oakley_ph1hash_base_i(iph1, sw)
return NULL;
}
- switch (AUTHMETHOD(iph1)) {
+ switch (iph1->approval->authmethod) {
case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
@@ -989,7 +1039,7 @@ oakley_ph1hash_base_i(iph1, sw)
case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I:
case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
- case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I:
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I:
case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
#endif
if (iph1->skeyid == NULL) {
@@ -1121,7 +1171,7 @@ oakley_ph1hash_base_r(iph1, sw)
return NULL;
}
- switch(AUTHMETHOD(iph1)) {
+ switch (iph1->approval->authmethod) {
case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
#ifdef ENABLE_HYBRID
@@ -1133,7 +1183,7 @@ oakley_ph1hash_base_r(iph1, sw)
case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
- case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I:
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I:
#endif
break;
default:
@@ -1249,10 +1299,10 @@ oakley_validate_auth(iph1)
gettimeofday(&start, NULL);
#endif
- switch (AUTHMETHOD(iph1)) {
+ switch (iph1->approval->authmethod) {
case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
#ifdef ENABLE_HYBRID
- case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I:
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I:
case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
#endif
/* validate HASH */
@@ -1265,7 +1315,7 @@ oakley_validate_auth(iph1)
return ISAKMP_NTYPE_PAYLOAD_MALFORMED;
}
#ifdef ENABLE_HYBRID
- if (AUTHMETHOD(iph1) == FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I &&
+ if (iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I &&
((iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) == 0))
{
plog(LLV_ERROR, LOCATION, NULL, "No SIG was passed, "
@@ -1323,7 +1373,7 @@ oakley_validate_auth(iph1)
#endif
{
int error = 0;
- int certtype = 0;
+ int certtype;
/* validation */
if (iph1->id_p == NULL) {
@@ -1341,132 +1391,104 @@ oakley_validate_auth(iph1)
plogdump(LLV_DEBUG, iph1->sig_p->v, iph1->sig_p->l);
/* get peer's cert */
- switch (iph1->rmconf->getcert_method) {
- case ISAKMP_GETCERT_PAYLOAD:
+ certtype = oakley_get_certtype(iph1->rmconf->peerscert);
+ switch (certtype) {
+ case ISAKMP_CERT_NONE:
+ /* expect to receive one from peer */
if (iph1->cert_p == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
- "no peer's CERT payload found.\n");
+ "no peer's CERT payload found.\n");
return ISAKMP_INTERNAL_ERROR;
}
- break;
- case ISAKMP_GETCERT_LOCALFILE:
- switch (iph1->rmconf->certtype) {
- case ISAKMP_CERT_X509SIGN:
- if (iph1->rmconf->peerscertfile == NULL) {
- plog(LLV_ERROR, LOCATION, NULL,
- "no peer's CERT file found.\n");
- return ISAKMP_INTERNAL_ERROR;
- }
-
- /* don't use cached cert */
- if (iph1->cert_p != NULL) {
- oakley_delcert(iph1->cert_p);
- iph1->cert_p = NULL;
- }
-
- error = get_cert_fromlocal(iph1, 0);
-#ifdef ANDROID_PATCHED
- if (!error)
- break;
- default:
- return ISAKMP_INTERNAL_ERROR;
-#else
- break;
+ /* verify the cert if needed */
+ if (!iph1->rmconf->verify_cert)
+ break;
- case ISAKMP_CERT_PLAINRSA:
- error = get_plainrsa_fromlocal(iph1, 0);
- break;
- }
- if (error)
+ switch (oakley_get_certtype(iph1->cert_p)) {
+ case ISAKMP_CERT_X509SIGN: {
+ char path[MAXPATHLEN];
+ char *ca;
+
+ if (iph1->rmconf->cacertfile != NULL) {
+ getpathname(path, sizeof(path),
+ LC_PATHTYPE_CERT,
+ iph1->rmconf->cacertfile);
+ ca = path;
+ } else {
+ ca = NULL;
+ }
+
+ error = eay_check_x509cert(
+ iph1->cert_p,
+ lcconf->pathinfo[LC_PATHTYPE_CERT],
+ ca, 0);
+ break;
+ }
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "peers_cert certtype %d was not expected\n",
+ certtype);
return ISAKMP_INTERNAL_ERROR;
+ }
+
+ if (error != 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "the peer's certificate is not verified.\n");
+ return ISAKMP_NTYPE_INVALID_CERT_AUTHORITY;
+ }
break;
- case ISAKMP_GETCERT_DNS:
- if (iph1->rmconf->peerscertfile != NULL) {
+ case ISAKMP_CERT_X509SIGN:
+ if (iph1->rmconf->peerscert == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
- "why peer's CERT file is defined "
- "though getcert method is dns ?\n");
+ "no peer's CERT file found.\n");
return ISAKMP_INTERNAL_ERROR;
}
-
- /* don't use cached cert */
+ /* don't use received cert */
+ if (iph1->cert_p != NULL) {
+ vfree(iph1->cert_p);
+ iph1->cert_p = NULL;
+ }
+ /* copy from remoteconf instead */
+ iph1->cert_p = vdup(iph1->rmconf->peerscert);
+ break;
+#ifndef ANDROID_PATCHED
+ case ISAKMP_CERT_PLAINRSA:
+ if (get_plainrsa_fromlocal(iph1, 0))
+ return ISAKMP_INTERNAL_ERROR;
+ break;
+ case ISAKMP_CERT_DNS:
+ /* don't use received cert */
if (iph1->cert_p != NULL) {
- oakley_delcert(iph1->cert_p);
+ vfree(iph1->cert_p);
iph1->cert_p = NULL;
}
iph1->cert_p = dnssec_getcert(iph1->id_p);
if (iph1->cert_p == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
- "no CERT RR found.\n");
+ "no CERT RR found.\n");
return ISAKMP_INTERNAL_ERROR;
-#endif
}
break;
+#endif
default:
plog(LLV_ERROR, LOCATION, NULL,
- "invalid getcert_mothod: %d\n",
- iph1->rmconf->getcert_method);
+ "invalid certificate type: %d\n",
+ oakley_get_certtype(iph1->rmconf->peerscert));
return ISAKMP_INTERNAL_ERROR;
}
/* compare ID payload and certificate name */
- if (iph1->rmconf->verify_cert &&
- (error = oakley_check_certid(iph1)) != 0)
+ if ((error = oakley_check_certid(iph1)) != 0)
return error;
- /* verify certificate */
- if (iph1->rmconf->verify_cert
- && iph1->rmconf->getcert_method == ISAKMP_GETCERT_PAYLOAD) {
- certtype = iph1->rmconf->certtype;
-#ifdef ENABLE_HYBRID
- switch (AUTHMETHOD(iph1)) {
- case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
- case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
- certtype = iph1->cert_p->type;
- break;
- default:
- break;
- }
-#endif
- switch (certtype) {
- case ISAKMP_CERT_X509SIGN: {
- char path[MAXPATHLEN];
- char *ca;
-
- if (iph1->rmconf->cacertfile != NULL) {
- getpathname(path, sizeof(path),
- LC_PATHTYPE_CERT,
- iph1->rmconf->cacertfile);
- ca = path;
- } else {
- ca = NULL;
- }
-
- error = eay_check_x509cert(&iph1->cert_p->cert,
- lcconf->pathinfo[LC_PATHTYPE_CERT],
- ca, 0);
- break;
- }
-
- default:
- plog(LLV_ERROR, LOCATION, NULL,
- "no supported certtype %d\n", certtype);
- return ISAKMP_INTERNAL_ERROR;
- }
- if (error != 0) {
- plog(LLV_ERROR, LOCATION, NULL,
- "the peer's certificate is not verified.\n");
- return ISAKMP_NTYPE_INVALID_CERT_AUTHORITY;
- }
- }
-
- /* Generate a warning if verify_cert == 0
- */
- if (iph1->rmconf->verify_cert){
- plog(LLV_DEBUG, LOCATION, NULL, "CERT validated\n");
- }else{
+ /* Generate a warning if verify_cert */
+ if (iph1->rmconf->verify_cert) {
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "CERT validated\n");
+ } else {
plog(LLV_WARNING, LOCATION, NULL,
- "CERT validation disabled by configuration\n");
+ "CERT validation disabled by configuration\n");
}
/* compute hash */
@@ -1489,38 +1511,30 @@ oakley_validate_auth(iph1)
if (my_hash == NULL)
return ISAKMP_INTERNAL_ERROR;
-
- certtype = iph1->rmconf->certtype;
-#ifdef ENABLE_HYBRID
- switch (AUTHMETHOD(iph1)) {
- case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
- case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
- certtype = iph1->cert_p->type;
- break;
- default:
- break;
- }
-#endif
/* check signature */
+ certtype = oakley_get_certtype(iph1->cert_p);
+ if (certtype == ISAKMP_CERT_NONE)
+ certtype = oakley_get_certtype(iph1->rmconf->peerscert);
switch (certtype) {
case ISAKMP_CERT_X509SIGN:
case ISAKMP_CERT_DNS:
error = eay_check_x509sign(my_hash,
- iph1->sig_p,
- &iph1->cert_p->cert);
+ iph1->sig_p,
+ iph1->cert_p);
break;
#ifndef ANDROID_PATCHED
case ISAKMP_CERT_PLAINRSA:
iph1->rsa_p = rsa_try_check_rsasign(my_hash,
iph1->sig_p, iph1->rsa_candidates);
error = iph1->rsa_p ? 0 : -1;
-
+ genlist_free(iph1->rsa_candidates, NULL);
+ iph1->rsa_candidates = NULL;
break;
#endif
default:
plog(LLV_ERROR, LOCATION, NULL,
- "no supported certtype %d\n",
- certtype);
+ "cannot check signature for certtype %d\n",
+ certtype);
vfree(my_hash);
return ISAKMP_INTERNAL_ERROR;
}
@@ -1634,115 +1648,26 @@ int
oakley_getmycert(iph1)
struct ph1handle *iph1;
{
- switch (iph1->rmconf->certtype) {
- case ISAKMP_CERT_X509SIGN:
- if (iph1->cert)
- return 0;
- return get_cert_fromlocal(iph1, 1);
-
-#ifndef ANDROID_PATCHED
- case ISAKMP_CERT_PLAINRSA:
- if (iph1->rsa)
- return 0;
- return get_plainrsa_fromlocal(iph1, 1);
-#endif
-
- default:
- plog(LLV_ERROR, LOCATION, NULL,
- "Unknown certtype #%d\n",
- iph1->rmconf->certtype);
- return -1;
- }
-
-}
-
-/*
- * get a CERT from local file.
- * IN:
- * my != 0 my cert.
- * my == 0 peer's cert.
- */
-static int
-get_cert_fromlocal(iph1, my)
- struct ph1handle *iph1;
- int my;
-{
- char path[MAXPATHLEN];
- vchar_t *cert = NULL;
- cert_t **certpl;
- char *certfile;
- int error = -1;
-
- if (my) {
- certfile = iph1->rmconf->mycertfile;
- certpl = &iph1->cert;
- } else {
- certfile = iph1->rmconf->peerscertfile;
- certpl = &iph1->cert_p;
- }
- if (!certfile) {
- plog(LLV_ERROR, LOCATION, NULL, "no CERT defined.\n");
- return 0;
- }
-
- switch (iph1->rmconf->certtype) {
+ switch (oakley_get_certtype(iph1->rmconf->mycert)) {
case ISAKMP_CERT_X509SIGN:
- case ISAKMP_CERT_DNS:
- /* make public file name */
- getpathname(path, sizeof(path), LC_PATHTYPE_CERT, certfile);
- cert = eay_get_x509cert(path);
- if (cert) {
- char *p = NULL;
- p = eay_get_x509text(cert);
- plog(LLV_DEBUG, LOCATION, NULL, "%s", p ? p : "\n");
- racoon_free(p);
- };
+ if (iph1->cert)
+ return 0;
+ iph1->cert = vdup(iph1->rmconf->mycert);
break;
-
+#ifndef ANDROID_PATCHED
+ case ISAKMP_CERT_PLAINRSA:
+ if (iph1->rsa)
+ return 0;
+ return get_plainrsa_fromlocal(iph1, 1);
+#endif
default:
plog(LLV_ERROR, LOCATION, NULL,
- "not supported certtype %d\n",
- iph1->rmconf->certtype);
- goto end;
- }
-
- if (!cert) {
- plog(LLV_ERROR, LOCATION, NULL,
- "failed to get %s CERT.\n",
- my ? "my" : "peers");
- goto end;
- }
-
- *certpl = oakley_newcert();
- if (!*certpl) {
- plog(LLV_ERROR, LOCATION, NULL,
- "failed to get cert buffer.\n");
- goto end;
- }
- (*certpl)->pl = vmalloc(cert->l + 1);
- if ((*certpl)->pl == NULL) {
- plog(LLV_ERROR, LOCATION, NULL,
- "failed to get cert buffer\n");
- oakley_delcert(*certpl);
- *certpl = NULL;
- goto end;
+ "Unknown certtype #%d\n",
+ oakley_get_certtype(iph1->rmconf->mycert));
+ return -1;
}
- memcpy((*certpl)->pl->v + 1, cert->v, cert->l);
- (*certpl)->pl->v[0] = iph1->rmconf->certtype;
- (*certpl)->type = iph1->rmconf->certtype;
- (*certpl)->cert.v = (*certpl)->pl->v + 1;
- (*certpl)->cert.l = (*certpl)->pl->l - 1;
-
- plog(LLV_DEBUG, LOCATION, NULL, "created CERT payload:\n");
- plogdump(LLV_DEBUG, (*certpl)->pl->v, (*certpl)->pl->l);
-
- error = 0;
-
-end:
- if (cert != NULL)
- vfree(cert);
- return error;
+ return 0;
}
#ifndef ANDROID_PATCHED
@@ -1808,7 +1733,7 @@ oakley_getsign(iph1)
vchar_t *privkey = NULL;
int error = -1;
- switch (iph1->rmconf->certtype) {
+ switch (oakley_get_certtype(iph1->rmconf->mycert)) {
case ISAKMP_CERT_X509SIGN:
case ISAKMP_CERT_DNS:
if (iph1->rmconf->myprivfile == NULL) {
@@ -1828,7 +1753,6 @@ oakley_getsign(iph1)
}
plog(LLV_DEBUG2, LOCATION, NULL, "private key:\n");
plogdump(LLV_DEBUG2, privkey->v, privkey->l);
-
iph1->sig = eay_get_x509sign(iph1->hash, privkey);
break;
#ifndef ANDROID_PATCHED
@@ -1839,7 +1763,7 @@ oakley_getsign(iph1)
default:
plog(LLV_ERROR, LOCATION, NULL,
"Unknown certtype #%d\n",
- iph1->rmconf->certtype);
+ oakley_get_certtype(iph1->rmconf->mycert));
goto end;
}
@@ -1873,8 +1797,11 @@ oakley_check_certid(iph1)
int idlen, type;
int error;
+ if (iph1->rmconf == NULL || iph1->rmconf->verify_cert == FALSE)
+ return 0;
+
if (iph1->id_p == NULL || iph1->cert_p == NULL) {
- plog(LLV_ERROR, LOCATION, NULL, "no ID nor CERT found.\n");
+ plog(LLV_ERROR, LOCATION, iph1->remote, "no ID nor CERT found.\n");
return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
}
@@ -1883,27 +1810,30 @@ oakley_check_certid(iph1)
switch (id_b->type) {
case IPSECDOI_ID_DER_ASN1_DN:
- name = eay_get_x509asn1subjectname(&iph1->cert_p->cert);
+ name = eay_get_x509asn1subjectname(iph1->cert_p);
if (!name) {
- plog(LLV_ERROR, LOCATION, NULL,
+ plog(LLV_ERROR, LOCATION, iph1->remote,
"failed to get subjectName\n");
return ISAKMP_NTYPE_INVALID_CERTIFICATE;
}
if (idlen != name->l) {
- plog(LLV_ERROR, LOCATION, NULL,
+ plog(LLV_ERROR, LOCATION, iph1->remote,
"Invalid ID length in phase 1.\n");
vfree(name);
return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
}
error = memcmp(id_b + 1, name->v, idlen);
- vfree(name);
if (error != 0) {
- plog(LLV_ERROR, LOCATION, NULL,
+ plog(LLV_ERROR, LOCATION, iph1->remote,
"ID mismatched with ASN1 SubjectName.\n");
plogdump(LLV_DEBUG, id_b + 1, idlen);
plogdump(LLV_DEBUG, name->v, idlen);
- return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
+ if (iph1->rmconf->verify_identifier) {
+ vfree(name);
+ return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
+ }
}
+ vfree(name);
return 0;
case IPSECDOI_ID_IPV4_ADDR:
case IPSECDOI_ID_IPV6_ADDR:
@@ -1918,7 +1848,7 @@ oakley_check_certid(iph1)
int pos;
for (pos = 1; ; pos++) {
- if (eay_get_x509subjectaltname(&iph1->cert_p->cert,
+ if (eay_get_x509subjectaltname(iph1->cert_p,
&altname, &type, pos) !=0) {
plog(LLV_ERROR, LOCATION, NULL,
"failed to get subjectAltName\n");
@@ -1944,10 +1874,11 @@ oakley_check_certid(iph1)
hints.ai_socktype = SOCK_RAW;
hints.ai_flags = AI_NUMERICHOST;
error = getaddrinfo(altname, NULL, &hints, &res);
+ racoon_free(altname);
+ altname = NULL;
if (error != 0) {
plog(LLV_ERROR, LOCATION, NULL,
"no proper subjectAltName.\n");
- racoon_free(altname);
return ISAKMP_NTYPE_INVALID_CERTIFICATE;
}
switch (res->ai_family) {
@@ -1962,7 +1893,6 @@ oakley_check_certid(iph1)
default:
plog(LLV_ERROR, LOCATION, NULL,
"family not supported: %d.\n", res->ai_family);
- racoon_free(altname);
freeaddrinfo(res);
return ISAKMP_NTYPE_INVALID_CERTIFICATE;
}
@@ -1974,7 +1904,8 @@ oakley_check_certid(iph1)
"ID mismatched with subjectAltName.\n");
plogdump(LLV_DEBUG, id_b + 1, idlen);
plogdump(LLV_DEBUG, a, idlen);
- return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
+ if (iph1->rmconf->verify_identifier)
+ return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
}
return 0;
}
@@ -1984,7 +1915,7 @@ oakley_check_certid(iph1)
int pos;
for (pos = 1; ; pos++) {
- if (eay_get_x509subjectaltname(&iph1->cert_p->cert,
+ if (eay_get_x509subjectaltname(iph1->cert_p,
&altname, &type, pos) != 0){
plog(LLV_ERROR, LOCATION, NULL,
"failed to get subjectAltName\n");
@@ -2078,7 +2009,7 @@ oakley_savecert(iph1, gen)
struct ph1handle *iph1;
struct isakmp_gen *gen;
{
- cert_t **c;
+ vchar_t **c;
u_int8_t type;
STACK_OF(X509) *certs=NULL;
PKCS7 *p7;
@@ -2173,7 +2104,7 @@ oakley_savecert(iph1, gen)
"Trying PKCS#7 cert %d.\n", i);
/* We'll just try each cert in turn */
- *c = save_certx509(cert);
+ *c = dump_x509(cert);
if (!*c) {
plog(LLV_ERROR, LOCATION, NULL,
@@ -2185,19 +2116,18 @@ oakley_savecert(iph1, gen)
* XXX If verify cert is disabled, we still just take
* the first certificate....
*/
- if(iph1->rmconf->verify_cert &&
- oakley_check_certid(iph1)) {
+ if (oakley_check_certid(iph1)) {
plog(LLV_DEBUG, LOCATION, NULL,
"Discarding CERT: does not match ID.\n");
- oakley_delcert((*c));
+ vfree((*c));
*c = NULL;
continue;
}
{
- char *p = eay_get_x509text(&(*c)->cert);
+ char *p = eay_get_x509text(*c);
plog(LLV_DEBUG, LOCATION, NULL, "CERT saved:\n");
- plogdump(LLV_DEBUG, (*c)->cert.v, (*c)->cert.l);
+ plogdump(LLV_DEBUG, (*c)->v, (*c)->l);
plog(LLV_DEBUG, LOCATION, NULL, "%s",
p ? p : "\n");
racoon_free(p);
@@ -2205,21 +2135,15 @@ oakley_savecert(iph1, gen)
break;
}
PKCS7_free(p7);
-
} else {
- *c = save_certbuf(gen);
+ *c = dump_isakmp_payload(gen);
if (!*c) {
plog(LLV_ERROR, LOCATION, NULL,
"Failed to get CERT buffer.\n");
return -1;
}
- switch ((*c)->type) {
- case ISAKMP_CERT_DNS:
- plog(LLV_WARNING, LOCATION, NULL,
- "CERT payload is unnecessary in DNSSEC. "
- "ignore it.\n");
- return 0;
+ switch (type) {
case ISAKMP_CERT_PGP:
case ISAKMP_CERT_X509SIGN:
case ISAKMP_CERT_KERBEROS:
@@ -2228,33 +2152,32 @@ oakley_savecert(iph1, gen)
* XXX If verify cert is disabled, we still just take
* the first certificate....
*/
- if(iph1->rmconf->verify_cert &&
- oakley_check_certid(iph1)){
+ if (oakley_check_certid(iph1)){
plog(LLV_DEBUG, LOCATION, NULL,
"Discarding CERT: does not match ID.\n");
- oakley_delcert((*c));
+ vfree((*c));
*c = NULL;
return 0;
}
{
- char *p = eay_get_x509text(&(*c)->cert);
+ char *p = eay_get_x509text(*c);
plog(LLV_DEBUG, LOCATION, NULL, "CERT saved:\n");
- plogdump(LLV_DEBUG, (*c)->cert.v, (*c)->cert.l);
+ plogdump(LLV_DEBUG, (*c)->v, (*c)->l);
plog(LLV_DEBUG, LOCATION, NULL, "%s", p ? p : "\n");
racoon_free(p);
}
break;
case ISAKMP_CERT_CRL:
plog(LLV_DEBUG, LOCATION, NULL, "CRL saved:\n");
- plogdump(LLV_DEBUG, (*c)->cert.v, (*c)->cert.l);
+ plogdump(LLV_DEBUG, (*c)->v, (*c)->l);
break;
case ISAKMP_CERT_X509KE:
case ISAKMP_CERT_X509ATTR:
case ISAKMP_CERT_ARL:
default:
/* XXX */
- oakley_delcert((*c));
+ vfree(*c);
*c = NULL;
return 0;
}
@@ -2271,11 +2194,11 @@ oakley_savecr(iph1, gen)
struct ph1handle *iph1;
struct isakmp_gen *gen;
{
- cert_t **c;
+ vchar_t *cert;
+ vchar_t **c;
u_int8_t type;
type = *(u_int8_t *)(gen + 1) & 0xff;
-
switch (type) {
case ISAKMP_CERT_DNS:
plog(LLV_WARNING, LOCATION, NULL,
@@ -2301,119 +2224,109 @@ oakley_savecr(iph1, gen)
return -1;
}
- *c = save_certbuf(gen);
- if (!*c) {
+ /* Already found an acceptable CR? */
+ if (*c != NULL)
+ return 0;
+
+ cert = dump_isakmp_payload(gen);
+ if (cert == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
"Failed to get CR buffer.\n");
return -1;
}
- plog(LLV_DEBUG, LOCATION, NULL, "CR saved:\n");
- plogdump(LLV_DEBUG, (*c)->cert.v, (*c)->cert.l);
+ plog(LLV_DEBUG, LOCATION, NULL, "CR received:\n");
+ plogdump(LLV_DEBUG, cert->v, cert->l);
+ *c = cert;
+ if (resolveph1rmconf(iph1) == 0) {
+ /* Found unique match */
+ plog(LLV_DEBUG, LOCATION, NULL, "CR saved.\n");
+ } else {
+ /* Still ambiguous or matches nothing, ignore this CR */
+ *c = NULL;
+ vfree(cert);
+ }
return 0;
}
-static cert_t *
-save_certbuf(gen)
- struct isakmp_gen *gen;
+/*
+ * Add a single CR.
+ */
+struct append_cr_ctx {
+ struct ph1handle *iph1;
+ struct payload_list *plist;
+};
+
+static int
+oakley_append_rmconf_cr(rmconf, ctx)
+ struct remoteconf *rmconf;
+ void *ctx;
{
- cert_t *new;
+ struct append_cr_ctx *actx = (struct append_cr_ctx *) ctx;
+ vchar_t *buf, *asn1dn = NULL;
+ int type;
- if(ntohs(gen->len) <= sizeof(*gen)){
- plog(LLV_ERROR, LOCATION, NULL,
- "Len is too small !!.\n");
- return NULL;
- }
+ /* Do we want to send CR about this? */
+ if (rmconf->send_cr == FALSE)
+ return 0;
- new = oakley_newcert();
- if (!new) {
- plog(LLV_ERROR, LOCATION, NULL,
- "Failed to get CERT buffer.\n");
- return NULL;
- }
+ if (rmconf->peerscert != NULL) {
+ type = oakley_get_certtype(rmconf->peerscert);
+ asn1dn = eay_get_x509asn1issuername(rmconf->peerscert);
+ } else if (rmconf->cacert != NULL) {
+ type = oakley_get_certtype(rmconf->cacert);
+ asn1dn = eay_get_x509asn1subjectname(rmconf->cacert);
+ } else
+ return 0;
- new->pl = vmalloc(ntohs(gen->len) - sizeof(*gen));
- if (new->pl == NULL) {
- plog(LLV_ERROR, LOCATION, NULL,
- "Failed to copy CERT from packet.\n");
- oakley_delcert(new);
- new = NULL;
- return NULL;
+ if (asn1dn == NULL) {
+ plog(LLV_ERROR, LOCATION, actx->iph1->remote,
+ "Failed to get CR ASN1 DN from certificate\n");
+ return 0;
}
- memcpy(new->pl->v, gen + 1, new->pl->l);
- new->type = new->pl->v[0] & 0xff;
- new->cert.v = new->pl->v + 1;
- new->cert.l = new->pl->l - 1;
- return new;
-}
+ buf = vmalloc(1 + asn1dn->l);
+ if (buf == NULL)
+ goto err;
-static cert_t *
-save_certx509(cert)
- X509 *cert;
-{
- cert_t *new;
- int len;
- u_char *bp;
+ buf->v[0] = type;
+ memcpy(&buf->v[1], asn1dn->v, asn1dn->l);
- new = oakley_newcert();
- if (!new) {
- plog(LLV_ERROR, LOCATION, NULL,
- "Failed to get CERT buffer.\n");
- return NULL;
- }
+ plog(LLV_DEBUG, LOCATION, actx->iph1->remote,
+ "appending CR: %s\n",
+ s_isakmp_certtype(buf->v[0]));
+ plogdump(LLV_DEBUG, buf->v, buf->l);
- len = i2d_X509(cert, NULL);
- new->pl = vmalloc(len);
- if (new->pl == NULL) {
- plog(LLV_ERROR, LOCATION, NULL,
- "Failed to copy CERT from packet.\n");
- oakley_delcert(new);
- new = NULL;
- return NULL;
- }
- bp = (u_char *) new->pl->v;
- len = i2d_X509(cert, &bp);
- new->type = ISAKMP_CERT_X509SIGN;
- new->cert.v = new->pl->v;
- new->cert.l = new->pl->l;
+ actx->plist = isakmp_plist_append_full(actx->plist, buf, ISAKMP_NPTYPE_CR, 1);
- return new;
+err:
+ vfree(asn1dn);
+ return 0;
}
/*
- * get my CR.
- * NOTE: No Certificate Authority field is included to CR payload at the
- * moment. Becuase any certificate authority are accepted without any check.
- * The section 3.10 in RFC2408 says that this field SHOULD not be included,
- * if there is no specific certificate authority requested.
+ * Append list of acceptable CRs.
+ * RFC2048 3.10
*/
-vchar_t *
-oakley_getcr(iph1)
+struct payload_list *
+oakley_append_cr(plist, iph1)
+ struct payload_list *plist;
struct ph1handle *iph1;
{
- vchar_t *buf;
-
- buf = vmalloc(1);
- if (buf == NULL) {
- plog(LLV_ERROR, LOCATION, NULL,
- "failed to get cr buffer\n");
- return NULL;
- }
- if(iph1->rmconf->certtype == ISAKMP_CERT_NONE) {
- buf->v[0] = iph1->rmconf->cacerttype;
- plog(LLV_DEBUG, LOCATION, NULL, "create my CR: NONE, using %s instead\n",
- s_isakmp_certtype(iph1->rmconf->cacerttype));
+ struct append_cr_ctx ctx;
+ struct rmconfselector sel;
+
+ ctx.iph1 = iph1;
+ ctx.plist = plist;
+ if (iph1->rmconf == NULL) {
+ rmconf_selector_from_ph1(&sel, iph1);
+ enumrmconf(&sel, oakley_append_rmconf_cr, &ctx);
} else {
- buf->v[0] = iph1->rmconf->certtype;
- plog(LLV_DEBUG, LOCATION, NULL, "create my CR: %s\n",
- s_isakmp_certtype(iph1->rmconf->certtype));
+ oakley_append_rmconf_cr(iph1->rmconf, &ctx);
}
- if (buf->l > 1)
- plogdump(LLV_DEBUG, buf->v, buf->l);
- return buf;
+ return ctx.plist;
}
/*
@@ -2423,17 +2336,20 @@ int
oakley_checkcr(iph1)
struct ph1handle *iph1;
{
+ int type;
+
if (iph1->cr_p == NULL)
return 0;
plog(LLV_DEBUG, LOCATION, iph1->remote,
"peer transmitted CR: %s\n",
- s_isakmp_certtype(iph1->cr_p->type));
+ s_isakmp_certtype(oakley_get_certtype(iph1->cr_p)));
- if (iph1->cr_p->type != iph1->rmconf->certtype) {
+ type = oakley_get_certtype(iph1->cr_p);
+ if (type != oakley_get_certtype(iph1->rmconf->mycert)) {
plog(LLV_ERROR, LOCATION, iph1->remote,
- "such a cert type isn't supported: %d\n",
- (char)iph1->cr_p->type);
+ "such a cert type isn't supported: %d\n",
+ type);
return -1;
}
@@ -2482,10 +2398,10 @@ oakley_skeyid(iph1)
int error = -1;
/* SKEYID */
- switch (AUTHMETHOD(iph1)) {
+ switch (iph1->approval->authmethod) {
case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
#ifdef ENABLE_HYBRID
- case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I:
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I:
case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
#endif
if (iph1->etype != ISAKMP_ETYPE_IDENT) {
@@ -2748,7 +2664,7 @@ oakley_compute_enckey(iph1)
iph1->approval->encklen);
if (keylen == -1) {
plog(LLV_ERROR, LOCATION, NULL,
- "invalid encryption algoritym %d, "
+ "invalid encryption algorithm %d, "
"or invalid key length %d.\n",
iph1->approval->enctype,
iph1->approval->encklen);
@@ -2852,7 +2768,7 @@ oakley_compute_enckey(iph1)
if (iph1->approval->enctype > ARRAYLEN(oakley_encdef)
|| oakley_encdef[iph1->approval->enctype].weakkey == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
- "encryption algoritym %d isn't supported.\n",
+ "encryption algorithm %d isn't supported.\n",
iph1->approval->enctype);
goto end;
}
@@ -2872,36 +2788,6 @@ end:
return error;
}
-/* allocated new buffer for CERT */
-cert_t *
-oakley_newcert()
-{
- cert_t *new;
-
- new = racoon_calloc(1, sizeof(*new));
- if (new == NULL) {
- plog(LLV_ERROR, LOCATION, NULL,
- "failed to get cert's buffer\n");
- return NULL;
- }
-
- new->pl = NULL;
-
- return new;
-}
-
-/* delete buffer for CERT */
-void
-oakley_delcert(cert)
- cert_t *cert;
-{
- if (!cert)
- return;
- if (cert->pl)
- VPTRINIT(cert->pl);
- racoon_free(cert);
-}
-
/*
* compute IV and set to ph1handle
* IV = hash(g^xi | g^xr)
@@ -2956,7 +2842,7 @@ oakley_newiv(iph1)
newivm->iv->l = alg_oakley_encdef_blocklen(iph1->approval->enctype);
if (newivm->iv->l == -1) {
plog(LLV_ERROR, LOCATION, NULL,
- "invalid encryption algoriym %d.\n",
+ "invalid encryption algorithm %d.\n",
iph1->approval->enctype);
vfree(buf);
oakley_delivm(newivm);
@@ -3038,7 +2924,7 @@ oakley_newiv2(iph1, msgid)
newivm->iv->l = alg_oakley_encdef_blocklen(iph1->approval->enctype);
if (newivm->iv->l == -1) {
plog(LLV_ERROR, LOCATION, NULL,
- "invalid encryption algoriym %d.\n",
+ "invalid encryption algorithm %d.\n",
iph1->approval->enctype);
goto end;
}
@@ -3102,7 +2988,7 @@ oakley_do_decrypt(iph1, msg, ivdp, ivep)
blen = alg_oakley_encdef_blocklen(iph1->approval->enctype);
if (blen == -1) {
plog(LLV_ERROR, LOCATION, NULL,
- "invalid encryption algoriym %d.\n",
+ "invalid encryption algorithm %d.\n",
iph1->approval->enctype);
goto end;
}
@@ -3224,7 +3110,7 @@ oakley_do_encrypt(iph1, msg, ivep, ivp)
blen = alg_oakley_encdef_blocklen(iph1->approval->enctype);
if (blen == -1) {
plog(LLV_ERROR, LOCATION, NULL,
- "invalid encryption algoriym %d.\n",
+ "invalid encryption algorithm %d.\n",
iph1->approval->enctype);
goto end;
}
diff --git a/src/racoon/oakley.h b/src/racoon/oakley.h
index a8dbbd2..f8cdb76 100644
--- a/src/racoon/oakley.h
+++ b/src/racoon/oakley.h
@@ -1,4 +1,4 @@
-/* $NetBSD: oakley.h,v 1.5 2006/10/06 12:02:27 manu Exp $ */
+/* $NetBSD: oakley.h,v 1.7 2009/03/12 10:57:26 tteras Exp $ */
/* Id: oakley.h,v 1.13 2005/05/30 20:12:43 fredsen Exp */
@@ -89,21 +89,18 @@
#define OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R 65010
#endif
- /* 65500 -> still private
- * to avoid clash with GSSAPI_KRB below
- */
-#define FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I 65500
+/*
+ * The following are valid when the Vendor ID is one of
+ * the following:
+ *
+ * MD5("A GSS-API Authentication Method for IKE")
+ * MD5("GSSAPI") (recognized by Windows 2000)
+ * MD5("MS NT5 ISAKMPOAKLEY") (sent by Windows 2000)
+ */
+#define OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB (65001 + 0x10000)
+#define OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB_REAL 65001
- /*
- * The following are valid when the Vendor ID is one of
- * the following:
- *
- * MD5("A GSS-API Authentication Method for IKE")
- * MD5("GSSAPI") (recognized by Windows 2000)
- * MD5("MS NT5 ISAKMPOAKLEY") (sent by Windows 2000)
- */
-#define OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB 65001
#define OAKLEY_ATTR_GRP_DESC 4 /* B */
#define OAKLEY_ATTR_GRP_DESC_MODP768 1
#define OAKLEY_ATTR_GRP_DESC_MODP1024 2
@@ -163,13 +160,6 @@ struct dhgroup {
vchar_t *order;
};
-/* certificate holder */
-typedef struct cert_t_tag {
- u_int8_t type; /* type of CERT, must be same to pl->v[0]*/
- vchar_t cert; /* pointer to the CERT */
- vchar_t *pl; /* CERT payload minus isakmp general header */
-} cert_t;
-
struct ph1handle;
struct ph2handle;
struct isakmp_ivm;
@@ -200,10 +190,13 @@ extern vchar_t *oakley_ph1hash_common __P((struct ph1handle *, int));
extern vchar_t *oakley_ph1hash_base_i __P((struct ph1handle *, int));
extern vchar_t *oakley_ph1hash_base_r __P((struct ph1handle *, int));
+extern int oakley_get_certtype __P((vchar_t *));
extern int oakley_validate_auth __P((struct ph1handle *));
extern int oakley_getmycert __P((struct ph1handle *));
extern int oakley_getsign __P((struct ph1handle *));
extern vchar_t *oakley_getcr __P((struct ph1handle *));
+extern struct payload_list *oakley_append_cr __P((struct payload_list *,
+ struct ph1handle *));
extern int oakley_checkcr __P((struct ph1handle *));
extern int oakley_needcr __P((int));
struct isakmp_gen;
@@ -214,8 +207,6 @@ extern int oakley_skeyid __P((struct ph1handle *));
extern int oakley_skeyid_dae __P((struct ph1handle *));
extern int oakley_compute_enckey __P((struct ph1handle *));
-extern cert_t *oakley_newcert __P((void));
-extern void oakley_delcert __P((cert_t *));
extern int oakley_newiv __P((struct ph1handle *));
extern struct isakmp_ivm *oakley_newiv2 __P((struct ph1handle *, u_int32_t));
extern void oakley_delivm __P((struct isakmp_ivm *));
@@ -224,20 +215,4 @@ extern vchar_t *oakley_do_decrypt __P((struct ph1handle *,
extern vchar_t *oakley_do_encrypt __P((struct ph1handle *,
vchar_t *, vchar_t *, vchar_t *));
-#ifdef ENABLE_HYBRID
-#define AUTHMETHOD(iph1) \
- (((iph1)->rmconf->xauth && \
- (iph1)->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I) ? \
- FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I : (iph1)->approval->authmethod)
-#define RMAUTHMETHOD(iph1) \
- (((iph1)->rmconf->xauth && \
- (iph1)->rmconf->proposal->authmethod == \
- OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I) ? \
- FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I : \
- (iph1)->rmconf->proposal->authmethod)
-#else
-#define AUTHMETHOD(iph1) (iph1)->approval->authmethod
-#define RMAUTHMETHOD(iph1) (iph1)->rmconf->proposal->authmethod
-#endif /* ENABLE_HYBRID */
-
#endif /* _OAKLEY_H */
diff --git a/src/racoon/pfkey.c b/src/racoon/pfkey.c
index e73acc8..e69cb94 100644
--- a/src/racoon/pfkey.c
+++ b/src/racoon/pfkey.c
@@ -1,11 +1,11 @@
-/* $NetBSD: pfkey.c,v 1.18.4.5 2008/03/05 22:14:24 mgrooms Exp $ */
+/* $NetBSD: pfkey.c,v 1.57 2011/03/15 13:20:14 vanhu Exp $ */
-/* $Id: pfkey.c,v 1.18.4.5 2008/03/05 22:14:24 mgrooms Exp $ */
+/* $Id: pfkey.c,v 1.57 2011/03/15 13:20:14 vanhu Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -17,7 +17,7 @@
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -77,6 +77,7 @@
#include "vmbuf.h"
#include "plog.h"
#include "sockmisc.h"
+#include "session.h"
#include "debug.h"
#include "schedule.h"
@@ -94,6 +95,7 @@
#include "algorithm.h"
#include "sainfo.h"
#include "admin.h"
+#include "evt.h"
#include "privsep.h"
#include "strnames.h"
#include "backupsa.h"
@@ -129,6 +131,9 @@ static int pk_recvspdexpire __P((caddr_t *));
static int pk_recvspdget __P((caddr_t *));
static int pk_recvspddump __P((caddr_t *));
static int pk_recvspdflush __P((caddr_t *));
+#if defined(SADB_X_MIGRATE) && defined(SADB_X_EXT_KMADDRESS)
+static int pk_recvmigrate __P((caddr_t *));
+#endif
static struct sadb_msg *pk_recv __P((int, int *));
static int (*pkrecvf[]) __P((caddr_t *)) = {
@@ -156,17 +161,21 @@ NULL, /* SADB_X_SPDSETIDX */
pk_recvspdexpire,
NULL, /* SADB_X_SPDDELETE2 */
NULL, /* SADB_X_NAT_T_NEW_MAPPING */
+#if defined(SADB_X_MIGRATE) && defined(SADB_X_EXT_KMADDRESS)
+pk_recvmigrate,
+#else
NULL, /* SADB_X_MIGRATE */
+#endif
#if (SADB_MAX > 24)
#error "SADB extra message?"
#endif
};
-static int addnewsp __P((caddr_t *));
+static int addnewsp __P((caddr_t *, struct sockaddr *, struct sockaddr *));
/* cope with old kame headers - ugly */
#ifndef SADB_X_AALG_MD5
-#define SADB_X_AALG_MD5 SADB_AALG_MD5
+#define SADB_X_AALG_MD5 SADB_AALG_MD5
#endif
#ifndef SADB_X_AALG_SHA
#define SADB_X_AALG_SHA SADB_AALG_SHA
@@ -192,8 +201,10 @@ static int addnewsp __P((caddr_t *));
* 0: success
* -1: fail
*/
-int
-pfkey_handler()
+static int
+pfkey_handler(ctx, fd)
+ void *ctx;
+ int fd;
{
struct sadb_msg *msg;
int len;
@@ -202,9 +213,16 @@ pfkey_handler()
/* receive pfkey message. */
len = 0;
- msg = (struct sadb_msg *)pk_recv(lcconf->sock_pfkey, &len);
+ msg = (struct sadb_msg *) pk_recv(fd, &len);
if (msg == NULL) {
if (len < 0) {
+ /* do not report EAGAIN as error; well get
+ * called from main loop later. and it's normal
+ * when spd dump is received during reload and
+ * this function is called in loop. */
+ if (errno == EAGAIN)
+ goto end;
+
plog(LLV_ERROR, LOCATION, NULL,
"failed to recv from pfkey (%s)\n",
strerror(errno));
@@ -215,7 +233,7 @@ pfkey_handler()
}
}
- plog(LLV_DEBUG, LOCATION, NULL, "get pfkey %s message\n",
+ plog(LLV_DEBUG, LOCATION, NULL, "got pfkey %s message\n",
s_pfkey_type(msg->sadb_msg_type));
plogdump(LLV_DEBUG2, msg, msg->sadb_msg_len << 3);
@@ -271,7 +289,7 @@ pfkey_handler()
if ((pkrecvf[msg->sadb_msg_type])(mhp) < 0)
goto end;
- error = 0;
+ error = 1;
end:
if (msg)
racoon_free(msg);
@@ -285,20 +303,32 @@ vchar_t *
pfkey_dump_sadb(satype)
int satype;
{
- int s = -1;
+ int s;
vchar_t *buf = NULL;
pid_t pid = getpid();
struct sadb_msg *msg = NULL;
size_t bl, ml;
int len;
+ int bufsiz;
- if ((s = privsep_pfkey_open()) < 0) {
+ if ((s = privsep_socket(PF_KEY, SOCK_RAW, PF_KEY_V2)) < 0) {
plog(LLV_ERROR, LOCATION, NULL,
"libipsec failed pfkey open: %s\n",
ipsec_strerror());
return NULL;
}
+ if ((bufsiz = pfkey_set_buffer_size(s, lcconf->pfkey_buffer_size)) < 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "libipsec failed pfkey set buffer size to %d: %s\n",
+ lcconf->pfkey_buffer_size, ipsec_strerror());
+ return NULL;
+ } else if (bufsiz < lcconf->pfkey_buffer_size) {
+ plog(LLV_WARNING, LOCATION, NULL,
+ "pfkey socket receive buffer set to %dKB, instead of %d\n",
+ bufsiz, lcconf->pfkey_buffer_size);
+ }
+
plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_dump\n");
if (pfkey_send_dump(s, satype) < 0) {
plog(LLV_ERROR, LOCATION, NULL,
@@ -325,7 +355,7 @@ pfkey_dump_sadb(satype)
"type %i, pid %i\n", msg->sadb_msg_type, msg->sadb_msg_pid);
continue;
}
-
+
ml = msg->sadb_msg_len << 3;
bl = buf ? buf->l : 0;
@@ -349,8 +379,7 @@ fail:
done:
if (msg)
racoon_free(msg);
- if (s >= 0)
- privsep_pfkey_close(s);
+ close(s);
return buf;
}
@@ -400,12 +429,25 @@ int
pfkey_init()
{
int i, reg_fail;
+ int bufsiz;
- if ((lcconf->sock_pfkey = privsep_pfkey_open()) < 0) {
+ if ((lcconf->sock_pfkey = pfkey_open()) < 0) {
plog(LLV_ERROR, LOCATION, NULL,
"libipsec failed pfkey open (%s)\n", ipsec_strerror());
return -1;
}
+ if ((bufsiz = pfkey_set_buffer_size(lcconf->sock_pfkey,
+ lcconf->pfkey_buffer_size)) < 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "libipsec failed to set pfkey buffer size to %d (%s)\n",
+ lcconf->pfkey_buffer_size, ipsec_strerror());
+ return -1;
+ } else if (bufsiz < lcconf->pfkey_buffer_size) {
+ plog(LLV_WARNING, LOCATION, NULL,
+ "pfkey socket receive buffer set to %dKB, instead of %d\n",
+ bufsiz, lcconf->pfkey_buffer_size);
+ }
+
if (fcntl(lcconf->sock_pfkey, F_SETFL, O_NONBLOCK) == -1)
plog(LLV_WARNING, LOCATION, NULL,
"failed to set the pfkey socket to NONBLOCK\n");
@@ -447,6 +489,25 @@ pfkey_init()
return -1;
}
#endif
+ monitor_fd(lcconf->sock_pfkey, pfkey_handler, NULL, 0);
+ return 0;
+}
+
+int
+pfkey_reload()
+{
+ flushsp();
+
+ if (pfkey_send_spddump(lcconf->sock_pfkey) < 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "libipsec sending spddump failed: %s\n",
+ ipsec_strerror());
+ return -1;
+ }
+
+ while (pfkey_handler(NULL, lcconf->sock_pfkey) > 0)
+ continue;
+
return 0;
}
@@ -717,6 +778,29 @@ keylen_ealg(enctype, encklen)
return res;
}
+void
+pk_fixup_sa_addresses(mhp)
+ caddr_t *mhp;
+{
+ struct sockaddr *src, *dst;
+
+ src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
+ dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
+ set_port(src, PORT_ISAKMP);
+ set_port(dst, PORT_ISAKMP);
+
+#ifdef ENABLE_NATT
+ if (PFKEY_ADDR_X_NATTYPE(mhp[SADB_X_EXT_NAT_T_TYPE])) {
+ /* NAT-T is enabled for this SADB entry; copy
+ * the ports from NAT-T extensions */
+ if(mhp[SADB_X_EXT_NAT_T_SPORT] != NULL)
+ set_port(src, PFKEY_ADDR_X_PORT(mhp[SADB_X_EXT_NAT_T_SPORT]));
+ if(mhp[SADB_X_EXT_NAT_T_DPORT] != NULL)
+ set_port(dst, PFKEY_ADDR_X_PORT(mhp[SADB_X_EXT_NAT_T_DPORT]));
+ }
+#endif
+}
+
int
pfkey_convertfromipsecdoi(proto_id, t_id, hashtype,
e_type, e_keylen, a_type, a_keylen, flags)
@@ -757,7 +841,7 @@ pfkey_convertfromipsecdoi(proto_id, t_id, hashtype,
goto bad;
*a_keylen >>= 3;
- if (t_id == IPSECDOI_ATTR_AUTH_HMAC_MD5
+ if (t_id == IPSECDOI_ATTR_AUTH_HMAC_MD5
&& hashtype == IPSECDOI_ATTR_AUTH_KPDK) {
/* AH_MD5 + Auth(KPDK) = RFC1826 keyed-MD5 */
*a_type = SADB_X_AALG_MD5;
@@ -798,35 +882,6 @@ pfkey_convertfromipsecdoi(proto_id, t_id, hashtype,
return -1;
}
-/* called from scheduler */
-void
-pfkey_timeover_stub(p)
- void *p;
-{
-
- pfkey_timeover((struct ph2handle *)p);
-}
-
-void
-pfkey_timeover(iph2)
- struct ph2handle *iph2;
-{
- plog(LLV_ERROR, LOCATION, NULL,
- "%s give up to get IPsec-SA due to time up to wait.\n",
- saddrwop2str(iph2->dst));
- SCHED_KILL(iph2->sce);
-
- /* If initiator side, send error to kernel by SADB_ACQUIRE. */
- if (iph2->side == INITIATOR)
- pk_sendeacquire(iph2);
-
- unbindph12(iph2);
- remph2(iph2);
- delph2(iph2);
-
- return;
-}
-
/*%%%*/
/* send getspi message per ipsec protocol per remote address */
/*
@@ -843,25 +898,28 @@ pk_sendgetspi(iph2)
struct saprop *pp;
struct saproto *pr;
u_int32_t minspi, maxspi;
- int proxy = 0;
+ u_int8_t natt_type = 0;
+ u_int16_t sport = 0, dport = 0;
- if (iph2->side == INITIATOR) {
+ if (iph2->side == INITIATOR)
pp = iph2->proposal;
- proxy = iph2->ph1->rmconf->support_proxy;
- } else {
+ else
pp = iph2->approval;
- if (iph2->sainfo && iph2->sainfo->id_i)
- proxy = 1;
- }
- /* for mobile IPv6 */
- if (proxy && iph2->src_id && iph2->dst_id &&
- ipsecdoi_transportmode(pp)) {
- src = iph2->src_id;
- dst = iph2->dst_id;
+ if (iph2->sa_src && iph2->sa_dst) {
+ /* MIPv6: Use SA addresses, not IKE ones */
+ src = dupsaddr(iph2->sa_src);
+ dst = dupsaddr(iph2->sa_dst);
} else {
- src = iph2->src;
- dst = iph2->dst;
+ /* Common case: SA addresses and IKE ones are the same */
+ src = dupsaddr(iph2->src);
+ dst = dupsaddr(iph2->dst);
+ }
+
+ if (src == NULL || dst == NULL) {
+ racoon_free(src);
+ racoon_free(dst);
+ return -1;
}
for (pr = pp->head; pr != NULL; pr = pr->next) {
@@ -871,6 +929,8 @@ pk_sendgetspi(iph2)
if (satype == ~0) {
plog(LLV_ERROR, LOCATION, NULL,
"invalid proto_id %d\n", pr->proto_id);
+ racoon_free(src);
+ racoon_free(dst);
return -1;
}
/* this works around a bug in Linux kernel where it allocates 4 byte
@@ -887,30 +947,36 @@ pk_sendgetspi(iph2)
if (mode == ~0) {
plog(LLV_ERROR, LOCATION, NULL,
"invalid encmode %d\n", pr->encmode);
+ racoon_free(src);
+ racoon_free(dst);
return -1;
}
#ifdef ENABLE_NATT
- /* XXX should we do a copy of src/dst for each pr ?
- */
- if (! pr->udp_encap) {
- /* Remove port information, that SA doesn't use it */
- set_port(src, 0);
- set_port(dst, 0);
+ if (pr->udp_encap) {
+ natt_type = iph2->ph1->natt_options->encaps_type;
+ sport=extract_port(src);
+ dport=extract_port(dst);
}
#endif
+
plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_getspi\n");
- if (pfkey_send_getspi(
+ if (pfkey_send_getspi_nat(
lcconf->sock_pfkey,
satype,
mode,
dst, /* src of SA */
src, /* dst of SA */
+ natt_type,
+ dport,
+ sport,
minspi, maxspi,
pr->reqid_in, iph2->seq) < 0) {
plog(LLV_ERROR, LOCATION, NULL,
"ipseclib failed send getspi (%s)\n",
ipsec_strerror());
+ racoon_free(src);
+ racoon_free(dst);
return -1;
}
plog(LLV_DEBUG, LOCATION, NULL,
@@ -918,6 +984,8 @@ pk_sendgetspi(iph2)
sadbsecas2str(dst, src, satype, 0, mode));
}
+ racoon_free(src);
+ racoon_free(dst);
return 0;
}
@@ -925,13 +993,13 @@ pk_sendgetspi(iph2)
* receive GETSPI from kernel.
*/
static int
-pk_recvgetspi(mhp)
+pk_recvgetspi(mhp)
caddr_t *mhp;
{
struct sadb_msg *msg;
struct sadb_sa *sa;
struct ph2handle *iph2;
- struct sockaddr *dst;
+ struct sockaddr *src, *dst;
int proto_id;
int allspiok, notfound;
struct saprop *pp;
@@ -939,14 +1007,17 @@ pk_recvgetspi(mhp)
/* validity check */
if (mhp[SADB_EXT_SA] == NULL
- || mhp[SADB_EXT_ADDRESS_DST] == NULL) {
+ || mhp[SADB_EXT_ADDRESS_DST] == NULL
+ || mhp[SADB_EXT_ADDRESS_SRC] == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
"inappropriate sadb getspi message passed.\n");
return -1;
}
msg = (struct sadb_msg *)mhp[0];
sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
+ pk_fixup_sa_addresses(mhp);
dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]); /* note SA dir */
+ src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
/* the message has to be processed or not ? */
if (msg->sadb_msg_pid != getpid()) {
@@ -986,7 +1057,7 @@ pk_recvgetspi(mhp)
notfound = 0;
plog(LLV_DEBUG, LOCATION, NULL,
"pfkey GETSPI succeeded: %s\n",
- sadbsecas2str(iph2->dst, iph2->src,
+ sadbsecas2str(dst, src,
msg->sadb_msg_satype,
sa->sadb_sa_spi,
ipsecdoi2pfkey_mode(pr->encmode)));
@@ -998,7 +1069,7 @@ pk_recvgetspi(mhp)
if (notfound) {
plog(LLV_ERROR, LOCATION, NULL,
"get spi for unknown address %s\n",
- saddrwop2str(iph2->dst));
+ saddrwop2str(dst));
return -1;
}
@@ -1008,7 +1079,6 @@ pk_recvgetspi(mhp)
if (isakmp_post_getspi(iph2) < 0) {
plog(LLV_ERROR, LOCATION, NULL,
"failed to start post getspi.\n");
- unbindph12(iph2);
remph2(iph2);
delph2(iph2);
iph2 = NULL;
@@ -1028,34 +1098,38 @@ pk_sendupdate(iph2)
{
struct saproto *pr;
struct pfkey_send_sa_args sa_args;
- int proxy = 0;
/* sanity check */
if (iph2->approval == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
"no approvaled SAs found.\n");
+ return -1;
}
- if (iph2->side == INITIATOR)
- proxy = iph2->ph1->rmconf->support_proxy;
- else if (iph2->sainfo && iph2->sainfo->id_i)
- proxy = 1;
-
/* fill in some needed for pfkey_send_update2 */
memset (&sa_args, 0, sizeof (sa_args));
sa_args.so = lcconf->sock_pfkey;
- sa_args.l_addtime = iph2->approval->lifetime;
- sa_args.seq = iph2->seq;
+ if (iph2->lifetime_secs)
+ sa_args.l_addtime = iph2->lifetime_secs;
+ else
+ sa_args.l_addtime = iph2->approval->lifetime;
+ sa_args.seq = iph2->seq;
sa_args.wsize = 4;
- /* for mobile IPv6 */
- if (proxy && iph2->src_id && iph2->dst_id &&
- ipsecdoi_transportmode(iph2->approval)) {
- sa_args.dst = iph2->src_id;
- sa_args.src = iph2->dst_id;
+ if (iph2->sa_src && iph2->sa_dst) {
+ /* MIPv6: Use SA addresses, not IKE ones */
+ sa_args.dst = dupsaddr(iph2->sa_src);
+ sa_args.src = dupsaddr(iph2->sa_dst);
} else {
- sa_args.dst = iph2->src;
- sa_args.src = iph2->dst;
+ /* Common case: SA addresses and IKE ones are the same */
+ sa_args.dst = dupsaddr(iph2->src);
+ sa_args.src = dupsaddr(iph2->dst);
+ }
+
+ if (sa_args.src == NULL || sa_args.dst == NULL) {
+ racoon_free(sa_args.src);
+ racoon_free(sa_args.dst);
+ return -1;
}
for (pr = iph2->approval->head; pr != NULL; pr = pr->next) {
@@ -1064,6 +1138,8 @@ pk_sendupdate(iph2)
if (sa_args.satype == ~0) {
plog(LLV_ERROR, LOCATION, NULL,
"invalid proto_id %d\n", pr->proto_id);
+ racoon_free(sa_args.src);
+ racoon_free(sa_args.dst);
return -1;
}
else if (sa_args.satype == SADB_X_SATYPE_IPCOMP) {
@@ -1077,6 +1153,8 @@ pk_sendupdate(iph2)
if (sa_args.mode == ~0) {
plog(LLV_ERROR, LOCATION, NULL,
"invalid encmode %d\n", pr->encmode);
+ racoon_free(sa_args.src);
+ racoon_free(sa_args.dst);
return -1;
}
#endif
@@ -1087,9 +1165,12 @@ pk_sendupdate(iph2)
pr->head->trns_id,
pr->head->authtype,
&sa_args.e_type, &sa_args.e_keylen,
- &sa_args.a_type, &sa_args.a_keylen,
- &sa_args.flags) < 0)
+ &sa_args.a_type, &sa_args.a_keylen,
+ &sa_args.flags) < 0){
+ racoon_free(sa_args.src);
+ racoon_free(sa_args.dst);
return -1;
+ }
#if 0
sa_args.l_bytes = iph2->approval->lifebyte * 1024,
@@ -1109,19 +1190,15 @@ pk_sendupdate(iph2)
#ifdef ENABLE_NATT
if (pr->udp_encap) {
sa_args.l_natt_type = iph2->ph1->natt_options->encaps_type;
- sa_args.l_natt_sport = extract_port (iph2->ph1->remote);
- sa_args.l_natt_dport = extract_port (iph2->ph1->local);
- sa_args.l_natt_oa = NULL; // FIXME: Here comes OA!!!
+ sa_args.l_natt_sport = extract_port(iph2->ph1->remote);
+ sa_args.l_natt_dport = extract_port(iph2->ph1->local);
+ sa_args.l_natt_oa = iph2->natoa_src;
#ifdef SADB_X_EXT_NAT_T_FRAG
sa_args.l_natt_frag = iph2->ph1->rmconf->esp_frag;
#endif
- } else {
- /* Remove port information, that SA doesn't use it */
- set_port(sa_args.src, 0);
- set_port(sa_args.dst, 0);
}
-
#endif
+
/* more info to fill in */
sa_args.spi = pr->spi;
sa_args.reqid = pr->reqid_in;
@@ -1132,6 +1209,8 @@ pk_sendupdate(iph2)
plog(LLV_ERROR, LOCATION, NULL,
"libipsec failed send update (%s)\n",
ipsec_strerror());
+ racoon_free(sa_args.src);
+ racoon_free(sa_args.dst);
return -1;
}
@@ -1145,11 +1224,11 @@ pk_sendupdate(iph2)
* But it is impossible because there is not key in the
* information from the kernel.
*/
-
+
/* change some things before backing up */
sa_args.wsize = 4;
sa_args.l_bytes = iph2->approval->lifebyte * 1024;
-
+
if (backupsa_to_file(&sa_args) < 0) {
plog(LLV_ERROR, LOCATION, NULL,
"backuped SA failed: %s\n",
@@ -1163,6 +1242,8 @@ pk_sendupdate(iph2)
#endif
}
+ racoon_free(sa_args.src);
+ racoon_free(sa_args.dst);
return 0;
}
@@ -1192,6 +1273,7 @@ pk_recvupdate(mhp)
return -1;
}
msg = (struct sadb_msg *)mhp[0];
+ pk_fixup_sa_addresses(mhp);
src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
@@ -1246,14 +1328,14 @@ pk_recvupdate(mhp)
pr->ok = 1;
plog(LLV_DEBUG, LOCATION, NULL,
"pfkey UPDATE succeeded: %s\n",
- sadbsecas2str(iph2->dst, iph2->src,
+ sadbsecas2str(dst, src,
msg->sadb_msg_satype,
sa->sadb_sa_spi,
sa_mode));
plog(LLV_INFO, LOCATION, NULL,
"IPsec-SA established: %s\n",
- sadbsecas2str(iph2->dst, iph2->src,
+ sadbsecas2str(dst, src,
msg->sadb_msg_satype, sa->sadb_sa_spi,
sa_mode));
}
@@ -1266,10 +1348,11 @@ pk_recvupdate(mhp)
return 0;
/* turn off the timer for calling pfkey_timeover() */
- SCHED_KILL(iph2->sce);
-
+ sched_cancel(&iph2->sce);
+
/* update status */
iph2->status = PHASE2ST_ESTABLISHED;
+ evt_phase2(iph2, EVT_PHASE2_UP, NULL);
#ifdef ENABLE_STATS
gettimeofday(&iph2->end, NULL);
@@ -1277,29 +1360,15 @@ pk_recvupdate(mhp)
"phase2", "quick", timedelta(&iph2->start, &iph2->end));
#endif
- /* count up */
- iph2->ph1->ph2cnt++;
-
/* turn off schedule */
- SCHED_KILL(iph2->scr);
-
- /* Force the update of ph2's ports, as there is at least one
- * situation where they'll mismatch with ph1's values
- */
-
-#ifdef ENABLE_NATT
- set_port(iph2->src, extract_port(iph2->ph1->local));
- set_port(iph2->dst, extract_port(iph2->ph1->remote));
-#endif
+ sched_cancel(&iph2->scr);
/*
* since we are going to reuse the phase2 handler, we need to
* remain it and refresh all the references between ph1 and ph2 to use.
*/
- unbindph12(iph2);
-
- iph2->sce = sched_new(iph2->approval->lifetime,
- isakmp_ph2expire_stub, iph2);
+ sched_schedule(&iph2->sce, iph2->approval->lifetime,
+ isakmp_ph2expire_stub);
plog(LLV_DEBUG, LOCATION, NULL, "===\n");
return 0;
@@ -1313,7 +1382,6 @@ pk_sendadd(iph2)
struct ph2handle *iph2;
{
struct saproto *pr;
- int proxy = 0;
struct pfkey_send_sa_args sa_args;
/* sanity check */
@@ -1323,26 +1391,30 @@ pk_sendadd(iph2)
return -1;
}
- if (iph2->side == INITIATOR)
- proxy = iph2->ph1->rmconf->support_proxy;
- else if (iph2->sainfo && iph2->sainfo->id_i)
- proxy = 1;
-
/* fill in some needed for pfkey_send_update2 */
memset (&sa_args, 0, sizeof (sa_args));
sa_args.so = lcconf->sock_pfkey;
- sa_args.l_addtime = iph2->approval->lifetime;
+ if (iph2->lifetime_secs)
+ sa_args.l_addtime = iph2->lifetime_secs;
+ else
+ sa_args.l_addtime = iph2->approval->lifetime;
sa_args.seq = iph2->seq;
sa_args.wsize = 4;
- /* for mobile IPv6 */
- if (proxy && iph2->src_id && iph2->dst_id &&
- ipsecdoi_transportmode(iph2->approval)) {
- sa_args.src = iph2->src_id;
- sa_args.dst = iph2->dst_id;
+ if (iph2->sa_src && iph2->sa_dst) {
+ /* MIPv6: Use SA addresses, not IKE ones */
+ sa_args.src = dupsaddr(iph2->sa_src);
+ sa_args.dst = dupsaddr(iph2->sa_dst);
} else {
- sa_args.src = iph2->src;
- sa_args.dst = iph2->dst;
+ /* Common case: SA addresses and IKE ones are the same */
+ sa_args.src = dupsaddr(iph2->src);
+ sa_args.dst = dupsaddr(iph2->dst);
+ }
+
+ if (sa_args.src == NULL || sa_args.dst == NULL) {
+ racoon_free(sa_args.src);
+ racoon_free(sa_args.dst);
+ return -1;
}
for (pr = iph2->approval->head; pr != NULL; pr = pr->next) {
@@ -1351,6 +1423,8 @@ pk_sendadd(iph2)
if (sa_args.satype == ~0) {
plog(LLV_ERROR, LOCATION, NULL,
"invalid proto_id %d\n", pr->proto_id);
+ racoon_free(sa_args.src);
+ racoon_free(sa_args.dst);
return -1;
}
else if (sa_args.satype == SADB_X_SATYPE_IPCOMP) {
@@ -1364,6 +1438,8 @@ pk_sendadd(iph2)
if (sa_args.mode == ~0) {
plog(LLV_ERROR, LOCATION, NULL,
"invalid encmode %d\n", pr->encmode);
+ racoon_free(sa_args.src);
+ racoon_free(sa_args.dst);
return -1;
}
#endif
@@ -1375,9 +1451,12 @@ pk_sendadd(iph2)
pr->head->trns_id,
pr->head->authtype,
&sa_args.e_type, &sa_args.e_keylen,
- &sa_args.a_type, &sa_args.a_keylen,
- &sa_args.flags) < 0)
+ &sa_args.a_type, &sa_args.a_keylen,
+ &sa_args.flags) < 0){
+ racoon_free(sa_args.src);
+ racoon_free(sa_args.dst);
return -1;
+ }
#if 0
sa_args.l_bytes = iph2->approval->lifebyte * 1024,
@@ -1402,22 +1481,12 @@ pk_sendadd(iph2)
sa_args.l_natt_type = UDP_ENCAP_ESPINUDP;
sa_args.l_natt_sport = extract_port(iph2->ph1->local);
sa_args.l_natt_dport = extract_port(iph2->ph1->remote);
- sa_args.l_natt_oa = NULL; // FIXME: Here comes OA!!!
+ sa_args.l_natt_oa = iph2->natoa_dst;
#ifdef SADB_X_EXT_NAT_T_FRAG
sa_args.l_natt_frag = iph2->ph1->rmconf->esp_frag;
#endif
- } else {
- /* Remove port information, that SA doesn't use it */
- set_port(sa_args.src, 0);
- set_port(sa_args.dst, 0);
}
-
-#else
- /* Remove port information, it is not used without NAT-T */
- set_port(sa_args.src, 0);
- set_port(sa_args.dst, 0);
#endif
-
/* more info to fill in */
sa_args.spi = pr->spi_p;
sa_args.reqid = pr->reqid_out;
@@ -1428,6 +1497,8 @@ pk_sendadd(iph2)
plog(LLV_ERROR, LOCATION, NULL,
"libipsec failed send add (%s)\n",
ipsec_strerror());
+ racoon_free(sa_args.src);
+ racoon_free(sa_args.dst);
return -1;
}
@@ -1453,6 +1524,8 @@ pk_sendadd(iph2)
sa_args.satype, sa_args.spi, sa_args.mode));
#endif
}
+ racoon_free(sa_args.src);
+ racoon_free(sa_args.dst);
return 0;
}
@@ -1480,6 +1553,7 @@ pk_recvadd(mhp)
return -1;
}
msg = (struct sadb_msg *)mhp[0];
+ pk_fixup_sa_addresses(mhp);
src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
@@ -1514,7 +1588,7 @@ pk_recvadd(mhp)
plog(LLV_INFO, LOCATION, NULL,
"IPsec-SA established: %s\n",
- sadbsecas2str(iph2->src, iph2->dst,
+ sadbsecas2str(src, dst,
msg->sadb_msg_satype, sa->sadb_sa_spi, sa_mode));
plog(LLV_DEBUG, LOCATION, NULL, "===\n");
@@ -1544,6 +1618,7 @@ pk_recvexpire(mhp)
}
msg = (struct sadb_msg *)mhp[0];
sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
+ pk_fixup_sa_addresses(mhp);
src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
@@ -1577,54 +1652,63 @@ pk_recvexpire(mhp)
sa_mode));
return 0;
}
- if (iph2->status != PHASE2ST_ESTABLISHED) {
+
+ /* resent expiry message? */
+ if (iph2->status > PHASE2ST_ESTABLISHED)
+ return 0;
+
+ /* still negotiating? */
+ if (iph2->status < PHASE2ST_ESTABLISHED) {
+ /* not a hard timeout? */
+ if (mhp[SADB_EXT_LIFETIME_HARD] == NULL)
+ return 0;
+
/*
- * If the status is not equal to PHASE2ST_ESTABLISHED,
- * racoon ignores this expire message. There are two reason.
- * One is that the phase 2 probably starts because there is
- * a potential that racoon receives the acquire message
- * without receiving a expire message. Another is that racoon
- * may receive the multiple expire messages from the kernel.
+ * We were negotiating for that SA (w/o much success
+ * from current status) and kernel has decided our time
+ * is over trying (xfrm_larval_drop controls that and
+ * is enabled by default on Linux >= 2.6.28 kernels).
*/
plog(LLV_WARNING, LOCATION, NULL,
- "the expire message is received "
- "but the handler has not been established.\n");
- return 0;
+ "PF_KEY EXPIRE message received from kernel for SA"
+ " being negotiated. Stopping negotiation.\n");
}
- /* turn off the timer for calling isakmp_ph2expire() */
- SCHED_KILL(iph2->sce);
-
- iph2->status = PHASE2ST_EXPIRED;
+ /* turn off the timer for calling isakmp_ph2expire() */
+ sched_cancel(&iph2->sce);
- /* INITIATOR, begin phase 2 exchange. */
- /* allocate buffer for status management of pfkey message */
- if (iph2->side == INITIATOR) {
-
- initph2(iph2);
+ if (iph2->status == PHASE2ST_ESTABLISHED &&
+ iph2->side == INITIATOR) {
+ struct ph1handle *iph1hint;
+ /*
+ * Active phase 2 expired and we were initiator.
+ * Begin new phase 2 exchange, so we can keep on sending
+ * traffic.
+ */
/* update status for re-use */
+ iph1hint = iph2->ph1;
+ initph2(iph2);
iph2->status = PHASE2ST_STATUS2;
- /* start isakmp initiation by using ident exchange */
- if (isakmp_post_acquire(iph2) < 0) {
+ /* start quick exchange */
+ if (isakmp_post_acquire(iph2, iph1hint, FALSE) < 0) {
plog(LLV_ERROR, LOCATION, iph2->dst,
"failed to begin ipsec sa "
"re-negotication.\n");
- unbindph12(iph2);
remph2(iph2);
delph2(iph2);
return -1;
}
return 0;
- /*NOTREACHED*/
}
- /* If not received SADB_EXPIRE, INITIATOR delete ph2handle. */
- /* RESPONDER always delete ph2handle, keep silent. RESPONDER doesn't
- * manage IPsec SA, so delete the list */
- unbindph12(iph2);
+ /*
+ * We are responder or the phase 2 was not established.
+ * Just remove the ph2handle to reflect SADB.
+ */
+ iph2->status = PHASE2ST_EXPIRED;
remph2(iph2);
delph2(iph2);
@@ -1638,17 +1722,15 @@ pk_recvacquire(mhp)
struct sadb_msg *msg;
struct sadb_x_policy *xpl;
struct secpolicy *sp_out = NULL, *sp_in = NULL;
-#define MAXNESTEDSA 5 /* XXX */
- struct ph2handle *iph2[MAXNESTEDSA];
- struct sockaddr *src, *dst;
- int n; /* # of phase 2 handler */
- int remoteid=0;
+ struct ph2handle *iph2;
+ struct sockaddr *src, *dst; /* IKE addresses (for exchanges) */
+ struct sockaddr *sp_src, *sp_dst; /* SP addresses (selectors). */
+ struct sockaddr *sa_src = NULL, *sa_dst = NULL ; /* SA addresses */
#ifdef HAVE_SECCTX
struct sadb_x_sec_ctx *m_sec_ctx;
#endif /* HAVE_SECCTX */
struct policyindex spidx;
-
/* ignore this message because of local test mode. */
if (f_local)
return 0;
@@ -1664,8 +1746,11 @@ pk_recvacquire(mhp)
}
msg = (struct sadb_msg *)mhp[0];
xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
- src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
- dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
+ /* acquire does not have nat-t ports; so do not bother setting
+ * the default port 500; just use the port zero for wildcard
+ * matching the get a valid natted destination */
+ sp_src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
+ sp_dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
#ifdef HAVE_SECCTX
m_sec_ctx = (struct sadb_x_sec_ctx *)mhp[SADB_X_EXT_SEC_CTX];
@@ -1673,7 +1758,7 @@ pk_recvacquire(mhp)
if (m_sec_ctx != NULL) {
plog(LLV_INFO, LOCATION, NULL, "security context doi: %u\n",
m_sec_ctx->sadb_x_ctx_doi);
- plog(LLV_INFO, LOCATION, NULL,
+ plog(LLV_INFO, LOCATION, NULL,
"security context algorithm: %u\n",
m_sec_ctx->sadb_x_ctx_alg);
plog(LLV_INFO, LOCATION, NULL, "security context length: %u\n",
@@ -1690,50 +1775,81 @@ pk_recvacquire(mhp)
return 0;
}
- /* ignore it if src is multicast address */
- {
- struct sockaddr *sa = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
+ /* ignore it if src or dst are multicast addresses. */
+ if ((sp_dst->sa_family == AF_INET
+ && IN_MULTICAST(ntohl(((struct sockaddr_in *)sp_dst)->sin_addr.s_addr)))
+#ifdef INET6
+ || (sp_dst->sa_family == AF_INET6
+ && IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *)sp_dst)->sin6_addr))
+#endif
+ ) {
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "ignore due to multicast destination address: %s.\n",
+ saddrwop2str(sp_dst));
+ return 0;
+ }
- if ((sa->sa_family == AF_INET
- && IN_MULTICAST(ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr)))
+ if ((sp_src->sa_family == AF_INET
+ && IN_MULTICAST(ntohl(((struct sockaddr_in *)sp_src)->sin_addr.s_addr)))
#ifdef INET6
- || (sa->sa_family == AF_INET6
- && IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *)sa)->sin6_addr))
+ || (sp_src->sa_family == AF_INET6
+ && IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *)sp_src)->sin6_addr))
#endif
) {
plog(LLV_DEBUG, LOCATION, NULL,
- "ignore due to multicast address: %s.\n",
- saddrwop2str(sa));
+ "ignore due to multicast source address: %s.\n",
+ saddrwop2str(sp_src));
return 0;
}
- }
-
- /* ignore, if we do not listen on source address */
- {
- /* reasons behind:
- * - if we'll contact peer from address we do not listen -
- * we will be unable to complete negotiation;
- * - if we'll negotiate using address we're listening -
- * remote peer will send packets to address different
- * than one in the policy, so kernel will drop them;
- * => therefore this acquire is not for us! --Aidas
- */
- struct sockaddr *sa = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
- struct myaddrs *p;
- int do_listen = 0;
- for (p = lcconf->myaddrs; p; p = p->next) {
- if (!cmpsaddrwop(p->addr, sa)) {
- do_listen = 1;
- break;
- }
- }
- if (!do_listen) {
- plog(LLV_DEBUG, LOCATION, NULL,
- "ignore because do not listen on source address : %s.\n",
- saddrwop2str(sa));
- return 0;
- }
+ /* search for proper policyindex */
+ sp_out = getspbyspid(xpl->sadb_x_policy_id);
+ if (sp_out == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL, "no policy found: id:%d.\n",
+ xpl->sadb_x_policy_id);
+ return -1;
+ }
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "suitable outbound SP found: %s.\n", spidx2str(&sp_out->spidx));
+
+ /* Before going further, let first get the source and destination
+ * address that would be used for IKE negotiation. The logic is:
+ * - if SP from SPD image contains local and remote hints, we
+ * use them (provided by MIGRATE).
+ * - otherwise, we use the ones from the ipsecrequest, which means:
+ * - the addresses from the request for transport mode
+ * - the endpoints addresses for tunnel mode
+ *
+ * Note that:
+ * 1) racoon does not support negotiation of bundles which
+ * simplifies the lookup for the addresses in the ipsecrequest
+ * list, as we expect only one.
+ * 2) We do source and destination parts all together and do not
+ * accept semi-defined information. This is just a decision,
+ * there might be needs.
+ *
+ * --arno
+ */
+ if (sp_out->req && sp_out->req->saidx.mode == IPSEC_MODE_TUNNEL) {
+ /* For Tunnel mode, SA addresses are the endpoints */
+ src = (struct sockaddr *) &sp_out->req->saidx.src;
+ dst = (struct sockaddr *) &sp_out->req->saidx.dst;
+ } else {
+ /* Otherwise use requested addresses.
+ *
+ * We need to explicitly setup sa_src and sa_dst too,
+ * since the SA ports are different from IKE port. And
+ * src/dst ports will be overwritten when the matching
+ * phase1 is found. */
+ src = sa_src = sp_src;
+ dst = sa_dst = sp_dst;
+ }
+ if (sp_out->local && sp_out->remote) {
+ /* hints available, let's use them */
+ sa_src = src;
+ sa_dst = dst;
+ src = (struct sockaddr *) sp_out->local;
+ dst = (struct sockaddr *) sp_out->remote;
}
/*
@@ -1746,27 +1862,25 @@ pk_recvacquire(mhp)
* has to prcesss such a acquire message because racoon may
* lost the expire message.
*/
- iph2[0] = getph2byid(src, dst, xpl->sadb_x_policy_id);
- if (iph2[0] != NULL) {
- if (iph2[0]->status < PHASE2ST_ESTABLISHED) {
+ iph2 = getph2byid(src, dst, xpl->sadb_x_policy_id);
+ if (iph2 != NULL) {
+ if (iph2->status < PHASE2ST_ESTABLISHED) {
plog(LLV_DEBUG, LOCATION, NULL,
"ignore the acquire because ph2 found\n");
return -1;
}
- if (iph2[0]->status == PHASE2ST_EXPIRED)
- iph2[0] = NULL;
+ if (iph2->status == PHASE2ST_EXPIRED)
+ iph2 = NULL;
/*FALLTHROUGH*/
}
- /* search for proper policyindex */
- sp_out = getspbyspid(xpl->sadb_x_policy_id);
- if (sp_out == NULL) {
- plog(LLV_ERROR, LOCATION, NULL, "no policy found: id:%d.\n",
- xpl->sadb_x_policy_id);
- return -1;
+ /* Check we are listening on source address. If not, ignore. */
+ if (myaddr_getsport(src) == -1) {
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "Not listening on source address %s. Ignoring ACQUIRE.\n",
+ saddrwop2str(src));
+ return 0;
}
- plog(LLV_DEBUG, LOCATION, NULL,
- "suitable outbound SP found: %s.\n", spidx2str(&sp_out->spidx));
/* get inbound policy */
{
@@ -1802,119 +1916,67 @@ pk_recvacquire(mhp)
}
}
- memset(iph2, 0, MAXNESTEDSA);
-
- n = 0;
-
/* allocate a phase 2 */
- iph2[n] = newph2();
- if (iph2[n] == NULL) {
+ iph2 = newph2();
+ if (iph2 == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
"failed to allocate phase2 entry.\n");
return -1;
}
- iph2[n]->side = INITIATOR;
- iph2[n]->spid = xpl->sadb_x_policy_id;
- iph2[n]->satype = msg->sadb_msg_satype;
- iph2[n]->seq = msg->sadb_msg_seq;
- iph2[n]->status = PHASE2ST_STATUS2;
-
- /* set end addresses of SA */
- iph2[n]->dst = dupsaddr(PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]));
- if (iph2[n]->dst == NULL) {
- delph2(iph2[n]);
+ iph2->side = INITIATOR;
+ iph2->spid = xpl->sadb_x_policy_id;
+ iph2->satype = msg->sadb_msg_satype;
+ iph2->seq = msg->sadb_msg_seq;
+ iph2->status = PHASE2ST_STATUS2;
+
+ /* set address used by IKE for the negotiation (might differ from
+ * SA address, i.e. might not be tunnel endpoints or addresses
+ * of transport mode SA) */
+ iph2->dst = dupsaddr(dst);
+ if (iph2->dst == NULL) {
+ delph2(iph2);
return -1;
}
- iph2[n]->src = dupsaddr(PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]));
- if (iph2[n]->src == NULL) {
- delph2(iph2[n]);
+ iph2->src = dupsaddr(src);
+ if (iph2->src == NULL) {
+ delph2(iph2);
return -1;
}
- plog(LLV_DEBUG, LOCATION, NULL,
- "new acquire %s\n", spidx2str(&sp_out->spidx));
-
- /* get sainfo */
- {
- vchar_t *idsrc, *iddst;
-
- idsrc = ipsecdoi_sockaddr2id((struct sockaddr *)&sp_out->spidx.src,
- sp_out->spidx.prefs, sp_out->spidx.ul_proto);
- if (idsrc == NULL) {
- plog(LLV_ERROR, LOCATION, NULL,
- "failed to get ID for %s\n",
- spidx2str(&sp_out->spidx));
- delph2(iph2[n]);
- return -1;
+ /* If sa_src and sa_dst have been set, this mean we have to
+ * set iph2->sa_src and iph2->sa_dst to provide the addresses
+ * of the SA because iph2->src and iph2->dst are only the ones
+ * used for the IKE exchanges. Those that need these addresses
+ * are for instance pk_sendupdate() or pk_sendgetspi() */
+ if (sa_src) {
+ iph2->sa_src = dupsaddr(sa_src);
+ iph2->sa_dst = dupsaddr(sa_dst);
}
- iddst = ipsecdoi_sockaddr2id((struct sockaddr *)&sp_out->spidx.dst,
- sp_out->spidx.prefd, sp_out->spidx.ul_proto);
- if (iddst == NULL) {
- plog(LLV_ERROR, LOCATION, NULL,
- "failed to get ID for %s\n",
- spidx2str(&sp_out->spidx));
- vfree(idsrc);
- delph2(iph2[n]);
- return -1;
- }
- {
- struct remoteconf *conf;
- conf = getrmconf(iph2[n]->dst);
- if (conf != NULL)
- remoteid=conf->ph1id;
- else{
- plog(LLV_DEBUG, LOCATION, NULL, "Warning: no valid rmconf !\n");
- remoteid=0;
- }
- }
- iph2[n]->sainfo = getsainfo(idsrc, iddst, NULL, remoteid);
- vfree(idsrc);
- vfree(iddst);
- if (iph2[n]->sainfo == NULL) {
- plog(LLV_ERROR, LOCATION, NULL,
- "failed to get sainfo.\n");
- delph2(iph2[n]);
- return -1;
- /* XXX should use the algorithm list from register message */
- }
-
- plog(LLV_DEBUG, LOCATION, NULL,
- "selected sainfo: %s\n", sainfo2str(iph2[n]->sainfo));
- }
- if (set_proposal_from_policy(iph2[n], sp_out, sp_in) < 0) {
- plog(LLV_ERROR, LOCATION, NULL,
- "failed to create saprop.\n");
- delph2(iph2[n]);
+ if (isakmp_get_sainfo(iph2, sp_out, sp_in) < 0) {
+ delph2(iph2);
return -1;
}
+
#ifdef HAVE_SECCTX
if (m_sec_ctx) {
- set_secctx_in_proposal(iph2[n], spidx);
+ set_secctx_in_proposal(iph2, spidx);
}
#endif /* HAVE_SECCTX */
- insph2(iph2[n]);
+ insph2(iph2);
/* start isakmp initiation by using ident exchange */
/* XXX should be looped if there are multiple phase 2 handler. */
- if (isakmp_post_acquire(iph2[n]) < 0) {
+ if (isakmp_post_acquire(iph2, NULL, TRUE) < 0) {
plog(LLV_ERROR, LOCATION, NULL,
"failed to begin ipsec sa negotication.\n");
- goto err;
+ remph2(iph2);
+ delph2(iph2);
+ return -1;
}
return 0;
-
-err:
- while (n >= 0) {
- unbindph12(iph2[n]);
- remph2(iph2[n]);
- delph2(iph2[n]);
- iph2[n] = NULL;
- n--;
- }
- return -1;
}
static int
@@ -1942,6 +2004,7 @@ pk_recvdelete(mhp)
}
msg = (struct sadb_msg *)mhp[0];
sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
+ pk_fixup_sa_addresses(mhp);
src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
@@ -1973,14 +2036,13 @@ pk_recvdelete(mhp)
plog(LLV_ERROR, LOCATION, NULL,
"pfkey DELETE received: %s\n",
- sadbsecas2str(iph2->src, iph2->dst,
+ sadbsecas2str(src, dst,
msg->sadb_msg_satype, sa->sadb_sa_spi, IPSEC_MODE_ANY));
/* send delete information */
if (iph2->status == PHASE2ST_ESTABLISHED)
isakmp_info_send_d2(iph2);
- unbindph12(iph2);
remph2(iph2);
delph2(iph2);
@@ -2014,6 +2076,7 @@ getsadbpolicy(policy0, policylen0, type, iph2)
struct ph2handle *iph2;
{
struct policyindex *spidx = (struct policyindex *)iph2->spidx_gen;
+ struct sockaddr *src = NULL, *dst = NULL;
struct sadb_x_policy *xpl;
struct sadb_x_ipsecrequest *xisr;
struct saproto *pr;
@@ -2032,11 +2095,19 @@ getsadbpolicy(policy0, policylen0, type, iph2)
/* get policy buffer size */
policylen = sizeof(struct sadb_x_policy);
if (type != SADB_X_SPDDELETE) {
+ if (iph2->sa_src && iph2->sa_dst) {
+ src = iph2->sa_src; /* MIPv6: Use SA addresses, */
+ dst = iph2->sa_dst; /* not IKE ones */
+ } else {
+ src = iph2->src; /* Common case: SA addresses */
+ dst = iph2->dst; /* and IKE ones are the same */
+ }
+
for (pr = iph2->approval->head; pr; pr = pr->next) {
xisrlen = sizeof(*xisr);
if (pr->encmode == IPSECDOI_ATTR_ENC_MODE_TUNNEL) {
- xisrlen += (sysdep_sa_len(iph2->src)
- + sysdep_sa_len(iph2->dst));
+ xisrlen += (sysdep_sa_len(src) +
+ sysdep_sa_len(dst));
}
policylen += PFKEY_ALIGN8(xisrlen);
@@ -2082,7 +2153,7 @@ getsadbpolicy(policy0, policylen0, type, iph2)
p->sadb_x_ctx_len = spidx->sec_ctx.ctx_strlen;
p->sadb_x_ctx_doi = spidx->sec_ctx.ctx_doi;
p->sadb_x_ctx_alg = spidx->sec_ctx.ctx_alg;
-
+
memcpy(p + 1,spidx->sec_ctx.ctx_str,spidx->sec_ctx.ctx_strlen);
len += ctxlen;
}
@@ -2121,7 +2192,7 @@ getsadbpolicy(policy0, policylen0, type, iph2)
goto err;
}
- /*
+ /*
* the policy level cannot be unique because the policy
* is defined later than SA, so req_id cannot be bound to SA.
*/
@@ -2141,20 +2212,20 @@ getsadbpolicy(policy0, policylen0, type, iph2)
if (pr->encmode == IPSECDOI_ATTR_ENC_MODE_TUNNEL) {
int src_len, dst_len;
- src_len = sysdep_sa_len(iph2->src);
- dst_len = sysdep_sa_len(iph2->dst);
+ src_len = sysdep_sa_len(src);
+ dst_len = sysdep_sa_len(dst);
xisrlen += src_len + dst_len;
- memcpy(p, iph2->src, src_len);
+ memcpy(p, src, src_len);
p += src_len;
- memcpy(p, iph2->dst, dst_len);
+ memcpy(p, dst, dst_len);
p += dst_len;
}
xisr->sadb_x_ipsecrequest_len = PFKEY_ALIGN8(xisrlen);
xisr = (struct sadb_x_ipsecrequest *)p;
-
+
}
racoon_free(pr_rlist);
@@ -2219,10 +2290,12 @@ pk_recvspdupdate(mhp)
{
struct sadb_address *saddr, *daddr;
struct sadb_x_policy *xpl;
- struct sadb_lifetime *lt;
+ struct sadb_lifetime *lt;
struct policyindex spidx;
struct secpolicy *sp;
- u_int64_t created;
+ struct sockaddr *local=NULL, *remote=NULL;
+ u_int64_t created;
+ int ret;
/* sanity check */
if (mhp[0] == NULL
@@ -2277,15 +2350,29 @@ pk_recvspdupdate(mhp)
sp = getsp(&spidx);
if (sp == NULL) {
- plog(LLV_ERROR, LOCATION, NULL,
- "such policy does not already exist: \"%s\"\n",
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "this policy did not exist for removal: \"%s\"\n",
spidx2str(&spidx));
} else {
+ /* preserve hints before deleting the SP */
+ local = sp->local;
+ remote = sp->remote;
+ sp->local = NULL;
+ sp->remote = NULL;
+
remsp(sp);
delsp(sp);
}
- if (addnewsp(mhp) < 0)
+ /* Add new SP (with old hints) */
+ ret = addnewsp(mhp, local, remote);
+
+ if (local != NULL)
+ racoon_free(local);
+ if (remote != NULL)
+ racoon_free(remote);
+
+ if (ret < 0)
return -1;
return 0;
@@ -2344,7 +2431,9 @@ pk_recvspdadd(mhp)
struct sadb_lifetime *lt;
struct policyindex spidx;
struct secpolicy *sp;
+ struct sockaddr *local = NULL, *remote = NULL;
u_int64_t created;
+ int ret;
/* sanity check */
if (mhp[0] == NULL
@@ -2403,11 +2492,26 @@ pk_recvspdadd(mhp)
"such policy already exists. "
"anyway replace it: %s\n",
spidx2str(&spidx));
+
+ /* preserve hints before deleting the SP */
+ local = sp->local;
+ remote = sp->remote;
+ sp->local = NULL;
+ sp->remote = NULL;
+
remsp(sp);
delsp(sp);
}
- if (addnewsp(mhp) < 0)
+ /* Add new SP (with old hints) */
+ ret = addnewsp(mhp, local, remote);
+
+ if (local != NULL)
+ racoon_free(local);
+ if (remote != NULL)
+ racoon_free(remote);
+
+ if (ret < 0)
return -1;
return 0;
@@ -2628,7 +2732,9 @@ pk_recvspddump(mhp)
struct sadb_lifetime *lt;
struct policyindex spidx;
struct secpolicy *sp;
+ struct sockaddr *local=NULL, *remote=NULL;
u_int64_t created;
+ int ret;
/* sanity check */
if (mhp[0] == NULL) {
@@ -2637,7 +2743,6 @@ pk_recvspddump(mhp)
return -1;
}
msg = (struct sadb_msg *)mhp[0];
-
saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
@@ -2692,11 +2797,26 @@ pk_recvspddump(mhp)
"such policy already exists. "
"anyway replace it: %s\n",
spidx2str(&spidx));
+
+ /* preserve hints before deleting the SP */
+ local = sp->local;
+ remote = sp->remote;
+ sp->local = NULL;
+ sp->remote = NULL;
+
remsp(sp);
delsp(sp);
}
- if (addnewsp(mhp) < 0)
+ /* Add new SP (with old hints) */
+ ret = addnewsp(mhp, local, remote);
+
+ if (local != NULL)
+ racoon_free(local);
+ if (remote != NULL)
+ racoon_free(remote);
+
+ if (ret < 0)
return -1;
return 0;
@@ -2718,10 +2838,731 @@ pk_recvspdflush(mhp)
return 0;
}
+#if defined(SADB_X_MIGRATE) && defined(SADB_X_EXT_KMADDRESS)
+
+/* MIGRATE support (pk_recvmigrate() is the handler of MIGRATE message).
+ *
+ * pk_recvmigrate()
+ * 1) some preprocessing and checks
+ * 2) parsing of sadb_x_kmaddress extension
+ * 3) SP lookup using selectors and content of policy extension from MIGRATE
+ * 4) resolution of current local and remote IKE addresses
+ * 5) Use of addresses to get Phase 1 handler if any
+ * 6) Update of IKE addresses in Phase 1 (iph1->local and iph1->remote)
+ * 7) Update of IKE addresses in Phase 2 (iph2->src and iph2->dst)
+ * 8) Update of IKE addresses in SP (sp->local and sp->remote)
+ * 9) Loop on sadb_x_ipsecrequests pairs from MIGRATE
+ * - update of associated ipsecrequests entries in sp->req (should be
+ * only one as racoon does not support bundles), i.e. update of
+ * tunnel endpoints when required.
+ * - If tunnel mode endpoints have been updated, lookup of associated
+ * Phase 2 handle to also update sa_src and sa_dst entries
+ *
+ * XXX Note that we do not support yet the update of SA addresses for transport
+ * mode, but only the update of SA addresses for tunnel mode (endpoints).
+ * Reasons are:
+ * - there is no initial need for MIPv6
+ * - racoon does not support bundles
+ * - this would imply more work to deal with sainfo update (if feasible).
+ */
+
+/* Generic argument structure for migration callbacks */
+struct migrate_args {
+ struct sockaddr *local;
+ struct sockaddr *remote;
+};
+
+/*
+ * Update local and remote addresses of given Phase 1. Schedule removal
+ * if negotiation was going on and restart a one from updated address.
+ *
+ * -1 is returned on error. 0 if everything went right.
+ */
+static int
+migrate_ph1_ike_addresses(iph1, arg)
+ struct ph1handle *iph1;
+ void *arg;
+{
+ struct migrate_args *ma = (struct migrate_args *) arg;
+ struct remoteconf *rmconf;
+ u_int16_t port;
+
+ /* Already up-to-date? */
+ if (cmpsaddr(iph1->local, ma->local) == CMPSADDR_MATCH &&
+ cmpsaddr(iph1->remote, ma->remote) == CMPSADDR_MATCH)
+ return 0;
+
+ if (iph1->status < PHASE1ST_ESTABLISHED) {
+ /* Bad luck! We received a MIGRATE *while* negotiating
+ * Phase 1 (i.e. it was not established yet). If we act as
+ * initiator we need to restart the negotiation. As
+ * responder, our best bet is to update our addresses
+ * and wait for the initiator to do something */
+ plog(LLV_WARNING, LOCATION, NULL, "MIGRATE received *during* "
+ "Phase 1 negotiation (%s).\n",
+ saddr2str_fromto("%s => %s", ma->local, ma->remote));
+
+ /* If we are not acting as initiator, let's just leave and
+ * let the remote peer handle the restart */
+ rmconf = getrmconf(ma->remote, 0);
+ if (rmconf == NULL || !rmconf->passive) {
+ iph1->status = PHASE1ST_EXPIRED;
+ isakmp_ph1delete(iph1);
+
+ /* This is unlikely, but let's just check if a Phase 1
+ * for the new addresses already exist */
+ if (getph1byaddr(ma->local, ma->remote, 0)) {
+ plog(LLV_WARNING, LOCATION, NULL, "No need "
+ "to start a new Phase 1 negotiation. One "
+ "already exists.\n");
+ return 0;
+ }
+
+ plog(LLV_WARNING, LOCATION, NULL, "As initiator, "
+ "restarting it.\n");
+ /* Note that the insertion of the new Phase 1 will not
+ * interfere with the fact we are called from enumph1,
+ * because it is inserted as first element. --arno */
+ isakmp_ph1begin_i(rmconf, ma->local, ma->remote);
+
+ return 0;
+ }
+ }
+
+ if (iph1->local != NULL) {
+ plog(LLV_DEBUG, LOCATION, NULL, "Migrating Phase 1 local "
+ "address from %s\n",
+ saddr2str_fromto("%s to %s", iph1->local, ma->local));
+ port = extract_port(iph1->local);
+ racoon_free(iph1->local);
+ } else
+ port = 0;
+
+ iph1->local = dupsaddr(ma->local);
+ if (iph1->local == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL, "unable to allocate "
+ "Phase 1 local address.\n");
+ return -1;
+ }
+ set_port(iph1->local, port);
+
+ if (iph1->remote != NULL) {
+ plog(LLV_DEBUG, LOCATION, NULL, "Migrating Phase 1 remote "
+ "address from %s\n",
+ saddr2str_fromto("%s to %s", iph1->remote, ma->remote));
+ port = extract_port(iph1->remote);
+ racoon_free(iph1->remote);
+ } else
+ port = 0;
+
+ iph1->remote = dupsaddr(ma->remote);
+ if (iph1->remote == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL, "unable to allocate "
+ "Phase 1 remote address.\n");
+ return -1;
+ }
+ set_port(iph1->remote, port);
+
+ return 0;
+}
+
+/* Update src and dst of all current Phase 2 handles.
+ * with provided local and remote addresses.
+ * Our intent is NOT to modify IPsec SA endpoints but IKE
+ * addresses so we need to take care to separate those if
+ * they are different. -1 is returned on error. 0 if everything
+ * went right.
+ *
+ * Note: we do not maintain port information as it is not
+ * expected to be meaningful --arno
+ */
+static int
+migrate_ph2_ike_addresses(iph2, arg)
+ struct ph2handle *iph2;
+ void *arg;
+{
+ struct migrate_args *ma = (struct migrate_args *) arg;
+ struct ph1handle *iph1;
+
+ /* If Phase 2 has an associated Phase 1, migrate addresses */
+ if (iph2->ph1)
+ migrate_ph1_ike_addresses(iph2->ph1, arg);
+
+ /* Already up-to-date? */
+ if (cmpsaddr(iph2->src, ma->local) == CMPSADDR_MATCH &&
+ cmpsaddr(iph2->dst, ma->remote) == CMPSADDR_MATCH)
+ return 0;
+
+ /* save src/dst as sa_src/sa_dst before rewriting */
+ if (iph2->sa_src == NULL && iph2->sa_dst == NULL) {
+ iph2->sa_src = iph2->src;
+ iph2->sa_dst = iph2->dst;
+ iph2->src = NULL;
+ iph2->dst = NULL;
+ }
+
+ if (iph2->src != NULL)
+ racoon_free(iph2->src);
+ iph2->src = dupsaddr(ma->local);
+ if (iph2->src == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "unable to allocate Phase 2 src address.\n");
+ return -1;
+ }
+
+ if (iph2->dst != NULL)
+ racoon_free(iph2->dst);
+ iph2->dst = dupsaddr(ma->remote);
+ if (iph2->dst == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "unable to allocate Phase 2 dst address.\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Consider existing Phase 2 handles with given spid and update their source
+ * and destination addresses for SA. As racoon does not support bundles, if
+ * we modify multiple occurrences, this probably imply rekeying has happened.
+ *
+ * Both addresses passed to the function are expected not to be NULL and of
+ * same family. -1 is returned on error. 0 if everything went right.
+ *
+ * Specific care is needed to support Phase 2 for which negotiation has
+ * already started but are which not yet established.
+ */
+static int
+migrate_ph2_sa_addresses(iph2, args)
+ struct ph2handle *iph2;
+ void *args;
+{
+ struct migrate_args *ma = (struct migrate_args *) args;
+
+ if (iph2->sa_src != NULL) {
+ racoon_free(iph2->sa_src);
+ iph2->sa_src = NULL;
+ }
+
+ if (iph2->sa_dst != NULL) {
+ racoon_free(iph2->sa_dst);
+ iph2->sa_dst = NULL;
+ }
+
+ iph2->sa_src = dupsaddr(ma->local);
+ if (iph2->sa_src == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "unable to allocate Phase 2 sa_src address.\n");
+ return -1;
+ }
+
+ iph2->sa_dst = dupsaddr(ma->remote);
+ if (iph2->sa_dst == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "unable to allocate Phase 2 sa_dst address.\n");
+ return -1;
+ }
+
+ if (iph2->status < PHASE2ST_ESTABLISHED) {
+ struct remoteconf *rmconf;
+ /* We were negotiating for that SA when we received the MIGRATE.
+ * We cannot simply update the addresses and let the exchange
+ * go on. We have to restart the whole negotiation if we are
+ * the initiator. Otherwise (acting as responder), we just need
+ * to delete our ph2handle and wait for the initiator to start
+ * a new negotiation. */
+
+ if (iph2->ph1 && iph2->ph1->rmconf)
+ rmconf = iph2->ph1->rmconf;
+ else
+ rmconf = getrmconf(iph2->dst, 0);
+
+ if (rmconf && !rmconf->passive) {
+ struct ph1handle *iph1hint;
+
+ plog(LLV_WARNING, LOCATION, iph2->dst, "MIGRATE received "
+ "*during* IPsec SA negotiation. As initiator, "
+ "restarting it.\n");
+
+ /* Turn off expiration timer ...*/
+ sched_cancel(&iph2->sce);
+ iph2->status = PHASE2ST_EXPIRED;
+
+ /* ... clean Phase 2 handle ... */
+ iph1hint = iph2->ph1;
+ initph2(iph2);
+ iph2->status = PHASE2ST_STATUS2;
+
+ /* and start a new negotiation */
+ if (isakmp_post_acquire(iph2, iph1hint, FALSE) < 0) {
+ plog(LLV_ERROR, LOCATION, iph2->dst, "failed "
+ "to begin IPsec SA renegotiation after "
+ "MIGRATE reception.\n");
+ remph2(iph2);
+ delph2(iph2);
+ return -1;
+ }
+ } else {
+ plog(LLV_WARNING, LOCATION, iph2->dst, "MIGRATE received "
+ "*during* IPsec SA negotiation. As responder, let's"
+ "wait for the initiator to act.\n");
+
+ /* Simply schedule deletion */
+ isakmp_ph2expire(iph2);
+ }
+ }
+
+ return 0;
+}
+
+/* Update SP hints (local and remote addresses) for future IKE
+ * negotiations of SA associated with that SP. -1 is returned
+ * on error. 0 if everything went right.
+ *
+ * Note: we do not maintain port information as it is not
+ * expected to be meaningful --arno
+ */
+static int
+migrate_sp_ike_addresses(sp, local, remote)
+ struct secpolicy *sp;
+ struct sockaddr *local, *remote;
+{
+ if (sp == NULL || local == NULL || remote == NULL)
+ return -1;
+
+ if (sp->local != NULL)
+ racoon_free(sp->local);
+
+ sp->local = dupsaddr(local);
+ if (sp->local == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL, "unable to allocate "
+ "local hint for SP.\n");
+ return -1;
+ }
+
+ if (sp->remote != NULL)
+ racoon_free(sp->remote);
+
+ sp->remote = dupsaddr(remote);
+ if (sp->remote == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL, "unable to allocate "
+ "remote hint for SP.\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Given current ipsecrequest (isr_cur) to be migrated in considered
+ tree, the function first checks that it matches the expected one
+ (xisr_old) provided in MIGRATE message and then updates the addresses
+ if it is tunnel mode (with content of xisr_new). Various other checks
+ are performed. For transport mode, structures are not modified, only
+ the checks are done. -1 is returned on error. */
+static int
+migrate_ph2_one_isr(spid, isr_cur, xisr_old, xisr_new)
+ u_int32_t spid;
+ struct ipsecrequest *isr_cur;
+ struct sadb_x_ipsecrequest *xisr_old, *xisr_new;
+{
+ struct secasindex *saidx = &isr_cur->saidx;
+ struct sockaddr *osaddr, *odaddr, *nsaddr, *ndaddr;
+ struct ph2selector ph2sel;
+ struct migrate_args ma;
+
+ /* First, check that mode and proto do match */
+ if (xisr_old->sadb_x_ipsecrequest_proto != saidx->proto ||
+ xisr_old->sadb_x_ipsecrequest_mode != saidx->mode ||
+ xisr_new->sadb_x_ipsecrequest_proto != saidx->proto ||
+ xisr_new->sadb_x_ipsecrequest_mode != saidx->mode)
+ return -1;
+
+ /* Then, verify reqid if necessary */
+ if (isr_cur->saidx.reqid &&
+ (xisr_old->sadb_x_ipsecrequest_reqid != IPSEC_LEVEL_UNIQUE ||
+ xisr_new->sadb_x_ipsecrequest_reqid != IPSEC_LEVEL_UNIQUE ||
+ isr_cur->saidx.reqid != xisr_old->sadb_x_ipsecrequest_reqid ||
+ isr_cur->saidx.reqid != xisr_new->sadb_x_ipsecrequest_reqid))
+ return -1;
+
+ /* If not tunnel mode, our work is over */
+ if (saidx->mode != IPSEC_MODE_TUNNEL) {
+ plog(LLV_DEBUG, LOCATION, NULL, "SADB_X_MIGRATE: "
+ "non tunnel mode isr, skipping SA address migration.\n");
+ return 0;
+ }
+
+ /* Tunnel mode: let's check addresses do match and then update them. */
+ osaddr = (struct sockaddr *)(xisr_old + 1);
+ odaddr = (struct sockaddr *)(((u_int8_t *)osaddr) + sysdep_sa_len(osaddr));
+ nsaddr = (struct sockaddr *)(xisr_new + 1);
+ ndaddr = (struct sockaddr *)(((u_int8_t *)nsaddr) + sysdep_sa_len(nsaddr));
+
+ /* Check family does match */
+ if (osaddr->sa_family != odaddr->sa_family ||
+ nsaddr->sa_family != ndaddr->sa_family)
+ return -1;
+
+ /* Check family does match */
+ if (saidx->src.ss_family != osaddr->sa_family)
+ return -1;
+
+ /* We log IPv4 to IPv6 and IPv6 to IPv4 switches */
+ if (nsaddr->sa_family != osaddr->sa_family)
+ plog(LLV_INFO, LOCATION, NULL, "SADB_X_MIGRATE: "
+ "changing address families (%d to %d) for endpoints.\n",
+ osaddr->sa_family, nsaddr->sa_family);
+
+ if (cmpsaddr(osaddr, (struct sockaddr *) &saidx->src) != CMPSADDR_MATCH ||
+ cmpsaddr(odaddr, (struct sockaddr *) &saidx->dst) != CMPSADDR_MATCH) {
+ plog(LLV_DEBUG, LOCATION, NULL, "SADB_X_MIGRATE: "
+ "mismatch of addresses in saidx and xisr.\n");
+ return -1;
+ }
+
+ /* Excellent. Let's grab associated Phase 2 handle (if any)
+ * and update its sa_src and sa_dst entries. Note that we
+ * make the assumption that racoon does not support bundles
+ * and make the lookup using spid: we blindly update
+ * sa_src and sa_dst for _all_ found Phase 2 handles */
+ memset(&ph2sel, 0, sizeof(ph2sel));
+ ph2sel.spid = spid;
+
+ memset(&ma, 0, sizeof(ma));
+ ma.local = nsaddr;
+ ma.remote = ndaddr;
+
+ if (enumph2(&ph2sel, migrate_ph2_sa_addresses, &ma) < 0)
+ return -1;
+
+ /* Now we can do the update of endpoints in secasindex */
+ memcpy(&saidx->src, nsaddr, sysdep_sa_len(nsaddr));
+ memcpy(&saidx->dst, ndaddr, sysdep_sa_len(ndaddr));
+
+ return 0;
+}
+
+/* Process the raw (unparsed yet) list of sadb_x_ipsecrequests of MIGRATE
+ * message. For each sadb_x_ipsecrequest pair (old followed by new),
+ * the corresponding ipsecrequest entry in the SP is updated. Associated
+ * existing Phase 2 handle is also updated (if any) */
+static int
+migrate_sp_isr_list(sp, xisr_list, xisr_list_len)
+ struct secpolicy *sp;
+ struct sadb_x_ipsecrequest *xisr_list;
+ int xisr_list_len;
+{
+ struct sadb_x_ipsecrequest *xisr_new, *xisr_old = xisr_list;
+ int xisr_old_len, xisr_new_len;
+ struct ipsecrequest *isr_cur;
+
+ isr_cur = sp->req; /* ipsecrequest list from from sp */
+
+ while (xisr_list_len > 0 && isr_cur != NULL) {
+ /* Get old xisr (length field is in bytes) */
+ xisr_old_len = xisr_old->sadb_x_ipsecrequest_len;
+ if (xisr_old_len < sizeof(*xisr_old) ||
+ xisr_old_len + sizeof(*xisr_new) > xisr_list_len) {
+ plog(LLV_ERROR, LOCATION, NULL, "SADB_X_MIGRATE: "
+ "invalid ipsecrequest length. Exiting.\n");
+ return -1;
+ }
+
+ /* Get new xisr with updated info */
+ xisr_new = (struct sadb_x_ipsecrequest *)(((u_int8_t *)xisr_old) + xisr_old_len);
+ xisr_new_len = xisr_new->sadb_x_ipsecrequest_len;
+ if (xisr_new_len < sizeof(*xisr_new) ||
+ xisr_new_len + xisr_old_len > xisr_list_len) {
+ plog(LLV_ERROR, LOCATION, NULL, "SADB_X_MIGRATE: "
+ "invalid ipsecrequest length. Exiting.\n");
+ return -1;
+ }
+
+ /* Start by migrating current ipsecrequest from SP */
+ if (migrate_ph2_one_isr(sp->id, isr_cur, xisr_old, xisr_new) == -1) {
+ plog(LLV_ERROR, LOCATION, NULL, "SADB_X_MIGRATE: "
+ "Unable to match and migrate isr. Exiting.\n");
+ return -1;
+ }
+
+ /* Update pointers for next round */
+ xisr_list_len -= xisr_old_len + xisr_new_len;
+ xisr_old = (struct sadb_x_ipsecrequest *)(((u_int8_t *)xisr_new) +
+ xisr_new_len);
+
+ isr_cur = isr_cur->next; /* Get next ipsecrequest from SP */
+ }
+
+ /* Check we had the same amount of pairs in the MIGRATE
+ as the number of ipsecrequests in the SP */
+ if ((xisr_list_len != 0) || isr_cur != NULL) {
+ plog(LLV_ERROR, LOCATION, NULL, "SADB_X_MIGRATE: "
+ "number of ipsecrequest does not match the one in SP.\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Parse sadb_x_kmaddress extension and make local and remote
+ * parameters point to the new addresses (zero copy). -1 is
+ * returned on error, meaning that addresses are not usable */
+static int
+parse_kmaddress(kmaddr, local, remote)
+ struct sadb_x_kmaddress *kmaddr;
+ struct sockaddr **local, **remote;
+{
+ int addrslen, local_len=0;
+ struct ph1handle *iph1;
+
+ if (kmaddr == NULL)
+ return -1;
+
+ /* Grab addresses in sadb_x_kmaddress extension */
+ addrslen = PFKEY_EXTLEN(kmaddr) - sizeof(*kmaddr);
+ if (addrslen < sizeof(struct sockaddr))
+ return -1;
+
+ *local = (struct sockaddr *)(kmaddr + 1);
+
+ switch ((*local)->sa_family) {
+ case AF_INET:
+ local_len = sizeof(struct sockaddr_in);
+ break;
+#ifdef INET6
+ case AF_INET6:
+ local_len = sizeof(struct sockaddr_in6);
+ break;
+#endif
+ default:
+ return -1;
+ }
+
+ if (addrslen != PFKEY_ALIGN8(2*local_len))
+ return -1;
+
+ *remote = (struct sockaddr *)(((u_int8_t *)(*local)) + local_len);
+
+ if ((*local)->sa_family != (*remote)->sa_family)
+ return -1;
+
+ return 0;
+}
+
+/* Handler of PF_KEY MIGRATE message. Helpers are above */
+static int
+pk_recvmigrate(mhp)
+ caddr_t *mhp;
+{
+ struct sadb_address *saddr, *daddr;
+ struct sockaddr *old_saddr, *new_saddr;
+ struct sockaddr *old_daddr, *new_daddr;
+ struct sockaddr *old_local, *old_remote;
+ struct sockaddr *local, *remote;
+ struct sadb_x_kmaddress *kmaddr;
+ struct sadb_x_policy *xpl;
+ struct sadb_x_ipsecrequest *xisr_list;
+ struct sadb_lifetime *lt;
+ struct policyindex spidx;
+ struct secpolicy *sp;
+ struct ipsecrequest *isr_cur;
+ struct secasindex *oldsaidx;
+ struct ph2handle *iph2;
+ struct ph1handle *iph1;
+ struct ph2selector ph2sel;
+ struct ph1selector ph1sel;
+ u_int32_t spid;
+ u_int64_t created;
+ int xisr_list_len;
+ int ulproto;
+ struct migrate_args ma;
+
+ /* Some sanity checks */
+
+ if (mhp[0] == NULL
+ || mhp[SADB_EXT_ADDRESS_SRC] == NULL
+ || mhp[SADB_EXT_ADDRESS_DST] == NULL
+ || mhp[SADB_X_EXT_KMADDRESS] == NULL
+ || mhp[SADB_X_EXT_POLICY] == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "SADB_X_MIGRATE: invalid MIGRATE message received.\n");
+ return -1;
+ }
+ kmaddr = (struct sadb_x_kmaddress *)mhp[SADB_X_EXT_KMADDRESS];
+ saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
+ daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
+ xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
+ lt = (struct sadb_lifetime*)mhp[SADB_EXT_LIFETIME_HARD];
+ if (lt != NULL)
+ created = lt->sadb_lifetime_addtime;
+ else
+ created = 0;
+
+ if (xpl->sadb_x_policy_type != IPSEC_POLICY_IPSEC) {
+ plog(LLV_WARNING, LOCATION, NULL,"SADB_X_MIGRATE: "
+ "found non IPsec policy in MIGRATE message. Exiting.\n");
+ return -1;
+ }
+
+ if (PFKEY_EXTLEN(xpl) < sizeof(*xpl)) {
+ plog(LLV_ERROR, LOCATION, NULL, "SADB_X_MIGRATE: "
+ "invalid size for sadb_x_policy. Exiting.\n");
+ return -1;
+ }
+
+ /* Some logging to help debbugging */
+ if (xpl->sadb_x_policy_dir == IPSEC_DIR_OUTBOUND)
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "SADB_X_MIGRATE: Outbound SA being migrated.\n");
+ else
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "SADB_X_MIGRATE: Inbound SA being migrated.\n");
+
+ /* validity check */
+ xisr_list = (struct sadb_x_ipsecrequest *)(xpl + 1);
+ xisr_list_len = PFKEY_EXTLEN(xpl) - sizeof(*xpl);
+ if (xisr_list_len < sizeof(*xisr_list)) {
+ plog(LLV_ERROR, LOCATION, NULL, "SADB_X_MIGRATE: "
+ "invalid sadb_x_policy message length. Exiting.\n");
+ return -1;
+ }
+
+ if (parse_kmaddress(kmaddr, &local, &remote) == -1) {
+ plog(LLV_ERROR, LOCATION, NULL, "SADB_X_MIGRATE: "
+ "invalid sadb_x_kmaddress extension. Exiting.\n");
+ return -1;
+ }
+
+ /* 0 means ANY */
+ if (saddr->sadb_address_proto == 0)
+ ulproto = IPSEC_ULPROTO_ANY;
+ else
+ ulproto = saddr->sadb_address_proto;
+
+#ifdef HAVE_PFKEY_POLICY_PRIORITY
+ KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
+ saddr + 1,
+ daddr + 1,
+ saddr->sadb_address_prefixlen,
+ daddr->sadb_address_prefixlen,
+ ulproto,
+ xpl->sadb_x_policy_priority,
+ created,
+ &spidx);
+#else
+ KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
+ saddr + 1,
+ daddr + 1,
+ saddr->sadb_address_prefixlen,
+ daddr->sadb_address_prefixlen,
+ ulproto,
+ created,
+ &spidx);
+#endif
+
+ /* Everything seems ok, let's get the SP.
+ *
+ * XXX We could also do the lookup using the spid from xpl.
+ * I don't know which one is better. --arno */
+ sp = getsp(&spidx);
+ if (sp == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "SADB_X_MIGRATE: Passed policy does not exist: %s\n",
+ spidx2str(&spidx));
+ return -1;
+ }
+
+ /* Get the best source and destination addresses used for IKE
+ * negotiation, to find and migrate existing Phase 1 */
+ if (sp->local && sp->remote) {
+ /* hints available, let's use them */
+ old_local = (struct sockaddr *)sp->local;
+ old_remote = (struct sockaddr *)sp->remote;
+ } else if (sp->req && sp->req->saidx.mode == IPSEC_MODE_TUNNEL) {
+ /* Tunnel mode and no hint, use endpoints */
+ old_local = (struct sockaddr *)&sp->req->saidx.src;
+ old_remote = (struct sockaddr *)&sp->req->saidx.dst;
+ } else {
+ /* default, use selectors as fallback */
+ old_local = (struct sockaddr *)&sp->spidx.src;
+ old_remote = (struct sockaddr *)&sp->spidx.dst;
+ }
+
+ /* We migrate all Phase 1 that match our old local and remote
+ * addresses (no matter their state).
+ *
+ * XXX In fact, we should probably havea special treatment for
+ * Phase 1 that are being established when we receive a MIGRATE.
+ * This can happen if a movement occurs during the initial IKE
+ * negotiation. In that case, I wonder if should restart the
+ * negotiation from the new address or just update things like
+ * we do it now.
+ *
+ * XXX while looking at getph1byaddr(), the comment at the
+ * beginning of the function expects comparison to happen
+ * without ports considerations but it uses CMPSADDR() which
+ * relies either on cmpsaddrstrict() or cmpsaddrwop() based
+ * on NAT-T support being activated. That make me wonder if I
+ * should force ports to 0 (ANY) in local and remote values
+ * used below.
+ *
+ * -- arno */
+
+ /* Apply callback data ...*/
+ memset(&ma, 0, sizeof(ma));
+ ma.local = local;
+ ma.remote = remote;
+
+ /* Fill phase1 match criteria ... */
+ memset(&ph1sel, 0, sizeof(ph1sel));
+ ph1sel.local = old_local;
+ ph1sel.remote = old_remote;
+
+
+ /* Have matching Phase 1 found and addresses updated. As this is a
+ * time consuming task on a busy responder, and MIGRATE messages
+ * are always sent for *both* inbound and outbound (and possibly
+ * forward), we only do that for outbound SP. */
+ if (xpl->sadb_x_policy_dir == IPSEC_DIR_OUTBOUND &&
+ enumph1(&ph1sel, migrate_ph1_ike_addresses, &ma) < 0) {
+ plog(LLV_ERROR, LOCATION, NULL, "SADB_X_MIGRATE: Unable "
+ "to migrate Phase 1 addresses.\n");
+ return -1;
+ }
+
+ /* We can now update IKE addresses in Phase 2 handle. */
+ memset(&ph2sel, 0, sizeof(ph2sel));
+ ph2sel.spid = sp->id;
+ if (enumph2(&ph2sel, migrate_ph2_ike_addresses, &ma) < 0) {
+ plog(LLV_ERROR, LOCATION, NULL, "SADB_X_MIGRATE: Unable "
+ "to migrate Phase 2 IKE addresses.\n");
+ return -1;
+ }
+
+ /* and _then_ in SP. */
+ if (migrate_sp_ike_addresses(sp, local, remote) < 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "SADB_X_MIGRATE: Unable to migrate SP IKE addresses.\n");
+ return -1;
+ }
+
+ /* Loop on sadb_x_ipsecrequest list to possibly update sp->req
+ * entries and associated live Phase 2 handles (their sa_src
+ * and sa_dst) */
+ if (migrate_sp_isr_list(sp, xisr_list, xisr_list_len) < 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "SADB_X_MIGRATE: Unable to migrate isr list.\n");
+ return -1;
+ }
+
+ return 0;
+}
+#endif
+
#ifndef ANDROID_PATCHED
/*
- * send error against acquire message to kenrel.
+ * send error against acquire message to kernel.
*/
int
pk_sendeacquire(iph2)
@@ -2759,8 +3600,8 @@ pk_sendeacquire(iph2)
#else
int pk_sendeacquire(struct ph2handle *iph2)
-{
- exit(1);
+{
+ exit(1);
}
#endif
@@ -2787,8 +3628,8 @@ pk_checkalg(class, calg, keylen)
break;
case IPSECDOI_PROTO_IPCOMP:
plog(LLV_DEBUG, LOCATION, NULL,
- "compression algorithm can not be checked "
- "because sadb message doesn't support it.\n");
+ "no check of compression algorithm; "
+ "not supported in sadb message.\n");
return 0;
default:
plog(LLV_ERROR, LOCATION, NULL,
@@ -2848,6 +3689,11 @@ pk_recv(so, lenp)
return NULL;
reallen = PFKEY_UNUNIT64(buf.sadb_msg_len);
+ if (reallen < sizeof(buf)) {
+ *lenp = -1;
+ errno = EIO;
+ return NULL; /*fatal*/
+ }
if ((newmsg = racoon_calloc(1, reallen)) == NULL)
return NULL;
@@ -2880,8 +3726,9 @@ pk_getseq()
}
static int
-addnewsp(mhp)
+addnewsp(mhp, local, remote)
caddr_t *mhp;
+ struct sockaddr *local, *remote;
{
struct secpolicy *new = NULL;
struct sadb_address *saddr, *daddr;
@@ -3090,6 +3937,12 @@ addnewsp(mhp)
}
#endif /* HAVE_SECCTX */
+ /* Set local and remote hints for that SP, if available */
+ if (local && remote) {
+ new->local = dupsaddr(local);
+ new->remote = dupsaddr(remote);
+ }
+
inssp(new);
return 0;
diff --git a/src/racoon/pfkey.h b/src/racoon/pfkey.h
index 547f94a..cfe111d 100644
--- a/src/racoon/pfkey.h
+++ b/src/racoon/pfkey.h
@@ -1,4 +1,4 @@
-/* $NetBSD: pfkey.h,v 1.4 2006/09/09 16:22:10 manu Exp $ */
+/* $NetBSD: pfkey.h,v 1.8 2009/07/03 06:40:10 tteras Exp $ */
/* Id: pfkey.h,v 1.3 2004/06/11 16:00:17 ludvigm Exp */
@@ -42,16 +42,17 @@ struct pfkey_satype {
extern const struct pfkey_satype pfkey_satypes[];
extern const int pfkey_nsatypes;
-extern int pfkey_handler __P((void));
extern vchar_t *pfkey_dump_sadb __P((int));
extern void pfkey_flush_sadb __P((u_int));
extern int pfkey_init __P((void));
+extern int pfkey_reload __P((void));
extern struct pfkey_st *pfkey_getpst __P((caddr_t *, int, int));
extern int pk_checkalg __P((int, int, int));
struct ph2handle;
+extern void pk_fixup_sa_addresses __P((caddr_t *mhp));
extern int pk_sendgetspi __P((struct ph2handle *));
extern int pk_sendupdate __P((struct ph2handle *));
extern int pk_sendadd __P((struct ph2handle *));
@@ -60,9 +61,6 @@ extern int pk_sendspdupdate2 __P((struct ph2handle *));
extern int pk_sendspdadd2 __P((struct ph2handle *));
extern int pk_sendspddelete __P((struct ph2handle *));
-extern void pfkey_timeover_stub __P((void *));
-extern void pfkey_timeover __P((struct ph2handle *));
-
extern u_int pfkey2ipsecdoi_proto __P((u_int));
extern u_int ipsecdoi2pfkey_proto __P((u_int));
extern u_int pfkey2ipsecdoi_mode __P((u_int));
diff --git a/src/racoon/plainrsa-gen.c b/src/racoon/plainrsa-gen.c
index 1bd5f67..cad1861 100644
--- a/src/racoon/plainrsa-gen.c
+++ b/src/racoon/plainrsa-gen.c
@@ -1,4 +1,4 @@
-/* $NetBSD: plainrsa-gen.c,v 1.4 2006/09/09 16:22:10 manu Exp $ */
+/* $NetBSD: plainrsa-gen.c,v 1.6 2011/02/11 10:07:19 tteras Exp $ */
/* Id: plainrsa-gen.c,v 1.6 2005/04/21 09:08:40 monas Exp */
/*
@@ -43,11 +43,13 @@
#include <sys/stat.h>
#include <sys/socket.h>
#include <unistd.h>
+#include <fcntl.h>
#include <openssl/bio.h>
#include <openssl/bn.h>
#include <openssl/err.h>
#include <openssl/objects.h>
+#include <openssl/pem.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>
#ifdef HAVE_OPENSSL_ENGINE_H
@@ -72,6 +74,7 @@ usage (char *argv0)
fprintf(stderr, " -b bits Generate <bits> long RSA key (default=1024)\n");
fprintf(stderr, " -e pubexp Public exponent to use (default=0x3)\n");
fprintf(stderr, " -f filename Filename to store the key to (default=stdout)\n");
+ fprintf(stderr, " -i filename Input source for format conversion\n");
fprintf(stderr, " -h Help\n");
fprintf(stderr, "\n");
fprintf(stderr, "Report bugs to <ipsec-tools-devel@lists.sourceforge.net>\n");
@@ -82,7 +85,7 @@ usage (char *argv0)
* See RFC 2065, section 3.5 for details about the output format.
*/
vchar_t *
-mix_b64_pubkey(RSA *key)
+mix_b64_pubkey(const RSA *key)
{
char *binbuf;
long binlen, ret;
@@ -116,17 +119,10 @@ lowercase(char *input)
}
int
-gen_rsa_key(FILE *fp, size_t bits, unsigned long exp)
+print_rsa_key(FILE *fp, const RSA *key)
{
- RSA *key;
vchar_t *pubkey64 = NULL;
- key = RSA_generate_key(bits, exp, NULL, NULL);
- if (!key) {
- fprintf(stderr, "RSA_generate_key(): %s\n", eay_strerror());
- return -1;
- }
-
pubkey64 = mix_b64_pubkey(key);
if (!pubkey64) {
fprintf(stderr, "mix_b64_pubkey(): %s\n", eay_strerror());
@@ -135,7 +131,7 @@ gen_rsa_key(FILE *fp, size_t bits, unsigned long exp)
fprintf(fp, "# : PUB 0s%s\n", pubkey64->v);
fprintf(fp, ": RSA\t{\n");
- fprintf(fp, "\t# RSA %zu bits\n", bits);
+ fprintf(fp, "\t# RSA %d bits\n", BN_num_bits(key->n));
fprintf(fp, "\t# pubkey=0s%s\n", pubkey64->v);
fprintf(fp, "\tModulus: 0x%s\n", lowercase(BN_bn2hex(key->n)));
fprintf(fp, "\tPublicExponent: 0x%s\n", lowercase(BN_bn2hex(key->e)));
@@ -148,23 +144,92 @@ gen_rsa_key(FILE *fp, size_t bits, unsigned long exp)
fprintf(fp, " }\n");
vfree(pubkey64);
+ return 0;
+}
+
+int
+print_public_rsa_key(FILE *fp, const RSA *key)
+{
+ vchar_t *pubkey64 = NULL;
+ pubkey64 = mix_b64_pubkey(key);
+ if (!pubkey64) {
+ fprintf(stderr, "mix_b64_pubkey(): %s\n", eay_strerror());
+ return -1;
+ }
+
+ fprintf(fp, ": PUB 0s%s\n", pubkey64->v);
+
+ vfree(pubkey64);
return 0;
}
int
+convert_rsa_key(FILE *fpout, FILE *fpin)
+{
+ int ret;
+ RSA *key = NULL;
+
+ key = PEM_read_RSAPrivateKey(fpin, NULL, NULL, NULL);
+ if (key) {
+ ret = print_rsa_key(fpout, key);
+ RSA_free(key);
+
+ return ret;
+ }
+
+ rewind(fpin);
+
+ key = PEM_read_RSA_PUBKEY(fpin, NULL, NULL, NULL);
+ if (key) {
+ ret = print_public_rsa_key(fpout, key);
+ RSA_free(key);
+
+ return ret;
+ }
+
+ /* Implement parsing of input stream containing
+ * private or public "plainrsa" formatted text.
+ * Convert the result to PEM formatted output.
+ *
+ * This seemingly needs manual use of prsaparse().
+ * An expert ought to do this. */
+
+ fprintf(stderr, "convert_rsa_key: %s\n", "Only conversion from PEM at this time");
+ return -1;
+}
+
+int
+gen_rsa_key(FILE *fp, size_t bits, unsigned long exp)
+{
+ int ret;
+ RSA *key;
+
+ key = RSA_generate_key(bits, exp, NULL, NULL);
+ if (!key) {
+ fprintf(stderr, "RSA_generate_key(): %s\n", eay_strerror());
+ return -1;
+ }
+
+ ret = print_rsa_key(fp, key);
+ RSA_free(key);
+
+ return ret;
+}
+
+int
main (int argc, char *argv[])
{
- FILE *fp = stdout;
+ FILE *fp = stdout, *fpin = NULL;
size_t bits = 1024;
unsigned int pubexp = 0x3;
struct stat st;
extern char *optarg;
extern int optind;
- int c;
- char *fname = NULL;
+ int c, fd = -1, fdin = -1;
+ char *fname = NULL, *finput = NULL;
- while ((c = getopt(argc, argv, "e:b:f:h")) != -1)
+ while ((c = getopt(argc, argv, "e:b:f:i:h")) != -1)
switch (c) {
case 'e':
if (strncmp(optarg, "0x", 2) == 0)
@@ -178,31 +243,65 @@ main (int argc, char *argv[])
case 'f':
fname = optarg;
break;
+ case 'i':
+ finput = optarg;
+ break;
case 'h':
default:
usage(argv[0]);
}
if (fname) {
- if (stat(fname, &st) >= 0) {
- fprintf(stderr, "%s: file exists! Please use a different name.\n", fname);
+ umask(0077);
+ /* Restrictive access due to private key material. */
+ fd = open(fname, O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW, S_IRUSR | S_IWUSR);
+ if (fd < 0) {
+ if (errno == EEXIST)
+ fprintf(stderr, "%s: file exists! Please use a different name.\n", fname);
+ else
+ fprintf(stderr, "%s: %s\n", fname, strerror(errno));
exit(1);
}
-
- umask(0077);
- fp = fopen(fname, "w");
+ fp = fdopen(fd, "w");
if (fp == NULL) {
fprintf(stderr, "%s: %s\n", fname, strerror(errno));
+ close(fd);
exit(1);
}
}
+ if (finput) {
+ /* Restrictive access once more. Do not be fooled by a link. */
+ fdin = open(finput, O_RDONLY | O_NOFOLLOW);
+ if (fdin < 0) {
+ if (errno == ELOOP)
+ fprintf(stderr, "%s: file is a link. Discarded for security.\n", fname);
+ if (fp)
+ fclose(fp);
+ exit(1);
+ }
+ fpin = fdopen(fdin, "r");
+ if (fpin == NULL) {
+ fprintf(stderr, "%s: %s\n", fname, strerror(errno));
+ close(fdin);
+ if (fp)
+ fclose(fp);
+ exit(1);
+ }
+
+ }
+
ploginit();
eay_init();
- gen_rsa_key(fp, bits, pubexp);
+ if (fpin)
+ convert_rsa_key(fp, fpin);
+ else
+ gen_rsa_key(fp, bits, pubexp);
fclose(fp);
+ if (fpin)
+ fclose(fpin);
return 0;
}
diff --git a/src/racoon/plog.c b/src/racoon/plog.c
index 008260d..aebfed2 100644
--- a/src/racoon/plog.c
+++ b/src/racoon/plog.c
@@ -1,4 +1,4 @@
-/* $NetBSD: plog.c,v 1.4.6.2 2009/04/20 13:35:36 tteras Exp $ */
+/* $NetBSD: plog.c,v 1.7 2011/01/28 12:51:40 tteras Exp $ */
/* Id: plog.c,v 1.11 2006/06/20 09:57:31 vanhu Exp */
@@ -36,6 +36,7 @@
#include <sys/types.h>
#include <sys/param.h>
+#include <arpa/inet.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -78,7 +79,7 @@ int print_location = 0;
static struct log *logp = NULL;
static char *logfile = NULL;
-static char *plog_common __P((int, const char *, const char *));
+static char *plog_common __P((int, const char *, const char *, struct sockaddr *));
static struct plogtags {
char *name;
@@ -94,11 +95,13 @@ static struct plogtags {
};
static char *
-plog_common(pri, fmt, func)
+plog_common(pri, fmt, func, sa)
int pri;
const char *fmt, *func;
+ struct sockaddr *sa;
{
static char buf[800]; /* XXX shoule be allocated every time ? */
+ void *addr;
char *p;
int reslen, len;
@@ -116,19 +119,43 @@ plog_common(pri, fmt, func)
reslen -= len;
}
+ if (sa && reslen > 3) {
+ addr = NULL;
+ switch (sa->sa_family) {
+ case AF_INET:
+ addr = &((struct sockaddr_in*)sa)->sin_addr;
+ break;
+ case AF_INET6:
+ addr = &((struct sockaddr_in6*)sa)->sin6_addr;
+ break;
+ }
+ if (inet_ntop(sa->sa_family, addr, p + 1, reslen - 3) != NULL) {
+ *p++ = '[';
+ len = strlen(p);
+ p += len;
+ *p++ = ']';
+ *p++ = ' ';
+ reslen -= len + 3;
+ }
+ }
+
if (pri < ARRAYLEN(ptab)) {
len = snprintf(p, reslen, "%s: ", ptab[pri].name);
- if (len >= 0 && len < reslen) {
- p += len;
- reslen -= len;
- } else
- *p = '\0';
+ p += len;
+ reslen -= len;
}
if (print_location)
- snprintf(p, reslen, "%s: %s", func, fmt);
+ len = snprintf(p, reslen, "%s: %s", func, fmt);
else
- snprintf(p, reslen, "%s", fmt);
+ len = snprintf(p, reslen, "%s", fmt);
+ p += len;
+ reslen -= len;
+
+ /* Force nul termination */
+ if (reslen == 0)
+ p[-1] = 0;
+
#ifdef BROKEN_PRINTF
while ((p = strstr(buf,"%z")) != NULL)
p[1] = 'l';
@@ -157,7 +184,7 @@ plogv(int pri, const char *func, struct sockaddr *sa,
if (pri > loglevel)
return;
- newfmt = plog_common(pri, fmt, func);
+ newfmt = plog_common(pri, fmt, func, sa);
VA_COPY(ap_bak, ap);
diff --git a/src/racoon/plog.h b/src/racoon/plog.h
index 4d9a93f..6c3ac12 100644
--- a/src/racoon/plog.h
+++ b/src/racoon/plog.h
@@ -1,4 +1,4 @@
-/* $NetBSD: plog.h,v 1.4.6.1 2007/11/06 16:41:27 vanhu Exp $ */
+/* $NetBSD: plog.h,v 1.5 2007/10/02 09:47:40 vanhu Exp $ */
/* Id: plog.h,v 1.7 2006/06/20 09:57:31 vanhu Exp */
diff --git a/src/racoon/policy.c b/src/racoon/policy.c
index 29a6818..4c00677 100644
--- a/src/racoon/policy.c
+++ b/src/racoon/policy.c
@@ -1,4 +1,4 @@
-/* $NetBSD: policy.c,v 1.6.4.1 2007/08/01 11:52:21 vanhu Exp $ */
+/* $NetBSD: policy.c,v 1.12 2011/03/14 17:18:13 tteras Exp $ */
/* $KAME: policy.c,v 1.46 2001/11/16 04:08:10 sakane Exp $ */
@@ -91,13 +91,17 @@ getsp_r(spidx)
struct policyindex *spidx;
{
struct secpolicy *p;
+ struct secpolicy *found = NULL;
for (p = TAILQ_FIRST(&sptree); p; p = TAILQ_NEXT(p, chain)) {
- if (!cmpspidxwild(spidx, &p->spidx))
+ if (!cmpspidxstrict(spidx, &p->spidx))
return p;
+
+ if (!found && !cmpspidxwild(spidx, &p->spidx))
+ found = p;
}
- return NULL;
+ return found;
}
#else
struct secpolicy *
@@ -137,16 +141,18 @@ getsp_r(spidx, iph2)
saddr2str(iph2->src));
plog(LLV_DEBUG, LOCATION, NULL, "src2: %s\n",
saddr2str((struct sockaddr *)&spidx->src));
- if (cmpsaddrwop(iph2->src, (struct sockaddr *)&spidx->src)
- || spidx->prefs != prefixlen)
+
+ if (cmpsaddr(iph2->src, (struct sockaddr *) &spidx->src) != CMPSADDR_MATCH ||
+ spidx->prefs != prefixlen)
return NULL;
plog(LLV_DEBUG, LOCATION, NULL, "dst1: %s\n",
saddr2str(iph2->dst));
plog(LLV_DEBUG, LOCATION, NULL, "dst2: %s\n",
saddr2str((struct sockaddr *)&spidx->dst));
- if (cmpsaddrwop(iph2->dst, (struct sockaddr *)&spidx->dst)
- || spidx->prefd != prefixlen)
+
+ if (cmpsaddr(iph2->dst, (struct sockaddr *) &spidx->dst) != CMPSADDR_MATCH ||
+ spidx->prefd != prefixlen)
return NULL;
plog(LLV_DEBUG, LOCATION, NULL, "looks to be transport mode\n");
@@ -194,11 +200,11 @@ cmpspidxstrict(a, b)
|| a->ul_proto != b->ul_proto)
return 1;
- if (cmpsaddrstrict((struct sockaddr *)&a->src,
- (struct sockaddr *)&b->src))
+ if (cmpsaddr((struct sockaddr *) &a->src,
+ (struct sockaddr *) &b->src) != CMPSADDR_MATCH)
return 1;
- if (cmpsaddrstrict((struct sockaddr *)&a->dst,
- (struct sockaddr *)&b->dst))
+ if (cmpsaddr((struct sockaddr *) &a->dst,
+ (struct sockaddr *) &b->dst) != CMPSADDR_MATCH)
return 1;
#ifdef HAVE_SECCTX
@@ -228,8 +234,7 @@ cmpspidxwild(a, b)
if (!(b->dir == IPSEC_DIR_ANY || a->dir == b->dir))
return 1;
- if (!(a->ul_proto == IPSEC_ULPROTO_ANY ||
- b->ul_proto == IPSEC_ULPROTO_ANY ||
+ if (!(b->ul_proto == IPSEC_ULPROTO_ANY ||
a->ul_proto == b->ul_proto))
return 1;
@@ -256,7 +261,7 @@ cmpspidxwild(a, b)
a, b->prefs, saddr2str((struct sockaddr *)&sa1));
plog(LLV_DEBUG, LOCATION, NULL, "%p masked with /%d: %s\n",
b, b->prefs, saddr2str((struct sockaddr *)&sa2));
- if (cmpsaddrwild((struct sockaddr *)&sa1, (struct sockaddr *)&sa2))
+ if (cmpsaddr((struct sockaddr *)&sa1, (struct sockaddr *)&sa2) > CMPSADDR_WILDPORT_MATCH)
return 1;
#ifndef __linux__
@@ -274,7 +279,7 @@ cmpspidxwild(a, b)
a, b->prefd, saddr2str((struct sockaddr *)&sa1));
plog(LLV_DEBUG, LOCATION, NULL, "%p masked with /%d: %s\n",
b, b->prefd, saddr2str((struct sockaddr *)&sa2));
- if (cmpsaddrwild((struct sockaddr *)&sa1, (struct sockaddr *)&sa2))
+ if (cmpsaddr((struct sockaddr *)&sa1, (struct sockaddr *)&sa2) > CMPSADDR_WILDPORT_MATCH)
return 1;
#ifdef HAVE_SECCTX
@@ -309,6 +314,11 @@ delsp(sp)
racoon_free(req);
}
+ if (sp->local)
+ racoon_free(sp->local);
+ if (sp->remote)
+ racoon_free(sp->remote);
+
racoon_free(sp);
}
diff --git a/src/racoon/policy.h b/src/racoon/policy.h
index 8c47451..ef7f923 100644
--- a/src/racoon/policy.h
+++ b/src/racoon/policy.h
@@ -1,4 +1,4 @@
-/* $NetBSD: policy.h,v 1.5.4.2 2007/06/07 20:34:19 manu Exp $ */
+/* $NetBSD: policy.h,v 1.8 2008/12/05 06:02:20 tteras Exp $ */
/* Id: policy.h,v 1.5 2004/06/11 16:00:17 ludvigm Exp */
@@ -82,6 +82,12 @@ struct secpolicy {
struct ipsecrequest *req;
/* pointer to the ipsec request tree, */
/* if policy == IPSEC else this value == NULL.*/
+
+ /* MIPv6 needs to perform negotiation of SA using different addresses
+ * than the endpoints of the SA (CoA for the source). In that case,
+ * MIGRATE msg provides that info (before movement occurs on the MN) */
+ struct sockaddr *local;
+ struct sockaddr *remote;
};
/* Security Assocciation Index */
@@ -111,7 +117,7 @@ struct ipsecrequest {
#ifdef HAVE_PFKEY_POLICY_PRIORITY
#define KEY_SETSECSPIDX(_dir, s, d, ps, pd, ulp, _priority, _created, idx) \
do { \
- memset((idx), 0, sizeof(struct policyindex)); \
+ bzero((idx), sizeof(struct policyindex)); \
(idx)->dir = (_dir); \
(idx)->prefs = (ps); \
(idx)->prefd = (pd); \
@@ -124,7 +130,7 @@ do { \
#else
#define KEY_SETSECSPIDX(_dir, s, d, ps, pd, ulp, _created, idx) \
do { \
- memset((idx), 0, sizeof(struct policyindex)); \
+ bzero((idx), sizeof(struct policyindex)); \
(idx)->dir = (_dir); \
(idx)->prefs = (ps); \
(idx)->prefd = (pd); \
diff --git a/src/racoon/privsep.c b/src/racoon/privsep.c
index 9e60b89..55a3908 100644
--- a/src/racoon/privsep.c
+++ b/src/racoon/privsep.c
@@ -1,4 +1,4 @@
-/* $NetBSD: privsep.c,v 1.6 2006/09/09 16:22:10 manu Exp $ */
+/* $NetBSD: privsep.c,v 1.21 2011/03/06 08:28:10 tteras Exp $ */
/* Id: privsep.c,v 1.15 2005/08/08 11:23:44 vanhu Exp */
@@ -42,15 +42,17 @@
#include <signal.h>
#include <pwd.h>
+#include <sys/types.h>
#include <sys/socket.h>
#include <sys/param.h>
+#include <netinet/in.h>
+
#include "gcmalloc.h"
#include "vmbuf.h"
#include "misc.h"
#include "plog.h"
#include "var.h"
-#include "libpfkey.h"
#include "crypto_openssl.h"
#include "isakmp_var.h"
@@ -75,6 +77,28 @@ static int port_check(int);
static int unsafe_env(char *const *);
static int unknown_name(int);
static int unsafe_path(char *, int);
+static int rec_fd(int);
+static int send_fd(int, int);
+
+struct socket_args {
+ int domain;
+ int type;
+ int protocol;
+};
+
+struct sockopt_args {
+ int s;
+ int level;
+ int optname;
+ const void *optval;
+ socklen_t optlen;
+};
+
+struct bind_args {
+ int s;
+ const struct sockaddr *addr;
+ socklen_t addrlen;
+};
static int
privsep_send(sock, buf, len)
@@ -116,13 +140,19 @@ privsep_recv(sock, bufp, lenp)
sizeof(com), MSG_PEEK, NULL, NULL)) == -1) {
if (errno == EINTR)
continue;
+ if (errno == ECONNRESET)
+ return -1;
plog(LLV_ERROR, LOCATION, NULL,
"privsep_recv failed: %s\n",
strerror(errno));
return -1;
}
-
+
+ /* EOF, other side has closed. */
+ if (len == 0)
+ return -1;
+
/* Check for short packets */
if (len < sizeof(com)) {
plog(LLV_ERROR, LOCATION, NULL,
@@ -142,6 +172,8 @@ privsep_recv(sock, bufp, lenp)
com.ac_len, 0, NULL, NULL)) == -1) {
if (errno == EINTR)
continue;
+ if (errno == ECONNRESET)
+ return -1;
plog(LLV_ERROR, LOCATION, NULL,
"failed to recv privsep command: %s\n",
strerror(errno));
@@ -174,7 +206,7 @@ privsep_init(void)
/*
* When running privsep, certificate and script paths
* are mandatory, as they enable us to check path safety
- * in the privilegied instance
+ * in the privileged instance
*/
if ((lcconf->pathinfo[LC_PATHTYPE_CERT] == NULL) ||
(lcconf->pathinfo[LC_PATHTYPE_SCRIPT] == NULL)) {
@@ -183,7 +215,7 @@ privsep_init(void)
return -1;
}
- if (socketpair(PF_LOCAL, SOCK_DGRAM, 0, privsep_sock) != 0) {
+ if (socketpair(PF_LOCAL, SOCK_STREAM, 0, privsep_sock) != 0) {
plog(LLV_ERROR, LOCATION, NULL,
"Cannot allocate privsep_sock: %s\n", strerror(errno));
return -1;
@@ -197,6 +229,8 @@ privsep_init(void)
break;
case 0: /* Child: drop privileges */
+ (void)close(privsep_sock[0]);
+
if (lcconf->chroot != NULL) {
if (chdir(lcconf->chroot) != 0) {
plog(LLV_ERROR, LOCATION, NULL,
@@ -243,7 +277,7 @@ privsep_init(void)
return 0;
break;
- default: /* Parent: privilegied process */
+ default: /* Parent: privileged process */
break;
}
@@ -254,8 +288,6 @@ privsep_init(void)
for (i = sysconf(_SC_OPEN_MAX); i > 0; i--) {
if (i == privsep_sock[0])
continue;
- if (i == privsep_sock[1])
- continue;
if ((f_foreground) && (i == 1))
continue;
(void)close(i);
@@ -265,16 +297,20 @@ privsep_init(void)
ploginit();
plog(LLV_INFO, LOCATION, NULL,
- "racoon privilegied process running with PID %d\n", getpid());
+ "racoon privileged process running with PID %d\n", getpid());
-#ifdef __NetBSD__
+ plog(LLV_INFO, LOCATION, NULL,
+ "racoon unprivileged process running with PID %d\n", child_pid);
+
+#if defined(__NetBSD__) || defined(__FreeBSD__)
setproctitle("[priv]");
#endif
- /*
- * Don't catch any signal
+ /*
+ * Don't catch any signal
* This duplicate session:signals[], which is static...
*/
+ signal(SIGPIPE, SIG_IGN);
signal(SIGHUP, SIG_DFL);
signal(SIGINT, SIG_DFL);
signal(SIGTERM, SIG_DFL);
@@ -331,7 +367,7 @@ privsep_init(void)
/*
* XXX Improvement: instead of returning the key,
* stuff eay_get_pkcs1privkey and eay_get_x509sign
- * together and sign the hash in the privilegied
+ * together and sign the hash in the privileged
* instance?
* pro: the key remains inaccessible to unpriv
* con: a compromised unpriv racoon can still sign anything
@@ -503,6 +539,154 @@ privsep_init(void)
break;
}
+ case PRIVSEP_SOCKET: {
+ struct socket_args socket_args;
+ int s;
+
+ /* Make sure the string is NULL terminated */
+ if (safety_check(combuf, 0) != 0)
+ break;
+
+ if (combuf->bufs.buflen[0] !=
+ sizeof(struct socket_args)) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "privsep_socket: corrupted message\n");
+ goto out;
+ }
+ memcpy(&socket_args, bufs[0],
+ sizeof(struct socket_args));
+
+ if (socket_args.domain != PF_INET &&
+ socket_args.domain != PF_INET6) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "privsep_socket: "
+ "unauthorized domain (%d)\n",
+ socket_args.domain);
+ goto out;
+ }
+
+ if ((s = socket(socket_args.domain, socket_args.type,
+ socket_args.protocol)) == -1) {
+ reply->hdr.ac_errno = errno;
+ break;
+ }
+
+ if (send_fd(privsep_sock[0], s) < 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "privsep_socket: send_fd failed\n");
+ close(s);
+ goto out;
+ }
+
+ close(s);
+ break;
+ }
+
+ case PRIVSEP_BIND: {
+ struct bind_args bind_args;
+ int err, port = 0;
+
+ /* Make sure the string is NULL terminated */
+ if (safety_check(combuf, 0) != 0)
+ break;
+
+ if (combuf->bufs.buflen[0] !=
+ sizeof(struct bind_args)) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "privsep_bind: corrupted message\n");
+ goto out;
+ }
+ memcpy(&bind_args, bufs[0], sizeof(struct bind_args));
+
+ if (combuf->bufs.buflen[1] != bind_args.addrlen) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "privsep_bind: corrupted message\n");
+ goto out;
+ }
+ bind_args.addr = (const struct sockaddr *)bufs[1];
+
+ if ((bind_args.s = rec_fd(privsep_sock[0])) < 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "privsep_bind: rec_fd failed\n");
+ goto out;
+ }
+
+ port = extract_port(bind_args.addr);
+ if (port != PORT_ISAKMP && port != PORT_ISAKMP_NATT &&
+ port != lcconf->port_isakmp &&
+ port != lcconf->port_isakmp_natt) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "privsep_bind: "
+ "unauthorized port (%d)\n",
+ port);
+ close(bind_args.s);
+ goto out;
+ }
+
+ err = bind(bind_args.s, bind_args.addr,
+ bind_args.addrlen);
+
+ if (err)
+ reply->hdr.ac_errno = errno;
+
+ close(bind_args.s);
+ break;
+ }
+
+ case PRIVSEP_SETSOCKOPTS: {
+ struct sockopt_args sockopt_args;
+ int err;
+
+ /* Make sure the string is NULL terminated */
+ if (safety_check(combuf, 0) != 0)
+ break;
+
+ if (combuf->bufs.buflen[0] !=
+ sizeof(struct sockopt_args)) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "privsep_setsockopt: "
+ "corrupted message\n");
+ goto out;
+ }
+ memcpy(&sockopt_args, bufs[0],
+ sizeof(struct sockopt_args));
+
+ if (combuf->bufs.buflen[1] != sockopt_args.optlen) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "privsep_setsockopt: corrupted message\n");
+ goto out;
+ }
+ sockopt_args.optval = bufs[1];
+
+ if (sockopt_args.optname !=
+ (sockopt_args.level ==
+ IPPROTO_IP ? IP_IPSEC_POLICY :
+ IPV6_IPSEC_POLICY)) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "privsep_setsockopt: "
+ "unauthorized option (%d)\n",
+ sockopt_args.optname);
+ goto out;
+ }
+
+ if ((sockopt_args.s = rec_fd(privsep_sock[0])) < 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "privsep_setsockopt: rec_fd failed\n");
+ goto out;
+ }
+
+ err = setsockopt(sockopt_args.s,
+ sockopt_args.level,
+ sockopt_args.optname,
+ sockopt_args.optval,
+ sockopt_args.optlen);
+ if (err)
+ reply->hdr.ac_errno = errno;
+
+ close(sockopt_args.s);
+ break;
+ }
+
#ifdef ENABLE_HYBRID
case PRIVSEP_ACCOUNTING_SYSTEM: {
int pool_size;
@@ -687,14 +871,17 @@ privsep_init(void)
/* This frees reply */
if (privsep_send(privsep_sock[0],
- reply, reply->hdr.ac_len) != 0)
+ reply, reply->hdr.ac_len) != 0) {
+ racoon_free(reply);
goto out;
+ }
racoon_free(combuf);
}
out:
- plog(LLV_INFO, LOCATION, NULL, "privsep exit\n");
+ plog(LLV_INFO, LOCATION, NULL,
+ "racoon privileged process %d terminated\n", getpid());
_exit(0);
}
@@ -745,37 +932,6 @@ out:
return NULL;
}
-/*
- * No prigilege separation trick here, we just open PFKEY before
- * dropping root privs and we remember it later.
- */
-static int pfkey_socket = -1;
-int
-privsep_pfkey_open(void)
-{
- int ps;
-
- if (pfkey_socket != -1)
- return pfkey_socket;
-
- ps = pfkey_open();
- if (ps != -1)
- pfkey_socket = ps;
-
- return ps;
-}
-
-/*
- * Consequence of the above trickery: don't
- * really close PFKEY as we never re-open it.
- */
-void
-privsep_pfkey_close(ps)
- int ps;
-{
- return;
-}
-
int
privsep_script_exec(script, name, envp)
char *script;
@@ -941,6 +1097,224 @@ out:
return NULL;
}
+/*
+ * Create a privileged socket. On BSD systems a socket obtains special
+ * capabilities if it is created by root; setsockopt(IP_IPSEC_POLICY) will
+ * succeed but will be ineffective if performed on an unprivileged socket.
+ */
+int
+privsep_socket(domain, type, protocol)
+ int domain;
+ int type;
+ int protocol;
+{
+ struct privsep_com_msg *msg;
+ size_t len;
+ char *data;
+ struct socket_args socket_args;
+ int s, saved_errno = 0;
+
+ if (geteuid() == 0)
+ return socket(domain, type, protocol);
+
+ len = sizeof(*msg) + sizeof(socket_args);
+
+ if ((msg = racoon_malloc(len)) == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "Cannot allocate memory: %s\n", strerror(errno));
+ return -1;
+ }
+ bzero(msg, len);
+ msg->hdr.ac_cmd = PRIVSEP_SOCKET;
+ msg->hdr.ac_len = len;
+
+ socket_args.domain = domain;
+ socket_args.type = type;
+ socket_args.protocol = protocol;
+
+ data = (char *)(msg + 1);
+ msg->bufs.buflen[0] = sizeof(socket_args);
+ memcpy(data, &socket_args, msg->bufs.buflen[0]);
+
+ /* frees msg */
+ if (privsep_send(privsep_sock[1], msg, len) != 0)
+ goto out;
+
+ /* Get the privileged socket descriptor from the privileged process. */
+ if ((s = rec_fd(privsep_sock[1])) == -1)
+ return -1;
+
+ if (privsep_recv(privsep_sock[1], &msg, &len) != 0)
+ goto out;
+
+ if (msg->hdr.ac_errno != 0) {
+ errno = msg->hdr.ac_errno;
+ goto out;
+ }
+
+ racoon_free(msg);
+ return s;
+
+out:
+ racoon_free(msg);
+ return -1;
+}
+
+/*
+ * Bind() a socket to a port. This works just like regular bind(), except that
+ * if you want to bind to the designated isakmp ports and you don't have the
+ * privilege to do so, it will ask a privileged process to do it.
+ */
+int
+privsep_bind(s, addr, addrlen)
+ int s;
+ const struct sockaddr *addr;
+ socklen_t addrlen;
+{
+ struct privsep_com_msg *msg;
+ size_t len;
+ char *data;
+ struct bind_args bind_args;
+ int err, saved_errno = 0;
+
+ err = bind(s, addr, addrlen);
+ if ((err == 0) || (saved_errno = errno) != EACCES || geteuid() == 0) {
+ if (saved_errno)
+ plog(LLV_ERROR, LOCATION, NULL,
+ "privsep_bind (%s) = %d\n", strerror(saved_errno), err);
+ errno = saved_errno;
+ return err;
+ }
+
+ len = sizeof(*msg) + sizeof(bind_args) + addrlen;
+
+ if ((msg = racoon_malloc(len)) == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "Cannot allocate memory: %s\n", strerror(errno));
+ return -1;
+ }
+ bzero(msg, len);
+ msg->hdr.ac_cmd = PRIVSEP_BIND;
+ msg->hdr.ac_len = len;
+
+ bind_args.s = -1;
+ bind_args.addr = NULL;
+ bind_args.addrlen = addrlen;
+
+ data = (char *)(msg + 1);
+ msg->bufs.buflen[0] = sizeof(bind_args);
+ memcpy(data, &bind_args, msg->bufs.buflen[0]);
+
+ data += msg->bufs.buflen[0];
+ msg->bufs.buflen[1] = addrlen;
+ memcpy(data, addr, addrlen);
+
+ /* frees msg */
+ if (privsep_send(privsep_sock[1], msg, len) != 0)
+ goto out;
+
+ /* Send the socket descriptor to the privileged process. */
+ if (send_fd(privsep_sock[1], s) < 0)
+ return -1;
+
+ if (privsep_recv(privsep_sock[1], &msg, &len) != 0)
+ goto out;
+
+ if (msg->hdr.ac_errno != 0) {
+ errno = msg->hdr.ac_errno;
+ goto out;
+ }
+
+ racoon_free(msg);
+ return 0;
+
+out:
+ racoon_free(msg);
+ return -1;
+}
+
+/*
+ * Set socket options. This works just like regular setsockopt(), except that
+ * if you want to change IP_IPSEC_POLICY or IPV6_IPSEC_POLICY and you don't
+ * have the privilege to do so, it will ask a privileged process to do it.
+ */
+int
+privsep_setsockopt(s, level, optname, optval, optlen)
+ int s;
+ int level;
+ int optname;
+ const void *optval;
+ socklen_t optlen;
+{
+ struct privsep_com_msg *msg;
+ size_t len;
+ char *data;
+ struct sockopt_args sockopt_args;
+ int err, saved_errno = 0;
+
+ if ((err = setsockopt(s, level, optname, optval, optlen) == 0) ||
+ (saved_errno = errno) != EACCES ||
+ geteuid() == 0) {
+ if (saved_errno)
+ plog(LLV_ERROR, LOCATION, NULL,
+ "privsep_setsockopt (%s)\n",
+ strerror(saved_errno));
+
+ errno = saved_errno;
+ return err;
+ }
+
+ len = sizeof(*msg) + sizeof(sockopt_args) + optlen;
+
+ if ((msg = racoon_malloc(len)) == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "Cannot allocate memory: %s\n", strerror(errno));
+ return -1;
+ }
+ bzero(msg, len);
+ msg->hdr.ac_cmd = PRIVSEP_SETSOCKOPTS;
+ msg->hdr.ac_len = len;
+
+ sockopt_args.s = -1;
+ sockopt_args.level = level;
+ sockopt_args.optname = optname;
+ sockopt_args.optval = NULL;
+ sockopt_args.optlen = optlen;
+
+ data = (char *)(msg + 1);
+ msg->bufs.buflen[0] = sizeof(sockopt_args);
+ memcpy(data, &sockopt_args, msg->bufs.buflen[0]);
+
+ data += msg->bufs.buflen[0];
+ msg->bufs.buflen[1] = optlen;
+ memcpy(data, optval, optlen);
+
+ /* frees msg */
+ if (privsep_send(privsep_sock[1], msg, len) != 0)
+ goto out;
+
+ if (send_fd(privsep_sock[1], s) < 0)
+ return -1;
+
+ if (privsep_recv(privsep_sock[1], &msg, &len) != 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "privsep_recv failed\n");
+ goto out;
+ }
+
+ if (msg->hdr.ac_errno != 0) {
+ errno = msg->hdr.ac_errno;
+ goto out;
+ }
+
+ racoon_free(msg);
+ return 0;
+
+out:
+ racoon_free(msg);
+ return -1;
+}
+
#ifdef ENABLE_HYBRID
int
privsep_xauth_login_system(usr, pwd)
@@ -972,6 +1346,7 @@ privsep_xauth_login_system(usr, pwd)
msg->bufs.buflen[1] = strlen(pwd) + 1;
memcpy(data, pwd, msg->bufs.buflen[1]);
+ /* frees msg */
if (privsep_send(privsep_sock[1], msg, len) != 0)
return -1;
@@ -1034,6 +1409,7 @@ privsep_accounting_system(port, raddr, usr, inout)
data += msg->bufs.buflen[2];
memcpy(data, &inout, msg->bufs.buflen[3]);
+ /* frees msg */
if (privsep_send(privsep_sock[1], msg, len) != 0)
return -1;
@@ -1089,7 +1465,7 @@ safety_check(msg, index)
}
/*
- * Filter unsafe environement variables
+ * Filter unsafe environment variables
*/
static int
unsafe_env(envp)
@@ -1110,7 +1486,7 @@ unsafe_env(envp)
return 0;
found:
plog(LLV_ERROR, LOCATION, NULL,
- "privsep_script_exec: unsafe environement variable\n");
+ "privsep_script_exec: unsafe environment variable\n");
return -1;
}
@@ -1161,6 +1537,86 @@ unknown_name(name)
return 0;
}
+/* Receive a file descriptor through the argument socket */
+static int
+rec_fd(s)
+ int s;
+{
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ int *fdptr;
+ int fd;
+ char cmsbuf[1024];
+ struct iovec iov;
+ char iobuf[1];
+
+ iov.iov_base = iobuf;
+ iov.iov_len = 1;
+
+ if (sizeof(cmsbuf) < CMSG_SPACE(sizeof(fd))) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "send_fd: buffer size too small\n");
+ return -1;
+ }
+ bzero(&msg, sizeof(msg));
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = cmsbuf;
+ msg.msg_controllen = CMSG_SPACE(sizeof(fd));
+
+ if (recvmsg(s, &msg, MSG_WAITALL) == -1)
+ return -1;
+
+ cmsg = CMSG_FIRSTHDR(&msg);
+ fdptr = (int *) CMSG_DATA(cmsg);
+ return fdptr[0];
+}
+
+/* Send the file descriptor fd through the argument socket s */
+static int
+send_fd(s, fd)
+ int s;
+ int fd;
+{
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ char cmsbuf[1024];
+ struct iovec iov;
+ int *fdptr;
+
+ iov.iov_base = " ";
+ iov.iov_len = 1;
+
+ if (sizeof(cmsbuf) < CMSG_SPACE(sizeof(fd))) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "send_fd: buffer size too small\n");
+ return -1;
+ }
+ bzero(&msg, sizeof(msg));
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = cmsbuf;
+ msg.msg_controllen = CMSG_SPACE(sizeof(fd));
+ msg.msg_flags = 0;
+
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
+ fdptr = (int *)CMSG_DATA(cmsg);
+ fdptr[0] = fd;
+ msg.msg_controllen = cmsg->cmsg_len;
+
+ if (sendmsg(s, &msg, 0) == -1)
+ return -1;
+
+ return 0;
+}
+
#ifdef HAVE_LIBPAM
int
privsep_accounting_pam(port, inout)
@@ -1202,6 +1658,7 @@ privsep_accounting_pam(port, inout)
*inout_data = inout;
*pool_size_data = isakmp_cfg_config.pool_size;
+ /* frees msg */
if (privsep_send(privsep_sock[1], msg, len) != 0)
return -1;
@@ -1272,6 +1729,7 @@ privsep_xauth_login_pam(port, raddr, usr, pwd)
data += msg->bufs.buflen[3];
memcpy(data, pwd, msg->bufs.buflen[4]);
+ /* frees msg */
if (privsep_send(privsep_sock[1], msg, len) != 0)
return -1;
@@ -1324,6 +1782,7 @@ privsep_cleanup_pam(port)
data += msg->bufs.buflen[0];
memcpy(data, &isakmp_cfg_config.pool_size, msg->bufs.buflen[1]);
+ /* frees msg */
if (privsep_send(privsep_sock[1], msg, len) != 0)
return;
diff --git a/src/racoon/privsep.h b/src/racoon/privsep.h
index 0fa4363..732743c 100644
--- a/src/racoon/privsep.h
+++ b/src/racoon/privsep.h
@@ -1,4 +1,4 @@
-/* $NetBSD: privsep.h,v 1.4 2006/09/09 16:22:10 manu Exp $ */
+/* $NetBSD: privsep.h,v 1.6 2008/12/08 06:00:54 tteras Exp $ */
/* Id: privsep.h,v 1.5 2005/06/07 12:22:11 fredsen Exp */
@@ -42,6 +42,9 @@
#define PRIVSEP_XAUTH_LOGIN_PAM 0x0807 /* admin_com_bufs follows */
#define PRIVSEP_CLEANUP_PAM 0x0808 /* admin_com_bufs follows */
#define PRIVSEP_ACCOUNTING_SYSTEM 0x0809 /* admin_com_bufs follows */
+#define PRIVSEP_SETSOCKOPTS 0x080A /* admin_com_bufs follows */
+#define PRIVSEP_BIND 0x080B /* admin_com_bufs follows */
+#define PRIVSEP_SOCKET 0x080C /* admin_com_bufs follows */
#define PRIVSEP_NBUF_MAX 24
#define PRIVSEP_BUFLEN_MAX 4096
@@ -58,9 +61,10 @@ struct privsep_com_msg {
int privsep_init __P((void));
vchar_t *privsep_eay_get_pkcs1privkey __P((char *));
-int privsep_pfkey_open __P((void));
-void privsep_pfkey_close __P((int));
int privsep_script_exec __P((char *, int, char * const *));
+int privsep_setsockopt __P((int, int, int, const void *, socklen_t));
+int privsep_socket __P((int, int, int));
+int privsep_bind __P((int, const struct sockaddr *, socklen_t));
vchar_t *privsep_getpsk __P((const char *, const int));
int privsep_xauth_login_system __P((char *, char *));
#ifdef HAVE_LIBPAM
diff --git a/src/racoon/proposal.c b/src/racoon/proposal.c
index 26c9274..33dd311 100644
--- a/src/racoon/proposal.c
+++ b/src/racoon/proposal.c
@@ -1,6 +1,6 @@
-/* $NetBSD: proposal.c,v 1.13.4.2 2008/07/22 13:25:42 vanhu Exp $ */
+/* $NetBSD: proposal.c,v 1.17 2008/09/19 11:14:49 tteras Exp $ */
-/* $Id: proposal.c,v 1.13.4.2 2008/07/22 13:25:42 vanhu Exp $ */
+/* $Id: proposal.c,v 1.17 2008/09/19 11:14:49 tteras Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -1186,10 +1186,10 @@ set_proposal_from_proposal(iph2)
* make my proposal according as the client proposal.
* XXX assumed there is only one proposal even if it's the SA bundle.
*/
- for (i = 0; i < MAXPROPPAIRLEN; i++) {
- if (pair[i] == NULL)
- continue;
-
+ for (i = 0; i < MAXPROPPAIRLEN; i++) {
+ if (pair[i] == NULL)
+ continue;
+
if (pp_peer != NULL)
flushsaprop(pp_peer);
@@ -1226,8 +1226,6 @@ set_proposal_from_proposal(iph2)
for (pr = pp_peer->head; pr; pr = pr->next)
{
- struct remoteconf *conf;
-
newpr = newsaproto();
if (newpr == NULL)
{
@@ -1244,9 +1242,7 @@ set_proposal_from_proposal(iph2)
newpr->reqid_in = 0;
newpr->reqid_out = 0;
- conf = getrmconf(iph2->dst);
- if (conf != NULL &&
- conf->gen_policy == GENERATE_POLICY_UNIQUE){
+ if (iph2->ph1->rmconf->gen_policy == GENERATE_POLICY_UNIQUE){
newpr->reqid_in = g_nextreqid ;
newpr->reqid_out = g_nextreqid ++;
/*
diff --git a/src/racoon/proposal.h b/src/racoon/proposal.h
index 60fc531..11fbab8 100644
--- a/src/racoon/proposal.h
+++ b/src/racoon/proposal.h
@@ -1,4 +1,4 @@
-/* $NetBSD: proposal.h,v 1.6 2006/12/09 05:52:57 manu Exp $ */
+/* $NetBSD: proposal.h,v 1.7 2010/02/09 23:05:16 wiz Exp $ */
/* Id: proposal.h,v 1.5 2004/06/11 16:00:17 ludvigm Exp */
@@ -88,7 +88,7 @@ struct saproto {
int reqid_out; /* request id (outbound) */
int reqid_in; /* request id (inbound) */
- int ok; /* if 1, success to set SA in kenrel */
+ int ok; /* if 1, success to set SA in kernel */
struct satrns *head; /* header of transform */
struct saproto *next; /* next protocol */
diff --git a/src/racoon/prsa_par.h b/src/racoon/prsa_par.h
index 3bdb11d..6e845d8 100644
--- a/src/racoon/prsa_par.h
+++ b/src/racoon/prsa_par.h
@@ -1,24 +1,23 @@
-/* A Bison parser, made by GNU Bison 2.3. */
-/* Skeleton interface for Bison's Yacc-like parsers in C
+/* A Bison parser, made by GNU Bison 2.4.1. */
- Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+/* Skeleton interface for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
+
+ This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
@@ -29,10 +28,11 @@
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
-
+
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
+
/* Tokens. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
@@ -90,21 +90,27 @@
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
-#line 130 "prsa_par.y"
{
+
+/* Line 1676 of yacc.c */
+#line 130 "prsa_par.y"
+
BIGNUM *bn;
RSA *rsa;
char *chr;
long num;
struct netaddr *naddr;
-}
-/* Line 1489 of yacc.c. */
-#line 103 "prsa_par.h"
- YYSTYPE;
+
+
+
+/* Line 1676 of yacc.c */
+#line 108 "prsa_par.h"
+} YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
#endif
extern YYSTYPE prsalval;
+
diff --git a/src/racoon/prsa_par.y b/src/racoon/prsa_par.y
index f21a82b..1987e4d 100644
--- a/src/racoon/prsa_par.y
+++ b/src/racoon/prsa_par.y
@@ -1,4 +1,4 @@
-/* $NetBSD: prsa_par.y,v 1.4 2006/09/09 16:22:10 manu Exp $ */
+/* $NetBSD: prsa_par.y,v 1.6 2011/03/02 14:49:21 vanhu Exp $ */
/* Id: prsa_par.y,v 1.3 2004/11/08 12:04:23 ludvigm Exp */
@@ -211,6 +211,7 @@ rsa_statement:
YYABORT;
}
$$ = base64_pubkey2rsa($2);
+ free($2);
}
| TAG_PUB HEX
{
@@ -236,6 +237,7 @@ addr4:
{
int err;
struct sockaddr_in *sap;
+ struct addrinfo hints, *res;
if ($2 == -1) $2 = 32;
if ($2 < 0 || $2 > 32) {
@@ -245,12 +247,17 @@ addr4:
$$ = calloc (sizeof(struct netaddr), 1);
$$->prefix = $2;
sap = (struct sockaddr_in *)(&$$->sa);
- sap->sin_family = AF_INET;
- err = inet_pton(AF_INET, $1, (struct in_addr*)(&sap->sin_addr));
- if (err <= 0) {
- prsaerror("inet_pton(%s): %s\n", $1, strerror(errno));
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET;
+ hints.ai_flags = AI_NUMERICHOST;
+ err = getaddrinfo($1, NULL, &hints, &res);
+ if (err < 0) {
+ prsaerror("getaddrinfo(%s): %s\n", $1, gai_strerror(err));
YYABORT;
}
+ memcpy(sap, res->ai_addr, res->ai_addrlen);
+ freeaddrinfo(res);
+ free($1);
}
;
@@ -259,6 +266,7 @@ addr6:
{
int err;
struct sockaddr_in6 *sap;
+ struct addrinfo hints, *res;
if ($2 == -1) $2 = 128;
if ($2 < 0 || $2 > 128) {
@@ -268,12 +276,17 @@ addr6:
$$ = calloc (sizeof(struct netaddr), 1);
$$->prefix = $2;
sap = (struct sockaddr_in6 *)(&$$->sa);
- sap->sin6_family = AF_INET6;
- err = inet_pton(AF_INET6, $1, (struct in6_addr*)(&sap->sin6_addr));
- if (err <= 0) {
- prsaerror("inet_pton(%s): %s\n", $1, strerror(errno));
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET6;
+ hints.ai_flags = AI_NUMERICHOST;
+ err = getaddrinfo($1, NULL, &hints, &res);
+ if (err < 0) {
+ prsaerror("getaddrinfo(%s): %s\n", $1, gai_strerror(err));
YYABORT;
}
+ memcpy(sap, res->ai_addr, res->ai_addrlen);
+ freeaddrinfo(res);
+ free($1);
}
;
diff --git a/src/racoon/racoon.8 b/src/racoon/racoon.8
index a6d39d7..58fefdd 100644
--- a/src/racoon/racoon.8
+++ b/src/racoon/racoon.8
@@ -1,4 +1,4 @@
-.\" $NetBSD: racoon.8,v 1.10 2006/09/09 16:22:10 manu Exp $
+.\" $NetBSD: racoon.8,v 1.12 2009/01/24 10:42:31 wiz Exp $
.\"
.\" Id: racoon.8,v 1.4 2005/04/18 11:07:55 manubsd Exp
.\"
@@ -29,7 +29,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd November 20, 2000
+.Dd January 23, 2009
.Dt RACOON 8
.Os
.\"
@@ -40,7 +40,7 @@
.Sh SYNOPSIS
.Nm racoon
.Bk -words
-.Op Fl 46BdFLv
+.Op Fl 46BdFLVv
.Ek
.Bk -words
.Op Fl f Ar configfile
@@ -115,6 +115,8 @@ The default is 4500.
Listen to the ISAKMP key exchange on port
.Ar isakmp-port
instead of the default port number, 500.
+.It Fl V
+Print racoon version and compilation options and exit.
.It Fl v
This flag causes the packet dump be more verbose, with higher
debugging level.
diff --git a/src/racoon/racoon.conf.5 b/src/racoon/racoon.conf.5
index 9ddee80..70c7eda 100644
--- a/src/racoon/racoon.conf.5
+++ b/src/racoon/racoon.conf.5
@@ -1,4 +1,4 @@
-.\" $NetBSD: racoon.conf.5,v 1.34.4.3 2007/09/03 18:07:29 mgrooms Exp $
+.\" $NetBSD: racoon.conf.5,v 1.61 2010/06/22 20:51:04 wiz Exp $
.\"
.\" Id: racoon.conf.5,v 1.54 2006/08/22 18:17:17 manubsd Exp
.\"
@@ -29,7 +29,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd September 19, 2006
+.Dd June 22, 2010
.Dt RACOON.CONF 5
.Os
.\"
@@ -152,7 +152,7 @@ The user to which the unprivileged instance of
should switch.
This can be a quoted user name or a numeric UID.
.It Ic group Ar group ;
-The group the unprivilegied instance of
+The group the unprivileged instance of
.Xr racoon 8 ,
should switch.
This can be a quoted group name or a numeric GID.
@@ -184,7 +184,8 @@ When running in privilege separation mode,
.Ic certificate
and
.Ic script
-paths are mandatory. A
+paths are mandatory.
+A
.Xr racoon 8
restart is required if you want path changes to be taken into account.
.Bl -tag -width Ds -compact
@@ -223,7 +224,8 @@ will refuse to execute a script stored outside of this directory.
Specifies file where to store PID of process.
If path starts with
.Pa /
-it is treated as an absolute path. Otherwise, it is treated as a relative
+it is treated as an absolute path.
+Otherwise, it is treated as a relative
path to the VARRUN directory specified at compilation time.
Default is
.Pa racoon.pid .
@@ -235,12 +237,6 @@ Default is
Specifies other configuration files to be included.
.El
.\"
-.Ss Identifier Specification
-is obsolete.
-It must be defined at each
-.Ic remote
-directive.
-.\"
.Ss Timer Specification
.Bl -tag -width Ds -compact
.It Ic timer { Ar statements Ic }
@@ -319,12 +315,14 @@ The
.Ar owner ,
and
.Ar group
-values specify the socket path, owner, and group. They must be quoted.
+values specify the socket path, owner, and group.
+They must be quoted.
The defaults are
.Pa /var/racoon/racoon.sock ,
UID 0, and GID 0.
.Ar mode
-is the access mode in octal. The default is 0600.
+is the access mode in octal.
+The default is 0600.
.It Ic adminsock disabled ;
This directive tells racoon to not listen on the admin socket.
.El
@@ -360,22 +358,66 @@ This is the encoding used by older versions of
.El
.El
.\"
+.Pp
+.Bl -tag -width Ds -compact
+.It Ic pfkey_buffer Ar kBytes
+Specifies the socket send/receive buffer size in kilobytes.
+Numerous kernel PF_KEY implementations have problems with dumping
+SAD/SDP with large amount of entries (this happens when 100s to
+1000s of tunnels are configured).
+.Pp
+The default value of 0 leaves everything at the OS-specific default value.
+If the default buffer size is greater than what is specified here racoon
+will not decrease it.
+.Pp
+This problem is known to be fixed in Linux 2.6.25 and later.
+.El
+.\"
.Ss Remote Nodes Specifications
.Bl -tag -width Ds -compact
-.It Xo
-.Ic remote ( Ar address | Ic anonymous )
-.Bq Bq Ar port
-.Bq Ic inherit Ar parent
-.Ic { Ar statements Ic }
-.Xc
+.It Ic remote Ar name Bo Ic inherit Ar parent_name Bc Ic { Ar statements Ic }
Specifies the IKE phase 1 parameters for each remote node.
-The default port is 500.
-If
-.Ic anonymous
-is specified, the statements will apply to any peer that does not match a
-more specific
-.Ic remote
-directive.
+.Pp
+If connection is initiated using racoonctl, a unique match using the
+remote IP must be found or the remote block name has to be given.
+For received acquires (kernel notices traffic requiring a new SA) the
+remote IP and remoteid from matching sainfo block are used to decide
+the remoteblock.
+If no uniquely matching remoteblock is found using
+these criteria, no connection attempt is done.
+.Pp
+When acting as responder, racoon picks the first proposal that has one
+or more acceptable remote configurations.
+When determining if a remote
+specification is matching the following information is checked:
+.Bl -bullet -width Ds -compact
+.It
+The remote IP is checked against
+.Ic remote_address .
+.It
+ISAKMP exchange type is checked against
+.Ic exchange_mode .
+.It
+ISAKMP SA attributes must match a
+.Ic proposal
+block.
+.It
+The remote identity is matched against
+.Ic peers_identifier
+if
+.Ic verify_identifier
+is on.
+.It
+If a certificate request was received, it must match the issuer of
+.Ic "certificate_type x509"
+certificate.
+If certificate request without issuer name was sent, the
+.Ic match_empty_cr
+parameter specifies whether or not remote block matches.
+.El
+.Pp
+Similarly, NAT-T is enabled if any of the initial remote configuration
+candidates allow NAT-T.
.Pp
Sections with
.Ic inherit Ar parent
@@ -393,6 +435,9 @@ The following are valid statements.
.Pp
.Bl -tag -width Ds -compact
.\"
+.It Ic remote_address Ar address ;
+Defines the IP address of the peer.
+.\"
.It Ic exchange_mode ( main | aggressive | base ) ;
Defines the exchange mode for phase 1 when racoon is the initiator.
It also means the acceptable exchange mode when racoon is the responder.
@@ -408,14 +453,7 @@ You can omit this statement.
Means to use SIT_IDENTITY_ONLY as specified in RFC 2407.
You can omit this statement.
.\"
-.It Ic identifier Ar idtype ;
-This statment is obsolete. Instead, use
-.Ic my_identifier .
-.\"
-.It Xo
-.Ic my_identifier Bq Ar qualifier
-.Ar idtype ... ;
-.Xc
+.It Ic my_identifier Bo Ar qualifier Bc Ar idtype ... ;
Specifies the identifier sent to the remote host
and the type to use in the phase 1 negotiation.
.Ic address, fqdn , user_fqdn , keyid ,
@@ -440,10 +478,7 @@ This is the default type if you do not specify an identifier to use.
The type is a USER_FQDN (user fully-qualified domain name).
.It Ic my_identifier Ic fqdn Ar string ;
The type is a FQDN (fully-qualified domain name).
-.It Xo
-.Ic my_identifier Ic keyid Bq Ic file
-.Ar file ;
-.Xc
+.It Ic my_identifier Ic keyid Bo Ic file Bc Ar file ;
The type is a KEY_ID, read from the file.
.It Ic my_identifier Ic keyid Ic tag Ar string ;
The type is a KEY_ID, specified in the quoted string.
@@ -482,6 +517,13 @@ except that the individual component values of an
identifier may specified as
.Ic *
to match any value (e.g. "C=XX, O=MyOrg, OU=*, CN=Mine").
+The format of the
+specification should correspond to RFC 2253; in particular, commas and certain
+other characters -
+.Ic ,=+\*[Lt]\*[Gt]#;
+- may be included in a name by preceeding them with a backslash "\e", and
+arbitrary characters may be inserted in a name with the "\enn" escape, where
+nn is the hex representation of the ascii value of the desired character.
Alternative acceptable peer identifiers may be specified by repeating the
.Ic peers_identifier
statement.
@@ -509,7 +551,9 @@ means a file name of a secret key.
.Bl -tag -width Ds -compact
.It Ic plain_rsa Ar privkeyfile ;
.Ar privkeyfile
-means a file name of a private key generated by plainrsa-gen(8). Required
+means a file name of a private key generated by
+.Xr plainrsa-gen 8 .
+Required
for RSA authentication.
.El
.It Ic ca_type Ar cacertspec ;
@@ -553,16 +597,20 @@ is defined,
.Xr racoon 8
will expect
.Ar pubkeyfile
-to be the peer's public key that was generated
-by plainrsa-gen(8).
+to be the peer's public key that was generated by
+.Xr plainrsa-gen 8 .
.\"
.It Ic script Ar script Ic phase1_up
.It Ic script Ar script Ic phase1_down
-Shell scripts that get executed when a phase 1 SA goes up or down.
-Both scripts get either
+.It Ic script Ar script Ic phase1_dead
+Shell scripts that get executed when a phase 1 SA goes up or down, or
+when it is detected as dead by DPD.
+All scripts get either
.Ic phase1_up
-or
+,
.Ic phase1_down
+or
+.Ic phase1_dead
as first argument, and the following
variables are set in their environment:
.Bl -tag -width Ds -compact
@@ -574,6 +622,8 @@ The local port used for IKE for the phase 1 SA.
The remote address of the phase 1 SA.
.It Ev REMOTE_PORT
The remote port used for IKE for the phase 1 SA.
+.It Ev REMOTE_ID
+The remote identity received in IKE for the phase 1 SA.
.El
The following variables are only set if
.Ic mode_cfg
@@ -604,6 +654,10 @@ SPLIT_INCLUDE and SPLIT_LOCAL are mutually exclusive.
The space separated list of IPv4 addresses and masks (address slash mask)
that define the networks to be considered local, and thus excluded from the
tunnels ; obtained by ISAKMP mode config.
+.It SPLIT_INCLUDE_CIDR
+Same as SPLIT_INCLUDE, with netmasks in CIDR notation.
+.It SPLIT_LOCAL_CIDR
+Same as SPLIT_LOCAL, with netmasks in CIDR notation.
.It DEFAULT_DOMAIN
The DNS default domain name obtained by ISAKMP mode config.
.El
@@ -617,16 +671,21 @@ The default is on.
If you do not want to send a certificate request, set this to off.
The default is on.
.\"
+.It Ic match_empty_cr (on | off) ;
+Specifies whether this remote block is a valid match when a non-specific
+certificate request is received.
+The default is on.
+.\"
.It Ic verify_cert (on | off) ;
By default, the identifier sent by the remote host (as specified in its
.Ic my_identifier
statement) is compared with the credentials in the certificate
used to authenticate the remote host as follows:
.Bl -tag -width Ds -compact
-.It Type Ic asn1dn:
+.It Type Ic asn1dn :
The entire certificate subject name is compared with the identifier,
e.g. "C=XX, O=YY, ...".
-.It Type Ic address, fqdn, or user_fqdn:
+.It Type Ic address, fqdn, or user_fqdn :
The certificate's subjectAltName is compared with the identifier.
.El
If the two do not match the negotiation will fail.
@@ -692,7 +751,7 @@ The default value is
It is useful for a server.
.\"
.It Ic proposal_check Ar level ;
-Specifies the action of lifetime length, key length and PFS of the phase 2
+Specifies the action of lifetime length, key length, and PFS of the phase 2
selection on the responder side, and the action of lifetime check in
phase 1.
The default level is
@@ -812,6 +871,22 @@ is set, this sets the maximum number of liveliness proofs to request
The default value is
.Ic 5 .
.\"
+.It Ic rekey (on | off | force) ;
+Enable automatic renegotiation of expired phase1 when there are non-dying
+phase2 SAs.
+Possible values are:
+.Bl -tag -width Ds -compact
+.It Ic force
+Rekeying is done unconditionally.
+.It Ic on
+Rekeying is done only if DPD monitoring is active.
+This is the default.
+.It Ic off
+No automatic rekeying.
+Do note that turning off automatic rekeying will
+result in inaccurate DPD monitoring.
+.El
+.\"
.It Ic nonce_size Ar number ;
define the byte size of nonce value.
Racoon can send any value although
@@ -819,13 +894,11 @@ RFC2409 specifies that the value MUST be between 8 and 256 bytes.
The default size is 16 bytes.
.\"
.It Ic ph1id Ar number ;
-An optionnal number to identify the remote proposal and to link it
+An optional number to identify the remote proposal and to link it
only with sainfos who have the same number.
Defaults to 0.
.\"
-.It Xo
-.Ic proposal { Ar sub-substatements Ic }
-.Xc
+.It Ic proposal { Ar sub-substatements Ic }
.Bl -tag -width Ds -compact
.\"
.It Ic encryption_algorithm Ar algorithm ;
@@ -888,30 +961,35 @@ is used, where hostname is the value returned by the
command.
.El
.El
+.Pp
+.It Ic remote Po Ar address | Ic anonymous Pc Bo Bo Ar port Bc Bc \
+Bo Ic inherit Ar parent Bc Ic { Ar statements Ic }
+Deprecated format of specifying a remote block.
+This will be removed in future.
+It is a remnant from time when remote block was decided
+solely based on the peers IP address.
+.Pp
+This is equivalent to:
+.Bd -literal -offset
+remote "address" [inherit "parent-address"] {
+ remote_address address;
+}
+.Ed
.El
.\"
-.Ss Policy Specifications
-The policy directive is obsolete, policies are now in the SPD.
-.Xr racoon 8
-will obey the policy configured into the kernel by
-.Xr setkey 8 ,
-and will construct phase 2 proposals by combining
-.Ic sainfo
-specifications in
-.Nm ,
-and policies in the kernel.
-.\"
.Ss Sainfo Specifications
.Bl -tag -width Ds -compact
-.It Xo
-.Ic sainfo ( Ar source_id destination_id | Ar source_id Ic anonymous | Ic anonymous Ar destination_id | Ic anonymous ) [ from Ar idtype [ Ar string ] ] [ Ic group Ar string ]
-.Ic { Ar statements Ic }
-.Xc
-defines the parameters of the IKE phase 2 (IPsec-SA establishment).
-.Ar source_id
+.It Ic sainfo Po Ar local_id | Ic anonymous Pc \
+Po Ar remote_id | Ic clientaddr | Ic anonymous Pc \
+Bo Ic from Ar idtype Bo Ar string Bc Bc Bo Ic group Ar string Bc \
+Ic { Ar statements Ic }
+Defines the parameters of the IKE phase 2 (IPsec-SA establishment).
+.Pp
+The
+.Ar local_id
and
-.Ar destination_id
-are constructed like:
+.Ar remote_id
+strings are constructed like:
.Pp
.Ic address Ar address
.Bq Ic / Ar prefix
@@ -925,17 +1003,11 @@ or
.Bq Ic [ Ar port ]
.Ar ul_proto
.Pp
-or
-.Pp
-.Ar idtype Ar string
-.Pp
-An id string should be expressed to match the exact value of an ID payload
-(source is the local end, destination is the remote end).
+An id string should be expressed to match the exact value of an ID payload.
This is not like a filter rule.
For example, if you define 3ffe:501:4819::/48 as
-.Ar source_id .
+.Ar local_id .
3ffe:501:4819:1000:/64 will not match.
-.Pp
In the case of a longest prefix (selecting a single host),
.Ar address
instructs to send ID type of ADDRESS while
@@ -943,7 +1015,24 @@ instructs to send ID type of ADDRESS while
instructs to send ID type of SUBNET.
Otherwise, these instructions are identical.
.Pp
-The group keyword allows an XAuth group membership check to be performed
+The
+.Ic anonymous
+keyword can be used to match any id.
+The
+.Ic clientaddr
+keyword can be used to match a remote id that is equal to either the peer
+ip address or the mode_cfg ip address (if assigned).
+This can be useful
+to restrict policy generation when racoon is acting as a client gateway
+for peers with dynamic ip addresses.
+.Pp
+The
+.Ic from
+keyword allows an sainfo to only match for peers that use a specific phase1
+id value during authentication.
+The
+.Ic group
+keyword allows an XAuth group membership check to be performed
for this sainfo section.
When the mode_cfg auth source is set to
.Ic system
@@ -977,10 +1066,6 @@ directive.
Sainfos will only be used if their remoteid matches the ph1id of the
remote section used for phase 1.
Defaults to 0, which is also the default for ph1id.
-.\"
-.It Ic my_identifier Ar idtype ... ;
-is obsolete.
-It does not make sense to specify an identifier in the phase 2.
.El
.\"
.Pp
@@ -1037,7 +1122,7 @@ Defines the logging level.
.Ar level
is one of following:
.Ic error , warning , notify , info , debug
-and
+or
.Ic debug2 .
The default is
.Ic info .
@@ -1091,8 +1176,10 @@ This is the default.
means to use a RADIUS server.
It works only if
.Xr racoon 8
-was built with libradius support. Radius configuration is hanlded by
-.Xr radius.conf 5 .
+was built with libradius support.
+Radius configuration is handled by statements in the
+.Ic radiuscfg
+section.
.Ar pam
means to use PAM.
It works only if
@@ -1102,8 +1189,8 @@ was built with libpam support.
means to use LDAP.
It works only if
.Xr racoon 8
-was built with libldap support. LDAP configuration is handled by
-statements in the
+was built with libldap support.
+LDAP configuration is handled by statements in the
.Ic ldapcfg
section.
.It Ic auth_groups Ar "group1", ... ;
@@ -1111,7 +1198,7 @@ Specifies the group memberships for Xauth in quoted group name strings.
When defined, the authenticating user must be a member of at least one
group for Xauth to succeed.
.It Ic group_source (system | ldap) ;
-Specifies the source for group validataion of users through Xauth.
+Specifies the source for group validation of users through Xauth.
.Ar system
means to use the Unix user database.
This is the default.
@@ -1137,9 +1224,10 @@ This is the default.
means to use a RADIUS server.
It works only if
.Xr racoon 8
-was built with libradius support and requires RADIUS authentiation.
-RADIUS configuration is handled by
-.Xr radius.conf 5 .
+was built with libradius support and requires RADIUS authentication.
+RADIUS configuration is handled by statements in the
+.Ic radiuscfg
+section.
.Ar ldap
means to use an LDAP server.
It works only if
@@ -1164,8 +1252,9 @@ enables RADIUS accounting.
It works only if
.Xr racoon 8
was built with libradius support and requires RADIUS authentication.
-RADIUS configuration is handled by
-.Xr radius.conf 5 .
+RADIUS configuration is handled by statements in the
+.Ic radiuscfg
+section.
Specifying
.Ar pam
enables PAM accounting.
@@ -1198,12 +1287,13 @@ A list of IPv4 addresses for DNS servers, separated by commas, or on multiple
.Ic dns4
lines.
.It Ic wins4 Ar addresses ;
-A list of IPv4 address for WINS servers. The keyword
+A list of IPv4 address for WINS servers.
+The keyword
.It nbns4
can also be used as an alias for
.It wins4 .
.It Ic split_network (include | local_lan) Ar network/mask, ...
-The network configuration to send, in cidr notation (e.g. 192.168.1.0/24).
+The network configuration to send, in CIDR notation (e.g. 192.168.1.0/24).
If
.Ic include
is specified, the tunnel should be only used to encrypt the indicated
@@ -1255,11 +1345,11 @@ The default is
The host name or ip address of the ldap server.
The default is
.Ic localhost .
-.It Ic port Ar number;
+.It Ic port Ar number ;
The port that the ldap server is configured to listen on.
The default is
.Ic 389 .
-.It Ic base Ar distinguished name;
+.It Ic base Ar distinguished name ;
The ldap search base.
This option has no default value.
.It Ic subtree (on | off) ;
@@ -1267,20 +1357,20 @@ Use the subtree ldap search scope.
Otherwise, use the one level search scope.
The default is
.Ic off .
-.It Ic bind_dn Ar distinguised name;
-The user dn used to optionaly bind as before performing ldap search operations.
+.It Ic bind_dn Ar distinguished name ;
+The user dn used to optionally bind as before performing ldap search operations.
If this option is not specified, anonymous binds are used.
-.It Ic bind_pw Ar string;
+.It Ic bind_pw Ar string ;
The password used when binding as
.Ic bind_dn .
-.It Ic attr_user Ar attribute name;
+.It Ic attr_user Ar attribute name ;
The attribute used to specify a users name in an ldap directory.
For example,
if a user dn is "cn=jdoe,dc=my,dc=net" then the attribute would be "cn".
The default value is
.Ic cn .
-.It Ic attr_addr Ar attribute name;
-.It Ic attr_mask Ar attribute name;
+.It Ic attr_addr Ar attribute name ;
+.It Ic attr_mask Ar attribute name ;
The attributes used to specify a users network address and subnet mask in an
ldap directory.
These values are forwarded during mode_cfg negotiation when
@@ -1289,18 +1379,54 @@ The default values are
.Ic racoon-address
and
.Ic racoon-netmask .
-.It Ic attr_group Ar attribute name;
+.It Ic attr_group Ar attribute name ;
The attribute used to specify a group name in an ldap directory.
For example,
if a group dn is "cn=users,dc=my,dc=net" then the attribute would be "cn".
The default value is
.Ic cn .
-.It Ic attr_member Ar attribute name;
+.It Ic attr_member Ar attribute name ;
The attribute used to specify group membership in an ldap directory.
The default value is
.Ic member .
.El
.El
+.Ss Radius configuration settings
+.Bl -tag -width Ds -compact
+.It Ic radiuscfg { Ar statements Ic }
+Defines the parameters that will be used to communicate with radius
+servers for
+.Ic xauth
+authentication.
+If radius is selected as the xauth authentication or accounting
+source and no servers are defined in this section, settings from
+the system
+.Xr radius.conf 5
+configuration file will be used instead.
+.Pp
+The following are valid statements:
+.Bl -tag -width Ds -compact
+.It Ic auth Ar (hostname | address) [port] sharedsecret ;
+The host name or ip address, optional port value and shared secret value
+of a radius authentication server.
+Up to 5 radius authentication servers
+may be specified using multiple lines.
+.It Ic acct Ar (hostname | address) [port] sharedsecret ;
+The host name or ip address, optional port value and shared secret value
+of a radius accounting server.
+Up to 5 radius accounting servers may be
+specified using multiple lines.
+.It Ic timeout Ar seconds ;
+The timeout for receiving replies from radius servers.
+The default is
+.Ic 3 .
+.It Ic retries Ar count ;
+The maximum number of repeated requests to make before giving up
+on a radius server.
+The default is
+.Ic 3 .
+.El
+.El
.Ss Special directives
.Bl -tag -width Ds -compact
.It Ic complex_bundle (on | off) ;
diff --git a/src/racoon/racoonctl.8 b/src/racoon/racoonctl.8
index b27b188..697f3ed 100644
--- a/src/racoon/racoonctl.8
+++ b/src/racoon/racoonctl.8
@@ -1,4 +1,4 @@
-.\" $NetBSD: racoonctl.8,v 1.13 2006/09/09 16:22:10 manu Exp $
+.\" $NetBSD: racoonctl.8,v 1.22 2009/03/12 14:01:09 wiz Exp $
.\"
.\" Id: racoonctl.8,v 1.6 2006/05/07 21:32:59 manubsd Exp
.\"
@@ -29,7 +29,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd November 16, 2004
+.Dd March 12, 2009
.Dt RACOONCTL 8
.Os
.\"
@@ -39,34 +39,49 @@
.\"
.Sh SYNOPSIS
.Nm
+.Op opts
reload-config
.Nm
+.Op opts
show-schedule
.Nm
-.Op Fl l Op Fl l
+.Op opts
show-sa
.Op isakmp|esp|ah|ipsec
.Nm
+.Op opts
+get-sa-cert
+.Op inet|inet6
+.Ar src dst
+.Nm
+.Op opts
flush-sa
.Op isakmp|esp|ah|ipsec
.Nm
+.Op opts
delete-sa
.Ar saopts
.Nm
+.Op opts
establish-sa
+.Op Fl w
+.Op Fl n Ar remoteconf
.Op Fl u Ar identity
.Ar saopts
.Nm
+.Op opts
vpn-connect
-.Op Fl u identity
+.Op Fl u Ar identity
.Ar vpn_gateway
.Nm
+.Op opts
vpn-disconnect
.Ar vpn_gateway
.Nm
+.Op opts
show-event
-.Op Fl l
.Nm
+.Op opts
logout-user
.Ar login
.\"
@@ -85,6 +100,19 @@ of the socket, you can allow non-root users to alter
.Xr racoon 8
behavior, so do that with caution.
.Pp
+The following general options are available:
+.Bl -tag -width Ds
+.It Fl d
+Debug mode.
+Hexdump sent admin port commands.
+.It Fl l
+Increase verbosity.
+Mainly for show-sa command.
+.It Fl s Ar socket
+Specify unix socket name used to connecting racoon.
+.El
+.\"
+.Pp
The following commands are available:
.Bl -tag -width Ds
.It reload-config
@@ -99,33 +127,41 @@ IPsec ESP SAs, IPsec AH SAs, or all IPsec SAs.
Use
.Fl l
to increase verbosity.
+.It get-sa-cert Oo inet|inet6 Oc Ar src dst
+Output the raw certificate that was used to authenticate the phase 1
+matching
+.Ar src
+and
+.Ar dst .
.It flush-sa Op isakmp|esp|ah|ipsec
is used to flush all SAs if no SA class is provided, or a class of SAs,
either ISAKMP SAs, IPsec ESP SAs, IPsec AH SAs, or all IPsec SAs.
-.It Xo establish-sa
-.Oo Fl u Ar username
-.Oc Ar saopts
-.Xc
+.It establish-sa Oo Fl w Oc Oo Fl n Ar remoteconf Oc Oo Fl u Ar username \
+Oc Ar saopts
Establish an SA, either an ISAKMP SA, IPsec ESP SA, or IPsec AH SA.
The optional
.Fl u Ar username
can be used when establishing an ISAKMP SA while hybrid auth is in use.
+The exact remote block to use can be specified with
+.Fl n Ar remoteconf .
.Nm
will prompt you for the password associated with
.Ar username
and these credentials will be used in the Xauth exchange.
.Pp
+Specifying
+.Fl w
+will make racoonctl wait until the SA is actually established or
+an error occurs.
+.Pp
.Ar saopts
has the following format:
.Bl -tag -width Bl
.It isakmp {inet|inet6} Ar src Ar dst
.It {esp|ah} {inet|inet6} Ar src/prefixlen/port Ar dst/prefixlen/port
-{icmp|tcp|udp|any}
+{icmp|tcp|udp|gre|any}
.El
-.It Xo vpn-connect
-.Oo Fl u Ar username
-.Oc Ar vpn_gateway
-.Xc
+.It vpn-connect Oo Fl u Ar username Oc Ar vpn_gateway
This is a particular case of the previous command.
It will establish an ISAKMP SA with
.Ar vpn_gateway .
@@ -135,16 +171,9 @@ Delete an SA, either an ISAKMP SA, IPsec ESP SA, or IPsec AH SA.
This is a particular case of the previous command.
It will kill all SAs associated with
.Ar vpn_gateway .
-.It show-event Op Fl l
-Dump all events reported by
-.Xr racoon 8 ,
-then quit.
-The
-.Fl l
-flag causes
-.Nm
-to not stop once all the events have been read, but rather to loop
-awaiting and reporting new events.
+.It show-event
+Listen for all events reported by
+.Xr racoon 8 .
.It logout-user Ar login
Delete all SA established on behalf of the Xauth user
.Ar login .
diff --git a/src/racoon/racoonctl.c b/src/racoon/racoonctl.c
index 1dd26f0..da28ecd 100644
--- a/src/racoon/racoonctl.c
+++ b/src/racoon/racoonctl.c
@@ -1,9 +1,10 @@
-/* $NetBSD: racoonctl.c,v 1.7.6.2 2009/04/20 13:32:57 tteras Exp $ */
+/* $NetBSD: racoonctl.c,v 1.18 2010/11/12 09:08:26 tteras Exp $ */
/* Id: racoonctl.c,v 1.11 2006/04/06 17:06:25 manubsd Exp */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * Copyright (C) 2008 Timo Teras.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -92,6 +93,7 @@ static int handle_recv __P((vchar_t *));
static vchar_t *f_reload __P((int, char **));
static vchar_t *f_getsched __P((int, char **));
static vchar_t *f_getsa __P((int, char **));
+static vchar_t *f_getsacert __P((int, char **));
static vchar_t *f_flushsa __P((int, char **));
static vchar_t *f_deletesa __P((int, char **));
static vchar_t *f_exchangesa __P((int, char **));
@@ -104,59 +106,59 @@ static vchar_t *f_logoutusr __P((int, char **));
struct cmd_tag {
vchar_t *(*func) __P((int, char **));
- int cmd;
char *str;
} cmdtab[] = {
- { f_reload, ADMIN_RELOAD_CONF, "reload-config" },
- { f_reload, ADMIN_RELOAD_CONF, "rc" },
- { f_getsched, ADMIN_SHOW_SCHED, "show-schedule" },
- { f_getsched, ADMIN_SHOW_SCHED, "sc" },
- { f_getsa, ADMIN_SHOW_SA, "show-sa" },
- { f_getsa, ADMIN_SHOW_SA, "ss" },
- { f_flushsa, ADMIN_FLUSH_SA, "flush-sa" },
- { f_flushsa, ADMIN_FLUSH_SA, "fs" },
- { f_deletesa, ADMIN_DELETE_SA, "delete-sa" },
- { f_deletesa, ADMIN_DELETE_SA, "ds" },
- { f_exchangesa, ADMIN_ESTABLISH_SA, "establish-sa" },
- { f_exchangesa, ADMIN_ESTABLISH_SA, "es" },
- { f_vpnc, ADMIN_ESTABLISH_SA, "vpn-connect" },
- { f_vpnc, ADMIN_ESTABLISH_SA, "vc" },
- { f_vpnd, ADMIN_DELETE_ALL_SA_DST,"vpn-disconnect" },
- { f_vpnd, ADMIN_DELETE_ALL_SA_DST,"vd" },
- { f_getevt, ADMIN_SHOW_EVT, "show-event" },
- { f_getevt, ADMIN_SHOW_EVT, "se" },
+ { f_reload, "reload-config" },
+ { f_reload, "rc" },
+ { f_getsched, "show-schedule" },
+ { f_getsched, "sc" },
+ { f_getsa, "show-sa" },
+ { f_getsa, "ss" },
+ { f_getsacert, "get-cert" },
+ { f_getsacert, "gc" },
+ { f_flushsa, "flush-sa" },
+ { f_flushsa, "fs" },
+ { f_deletesa, "delete-sa" },
+ { f_deletesa, "ds" },
+ { f_exchangesa, "establish-sa" },
+ { f_exchangesa, "es" },
+ { f_vpnc, "vpn-connect" },
+ { f_vpnc, "vc" },
+ { f_vpnd, "vpn-disconnect" },
+ { f_vpnd, "vd" },
+ { f_getevt, "show-event" },
+ { f_getevt, "se" },
#ifdef ENABLE_HYBRID
- { f_logoutusr, ADMIN_LOGOUT_USER, "logout-user" },
- { f_logoutusr, ADMIN_LOGOUT_USER, "lu" },
+ { f_logoutusr, "logout-user" },
+ { f_logoutusr, "lu" },
#endif
- { NULL, 0, NULL },
+ { NULL, NULL },
};
struct evtmsg {
int type;
char *msg;
- enum { UNSPEC, ERROR, INFO } level;
} evtmsg[] = {
- { EVTT_PHASE1_UP, "Phase 1 established", INFO },
- { EVTT_PHASE1_DOWN, "Phase 1 deleted", INFO },
- { EVTT_XAUTH_SUCCESS, "Xauth exchange passed", INFO },
- { EVTT_ISAKMP_CFG_DONE, "ISAKMP mode config done", INFO },
- { EVTT_PHASE2_UP, "Phase 2 established", INFO },
- { EVTT_PHASE2_DOWN, "Phase 2 deleted", INFO },
- { EVTT_DPD_TIMEOUT, "Peer not reachable anymore", ERROR },
- { EVTT_PEER_NO_RESPONSE, "Peer not responding", ERROR },
- { EVTT_PEER_DELETE, "Peer terminated security association", ERROR },
- { EVTT_RACOON_QUIT, "Raccon terminated", ERROR },
- { EVTT_OVERFLOW, "Event queue overflow", ERROR },
- { EVTT_XAUTH_FAILED, "Xauth exchange failed", ERROR },
- { EVTT_PEERPH1AUTH_FAILED, "Peer failed phase 1 authentication "
- "(certificate problem?)", ERROR },
- { EVTT_PEERPH1_NOPROP, "Peer failed phase 1 initiation "
- "(proposal problem?)", ERROR },
- { 0, NULL, UNSPEC },
- { EVTT_NO_ISAKMP_CFG, "No need for ISAKMP mode config ", INFO },
+ { EVT_RACOON_QUIT, "Racoon terminated" },
+
+ { EVT_PHASE1_UP, "Phase 1 established" },
+ { EVT_PHASE1_DOWN, "Phase 1 deleted" },
+ { EVT_PHASE1_NO_RESPONSE, "Phase 1 error: peer not responding" },
+ { EVT_PHASE1_NO_PROPOSAL, "Phase 1 error: no proposal chosen" },
+ { EVT_PHASE1_AUTH_FAILED,
+ "Phase 1 error: authentication failed (bad certificate?)" },
+ { EVT_PHASE1_DPD_TIMEOUT, "Phase 1 error: dead peer detected" },
+ { EVT_PHASE1_MODE_CFG, "Phase 1 mode configuration done" },
+ { EVT_PHASE1_XAUTH_SUCCESS, "Phase 1 Xauth succeeded" },
+ { EVT_PHASE1_XAUTH_FAILED, "Phase 1 Xauth failed" },
+
+ { EVT_PHASE2_NO_PHASE1, "Phase 2 error: no suitable phase 1" },
+ { EVT_PHASE2_UP, "Phase 2 established" },
+ { EVT_PHASE2_DOWN, "Phase 2 deleted" },
+ { EVT_PHASE2_NO_RESPONSE, "Phase 2 error: no response" },
};
+static vchar_t *get_proto_and_index __P((int, char **, u_int16_t *));
static int get_proto __P((char *));
static vchar_t *get_index __P((int, char **));
static int get_family __P((char *));
@@ -184,6 +186,7 @@ struct ulproto_tag {
{ IPPROTO_ICMP, "icmp" },
{ IPPROTO_TCP, "tcp" },
{ IPPROTO_UDP, "udp" },
+ { IPPROTO_GRE, "gre" },
{ 0, NULL },
};
@@ -193,31 +196,13 @@ static char _addr1_[NI_MAXHOST], _addr2_[NI_MAXHOST];
char *pname;
int long_format = 0;
-
-#define EVTF_NONE 0x0000 /* Ignore any events */
-#define EVTF_LOOP 0x0001 /* Loop awaiting for new events */
-#define EVTF_CFG_STOP 0x0002 /* Stop after ISAKMP mode config */
-#define EVTF_CFG 0x0004 /* Print ISAKMP mode config info */
-#define EVTF_ALL 0x0008 /* Print any events */
-#define EVTF_PURGE 0x0010 /* Print all available events */
-#define EVTF_PH1DOWN_STOP 0x0020 /* Stop when phase 1 SA gets down */
-#define EVTF_PH1DOWN 0x0040 /* Print that phase 1 SA got down */
-#define EVTF_ERR 0x0080 /* Print any error */
-#define EVTF_ERR_STOP 0x0100 /* Stop on any error */
-
-int evt_filter = EVTF_NONE;
-time_t evt_start;
+int evt_quit_event = 0;
void dump_isakmp_sa __P((char *, int));
void dump_internal __P((char *, int));
char *pindex_isakmp __P((isakmp_index *));
void print_schedule __P((caddr_t, int));
-void print_evt __P((caddr_t, int));
-void print_cfg __P((caddr_t, int));
-void print_err __P((caddr_t, int));
-void print_ph1down __P((caddr_t, int));
-void print_ph1up __P((caddr_t, int));
-int evt_poll __P((void));
+void print_evt __P((struct evt_async *));
char * fixed_addr __P((char *, char *, int));
static void
@@ -225,14 +210,23 @@ usage()
{
printf(
"Usage:\n"
-" %s reload-config\n"
-" %s [-l [-l]] show-sa [protocol]\n"
-" %s flush-sa [protocol]\n"
-" %s delete-sa <saopts>\n"
-" %s establish-sa [-u identity] <saopts>\n"
-" %s vpn-connect [-u identity] vpn_gateway\n"
-" %s vpn-disconnect vpn_gateway\n"
+" %s [opts] reload-config\n"
+" %s [opts] show-schedule\n"
+" %s [opts] show-sa [protocol]\n"
+" %s [opts] flush-sa [protocol]\n"
+" %s [opts] delete-sa <saopts>\n"
+" %s [opts] establish-sa [-u identity] [-n remoteconf] [-w] <saopts>\n"
+" %s [opts] vpn-connect [-u identity] vpn_gateway\n"
+" %s [opts] vpn-disconnect vpn_gateway\n"
+" %s [opts] show-event\n"
+" %s [opts] logout-user login\n"
"\n"
+"General options:\n"
+" -d Debug: hexdump admin messages before sending\n"
+" -l Increase output verbosity (mainly for show-sa)\n"
+" -s <socket> Specify adminport socket to use (default: %s)\n"
+"\n"
+"Parameter specifications:\n"
" <protocol>: \"isakmp\", \"esp\" or \"ah\".\n"
" In the case of \"show-sa\" or \"flush-sa\", you can use \"ipsec\".\n"
"\n"
@@ -240,8 +234,10 @@ usage()
" : {\"esp\",\"ah\"} <family> <src/prefixlen/port> <dst/prefixlen/port>\n"
" <ul_proto>\n"
" <family>: \"inet\" or \"inet6\"\n"
-" <ul_proto>: \"icmp\", \"tcp\", \"udp\" or \"any\"\n",
- pname, pname, pname, pname, pname, pname, pname);
+" <ul_proto>: \"icmp\", \"tcp\", \"udp\", \"gre\" or \"any\"\n"
+"\n",
+ pname, pname, pname, pname, pname, pname, pname, pname, pname, pname,
+ ADMINSOCK_PATH);
}
/*
@@ -312,54 +308,24 @@ main(ac, av)
vfree(combuf);
- if (com_recv(&combuf) != 0)
- goto bad;
- if (handle_recv(combuf) != 0)
- goto bad;
-
- vfree(combuf);
+ do {
+ if (com_recv(&combuf) != 0)
+ goto bad;
+ if (handle_recv(combuf) != 0)
+ goto bad;
+ vfree(combuf);
+ } while (evt_quit_event != 0);
- if (evt_filter != EVTF_NONE)
- if (evt_poll() != 0)
- goto bad;
-
+ close(so);
exit(0);
- bad:
+bad:
+ close(so);
+ if (errno == EEXIST)
+ exit(0);
exit(1);
}
-int
-evt_poll(void) {
- struct timeval tv;
- vchar_t *recvbuf;
- vchar_t *sendbuf;
-
- if ((sendbuf = f_getevt(0, NULL)) == NULL)
- errx(1, "Cannot make combuf");
-
-
- while (evt_filter & (EVTF_LOOP|EVTF_PURGE)) {
- /* handle_recv closes the socket time, so open it each time */
- com_init();
-
- if (com_send(sendbuf) != 0)
- errx(1, "Cannot send combuf");
-
- if (com_recv(&recvbuf) == 0) {
- handle_recv(recvbuf);
- vfree(recvbuf);
- }
-
- tv.tv_sec = 0;
- tv.tv_usec = 10;
- (void)select(0, NULL, NULL, NULL, &tv);
- }
-
- vfree(sendbuf);
- return 0;
-}
-
/* %%% */
/*
* return command buffer.
@@ -394,61 +360,42 @@ get_combuf(ac, av)
}
static vchar_t *
-f_reload(ac, av)
- int ac;
- char **av;
+make_request(u_int16_t cmd, u_int16_t proto, size_t len)
{
vchar_t *buf;
struct admin_com *head;
- buf = vmalloc(sizeof(*head));
+ buf = vmalloc(sizeof(struct admin_com) + len);
if (buf == NULL)
errx(1, "not enough core");
- head = (struct admin_com *)buf->v;
+ head = (struct admin_com *) buf->v;
head->ac_len = buf->l;
- head->ac_cmd = ADMIN_RELOAD_CONF;
- head->ac_errno = 0;
- head->ac_proto = 0;
+ head->ac_cmd = ADMIN_FLAG_VERSION | cmd;
+ head->ac_version = 1;
+ head->ac_proto = proto;
return buf;
}
static vchar_t *
-f_getevt(ac, av)
+f_reload(ac, av)
int ac;
char **av;
{
- vchar_t *buf;
- struct admin_com *head;
-
- /*
- * There are 3 ways of getting here
- * 1) racoonctl vc => evt_filter = (EVTF_LOOP|EVTF_CFG| ... )
- * 2) racoonctl es => evt_filter = EVTF_NONE
- * 3) racoonctl es -l => evt_filter = EVTF_LOOP
- * Catch the second case: show-event is here to purge all
- */
- if (evt_filter == EVTF_NONE)
- evt_filter = (EVTF_ALL|EVTF_PURGE);
-
- if ((ac >= 1) && (strcmp(av[0], "-l") == 0))
- evt_filter |= EVTF_LOOP;
+ return make_request(ADMIN_RELOAD_CONF, 0, 0);
+}
- if (ac >= 2)
+static vchar_t *
+f_getevt(ac, av)
+ int ac;
+ char **av;
+{
+ evt_quit_event = -1;
+ if (ac >= 1)
errx(1, "too many arguments");
- buf = vmalloc(sizeof(*head));
- if (buf == NULL)
- errx(1, "not enough core");
-
- head = (struct admin_com *)buf->v;
- head->ac_len = buf->l;
- head->ac_cmd = ADMIN_SHOW_EVT;
- head->ac_errno = 0;
- head->ac_proto = 0;
-
- return buf;
+ return make_request(ADMIN_SHOW_EVT, 0, 0);
}
static vchar_t *
@@ -456,20 +403,7 @@ f_getsched(ac, av)
int ac;
char **av;
{
- vchar_t *buf;
- struct admin_com *head;
-
- buf = vmalloc(sizeof(*head));
- if (buf == NULL)
- errx(1, "not enough core");
-
- head = (struct admin_com *)buf->v;
- head->ac_len = buf->l;
- head->ac_cmd = ADMIN_SHOW_SCHED;
- head->ac_errno = 0;
- head->ac_proto = 0;
-
- return buf;
+ return make_request(ADMIN_SHOW_SCHED, 0, 0);
}
static vchar_t *
@@ -477,8 +411,6 @@ f_getsa(ac, av)
int ac;
char **av;
{
- vchar_t *buf;
- struct admin_com *head;
int proto;
/* need protocol */
@@ -488,15 +420,29 @@ f_getsa(ac, av)
if (proto == -1)
errx(1, "unknown protocol %s", *av);
- buf = vmalloc(sizeof(*head));
+ return make_request(ADMIN_SHOW_SA, proto, 0);
+}
+
+static vchar_t *
+f_getsacert(ac, av)
+ int ac;
+ char **av;
+{
+ vchar_t *buf, *index;
+ struct admin_com_indexes *com;
+
+ index = get_index(ac, av);
+ if (index == NULL)
+ return NULL;
+
+ com = (struct admin_com_indexes *) index->v;
+ buf = make_request(ADMIN_GET_SA_CERT, ADMIN_PROTO_ISAKMP, index->l);
if (buf == NULL)
- errx(1, "not enough core");
+ errx(1, "Cannot allocate buffer");
- head = (struct admin_com *)buf->v;
- head->ac_len = buf->l;
- head->ac_cmd = ADMIN_SHOW_SA;
- head->ac_errno = 0;
- head->ac_proto = proto;
+ memcpy(buf->v+sizeof(struct admin_com), index->v, index->l);
+
+ vfree(index);
return buf;
}
@@ -517,17 +463,7 @@ f_flushsa(ac, av)
if (proto == -1)
errx(1, "unknown protocol %s", *av);
- buf = vmalloc(sizeof(*head));
- if (buf == NULL)
- errx(1, "not enough core");
-
- head = (struct admin_com *)buf->v;
- head->ac_len = buf->l;
- head->ac_cmd = ADMIN_FLUSH_SA;
- head->ac_errno = 0;
- head->ac_proto = proto;
-
- return buf;
+ return make_request(ADMIN_FLUSH_SA, proto, 0);
}
static vchar_t *
@@ -536,7 +472,6 @@ f_deletesa(ac, av)
char **av;
{
vchar_t *buf, *index;
- struct admin_com *head;
int proto;
/* need protocol */
@@ -566,17 +501,11 @@ f_deletesa(ac, av)
return NULL;
}
- buf = vmalloc(sizeof(*head) + index->l);
+ buf = make_request(ADMIN_DELETE_SA, proto, index->l);
if (buf == NULL)
goto out;
- head = (struct admin_com *)buf->v;
- head->ac_len = buf->l + index->l;
- head->ac_cmd = ADMIN_DELETE_SA;
- head->ac_errno = 0;
- head->ac_proto = proto;
-
- memcpy(buf->v+sizeof(*head), index->v, index->l);
+ memcpy(buf->v + sizeof(struct admin_com), index->v, index->l);
out:
if (index != NULL)
@@ -591,47 +520,17 @@ f_deleteallsadst(ac, av)
char **av;
{
vchar_t *buf, *index;
- struct admin_com *head;
- int proto;
-
- /* need protocol */
- if (ac < 1)
- errx(1, "insufficient arguments");
- proto = get_proto(*av);
- if (proto == -1)
- errx(1, "unknown protocol %s", *av);
+ u_int16_t proto;
- /* get index(es) */
- av++;
- ac--;
- switch (proto) {
- case ADMIN_PROTO_ISAKMP:
- index = get_index(ac, av);
- if (index == NULL)
- return NULL;
- break;
- case ADMIN_PROTO_AH:
- case ADMIN_PROTO_ESP:
- index = get_index(ac, av);
- if (index == NULL)
- return NULL;
- break;
- default:
- errno = EPROTONOSUPPORT;
+ index = get_proto_and_index(ac, av, &proto);
+ if (index == NULL)
return NULL;
- }
- buf = vmalloc(sizeof(*head) + index->l);
+ buf = make_request(ADMIN_DELETE_ALL_SA_DST, proto, index->l);
if (buf == NULL)
goto out;
- head = (struct admin_com *)buf->v;
- head->ac_len = buf->l + index->l;
- head->ac_cmd = ADMIN_DELETE_ALL_SA_DST;
- head->ac_errno = 0;
- head->ac_proto = proto;
-
- memcpy(buf->v+sizeof(*head), index->v, index->l);
+ memcpy(buf->v+sizeof(struct admin_com), index->v, index->l);
out:
if (index != NULL)
@@ -646,13 +545,14 @@ f_exchangesa(ac, av)
char **av;
{
vchar_t *buf, *index;
- struct admin_com *head;
- int proto;
+ u_int16_t proto;
int cmd = ADMIN_ESTABLISH_SA;
size_t com_len = 0;
char *id = NULL;
char *key = NULL;
+ char *remoteconf = NULL;
struct admin_com_psk *acp;
+ int wait = 0;
if (ac < 1)
errx(1, "insufficient arguments");
@@ -673,48 +573,57 @@ f_exchangesa(ac, av)
ac -= 2;
}
- /* need protocol */
- if (ac < 1)
- errx(1, "insufficient arguments");
- if ((proto = get_proto(*av)) == -1)
- errx(1, "unknown protocol %s", *av);
+ if (ac >= 2 && strcmp(av[0], "-n") == 0) {
+ /* Remoteconf name */
+ remoteconf = av[1];
+ av += 2;
+ ac -= 2;
+ }
- /* get index(es) */
- av++;
- ac--;
- switch (proto) {
- case ADMIN_PROTO_ISAKMP:
- index = get_index(ac, av);
- if (index == NULL)
- return NULL;
- break;
- case ADMIN_PROTO_AH:
- case ADMIN_PROTO_ESP:
- index = get_index(ac, av);
- if (index == NULL)
- return NULL;
- break;
- default:
- errno = EPROTONOSUPPORT;
+ if (ac >= 1 && strcmp(av[0], "-w") == 0) {
+ wait = 1;
+ av++;
+ ac--;
+ }
+
+ index = get_proto_and_index(ac, av, &proto);
+ if (index == NULL)
return NULL;
+
+ if (proto == ADMIN_PROTO_ISAKMP && cmd == ADMIN_ESTABLISH_SA &&
+ remoteconf != NULL)
+ com_len += strlen(remoteconf) + 1;
+
+ if (wait) {
+ switch (proto) {
+ case ADMIN_PROTO_ISAKMP:
+ evt_quit_event = EVT_PHASE1_MODE_CFG;
+ break;
+ case ADMIN_PROTO_AH:
+ case ADMIN_PROTO_ESP:
+ evt_quit_event = EVT_PHASE2_UP;
+ break;
+ default:
+ errno = EPROTONOSUPPORT;
+ return NULL;
+ }
}
- com_len += sizeof(*head) + index->l;
- if ((buf = vmalloc(com_len)) == NULL)
+ com_len += index->l;
+ buf = make_request(cmd, proto, com_len);
+ if (buf == NULL)
errx(1, "Cannot allocate buffer");
- head = (struct admin_com *)buf->v;
- head->ac_len = buf->l;
- head->ac_cmd = cmd;
- head->ac_errno = 0;
- head->ac_proto = proto;
-
- memcpy(buf->v+sizeof(*head), index->v, index->l);
+ memcpy(buf->v+sizeof(struct admin_com), index->v, index->l);
- if (id && key) {
+ if (proto == ADMIN_PROTO_ISAKMP && cmd == ADMIN_ESTABLISH_SA &&
+ remoteconf != NULL) {
+ strcpy(buf->v + sizeof(struct admin_com) + index->l,
+ remoteconf);
+ } else if (id && key) {
char *data;
acp = (struct admin_com_psk *)
- (buf->v + sizeof(*head) + index->l);
+ (buf->v + sizeof(struct admin_com) + index->l);
acp->id_type = IDTYPE_USERFQDN;
acp->id_len = strlen(id) + 1;
@@ -749,8 +658,7 @@ f_vpnc(ac, av)
if (ac < 1)
errx(1, "insufficient arguments");
- evt_filter = (EVTF_LOOP|EVTF_CFG|EVTF_CFG_STOP|EVTF_ERR|EVTF_ERR_STOP);
- time(&evt_start);
+ evt_quit_event = EVT_PHASE1_MODE_CFG;
/* Optional -u identity */
if (strcmp(av[0], "-u") == 0) {
@@ -765,7 +673,7 @@ f_vpnc(ac, av)
}
if (ac < 1)
- errx(1, "VPN gateway required");
+ errx(1, "VPN gateway required");
if (ac > 1)
warnx("Extra arguments");
@@ -810,12 +718,11 @@ f_vpnd(ac, av)
char *idx;
if (ac < 1)
- errx(1, "VPN gateway required");
+ errx(1, "VPN gateway required");
if (ac > 1)
warnx("Extra arguments");
- evt_filter =
- (EVTF_PH1DOWN|EVTF_PH1DOWN_STOP|EVTF_LOOP|EVTF_ERR|EVTF_ERR_STOP);
+ evt_quit_event = EVT_PHASE1_DOWN;
nav[nac++] = isakmp;
nav[nac++] = inet;
@@ -832,7 +739,6 @@ f_logoutusr(ac, av)
char **av;
{
vchar_t *buf;
- struct admin_com *head;
char *user;
size_t userlen;
@@ -844,22 +750,46 @@ f_logoutusr(ac, av)
if ((user == NULL) || (userlen > LOGINLEN))
errx(1, "bad login (too long?)");
- buf = vmalloc(sizeof(*head) + userlen);
+ buf = make_request(ADMIN_LOGOUT_USER, 0, userlen);
if (buf == NULL)
return NULL;
- head = (struct admin_com *)buf->v;
- head->ac_len = buf->l;
- head->ac_cmd = ADMIN_LOGOUT_USER;
- head->ac_errno = 0;
- head->ac_proto = 0;
-
- strncpy((char *)(head + 1), user, userlen);
+ strncpy(buf->v + sizeof(struct admin_com), user, userlen);
return buf;
}
#endif /* ENABLE_HYBRID */
+static vchar_t *
+get_proto_and_index(ac, av, proto)
+ int ac;
+ char **av;
+ u_int16_t *proto;
+{
+ vchar_t *index = NULL;
+
+ /* need protocol */
+ if (ac < 1)
+ errx(1, "insufficient arguments");
+ *proto = get_proto(*av);
+ if (*proto == (u_int16_t) -1)
+ errx(1, "unknown protocol %s", *av);
+
+ /* get index(es) */
+ av++;
+ ac--;
+ switch (*proto) {
+ case ADMIN_PROTO_ISAKMP:
+ case ADMIN_PROTO_AH:
+ case ADMIN_PROTO_ESP:
+ index = get_index(ac, av);
+ break;
+ default:
+ errno = EPROTONOSUPPORT;
+ break;
+ }
+ return index;
+}
static int
get_proto(str)
@@ -1337,84 +1267,32 @@ print_schedule(buf, len)
void
-print_evt(buf, len)
- caddr_t buf;
- int len;
+print_evt(evtdump)
+ struct evt_async *evtdump;
{
- struct evtdump *evtdump = (struct evtdump *)buf;
int i;
char *srcstr;
char *dststr;
- for (i = 0; evtmsg[i].msg; i++)
- if (evtmsg[i].type == evtdump->type)
- break;
-
- if (evtmsg[i].msg == NULL)
- printf("Event %d: ", evtdump->type);
+ for (i = 0; i < sizeof(evtmsg) / sizeof(evtmsg[0]); i++)
+ if (evtmsg[i].type == evtdump->ec_type)
+ break;
+
+ if (evtmsg[i].msg == NULL)
+ printf("Event %d: ", evtdump->ec_type);
else
printf("%s : ", evtmsg[i].msg);
- if ((srcstr = saddr2str((struct sockaddr *)&evtdump->src)) == NULL)
+ if ((srcstr = saddr2str((struct sockaddr *)&evtdump->ec_ph1src)) == NULL)
printf("unknown");
- else
+ else
printf("%s", srcstr);
printf(" -> ");
- if ((dststr = saddr2str((struct sockaddr *)&evtdump->dst)) == NULL)
+ if ((dststr = saddr2str((struct sockaddr *)&evtdump->ec_ph1dst)) == NULL)
printf("unknown");
- else
+ else
printf("%s", dststr);
printf("\n");
-
- return;
-}
-
-void
-print_err(buf, len)
- caddr_t buf;
- int len;
-{
- struct evtdump *evtdump = (struct evtdump *)buf;
- int i;
-
-
- for (i = 0; evtmsg[i].msg; i++)
- if (evtmsg[i].type == evtdump->type)
- break;
-
- if (evtmsg[i].level != ERROR)
- return;
-
- if (evtmsg[i].msg == NULL)
- printf("Error: Event %d\n", evtdump->type);
- else
- printf("Error: %s\n", evtmsg[i].msg);
-
- if (evt_filter & EVTF_ERR_STOP)
- evt_filter &= ~EVTF_LOOP;
-
- return;
-}
-
-/*
- * Print a message when phase 1 SA goes down
- */
-void
-print_ph1down(buf, len)
- caddr_t buf;
- int len;
-{
- struct evtdump *evtdump = (struct evtdump *)buf;
-
- if (evtdump->type != EVTT_PHASE1_DOWN)
- return;
-
- printf("VPN connexion terminated\n");
-
- if (evt_filter & EVTF_PH1DOWN_STOP)
- evt_filter &= ~EVTF_LOOP;
-
- return;
}
/*
@@ -1425,15 +1303,14 @@ print_cfg(buf, len)
caddr_t buf;
int len;
{
- struct evtdump *evtdump = (struct evtdump *)buf;
+ struct evt_async *evtdump = (struct evt_async *)buf;
struct isakmp_data *attr;
char *banner = NULL;
struct in_addr addr4;
memset(&addr4, 0, sizeof(addr4));
- if (evtdump->type != EVTT_ISAKMP_CFG_DONE &&
- evtdump->type != EVTT_NO_ISAKMP_CFG)
+ if (evtdump->ec_type != EVT_PHASE1_MODE_CFG)
return;
len -= sizeof(*evtdump);
@@ -1486,12 +1363,12 @@ print_cfg(buf, len)
(n + sizeof(*attr) + ntohs(attr->lorv));
}
}
-
- if (evtdump->type == EVTT_ISAKMP_CFG_DONE)
+
+ if (len > 0)
printf("Bound to address %s\n", inet_ntoa(addr4));
else
printf("VPN connexion established\n");
-
+
if (banner) {
struct winsize win;
int col = 0;
@@ -1508,13 +1385,8 @@ print_cfg(buf, len)
printf("\n");
racoon_free(banner);
}
-
- if (evt_filter & EVTF_CFG_STOP)
- evt_filter &= ~EVTF_LOOP;
-
- return;
}
-
+
char *
fixed_addr(addr, port, len)
@@ -1549,49 +1421,54 @@ static int
handle_recv(combuf)
vchar_t *combuf;
{
- struct admin_com h, *com;
+ struct admin_com *com;
caddr_t buf;
int len;
com = (struct admin_com *)combuf->v;
- len = com->ac_len - sizeof(*com);
+ if (com->ac_cmd & ADMIN_FLAG_LONG_REPLY)
+ len = ((u_int32_t)com->ac_len) + (((u_int32_t)com->ac_len_high) << 16);
+ else
+ len = com->ac_len;
+ len -= sizeof(*com);
buf = combuf->v + sizeof(*com);
- switch (com->ac_cmd) {
+ switch (com->ac_cmd & ~ADMIN_FLAG_LONG_REPLY) {
case ADMIN_SHOW_SCHED:
print_schedule(buf, len);
break;
case ADMIN_SHOW_EVT: {
- struct evtdump *evtdump;
+ struct evt_async *ec;
- /* We got no event */
- if (len == 0) {
- /* If we were purging the queue, it is now done */
- if (evt_filter & EVTF_PURGE)
- evt_filter &= ~EVTF_PURGE;
+ /* We got no event? */
+ if (len == 0)
break;
- }
-
- if (len < sizeof(struct evtdump))
- errx(1, "Short buffer\n");
- /* Toss outdated events */
- evtdump = (struct evtdump *)buf;
- if (evtdump->timestamp < evt_start)
- break;
+ if (len < sizeof(struct evt_async))
+ errx(1, "Short buffer\n");
- if (evt_filter & EVTF_ALL)
- print_evt(buf, len);
- if (evt_filter & EVTF_ERR)
- print_err(buf, len);
- if (evt_filter & EVTF_CFG)
- print_cfg(buf, len);
- if (evt_filter & EVTF_PH1DOWN)
- print_ph1down(buf, len);
+ ec = (struct evt_async *) buf;
+ if (evt_quit_event <= 0)
+ print_evt(ec);
+ else if (evt_quit_event == ec->ec_type) {
+ switch (ec->ec_type) {
+ case EVT_PHASE1_MODE_CFG:
+ print_cfg(ec, len);
+ break;
+ default:
+ print_evt(ec);
+ break;
+ }
+ evt_quit_event = 0;
+ }
break;
}
+ case ADMIN_GET_SA_CERT:
+ fwrite(buf, len, 1, stdout);
+ break;
+
case ADMIN_SHOW_SA:
{
switch (com->ac_proto) {
@@ -1645,10 +1522,8 @@ handle_recv(combuf)
break;
}
- close(so);
return 0;
- bad:
- close(so);
+bad:
return -1;
}
diff --git a/src/racoon/remoteconf.c b/src/racoon/remoteconf.c
index c9c803f..74e386c 100644
--- a/src/racoon/remoteconf.c
+++ b/src/racoon/remoteconf.c
@@ -1,11 +1,11 @@
-/* $NetBSD: remoteconf.c,v 1.9.4.2 2008/06/18 07:30:19 mgrooms Exp $ */
+/* $NetBSD: remoteconf.c,v 1.26 2011/03/14 15:50:36 vanhu Exp $ */
/* Id: remoteconf.c,v 1.38 2006/05/06 15:52:44 manubsd Exp */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -17,7 +17,7 @@
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -63,6 +63,7 @@
#endif
#include "isakmp.h"
#include "ipsec_doi.h"
+#include "crypto_openssl.h"
#include "oakley.h"
#include "remoteconf.h"
#include "localconf.h"
@@ -75,16 +76,307 @@
#include "algorithm.h"
#include "nattraversal.h"
#include "isakmp_frag.h"
+#include "handler.h"
#include "genlist.h"
+#include "rsalist.h"
-static TAILQ_HEAD(_rmtree, remoteconf) rmtree, rmtree_save, rmtree_tmp;
+typedef TAILQ_HEAD(_rmtree, remoteconf) remoteconf_tailq_head_t;
+static remoteconf_tailq_head_t rmtree, rmtree_save;
-/*
+/*
* Script hook names and script hook paths
*/
-char *script_names[SCRIPT_MAX + 1] = { "phase1_up", "phase1_down" };
+char *script_names[SCRIPT_MAX + 1] = {
+ "phase1_up", "phase1_down", "phase1_dead" };
/*%%%*/
+
+int
+rmconf_match_identity(rmconf, id_p)
+ struct remoteconf *rmconf;
+ vchar_t *id_p;
+{
+ struct ipsecdoi_id_b *id_b = (struct ipsecdoi_id_b *) id_p->v;
+ struct sockaddr *sa;
+ caddr_t sa1, sa2;
+ vchar_t ident;
+ struct idspec *id;
+ struct genlist_entry *gpb;
+
+ /* compare with the ID if specified. */
+ if (!genlist_next(rmconf->idvl_p, 0))
+ return 0;
+
+ for (id = genlist_next(rmconf->idvl_p, &gpb); id; id = genlist_next(0, &gpb)) {
+ /* No ID specified in configuration, so it is ok */
+ if (id->id == 0)
+ return 0;
+
+ /* check the type of both IDs */
+ if (id->idtype != doi2idtype(id_b->type))
+ continue; /* ID type mismatch */
+
+ /* compare defined ID with the ID sent by peer. */
+ switch (id->idtype) {
+ case IDTYPE_ASN1DN:
+ ident.v = id_p->v + sizeof(*id_b);
+ ident.l = id_p->l - sizeof(*id_b);
+ if (eay_cmp_asn1dn(id->id, &ident) == 0)
+ return 0;
+ break;
+ case IDTYPE_ADDRESS:
+ sa = (struct sockaddr *)id->id->v;
+ sa2 = (caddr_t)(id_b + 1);
+ switch (sa->sa_family) {
+ case AF_INET:
+ if (id_p->l - sizeof(*id_b) != sizeof(struct in_addr))
+ continue; /* ID value mismatch */
+ sa1 = (caddr_t) &((struct sockaddr_in *)sa)->sin_addr;
+ if (memcmp(sa1, sa2, sizeof(struct in_addr)) == 0)
+ return 0;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ if (id_p->l - sizeof(*id_b) != sizeof(struct in6_addr))
+ continue; /* ID value mismatch */
+ sa1 = (caddr_t) &((struct sockaddr_in6 *)sa)->sin6_addr;
+ if (memcmp(sa1, sa2, sizeof(struct in6_addr)) == 0)
+ return 0;
+ break;
+#endif
+ default:
+ break;
+ }
+ break;
+ default:
+ if (memcmp(id->id->v, id_b + 1, id->id->l) == 0)
+ return 0;
+ break;
+ }
+ }
+
+ plog(LLV_WARNING, LOCATION, NULL, "No ID match.\n");
+ if (rmconf->verify_identifier)
+ return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
+
+ return 0;
+}
+
+static int
+rmconf_match_etype_and_approval(rmconf, etype, approval)
+ struct remoteconf *rmconf;
+ int etype;
+ struct isakmpsa *approval;
+{
+ struct isakmpsa *p;
+
+ if (check_etypeok(rmconf, (void *) (intptr_t) etype) == 0)
+ return ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN;
+
+ if (approval == NULL)
+ return 0;
+
+ if (etype == ISAKMP_ETYPE_AGG &&
+ approval->dh_group != rmconf->dh_group)
+ return ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN;
+
+ if (checkisakmpsa(rmconf->pcheck_level, approval,
+ rmconf->proposal) == NULL)
+ return ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN;
+
+ return 0;
+}
+
+enum rmconf_match_t {
+ MATCH_NONE = 0,
+ MATCH_BASIC = 0x0000001,
+ MATCH_ADDRESS = 0x0000002,
+ MATCH_SA = 0x0000004,
+ MATCH_IDENTITY = 0x0000008,
+ MATCH_AUTH_IDENTITY = 0x0000010,
+};
+
+static int
+rmconf_match_type(rmsel, rmconf)
+ struct rmconfselector *rmsel;
+ struct remoteconf *rmconf;
+{
+ int ret = MATCH_NONE, tmp;
+
+ /* No match at all: unwanted anonymous */
+ if ((rmsel->flags & GETRMCONF_F_NO_ANONYMOUS) &&
+ rmconf->remote->sa_family == AF_UNSPEC){
+ plog(LLV_DEBUG2, LOCATION, rmsel->remote,
+ "Not matched: Anonymous conf.\n");
+ return MATCH_NONE;
+ }
+
+ if ((rmsel->flags & GETRMCONF_F_NO_PASSIVE) && rmconf->passive){
+ plog(LLV_DEBUG2, LOCATION, rmsel->remote,
+ "Not matched: passive conf.\n");
+ return MATCH_NONE;
+ }
+
+ ret |= MATCH_BASIC;
+
+ /* Check address */
+ if (rmsel->remote != NULL) {
+ if (rmconf->remote->sa_family != AF_UNSPEC) {
+ if (cmpsaddr(rmsel->remote, rmconf->remote) == CMPSADDR_MISMATCH){
+ plog(LLV_DEBUG2, LOCATION, rmsel->remote,
+ "Not matched: address mismatch.\n");
+ return MATCH_NONE;
+ }
+
+ /* Address matched */
+ ret |= MATCH_ADDRESS;
+ }
+ }
+
+ /* Check etype and approval */
+ if (rmsel->etype != ISAKMP_ETYPE_NONE) {
+ tmp=rmconf_match_etype_and_approval(rmconf, rmsel->etype,
+ rmsel->approval);
+ if (tmp != 0){
+ plog(LLV_DEBUG2, LOCATION, rmsel->remote,
+ "Not matched: etype (%d)/approval mismatch (%d).\n", rmsel->etype, tmp);
+ return MATCH_NONE;
+ }
+ ret |= MATCH_SA;
+ }
+
+ /* Check identity */
+ if (rmsel->identity != NULL && rmconf->verify_identifier) {
+ if (rmconf_match_identity(rmconf, rmsel->identity) != 0){
+ plog(LLV_DEBUG2, LOCATION, rmsel->remote,
+ "Not matched: identity mismatch.\n");
+ return MATCH_NONE;
+ }
+ ret |= MATCH_IDENTITY;
+ }
+
+ /* Check certificate request */
+ if (rmsel->certificate_request != NULL) {
+ if (oakley_get_certtype(rmsel->certificate_request) !=
+ oakley_get_certtype(rmconf->mycert)){
+ plog(LLV_DEBUG2, LOCATION, rmsel->remote,
+ "Not matched: cert type mismatch.\n");
+ return MATCH_NONE;
+ }
+
+ if (rmsel->certificate_request->l > 1) {
+ vchar_t *issuer;
+
+ issuer = eay_get_x509asn1issuername(rmconf->mycert);
+ if (rmsel->certificate_request->l - 1 != issuer->l ||
+ memcmp(rmsel->certificate_request->v + 1,
+ issuer->v, issuer->l) != 0) {
+ vfree(issuer);
+ plog(LLV_DEBUG2, LOCATION, rmsel->remote,
+ "Not matched: cert issuer mismatch.\n");
+ return MATCH_NONE;
+ }
+ vfree(issuer);
+ } else {
+ if (!rmconf->match_empty_cr){
+ plog(LLV_DEBUG2, LOCATION, rmsel->remote,
+ "Not matched: empty certificate request.\n");
+ return MATCH_NONE;
+ }
+ }
+
+ ret |= MATCH_AUTH_IDENTITY;
+ }
+
+ return ret;
+}
+
+void rmconf_selector_from_ph1(rmsel, iph1)
+ struct rmconfselector *rmsel;
+ struct ph1handle *iph1;
+{
+ memset(rmsel, 0, sizeof(*rmsel));
+ rmsel->flags = 0;
+ rmsel->remote = iph1->remote;
+ rmsel->etype = iph1->etype;
+ rmsel->approval = iph1->approval;
+ rmsel->identity = iph1->id_p;
+ rmsel->certificate_request = iph1->cr_p;
+}
+
+int
+enumrmconf(rmsel, enum_func, enum_arg)
+ struct rmconfselector *rmsel;
+ int (* enum_func)(struct remoteconf *rmconf, void *arg);
+ void *enum_arg;
+{
+ struct remoteconf *p;
+ int ret = 0;
+
+ RACOON_TAILQ_FOREACH_REVERSE(p, &rmtree, _rmtree, chain) {
+ plog(LLV_DEBUG2, LOCATION, rmsel->remote,
+ "Checking remote conf \"%s\" %s.\n", p->name,
+ p->remote->sa_family == AF_UNSPEC ?
+ "anonymous" : saddr2str(p->remote));
+
+ if (rmsel != NULL) {
+ if (rmconf_match_type(rmsel, p) == MATCH_NONE){
+ plog(LLV_DEBUG2, LOCATION, rmsel->remote,
+ "Not matched.\n");
+ continue;
+ }
+ }
+
+ plog(LLV_DEBUG2, LOCATION, NULL,
+ "enumrmconf: \"%s\" matches.\n", p->name);
+
+ ret = (*enum_func)(p, enum_arg);
+ if (ret)
+ break;
+ }
+
+ return ret;
+}
+
+struct rmconf_find_context {
+ struct rmconfselector sel;
+
+ struct remoteconf *rmconf;
+ int match_type;
+ int num_found;
+};
+
+static int
+rmconf_find(rmconf, ctx)
+ struct remoteconf *rmconf;
+ void *ctx;
+{
+ struct rmconf_find_context *fctx = (struct rmconf_find_context *) ctx;
+ int match_type;
+
+ /* First matching remote conf? */
+ match_type = rmconf_match_type(&fctx->sel, rmconf);
+
+ if (fctx->rmconf != NULL) {
+ /* More ambiguous matches are ignored. */
+ if (match_type < fctx->match_type)
+ return 0;
+
+ if (match_type == fctx->match_type) {
+ /* Ambiguous match */
+ fctx->num_found++;
+ return 0;
+ }
+ }
+
+ /* More exact match found */
+ fctx->match_type = match_type;
+ fctx->num_found = 1;
+ fctx->rmconf = rmconf;
+
+ return 0;
+}
+
/*
* search remote configuration.
* don't use port number to search if its value is either IPSEC_PORT_ANY.
@@ -93,76 +385,110 @@ char *script_names[SCRIPT_MAX + 1] = { "phase1_up", "phase1_down" };
* OUT: NULL: NG
* Other: remote configuration entry.
*/
+
struct remoteconf *
-getrmconf_strict(remote, allow_anon)
+getrmconf(remote, flags)
struct sockaddr *remote;
- int allow_anon;
+ int flags;
{
- struct remoteconf *p;
- struct remoteconf *anon = NULL;
- int withport;
- char buf[NI_MAXHOST + NI_MAXSERV + 10];
- char addr[NI_MAXHOST], port[NI_MAXSERV];
-
- withport = 0;
-
-#ifndef ENABLE_NATT
- /*
- * We never have ports set in our remote configurations, but when
- * NAT-T is enabled, the kernel can have policies with ports and
- * send us an acquire message for a destination that has a port set.
- * If we do this port check here, we don't find the remote config.
- *
- * In an ideal world, we would be able to have remote conf with
- * port, and the port could be a wildcard. That test could be used.
- */
- if (remote->sa_family != AF_UNSPEC &&
- extract_port(remote) != IPSEC_PORT_ANY)
- withport = 1;
-#endif /* ENABLE_NATT */
+ struct rmconf_find_context ctx;
+ int n = 0;
- if (remote->sa_family == AF_UNSPEC)
- snprintf (buf, sizeof(buf), "%s", "anonymous");
- else {
- GETNAMEINFO(remote, addr, port);
- snprintf(buf, sizeof(buf), "%s%s%s%s", addr,
- withport ? "[" : "",
- withport ? port : "",
- withport ? "]" : "");
- }
-
- TAILQ_FOREACH(p, &rmtree, chain) {
- if ((remote->sa_family == AF_UNSPEC
- && remote->sa_family == p->remote->sa_family)
- || (!withport && cmpsaddrwop(remote, p->remote) == 0)
- || (withport && cmpsaddrstrict(remote, p->remote) == 0)) {
- plog(LLV_DEBUG, LOCATION, NULL,
- "configuration found for %s.\n", buf);
- return p;
- }
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.sel.flags = flags;
+ ctx.sel.remote = remote;
- /* save the pointer to the anonymous configuration */
- if (p->remote->sa_family == AF_UNSPEC)
- anon = p;
+ if (enumrmconf(&ctx.sel, rmconf_find, &ctx) != 0) {
+ plog(LLV_ERROR, LOCATION, remote,
+ "multiple exact configurations.\n");
+ return NULL;
}
- if (allow_anon && anon != NULL) {
- plog(LLV_DEBUG, LOCATION, NULL,
- "anonymous configuration selected for %s.\n", buf);
- return anon;
+ if (ctx.rmconf == NULL) {
+ plog(LLV_DEBUG, LOCATION, remote,
+ "no remote configuration found.\n");
+ return NULL;
}
- plog(LLV_DEBUG, LOCATION, NULL,
- "no remote configuration found.\n");
+ if (ctx.num_found != 1) {
+ plog(LLV_DEBUG, LOCATION, remote,
+ "multiple non-exact configurations found.\n");
+ return NULL;
+ }
- return NULL;
+ plog(LLV_DEBUG, LOCATION, remote,
+ "configuration \"%s\" selected.\n",
+ ctx.rmconf->name);
+
+ return ctx.rmconf;
}
struct remoteconf *
-getrmconf(remote)
- struct sockaddr *remote;
+getrmconf_by_ph1(iph1)
+ struct ph1handle *iph1;
{
- return getrmconf_strict(remote, 1);
+ struct rmconf_find_context ctx;
+
+ memset(&ctx, 0, sizeof(ctx));
+ rmconf_selector_from_ph1(&ctx.sel, iph1);
+ if (loglevel >= LLV_DEBUG) {
+ char *idstr = NULL;
+
+ if (iph1->id_p != NULL)
+ idstr = ipsecdoi_id2str(iph1->id_p);
+
+ plog(LLV_DEBUG, LOCATION, iph1->remote,
+ "getrmconf_by_ph1: remote %s, identity %s.\n",
+ saddr2str(iph1->remote), idstr ? idstr : "<any>");
+
+ if (idstr)
+ racoon_free(idstr);
+ }
+
+ if (enumrmconf(&ctx.sel, rmconf_find, &ctx) != 0) {
+ plog(LLV_ERROR, LOCATION, iph1->remote,
+ "multiple exact configurations.\n");
+ return RMCONF_ERR_MULTIPLE;
+ }
+
+ if (ctx.rmconf == NULL) {
+ plog(LLV_DEBUG, LOCATION, iph1->remote,
+ "no remote configuration found\n");
+ return NULL;
+ }
+
+ if (ctx.num_found != 1) {
+ plog(LLV_DEBUG, LOCATION, iph1->remote,
+ "multiple non-exact configurations found.\n");
+ return RMCONF_ERR_MULTIPLE;
+ }
+
+ plog(LLV_DEBUG, LOCATION, iph1->remote,
+ "configuration \"%s\" selected.\n",
+ ctx.rmconf->name);
+
+ return ctx.rmconf;
+}
+
+struct remoteconf *
+getrmconf_by_name(name)
+ const char *name;
+{
+ struct remoteconf *p;
+
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "getrmconf_by_name: remote \"%s\".\n",
+ name);
+
+ RACOON_TAILQ_FOREACH_REVERSE(p, &rmtree, _rmtree, chain) {
+ if (p->name == NULL)
+ continue;
+
+ if (strcmp(name, p->name) == 0)
+ return p;
+ }
+
+ return NULL;
}
struct remoteconf *
@@ -191,19 +517,14 @@ newrmconf()
new->pcheck_level = PROP_CHECK_STRICT;
new->verify_identifier = FALSE;
new->verify_cert = TRUE;
- new->getcert_method = ISAKMP_GETCERT_PAYLOAD;
- new->getcacert_method = ISAKMP_GETCERT_LOCALFILE;
- new->cacerttype = ISAKMP_CERT_X509SIGN;
- new->certtype = ISAKMP_CERT_NONE;
new->cacertfile = NULL;
new->send_cert = TRUE;
new->send_cr = TRUE;
+ new->match_empty_cr = FALSE;
new->support_proxy = FALSE;
for (i = 0; i <= SCRIPT_MAX; i++)
new->script[i] = NULL;
new->gen_policy = FALSE;
- new->retry_counter = lcconf->retry_counter;
- new->retry_interval = lcconf->retry_interval;
new->nat_traversal = FALSE;
new->rsa_private = genlist_init();
new->rsa_public = genlist_init();
@@ -215,34 +536,21 @@ newrmconf()
new->dpd_retry = 5;
new->dpd_maxfails = 5;
+ new->rekey = REKEY_ON;
+
new->weak_phase1_check = 0;
#ifdef ENABLE_HYBRID
new->xauth = NULL;
#endif
- return new;
-}
-
-struct remoteconf *
-copyrmconf(remote)
- struct sockaddr *remote;
-{
- struct remoteconf *new, *old;
-
- old = getrmconf_strict (remote, 0);
- if (old == NULL) {
- plog (LLV_ERROR, LOCATION, NULL,
- "Remote configuration for '%s' not found!\n",
- saddr2str (remote));
- return NULL;
- }
-
- new = duprmconf (old);
+ new->lifetime = oakley_get_defaultlifetime();
return new;
}
+#ifndef ANDROID_PATCHED
+
void *
dupidvl(entry, arg)
void *entry;
@@ -264,29 +572,147 @@ dupidvl(entry, arg)
return NULL;
}
+void *
+duprsa(entry, arg)
+ void *entry;
+ void *arg;
+{
+ struct rsa_key *new;
+
+ new = rsa_key_dup((struct rsa_key *)entry);
+ if (new == NULL)
+ return (void *) -1;
+ genlist_append(arg, new);
+
+ /* keep genlist_foreach going */
+ return NULL;
+}
+
+/* Creates shallow copy of a remote config. Used for "inherit" keyword. */
struct remoteconf *
-duprmconf (rmconf)
+duprmconf_shallow (rmconf)
struct remoteconf *rmconf;
{
struct remoteconf *new;
+ struct proposalspec *prspec;
new = racoon_calloc(1, sizeof(*new));
if (new == NULL)
return NULL;
- memcpy (new, rmconf, sizeof (*new));
- // FIXME: We should duplicate the proposal as well.
- // This is now handled in the cfparse.y
- // new->proposal = ...;
-
- /* duplicate dynamic structures */
- if (new->etypes)
- new->etypes=dupetypes(new->etypes);
- new->idvl_p = genlist_init();
- genlist_foreach(rmconf->idvl_p, dupidvl, new->idvl_p);
+
+ memcpy(new, rmconf, sizeof(*new));
+ new->name = NULL;
+ new->inherited_from = rmconf;
+
+ new->proposal = NULL; /* will be filled by set_isakmp_proposal() */
return new;
}
+/* Copies pointer structures of an inherited remote config.
+ * Used by "inherit" mechanism in a two step copy method, necessary to
+ * prevent both double free() and memory leak during config reload.
+ */
+int
+duprmconf_finish (new)
+ struct remoteconf *new;
+{
+ struct remoteconf *rmconf;
+ int i;
+
+ if (new->inherited_from == NULL)
+ return 0; /* nothing todo, no inheritance */
+
+ rmconf = new->inherited_from;
+
+ /* duplicate dynamic structures unless value overridden */
+ if (new->etypes != NULL && new->etypes == rmconf->etypes)
+ new->etypes = dupetypes(new->etypes);
+ if (new->idvl_p == rmconf->idvl_p) {
+ new->idvl_p = genlist_init();
+ genlist_foreach(rmconf->idvl_p, dupidvl, new->idvl_p);
+ }
+
+ if (new->rsa_private == rmconf->rsa_private) {
+ new->rsa_private = genlist_init();
+ genlist_foreach(rmconf->rsa_private, duprsa, new->rsa_private);
+ }
+ if (new->rsa_public == rmconf->rsa_public) {
+ new->rsa_public = genlist_init();
+ genlist_foreach(rmconf->rsa_public, duprsa, new->rsa_public);
+ }
+ if (new->remote != NULL && new->remote == rmconf->remote) {
+ new->remote = racoon_malloc(sizeof(*new->remote));
+ if (new->remote == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "duprmconf_finish: malloc failed (remote)\n");
+ exit(1);
+ }
+ memcpy(new->remote, rmconf->remote, sizeof(*new->remote));
+ }
+ if (new->spspec != NULL && new->spspec == rmconf->spspec) {
+ dupspspec_list(new, rmconf);
+ }
+
+ /* proposal has been deep copied already from spspec's, see
+ * cfparse.y:set_isakmp_proposal, which in turn calls
+ * cfparse.y:expand_isakmpspec where the copying happens.
+ */
+
+#ifdef ENABLE_HYBRID
+ if (new->xauth != NULL && new->xauth == rmconf->xauth) {
+ new->xauth = xauth_rmconf_dup(new->xauth);
+ if (new->xauth == NULL)
+ exit(1);
+ }
+#endif
+
+ /* duplicate strings unless value overridden */
+ if (new->mycertfile != NULL && new->mycertfile == rmconf->mycertfile) {
+ new->mycertfile = racoon_strdup(new->mycertfile);
+ STRDUP_FATAL(new->mycertfile);
+ }
+ if (new->myprivfile != NULL && new->myprivfile == rmconf->myprivfile) {
+ new->myprivfile = racoon_strdup(new->myprivfile);
+ STRDUP_FATAL(new->myprivfile);
+ }
+ if (new->peerscertfile != NULL && new->peerscertfile == rmconf->peerscertfile) {
+ new->peerscertfile = racoon_strdup(new->peerscertfile);
+ STRDUP_FATAL(new->peerscertfile);
+ }
+ if (new->cacertfile != NULL && new->cacertfile == rmconf->cacertfile) {
+ new->cacertfile = racoon_strdup(new->cacertfile);
+ STRDUP_FATAL(new->cacertfile);
+ }
+ if (new->idv != NULL && new->idv == rmconf->idv) {
+ new->idv = vdup(new->idv);
+ STRDUP_FATAL(new->idv);
+ }
+ if (new->key != NULL && new->key == rmconf->key) {
+ new->key = vdup(new->key);
+ STRDUP_FATAL(new->key);
+ }
+ if (new->mycert != NULL && new->mycert == rmconf->mycert) {
+ new->mycert = vdup(new->mycert);
+ STRDUP_FATAL(new->mycert);
+ }
+ if (new->peerscert != NULL && new->peerscert == rmconf->peerscert) {
+ new->peerscert = vdup(new->peerscert);
+ STRDUP_FATAL(new->peerscert);
+ }
+ if (new->cacert != NULL && new->cacert == rmconf->cacert) {
+ new->cacert = vdup(new->cacert);
+ STRDUP_FATAL(new->cacert);
+ }
+ for (i = 0; i <= SCRIPT_MAX; i++)
+ if (new->script[i] != NULL && new->script[i] == rmconf->script[i]) {
+ new->script[i] = vdup(new->script[i]);
+ STRDUP_FATAL(new->script[i]);
+ }
+
+ return 0;
+}
+
static void
idspec_free(void *data)
{
@@ -298,6 +724,8 @@ void
delrmconf(rmconf)
struct remoteconf *rmconf;
{
+ int i;
+
#ifdef ENABLE_HYBRID
if (rmconf->xauth)
xauth_rmconf_delete(&rmconf->xauth);
@@ -306,15 +734,55 @@ delrmconf(rmconf)
deletypes(rmconf->etypes);
rmconf->etypes=NULL;
}
+ if (rmconf->idv)
+ vfree(rmconf->idv);
+ if (rmconf->key)
+ vfree(rmconf->key);
if (rmconf->idvl_p)
genlist_free(rmconf->idvl_p, idspec_free);
if (rmconf->dhgrp)
oakley_dhgrp_free(rmconf->dhgrp);
if (rmconf->proposal)
delisakmpsa(rmconf->proposal);
+ flushspspec(rmconf);
+ if (rmconf->mycert)
+ vfree(rmconf->mycert);
+ if (rmconf->mycertfile)
+ racoon_free(rmconf->mycertfile);
+ if (rmconf->myprivfile)
+ racoon_free(rmconf->myprivfile);
+ if (rmconf->peerscert)
+ vfree(rmconf->peerscert);
+ if (rmconf->peerscertfile)
+ racoon_free(rmconf->peerscertfile);
+ if (rmconf->cacert)
+ vfree(rmconf->cacert);
+ if (rmconf->cacertfile)
+ racoon_free(rmconf->cacertfile);
+ if (rmconf->rsa_private)
+ genlist_free(rmconf->rsa_private, rsa_key_free);
+ if (rmconf->rsa_public)
+ genlist_free(rmconf->rsa_public, rsa_key_free);
+ if (rmconf->name)
+ racoon_free(rmconf->name);
+ if (rmconf->remote)
+ racoon_free(rmconf->remote);
+ for (i = 0; i <= SCRIPT_MAX; i++)
+ if (rmconf->script[i])
+ vfree(rmconf->script[i]);
+
racoon_free(rmconf);
}
+#else
+
+void delrmconf(struct remoteconf *rmconf)
+{
+ exit(1);
+}
+
+#endif
+
void
delisakmpsa(sa)
struct isakmpsa *sa;
@@ -336,11 +804,11 @@ dupetypes(orig)
{
struct etypes *new;
- if (!orig)
+ if (!orig)
return NULL;
new = racoon_malloc(sizeof(struct etypes));
- if (new == NULL)
+ if (new == NULL)
return NULL;
new->type = orig->type;
@@ -368,6 +836,14 @@ void
insrmconf(new)
struct remoteconf *new;
{
+ if (new->name == NULL) {
+ new->name = racoon_strdup(saddr2str(new->remote));
+ }
+ if (new->remote == NULL) {
+ new->remote = newsaddr(sizeof(struct sockaddr));
+ new->remote->sa_family = AF_UNSPEC;
+ }
+
TAILQ_INSERT_HEAD(&rmtree, new, chain);
}
@@ -397,15 +873,17 @@ initrmconf()
}
void
-save_rmconf()
+rmconf_start_reload()
{
rmtree_save=rmtree;
initrmconf();
}
void
-save_rmconf_flush()
+rmconf_finish_reload()
{
+ remoteconf_tailq_head_t rmtree_tmp;
+
rmtree_tmp=rmtree;
rmtree=rmtree_save;
flushrmconf();
@@ -416,19 +894,22 @@ save_rmconf_flush()
/* check exchange type to be acceptable */
-struct etypes *
-check_etypeok(rmconf, etype)
+int
+check_etypeok(rmconf, ctx)
struct remoteconf *rmconf;
- u_int8_t etype;
+ void *ctx;
{
+ u_int8_t etype = (u_int8_t) (intptr_t) ctx;
struct etypes *e;
for (e = rmconf->etypes; e != NULL; e = e->next) {
if (e->type == etype)
- break;
+ return 1;
+ plog(LLV_DEBUG2, LOCATION, NULL,
+ "Etype mismatch: got %d, expected %d.\n", e->type, etype);
}
- return e;
+ return 0;
}
/*%%%*/
@@ -448,7 +929,6 @@ newisakmpsa()
new->vendorid = VENDORID_UNKNOWN;
new->next = NULL;
- new->rmconf = NULL;
#ifdef HAVE_GSSAPI
new->gssid = NULL;
#endif
@@ -466,8 +946,6 @@ insisakmpsa(new, rmconf)
{
struct isakmpsa *p;
- new->rmconf = rmconf;
-
if (rmconf->proposal == NULL) {
rmconf->proposal = new;
return;
@@ -476,21 +954,6 @@ insisakmpsa(new, rmconf)
for (p = rmconf->proposal; p->next != NULL; p = p->next)
;
p->next = new;
-
- return;
-}
-
-struct remoteconf *
-foreachrmconf(rmconf_func_t rmconf_func, void *data)
-{
- struct remoteconf *p, *ret = NULL;
- RACOON_TAILQ_FOREACH_REVERSE(p, &rmtree, _rmtree, chain) {
- ret = (*rmconf_func)(p, data);
- if (ret)
- break;
- }
-
- return ret;
}
static void *
@@ -507,7 +970,7 @@ dump_peers_identifiers (void *entry, void *arg)
return NULL;
}
-static struct remoteconf *
+static int
dump_rmconf_single (struct remoteconf *p, void *data)
{
struct etypes *etype = p->etypes;
@@ -515,10 +978,11 @@ dump_rmconf_single (struct remoteconf *p, void *data)
char buf[1024], *pbuf;
pbuf = buf;
- pbuf += sprintf(pbuf, "remote %s", saddr2str(p->remote));
+
+ pbuf += sprintf(pbuf, "remote \"%s\"", p->name);
if (p->inherited_from)
- pbuf += sprintf(pbuf, " inherit %s",
- saddr2str(p->inherited_from->remote));
+ pbuf += sprintf(pbuf, " inherit \"%s\"",
+ p->inherited_from->name);
plog(LLV_INFO, LOCATION, NULL, "%s {\n", buf);
pbuf = buf;
pbuf += sprintf(pbuf, "\texchange_type ");
@@ -533,23 +997,30 @@ dump_rmconf_single (struct remoteconf *p, void *data)
pbuf += sprintf(pbuf, "\tmy_identifier %s", s_idtype (p->idvtype));
if (p->idvtype == IDTYPE_ASN1DN) {
plog(LLV_INFO, LOCATION, NULL, "%s;\n", buf);
- plog(LLV_INFO, LOCATION, NULL, "\tcertificate_type %s \"%s\" \"%s\";\n",
- p->certtype == ISAKMP_CERT_X509SIGN ? "x509" : "*UNKNOWN*",
- p->mycertfile, p->myprivfile);
- switch (p->getcert_method) {
- case 0:
- break;
- case ISAKMP_GETCERT_PAYLOAD:
- plog(LLV_INFO, LOCATION, NULL, "\t/* peers certificate from payload */\n");
+ plog(LLV_INFO, LOCATION, NULL,
+ "\tcertificate_type %s \"%s\" \"%s\";\n",
+ oakley_get_certtype(p->mycert) == ISAKMP_CERT_X509SIGN
+ ? "x509" : "*UNKNOWN*",
+ p->mycertfile, p->myprivfile);
+
+ switch (oakley_get_certtype(p->peerscert)) {
+ case ISAKMP_CERT_NONE:
+ plog(LLV_INFO, LOCATION, NULL,
+ "\t/* peers certificate from payload */\n");
+ break;
+ case ISAKMP_CERT_X509SIGN:
+ plog(LLV_INFO, LOCATION, NULL,
+ "\tpeers_certfile \"%s\";\n", p->peerscertfile);
break;
- case ISAKMP_GETCERT_LOCALFILE:
- plog(LLV_INFO, LOCATION, NULL, "\tpeers_certfile \"%s\";\n", p->peerscertfile);
+ case ISAKMP_CERT_DNS:
+ plog(LLV_INFO, LOCATION, NULL,
+ "\tpeers_certfile dnssec;\n");
break;
- case ISAKMP_GETCERT_DNS:
- plog(LLV_INFO, LOCATION, NULL, "\tpeer_certfile dnssec;\n");
+ default:
+ plog(LLV_INFO, LOCATION, NULL,
+ "\tpeers_certfile *UNKNOWN* (%d)\n",
+ oakley_get_certtype(p->peerscert));
break;
- default:
- plog(LLV_INFO, LOCATION, NULL, "\tpeers_certfile *UNKNOWN* (%d)\n", p->getcert_method);
}
}
else {
@@ -559,10 +1030,14 @@ dump_rmconf_single (struct remoteconf *p, void *data)
genlist_foreach(p->idvl_p, &dump_peers_identifiers, NULL);
}
+ plog(LLV_INFO, LOCATION, NULL, "\trekey %s;\n",
+ p->rekey == REKEY_FORCE ? "force" : s_switch (p->rekey));
plog(LLV_INFO, LOCATION, NULL, "\tsend_cert %s;\n",
s_switch (p->send_cert));
plog(LLV_INFO, LOCATION, NULL, "\tsend_cr %s;\n",
s_switch (p->send_cr));
+ plog(LLV_INFO, LOCATION, NULL, "\tmatch_empty_cr %s;\n",
+ s_switch (p->match_empty_cr));
plog(LLV_INFO, LOCATION, NULL, "\tverify_cert %s;\n",
s_switch (p->verify_cert));
plog(LLV_INFO, LOCATION, NULL, "\tverify_identifier %s;\n",
@@ -588,9 +1063,8 @@ dump_rmconf_single (struct remoteconf *p, void *data)
while (prop) {
plog(LLV_INFO, LOCATION, NULL, "\n");
plog(LLV_INFO, LOCATION, NULL,
- "\t/* prop_no=%d, trns_no=%d, rmconf=%s */\n",
- prop->prop_no, prop->trns_no,
- saddr2str(prop->rmconf->remote));
+ "\t/* prop_no=%d, trns_no=%d */\n",
+ prop->prop_no, prop->trns_no);
plog(LLV_INFO, LOCATION, NULL, "\tproposal {\n");
plog(LLV_INFO, LOCATION, NULL, "\t\tlifetime time %lu sec;\n",
(long)prop->lifetime);
@@ -598,11 +1072,11 @@ dump_rmconf_single (struct remoteconf *p, void *data)
prop->lifebyte);
plog(LLV_INFO, LOCATION, NULL, "\t\tdh_group %s;\n",
alg_oakley_dhdef_name(prop->dh_group));
- plog(LLV_INFO, LOCATION, NULL, "\t\tencryption_algorithm %s;\n",
+ plog(LLV_INFO, LOCATION, NULL, "\t\tencryption_algorithm %s;\n",
alg_oakley_encdef_name(prop->enctype));
- plog(LLV_INFO, LOCATION, NULL, "\t\thash_algorithm %s;\n",
+ plog(LLV_INFO, LOCATION, NULL, "\t\thash_algorithm %s;\n",
alg_oakley_hashdef_name(prop->hashtype));
- plog(LLV_INFO, LOCATION, NULL, "\t\tauthentication_method %s;\n",
+ plog(LLV_INFO, LOCATION, NULL, "\t\tauthentication_method %s;\n",
alg_oakley_authdef_name(prop->authmethod));
plog(LLV_INFO, LOCATION, NULL, "\t}\n");
prop = prop->next;
@@ -610,13 +1084,13 @@ dump_rmconf_single (struct remoteconf *p, void *data)
plog(LLV_INFO, LOCATION, NULL, "}\n");
plog(LLV_INFO, LOCATION, NULL, "\n");
- return NULL;
+ return 0;
}
void
dumprmconf()
{
- foreachrmconf (dump_rmconf_single, NULL);
+ enumrmconf(NULL, dump_rmconf_single, NULL);
}
struct idspec *
@@ -671,25 +1145,115 @@ script_path_add(path)
struct isakmpsa *
dupisakmpsa(struct isakmpsa *sa)
{
- struct isakmpsa *res=NULL;
+ struct isakmpsa *res = NULL;
if(sa == NULL)
return NULL;
- res=newisakmpsa();
+ res = newisakmpsa();
if(res == NULL)
return NULL;
- *res=*sa;
+ *res = *sa;
#ifdef HAVE_GSSAPI
- /* XXX gssid
- */
+ if (sa->gssid != NULL)
+ res->gssid = vdup(sa->gssid);
#endif
- res->next=NULL;
+ res->next = NULL;
if(sa->dhgrp != NULL)
- oakley_setdhgroup (sa->dh_group, &(res->dhgrp));
+ oakley_setdhgroup(sa->dh_group, &res->dhgrp);
return res;
}
+
+#ifdef ENABLE_HYBRID
+int
+isakmpsa_switch_authmethod(authmethod)
+ int authmethod;
+{
+ switch(authmethod) {
+ case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
+ authmethod = OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I;
+ break;
+ case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
+ authmethod = OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I;
+ break;
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
+ authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I;
+ break;
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
+ authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I;
+ break;
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
+ authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I;
+ break;
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
+ authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I;
+ break;
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
+ authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I;
+ break;
+ default:
+ break;
+ }
+
+ return authmethod;
+}
+#endif
+
+/*
+ * Given a proposed ISAKMP SA, and a list of acceptable
+ * ISAKMP SAs, it compares using pcheck_level policy and
+ * returns first match (if any).
+ */
+struct isakmpsa *
+checkisakmpsa(pcheck_level, proposal, acceptable)
+ int pcheck_level;
+ struct isakmpsa *proposal, *acceptable;
+{
+ struct isakmpsa *p;
+
+ for (p = acceptable; p != NULL; p = p->next){
+ plog(LLV_DEBUG2, LOCATION, NULL,
+ "checkisakmpsa:\nauthmethod: %d / %d\n",
+ isakmpsa_switch_authmethod(proposal->authmethod), isakmpsa_switch_authmethod(p->authmethod));
+ if (isakmpsa_switch_authmethod(proposal->authmethod) != isakmpsa_switch_authmethod(p->authmethod) ||
+ proposal->enctype != p->enctype ||
+ proposal->dh_group != p->dh_group ||
+ proposal->hashtype != p->hashtype)
+ continue;
+
+ switch (pcheck_level) {
+ case PROP_CHECK_OBEY:
+ break;
+
+ case PROP_CHECK_CLAIM:
+ case PROP_CHECK_STRICT:
+ if (proposal->encklen < p->encklen ||
+#if 0
+ proposal->lifebyte > p->lifebyte ||
+#endif
+ proposal->lifetime > p->lifetime)
+ continue;
+ break;
+
+ case PROP_CHECK_EXACT:
+ if (proposal->encklen != p->encklen ||
+#if 0
+ proposal->lifebyte != p->lifebyte ||
+#endif
+ proposal->lifetime != p->lifetime)
+ continue;
+ break;
+
+ default:
+ continue;
+ }
+
+ return p;
+ }
+
+ return NULL;
+}
diff --git a/src/racoon/remoteconf.h b/src/racoon/remoteconf.h
index ca5945e..3ebe004 100644
--- a/src/racoon/remoteconf.h
+++ b/src/racoon/remoteconf.h
@@ -1,4 +1,4 @@
-/* $NetBSD: remoteconf.h,v 1.7 2006/10/03 08:01:56 vanhu Exp $ */
+/* $NetBSD: remoteconf.h,v 1.16 2011/03/14 15:50:36 vanhu Exp $ */
/* Id: remoteconf.h,v 1.26 2006/05/06 15:52:44 manubsd Exp */
@@ -43,20 +43,49 @@
#include "isakmp_xauth.h"
#endif
-struct proposalspec;
+struct ph1handle;
+struct secprotospec;
struct etypes {
int type;
struct etypes *next;
};
+/* ISAKMP SA specification */
+struct isakmpsa {
+ int prop_no;
+ int trns_no;
+ time_t lifetime;
+ size_t lifebyte;
+ int enctype;
+ int encklen;
+ int authmethod;
+ int hashtype;
+ int vendorid;
+#ifdef HAVE_GSSAPI
+ vchar_t *gssid;
+#endif
+ int dh_group; /* don't use it if aggressive mode */
+ struct dhgroup *dhgrp; /* don't use it if aggressive mode */
+
+ struct isakmpsa *next; /* next transform */
+};
+
+/* Certificate information */
+struct rmconf_cert {
+ vchar_t *data; /* certificate payload */
+ char *filename; /* name of local file */
+};
+
/* Script hooks */
#define SCRIPT_PHASE1_UP 0
#define SCRIPT_PHASE1_DOWN 1
-#define SCRIPT_MAX 1
+#define SCRIPT_PHASE1_DEAD 2
+#define SCRIPT_MAX 2
extern char *script_names[SCRIPT_MAX + 1];
struct remoteconf {
+ char *name; /* remote configuration name */
struct sockaddr *remote; /* remote IP address */
/* if family is AF_UNSPEC, that is
* for anonymous configuration. */
@@ -71,16 +100,17 @@ struct remoteconf {
vchar_t *key; /* my pre-shared key */
struct genlist *idvl_p; /* peer's identifiers list */
- int certtype; /* certificate type if need */
- char *mycertfile; /* file name of my certificate */
char *myprivfile; /* file name of my private key file */
+ char *mycertfile; /* file name of my certificate */
+ vchar_t *mycert; /* my certificate */
char *peerscertfile; /* file name of peer's certifcate */
- int getcert_method; /* the way to get peer's certificate */
- int cacerttype; /* CA type is needed */
+ vchar_t *peerscert; /* peer's certificate */
char *cacertfile; /* file name of CA */
- int getcacert_method; /* the way to get the CA */
+ vchar_t *cacert; /* CA certificate */
+
int send_cert; /* send to CERT or not */
int send_cr; /* send to CR or not */
+ int match_empty_cr; /* does this match if CR is empty */
int verify_cert; /* verify a CERT strictly */
int verify_identifier; /* vefify the peer's identifier */
int nonce_size; /* the number of bytes of nonce */
@@ -89,9 +119,9 @@ struct remoteconf {
int esp_frag; /* ESP fragmentation */
int mode_cfg; /* Gets config through mode config */
int support_proxy; /* support mip6/proxy */
-#define GENERATE_POLICY_NONE 0
-#define GENERATE_POLICY_REQUIRE 1
-#define GENERATE_POLICY_UNIQUE 2
+#define GENERATE_POLICY_NONE 0
+#define GENERATE_POLICY_REQUIRE 1
+#define GENERATE_POLICY_UNIQUE 2
int gen_policy; /* generate policy if no policy found */
int ini_contact; /* initial contact */
int pcheck_level; /* level of propocl checking */
@@ -101,16 +131,17 @@ struct remoteconf {
struct dhgroup *dhgrp; /* use it when only aggressive mode */
/* above two can't be defined by user*/
- int retry_counter; /* times to retry. */
- int retry_interval; /* interval each retry. */
- /* above 2 values are copied from localconf. */
-
int dpd; /* Negociate DPD support ? */
int dpd_retry; /* in seconds */
int dpd_interval; /* in seconds */
- int dpd_maxfails;
+ int dpd_maxfails;
+
+ int rekey; /* rekey ph1 when active ph2s? */
+#define REKEY_OFF FALSE
+#define REKEY_ON TRUE
+#define REKEY_FORCE 2
- int ph1id; /* ph1id to be matched with sainfo sections */
+ uint32_t ph1id; /* ph1id to be matched with sainfo sections */
int weak_phase1_check; /* act on unencrypted deletions ? */
@@ -118,7 +149,10 @@ struct remoteconf {
struct remoteconf *inherited_from; /* the original rmconf
from which this one
was inherited */
- struct proposalspec *prhead;
+
+ time_t lifetime; /* for isakmp/ipsec */
+ int lifebyte; /* for isakmp/ipsec */
+ struct secprotospec *spspec; /* the head is always current spec. */
struct genlist *rsa_private, /* lists of PlainRSA keys to use */
*rsa_public;
@@ -130,62 +164,75 @@ struct remoteconf {
TAILQ_ENTRY(remoteconf) chain; /* next remote conf */
};
-struct dhgroup;
-
-/* ISAKMP SA specification */
-struct isakmpsa {
- int prop_no;
- int trns_no;
- time_t lifetime;
- size_t lifebyte;
- int enctype;
- int encklen;
- int authmethod;
- int hashtype;
- int vendorid;
-#ifdef HAVE_GSSAPI
- vchar_t *gssid;
-#endif
- int dh_group; /* don't use it if aggressive mode */
- struct dhgroup *dhgrp; /* don't use it if aggressive mode */
+#define RMCONF_NONCE_SIZE(rmconf) \
+ (rmconf != NULL ? rmconf->nonce_size : DEFAULT_NONCE_SIZE)
- struct isakmpsa *next; /* next transform */
- struct remoteconf *rmconf; /* backpointer to remoteconf */
-};
+struct dhgroup;
struct idspec {
int idtype; /* identifier type */
vchar_t *id; /* identifier */
};
-typedef struct remoteconf * (rmconf_func_t)(struct remoteconf *rmconf, void *data);
+struct rmconfselector {
+ int flags;
+ struct sockaddr *remote;
+ int etype;
+ struct isakmpsa *approval;
+ vchar_t *identity;
+ vchar_t *certificate_request;
+};
+
+extern void rmconf_selector_from_ph1 __P((struct rmconfselector *rmsel,
+ struct ph1handle *iph1));
+extern int enumrmconf __P((struct rmconfselector *rmsel,
+ int (* enum_func)(struct remoteconf *rmconf, void *arg),
+ void *enum_arg));
+
+#define GETRMCONF_F_NO_ANONYMOUS 0x0001
+#define GETRMCONF_F_NO_PASSIVE 0x0002
+
+#define RMCONF_ERR_MULTIPLE ((struct remoteconf *) -1)
+
+extern int rmconf_match_identity __P((struct remoteconf *rmconf,
+ vchar_t *id_p));
+extern struct remoteconf *getrmconf __P((struct sockaddr *remote, int flags));
+extern struct remoteconf *getrmconf_by_ph1 __P((struct ph1handle *iph1));
+extern struct remoteconf *getrmconf_by_name __P((const char *name));
-extern struct remoteconf *getrmconf __P((struct sockaddr *));
-extern struct remoteconf *getrmconf_strict
- __P((struct sockaddr *remote, int allow_anon));
-extern struct remoteconf *copyrmconf __P((struct sockaddr *));
extern struct remoteconf *newrmconf __P((void));
-extern struct remoteconf *duprmconf __P((struct remoteconf *));
+extern struct remoteconf *duprmconf_shallow __P((struct remoteconf *));
+extern int duprmconf_finish __P((struct remoteconf *));
extern void delrmconf __P((struct remoteconf *));
-extern void delisakmpsa __P((struct isakmpsa *));
extern void deletypes __P((struct etypes *));
extern struct etypes * dupetypes __P((struct etypes *));
extern void insrmconf __P((struct remoteconf *));
extern void remrmconf __P((struct remoteconf *));
extern void flushrmconf __P((void));
+extern void dupspspec_list __P((struct remoteconf *, struct remoteconf *));
+extern void flushspspec __P((struct remoteconf *));
extern void initrmconf __P((void));
-extern void save_rmconf __P((void));
-extern void save_rmconf_flush __P((void));
+extern void rmconf_start_reload __P((void));
+extern void rmconf_finish_reload __P((void));
-extern struct etypes *check_etypeok
- __P((struct remoteconf *, u_int8_t));
-extern struct remoteconf *foreachrmconf __P((rmconf_func_t rmconf_func,
- void *data));
+extern int check_etypeok __P((struct remoteconf *, void *));
extern struct isakmpsa *newisakmpsa __P((void));
extern struct isakmpsa *dupisakmpsa __P((struct isakmpsa *));
-
+extern void delisakmpsa __P((struct isakmpsa *));
extern void insisakmpsa __P((struct isakmpsa *, struct remoteconf *));
+#ifdef ENABLE_HYBRID
+extern int isakmpsa_switch_authmethod __P((int authmethod));
+#else
+static inline int isakmpsa_switch_authmethod(int authmethod)
+{
+ return authmethod;
+}
+#endif
+extern struct isakmpsa * checkisakmpsa __P((int pcheck,
+ struct isakmpsa *proposal,
+ struct isakmpsa *acceptable));
+
extern void dumprmconf __P((void));
diff --git a/src/racoon/rsalist.c b/src/racoon/rsalist.c
index 850aa4c..f152c82 100644
--- a/src/racoon/rsalist.c
+++ b/src/racoon/rsalist.c
@@ -1,4 +1,4 @@
-/* $NetBSD: rsalist.c,v 1.4 2006/09/09 16:22:10 manu Exp $ */
+/* $NetBSD: rsalist.c,v 1.6 2011/03/14 15:50:36 vanhu Exp $ */
/* Id: rsalist.c,v 1.3 2004/11/08 12:04:23 ludvigm Exp */
@@ -88,6 +88,65 @@ rsa_key_insert(struct genlist *list, struct netaddr *src,
return 0;
}
+struct rsa_key *
+rsa_key_dup(struct rsa_key *key)
+{
+ struct rsa_key *new;
+
+ new = calloc(sizeof(struct rsa_key), 1);
+ if (new == NULL)
+ return NULL;
+
+ if (key->rsa) {
+ new->rsa = key->rsa->d != NULL ? RSAPrivateKey_dup(key->rsa) : RSAPublicKey_dup(key->rsa);
+ if (new->rsa == NULL)
+ goto dup_error;
+ }
+
+ if (key->src) {
+ new->src = malloc(sizeof(*new->src));
+ if (new->src == NULL)
+ goto dup_error;
+ memcpy(new->src, key->src, sizeof(*new->src));
+ }
+ if (key->dst) {
+ new->dst = malloc(sizeof(*new->dst));
+ if (new->dst == NULL)
+ goto dup_error;
+ memcpy(new->dst, key->dst, sizeof(*new->dst));
+ }
+
+ return new;
+
+dup_error:
+ if (new->rsa != NULL)
+ RSA_free(new->rsa);
+ if (new->dst != NULL)
+ free(new->dst);
+ if (new->src != NULL)
+ free(new->src);
+
+ free(new);
+ return NULL;
+}
+
+void
+rsa_key_free(void *data)
+{
+ struct rsa_key *rsa_key;
+
+
+ rsa_key = (struct rsa_key *)data;
+ if (rsa_key->src)
+ free(rsa_key->src);
+ if (rsa_key->dst)
+ free(rsa_key->dst);
+ if (rsa_key->rsa)
+ RSA_free(rsa_key->rsa);
+
+ free(rsa_key);
+}
+
static void *
rsa_key_dump_one(void *entry, void *arg)
{
diff --git a/src/racoon/rsalist.h b/src/racoon/rsalist.h
index 911670f..bc6a8d9 100644
--- a/src/racoon/rsalist.h
+++ b/src/racoon/rsalist.h
@@ -1,4 +1,4 @@
-/* $NetBSD: rsalist.h,v 1.4 2006/09/09 16:22:10 manu Exp $ */
+/* $NetBSD: rsalist.h,v 1.6 2011/03/14 15:50:36 vanhu Exp $ */
/* Id: rsalist.h,v 1.2 2004/07/12 20:43:51 ludvigm Exp */
/*
@@ -53,6 +53,8 @@ struct rsa_key {
};
int rsa_key_insert(struct genlist *list, struct netaddr *src, struct netaddr *dst, RSA *rsa);
+struct rsa_key *rsa_key_dup(struct rsa_key *key);
+void rsa_key_free(void *data);
void rsa_key_dump(struct genlist *list);
struct genlist *rsa_lookup_keys(struct ph1handle *iph1, int my);
diff --git a/src/racoon/sainfo.c b/src/racoon/sainfo.c
index afa0aac..b6577c2 100644
--- a/src/racoon/sainfo.c
+++ b/src/racoon/sainfo.c
@@ -1,4 +1,4 @@
-/* $NetBSD: sainfo.c,v 1.7.6.1 2007/08/01 11:52:22 vanhu Exp $ */
+/* $NetBSD: sainfo.c,v 1.14 2011/02/02 15:21:34 vanhu Exp $ */
/* $KAME: sainfo.c,v 1.16 2003/06/27 07:32:39 sakane Exp $ */
@@ -64,7 +64,8 @@
#include "sainfo.h"
#include "gcmalloc.h"
-static LIST_HEAD(_sitree, sainfo) sitree, sitree_save, sitree_tmp;
+typedef LIST_HEAD(_sitree, sainfo) sainfo_tailq_head_t;
+static sainfo_tailq_head_t sitree, sitree_save;
/* %%%
* modules for ipsec sa info
@@ -76,88 +77,112 @@ static LIST_HEAD(_sitree, sainfo) sitree, sitree_save, sitree_tmp;
* First pass is for sainfo from a specified peer, second for others.
*/
struct sainfo *
-getsainfo(loc, rmt, peer, remoteid)
- const vchar_t *loc, *rmt, *peer;
- int remoteid;
+getsainfo(loc, rmt, peer, client, remoteid)
+ const vchar_t *loc, *rmt, *peer, *client;
+ uint32_t remoteid;
{
struct sainfo *s = NULL;
- struct sainfo *anonymous = NULL;
- int pass = 1;
-
- if (peer == NULL)
- pass = 2;
/* debug level output */
if(loglevel >= LLV_DEBUG) {
char *dloc, *drmt, *dpeer, *dclient;
-
+
if (loc == NULL)
dloc = strdup("ANONYMOUS");
else
dloc = ipsecdoi_id2str(loc);
-
- if (rmt == NULL)
+
+ if (rmt == SAINFO_ANONYMOUS)
drmt = strdup("ANONYMOUS");
+ else if (rmt == SAINFO_CLIENTADDR)
+ drmt = strdup("CLIENTADDR");
else
drmt = ipsecdoi_id2str(rmt);
-
+
if (peer == NULL)
dpeer = strdup("NULL");
else
dpeer = ipsecdoi_id2str(peer);
-
+
+ if (client == NULL)
+ dclient = strdup("NULL");
+ else
+ dclient = ipsecdoi_id2str(client);
+
plog(LLV_DEBUG, LOCATION, NULL,
- "getsainfo params: loc=\'%s\', rmt=\'%s\', peer=\'%s\', id=%i\n",
- dloc, drmt, dpeer, remoteid );
+ "getsainfo params: loc=\'%s\' rmt=\'%s\' peer=\'%s\' client=\'%s\' id=%u\n",
+ dloc, drmt, dpeer, dclient, remoteid );
racoon_free(dloc);
racoon_free(drmt);
racoon_free(dpeer);
+ racoon_free(dclient);
}
- again:
- plog(LLV_DEBUG, LOCATION, NULL,
- "getsainfo pass #%i\n", pass);
-
LIST_FOREACH(s, &sitree, chain) {
const char *sainfostr = sainfo2str(s);
plog(LLV_DEBUG, LOCATION, NULL,
"evaluating sainfo: %s\n", sainfostr);
- if(s->remoteid != remoteid)
- continue;
-
- if (s->id_i != NULL) {
- if (pass == 2)
+ if(s->remoteid != remoteid) {
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "remoteid mismatch: %u != %u\n",
+ s->remoteid, remoteid);
continue;
+ }
+
+ /* compare 'from' id value */
+ if (s->id_i != NULL)
if (ipsecdoi_chkcmpids(peer, s->id_i, 0))
continue;
- } else if (pass == 1)
- continue;
- if (s->idsrc == NULL && s->iddst == NULL) {
- anonymous = s;
- continue;
- }
- /* anonymous ? */
- if (loc == NULL) {
- if (anonymous != NULL)
- break;
+ /* compare ids - client */
+ if( s->iddst == SAINFO_CLIENTADDR ) {
+ /*
+ * This sainfo section enforces client address
+ * checking. Prevent match if the client value
+ * ( modecfg or tunnel address ) is NULL.
+ */
+
+ if (client == NULL)
+ continue;
+
+ if( rmt == SAINFO_CLIENTADDR ) {
+ /*
+ * In the case where a supplied rmt value is
+ * also SAINFO_CLIENTADDR, we are comparing
+ * with another sainfo to check for duplicate.
+ * Only compare the local values to determine
+ * a match.
+ */
+
+ if (!ipsecdoi_chkcmpids(loc, s->idsrc, 0))
+ return s;
+ }
+ else {
+ /*
+ * In the case where a supplied rmt value is
+ * not SAINFO_CLIENTADDR, do a standard match
+ * for local values and enforce that the rmt
+ * id matches the client address value.
+ */
+
+ if (!ipsecdoi_chkcmpids(loc, s->idsrc, 0) &&
+ !ipsecdoi_chkcmpids(rmt, client, 0))
+ return s;
+ }
+
continue;
}
- /* compare the ids */
+
+ /* compare ids - standard */
if (!ipsecdoi_chkcmpids(loc, s->idsrc, 0) &&
!ipsecdoi_chkcmpids(rmt, s->iddst, 0))
return s;
}
- if ((anonymous == NULL) && (pass == 1)) {
- pass++;
- goto again;
- }
-
- return anonymous;
+ return NULL;
}
struct sainfo *
@@ -186,7 +211,8 @@ delsainfo(si)
if (si->idsrc)
vfree(si->idsrc);
- if (si->iddst)
+ if (si->iddst != NULL &&
+ si->iddst != SAINFO_CLIENTADDR)
vfree(si->iddst);
#ifdef ENABLE_HYBRID
@@ -197,11 +223,75 @@ delsainfo(si)
racoon_free(si);
}
+int prisainfo(s)
+ struct sainfo *s;
+{
+ /*
+ * determine the matching priority
+ * of an sainfo section
+ */
+
+ int pri = 0;
+
+ if(s->remoteid)
+ pri += 3;
+
+ if(s->id_i)
+ pri += 3;
+
+ if(s->idsrc)
+ pri++;
+
+ if(s->iddst)
+ pri++;
+
+ return pri;
+}
+
void
inssainfo(new)
struct sainfo *new;
{
- LIST_INSERT_HEAD(&sitree, new, chain);
+ if(LIST_EMPTY(&sitree)) {
+
+ /* first in list */
+ LIST_INSERT_HEAD(&sitree, new, chain);
+ }
+ else {
+ int npri, spri;
+ struct sainfo *s, *n;
+
+ /*
+ * insert our new sainfo section
+ * into our list which is sorted
+ * based on the match priority
+ */
+
+ npri = prisainfo(new);
+
+ s = LIST_FIRST(&sitree);
+ while (1) {
+
+ spri = prisainfo(s);
+ n = LIST_NEXT(s, chain);
+
+ if(npri > spri)
+ {
+ /* higher priority */
+ LIST_INSERT_BEFORE(s, new, chain);
+ return;
+ }
+
+ if(n == NULL)
+ {
+ /* last in list */
+ LIST_INSERT_AFTER(s, new, chain);
+ return;
+ }
+
+ s = n;
+ }
+ }
}
void
@@ -276,13 +366,15 @@ sainfo2str(si)
char *idloc = NULL, *idrmt = NULL, *id_i;
- if (si->idsrc == NULL)
+ if (si->idsrc == SAINFO_ANONYMOUS)
idloc = strdup("ANONYMOUS");
else
idloc = ipsecdoi_id2str(si->idsrc);
- if (si->iddst == NULL)
+ if (si->iddst == SAINFO_ANONYMOUS)
idrmt = strdup("ANONYMOUS");
+ else if (si->iddst == SAINFO_CLIENTADDR)
+ idrmt = strdup("CLIENTADDR");
else
idrmt = ipsecdoi_id2str(si->iddst);
@@ -291,7 +383,7 @@ sainfo2str(si)
else
id_i = ipsecdoi_id2str(si->id_i);
- snprintf(buf, 255, "loc=\'%s\', rmt=\'%s\', peer=\'%s\', id=%i",
+ snprintf(buf, 255, "loc=\'%s\', rmt=\'%s\', peer=\'%s\', id=%u",
idloc, idrmt, id_i, si->remoteid);
racoon_free(idloc);
@@ -301,12 +393,14 @@ sainfo2str(si)
return buf;
}
-void save_sainfotree(void){
+void sainfo_start_reload(void){
sitree_save=sitree;
initsainfo();
}
-void save_sainfotree_flush(void){
+void sainfo_finish_reload(void){
+ sainfo_tailq_head_t sitree_tmp;
+
sitree_tmp=sitree;
sitree=sitree_save;
flushsainfo();
diff --git a/src/racoon/sainfo.h b/src/racoon/sainfo.h
index 357da3f..e708cd6 100644
--- a/src/racoon/sainfo.h
+++ b/src/racoon/sainfo.h
@@ -1,4 +1,4 @@
-/* $NetBSD: sainfo.h,v 1.5 2006/10/03 08:01:56 vanhu Exp $ */
+/* $NetBSD: sainfo.h,v 1.8 2011/02/02 15:21:34 vanhu Exp $ */
/* Id: sainfo.h,v 1.5 2006/07/09 17:19:38 manubsd Exp */
@@ -36,6 +36,9 @@
#include <sys/queue.h>
+#define SAINFO_ANONYMOUS ((void *)NULL)
+#define SAINFO_CLIENTADDR ((void *)~0)
+
/* SA info */
struct sainfo {
vchar_t *idsrc;
@@ -44,6 +47,7 @@ struct sainfo {
* idsrc and iddst are constructed body of ID payload.
* that is (struct ipsecdoi_id_b) + ID value.
* If idsrc == NULL, that is anonymous entry.
+ * If idsrc == ~0, that is client address entry.
*/
#ifdef ENABLE_HYBRID
@@ -56,7 +60,7 @@ struct sainfo {
vchar_t *id_i; /* identifier of the authorized initiator */
struct sainfoalg *algs[MAXALGCLASS];
- int remoteid;
+ uint32_t remoteid;
LIST_ENTRY(sainfo) chain;
};
@@ -69,7 +73,7 @@ struct sainfoalg {
};
extern struct sainfo *getsainfo __P((const vchar_t *,
- const vchar_t *, const vchar_t *, int));
+ const vchar_t *, const vchar_t *, const vchar_t *, uint32_t));
extern struct sainfo *newsainfo __P((void));
extern void delsainfo __P((struct sainfo *));
extern void inssainfo __P((struct sainfo *));
@@ -81,8 +85,8 @@ extern void delsainfoalg __P((struct sainfoalg *));
extern void inssainfoalg __P((struct sainfoalg **, struct sainfoalg *));
extern const char * sainfo2str __P((const struct sainfo *));
-extern void save_sainfotree __P((void));
-extern void save_sainfotree_flush __P((void));
+extern void sainfo_start_reload __P((void));
+extern void sainfo_finish_reload __P((void));
extern void save_sainfotree_restore __P((void));
#endif /* _SAINFO_H */
diff --git a/src/racoon/samples/roadwarrior/client/phase1-down.sh b/src/racoon/samples/roadwarrior/client/phase1-down.sh
index 8edc187..92f2ba8 100755
--- a/src/racoon/samples/roadwarrior/client/phase1-down.sh
+++ b/src/racoon/samples/roadwarrior/client/phase1-down.sh
@@ -8,10 +8,10 @@ PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
case `uname -s` in
NetBSD)
- DEFAULT_GW=`netstat -rn | awk '($1 == "default"){print $2}'`
+ DEFAULT_GW=`netstat -finet -rn | awk '($1 == "default"){print $2; exit}'`
;;
Linux)
- DEFAULT_GW=`netstat -rn | awk '($1 == "0.0.0.0"){print $2}'`
+ DEFAULT_GW=`netstat --inet -rn | awk '($1 == "0.0.0.0"){print $2; exit}'`
;;
esac
@@ -21,24 +21,29 @@ echo "LOCAL_PORT = ${LOCAL_PORT}"
echo "REMOTE_ADDR = ${REMOTE_ADDR}"
echo "REMOTE_PORT = ${REMOTE_PORT}"
echo "DEFAULT_GW = ${DEFAULT_GW}"
+echo "INTERNAL_NETMASK4 = ${INTERNAL_NETMASK4}"
echo "INTERNAL_ADDR4 = ${INTERNAL_ADDR4}"
echo "INTERNAL_DNS4 = ${INTERNAL_DNS4}"
echo ${INTERNAL_ADDR4} | grep '[0-9]' > /dev/null || exit 0
+echo ${INTERNAL_NETMASK4} | grep '[0-9]' > /dev/null || exit 0
echo ${DEFAULT_GW} | grep '[0-9]' > /dev/null || exit 0
-test -f /etc/resolv.conf.bak && cp /etc/resolv.conf.bak /etc/resolv.conf
+if [ -f /etc/resolv.conf.bak ]; then
+ rm -f /etc/resolv.conf
+ mv /etc/resolv.conf.bak /etc/resolv.conf
+fi
case `uname -s` in
NetBSD)
- if=`netstat -rn|awk '($1 == "default"){print $7}'`
- ifconfig ${if} delete ${INTERNAL_ADDR4}
+ if=`netstat -finet -rn|awk '($1 == "default"){print $7; exit}'`
route delete default
route delete ${REMOTE_ADDR}
+ ifconfig ${if} delete ${INTERNAL_ADDR4}
route add default ${DEFAULT_GW} -ifa ${LOCAL_ADDR}
;;
Linux)
- if=`netstat -rn|awk '($1 == "0.0.0.0"){print $8}'`
+ if=`netstat --inet -rn|awk '($1 == "0.0.0.0"){print $8; exit}'`
route delete default
route delete ${REMOTE_ADDR}
ifconfig ${if}:1 del ${INTERNAL_ADDR4}
@@ -54,13 +59,13 @@ Linux)
;;
esac
-# Use this for a NAT-T setup
-LOCAL="${LOCAL_ADDR}[${LOCAL_PORT}]"
-REMOTE="${REMOTE_ADDR}[${REMOTE_PORT}]"
-
-# Use this for a non NAT-T setup
-#LOCAL="${LOCAL_ADDR}"
-#REMOTE="${REMOTE_ADDR}"
+LOCAL="${LOCAL_ADDR}"
+REMOTE="${REMOTE_ADDR}"
+if [ "x${LOCAL_PORT}" != "x500" ]; then
+ # NAT-T setup
+ LOCAL="${LOCAL}[${LOCAL_PORT}]"
+ REMOTE="${REMOTE}[${REMOTE_PORT}]"
+fi
echo "
deleteall ${REMOTE_ADDR} ${LOCAL_ADDR} esp;
diff --git a/src/racoon/samples/roadwarrior/client/phase1-up.sh b/src/racoon/samples/roadwarrior/client/phase1-up.sh
index e45b648..9275811 100755
--- a/src/racoon/samples/roadwarrior/client/phase1-up.sh
+++ b/src/racoon/samples/roadwarrior/client/phase1-up.sh
@@ -7,10 +7,10 @@ PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
case `uname -s` in
NetBSD)
- DEFAULT_GW=`netstat -rn | awk '($1 == "default"){print $2}'`
+ DEFAULT_GW=`netstat -finet -rn | awk '($1 == "default"){print $2; exit}'`
;;
Linux)
- DEFAULT_GW=`netstat -rn | awk '($1 == "0.0.0.0"){print $2}'`
+ DEFAULT_GW=`netstat --inet -rn | awk '($1 == "0.0.0.0"){print $2; exit}'`
;;
esac
@@ -21,25 +21,28 @@ echo "REMOTE_ADDR = ${REMOTE_ADDR}"
echo "REMOTE_PORT = ${REMOTE_PORT}"
echo "DEFAULT_GW = ${DEFAULT_GW}"
echo "INTERNAL_ADDR4 = ${INTERNAL_ADDR4}"
+echo "INTERNAL_NETMASK4 = ${INTERNAL_NETMASK4}"
echo "INTERNAL_DNS4 = ${INTERNAL_DNS4}"
echo ${INTERNAL_ADDR4} | grep '[0-9]' > /dev/null || exit 0
+echo ${INTERNAL_NETMASK4} | grep '[0-9]' > /dev/null || exit 0
echo ${DEFAULT_GW} | grep '[0-9]' > /dev/null || exit 0
-test -f /etc/resolv.conf.bak || cp /etc/resolv.conf /etc/resolv.conf.bak
-echo "# Generated by racoon on `date`" > /etc/resolv.conf
+mv /etc/resolv.conf /etc/resolv.conf.bak
+( umask 22; touch /etc/resolv.conf )
+echo "# Generated by racoon on `date`" >> /etc/resolv.conf
echo "nameserver ${INTERNAL_DNS4}" >> /etc/resolv.conf
case `uname -s` in
NetBSD)
- if=`netstat -rn|awk '($1 == "default"){print $7}'`
+ if=`netstat -finet -rn|awk '($1 == "default"){print $7; exit}'`
ifconfig ${if} alias ${INTERNAL_ADDR4} netmask ${INTERNAL_NETMASK4}
route delete default
route add default ${DEFAULT_GW} -ifa ${INTERNAL_ADDR4}
route add ${REMOTE_ADDR} ${DEFAULT_GW}
;;
Linux)
- if=`netstat -rn|awk '($1 == "0.0.0.0"){print $8}'`
+ if=`netstat --inet -rn|awk '($1 == "0.0.0.0"){print $8; exit}'`
ifconfig ${if}:1 ${INTERNAL_ADDR4}
route delete default
route add ${REMOTE_ADDR} gw ${DEFAULT_GW} dev ${if}
@@ -47,13 +50,13 @@ Linux)
;;
esac
-# Use this for a NAT-T setup
-LOCAL="${LOCAL_ADDR}[${LOCAL_PORT}]"
-REMOTE="${REMOTE_ADDR}[${REMOTE_PORT}]"
-
-# Use this for a non NAT-T setup
-#LOCAL="${LOCAL_ADDR}"
-#REMOTE="${REMOTE_ADDR}"
+LOCAL="${LOCAL_ADDR}"
+REMOTE="${REMOTE_ADDR}"
+if [ "x${LOCAL_PORT}" != "x500" ]; then
+ # NAT-T setup
+ LOCAL="${LOCAL}[${LOCAL_PORT}]"
+ REMOTE="${REMOTE}[${REMOTE_PORT}]"
+fi
echo "
diff --git a/src/racoon/schedule.c b/src/racoon/schedule.c
index 04723c5..018f920 100644
--- a/src/racoon/schedule.c
+++ b/src/racoon/schedule.c
@@ -1,9 +1,10 @@
-/* $NetBSD: schedule.c,v 1.4 2006/09/09 16:22:10 manu Exp $ */
+/* $NetBSD: schedule.c,v 1.7 2009/01/23 09:10:13 tteras Exp $ */
/* $KAME: schedule.c,v 1.19 2001/11/05 10:53:19 sakane Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * Copyright (C) 2008 Timo Teras.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -40,6 +41,7 @@
#include <sys/socket.h>
#include <stdlib.h>
+#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
@@ -51,25 +53,46 @@
#include "var.h"
#include "gcmalloc.h"
-#define FIXY2038PROBLEM
-
#ifndef TAILQ_FOREACH
#define TAILQ_FOREACH(elm, head, field) \
for (elm = TAILQ_FIRST(head); elm; elm = TAILQ_NEXT(elm, field))
#endif
-static struct timeval timeout;
+static TAILQ_HEAD(_schedtree, sched) sctree;
+
+void
+sched_get_monotonic_time(tv)
+ struct timeval *tv;
+{
+#ifdef HAVE_CLOCK_MONOTONIC
+ struct timespec ts;
-#ifdef FIXY2038PROBLEM
-#define Y2038TIME_T 0x7fffffff
-static time_t launched; /* time when the program launched. */
-static time_t deltaY2038;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ tv->tv_sec = ts.tv_sec;
+ tv->tv_usec = ts.tv_nsec / 1000;
+#else
+ gettimeofday(tv, NULL);
#endif
+}
-static TAILQ_HEAD(_schedtree, sched) sctree;
+time_t
+sched_monotonic_to_time_t(tv, now)
+ struct timeval *tv, *now;
+{
+#ifdef HAVE_CLOCK_MONOTONIC
+ struct timeval mynow, res;
+
+ if (now == NULL) {
+ sched_get_monotonic_time(&mynow);
+ now = &mynow;
+ }
+ timersub(now, tv, &res);
-static void sched_add __P((struct sched *));
-static time_t current_time __P((void));
+ return time(NULL) + res.tv_sec;
+#else
+ return tv->tv_sec;
+#endif
+}
/*
* schedule handler
@@ -80,42 +103,26 @@ static time_t current_time __P((void));
struct timeval *
schedular()
{
- time_t now, delta;
- struct sched *p, *next = NULL;
-
- now = current_time();
-
- for (p = TAILQ_FIRST(&sctree); p; p = next) {
- /* if the entry has been daed, remove it */
- if (p->dead)
- goto next_schedule;
-
- /* if the time hasn't come, proceed to the next entry */
- if (now < p->xtime) {
- next = TAILQ_NEXT(p, chain);
- continue;
- }
+ static struct timeval timeout;
+ struct timeval now;
+ struct sched *p;
- /* mark it with dead. and call the function. */
- p->dead = 1;
- if (p->func != NULL)
- (p->func)(p->param);
+ sched_get_monotonic_time(&now);
+ while (!TAILQ_EMPTY(&sctree) &&
+ timercmp(&TAILQ_FIRST(&sctree)->xtime, &now, <=)) {
+ void (*func)(struct sched *);
- next_schedule:
- next = TAILQ_NEXT(p, chain);
- TAILQ_REMOVE(&sctree, p, chain);
- racoon_free(p);
+ p = TAILQ_FIRST(&sctree);
+ func = p->func;
+ sched_cancel(p);
+ func(p);
}
p = TAILQ_FIRST(&sctree);
if (p == NULL)
return NULL;
- now = current_time();
-
- delta = p->xtime - now;
- timeout.tv_sec = delta < 0 ? 0 : delta;
- timeout.tv_usec = 0;
+ timersub(&p->xtime, &now, &timeout);
return &timeout;
}
@@ -123,101 +130,46 @@ schedular()
/*
* add new schedule to schedule table.
*/
-struct sched *
-sched_new(tick, func, param)
+void
+sched_schedule(sc, tick, func)
+ struct sched *sc;
time_t tick;
- void (*func) __P((void *));
- void *param;
+ void (*func) __P((struct sched *));
{
static long id = 1;
- struct sched *new;
-
- new = (struct sched *)racoon_malloc(sizeof(*new));
- if (new == NULL)
- return NULL;
-
- memset(new, 0, sizeof(*new));
- new->func = func;
- new->param = param;
+ struct sched *p;
+ struct timeval now;
- new->id = id++;
- time(&new->created);
- new->tick = tick;
+ sched_cancel(sc);
- new->xtime = current_time() + tick;
- new->dead = 0;
+ sc->func = func;
+ sc->id = id++;
+ sc->tick.tv_sec = tick;
+ sc->tick.tv_usec = 0;
+ sched_get_monotonic_time(&now);
+ timeradd(&now, &sc->tick, &sc->xtime);
/* add to schedule table */
- sched_add(new);
-
- return(new);
-}
-
-/* add new schedule to schedule table */
-static void
-sched_add(sc)
- struct sched *sc;
-{
- struct sched *p;
-
TAILQ_FOREACH(p, &sctree, chain) {
- if (sc->xtime < p->xtime) {
- TAILQ_INSERT_BEFORE(p, sc, chain);
- return;
- }
+ if (timercmp(&sc->xtime, &p->xtime, <))
+ break;
}
if (p == NULL)
TAILQ_INSERT_TAIL(&sctree, sc, chain);
-
- return;
+ else
+ TAILQ_INSERT_BEFORE(p, sc, chain);
}
-/* get current time.
- * if defined FIXY2038PROBLEM, base time is the time when called sched_init().
- * Otherwise, conform to time(3).
+/*
+ * cancel scheduled callback
*/
-static time_t
-current_time()
-{
- time_t n;
-#ifdef FIXY2038PROBLEM
- time_t t;
-
- time(&n);
- t = n - launched;
- if (t < 0)
- t += deltaY2038;
-
- return t;
-#else
- return time(&n);
-#endif
-}
-
void
-sched_kill(sc)
+sched_cancel(sc)
struct sched *sc;
{
- sc->dead = 1;
-
- return;
-}
-
-/* XXX this function is probably unnecessary. */
-void
-sched_scrub_param(param)
- void *param;
-{
- struct sched *sc;
-
- TAILQ_FOREACH(sc, &sctree, chain) {
- if (sc->param == param) {
- if (!sc->dead) {
- plog(LLV_DEBUG, LOCATION, NULL,
- "an undead schedule has been deleted.\n");
- }
- sched_kill(sc);
- }
+ if (sc->func != NULL) {
+ TAILQ_REMOVE(&sctree, sc, chain);
+ sc->func = NULL;
}
}
@@ -232,6 +184,7 @@ sched_dump(buf, len)
caddr_t new;
struct sched *p;
struct scheddump *dst;
+ struct timeval now, created;
int cnt = 0;
/* initialize */
@@ -252,12 +205,14 @@ sched_dump(buf, len)
return -1;
dst = (struct scheddump *)new;
- p = TAILQ_FIRST(&sctree);
+ sched_get_monotonic_time(&now);
+ p = TAILQ_FIRST(&sctree);
while (p) {
- dst->xtime = p->xtime;
+ timersub(&p->xtime, &p->tick, &created);
+ dst->xtime = p->xtime.tv_sec;
dst->id = p->id;
- dst->created = p->created;
- dst->tick = p->tick;
+ dst->created = sched_monotonic_to_time_t(&created, &now);
+ dst->tick = p->tick.tv_sec;
p = TAILQ_NEXT(p, chain);
if (p == NULL)
@@ -274,15 +229,7 @@ sched_dump(buf, len)
void
sched_init()
{
-#ifdef FIXY2038PROBLEM
- time(&launched);
-
- deltaY2038 = Y2038TIME_T - launched;
-#endif
-
TAILQ_INIT(&sctree);
-
- return;
}
#ifdef STEST
diff --git a/src/racoon/schedule.h b/src/racoon/schedule.h
index bd66593..228e677 100644
--- a/src/racoon/schedule.h
+++ b/src/racoon/schedule.h
@@ -1,9 +1,10 @@
-/* $NetBSD: schedule.h,v 1.4.6.1 2007/03/21 14:29:48 vanhu Exp $ */
+/* $NetBSD: schedule.h,v 1.8 2009/08/17 12:00:53 vanhu Exp $ */
/* Id: schedule.h,v 1.5 2006/05/03 21:53:42 vanhu Exp */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * Copyright (C) 2008 Timo Teras.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,39 +35,47 @@
#ifndef _SCHEDULE_H
#define _SCHEDULE_H
+#include <stddef.h>
+
#include <sys/queue.h>
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
#include "gnuc.h"
+#ifndef offsetof
+#ifdef __compiler_offsetof
+#define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)
+#else
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif
+#endif
+
+#ifndef container_of
+#define container_of(ptr, type, member) ({ \
+ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
+ (type *)( (char *)__mptr - offsetof(type,member) );})
+#endif
+
+
/* scheduling table */
/* the head is the nearest event. */
struct sched {
- time_t xtime; /* event time which is as time(3). */
- /*
- * if defined FIXY2038PROBLEM, this time
- * is from the time when called sched_init().
- */
- void (*func) __P((void *)); /* call this function when timeout. */
- void *param; /* pointer to parameter */
-
- int dead; /* dead or alive */
- long id; /* for debug */
- time_t created; /* for debug */
- time_t tick; /* for debug */
-
+ void (*func) __P((struct sched *)); /* callback on timeout */
+ struct timeval xtime; /* expiration time */
+ struct timeval tick; /* relative timeout */
TAILQ_ENTRY(sched) chain;
+ long id; /* for debug */
};
-/* cancel schedule */
-#define SCHED_KILL(s) \
-do { \
- if(s != NULL){ \
- sched_kill(s); \
- s = NULL; \
- }\
-} while(0)
-
-/* must be called after it's called from scheduler. */
-#define SCHED_INIT(s) (s) = NULL
+#define SCHED_INITIALIZER() { NULL, }
struct scheddump {
time_t xtime;
@@ -75,11 +84,16 @@ struct scheddump {
time_t tick;
};
+time_t sched_monotonic_to_time_t __P((struct timeval *tv,
+ struct timeval *now));
+void sched_get_monotonic_time __P((struct timeval *tv));
+
struct timeval *schedular __P((void));
-struct sched *sched_new __P((time_t, void (*func) __P((void *)), void *));
-void sched_kill __P((struct sched *));
+void sched_schedule __P((struct sched *, time_t,
+ void (*func) __P((struct sched *))));
+void sched_cancel __P((struct sched *));
+
int sched_dump __P((caddr_t *, int *));
void sched_init __P((void));
-void sched_scrub_param __P((void *));
#endif /* _SCHEDULE_H */
diff --git a/src/racoon/session.c b/src/racoon/session.c
index 9db901d..85e29a3 100644
--- a/src/racoon/session.c
+++ b/src/racoon/session.c
@@ -1,11 +1,11 @@
-/* $NetBSD: session.c,v 1.7.6.2 2007/08/01 11:52:22 vanhu Exp $ */
+/* $NetBSD: session.c,v 1.32 2011/03/02 15:09:16 vanhu Exp $ */
/* $KAME: session.c,v 1.32 2003/09/24 02:01:17 jinmei Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -17,7 +17,7 @@
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -59,6 +59,7 @@
#include <signal.h>
#include <sys/stat.h>
#include <paths.h>
+#include <err.h>
#include <netinet/in.h>
#include <resolv.h>
@@ -77,6 +78,8 @@
#include "evt.h"
#include "cfparse_proto.h"
#include "isakmp_var.h"
+#include "isakmp.h"
+#include "isakmp_var.h"
#include "isakmp_xauth.h"
#include "isakmp_cfg.h"
#include "admin_var.h"
@@ -88,80 +91,174 @@
#include "localconf.h"
#include "remoteconf.h"
#include "backupsa.h"
+#include "remoteconf.h"
#ifdef ENABLE_NATT
#include "nattraversal.h"
#endif
-
#include "algorithm.h" /* XXX ??? */
#include "sainfo.h"
+struct fd_monitor {
+ int (*callback)(void *ctx, int fd);
+ void *ctx;
+ int prio;
+ int fd;
+ TAILQ_ENTRY(fd_monitor) chain;
+};
+
+#define NUM_PRIORITIES 2
+
static void close_session __P((void));
-static void check_rtsock __P((void *));
static void initfds __P((void));
static void init_signal __P((void));
static int set_signal __P((int sig, RETSIGTYPE (*func) __P((int))));
static void check_sigreq __P((void));
-static void check_flushsa_stub __P((void *));
static void check_flushsa __P((void));
static int close_sockets __P((void));
-static fd_set mask0;
-static fd_set maskdying;
+static fd_set preset_mask, active_mask;
+static struct fd_monitor fd_monitors[FD_SETSIZE];
+static TAILQ_HEAD(fd_monitor_list, fd_monitor) fd_monitor_tree[NUM_PRIORITIES];
static int nfds = 0;
+
static volatile sig_atomic_t sigreq[NSIG + 1];
-static int dying = 0;
+static struct sched scflushsa = SCHED_INITIALIZER();
+
+void
+monitor_fd(int fd, int (*callback)(void *, int), void *ctx, int priority)
+{
+ if (fd < 0 || fd >= FD_SETSIZE) {
+ plog(LLV_ERROR, LOCATION, NULL, "fd_set overrun");
+ exit(1);
+ }
+
+ FD_SET(fd, &preset_mask);
+ if (fd > nfds)
+ nfds = fd;
+ if (priority <= 0)
+ priority = 0;
+ if (priority >= NUM_PRIORITIES)
+ priority = NUM_PRIORITIES - 1;
+
+ fd_monitors[fd].callback = callback;
+ fd_monitors[fd].ctx = ctx;
+ fd_monitors[fd].prio = priority;
+ fd_monitors[fd].fd = fd;
+ TAILQ_INSERT_TAIL(&fd_monitor_tree[priority],
+ &fd_monitors[fd], chain);
+}
+
+void
+unmonitor_fd(int fd)
+{
+ if (fd < 0 || fd >= FD_SETSIZE) {
+ plog(LLV_ERROR, LOCATION, NULL, "fd_set overrun");
+ exit(1);
+ }
+
+ if (fd_monitors[fd].callback == NULL)
+ return;
+
+ FD_CLR(fd, &preset_mask);
+ FD_CLR(fd, &active_mask);
+ fd_monitors[fd].callback = NULL;
+ fd_monitors[fd].ctx = NULL;
+ TAILQ_REMOVE(&fd_monitor_tree[fd_monitors[fd].prio],
+ &fd_monitors[fd], chain);
+}
int
session(void)
{
- fd_set rfds;
struct timeval *timeout;
int error;
- struct myaddrs *p;
char pid_file[MAXPATHLEN];
FILE *fp;
pid_t racoon_pid = 0;
- int i;
+ int i, count;
+ struct fd_monitor *fdm;
+
+ nfds = 0;
+ FD_ZERO(&preset_mask);
+
+ for (i = 0; i < NUM_PRIORITIES; i++)
+ TAILQ_INIT(&fd_monitor_tree[i]);
/* initialize schedular */
sched_init();
-
init_signal();
+ if (pfkey_init() < 0)
+ errx(1, "failed to initialize pfkey socket");
+
+ if (isakmp_init() < 0)
+ errx(1, "failed to initialize ISAKMP structures");
+
+#ifdef ENABLE_HYBRID
+ if (isakmp_cfg_init(ISAKMP_CFG_INIT_COLD))
+ errx(1, "could not initialize ISAKMP mode config structures");
+#endif
+
+#ifdef HAVE_LIBLDAP
+ if (xauth_ldap_init_conf() != 0)
+ errx(1, "could not initialize ldap config");
+#endif
+
+#ifdef HAVE_LIBRADIUS
+ if (xauth_radius_init_conf(0) != 0)
+ errx(1, "could not initialize radius config");
+#endif
+
+ myaddr_init_lists();
+
+ /*
+ * in order to prefer the parameters by command line,
+ * saving some parameters before parsing configuration file.
+ */
+ save_params();
+ if (cfparse() != 0)
+ errx(1, "failed to parse configuration file.");
+ restore_params();
+
#ifdef ENABLE_ADMINPORT
if (admin_init() < 0)
- exit(1);
+ errx(1, "failed to initialize admin port socket");
#endif
- initmyaddr();
- if (isakmp_init() < 0)
- exit(1);
+#ifdef ENABLE_HYBRID
+ if(isakmp_cfg_config.network4 && isakmp_cfg_config.pool_size == 0)
+ if ((error = isakmp_cfg_resize_pool(ISAKMP_CFG_MAX_CNX)) != 0)
+ return error;
+#endif
- initfds();
+ if (dump_config)
+ dumprmconf();
-#ifdef ENABLE_NATT
- natt_keepalive_init ();
+#ifdef HAVE_LIBRADIUS
+ if (xauth_radius_init() != 0)
+ errx(1, "could not initialize libradius");
#endif
- if (privsep_init() != 0)
- exit(1);
+ if (myaddr_init() != 0)
+ errx(1, "failed to listen to configured addresses");
+ myaddr_sync();
- for (i = 0; i <= NSIG; i++)
- sigreq[i] = 0;
+#ifdef ENABLE_NATT
+ natt_keepalive_init ();
+#endif
/* write .pid file */
- racoon_pid = getpid();
- if (lcconf->pathinfo[LC_PATHTYPE_PIDFILE] == NULL)
+ if (lcconf->pathinfo[LC_PATHTYPE_PIDFILE] == NULL)
strlcpy(pid_file, _PATH_VARRUN "racoon.pid", MAXPATHLEN);
- else if (lcconf->pathinfo[LC_PATHTYPE_PIDFILE][0] == '/')
+ else if (lcconf->pathinfo[LC_PATHTYPE_PIDFILE][0] == '/')
strlcpy(pid_file, lcconf->pathinfo[LC_PATHTYPE_PIDFILE], MAXPATHLEN);
else {
strlcat(pid_file, _PATH_VARRUN, MAXPATHLEN);
strlcat(pid_file, lcconf->pathinfo[LC_PATHTYPE_PIDFILE], MAXPATHLEN);
- }
+ }
fp = fopen(pid_file, "w");
if (fp) {
if (fchmod(fileno(fp),
@@ -170,19 +267,26 @@ session(void)
fclose(fp);
exit(1);
}
- fprintf(fp, "%ld\n", (long)racoon_pid);
- fclose(fp);
} else {
plog(LLV_ERROR, LOCATION, NULL,
"cannot open %s", pid_file);
}
- while (1) {
- if (dying)
- rfds = maskdying;
- else
- rfds = mask0;
+ if (privsep_init() != 0)
+ exit(1);
+ /*
+ * The fork()'ed privileged side will close its copy of fp. We wait
+ * until here to get the correct child pid.
+ */
+ racoon_pid = getpid();
+ fprintf(fp, "%ld\n", (long)racoon_pid);
+ fclose(fp);
+
+ for (i = 0; i <= NSIG; i++)
+ sigreq[i] = 0;
+
+ while (1) {
/*
* asynchronous requests via signal.
* make sure to reset sigreq to 0.
@@ -192,7 +296,11 @@ session(void)
/* scheduling */
timeout = schedular();
- error = select(nfds, &rfds, (fd_set *)0, (fd_set *)0, timeout);
+ /* schedular can change select() mask, so we reset
+ * the working copy here */
+ active_mask = preset_mask;
+
+ error = select(nfds + 1, &active_mask, NULL, NULL, timeout);
if (error < 0) {
switch (errno) {
case EINTR:
@@ -206,28 +314,24 @@ session(void)
/*NOTREACHED*/
}
-#ifdef ENABLE_ADMINPORT
- if ((lcconf->sock_admin != -1) &&
- (FD_ISSET(lcconf->sock_admin, &rfds)))
- admin_handler();
-#endif
-
- for (p = lcconf->myaddrs; p; p = p->next) {
- if (!p->addr)
- continue;
- if (FD_ISSET(p->sock, &rfds))
- isakmp_handler(p->sock);
+ count = 0;
+ for (i = 0; i < NUM_PRIORITIES; i++) {
+ TAILQ_FOREACH(fdm, &fd_monitor_tree[i], chain) {
+ if (!FD_ISSET(fdm->fd, &active_mask))
+ continue;
+
+ FD_CLR(fdm->fd, &active_mask);
+ if (fdm->callback != NULL) {
+ fdm->callback(fdm->ctx, fdm->fd);
+ count++;
+ } else
+ plog(LLV_ERROR, LOCATION, NULL,
+ "fd %d set, but no active callback\n", i);
+ }
+ if (count != 0)
+ break;
}
- if (FD_ISSET(lcconf->sock_pfkey, &rfds))
- pfkey_handler();
-
- if (lcconf->rtsock >= 0 && FD_ISSET(lcconf->rtsock, &rfds)) {
- if (update_myaddrs() && lcconf->autograbaddr)
- check_rtsock(NULL);
- else
- initfds();
- }
}
}
@@ -235,82 +339,18 @@ session(void)
static void
close_session()
{
-#ifdef ENABLE_FASTQUIT
+ evt_generic(EVT_RACOON_QUIT, NULL);
+ pfkey_send_flush(lcconf->sock_pfkey, SADB_SATYPE_UNSPEC);
flushph2();
-#endif
flushph1();
+ flushrmconf();
+ flushsainfo();
close_sockets();
backupsa_clean();
- plog(LLV_INFO, LOCATION, NULL, "racoon shutdown\n");
- exit(0);
-}
+ plog(LLV_INFO, LOCATION, NULL, "racoon process %d shutdown\n", getpid());
-static void
-check_rtsock(unused)
- void *unused;
-{
- isakmp_close();
- grab_myaddrs();
- autoconf_myaddrsport();
- isakmp_open();
-
- /* initialize socket list again */
- initfds();
-}
-
-static void
-initfds()
-{
- struct myaddrs *p;
-
- nfds = 0;
-
- FD_ZERO(&mask0);
- FD_ZERO(&maskdying);
-
-#ifdef ENABLE_ADMINPORT
- if (lcconf->sock_admin != -1) {
- if (lcconf->sock_admin >= FD_SETSIZE) {
- plog(LLV_ERROR, LOCATION, NULL, "fd_set overrun\n");
- exit(1);
- }
- FD_SET(lcconf->sock_admin, &mask0);
- /* XXX should we listen on admin socket when dying ?
- */
-#if 0
- FD_SET(lcconf->sock_admin, &maskdying);
-#endif
- nfds = (nfds > lcconf->sock_admin ? nfds : lcconf->sock_admin);
- }
-#endif
- if (lcconf->sock_pfkey >= FD_SETSIZE) {
- plog(LLV_ERROR, LOCATION, NULL, "fd_set overrun\n");
- exit(1);
- }
- FD_SET(lcconf->sock_pfkey, &mask0);
- FD_SET(lcconf->sock_pfkey, &maskdying);
- nfds = (nfds > lcconf->sock_pfkey ? nfds : lcconf->sock_pfkey);
- if (lcconf->rtsock >= 0) {
- if (lcconf->rtsock >= FD_SETSIZE) {
- plog(LLV_ERROR, LOCATION, NULL, "fd_set overrun\n");
- exit(1);
- }
- FD_SET(lcconf->rtsock, &mask0);
- nfds = (nfds > lcconf->rtsock ? nfds : lcconf->rtsock);
- }
-
- for (p = lcconf->myaddrs; p; p = p->next) {
- if (!p->addr)
- continue;
- if (p->sock >= FD_SETSIZE) {
- plog(LLV_ERROR, LOCATION, NULL, "fd_set overrun\n");
- exit(1);
- }
- FD_SET(p->sock, &mask0);
- nfds = (nfds > p->sock ? nfds : p->sock);
- }
- nfds++;
+ exit(0);
}
static int signals[] = {
@@ -331,10 +371,7 @@ RETSIGTYPE
signal_handler(sig)
int sig;
{
- /* Do not just set it to 1, because we may miss some signals by just setting
- * values to 0/1
- */
- sigreq[sig]++;
+ sigreq[sig] = 1;
}
@@ -345,27 +382,28 @@ static void reload_conf(){
#ifdef ENABLE_HYBRID
if ((isakmp_cfg_init(ISAKMP_CFG_INIT_WARM)) != 0) {
- plog(LLV_ERROR, LOCATION, NULL,
+ plog(LLV_ERROR, LOCATION, NULL,
"ISAKMP mode config structure reset failed, "
"not reloading\n");
return;
}
#endif
- save_sainfotree();
+ sainfo_start_reload();
/* TODO: save / restore / flush old lcconf (?) / rmtree
*/
-/* initlcconf();*/ /* racoon_conf ? ! */
+ rmconf_start_reload();
- save_rmconf();
- initrmconf();
+#ifdef HAVE_LIBRADIUS
+ /* free and init radius configuration */
+ xauth_radius_init_conf(1);
+#endif
+
+ pfkey_reload();
- /* Do a part of pfkey_init() ?
- * SPD reload ?
- */
-
save_params();
+ flushlcconf();
error = cfparse();
if (error != 0){
plog(LLV_ERROR, LOCATION, NULL, "config reload failed\n");
@@ -374,19 +412,17 @@ static void reload_conf(){
}
restore_params();
-#if 0
+#if 0
if (dump_config)
dumprmconf ();
#endif
- /*
- * init_myaddr() ?
- * If running in privilege separation, do not reinitialize
- * the IKE listener, as we will not have the right to
- * setsockopt(IP_IPSEC_POLICY).
- */
- if (geteuid() == 0)
- check_rtsock(NULL);
+ myaddr_sync();
+
+#ifdef HAVE_LIBRADIUS
+ /* re-initialize radius state */
+ xauth_radius_init();
+#endif
/* Revalidate ph1 / ph2tree !!!
* update ctdtree if removing some ph1 !
@@ -395,44 +431,33 @@ static void reload_conf(){
/* Update ctdtree ?
*/
- save_sainfotree_flush();
- save_rmconf_flush();
+ sainfo_finish_reload();
+ rmconf_finish_reload();
}
static void
check_sigreq()
{
- int sig;
+ int sig, s;
- /*
- * XXX We are not able to tell if we got
- * several time the same signal. This is
- * not a problem for the current code,
- * but we shall remember this limitation.
- */
for (sig = 0; sig <= NSIG; sig++) {
if (sigreq[sig] == 0)
continue;
+ sigreq[sig] = 0;
- sigreq[sig]--;
switch(sig) {
case 0:
return;
-
- /* Catch up childs, mainly scripts.
- */
+
case SIGCHLD:
- {
- pid_t pid;
- int s;
-
- pid = wait(&s);
- }
- break;
+ /* Reap all pending children */
+ while (waitpid(-1, &s, WNOHANG) > 0)
+ ;
+ break;
#ifdef DEBUG_RECORD_MALLOCATION
- /*
- * XXX This operation is signal handler unsafe and may lead to
+ /*
+ * XXX This operation is signal handler unsafe and may lead to
* crashes and security breaches: See Henning Brauer talk at
* EuroBSDCon 2005. Do not run in production with this option
* enabled.
@@ -448,108 +473,31 @@ check_sigreq()
break;
case SIGINT:
- case SIGTERM:
- plog(LLV_INFO, LOCATION, NULL,
+ case SIGTERM:
+ plog(LLV_INFO, LOCATION, NULL,
"caught signal %d\n", sig);
- EVT_PUSH(NULL, NULL, EVTT_RACOON_QUIT, NULL);
- pfkey_send_flush(lcconf->sock_pfkey,
- SADB_SATYPE_UNSPEC);
-#ifdef ENABLE_FASTQUIT
close_session();
-#else
- sched_new(1, check_flushsa_stub, NULL);
-#endif
- dying = 1;
break;
default:
- plog(LLV_INFO, LOCATION, NULL,
+ plog(LLV_INFO, LOCATION, NULL,
"caught signal %d\n", sig);
break;
}
}
}
-/*
- * waiting the termination of processing until sending DELETE message
- * for all inbound SA will complete.
- */
-static void
-check_flushsa_stub(p)
- void *p;
-{
-
- check_flushsa();
-}
-
-static void
-check_flushsa()
-{
- vchar_t *buf;
- struct sadb_msg *msg, *end, *next;
- struct sadb_sa *sa;
- caddr_t mhp[SADB_EXT_MAX + 1];
- int n;
-
- buf = pfkey_dump_sadb(SADB_SATYPE_UNSPEC);
- if (buf == NULL) {
- plog(LLV_DEBUG, LOCATION, NULL,
- "pfkey_dump_sadb: returned nothing.\n");
- return;
- }
-
- msg = (struct sadb_msg *)buf->v;
- end = (struct sadb_msg *)(buf->v + buf->l);
-
- /* counting SA except of dead one. */
- n = 0;
- while (msg < end) {
- if (PFKEY_UNUNIT64(msg->sadb_msg_len) < sizeof(*msg))
- break;
- next = (struct sadb_msg *)((caddr_t)msg + PFKEY_UNUNIT64(msg->sadb_msg_len));
- if (msg->sadb_msg_type != SADB_DUMP) {
- msg = next;
- continue;
- }
-
- if (pfkey_align(msg, mhp) || pfkey_check(mhp)) {
- plog(LLV_ERROR, LOCATION, NULL,
- "pfkey_check (%s)\n", ipsec_strerror());
- msg = next;
- continue;
- }
-
- sa = (struct sadb_sa *)(mhp[SADB_EXT_SA]);
- if (!sa) {
- msg = next;
- continue;
- }
-
- if (sa->sadb_sa_state != SADB_SASTATE_DEAD) {
- n++;
- msg = next;
- continue;
- }
-
- msg = next;
- }
-
- if (buf != NULL)
- vfree(buf);
-
- if (n) {
- sched_new(1, check_flushsa_stub, NULL);
- return;
- }
-
- close_session();
-}
-
static void
init_signal()
{
int i;
+ /*
+ * Ignore SIGPIPE as we check the return value of system calls
+ * that write to pipe-like fds.
+ */
+ signal(SIGPIPE, SIG_IGN);
+
for (i = 0; signals[i] != 0; i++)
if (set_signal(signals[i], signal_handler) < 0) {
plog(LLV_ERROR, LOCATION, NULL,
@@ -582,7 +530,7 @@ set_signal(sig, func)
static int
close_sockets()
{
- isakmp_close();
+ myaddr_close();
pfkey_close(lcconf->sock_pfkey);
#ifdef ENABLE_ADMINPORT
(void)admin_close();
diff --git a/src/racoon/session.h b/src/racoon/session.h
index 58799ee..7764c62 100644
--- a/src/racoon/session.h
+++ b/src/racoon/session.h
@@ -1,4 +1,4 @@
-/* $NetBSD: session.h,v 1.4 2006/09/09 16:22:10 manu Exp $ */
+/* $NetBSD: session.h,v 1.9 2010/10/21 06:15:28 tteras Exp $ */
/* Id: session.h,v 1.3 2004/06/11 16:00:17 ludvigm Exp */
@@ -37,4 +37,7 @@
extern int session __P((void));
extern RETSIGTYPE signal_handler __P((int));
+extern void monitor_fd __P((int fd, int (*callback)(void *, int), void *ctx, int priority));
+extern void unmonitor_fd __P((int fd));
+
#endif /* _SESSION_H */
diff --git a/src/racoon/sockmisc.c b/src/racoon/sockmisc.c
index 16c949d..48bede1 100644
--- a/src/racoon/sockmisc.c
+++ b/src/racoon/sockmisc.c
@@ -1,4 +1,4 @@
-/* $NetBSD: sockmisc.c,v 1.8.6.1 2007/08/01 11:52:22 vanhu Exp $ */
+/* $NetBSD: sockmisc.c,v 1.19 2011/03/14 17:18:13 tteras Exp $ */
/* Id: sockmisc.c,v 1.24 2006/05/07 21:32:59 manubsd Exp */
@@ -56,75 +56,28 @@
#include "var.h"
#include "misc.h"
+#include "vmbuf.h"
#include "plog.h"
#include "sockmisc.h"
#include "debug.h"
#include "gcmalloc.h"
#include "debugrm.h"
#include "libpfkey.h"
+#include "isakmp_var.h"
-#ifndef IP_IPSEC_POLICY
-#define IP_IPSEC_POLICY 16 /* XXX: from linux/in.h */
-#endif
-
-#ifndef IPV6_IPSEC_POLICY
-#define IPV6_IPSEC_POLICY 34 /* XXX: from linux/???.h per
- "Tom Lendacky" <toml@us.ibm.com> */
-#endif
-
-const int niflags = 0;
-
-/*
- * compare two sockaddr without port number.
- * OUT: 0: equal.
- * 1: not equal.
- */
-int
-cmpsaddrwop(addr1, addr2)
- const struct sockaddr *addr1;
- const struct sockaddr *addr2;
-{
- caddr_t sa1, sa2;
-
- if (addr1 == 0 && addr2 == 0)
- return 0;
- if (addr1 == 0 || addr2 == 0)
- return 1;
-
-#ifdef __linux__
- if (addr1->sa_family != addr2->sa_family)
- return 1;
+#ifdef NOUSE_PRIVSEP
+#define BIND bind
+#define SOCKET socket
+#define SETSOCKOPT setsockopt
#else
- if (addr1->sa_len != addr2->sa_len
- || addr1->sa_family != addr2->sa_family)
- return 1;
-
-#endif /* __linux__ */
-
- switch (addr1->sa_family) {
- case AF_INET:
- sa1 = (caddr_t)&((struct sockaddr_in *)addr1)->sin_addr;
- sa2 = (caddr_t)&((struct sockaddr_in *)addr2)->sin_addr;
- if (memcmp(sa1, sa2, sizeof(struct in_addr)) != 0)
- return 1;
- break;
-#ifdef INET6
- case AF_INET6:
- sa1 = (caddr_t)&((struct sockaddr_in6 *)addr1)->sin6_addr;
- sa2 = (caddr_t)&((struct sockaddr_in6 *)addr2)->sin6_addr;
- if (memcmp(sa1, sa2, sizeof(struct in6_addr)) != 0)
- return 1;
- if (((struct sockaddr_in6 *)addr1)->sin6_scope_id !=
- ((struct sockaddr_in6 *)addr2)->sin6_scope_id)
- return 1;
- break;
+#include "admin.h"
+#include "privsep.h"
+#define BIND privsep_bind
+#define SOCKET privsep_socket
+#define SETSOCKOPT privsep_setsockopt
#endif
- default:
- return 1;
- }
- return 0;
-}
+const int niflags = 0;
/*
* compare two sockaddr with port, taking care wildcard.
@@ -133,40 +86,34 @@ cmpsaddrwop(addr1, addr2)
* 1: not equal.
*/
int
-cmpsaddrwild(addr1, addr2)
+cmpsaddr(addr1, addr2)
const struct sockaddr *addr1;
const struct sockaddr *addr2;
{
caddr_t sa1, sa2;
- u_short port1, port2;
+ u_short port1 = IPSEC_PORT_ANY;
+ u_short port2 = IPSEC_PORT_ANY;
- if (addr1 == 0 && addr2 == 0)
- return 0;
- if (addr1 == 0 || addr2 == 0)
- return 1;
+ if (addr1 == NULL && addr2 == NULL)
+ return CMPSADDR_MATCH;
-#ifdef __linux__
- if (addr1->sa_family != addr2->sa_family)
- return 1;
-#else
- if (addr1->sa_len != addr2->sa_len
- || addr1->sa_family != addr2->sa_family)
- return 1;
+ if (addr1 == NULL || addr2 == NULL)
+ return CMPSADDR_MISMATCH;
-#endif /* __linux__ */
+ if (addr1->sa_family != addr2->sa_family ||
+ sysdep_sa_len(addr1) != sysdep_sa_len(addr2))
+ return CMPSADDR_MISMATCH;
switch (addr1->sa_family) {
+ case AF_UNSPEC:
+ break;
case AF_INET:
sa1 = (caddr_t)&((struct sockaddr_in *)addr1)->sin_addr;
sa2 = (caddr_t)&((struct sockaddr_in *)addr2)->sin_addr;
port1 = ((struct sockaddr_in *)addr1)->sin_port;
port2 = ((struct sockaddr_in *)addr2)->sin_port;
- if (!(port1 == IPSEC_PORT_ANY ||
- port2 == IPSEC_PORT_ANY ||
- port1 == port2))
- return 1;
if (memcmp(sa1, sa2, sizeof(struct in_addr)) != 0)
- return 1;
+ return CMPSADDR_MISMATCH;
break;
#ifdef INET6
case AF_INET6:
@@ -174,89 +121,31 @@ cmpsaddrwild(addr1, addr2)
sa2 = (caddr_t)&((struct sockaddr_in6 *)addr2)->sin6_addr;
port1 = ((struct sockaddr_in6 *)addr1)->sin6_port;
port2 = ((struct sockaddr_in6 *)addr2)->sin6_port;
- if (!(port1 == IPSEC_PORT_ANY ||
- port2 == IPSEC_PORT_ANY ||
- port1 == port2))
- return 1;
if (memcmp(sa1, sa2, sizeof(struct in6_addr)) != 0)
- return 1;
+ return CMPSADDR_MISMATCH;
if (((struct sockaddr_in6 *)addr1)->sin6_scope_id !=
((struct sockaddr_in6 *)addr2)->sin6_scope_id)
- return 1;
+ return CMPSADDR_MISMATCH;
break;
#endif
default:
- return 1;
+ return CMPSADDR_MISMATCH;
}
- return 0;
-}
+ if (port1 == port2)
+ return CMPSADDR_MATCH;
-/*
- * compare two sockaddr with strict match on port.
- * OUT: 0: equal.
- * 1: not equal.
- */
-int
-cmpsaddrstrict(addr1, addr2)
- const struct sockaddr *addr1;
- const struct sockaddr *addr2;
-{
- caddr_t sa1, sa2;
- u_short port1, port2;
+ if (port1 == IPSEC_PORT_ANY ||
+ port2 == IPSEC_PORT_ANY)
+ return CMPSADDR_WILDPORT_MATCH;
- if (addr1 == 0 && addr2 == 0)
- return 0;
- if (addr1 == 0 || addr2 == 0)
- return 1;
-
-#ifdef __linux__
- if (addr1->sa_family != addr2->sa_family)
- return 1;
-#else
- if (addr1->sa_len != addr2->sa_len
- || addr1->sa_family != addr2->sa_family)
- return 1;
-
-#endif /* __linux__ */
-
- switch (addr1->sa_family) {
- case AF_INET:
- sa1 = (caddr_t)&((struct sockaddr_in *)addr1)->sin_addr;
- sa2 = (caddr_t)&((struct sockaddr_in *)addr2)->sin_addr;
- port1 = ((struct sockaddr_in *)addr1)->sin_port;
- port2 = ((struct sockaddr_in *)addr2)->sin_port;
- if (port1 != port2)
- return 1;
- if (memcmp(sa1, sa2, sizeof(struct in_addr)) != 0)
- return 1;
- break;
-#ifdef INET6
- case AF_INET6:
- sa1 = (caddr_t)&((struct sockaddr_in6 *)addr1)->sin6_addr;
- sa2 = (caddr_t)&((struct sockaddr_in6 *)addr2)->sin6_addr;
- port1 = ((struct sockaddr_in6 *)addr1)->sin6_port;
- port2 = ((struct sockaddr_in6 *)addr2)->sin6_port;
- if (port1 != port2)
- return 1;
- if (memcmp(sa1, sa2, sizeof(struct in6_addr)) != 0)
- return 1;
- if (((struct sockaddr_in6 *)addr1)->sin6_scope_id !=
- ((struct sockaddr_in6 *)addr2)->sin6_scope_id)
- return 1;
- break;
-#endif
- default:
- return 1;
- }
-
- return 0;
+ return CMPSADDR_WOP_MATCH;
}
#ifdef ANDROID_PATCHED
struct sockaddr *getlocaladdr(struct sockaddr *remote)
-{
+{
struct sockaddr_storage local;
socklen_t len = sysdep_sa_len(remote);
int s = socket(remote->sa_family, SOCK_DGRAM, 0);
@@ -266,13 +155,12 @@ struct sockaddr *getlocaladdr(struct sockaddr *remote)
return NULL;
}
close(s);
- set_port((struct sockaddr *)&local, 0);
return dupsaddr((struct sockaddr *)&local);
}
int recvfromto(int s, void *buf, size_t len, int flags, struct sockaddr *from,
socklen_t *fromlen, struct sockaddr *to, unsigned int *tolen)
-{
+{
*tolen = sizeof(struct sockaddr_storage);
if (getsockname(s, to, (socklen_t *)tolen) == -1) {
return -1;
@@ -282,7 +170,7 @@ int recvfromto(int s, void *buf, size_t len, int flags, struct sockaddr *from,
int sendfromto(int s, const void *buf, size_t len, struct sockaddr *from,
struct sockaddr *to, int count)
-{
+{
socklen_t tolen = sysdep_sa_len(to);
int i;
for (i = 0; i < count; ++i) {
@@ -294,7 +182,7 @@ int sendfromto(int s, const void *buf, size_t len, struct sockaddr *from,
}
int setsockopt_bypass(int s, int family)
-{
+{
struct sadb_x_policy p = {
.sadb_x_policy_len = PFKEY_UNIT64(sizeof(struct sadb_x_policy)),
.sadb_x_policy_exttype = SADB_X_EXT_POLICY,
@@ -315,7 +203,7 @@ int setsockopt_bypass(int s, int family)
}
return 0;
}
-
+
#else
/* get local address against the destination. */
@@ -335,7 +223,7 @@ getlocaladdr(remote)
}
/* get real interface received packet */
- if ((s = socket(remote->sa_family, SOCK_DGRAM, 0)) < 0) {
+ if ((s = SOCKET(remote->sa_family, SOCK_DGRAM, 0)) < 0) {
plog(LLV_ERROR, LOCATION, NULL,
"socket (%s)\n", strerror(errno));
goto err;
@@ -382,8 +270,9 @@ recvfromto(s, buf, buflen, flags, from, fromlen, to, tolen)
u_int *tolen;
{
int otolen;
- u_int len;
- struct sockaddr_storage ss;
+ socklen_t slen;
+ int len;
+ union sockaddr_any sa;
struct msghdr m;
struct cmsghdr *cm;
struct iovec iov[2];
@@ -396,8 +285,8 @@ recvfromto(s, buf, buflen, flags, from, fromlen, to, tolen)
struct sockaddr_in6 *sin6;
#endif
- len = sizeof(ss);
- if (getsockname(s, (struct sockaddr *)&ss, &len) < 0) {
+ slen = sizeof(sa);
+ if (getsockname(s, &sa.sa, &slen) < 0) {
plog(LLV_ERROR, LOCATION, NULL,
"getsockname (%s)\n", strerror(errno));
return -1;
@@ -430,7 +319,7 @@ recvfromto(s, buf, buflen, flags, from, fromlen, to, tolen)
"cmsg %d %d\n", cm->cmsg_level, cm->cmsg_type);)
#endif
#if defined(INET6) && defined(INET6_ADVAPI)
- if (ss.ss_family == AF_INET6
+ if (sa.sa.sa_family == AF_INET6
&& cm->cmsg_level == IPPROTO_IPV6
&& cm->cmsg_type == IPV6_PKTINFO
&& otolen >= sizeof(*sin6)) {
@@ -449,14 +338,13 @@ recvfromto(s, buf, buflen, flags, from, fromlen, to, tolen)
sin6->sin6_scope_id = pi->ipi6_ifindex;
else
sin6->sin6_scope_id = 0;
- sin6->sin6_port =
- ((struct sockaddr_in6 *)&ss)->sin6_port;
+ sin6->sin6_port = sa.sin6.sin6_port;
otolen = -1; /* "to" already set */
continue;
}
#endif
#ifdef __linux__
- if (ss.ss_family == AF_INET
+ if (sa.sa.sa_family == AF_INET
&& cm->cmsg_level == IPPROTO_IP
&& cm->cmsg_type == IP_PKTINFO
&& otolen >= sizeof(sin)) {
@@ -467,14 +355,13 @@ recvfromto(s, buf, buflen, flags, from, fromlen, to, tolen)
sin->sin_family = AF_INET;
memcpy(&sin->sin_addr, &pi->ipi_addr,
sizeof(sin->sin_addr));
- sin->sin_port =
- ((struct sockaddr_in *)&ss)->sin_port;
+ sin->sin_port = sa.sin.sin_port;
otolen = -1; /* "to" already set */
continue;
}
#endif
#if defined(INET6) && defined(IPV6_RECVDSTADDR)
- if (ss.ss_family == AF_INET6
+ if (sa.sa.sa_family == AF_INET6
&& cm->cmsg_level == IPPROTO_IPV6
&& cm->cmsg_type == IPV6_RECVDSTADDR
&& otolen >= sizeof(*sin6)) {
@@ -485,14 +372,13 @@ recvfromto(s, buf, buflen, flags, from, fromlen, to, tolen)
sin6->sin6_len = sizeof(*sin6);
memcpy(&sin6->sin6_addr, CMSG_DATA(cm),
sizeof(sin6->sin6_addr));
- sin6->sin6_port =
- ((struct sockaddr_in6 *)&ss)->sin6_port;
+ sin6->sin6_port = sa.sin6.sin6_port;
otolen = -1; /* "to" already set */
continue;
}
#endif
#ifndef __linux__
- if (ss.ss_family == AF_INET
+ if (sa.sa.sa_family == AF_INET
&& cm->cmsg_level == IPPROTO_IP
&& cm->cmsg_type == IP_RECVDSTADDR
&& otolen >= sizeof(*sin)) {
@@ -503,7 +389,7 @@ recvfromto(s, buf, buflen, flags, from, fromlen, to, tolen)
sin->sin_len = sizeof(*sin);
memcpy(&sin->sin_addr, CMSG_DATA(cm),
sizeof(sin->sin_addr));
- sin->sin_port = ((struct sockaddr_in *)&ss)->sin_port;
+ sin->sin_port = sa.sin.sin_port;
otolen = -1; /* "to" already set */
continue;
}
@@ -523,7 +409,8 @@ sendfromto(s, buf, buflen, src, dst, cnt)
struct sockaddr *dst;
{
struct sockaddr_storage ss;
- u_int len;
+ socklen_t slen;
+ int len = 0;
int i;
if (src->sa_family != dst->sa_family) {
@@ -532,8 +419,8 @@ sendfromto(s, buf, buflen, src, dst, cnt)
return -1;
}
- len = sizeof(ss);
- if (getsockname(s, (struct sockaddr *)&ss, &len) < 0) {
+ slen = sizeof(ss);
+ if (getsockname(s, (struct sockaddr *)&ss, &slen) < 0) {
plog(LLV_ERROR, LOCATION, NULL,
"getsockname (%s)\n", strerror(errno));
return -1;
@@ -701,7 +588,7 @@ sendfromto(s, buf, buflen, src, dst, cnt)
* Better approach is to prepare bind'ed udp sockets for
* each of the interface addresses.
*/
- sendsock = socket(src->sa_family, SOCK_DGRAM, 0);
+ sendsock = SOCKET(src->sa_family, SOCK_DGRAM, 0);
if (sendsock < 0) {
plog(LLV_ERROR, LOCATION, NULL,
"socket (%s)\n", strerror(errno));
@@ -736,7 +623,8 @@ sendfromto(s, buf, buflen, src, dst, cnt)
return -1;
}
- if (bind(sendsock, (struct sockaddr *)src, sysdep_sa_len(src)) < 0) {
+ if (BIND(sendsock, (struct sockaddr *)src,
+ sysdep_sa_len(src)) < 0) {
plog(LLV_ERROR, LOCATION, NULL,
"bind 1 (%s)\n", strerror(errno));
close(sendsock);
@@ -800,7 +688,7 @@ setsockopt_bypass(so, family)
ipsec_strerror());
return -1;
}
- if (setsockopt(so, level,
+ if (SETSOCKOPT(so, level,
(level == IPPROTO_IP ?
IP_IPSEC_POLICY : IPV6_IPSEC_POLICY),
buf, ipsec_get_policylen(buf)) < 0) {
@@ -819,7 +707,7 @@ setsockopt_bypass(so, family)
ipsec_strerror());
return -1;
}
- if (setsockopt(so, level,
+ if (SETSOCKOPT(so, level,
(level == IPPROTO_IP ?
IP_IPSEC_POLICY : IPV6_IPSEC_POLICY),
buf, ipsec_get_policylen(buf)) < 0) {
@@ -833,6 +721,8 @@ setsockopt_bypass(so, family)
return 0;
}
+#endif
+
struct sockaddr *
newsaddr(len)
int len;
@@ -858,8 +748,6 @@ out:
return new;
}
-#endif
-
struct sockaddr *
dupsaddr(src)
struct sockaddr *src;
@@ -1114,13 +1002,13 @@ naddr_score(const struct netaddr *naddr, const struct sockaddr *saddr)
free(a2);
free(a3);
}
- if (cmpsaddrwop(&sa, &naddr->sa.sa) == 0)
+ if (cmpsaddr(&sa, &naddr->sa.sa) <= CMPSADDR_WOP_MATCH)
return naddr->prefix + port_score;
return -1;
}
-/* Some usefull functions for sockaddr port manipulations. */
+/* Some useful functions for sockaddr port manipulations. */
u_int16_t
extract_port (const struct sockaddr *addr)
{
@@ -1130,6 +1018,8 @@ extract_port (const struct sockaddr *addr)
return port;
switch (addr->sa_family) {
+ case AF_UNSPEC:
+ break;
case AF_INET:
port = ((struct sockaddr_in *)addr)->sin_port;
break;
diff --git a/src/racoon/sockmisc.h b/src/racoon/sockmisc.h
index a035dec..67bfdaf 100644
--- a/src/racoon/sockmisc.h
+++ b/src/racoon/sockmisc.h
@@ -1,4 +1,4 @@
-/* $NetBSD: sockmisc.h,v 1.7 2006/09/09 16:22:10 manu Exp $ */
+/* $NetBSD: sockmisc.h,v 1.13 2011/03/14 17:18:13 tteras Exp $ */
/* Id: sockmisc.h,v 1.9 2005/10/05 16:55:41 manubsd Exp */
@@ -34,26 +34,34 @@
#ifndef _SOCKMISC_H
#define _SOCKMISC_H
+#ifndef IP_IPSEC_POLICY
+#define IP_IPSEC_POLICY 16 /* XXX: from linux/in.h */
+#endif
+
+#ifndef IPV6_IPSEC_POLICY
+#define IPV6_IPSEC_POLICY 34 /* XXX: from linux/???.h per
+ "Tom Lendacky" <toml@us.ibm.com> */
+#endif
+
+union sockaddr_any {
+ struct sockaddr sa;
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
+};
+
struct netaddr {
- union {
- struct sockaddr sa;
- struct sockaddr_in sin;
- struct sockaddr_in6 sin6;
- } sa;
+ union sockaddr_any sa;
unsigned long prefix;
};
extern const int niflags;
-extern int cmpsaddrwop __P((const struct sockaddr *, const struct sockaddr *));
-extern int cmpsaddrwild __P((const struct sockaddr *, const struct sockaddr *));
-extern int cmpsaddrstrict __P((const struct sockaddr *, const struct sockaddr *));
+#define CMPSADDR_MATCH 0
+#define CMPSADDR_WILDPORT_MATCH 1
+#define CMPSADDR_WOP_MATCH 2
+#define CMPSADDR_MISMATCH 3
-#ifdef ENABLE_NATT
-#define CMPSADDR(saddr1, saddr2) cmpsaddrstrict((saddr1), (saddr2))
-#else
-#define CMPSADDR(saddr1, saddr2) cmpsaddrwop((saddr1), (saddr2))
-#endif
+extern int cmpsaddr __P((const struct sockaddr *, const struct sockaddr *));
extern struct sockaddr *getlocaladdr __P((struct sockaddr *));
@@ -81,7 +89,7 @@ extern char *naddrwop2str_fromto __P((const char *format, const struct netaddr *
const struct netaddr *daddr));
extern int naddr_score(const struct netaddr *naddr, const struct sockaddr *saddr);
-/* Some usefull functions for sockaddr port manipulations. */
+/* Some useful functions for sockaddr port manipulations. */
extern u_int16_t extract_port __P((const struct sockaddr *addr));
extern u_int16_t *set_port __P((struct sockaddr *addr, u_int16_t new_port));
extern u_int16_t *get_port_ptr __P((struct sockaddr *addr));
diff --git a/src/racoon/strnames.c b/src/racoon/strnames.c
index fa5df0f..4906b33 100644
--- a/src/racoon/strnames.c
+++ b/src/racoon/strnames.c
@@ -1,4 +1,4 @@
-/* $NetBSD: strnames.c,v 1.7.6.1 2007/08/01 11:52:22 vanhu Exp $ */
+/* $NetBSD: strnames.c,v 1.9 2008/07/14 05:40:13 tteras Exp $ */
/* $KAME: strnames.c,v 1.25 2003/11/13 10:53:26 itojun Exp $ */
@@ -276,6 +276,8 @@ static struct ksmap name_isakmp_notify_msg[] = {
{ ISAKMP_NTYPE_RESPONDER_LIFETIME, "RESPONDER-LIFETIME", NULL },
{ ISAKMP_NTYPE_REPLAY_STATUS, "REPLAY-STATUS", NULL },
{ ISAKMP_NTYPE_INITIAL_CONTACT, "INITIAL-CONTACT", NULL },
+{ ISAKMP_NTYPE_R_U_THERE, "R-U-THERE", NULL },
+{ ISAKMP_NTYPE_R_U_THERE_ACK, "R-U-THERE-ACK", NULL },
#ifdef ENABLE_HYBRID
{ ISAKMP_NTYPE_UNITY_HEARTBEAT, "HEARTBEAT (Unity)", NULL },
#endif
diff --git a/src/racoon/throttle.c b/src/racoon/throttle.c
index cd7de1f..84a2d6b 100644
--- a/src/racoon/throttle.c
+++ b/src/racoon/throttle.c
@@ -1,4 +1,4 @@
-/* $NetBSD: throttle.c,v 1.4 2006/09/09 16:22:10 manu Exp $ */
+/* $NetBSD: throttle.c,v 1.7 2011/03/14 17:18:13 tteras Exp $ */
/* Id: throttle.c,v 1.5 2006/04/05 20:54:50 manubsd Exp */
@@ -33,23 +33,10 @@
#include "config.h"
-#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
#include <sys/param.h>
#include <sys/queue.h>
-#include <sys/socket.h>
-
#include <netinet/in.h>
#include <resolv.h>
@@ -58,21 +45,21 @@
#include "plog.h"
#include "throttle.h"
#include "sockmisc.h"
-#include "libpfkey.h"
#include "isakmp_var.h"
#include "isakmp.h"
#include "isakmp_xauth.h"
#include "isakmp_cfg.h"
#include "gcmalloc.h"
-struct throttle_list throttle_list = TAILQ_HEAD_INITIALIZER(throttle_list);
-
+static struct throttle_list throttle_list =
+ TAILQ_HEAD_INITIALIZER(throttle_list);
struct throttle_entry *
throttle_add(addr)
struct sockaddr *addr;
{
struct throttle_entry *te;
+ struct timeval now, penalty;
size_t len;
len = sizeof(*te)
@@ -82,7 +69,11 @@ throttle_add(addr)
if ((te = racoon_malloc(len)) == NULL)
return NULL;
- te->penalty = time(NULL) + isakmp_cfg_config.auth_throttle;
+ sched_get_monotonic_time(&now);
+ penalty.tv_sec = isakmp_cfg_config.auth_throttle;
+ penalty.tv_usec = 0;
+ timeradd(&now, &penalty, &te->penalty_ends);
+
memcpy(&te->host, addr, sysdep_sa_len(addr));
TAILQ_INSERT_HEAD(&throttle_list, te, next);
@@ -95,26 +86,25 @@ throttle_host(addr, authfail)
int authfail;
{
struct throttle_entry *te;
+ struct timeval now, res;
int found = 0;
- time_t now;
if (isakmp_cfg_config.auth_throttle == 0)
return 0;
- now = time(NULL);
-
+ sched_get_monotonic_time(&now);
restart:
RACOON_TAILQ_FOREACH_REVERSE(te, &throttle_list, throttle_list, next) {
- /*
- * Remove outdated entries
- */
- if (te->penalty < now) {
+ /*
+ * Remove outdated entries
+ */
+ if (timercmp(&te->penalty_ends, &now, <)) {
TAILQ_REMOVE(&throttle_list, te, next);
racoon_free(te);
goto restart;
}
-
- if (cmpsaddrwop(addr, (struct sockaddr *)&te->host) == 0) {
+
+ if (cmpsaddr(addr, (struct sockaddr *) &te->host) <= CMPSADDR_WOP_MATCH) {
found = 1;
break;
}
@@ -130,8 +120,7 @@ restart:
if ((te = throttle_add(addr)) == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
"Throttle insertion failed\n");
- return (time(NULL)
- + isakmp_cfg_config.auth_throttle);
+ return isakmp_cfg_config.auth_throttle;
}
}
return 0;
@@ -140,19 +129,21 @@ restart:
* We had a match and auth failed, increase penalty.
*/
if (authfail) {
- time_t remaining;
- time_t new;
-
- remaining = te->penalty - now;
- new = remaining + isakmp_cfg_config.auth_throttle;
-
- if (new > THROTTLE_PENALTY_MAX)
- new = THROTTLE_PENALTY_MAX;
-
- te->penalty = now + new;
+ struct timeval remaining, penalty;
+
+ timersub(&te->penalty_ends, &now, &remaining);
+ penalty.tv_sec = isakmp_cfg_config.auth_throttle;
+ penalty.tv_usec = 0;
+ timeradd(&penalty, &remaining, &res);
+ if (res.tv_sec >= THROTTLE_PENALTY_MAX) {
+ res.tv_sec = THROTTLE_PENALTY_MAX;
+ res.tv_usec = 0;
+ }
+ timeradd(&now, &res, &te->penalty_ends);
}
}
-
- return te->penalty;
+
+ timersub(&te->penalty_ends, &now, &res);
+ return res.tv_sec;
}
diff --git a/src/racoon/throttle.h b/src/racoon/throttle.h
index baa9af5..54a8ed1 100644
--- a/src/racoon/throttle.h
+++ b/src/racoon/throttle.h
@@ -1,4 +1,4 @@
-/* $NetBSD: throttle.h,v 1.4 2006/09/09 16:22:10 manu Exp $ */
+/* $NetBSD: throttle.h,v 1.5 2009/01/23 08:25:07 tteras Exp $ */
/* Id: throttle.h,v 1.1 2004/11/30 00:46:09 manubsd Exp */
@@ -34,8 +34,10 @@
#ifndef _THROTTLE_H
#define _THROTTLE_H
+#include "schedule.h"
+
struct throttle_entry {
- int penalty;
+ struct timeval penalty_ends;
TAILQ_ENTRY(throttle_entry) next;
struct sockaddr_storage host;
};
diff --git a/src/racoon/var.h b/src/racoon/var.h
index 8abb1c2..2946a9f 100644
--- a/src/racoon/var.h
+++ b/src/racoon/var.h
@@ -1,4 +1,4 @@
-/* $NetBSD: var.h,v 1.4.6.1 2007/06/06 15:36:38 vanhu Exp $ */
+/* $NetBSD: var.h,v 1.5 2007/06/06 15:37:15 vanhu Exp $ */
/* Id: var.h,v 1.6 2004/11/20 16:16:59 monas Exp */
diff --git a/src/racoon/vendorid.c b/src/racoon/vendorid.c
index 82ddfe4..81297bd 100644
--- a/src/racoon/vendorid.c
+++ b/src/racoon/vendorid.c
@@ -1,4 +1,4 @@
-/* $NetBSD: vendorid.c,v 1.4 2006/09/09 16:22:10 manu Exp $ */
+/* $NetBSD: vendorid.c,v 1.8 2009/09/01 12:22:09 tteras Exp $ */
/* Id: vendorid.c,v 1.10 2006/02/22 16:10:21 vanhu Exp */
@@ -53,6 +53,16 @@
#include "isakmp.h"
#include "vendorid.h"
#include "crypto_openssl.h"
+#include "handler.h"
+#include "remoteconf.h"
+#ifdef ENABLE_NATT
+#include "nattraversal.h"
+#endif
+#ifdef ENABLE_HYBRID
+#include <resolv.h>
+#include "isakmp_xauth.h"
+#include "isakmp_cfg.h"
+#endif
static struct vendor_id all_vendor_ids[] = {
{ VENDORID_IPSEC_TOOLS, "IPSec-Tools" },
@@ -205,7 +215,7 @@ set_vendorid(int vendorid)
*
* gen ... points to Vendor ID payload.
*/
-int
+static int
check_vendorid(struct isakmp_gen *gen)
{
vchar_t vid, *vidhash;
@@ -238,6 +248,44 @@ unknown:
return (VENDORID_UNKNOWN);
}
+int
+handle_vendorid(struct ph1handle *iph1, struct isakmp_gen *gen)
+{
+ int vid_numeric;
+
+ vid_numeric = check_vendorid(gen);
+ if (vid_numeric == VENDORID_UNKNOWN)
+ return vid_numeric;
+
+ iph1->vendorid_mask |= BIT(vid_numeric);
+
+#ifdef ENABLE_NATT
+ if (natt_vendorid(vid_numeric))
+ natt_handle_vendorid(iph1, vid_numeric);
+#endif
+#ifdef ENABLE_HYBRID
+ switch (vid_numeric) {
+ case VENDORID_XAUTH:
+ iph1->mode_cfg->flags |= ISAKMP_CFG_VENDORID_XAUTH;
+ break;
+ case VENDORID_UNITY:
+ iph1->mode_cfg->flags |= ISAKMP_CFG_VENDORID_UNITY;
+ break;
+ default:
+ break;
+ }
+#endif
+#ifdef ENABLE_DPD
+ if (vid_numeric == VENDORID_DPD &&
+ (iph1->rmconf == NULL || iph1->rmconf->dpd)) {
+ iph1->dpd_support = 1;
+ plog(LLV_DEBUG, LOCATION, NULL, "remote supports DPD\n");
+ }
+#endif
+
+ return vid_numeric;
+}
+
static vchar_t *
vendorid_fixup(vendorid, vidhash)
int vendorid;
diff --git a/src/racoon/vendorid.h b/src/racoon/vendorid.h
index 7e2dcda..1774575 100644
--- a/src/racoon/vendorid.h
+++ b/src/racoon/vendorid.h
@@ -1,4 +1,4 @@
-/* $NetBSD: vendorid.h,v 1.4 2006/09/09 16:22:10 manu Exp $ */
+/* $NetBSD: vendorid.h,v 1.6 2009/01/23 08:06:56 tteras Exp $ */
/* Id: vendorid.h,v 1.11 2006/02/17 14:09:10 vanhu Exp */
@@ -34,25 +34,26 @@
#ifndef _VENDORID_H
#define _VENDORID_H
-/* The unknown vendor ID. */
-#define VENDORID_UNKNOWN -1
+#ifndef BIT
+#define BIT(x) (1 << (x))
+#endif
+/* The unknown vendor ID. */
+#define VENDORID_UNKNOWN -1
/* Our default vendor ID. */
-#define VENDORID_DEFAULT VENDORID_IPSEC_TOOLS
+#define VENDORID_DEFAULT VENDORID_IPSEC_TOOLS
-#define VENDORID_IPSEC_TOOLS 0
+#define VENDORID_IPSEC_TOOLS 0
-/*
- * Refer to draft-ietf-ipsec-isakmp-gss-auth-06.txt.
- */
-#define VENDORID_GSSAPI_LONG 1
-#define VENDORID_GSSAPI 2
-#define VENDORID_MS_NT5 3
-#define VENDOR_SUPPORTS_GSSAPI(x) \
- ((x) == VENDORID_GSSAPI_LONG || \
- (x) == VENDORID_GSSAPI || \
- (x) == VENDORID_MS_NT5)
+/* Refer to draft-ietf-ipsec-isakmp-gss-auth-06.txt. */
+#define VENDORID_GSSAPI_LONG 1
+#define VENDORID_GSSAPI 2
+#define VENDORID_MS_NT5 3
+
+#define VENDORID_GSSAPI_MASK (BIT(VENDORID_GSSAPI_LONG) | \
+ BIT(VENDORID_GSSAPI) | \
+ BIT(VENDORID_MS_NT5))
/* NAT-T support */
#define VENDORID_NATT_00 4
@@ -70,8 +71,7 @@
#define VENDORID_NATT_FIRST VENDORID_NATT_00
#define VENDORID_NATT_LAST VENDORID_NATT_RFC
-
-#define MAX_NATT_VID_COUNT (VENDORID_NATT_LAST - VENDORID_NATT_FIRST + 1 )
+#define MAX_NATT_VID_COUNT (VENDORID_NATT_LAST - VENDORID_NATT_FIRST + 1)
/* Hybrid auth */
#define VENDORID_XAUTH 15
@@ -88,8 +88,7 @@
* XXX: do some cleanup to have separate lists for "real" vendors (to complete)
* and "features" VendorIDs
*/
-#define VENDORID_KAME 19
-
+#define VENDORID_KAME 19
struct vendor_id {
int id;
@@ -98,7 +97,7 @@ struct vendor_id {
};
vchar_t *set_vendorid __P((int));
-int check_vendorid __P((struct isakmp_gen *));
+int handle_vendorid __P((struct ph1handle *, struct isakmp_gen *));
void compute_vendorids __P((void));
const char *vid_string_by_id __P((int id));