summaryrefslogtreecommitdiff
path: root/programs/pluto
diff options
context:
space:
mode:
Diffstat (limited to 'programs/pluto')
-rw-r--r--programs/pluto/Makefile18
-rw-r--r--programs/pluto/connections.c41
-rw-r--r--programs/pluto/constants.c91
-rw-r--r--programs/pluto/constants.h90
-rw-r--r--programs/pluto/defs.h4
-rw-r--r--programs/pluto/demux.c168
-rw-r--r--programs/pluto/demux.h4
-rw-r--r--programs/pluto/ike_alg.c33
-rw-r--r--programs/pluto/ipsec_doi.c137
-rw-r--r--programs/pluto/keys.c162
-rw-r--r--programs/pluto/keys.h10
-rw-r--r--programs/pluto/modecfg.c509
-rw-r--r--programs/pluto/modecfg.h31
-rw-r--r--programs/pluto/plutomain.c5
-rw-r--r--programs/pluto/spdb.c299
-rw-r--r--programs/pluto/spdb.h13
-rw-r--r--programs/pluto/state.h10
-rw-r--r--programs/pluto/vendor.c18
-rw-r--r--programs/pluto/vendor.h78
-rw-r--r--programs/pluto/xauth.c77
-rw-r--r--programs/pluto/xauth.h41
21 files changed, 1351 insertions, 488 deletions
diff --git a/programs/pluto/Makefile b/programs/pluto/Makefile
index 908060038..a11a755c0 100644
--- a/programs/pluto/Makefile
+++ b/programs/pluto/Makefile
@@ -12,7 +12,7 @@
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# for more details.
#
-# RCSID $Id: Makefile,v 1.45 2006/07/06 12:33:08 as Exp $
+# RCSID $Id: Makefile,v 1.47 2007/01/11 21:47:13 as Exp $
# relative path to top directory of FreeS/WAN source
# Note: referenced in ${FREESWANSRCDIR}/Makefile.inc
@@ -137,8 +137,8 @@ ifeq ($(USE_VENDORID),true)
DEFINES+= -DVENDORID
endif
-ifeq ($(USE_XAUTH_VID),true)
- DEFINES+= -DXAUTH_VID
+ifeq ($(USE_CISCO_QUIRKS),true)
+ DEFINES+= -DCISCO_QUIRKS
endif
# This compile option activates dynamic URL fetching using libcurl
@@ -262,6 +262,7 @@ DISTSRC = \
spdb.c spdb.h \
state.c state.h \
timer.c timer.h \
+ xauth.c xauth.h \
x509.c x509.h \
$(DISTGCRYPT) \
vendor.c nat_traversal.c virtual.c \
@@ -280,7 +281,7 @@ OBJSPLUTO = asn1.o connections.o constants.o cookie.o crypto.o defs.o fetch.o fo
ca.o certs.o id.o ipsec_doi.o kernel.o $(KERNEL26_OBJS) kernel_pfkey.o mp_defs.o \
kernel_noklips.o rcv_whack.o ${IPSECPOLICY_OBJS} demux.o packet.o lex.o keys.o \
dnskey.o smartcard.o ac.o rnd.o spdb.o sha1.o md5.o md2.o modecfg.o ocsp.o crl.o \
- vendor.o nat_traversal.o virtual.o
+ vendor.o nat_traversal.o virtual.o xauth.o
OBJSADNS = adns.o
@@ -477,6 +478,7 @@ vendor.o: vendor.c
virtual.o: virtual.c
whack.o: whack.c
x509.o: x509.c
+xauth.o: xauth.c
ac.o: constants.h
ac.o: defs.h
@@ -794,7 +796,7 @@ keys.o: log.h
keys.o: whack.h
keys.o: timer.h
keys.o: fetch.h
-keys.o: nat_traversal.h
+keys.o: xauth.h
lex.o: constants.h
lex.o: defs.h
lex.o: log.h
@@ -823,6 +825,7 @@ modecfg.o: sha1.h
modecfg.o: crypto.h
modecfg.o: modecfg.h
modecfg.o: whack.h
+modecfg.o: xauth.h
mp_defs.o: constants.h
mp_defs.o: defs.h
mp_defs.o: mp_defs.h
@@ -1088,3 +1091,8 @@ x509.o: whack.h
x509.o: fetch.h
x509.o: ocsp.h
x509.o: sha1.h
+xauth.o: constants.h
+xauth.o: defs.h
+xauth.o: xauth.h
+xauth.o: keys.h
+xauth.o: log.h
diff --git a/programs/pluto/connections.c b/programs/pluto/connections.c
index 1ea6ac5fa..93b3bd2b6 100644
--- a/programs/pluto/connections.c
+++ b/programs/pluto/connections.c
@@ -11,7 +11,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: connections.c,v 1.46 2006/10/19 15:40:52 as Exp $
+ * RCSID $Id: connections.c,v 1.47 2007/01/10 00:36:19 as Exp $
*/
#include <string.h>
@@ -3254,13 +3254,17 @@ find_host_connection(const ip_address *me, u_int16_t my_port
if (policy != LEMPTY)
{
+ lset_t auth_requested = policy & POLICY_ID_AUTH_MASK;
+
/* if we have requirements for the policy,
* choose the first matching connection.
*/
while (c != NULL)
{
- if ((c->policy & policy) == policy)
- break;
+ if (c->policy & auth_requested)
+ {
+ break;
+ }
c = c->hp_next;
}
}
@@ -3367,11 +3371,20 @@ refine_host_connection(const struct state *st, const struct id *peer_id
if (psk == NULL)
return NULL; /* cannot determine PSK! */
break;
-
+ case XAUTHInitPreShared:
+ case XAUTHRespPreShared:
+ auth_policy = POLICY_XAUTH_PSK;
+ psk = get_preshared_secret(c);
+ if (psk == NULL)
+ return NULL; /* cannot determine PSK! */
+ break;
case OAKLEY_RSA_SIG:
auth_policy = POLICY_RSASIG;
break;
-
+ case XAUTHInitRSA:
+ case XAUTHRespRSA:
+ auth_policy = POLICY_XAUTH_RSASIG;
+ break;
default:
bad_case(auth);
}
@@ -3394,17 +3407,21 @@ refine_host_connection(const struct state *st, const struct id *peer_id
bool matching_id = match_id(peer_id
, &d->spd.that.id, &wildcards);
+ bool matching_auth = (d->policy & auth_policy) != LEMPTY;
+
bool matching_trust = trusted_ca(peer_ca
, d->spd.that.ca, &peer_pathlen);
bool matching_request = match_requested_ca(c->requested_ca
, d->spd.this.ca, &our_pathlen);
- bool match = matching_id && matching_trust && matching_request;
-
+ bool match = matching_id && matching_auth &&
+ matching_trust && matching_request;
+
DBG(DBG_CONTROLMORE,
- DBG_log("%s: %s match (id: %s, trust: %s, request: %s)"
+ DBG_log("%s: %s match (id: %s, auth: %s, trust: %s, request: %s)"
, d->name
, match ? "full":" no"
, match_name[matching_id]
+ , match_name[matching_auth]
, match_name[matching_trust]
, match_name[matching_request])
)
@@ -3423,13 +3440,11 @@ refine_host_connection(const struct state *st, const struct id *peer_id
continue;
#endif
- /* authentication used must fit policy of this connection */
- if ((d->policy & auth_policy) == LEMPTY)
- continue; /* our auth isn't OK for this connection */
-
switch (auth)
{
case OAKLEY_PRESHARED_KEY:
+ case XAUTHInitPreShared:
+ case XAUTHRespPreShared:
/* secret must match the one we already used */
{
const chunk_t *dpsk = get_preshared_secret(d);
@@ -3445,6 +3460,8 @@ refine_host_connection(const struct state *st, const struct id *peer_id
break;
case OAKLEY_RSA_SIG:
+ case XAUTHInitRSA:
+ case XAUTHRespRSA:
/*
* We must at least be able to find our private key
.*/
diff --git a/programs/pluto/constants.c b/programs/pluto/constants.c
index 5ca7b65ce..f4aa9d5d1 100644
--- a/programs/pluto/constants.c
+++ b/programs/pluto/constants.c
@@ -11,7 +11,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: constants.c,v 1.22 2006/10/19 21:07:40 as Exp $
+ * RCSID $Id: constants.c,v 1.23 2007/01/10 00:36:19 as Exp $
*/
/*
@@ -54,8 +54,8 @@ const char compile_time_interop_options[] = ""
#ifdef VENDORID
" VENDORID"
#endif
-#ifdef XAUTH_VID
- " XAUTH_VID"
+#ifdef CISCO_QUIRKS
+ " CISCO_QUIRKS"
#endif
#ifdef USE_KEYRR
" KEYRR"
@@ -183,12 +183,22 @@ static const char *const state_name[] = {
"STATE_INFO",
"STATE_INFO_PROTECTED",
+ "STATE_XAUTH_I0",
+ "STATE_XAUTH_R1",
+ "STATE_XAUTH_I1",
+ "STATE_XAUTH_R2",
+ "STATE_XAUTH_I2",
+ "STATE_XAUTH_R3",
+
"STATE_MODE_CFG_R0",
- "STATE_MODE_CFG_R1",
- "STATE_MODE_CFG_R2",
"STATE_MODE_CFG_I1",
+ "STATE_MODE_CFG_R1",
"STATE_MODE_CFG_I2",
+
+ "STATE_MODE_CFG_I0",
+ "STATE_MODE_CFG_R3",
"STATE_MODE_CFG_I3",
+ "STATE_MODE_CFG_R4",
"STATE_IKE_ROOF"
};
@@ -216,13 +226,23 @@ const char *const state_story[] = {
"got Informational Message in clear", /* STATE_INFO */
"got encrypted Informational Message", /* STATE_INFO_PROTECTED */
-
- "sent ModeCfg reply", /* STATE_MODE_CFG_R0 */
- "sent ModeCfg reply", /* STATE_MODE_CFG_R1 */
- "received ModeCfg ack", /* STATE_MODE_CFG_R2 */
+
+ "expecting XAUTH request", /* STATE_XAUTH_I0 */
+ "sent XAUTH request, expecting reply", /* STATE_XAUTH_R1 */
+ "sent XAUTH reply, expecting status", /* STATE_XAUTH_I1 */
+ "sent XAUTH status, expecting ack", /* STATE_XAUTH_R2 */
+ "sent XAUTH ack, established", /* STATE_XAUTH_I2 */
+ "received XAUTH ack, established", /* STATE_XAUTH_R3 */
+
+ "expecting ModeCfg request", /* STATE_MODE_CFG_R0 */
"sent ModeCfg request, expecting reply", /* STATE_MODE_CFG_I1 */
- "received ModeCfg reply", /* STATE_MODE_CFG_I2 */
- "received ModeCfg set, sent ack", /* STATE_MODE_CFG_I3 */
+ "sent ModeCfg reply, established", /* STATE_MODE_CFG_R1 */
+ "received ModeCfg reply, established", /* STATE_MODE_CFG_I2 */
+
+ "expecting ModeCfg set", /* STATE_MODE_CFG_I0 */
+ "sent ModeCfg set, expecting ack", /* STATE_MODE_CFG_R3 */
+ "sent ModeCfg ack, established", /* STATE_MODE_CFG_I3 */
+ "received ModeCfg ack, established", /* STATE_MODE_CFG_R4 */
};
/* kind of struct connection */
@@ -487,6 +507,9 @@ const char *const sa_policy_bit_names[] = {
"GROUTED",
"UP",
"MODECFGPUSH",
+ "XAUTHPSK",
+ "XAUTHRSASIG",
+ "XAUTHSERVER",
NULL
};
@@ -675,7 +698,49 @@ enum_names auth_alg_names =
{ AUTH_ALGORITHM_HMAC_MD5, AUTH_ALGORITHM_HMAC_RIPEMD, auth_alg_name
, &extended_auth_alg_names };
-const char *const modecfg_attr_name[] = {
+/* From draft-beaulieu-ike-xauth */
+static const char *const xauth_type_name[] = {
+ "Generic",
+ "RADIUS-CHAP",
+ "OTP",
+ "S/KEY",
+};
+
+enum_names xauth_type_names =
+ { XAUTH_TYPE_GENERIC, XAUTH_TYPE_SKEY, xauth_type_name, NULL};
+
+/* From draft-beaulieu-ike-xauth */
+static const char *const xauth_attr_tv_name[] = {
+ "XAUTH_TYPE",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "XAUTH_STATUS",
+ };
+
+enum_names xauth_attr_tv_names = {
+ XAUTH_TYPE + ISAKMP_ATTR_AF_TV,
+ XAUTH_STATUS + ISAKMP_ATTR_AF_TV, xauth_attr_tv_name, NULL };
+
+static const char *const xauth_attr_name[] = {
+ "XAUTH_USER_NAME",
+ "XAUTH_USER_PASSWORD",
+ "XAUTH_PASSCODE",
+ "XAUTH_MESSAGE",
+ "XAUTH_CHALLENGE",
+ "XAUTH_DOMAIN",
+ "XAUTH_STATUS (wrong TLV syntax, should be TV)",
+ "XAUTH_NEXT_PIN",
+ "XAUTH_ANSWER",
+ };
+
+enum_names xauth_attr_names =
+ { XAUTH_USER_NAME , XAUTH_ANSWER, xauth_attr_name , &xauth_attr_tv_names };
+
+static const char *const modecfg_attr_name[] = {
"INTERNAL_IP4_ADDRESS",
"INTERNAL_IP4_NETMASK",
"INTERNAL_IP4_DNS",
@@ -695,7 +760,7 @@ const char *const modecfg_attr_name[] = {
};
enum_names modecfg_attr_names =
- { INTERNAL_IP4_ADDRESS , INTERNAL_IP6_SUBNET, modecfg_attr_name , NULL };
+ { INTERNAL_IP4_ADDRESS, INTERNAL_IP6_SUBNET, modecfg_attr_name , &xauth_attr_names };
/* Oakley Lifetime Type attribute */
diff --git a/programs/pluto/constants.h b/programs/pluto/constants.h
index bad162898..f18e93fed 100644
--- a/programs/pluto/constants.h
+++ b/programs/pluto/constants.h
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: constants.h,v 1.22 2006/10/19 21:07:40 as Exp $
+ * RCSID $Id: constants.h,v 1.23 2007/01/10 00:36:19 as Exp $
*/
#ifndef _CONSTANTS_H
@@ -504,13 +504,28 @@ enum state_kind {
STATE_INFO,
STATE_INFO_PROTECTED,
- STATE_MODE_CFG_R0, /* these states are used on the responder */
- STATE_MODE_CFG_R1,
- STATE_MODE_CFG_R2,
+ /* XAUTH states */
+
+ STATE_XAUTH_I0, /* initiator state (client) */
+ STATE_XAUTH_R1, /* responder state (server) */
+ STATE_XAUTH_I1,
+ STATE_XAUTH_R2,
+ STATE_XAUTH_I2,
+ STATE_XAUTH_R3,
+
+ /* Mode Config pull states */
- STATE_MODE_CFG_I1, /* this is used on the initiator */
+ STATE_MODE_CFG_R0, /* responder state (server) */
+ STATE_MODE_CFG_I1, /* initiator state (client) */
+ STATE_MODE_CFG_R1,
STATE_MODE_CFG_I2,
+
+ /* Mode Config push states */
+
+ STATE_MODE_CFG_I0, /* initiator state (client) */
+ STATE_MODE_CFG_R3, /* responder state (server) */
STATE_MODE_CFG_I3,
+ STATE_MODE_CFG_R4,
STATE_IKE_ROOF
};
@@ -519,22 +534,30 @@ enum state_kind {
#define PHASE1_INITIATOR_STATES (LELEM(STATE_MAIN_I1) | LELEM(STATE_MAIN_I2) \
| LELEM(STATE_MAIN_I3) | LELEM(STATE_MAIN_I4))
-#define ISAKMP_SA_ESTABLISHED_STATES (LELEM(STATE_MAIN_R3) | LELEM(STATE_MAIN_I4) \
- | LELEM(STATE_MODE_CFG_R1) | LELEM(STATE_MODE_CFG_R2) \
- | LELEM(STATE_MODE_CFG_I2) | LELEM(STATE_MODE_CFG_I3))
+#define ISAKMP_SA_ESTABLISHED_STATES ( \
+ LELEM(STATE_MAIN_R3) | LELEM(STATE_MAIN_I4) \
+ | LELEM(STATE_XAUTH_R1) | LELEM(STATE_XAUTH_R2) | LELEM(STATE_XAUTH_R3) \
+ | LELEM(STATE_XAUTH_I1) | LELEM(STATE_XAUTH_I2) \
+ | LELEM(STATE_MODE_CFG_I1) | LELEM(STATE_MODE_CFG_R1) | LELEM(STATE_MODE_CFG_I2) \
+ | LELEM(STATE_MODE_CFG_R3) | LELEM(STATE_MODE_CFG_I3) | LELEM(STATE_MODE_CFG_R4))
#define IS_PHASE1(s) ((STATE_MAIN_R0 <= (s) && (s) <= STATE_MAIN_I4) \
- || (STATE_MODE_CFG_R0 <= (s) && (s) <= STATE_MODE_CFG_I3))
+ || (STATE_XAUTH_I0 <= (s) && (s) <= STATE_XAUTH_R3) \
+ || (STATE_MODE_CFG_R0 <= (s) && (s) <= STATE_MODE_CFG_R4))
+
#define IS_QUICK(s) (STATE_QUICK_R0 <= (s) && (s) <= STATE_QUICK_R2)
#define IS_ISAKMP_ENCRYPTED(s) (STATE_MAIN_I2 <= (s))
-#define IS_ISAKMP_SA_ESTABLISHED(s) ( \
- (s) == STATE_MAIN_R3 \
- || (s) == STATE_MAIN_I4 \
- || (s) == STATE_MODE_CFG_R0 \
- || (s) == STATE_MODE_CFG_R1 \
- || (s) == STATE_MODE_CFG_R2 \
- || (s) == STATE_MODE_CFG_I2 \
- || (s) == STATE_MODE_CFG_I3)
+
+#define IS_ISAKMP_SA_ESTABLISHED(s) ( \
+ (s) == STATE_MAIN_R3 \
+ || (s) == STATE_MAIN_I4 \
+ || (s) == STATE_XAUTH_R3 \
+ || (s) == STATE_XAUTH_I2 \
+ || (s) == STATE_MODE_CFG_R1 \
+ || (s) == STATE_MODE_CFG_I2 \
+ || (s) == STATE_MODE_CFG_I3 \
+ || (s) == STATE_MODE_CFG_R4)
+
#define IS_IPSEC_SA_ESTABLISHED(s) ((s) == STATE_QUICK_I2 || (s) == STATE_QUICK_R2)
#define IS_ONLY_INBOUND_IPSEC_SA_ESTABLISHED(s) ((s) == STATE_QUICK_R1)
@@ -638,7 +661,32 @@ extern enum_names attr_msg_type_names;
#define SUPPORTED_ATTRIBUTES 14
#define INTERNAL_IP6_SUBNET 15
+#define MODECFG_ROOF 16
+
extern enum_names modecfg_attr_names;
+/* XAUTH attribute values */
+#define XAUTH_TYPE 16520
+#define XAUTH_USER_NAME 16521
+#define XAUTH_USER_PASSWORD 16522
+#define XAUTH_PASSCODE 16523
+#define XAUTH_MESSAGE 16524
+#define XAUTH_CHALLENGE 16525
+#define XAUTH_DOMAIN 16526
+#define XAUTH_STATUS 16527
+#define XAUTH_NEXT_PIN 16528
+#define XAUTH_ANSWER 16529
+
+#define XAUTH_BASE XAUTH_TYPE
+
+extern enum_names xauth_attr_names;
+
+/* XAUTH authentication types */
+#define XAUTH_TYPE_GENERIC 0
+#define XAUTH_TYPE_CHAP 1
+#define XAUTH_TYPE_OTP 2
+#define XAUTH_TYPE_SKEY 3
+
+extern enum_names xauth_type_names;
/* Exchange types
* RFC2408 "Internet Security Association and Key Management Protocol (ISAKMP)"
@@ -752,7 +800,7 @@ extern const char *prettypolicy(lset_t policy);
#define POLICY_RSASIG LELEM(1)
#define POLICY_ISAKMP_SHIFT 0 /* log2(POLICY_PSK) */
-#define POLICY_ID_AUTH_MASK LRANGES(POLICY_PSK, POLICY_RSASIG)
+#define POLICY_ID_AUTH_MASK (POLICY_PSK | POLICY_RSASIG | POLICY_XAUTH_PSK | POLICY_XAUTH_RSASIG)
#define POLICY_ISAKMP_MASK POLICY_ID_AUTH_MASK /* all so far */
/* Quick Mode (IPSEC) attributes */
@@ -794,7 +842,9 @@ extern const char *prettypolicy(lset_t policy);
#define POLICY_GROUTED LELEM(15) /* do we want this group routed? */
#define POLICY_UP LELEM(16) /* do we want this up? */
#define POLICY_MODECFG_PUSH LELEM(17) /* is modecfg pushed by server? */
-
+#define POLICY_XAUTH_PSK LELEM(18) /* do we support XAUTH????PreShared? */
+#define POLICY_XAUTH_RSASIG LELEM(19) /* do we support XAUTH????RSA? */
+#define POLICY_XAUTH_SERVER LELEM(20) /* are we an XAUTH server? */
/* Any IPsec policy? If not, a connection description
* is only for ISAKMP SA, not IPSEC SA. (A pun, I admit.)
@@ -804,7 +854,7 @@ extern const char *prettypolicy(lset_t policy);
#define HAS_IPSEC_POLICY(p) (((p) & POLICY_IPSEC_MASK) != 0)
/* Don't allow negotiation? */
-#define NEVER_NEGOTIATE(p) (LDISJOINT((p), POLICY_PSK | POLICY_RSASIG))
+#define NEVER_NEGOTIATE(p) (LDISJOINT((p), POLICY_ID_AUTH_MASK))
/* Oakley transform attributes
diff --git a/programs/pluto/defs.h b/programs/pluto/defs.h
index 7e92ea540..3fe5053d1 100644
--- a/programs/pluto/defs.h
+++ b/programs/pluto/defs.h
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: defs.h,v 1.10 2006/01/04 21:00:43 as Exp $
+ * RCSID $Id: defs.h,v 1.11 2007/01/09 21:59:06 as Exp $
*/
#ifndef _DEFS_H
@@ -82,7 +82,7 @@ typedef struct chunk chunk_t;
#define chunkcpy(dst, chunk) \
{ memcpy(dst, chunk.ptr, chunk.len); dst += chunk.len;}
#define same_chunk(a, b) \
- (a).len == (b).len && memcmp((a).ptr, (b).ptr, (b).len) == 0
+ ( (a).len == (b).len && memcmp((a).ptr, (b).ptr, (b).len) == 0 )
extern char* temporary_cyclic_buffer(void);
extern const char* concatenate_paths(const char *a, const char *b);
diff --git a/programs/pluto/demux.c b/programs/pluto/demux.c
index 3146b3d40..304d790e3 100644
--- a/programs/pluto/demux.c
+++ b/programs/pluto/demux.c
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: demux.c,v 1.16 2006/10/19 21:07:40 as Exp $
+ * RCSID $Id: demux.c,v 1.17 2007/01/10 00:36:19 as Exp $
*/
/* Ordering Constraints on Payloads
@@ -454,45 +454,81 @@ static const struct state_microcode state_microcode_table[] = {
, P(HASH), LEMPTY, PT(NONE)
, EVENT_NULL, informational },
- /* MODE_CFG_x:
- * Case R0: Responder -> Initiator
- * <- Req(addr=0)
- * Reply(ad=x) ->
- *
- * Case R1: Set(addr=x) ->
- * <- Ack(ok)
- */
+ /* XAUTH state transitions */
+ { STATE_XAUTH_I0, STATE_XAUTH_I1
+ , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY
+ , P(ATTR) | P(HASH), P(VID), PT(HASH)
+ , EVENT_RETRANSMIT, xauth_inI0 },
- { STATE_MODE_CFG_R0, STATE_MODE_CFG_R1
+ { STATE_XAUTH_R1, STATE_XAUTH_R2
, SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY
, P(ATTR) | P(HASH), P(VID), PT(HASH)
- , EVENT_SA_REPLACE, modecfg_inR0 },
+ , EVENT_RETRANSMIT, xauth_inR1 },
- { STATE_MODE_CFG_R1, STATE_MODE_CFG_R2
- , SMF_ALL_AUTH | SMF_ENCRYPTED
+ { STATE_XAUTH_I1, STATE_XAUTH_I2
+ , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY | SMF_RELEASE_PENDING_P2
, P(ATTR) | P(HASH), P(VID), PT(HASH)
- , EVENT_SA_REPLACE, modecfg_inR1 },
+ , EVENT_SA_REPLACE, xauth_inI1 },
+
+ { STATE_XAUTH_R2, STATE_XAUTH_R3
+ , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2
+ , P(ATTR) | P(HASH), P(VID), PT(NONE)
+ , EVENT_SA_REPLACE, xauth_inR2 },
+
+ { STATE_XAUTH_I2, STATE_UNDEFINED
+ , SMF_ALL_AUTH | SMF_ENCRYPTED
+ , LEMPTY, LEMPTY, PT(NONE)
+ , EVENT_NULL, unexpected },
- { STATE_MODE_CFG_R2, STATE_UNDEFINED
+ { STATE_XAUTH_R3, STATE_UNDEFINED
, SMF_ALL_AUTH | SMF_ENCRYPTED
, LEMPTY, LEMPTY, PT(NONE)
, EVENT_NULL, unexpected },
+ /* ModeCfg pull mode state transitions */
+
+ { STATE_MODE_CFG_R0, STATE_MODE_CFG_R1
+ , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY | SMF_RELEASE_PENDING_P2
+ , P(ATTR) | P(HASH), P(VID), PT(HASH)
+ , EVENT_SA_REPLACE, modecfg_inR0 },
+
{ STATE_MODE_CFG_I1, STATE_MODE_CFG_I2
, SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2
, P(ATTR) | P(HASH), P(VID), PT(HASH)
, EVENT_SA_REPLACE, modecfg_inI1 },
- { STATE_MODE_CFG_I2, STATE_MODE_CFG_I3
+ { STATE_MODE_CFG_R1, STATE_UNDEFINED
+ , SMF_ALL_AUTH | SMF_ENCRYPTED
+ , LEMPTY, LEMPTY, PT(NONE)
+ , EVENT_NULL, unexpected },
+
+ { STATE_MODE_CFG_I2, STATE_UNDEFINED
+ , SMF_ALL_AUTH | SMF_ENCRYPTED
+ , LEMPTY, LEMPTY, PT(NONE)
+ , EVENT_NULL, unexpected },
+
+ /* ModeCfg push mode state transitions */
+
+ { STATE_MODE_CFG_I0, STATE_MODE_CFG_I3
, SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY | SMF_RELEASE_PENDING_P2
, P(ATTR) | P(HASH), P(VID), PT(HASH)
- , EVENT_SA_REPLACE, modecfg_inI2 },
+ , EVENT_SA_REPLACE, modecfg_inI0 },
+
+ { STATE_MODE_CFG_R3, STATE_MODE_CFG_R4
+ , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2
+ , P(ATTR) | P(HASH), P(VID), PT(HASH)
+ , EVENT_SA_REPLACE, modecfg_inR3 },
{ STATE_MODE_CFG_I3, STATE_UNDEFINED
, SMF_ALL_AUTH | SMF_ENCRYPTED
, LEMPTY, LEMPTY, PT(NONE)
, EVENT_NULL, unexpected },
+ { STATE_MODE_CFG_R4, STATE_UNDEFINED
+ , SMF_ALL_AUTH | SMF_ENCRYPTED
+ , LEMPTY, LEMPTY, PT(NONE)
+ , EVENT_NULL, unexpected },
+
#undef P
#undef PT
};
@@ -1258,6 +1294,11 @@ process_packet(struct msg_digest **mdp)
{
plog("size (%u) differs from size specified in ISAKMP HDR (%u)"
, (unsigned) pbs_room(&md->packet_pbs), md->hdr.isa_length);
+#ifdef CISCO_QUIRKS
+ if (pbs_room(&md->packet_pbs) - md->hdr.isa_length == 16)
+ plog("Cisco VPN client appends 16 surplus NULL bytes");
+ else
+#endif
return;
}
@@ -1447,11 +1488,6 @@ process_packet(struct msg_digest **mdp)
return;
}
- if (st->st_state == STATE_MODE_CFG_R2) /* Have we just give an IP address to peer? */
- {
- st->st_state = STATE_MAIN_R3; /* ISAKMP is up... */
- }
-
set_cur_state(st);
if (!IS_ISAKMP_SA_ESTABLISHED(st->st_state))
@@ -1490,7 +1526,7 @@ process_packet(struct msg_digest **mdp)
case ISAKMP_XCHG_MODE_CFG:
if (is_zero_cookie(md->hdr.isa_icookie))
{
- plog("Mode Config message is invalid because"
+ plog("ModeCfg message is invalid because"
" it has an Initiator Cookie of 0");
/* XXX Could send notification back */
return;
@@ -1498,7 +1534,7 @@ process_packet(struct msg_digest **mdp)
if (is_zero_cookie(md->hdr.isa_rcookie))
{
- plog("Mode Config message is invalid because"
+ plog("ModeCfg message is invalid because"
" it has a Responder Cookie of 0");
/* XXX Could send notification back */
return;
@@ -1506,7 +1542,7 @@ process_packet(struct msg_digest **mdp)
if (md->hdr.isa_msgid == 0)
{
- plog("Mode Config message is invalid because"
+ plog("ModeCfg message is invalid because"
" it has a Message ID of 0");
/* XXX Could send notification back */
return;
@@ -1517,7 +1553,9 @@ process_packet(struct msg_digest **mdp)
if (st == NULL)
{
- /* No appropriate Mode Config state.
+ bool has_xauth_policy;
+
+ /* No appropriate ModeCfg state.
* See if we have a Main Mode state.
* ??? what if this is a duplicate of another message?
*/
@@ -1526,7 +1564,7 @@ process_packet(struct msg_digest **mdp)
if (st == NULL)
{
- plog("Mode Config message is for a non-existent (expired?)"
+ plog("ModeCfg message is for a non-existent (expired?)"
" ISAKMP SA");
/* XXX Could send notification back */
return;
@@ -1536,7 +1574,7 @@ process_packet(struct msg_digest **mdp)
if (!IS_ISAKMP_SA_ESTABLISHED(st->st_state))
{
- loglog(RC_LOG_SERIOUS, "Mode Config message is unacceptable because"
+ loglog(RC_LOG_SERIOUS, "ModeCfg message is unacceptable because"
" it is for an incomplete ISAKMP SA (state=%s)"
, enum_name(&state_names, st->st_state));
/* XXX Could send notification back */
@@ -1565,7 +1603,16 @@ process_packet(struct msg_digest **mdp)
*
*/
- if (st->st_connection->spd.that.modecfg
+ has_xauth_policy = (st->st_connection->policy
+ & (POLICY_XAUTH_RSASIG | POLICY_XAUTH_PSK))
+ != LEMPTY;
+
+ if (has_xauth_policy && !st->st_xauth.started
+ && IS_PHASE1(st->st_state))
+ {
+ from_state = STATE_XAUTH_I0;
+ }
+ else if (st->st_connection->spd.that.modecfg
&& IS_PHASE1(st->st_state))
{
from_state = STATE_MODE_CFG_R0;
@@ -1573,12 +1620,12 @@ process_packet(struct msg_digest **mdp)
else if (st->st_connection->spd.this.modecfg
&& IS_PHASE1(st->st_state))
{
- from_state = STATE_MODE_CFG_I2;
+ from_state = STATE_MODE_CFG_I0;
}
else
{
/* XXX check if we are being a mode config server here */
- plog("received MODECFG message when in state %s, and we aren't mode config client"
+ plog("received ModeCfg message when in state %s, and we aren't mode config client"
, enum_name(&state_names, st->st_state));
return;
}
@@ -1588,7 +1635,6 @@ process_packet(struct msg_digest **mdp)
set_cur_state(st);
from_state = st->st_state;
}
-
break;
#ifdef NOTYET
@@ -1630,7 +1676,23 @@ process_packet(struct msg_digest **mdp)
if (st != NULL)
{
- while (!LHAS(smc->flags, st->st_oakley.auth))
+ u_int16_t auth;
+
+ switch (st->st_oakley.auth)
+ {
+ case XAUTHInitPreShared:
+ case XAUTHRespPreShared:
+ auth = OAKLEY_PRESHARED_KEY;
+ break;
+ case XAUTHInitRSA:
+ case XAUTHRespRSA:
+ auth = OAKLEY_RSA_SIG;
+ break;
+ default:
+ auth = st->st_oakley.auth;
+ }
+
+ while (!LHAS(smc->flags, auth))
{
smc++;
passert(smc->state == from_state);
@@ -2046,6 +2108,8 @@ process_packet(struct msg_digest **mdp)
void
complete_state_transition(struct msg_digest **mdp, stf_status result)
{
+ bool has_xauth_policy;
+ bool is_xauth_server;
struct msg_digest *md = *mdp;
const struct state_microcode *smc = md->smc;
enum state_kind from_state = md->from_state;
@@ -2263,7 +2327,7 @@ complete_state_transition(struct msg_digest **mdp, stf_status result)
}
/* advance b to end of string */
b = b + strlen(b);
-
+
if (st->st_ah.present)
{
snprintf(b, sizeof(sadetails)-(b-sadetails)-1
@@ -2276,7 +2340,7 @@ complete_state_transition(struct msg_digest **mdp, stf_status result)
}
/* advance b to end of string */
b = b + strlen(b);
-
+
if (st->st_ipcomp.present)
{
snprintf(b, sizeof(sadetails)-(b-sadetails)-1
@@ -2319,7 +2383,7 @@ complete_state_transition(struct msg_digest **mdp, stf_status result)
}
if (IS_ISAKMP_SA_ESTABLISHED(st->st_state)
- || IS_IPSEC_SA_ESTABLISHED(st->st_state))
+ || IS_IPSEC_SA_ESTABLISHED(st->st_state))
{
/* log our success */
plog("%s%s", story, sadetails);
@@ -2333,6 +2397,36 @@ complete_state_transition(struct msg_digest **mdp, stf_status result)
, story, sadetails);
}
+ has_xauth_policy = (st->st_connection->policy
+ & (POLICY_XAUTH_RSASIG | POLICY_XAUTH_PSK))
+ != LEMPTY;
+ is_xauth_server = (st->st_connection->policy
+ & POLICY_XAUTH_SERVER)
+ != LEMPTY;
+
+ /* Should we start XAUTH as a server */
+ if (has_xauth_policy && is_xauth_server
+ && IS_ISAKMP_SA_ESTABLISHED(st->st_state)
+ && !st->st_xauth.started)
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("starting XAUTH server")
+ )
+ xauth_send_request(st);
+ break;
+ }
+
+ /* Wait for XAUTH request from server */
+ if (has_xauth_policy && !is_xauth_server
+ && IS_ISAKMP_SA_ESTABLISHED(st->st_state)
+ && !st->st_xauth.started)
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("waiting for XAUTH request from server")
+ )
+ break;
+ }
+
/* Should we start ModeConfig as a client? */
if (st->st_connection->spd.this.modecfg
&& IS_ISAKMP_SA_ESTABLISHED(st->st_state)
@@ -2384,7 +2478,7 @@ complete_state_transition(struct msg_digest **mdp, stf_status result)
}
if (IS_ISAKMP_SA_ESTABLISHED(st->st_state)
- || IS_IPSEC_SA_ESTABLISHED(st->st_state))
+ || IS_IPSEC_SA_ESTABLISHED(st->st_state))
release_whack(st);
break;
diff --git a/programs/pluto/demux.h b/programs/pluto/demux.h
index 7adac44f3..dc38e4cfc 100644
--- a/programs/pluto/demux.h
+++ b/programs/pluto/demux.h
@@ -11,7 +11,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: demux.h,v 1.4 2004/07/22 22:57:25 as Exp $
+ * RCSID $Id: demux.h,v 1.5 2007/01/11 05:44:02 as Exp $
*/
#include "packet.h"
@@ -69,7 +69,7 @@ struct msg_digest {
bool dpd; /* peer supports RFC 3706 DPD */
bool openpgp; /* peer supports OpenPGP certificates */
-# define PAYLIMIT 20
+# define PAYLIMIT 40
struct payload_digest
digest[PAYLIMIT],
*digest_roof,
diff --git a/programs/pluto/ike_alg.c b/programs/pluto/ike_alg.c
index 47393079a..456ca3a96 100644
--- a/programs/pluto/ike_alg.c
+++ b/programs/pluto/ike_alg.c
@@ -11,7 +11,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: ike_alg.c,v 1.6 2004/09/17 21:29:50 as Exp $
+ * RCSID $Id: ike_alg.c,v 1.7 2007/01/10 00:36:19 as Exp $
*/
#include <stdio.h>
@@ -233,6 +233,7 @@ ike_alg_db_new(struct alg_info_ike *ai , lset_t policy)
struct ike_info *ike_info;
u_int ealg, halg, modp, eklen = 0;
struct encrypt_desc *enc_desc;
+ bool is_xauth_server;
int i;
if (!ai)
@@ -298,11 +299,37 @@ ike_alg_db_new(struct alg_info_ike *ai , lset_t policy)
db_trans_add(db_ctx, KEY_IKE);
db_attr_add_values(db_ctx, OAKLEY_ENCRYPTION_ALGORITHM, ealg);
db_attr_add_values(db_ctx, OAKLEY_HASH_ALGORITHM, halg);
- if (ike_info->ike_eklen)
- db_attr_add_values(db_ctx, OAKLEY_KEY_LENGTH, ike_info->ike_eklen);
+ if (eklen)
+ db_attr_add_values(db_ctx, OAKLEY_KEY_LENGTH, eklen);
db_attr_add_values(db_ctx, OAKLEY_AUTHENTICATION_METHOD, OAKLEY_PRESHARED_KEY);
db_attr_add_values(db_ctx, OAKLEY_GROUP_DESCRIPTION, modp);
}
+
+ is_xauth_server = (policy & POLICY_XAUTH_SERVER) != LEMPTY;
+
+ if (policy & POLICY_XAUTH_RSASIG)
+ {
+ db_trans_add(db_ctx, KEY_IKE);
+ db_attr_add_values(db_ctx, OAKLEY_ENCRYPTION_ALGORITHM, ealg);
+ db_attr_add_values(db_ctx, OAKLEY_HASH_ALGORITHM, halg);
+ if (eklen)
+ db_attr_add_values(db_ctx, OAKLEY_KEY_LENGTH, eklen);
+ db_attr_add_values(db_ctx, OAKLEY_AUTHENTICATION_METHOD
+ , is_xauth_server ? XAUTHRespRSA : XAUTHInitRSA);
+ db_attr_add_values(db_ctx, OAKLEY_GROUP_DESCRIPTION, modp);
+ }
+
+ if (policy & POLICY_XAUTH_PSK)
+ {
+ db_trans_add(db_ctx, KEY_IKE);
+ db_attr_add_values(db_ctx, OAKLEY_ENCRYPTION_ALGORITHM, ealg);
+ db_attr_add_values(db_ctx, OAKLEY_HASH_ALGORITHM, halg);
+ if (eklen)
+ db_attr_add_values(db_ctx, OAKLEY_KEY_LENGTH, eklen);
+ db_attr_add_values(db_ctx, OAKLEY_AUTHENTICATION_METHOD
+ , is_xauth_server ? XAUTHRespPreShared : XAUTHInitPreShared);
+ db_attr_add_values(db_ctx, OAKLEY_GROUP_DESCRIPTION, modp);
+ }
}
fail:
return db_ctx;
diff --git a/programs/pluto/ipsec_doi.c b/programs/pluto/ipsec_doi.c
index fe5c846a7..e627f98b2 100644
--- a/programs/pluto/ipsec_doi.c
+++ b/programs/pluto/ipsec_doi.c
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: ipsec_doi.c,v 1.39 2006/04/22 21:59:20 as Exp $
+ * RCSID $Id: ipsec_doi.c,v 1.42 2007/01/10 00:36:19 as Exp $
*/
#include <stdio.h>
@@ -84,13 +84,13 @@
#endif /* !VENDORID */
/*
- * are we sending an XAUTH VID (Cisco Mode Config Interoperability)?
+ * are we sending a Cisco Unity VID?
*/
-#ifdef XAUTH_VID
-#define SEND_XAUTH_VID 1
-#else /* !XAUTH_VID */
-#define SEND_XAUTH_VID 0
-#endif /* !XAUTH_VID */
+#ifdef CISCO_QUIRKS
+#define SEND_CISCO_UNITY_VID 1
+#else /* !CISCO_QUIRKS */
+#define SEND_CISCO_UNITY_VID 0
+#endif /* !CISCO_QUIRKS */
/* MAGIC: perform f, a function that returns notification_t
* and return from the ENCLOSING stf_status returning function if it fails.
@@ -896,10 +896,12 @@ main_outI1(int whack_sock, struct connection *c, struct state *predecessor
/* determine how many Vendor ID payloads we will be sending */
if (SEND_PLUTO_VID)
vids_to_send++;
- if (SEND_XAUTH_VID)
+ if (SEND_CISCO_UNITY_VID)
vids_to_send++;
if (c->spd.this.cert.type == CERT_PGP)
vids_to_send++;
+ /* always send XAUTH Vendor ID */
+ vids_to_send++;
/* always send DPD Vendor ID */
vids_to_send++;
#ifdef NAT_TRAVERSAL
@@ -946,8 +948,8 @@ main_outI1(int whack_sock, struct connection *c, struct state *predecessor
u_char *sa_start = rbody.cur;
lset_t auth_policy = policy & POLICY_ID_AUTH_MASK;
- if (!out_sa(&rbody, &oakley_sadb[auth_policy >> POLICY_ISAKMP_SHIFT]
- , st, TRUE, vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE))
+ if (!out_sa(&rbody, &oakley_sadb, st, TRUE
+ , vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE))
{
reset_cur_state();
return STF_INTERNAL_ERROR;
@@ -970,17 +972,16 @@ main_outI1(int whack_sock, struct connection *c, struct state *predecessor
}
}
- /* if enabled send XAUTH Vendor ID */
- if (SEND_XAUTH_VID)
+ /* if enabled send Cisco Unity Vendor ID */
+ if (SEND_CISCO_UNITY_VID)
{
if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
- , &rbody, VID_MISC_XAUTH))
+ , &rbody, VID_CISCO_UNITY))
{
reset_cur_state();
return STF_INTERNAL_ERROR;
}
}
-
/* if we have an OpenPGP certificate we assume an
* OpenPGP peer and have to send the Vendor ID
*/
@@ -994,6 +995,14 @@ main_outI1(int whack_sock, struct connection *c, struct state *predecessor
}
}
+ /* Announce our ability to do eXtended AUTHentication to the peer */
+ if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
+ , &rbody, VID_MISC_XAUTH))
+ {
+ reset_cur_state();
+ return STF_INTERNAL_ERROR;
+ }
+
/* Announce our ability to do Dead Peer Detection to the peer */
{
if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
@@ -1199,11 +1208,15 @@ generate_skeyids_iv(struct state *st)
switch (st->st_oakley.auth)
{
case OAKLEY_PRESHARED_KEY:
+ case XAUTHInitPreShared:
+ case XAUTHRespPreShared:
if (!skeyid_preshared(st))
return FALSE;
break;
case OAKLEY_RSA_SIG:
+ case XAUTHInitRSA:
+ case XAUTHRespRSA:
if (!skeyid_digisig(st))
return FALSE;
break;
@@ -2972,8 +2985,7 @@ main_inI1_outR1(struct msg_digest *md)
{
struct payload_digest *const sa_pd = md->chain[ISAKMP_NEXT_SA];
struct state *st;
- struct connection *c = find_host_connection(&md->iface->addr, pluto_port
- , &md->sender, md->sender_port, LEMPTY);
+ struct connection *c;
struct isakmp_proposal proposal;
pb_stream proposal_pbs;
pb_stream r_sa_pbs;
@@ -2981,14 +2993,28 @@ main_inI1_outR1(struct msg_digest *md)
lset_t policy = LEMPTY;
int vids_to_send = 0;
+ /* We preparse the peer's proposal in order to determine
+ * the requested authentication policy (RSA or PSK)
+ */
RETURN_STF_FAILURE(preparse_isakmp_sa_body(&sa_pd->payload.sa
, &sa_pd->pbs, &ipsecdoisit, &proposal_pbs, &proposal));
+ backup_pbs(&proposal_pbs);
+ RETURN_STF_FAILURE(parse_isakmp_policy(&proposal_pbs
+ , proposal.isap_notrans, &policy));
+ restore_pbs(&proposal_pbs);
+
+ /* We are only considering candidate connections that match
+ * the requested authentication policy (RSA or PSK)
+ */
+ c = find_host_connection(&md->iface->addr, pluto_port
+ , &md->sender, md->sender_port, policy);
+
#ifdef NAT_TRAVERSAL
if (c == NULL && md->iface->ike_float)
{
c = find_host_connection(&md->iface->addr, NAT_T_IKE_FLOAT_PORT
- , &md->sender, md->sender_port, LEMPTY);
+ , &md->sender, md->sender_port, policy);
}
#endif
@@ -3007,11 +3033,6 @@ main_inI1_outR1(struct msg_digest *md)
{
struct connection *d;
- backup_pbs(&proposal_pbs);
- RETURN_STF_FAILURE(parse_isakmp_policy(&proposal_pbs
- , proposal.isap_notrans, &policy));
- restore_pbs(&proposal_pbs);
-
d = find_host_connection(&md->iface->addr
, pluto_port, (ip_address*)NULL, md->sender_port, policy);
@@ -3071,6 +3092,13 @@ main_inI1_outR1(struct msg_digest *md)
NULL);
}
}
+ else if (c->kind == CK_TEMPLATE)
+ {
+ /* Create an instance
+ * This is a rare case: wildcard peer ID but static peer IP address
+ */
+ c = rw_instantiate(c, &md->sender, md->sender_port, NULL, &c->spd.that.id);
+ }
/* Set up state */
md->st = st = new_state();
@@ -3109,10 +3137,12 @@ main_inI1_outR1(struct msg_digest *md)
/* determine how many Vendor ID payloads we will be sending */
if (SEND_PLUTO_VID)
vids_to_send++;
- if (SEND_XAUTH_VID)
+ if (SEND_CISCO_UNITY_VID)
vids_to_send++;
if (md->openpgp)
vids_to_send++;
+ /* always send XAUTH Vendor ID */
+ vids_to_send++;
/* always send DPD Vendor ID */
vids_to_send++;
#ifdef NAT_TRAVERSAL
@@ -3146,7 +3176,7 @@ main_inI1_outR1(struct msg_digest *md)
/* SA body in and out */
RETURN_STF_FAILURE(parse_isakmp_sa_body(ipsecdoisit, &proposal_pbs
- ,&proposal, &r_sa_pbs, st));
+ ,&proposal, &r_sa_pbs, st, FALSE));
/* if enabled send Pluto Vendor ID */
if (SEND_PLUTO_VID)
@@ -3158,11 +3188,11 @@ main_inI1_outR1(struct msg_digest *md)
}
}
- /* if enabled send XAUTH Vendor ID */
- if (SEND_XAUTH_VID)
+ /* if enabled send Cisco Unity Vendor ID */
+ if (SEND_CISCO_UNITY_VID)
{
if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
- , &md->rbody, VID_MISC_XAUTH))
+ , &md->rbody, VID_CISCO_UNITY))
{
return STF_INTERNAL_ERROR;
}
@@ -3180,13 +3210,18 @@ main_inI1_outR1(struct msg_digest *md)
}
}
+ /* Announce our ability to do eXtended AUTHentication to the peer */
+ if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
+ , &md->rbody, VID_MISC_XAUTH))
+ {
+ return STF_INTERNAL_ERROR;
+ }
+
/* Announce our ability to do Dead Peer Detection to the peer */
+ if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
+ , &md->rbody, VID_MISC_DPD))
{
- if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
- , &md->rbody, VID_MISC_DPD))
- {
- return STF_INTERNAL_ERROR;
- }
+ return STF_INTERNAL_ERROR;
}
#ifdef NAT_TRAVERSAL
@@ -3249,7 +3284,7 @@ main_inR1_outI2(struct msg_digest *md)
RETURN_STF_FAILURE(BAD_PROPOSAL_SYNTAX);
}
RETURN_STF_FAILURE(parse_isakmp_sa_body(ipsecdoisit
- , &proposal_pbs, &proposal, NULL, st));
+ , &proposal_pbs, &proposal, NULL, st, TRUE));
}
#ifdef NAT_TRAVERSAL
@@ -3342,9 +3377,11 @@ main_inI2_outR2(struct msg_digest *md)
pb_stream *keyex_pbs = &md->chain[ISAKMP_NEXT_KE]->pbs;
/* send CR if auth is RSA and no preloaded RSA public key exists*/
- bool send_cr = !no_cr_send && (st->st_oakley.auth == OAKLEY_RSA_SIG) &&
- !has_preloaded_public_key(st);
-
+ bool RSA_auth = st->st_oakley.auth == OAKLEY_RSA_SIG
+ || st->st_oakley.auth == XAUTHInitRSA
+ || st->st_oakley.auth == XAUTHRespRSA;
+ bool send_cr = !no_cr_send && RSA_auth && !has_preloaded_public_key(st);
+
u_int8_t np = ISAKMP_NEXT_NONE;
/* KE in */
@@ -3487,14 +3524,18 @@ main_inR2_outI3(struct msg_digest *md)
{
struct state *const st = md->st;
pb_stream *const keyex_pbs = &md->chain[ISAKMP_NEXT_KE]->pbs;
- int auth_payload = st->st_oakley.auth == OAKLEY_PRESHARED_KEY
- ? ISAKMP_NEXT_HASH : ISAKMP_NEXT_SIG;
pb_stream id_pbs; /* ID Payload; also used for hash calculation */
certpolicy_t cert_policy = st->st_connection->spd.this.sendcert;
cert_t mycert = st->st_connection->spd.this.cert;
bool requested, send_cert, send_cr;
+ bool RSA_auth = st->st_oakley.auth == OAKLEY_RSA_SIG
+ || st->st_oakley.auth == XAUTHInitRSA
+ || st->st_oakley.auth == XAUTHRespRSA;
+
+ int auth_payload = RSA_auth ? ISAKMP_NEXT_SIG : ISAKMP_NEXT_HASH;
+
/* KE in */
RETURN_STF_FAILURE(accept_KE(&st->st_gr, "Gr", st->st_oakley.group, keyex_pbs));
@@ -3516,8 +3557,7 @@ main_inR2_outI3(struct msg_digest *md)
*/
requested = cert_policy == CERT_SEND_IF_ASKED
&& st->st_connection->got_certrequest;
- send_cert = st->st_oakley.auth == OAKLEY_RSA_SIG
- && mycert.type != CERT_NONE
+ send_cert = RSA_auth && mycert.type != CERT_NONE
&& (cert_policy == CERT_ALWAYS_SEND || requested);
/* send certificate request if we don't have a preloaded RSA public key */
@@ -3560,7 +3600,7 @@ main_inR2_outI3(struct msg_digest *md)
}
/* CERT out */
- if ( st->st_oakley.auth == OAKLEY_RSA_SIG)
+ if (RSA_auth)
{
DBG(DBG_CONTROL,
DBG_log("our certificate policy is %s"
@@ -3716,6 +3756,8 @@ main_id_and_auth(struct msg_digest *md
switch (st->st_oakley.auth)
{
case OAKLEY_PRESHARED_KEY:
+ case XAUTHInitPreShared:
+ case XAUTHRespPreShared:
{
pb_stream *const hash_pbs = &md->chain[ISAKMP_NEXT_HASH]->pbs;
@@ -3732,6 +3774,8 @@ main_id_and_auth(struct msg_digest *md
break;
case OAKLEY_RSA_SIG:
+ case XAUTHInitRSA:
+ case XAUTHRespRSA:
r = RSA_check_signature(&peer, st, hash_val, hash_len
, &md->chain[ISAKMP_NEXT_SIG]->pbs
#ifdef USE_KEYRR
@@ -3909,6 +3953,7 @@ main_inI3_outR3_tail(struct msg_digest *md
pb_stream r_id_pbs; /* ID Payload; also used for hash calculation */
certpolicy_t cert_policy;
cert_t mycert;
+ bool RSA_auth;
bool send_cert;
bool requested;
@@ -3931,7 +3976,10 @@ main_inI3_outR3_tail(struct msg_digest *md
mycert = st->st_connection->spd.this.cert;
requested = cert_policy == CERT_SEND_IF_ASKED
&& st->st_connection->got_certrequest;
- send_cert = st->st_oakley.auth == OAKLEY_RSA_SIG
+ RSA_auth = st->st_oakley.auth == OAKLEY_RSA_SIG
+ || st->st_oakley.auth == XAUTHInitRSA
+ || st->st_oakley.auth == XAUTHRespRSA;
+ send_cert = RSA_auth
&& mycert.type != CERT_NONE
&& (cert_policy == CERT_ALWAYS_SEND || requested);
@@ -3949,8 +3997,7 @@ main_inI3_outR3_tail(struct msg_digest *md
*/
echo_hdr(md, TRUE, ISAKMP_NEXT_ID);
- auth_payload = st->st_oakley.auth == OAKLEY_PRESHARED_KEY
- ? ISAKMP_NEXT_HASH : ISAKMP_NEXT_SIG;
+ auth_payload = RSA_auth ? ISAKMP_NEXT_SIG : ISAKMP_NEXT_HASH;
/* IDir out */
{
@@ -3969,7 +4016,7 @@ main_inI3_outR3_tail(struct msg_digest *md
}
/* CERT out */
- if (st->st_oakley.auth == OAKLEY_RSA_SIG)
+ if (RSA_auth)
{
DBG(DBG_CONTROL,
DBG_log("our certificate policy is %s"
diff --git a/programs/pluto/keys.c b/programs/pluto/keys.c
index 55d13282c..39726f424 100644
--- a/programs/pluto/keys.c
+++ b/programs/pluto/keys.c
@@ -11,7 +11,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: keys.c,v 1.25 2006/07/06 19:23:28 as Exp $
+ * RCSID $Id: keys.c,v 1.26 2007/01/10 00:36:19 as Exp $
*/
#include <stddef.h>
@@ -54,6 +54,7 @@
#include "whack.h" /* for RC_LOG_SERIOUS */
#include "timer.h"
#include "fetch.h"
+#include "xauth.h"
const char *shared_secrets_file = SHARED_SECRETS_FILE;
@@ -72,6 +73,7 @@ struct secret {
union {
chunk_t preshared_secret;
RSA_private_key_t RSA_private_key;
+ xauth_t xauth_secret;
smartcard_t *smartcard;
} u;
secret_t *next;
@@ -96,11 +98,11 @@ allocate_RSA_public_key(const cert_t cert)
default:
plog("RSA public key allocation error");
}
- init_RSA_public_key(&pk->u.rsa, e, n);
-#ifdef DEBUG
- DBG(DBG_PRIVATE, RSA_show_public_key(&pk->u.rsa));
-#endif
+ init_RSA_public_key(&pk->u.rsa, e, n);
+ DBG(DBG_RAW,
+ RSA_show_public_key(&pk->u.rsa)
+ )
pk->alg = PUBKEY_ALG_RSA;
pk->id = empty_id;
@@ -182,14 +184,14 @@ get_secret(const struct connection *c, enum PrivateKeyKind kind, bool asym)
}
#ifdef NAT_TRAVERSAL
else if (kind == PPK_PSK
- && (c->policy & POLICY_PSK)
+ && (c->policy & (POLICY_PSK | POLICY_XAUTH_PSK))
&& ((c->kind == CK_TEMPLATE && c->spd.that.id.kind == ID_NONE) ||
(c->kind == CK_INSTANCE && id_is_ipaddr(&c->spd.that.id))))
{
- /* roadwarrior: replace him with 0.0.0.0 */
- rw_id.kind = ID_IPV4_ADDR;
- happy(anyaddr(addrtypeof(&c->spd.that.host_addr), &rw_id.ip_addr));
- his_id = &rw_id;
+ /* roadwarrior: replace him with 0.0.0.0 */
+ rw_id.kind = ID_IPV4_ADDR;
+ happy(anyaddr(addrtypeof(&c->spd.that.host_addr), &rw_id.ip_addr));
+ his_id = &rw_id;
}
#endif
@@ -295,14 +297,12 @@ get_preshared_secret(const struct connection *c)
{
const secret_t *s = get_secret(c, PPK_PSK, FALSE);
-#ifdef DEBUG
DBG(DBG_PRIVATE,
if (s == NULL)
DBG_log("no Preshared Key Found");
else
DBG_dump_chunk("Preshared Key", s->u.preshared_secret);
- );
-#endif
+ )
return s == NULL? NULL : &s->u.preshared_secret;
}
@@ -417,7 +417,7 @@ process_psk_secret(chunk_t *psk)
}
else
{
- char buf[RSA_MAX_ENCODING_BYTES]; /* limit on size of binary representation of key */
+ char buf[BUF_LEN]; /* limit on size of binary representation of key */
size_t sz;
ugh = ttodatav(tok, flp->cur - tok, 0, buf, sizeof(buf), &sz
@@ -586,6 +586,119 @@ process_rsa_keyfile(RSA_private_key_t *rsak, int whackfd)
}
/*
+ * process xauth secret read from ipsec.secrets
+ */
+static err_t
+process_xauth(secret_t *s)
+{
+ chunk_t user_name;
+
+ s->kind = PPK_XAUTH;
+
+ if (!shift())
+ return "missing xauth user name";
+ if (*tok == '"' || *tok == '\'') /* quoted user name */
+ {
+ user_name.ptr = tok + 1;
+ user_name.len = flp->cur - tok - 2;
+ }
+ else
+ {
+ user_name.ptr = tok;
+ user_name.len = flp->cur - tok;
+ }
+ plog(" loaded xauth credentials of user '%.*s'"
+ , user_name.len
+ , user_name.ptr);
+ clonetochunk(s->u.xauth_secret.user_name
+ , user_name.ptr, user_name.len, "xauth user name");
+
+ if (!shift())
+ return "missing xauth user password";
+ return process_psk_secret(&s->u.xauth_secret.user_password);
+}
+
+/* get XAUTH secret from chained secrets lists
+ * only one entry is currently supported
+ */
+static bool
+xauth_get_secret(xauth_t *xauth_secret)
+{
+ secret_t *s;
+ bool found = FALSE;
+
+ for (s = secrets; s != NULL; s = s->next)
+ {
+ if (s->kind == PPK_XAUTH)
+ {
+ if (found)
+ {
+ plog("found multiple xauth secrets - first selected");
+ }
+ else
+ {
+ found = TRUE;
+ *xauth_secret = s->u.xauth_secret;
+ }
+ }
+ }
+ return found;
+}
+
+/*
+ * find a matching secret
+ */
+static bool
+xauth_verify_secret(const xauth_t *xauth_secret)
+{
+ bool found = FALSE;
+ secret_t *s;
+
+ for (s = secrets; s != NULL; s = s->next)
+ {
+ if (s->kind == PPK_XAUTH)
+ {
+ if (!same_chunk(xauth_secret->user_name, s->u.xauth_secret.user_name))
+ continue;
+ found = TRUE;
+ if (same_chunk(xauth_secret->user_password, s->u.xauth_secret.user_password))
+ return TRUE;
+ }
+ }
+ plog("xauth user '%.*s' %s"
+ , xauth_secret->user_name.len, xauth_secret->user_name.ptr
+ , found? "sent wrong password":"not found");
+ return FALSE;
+}
+
+/*
+ * the global xauth_module struct is defined here
+ */
+xauth_module_t xauth_module;
+
+/*
+ * assign the default xauth functions to any null function pointers
+ */
+void
+xauth_defaults(void)
+{
+ if (xauth_module.get_secret == NULL)
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("xauth module: using default get_secret() function")
+ )
+ xauth_module.get_secret = xauth_get_secret;
+ }
+ if (xauth_module.verify_secret == NULL)
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("xauth module: using default verify_secret() function")
+ )
+ xauth_module.verify_secret = xauth_verify_secret;
+ }
+};
+
+/*
* process pin read from ipsec.secrets or prompted for it using whack
*/
static err_t
@@ -696,6 +809,10 @@ process_secret(secret_t *s, int whackfd)
ugh = process_rsa_keyfile(&s->u.RSA_private_key, whackfd);
}
}
+ else if (tokeqword("xauth"))
+ {
+ ugh = process_xauth(s);
+ }
else if (tokeqword("pin"))
{
ugh = process_pin(s, whackfd);
@@ -925,7 +1042,7 @@ void
free_preshared_secrets(void)
{
lock_certs_and_keys("free_preshared_secrets");
-
+
if (secrets != NULL)
{
secret_t *s, *ns;
@@ -951,6 +1068,10 @@ free_preshared_secrets(void)
case PPK_RSA:
free_RSA_private_content(&s->u.RSA_private_key);
break;
+ case PPK_XAUTH:
+ pfree(s->u.xauth_secret.user_name.ptr);
+ pfree(s->u.xauth_secret.user_password.ptr);
+ break;
case PPK_PIN:
scx_release(s->u.smartcard);
break;
@@ -961,7 +1082,7 @@ free_preshared_secrets(void)
}
secrets = NULL;
}
-
+
unlock_certs_and_keys("free_preshard_secrets");
}
@@ -1105,14 +1226,11 @@ unpack_RSA_public_key(RSA_public_key_t *rsa, const chunk_t *pubkey)
return RSA_MAX_OCTETS_UGH;
init_RSA_public_key(rsa, exp, mod);
-
-#ifdef DEBUG
- DBG(DBG_PRIVATE, RSA_show_public_key(rsa));
-#endif
-
-
rsa->k = mpz_sizeinbase(&rsa->n, 2); /* size in bits, for a start */
rsa->k = (rsa->k + BITS_PER_BYTE - 1) / BITS_PER_BYTE; /* now octets */
+ DBG(DBG_RAW,
+ RSA_show_public_key(rsa)
+ )
if (rsa->k != mod.len)
{
diff --git a/programs/pluto/keys.h b/programs/pluto/keys.h
index d47d8b0a2..2f6216b93 100644
--- a/programs/pluto/keys.h
+++ b/programs/pluto/keys.h
@@ -11,7 +11,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: keys.h,v 1.7 2006/01/26 20:10:34 as Exp $
+ * RCSID $Id: keys.h,v 1.8 2007/01/10 00:36:19 as Exp $
*/
#ifndef _KEYS_H
@@ -31,15 +31,19 @@ const char *shared_secrets_file;
extern void load_preshared_secrets(int whackfd);
extern void free_preshared_secrets(void);
-struct state; /* forward declaration */
-
enum PrivateKeyKind {
PPK_PSK,
/* PPK_DSS, */ /* not implemented */
PPK_RSA,
+ PPK_XAUTH,
PPK_PIN
};
+extern void xauth_defaults(void);
+
+/* forward declaration */
+struct connection;
+
extern const chunk_t *get_preshared_secret(const struct connection *c);
extern err_t unpack_RSA_public_key(RSA_public_key_t *rsa, const chunk_t *pubkey);
extern const RSA_private_key_t *get_RSA_private_key(const struct connection *c);
diff --git a/programs/pluto/modecfg.c b/programs/pluto/modecfg.c
index ec334aaf5..01bab8c6e 100644
--- a/programs/pluto/modecfg.c
+++ b/programs/pluto/modecfg.c
@@ -14,7 +14,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: modecfg.c,v 1.9 2006/10/21 17:11:13 as Exp $
+ * RCSID $Id: modecfg.c,v 1.10 2007/01/10 00:36:19 as Exp $
*
* This code originally written by Colubris Networks, Inc.
* Extraction of patch and porting to 1.99 codebases by Xelerance Corporation
@@ -39,6 +39,9 @@
#include "crypto.h"
#include "modecfg.h"
#include "whack.h"
+#include "xauth.h"
+
+#define MAX_XAUTH_TRIES 3
#define SUPPORTED_ATTR_SET ( LELEM(INTERNAL_IP4_ADDRESS) \
| LELEM(INTERNAL_IP4_NETMASK) \
@@ -53,10 +56,17 @@ typedef struct internal_addr internal_addr_t;
struct internal_addr
{
- lset_t attr_set;
- ip_address ipaddr;
- ip_address dns[2];
- ip_address wins[2];
+ lset_t attr_set;
+
+ /* ModeCfg variables */
+ ip_address ipaddr;
+ ip_address dns[2];
+ ip_address wins[2];
+
+ /* XAUTH variables */
+ u_int16_t xauth_type;
+ xauth_t xauth_secret;
+ bool xauth_status;
};
/*
@@ -66,6 +76,10 @@ static void
init_internal_addr(internal_addr_t *ia)
{
ia->attr_set = LEMPTY;
+ ia->xauth_secret.user_name = empty_chunk;
+ ia->xauth_secret.user_password = empty_chunk;
+ ia->xauth_status = FALSE;
+
anyaddr(AF_INET, &ia->ipaddr);
anyaddr(AF_INET, &ia->dns[0]);
anyaddr(AF_INET, &ia->dns[1]);
@@ -218,7 +232,20 @@ modecfg_build_msg(struct state *st, pb_stream *rbody
u_int len;
/* ISAKMP attr out */
- attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TLV;
+ if (attr_type == XAUTH_TYPE)
+ {
+ attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TV;
+ attr.isaat_lv = ia->xauth_type;
+ }
+ else if (attr_type == XAUTH_STATUS)
+ {
+ attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TV;
+ attr.isaat_lv = ia->xauth_status;
+ }
+ else
+ {
+ attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TLV;
+ }
out_struct(&attr, &isakmp_modecfg_attribute_desc, &strattr, &attrval);
switch (attr_type)
@@ -288,14 +315,34 @@ modecfg_build_msg(struct state *st, pb_stream *rbody
case INTERNAL_IP4_NBNS:
if (!isanyaddr(&ia->wins[wins_idx]))
{
- len = addrbytesptr(&ia->wins[wins_idx++], &byte_ptr);
- out_raw(byte_ptr, len, &attrval, "IP4_wins");
+ len = addrbytesptr(&ia->wins[wins_idx++], &byte_ptr);
+ out_raw(byte_ptr, len, &attrval, "IP4_wins");
}
if (wins_idx < 2 && !isanyaddr(&ia->wins[wins_idx]))
{
dont_advance = TRUE;
}
- break;
+ break;
+ case XAUTH_TYPE:
+ break;
+ case XAUTH_USER_NAME:
+ if (ia->xauth_secret.user_name.ptr != NULL)
+ {
+ out_raw(ia->xauth_secret.user_name.ptr
+ , ia->xauth_secret.user_name.len
+ , &attrval, "xauth_user_name");
+ }
+ break;
+ case XAUTH_USER_PASSWORD:
+ if (ia->xauth_secret.user_password.ptr != NULL)
+ {
+ out_raw(ia->xauth_secret.user_password.ptr
+ , ia->xauth_secret.user_password.len
+ , &attrval, "xauth_user_password");
+ }
+ break;
+ case XAUTH_STATUS:
+ break;
default:
plog("attempt to send unsupported mode cfg attribute %s."
, enum_show(&modecfg_attr_names, attr_type));
@@ -306,13 +353,17 @@ modecfg_build_msg(struct state *st, pb_stream *rbody
if (!dont_advance)
{
attr_type++;
+ if (attr_type == MODECFG_ROOF)
+ {
+ attr_type = XAUTH_BASE;
+ }
attr_set >>= 1;
}
}
close_message(&strattr);
}
- modecfg_hash(r_hashval, r_hash_start, rbody->cur,st);
+ modecfg_hash(r_hashval, r_hash_start, rbody->cur, st);
close_message(rbody);
encrypt_message(rbody, st);
return STF_OK;
@@ -361,6 +412,7 @@ modecfg_send_msg(struct state *st, int isama_type, internal_addr_t *ia)
, 0 /* XXX isama_id */
);
+ freeanychunk(st->st_tpacket);
clonetochunk(st->st_tpacket, msg.start, pbs_offset(&msg), "ModeCfg msg");
/* Transmit */
@@ -371,43 +423,10 @@ modecfg_send_msg(struct state *st, int isama_type, internal_addr_t *ia)
delete_event(st);
event_schedule(EVENT_RETRANSMIT, EVENT_RETRANSMIT_DELAY_0, st);
}
- st->st_modecfg.started = TRUE;
return STF_OK;
}
/*
- * Send ModeCfg request message from client to server in pull mode
- */
-stf_status
-modecfg_send_request(struct state *st)
-{
- internal_addr_t ia;
-
- init_internal_addr(&ia);
- ia.attr_set = LELEM(INTERNAL_IP4_ADDRESS)
- | LELEM(INTERNAL_IP4_NETMASK);
-
- plog("sending ModeCfg request");
- st->st_state = STATE_MODE_CFG_I1;
- return modecfg_send_msg(st, ISAKMP_CFG_REQUEST, &ia);
-}
-
-/*
- * Send ModeCfg set message from server to client in push mode
- */
-stf_status
-modecfg_send_set(struct state *st)
-{
- internal_addr_t ia;
-
- get_internal_addr(st->st_connection, &ia);
-
- plog("sending ModeCfg set");
- st->st_state = STATE_MODE_CFG_R1;
- return modecfg_send_msg(st, ISAKMP_CFG_SET, &ia);
-}
-
-/*
* Parse a ModeCfg attribute payload
*/
static stf_status
@@ -442,6 +461,22 @@ modecfg_parse_attributes(pb_stream *attrs, internal_addr_t *ia)
case INTERNAL_IP4_NBNS:
ia->attr_set |= LELEM(attr_type);
break;
+ case XAUTH_TYPE:
+ ia->xauth_type = attr.isaat_lv;
+ ia->attr_set |= LELEM(attr_type - XAUTH_BASE + MODECFG_ROOF);
+ break;
+ case XAUTH_USER_NAME:
+ setchunk(ia->xauth_secret.user_name, strattr.cur, attr_len);
+ ia->attr_set |= LELEM(attr_type - XAUTH_BASE + MODECFG_ROOF);
+ break;
+ case XAUTH_USER_PASSWORD:
+ setchunk(ia->xauth_secret.user_password, strattr.cur, attr_len);
+ ia->attr_set |= LELEM(attr_type - XAUTH_BASE + MODECFG_ROOF);
+ break;
+ case XAUTH_STATUS:
+ ia->xauth_status = attr.isaat_lv;
+ ia->attr_set |= LELEM(attr_type - XAUTH_BASE + MODECFG_ROOF);
+ break;
default:
plog("unsupported ModeCfg attribute %s received."
, enum_show(&modecfg_attr_names, attr_type));
@@ -483,7 +518,7 @@ modecfg_parse_msg(struct msg_digest *md, int isama_type, u_int16_t *isama_id
stat = modecfg_parse_attributes(&p->pbs, &ia_candidate);
if (stat == STF_OK)
{
- /* retrun with a valid set of attributes */
+ /* return with a valid set of attributes */
*ia = ia_candidate;
return STF_OK;
}
@@ -502,6 +537,27 @@ modecfg_parse_msg(struct msg_digest *md, int isama_type, u_int16_t *isama_id
return STF_IGNORE;
}
+/*
+ * Send ModeCfg request message from client to server in pull mode
+ */
+stf_status
+modecfg_send_request(struct state *st)
+{
+ stf_status stat;
+ internal_addr_t ia;
+
+ init_internal_addr(&ia);
+ ia.attr_set = LELEM(INTERNAL_IP4_ADDRESS)
+ | LELEM(INTERNAL_IP4_NETMASK);
+
+ plog("sending ModeCfg request");
+ st->st_state = STATE_MODE_CFG_I1;
+ stat = modecfg_send_msg(st, ISAKMP_CFG_REQUEST, &ia);
+ if (stat == STF_OK)
+ st->st_modecfg.started = TRUE;
+ return stat;
+}
+
/* STATE_MODE_CFG_R0:
* HDR*, HASH, ATTR(REQ=IP) --> HDR*, HASH, ATTR(REPLY=IP)
*
@@ -513,37 +569,118 @@ modecfg_inR0(struct msg_digest *md)
struct state *const st = md->st;
u_int16_t isama_id;
internal_addr_t ia;
- stf_status stat;
+ stf_status stat, stat_build;
stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, &ia);
if (stat != STF_OK)
return stat;
+
+ get_internal_addr(st->st_connection, &ia);
+
+ plog("sending ModeCfg reply");
+
+ stat_build = modecfg_build_msg(st, &md->rbody
+ , ISAKMP_CFG_REPLY
+ , &ia
+ , isama_id);
+ if (stat_build != STF_OK)
+ return stat_build;
+
+ st->st_msgid = 0;
+ return STF_OK;
+}
+
+/* STATE_MODE_CFG_I1:
+ * HDR*, HASH, ATTR(REPLY=IP)
+ *
+ * used in ModeCfg pull mode, on the client (initiator)
+ */
+stf_status
+modecfg_inI1(struct msg_digest *md)
+{
+ struct state *const st = md->st;
+ u_int16_t isama_id;
+ internal_addr_t ia;
+ stf_status stat;
+
+ plog("parsing ModeCfg reply");
+
+ stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, &ia);
+ if (stat != STF_OK)
+ return stat;
+
+ st->st_modecfg.vars_set = set_internal_addr(st->st_connection, &ia);
+ st->st_msgid = 0;
+ return STF_OK;
+}
+
+
+/*
+ * Send ModeCfg set message from server to client in push mode
+ */
+stf_status
+modecfg_send_set(struct state *st)
+{
+ stf_status stat;
+ internal_addr_t ia;
get_internal_addr(st->st_connection, &ia);
- /* build ISAKMP_CFG_REPLY */
- stat = modecfg_build_msg(st, &md->rbody
- , ISAKMP_CFG_REPLY
- , &ia
- , isama_id);
+ plog("sending ModeCfg set");
+ st->st_state = STATE_MODE_CFG_R3;
+ stat = modecfg_send_msg(st, ISAKMP_CFG_SET, &ia);
+ if (stat == STF_OK)
+ st->st_modecfg.started = TRUE;
+ return stat;
+}
+
+/* STATE_MODE_CFG_I0:
+ * HDR*, HASH, ATTR(SET=IP) --> HDR*, HASH, ATTR(ACK,OK)
+ *
+ * used in ModeCfg push mode, on the client (initiator).
+ */
+stf_status
+modecfg_inI0(struct msg_digest *md)
+{
+ struct state *const st = md->st;
+ u_int16_t isama_id;
+ internal_addr_t ia;
+ lset_t attr_set;
+ stf_status stat, stat_build;
+
+ plog("parsing ModeCfg set");
+
+ stat = modecfg_parse_msg(md, ISAKMP_CFG_SET, &isama_id, &ia);
if (stat != STF_OK)
- {
- /* notification payload - not exactly the right choice, but okay */
- md->note = ATTRIBUTES_NOT_SUPPORTED;
return stat;
- }
+
+ st->st_modecfg.vars_set = set_internal_addr(st->st_connection, &ia);
+
+ /* prepare ModeCfg ack which sends zero length attributes */
+ attr_set = ia.attr_set;
+ init_internal_addr(&ia);
+ ia.attr_set = attr_set & SUPPORTED_ATTR_SET;
+
+ plog("sending ModeCfg ack");
+
+ stat_build = modecfg_build_msg(st, &md->rbody
+ , ISAKMP_CFG_ACK
+ , &ia
+ , isama_id);
+ if (stat_build != STF_OK)
+ return stat_build;
st->st_msgid = 0;
return STF_OK;
}
-/* STATE_MODE_CFG_R1:
+/* STATE_MODE_CFG_R3:
* HDR*, HASH, ATTR(ACK,OK)
*
* used in ModeCfg push mode, on the server (responder)
*/
stf_status
-modecfg_inR1(struct msg_digest *md)
+modecfg_inR3(struct msg_digest *md)
{
struct state *const st = md->st;
u_int16_t isama_id;
@@ -560,61 +697,211 @@ modecfg_inR1(struct msg_digest *md)
return STF_OK;
}
-/* STATE_MODE_CFG_I1:
- * HDR*, HASH, ATTR(REPLY=IP)
+/*
+ * Send XAUTH credentials request (username + password)
+ */
+stf_status
+xauth_send_request(struct state *st)
+{
+ stf_status stat;
+ internal_addr_t ia;
+
+ init_internal_addr(&ia);
+ ia.attr_set = LELEM(XAUTH_USER_NAME - XAUTH_BASE + MODECFG_ROOF)
+ | LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE + MODECFG_ROOF);
+
+ plog("sending XAUTH request");
+ st->st_state = STATE_XAUTH_R1;
+ stat = modecfg_send_msg(st, ISAKMP_CFG_REQUEST, &ia);
+ if (stat == STF_OK)
+ st->st_xauth.started = TRUE;
+ return stat;
+}
+
+/* STATE_XAUTH_I0:
+ * HDR*, HASH, ATTR(REQ) --> HDR*, HASH, ATTR(REPLY=USERNAME/PASSWORD)
*
- * used in ModeCfg pull mode, on the client (initiator)
+ * used on the XAUTH client (initiator)
*/
stf_status
-modecfg_inI1(struct msg_digest *md)
+xauth_inI0(struct msg_digest *md)
{
struct state *const st = md->st;
u_int16_t isama_id;
internal_addr_t ia;
- stf_status stat;
+ stf_status stat, stat_build;
- plog("parsing ModeCfg reply");
+ plog("parsing XAUTH request");
- stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, &ia);
+ stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, &ia);
if (stat != STF_OK)
return stat;
+
+ /* check XAUTH attributes */
+ if ((ia.attr_set & LELEM(XAUTH_TYPE - XAUTH_BASE + MODECFG_ROOF)) != LEMPTY
+ && ia.xauth_type != XAUTH_TYPE_GENERIC)
+ {
+ plog("xauth type %s is not supported", enum_name(&xauth_type_names, ia.xauth_type));
+ stat = STF_FAIL;
+ }
+ else if ((ia.attr_set & LELEM(XAUTH_USER_NAME - XAUTH_BASE + MODECFG_ROOF)) == LEMPTY)
+ {
+ plog("user name attribute is missing in XAUTH request");
+ stat = STF_FAIL;
+ }
+ else if ((ia.attr_set & LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE + MODECFG_ROOF)) == LEMPTY)
+ {
+ plog("user password attribute is missing in XAUTH request");
+ stat = STF_FAIL;
+ }
- st->st_modecfg.vars_set = set_internal_addr(st->st_connection, &ia);
- st->st_msgid = 0;
- return STF_OK;
+ /* prepare XAUTH reply */
+ init_internal_addr(&ia);
+
+ if (stat == STF_OK)
+ {
+ /* get user credentials using a plugin function */
+ if (!xauth_module.get_secret(&ia.xauth_secret))
+ {
+ plog("xauth user credentials not found");
+ stat = STF_FAIL;
+ }
+ }
+ if (stat == STF_OK)
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("my xauth user name is '%.*s'"
+ , ia.xauth_secret.user_name.len
+ , ia.xauth_secret.user_name.ptr)
+ )
+ DBG(DBG_PRIVATE,
+ DBG_log("my xauth user password is '%.*s'"
+ , ia.xauth_secret.user_password.len
+ , ia.xauth_secret.user_password.ptr)
+ )
+ ia.attr_set = LELEM(XAUTH_USER_NAME - XAUTH_BASE + MODECFG_ROOF)
+ | LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE + MODECFG_ROOF);
+ }
+ else
+ {
+ ia.attr_set = LELEM(XAUTH_STATUS - XAUTH_BASE + MODECFG_ROOF);
+ ia.xauth_status = FALSE;
+ }
+
+ plog("sending XAUTH reply");
+
+ stat_build = modecfg_build_msg(st, &md->rbody
+ , ISAKMP_CFG_REPLY
+ , &ia
+ , isama_id);
+ if (stat_build != STF_OK)
+ return stat_build;
+
+ if (stat == STF_OK)
+ {
+ st->st_xauth.started = TRUE;
+ return STF_OK;
+ }
+ else
+ {
+ /* send XAUTH reply msg and then delete ISAKMP SA */
+ freeanychunk(st->st_tpacket);
+ clonetochunk(st->st_tpacket, md->reply.start
+ , pbs_offset(&md->reply), "XAUTH reply msg");
+ send_packet(st, "XAUTH reply msg");
+ delete_state(st);
+ return STF_IGNORE;
+ }
}
-/* STATE_MODE_CFG_I2:
- * HDR*, HASH, ATTR(SET=IP) --> HDR*, HASH, ATTR(ACK,OK)
+/* STATE_XAUTH_R1:
+ * HDR*, HASH, ATTR(REPLY=USERNAME/PASSWORD) --> HDR*, HASH, ATTR(STATUS)
*
- * used in ModeCfg push mode, on the client (initiator).
+ * used on the XAUTH server (responder)
*/
stf_status
-modecfg_inI2(struct msg_digest *md)
+xauth_inR1(struct msg_digest *md)
{
struct state *const st = md->st;
u_int16_t isama_id;
internal_addr_t ia;
- lset_t attr_set;
- stf_status stat;
+ stf_status stat, stat_build;
- plog("parsing ModeCfg set");
+ plog("parsing XAUTH reply");
- stat = modecfg_parse_msg(md, ISAKMP_CFG_SET, &isama_id, &ia);
+ stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, &ia);
if (stat != STF_OK)
return stat;
+
+ /* did the client return an XAUTH FAIL status? */
+ if ((ia.attr_set & LELEM(XAUTH_STATUS - XAUTH_BASE + MODECFG_ROOF)) != LEMPTY)
+ {
+ plog("received FAIL status in XAUTH reply");
- st->st_modecfg.vars_set = set_internal_addr(st->st_connection, &ia);
+ /* client is not able to do XAUTH, delete ISAKMP SA */
+ delete_state(st);
+ return STF_IGNORE;
+ }
- /* prepare ModeCfg ack which sends zero length attributes */
- attr_set = ia.attr_set;
+ /* check XAUTH reply */
+ if ((ia.attr_set & LELEM(XAUTH_USER_NAME - XAUTH_BASE + MODECFG_ROOF)) == LEMPTY)
+ {
+ plog("user name attribute is missing in XAUTH reply");
+ st->st_xauth.status = FALSE;
+ }
+ else if ((ia.attr_set & LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE + MODECFG_ROOF)) == LEMPTY)
+ {
+ plog("user password attribute is missing in XAUTH reply");
+ st->st_xauth.status = FALSE;
+ }
+ else
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("peer xauth user name is '%.*s'"
+ , ia.xauth_secret.user_name.len
+ , ia.xauth_secret.user_name.ptr)
+ )
+ DBG(DBG_PRIVATE,
+ DBG_log("peer xauth user password is '%.*s'"
+ , ia.xauth_secret.user_password.len
+ , ia.xauth_secret.user_password.ptr)
+ )
+ /* verify the user credentials using a plugn function */
+ st->st_xauth.status = xauth_module.verify_secret(&ia.xauth_secret);
+ plog("extended authentication %s", st->st_xauth.status? "was successful":"failed");
+ }
+
+ /* prepare XAUTH set which sends the authentication status */
init_internal_addr(&ia);
- ia.attr_set = attr_set & SUPPORTED_ATTR_SET;
+ ia.attr_set = LELEM(XAUTH_STATUS - XAUTH_BASE + MODECFG_ROOF);
+ ia.xauth_status = st->st_xauth.status;
+
+ plog("sending XAUTH status:");
+
+ stat_build = modecfg_build_msg(st, &md->rbody
+ , ISAKMP_CFG_SET
+ , &ia
+ , isama_id);
+ if (stat_build != STF_OK)
+ return stat_build;
+ return STF_OK;
+}
- stat = modecfg_build_msg(st, &md->rbody
- , ISAKMP_CFG_ACK
- , &ia
- , isama_id);
+/* STATE_XAUTH_I1:
+ * HDR*, HASH, ATTR(STATUS) --> HDR*, HASH, ATTR(ACK)
+ *
+ * used on the XAUTH client (initiator)
+ */
+stf_status
+xauth_inI1(struct msg_digest *md)
+{
+ struct state *const st = md->st;
+ u_int16_t isama_id;
+ internal_addr_t ia;
+ stf_status stat, stat_build;
+
+ plog("parsing XAUTH status");
+ stat = modecfg_parse_msg(md, ISAKMP_CFG_SET, &isama_id, &ia);
if (stat != STF_OK)
{
/* notification payload - not exactly the right choice, but okay */
@@ -622,6 +909,62 @@ modecfg_inI2(struct msg_digest *md)
return stat;
}
+ st->st_xauth.status = ia.xauth_status;
+ plog("extended authentication %s", st->st_xauth.status? "was successful":"failed");
+
+ plog("sending XAUTH ack");
+ init_internal_addr(&ia);
+ stat_build = modecfg_build_msg(st, &md->rbody
+ , ISAKMP_CFG_ACK
+ , &ia
+ , isama_id);
+ if (stat_build != STF_OK)
+ return stat_build;
+
+ if (st->st_xauth.status)
+ {
+ st->st_msgid = 0;
+ return STF_OK;
+ }
+ else
+ {
+ /* send XAUTH ack msg and then delete ISAKMP SA */
+ freeanychunk(st->st_tpacket);
+ clonetochunk(st->st_tpacket, md->reply.start
+ , pbs_offset(&md->reply), "XAUTH ack msg");
+ send_packet(st, "XAUTH ack msg");
+ delete_state(st);
+ return STF_IGNORE;
+ }
+}
+
+/* STATE_XAUTH_R2:
+ * HDR*, ATTR(STATUS), HASH --> Done
+ *
+ * used on the XAUTH server (responder)
+ */
+stf_status
+xauth_inR2(struct msg_digest *md)
+{
+ struct state *const st = md->st;
+ u_int16_t isama_id;
+ internal_addr_t ia;
+ stf_status stat;
+
+ plog("parsing XAUTH ack");
+
+ stat = modecfg_parse_msg(md, ISAKMP_CFG_ACK, &isama_id, &ia);
+ if (stat != STF_OK)
+ return stat;
+
st->st_msgid = 0;
- return STF_OK;
+ if (st->st_xauth.status)
+ {
+ return STF_OK;
+ }
+ else
+ {
+ delete_state(st);
+ return STF_IGNORE;
+ }
}
diff --git a/programs/pluto/modecfg.h b/programs/pluto/modecfg.h
index 1f8259ca8..4fce75aef 100644
--- a/programs/pluto/modecfg.h
+++ b/programs/pluto/modecfg.h
@@ -12,17 +12,36 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: modecfg.h,v 1.3 2006/10/19 21:07:40 as Exp $
+ * RCSID $Id: modecfg.h,v 1.4 2007/01/10 00:36:19 as Exp $
*/
+#ifndef _MODECFG_H
+#define _MODECFG_H
+
struct state;
+struct msg_digest;
-/* ModeConfig starting functions */
+/* ModeConfig pull mode start function */
extern stf_status modecfg_send_request(struct state *st);
-extern stf_status modecfg_send_set(struct state *st);
-/* ModeConfig state transition functions */
+/* ModeConfig pull mode state transition functions */
extern stf_status modecfg_inR0(struct msg_digest *md);
-extern stf_status modecfg_inR1(struct msg_digest *md);
extern stf_status modecfg_inI1(struct msg_digest *md);
-extern stf_status modecfg_inI2(struct msg_digest *md);
+
+/* ModeConfig push mode start function */
+extern stf_status modecfg_send_set(struct state *st);
+
+/* ModeConfig push mode state transition functions */
+extern stf_status modecfg_inI0(struct msg_digest *md);
+extern stf_status modecfg_inR3(struct msg_digest *md);
+
+/* XAUTH start function */
+extern stf_status xauth_send_request(struct state *st);
+
+/* XAUTH state transition funcgtions */
+extern stf_status xauth_inI0(struct msg_digest *md);
+extern stf_status xauth_inR1(struct msg_digest *md);
+extern stf_status xauth_inI1(struct msg_digest *md);
+extern stf_status xauth_inR2(struct msg_digest *md);
+
+#endif /* _MODECFG_H */
diff --git a/programs/pluto/plutomain.c b/programs/pluto/plutomain.c
index f9badbae3..613f8d50f 100644
--- a/programs/pluto/plutomain.c
+++ b/programs/pluto/plutomain.c
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: plutomain.c,v 1.16 2005/09/25 21:30:52 as Exp $
+ * RCSID $Id: plutomain.c,v 1.18 2007/01/14 10:11:56 as Exp $
*/
#include <stdio.h>
@@ -57,6 +57,7 @@
#include "ocsp.h"
#include "crl.h"
#include "fetch.h"
+#include "xauth.h"
#include "sha1.h"
#include "md5.h"
@@ -628,6 +629,7 @@ main(int argc, char **argv)
init_virtual_ip(virtual_private);
#endif
scx_init(pkcs11_module_path); /* load and initialize PKCS #11 module */
+ xauth_init(); /* load and initialize XAUTH module */
init_rnd_pool();
init_secret();
init_states();
@@ -678,6 +680,7 @@ exit_pluto(int status)
free_ocsp(); /* free ocsp cache */
free_ifaces();
scx_finalize(); /* finalize and unload PKCS #11 module */
+ xauth_finalize(); /* finalize and unload XAUTH module */
stop_adns();
free_md_pool();
delete_lock();
diff --git a/programs/pluto/spdb.c b/programs/pluto/spdb.c
index 0544a1da2..ab976511e 100644
--- a/programs/pluto/spdb.c
+++ b/programs/pluto/spdb.c
@@ -11,7 +11,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: spdb.c,v 1.9 2006/04/22 21:59:20 as Exp $
+ * RCSID $Id: spdb.c,v 1.10 2007/01/10 00:36:19 as Exp $
*/
#include <stdio.h>
@@ -54,158 +54,26 @@
/**************** Oakely (main mode) SA database ****************/
-/* arrays of attributes for transforms, preshared key */
-
-static struct db_attr otpsk1024des3md5[] = {
- { OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
- { OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
- { OAKLEY_AUTHENTICATION_METHOD, OAKLEY_PRESHARED_KEY },
- { OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
- };
-
-static struct db_attr otpsk1536des3md5[] = {
- { OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
- { OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
- { OAKLEY_AUTHENTICATION_METHOD, OAKLEY_PRESHARED_KEY },
- { OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
- };
-
-static struct db_attr otpsk1024des3sha[] = {
- { OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
- { OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
- { OAKLEY_AUTHENTICATION_METHOD, OAKLEY_PRESHARED_KEY },
- { OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
- };
-
-static struct db_attr otpsk1536des3sha[] = {
- { OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
- { OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
- { OAKLEY_AUTHENTICATION_METHOD, OAKLEY_PRESHARED_KEY },
- { OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
- };
-
-/* arrays of attributes for transforms, RSA signatures */
-
-static struct db_attr otrsasig1024des3md5[] = {
- { OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
- { OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
- { OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG },
- { OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
- };
-
-static struct db_attr otrsasig1536des3md5[] = {
- { OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
- { OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 },
- { OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG },
- { OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
- };
-
-static struct db_attr otrsasig1024des3sha[] = {
- { OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
- { OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
- { OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG },
- { OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
- };
-
-static struct db_attr otrsasig1536des3sha[] = {
- { OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
- { OAKLEY_HASH_ALGORITHM, OAKLEY_SHA },
- { OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG },
- { OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 },
- };
-
-/* We won't accept this, but by proposing it, we get to test
- * our rejection. We better not propose it to an IKE daemon
- * that will accept it!
- */
-#ifdef TEST_INDECENT_PROPOSAL
-static struct db_attr otpsk1024des3tiger[] = {
- { OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC },
- { OAKLEY_HASH_ALGORITHM, OAKLEY_TIGER },
- { OAKLEY_AUTHENTICATION_METHOD, OAKLEY_PRESHARED_KEY },
- { OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 },
- };
-#endif /* TEST_INDECENT_PROPOSAL */
-
-/* tables of transforms, in preference order (select based on AUTH) */
-
-static struct db_trans oakley_trans_psk[] = {
-#ifdef TEST_INDECENT_PROPOSAL
- { KEY_IKE, AD(otpsk1024des3tiger) },
-#endif
- { KEY_IKE, AD(otpsk1536des3md5) },
- { KEY_IKE, AD(otpsk1536des3sha) },
- { KEY_IKE, AD(otpsk1024des3sha) },
- { KEY_IKE, AD(otpsk1024des3md5) },
- };
-
-static struct db_trans oakley_trans_rsasig[] = {
- { KEY_IKE, AD(otrsasig1536des3md5) },
- { KEY_IKE, AD(otrsasig1536des3sha) },
- { KEY_IKE, AD(otrsasig1024des3sha) },
- { KEY_IKE, AD(otrsasig1024des3md5) },
- };
-
-/* In this table, either PSK or RSA sig is accepted.
- * The order matters, but I don't know what would be best.
- */
-static struct db_trans oakley_trans_pskrsasig[] = {
-#ifdef TEST_INDECENT_PROPOSAL
- { KEY_IKE, AD(otpsk1024des3tiger) },
-#endif
- { KEY_IKE, AD(otrsasig1536des3md5) },
- { KEY_IKE, AD(otpsk1536des3md5) },
- { KEY_IKE, AD(otrsasig1536des3sha) },
- { KEY_IKE, AD(otpsk1536des3sha) },
- { KEY_IKE, AD(otrsasig1024des3sha) },
- { KEY_IKE, AD(otpsk1024des3sha) },
- { KEY_IKE, AD(otrsasig1024des3md5) },
- { KEY_IKE, AD(otpsk1024des3md5) },
- };
-
/* array of proposals to be conjoined (can only be one for Oakley) */
-static struct db_prop oakley_pc_psk[] =
- { { PROTO_ISAKMP, AD(oakley_trans_psk) } };
-
-static struct db_prop oakley_pc_rsasig[] =
- { { PROTO_ISAKMP, AD(oakley_trans_rsasig) } };
-
-static struct db_prop oakley_pc_pskrsasig[] =
- { { PROTO_ISAKMP, AD(oakley_trans_pskrsasig) } };
+static struct db_prop oakley_pc[] =
+ { { PROTO_ISAKMP, AD_NULL } };
/* array of proposal conjuncts (can only be one) */
-static struct db_prop_conj oakley_props_psk[] = { { AD(oakley_pc_psk) } };
+static struct db_prop_conj oakley_props[] = { { AD(oakley_pc) } };
-static struct db_prop_conj oakley_props_rsasig[] = { { AD(oakley_pc_rsasig) } };
-
-static struct db_prop_conj oakley_props_pskrsasig[] = { { AD(oakley_pc_pskrsasig) } };
-
-/* the sadb entry, subscripted by POLICY_PSK and POLICY_RSASIG bits */
-struct db_sa oakley_sadb[] = {
- { AD_NULL }, /* none */
- { AD(oakley_props_psk) }, /* POLICY_PSK */
- { AD(oakley_props_rsasig) }, /* POLICY_RSASIG */
- { AD(oakley_props_pskrsasig) }, /* POLICY_PSK + POLICY_RSASIG */
- };
+/* the sadb entry */
+struct db_sa oakley_sadb = { AD(oakley_props) };
/**************** IPsec (quick mode) SA database ****************/
/* arrays of attributes for transforms */
-static struct db_attr espmd5_attr[] = {
- { AUTH_ALGORITHM, AUTH_ALGORITHM_HMAC_MD5 },
- };
-
static struct db_attr espsha1_attr[] = {
{ AUTH_ALGORITHM, AUTH_ALGORITHM_HMAC_SHA1 },
};
-static struct db_attr ah_HMAC_MD5_attr[] = {
- { AUTH_ALGORITHM, AUTH_ALGORITHM_HMAC_MD5 },
- };
-
static struct db_attr ah_HMAC_SHA1_attr[] = {
{ AUTH_ALGORITHM, AUTH_ALGORITHM_HMAC_SHA1 },
};
@@ -213,7 +81,6 @@ static struct db_attr ah_HMAC_SHA1_attr[] = {
/* arrays of transforms, each in in preference order */
static struct db_trans espa_trans[] = {
- { ESP_3DES, AD(espmd5_attr) },
{ ESP_3DES, AD(espsha1_attr) },
};
@@ -223,13 +90,11 @@ static struct db_trans esp_trans[] = {
#ifdef SUPPORT_ESP_NULL
static struct db_trans espnull_trans[] = {
- { ESP_NULL, AD(espmd5_attr) },
{ ESP_NULL, AD(espsha1_attr) },
};
#endif /* SUPPORT_ESP_NULL */
static struct db_trans ah_trans[] = {
- { AH_MD5, AD(ah_HMAC_MD5_attr) },
{ AH_SHA, AD(ah_HMAC_SHA1_attr) },
};
@@ -452,7 +317,7 @@ out_sa(pb_stream *outs
proposal.isap_spisize = oakley_mode ? 0
: p->protoid == PROTO_IPCOMP ? IPCOMP_CPI_SIZE
: IPSEC_DOI_SPI_SIZE;
-
+
/* In quick mode ONLY, create proposal for runtime kernel algos.
* Replace ESP proposals with runtime created one
*/
@@ -503,7 +368,7 @@ out_sa(pb_stream *outs
return_on(ret, FALSE);
}
}
-
+
proposal.isap_notrans = p->trans_cnt;
if (!out_struct(&proposal, &isakmp_proposal_desc, &sa_pbs, &proposal_pbs))
return_on(ret, FALSE);
@@ -888,7 +753,9 @@ restore_pbs(pb_stream *pbs)
* Parse an ISAKMP Proposal Payload for RSA and PSK authentication policies
*/
notification_t
-parse_isakmp_policy(pb_stream *proposal_pbs, u_int notrans, lset_t *policy)
+parse_isakmp_policy(pb_stream *proposal_pbs
+ , u_int notrans
+ , lset_t *policy)
{
int last_transnum = -1;
@@ -945,6 +812,18 @@ parse_isakmp_policy(pb_stream *proposal_pbs, u_int notrans, lset_t *policy)
case OAKLEY_RSA_SIG:
*policy |= POLICY_RSASIG;
break;
+ case XAUTHInitPreShared:
+ *policy |= POLICY_XAUTH_SERVER;
+ /* fall through */
+ case XAUTHRespPreShared:
+ *policy |= POLICY_XAUTH_PSK;
+ break;
+ case XAUTHInitRSA:
+ *policy |= POLICY_XAUTH_SERVER;
+ /* fall through */
+ case XAUTHRespRSA:
+ *policy |= POLICY_XAUTH_RSASIG;
+ break;
default:
break;
}
@@ -954,23 +833,35 @@ parse_isakmp_policy(pb_stream *proposal_pbs, u_int notrans, lset_t *policy)
}
}
}
+ DBG(DBG_CONTROL|DBG_PARSING,
+ DBG_log("preparse_isakmp_policy: peer requests %s authentication"
+ , prettypolicy(*policy))
+ )
+ return NOTHING_WRONG;
+}
- if ((*policy & POLICY_PSK) && (*policy & POLICY_RSASIG))
- {
- DBG(DBG_CONTROL|DBG_PARSING,
- DBG_log("preparse_isakmp_policy: "
- "peer supports both PSK and RSASIG authentication")
- )
- *policy = LEMPTY;
- }
- else
+/*
+ * check that we can find a preshared secret
+ */
+static err_t
+find_preshared_key(struct state* st)
+{
+ err_t ugh = NULL;
+ struct connection *c = st->st_connection;
+
+ if (get_preshared_secret(c) == NULL)
{
- DBG(DBG_CONTROL|DBG_PARSING,
- DBG_log("preparse_isakmp_policy: peer requests %s authentication"
- , (*policy & POLICY_PSK) ? "PSK":"RSASIG")
- )
+ char my_id[BUF_LEN], his_id[BUF_LEN];
+
+ idtoa(&c->spd.this.id, my_id, sizeof(my_id));
+ if (his_id_was_instantiated(c))
+ strcpy(his_id, "%any");
+ else
+ idtoa(&c->spd.that.id, his_id, sizeof(his_id));
+ ugh = builddiag("Can't authenticate: no preshared key found for `%s' and `%s'"
+ , my_id, his_id);
}
- return NOTHING_WRONG;
+ return ugh;
}
/* Parse the body of an ISAKMP SA Payload (i.e. Phase 1 / Main Mode).
@@ -987,7 +878,8 @@ parse_isakmp_sa_body(u_int32_t ipsecdoisit
, pb_stream *proposal_pbs
, struct isakmp_proposal *proposal
, pb_stream *r_sa_pbs
- , struct state *st)
+ , struct state *st
+ , bool initiator)
{
struct connection *c = st->st_connection;
unsigned no_trans_left;
@@ -1093,6 +985,10 @@ parse_isakmp_sa_body(u_int32_t ipsecdoisit
/* check that authentication method is acceptable */
lset_t iap = st->st_policy & POLICY_ID_AUTH_MASK;
+ /* is the initiator the XAUTH client? */
+ bool xauth_init = initiator && (st->st_policy & POLICY_XAUTH_SERVER) == LEMPTY
+ || !initiator && (st->st_policy & POLICY_XAUTH_SERVER) != LEMPTY;
+
switch (val)
{
case OAKLEY_PRESHARED_KEY:
@@ -1102,23 +998,30 @@ parse_isakmp_sa_body(u_int32_t ipsecdoisit
}
else
{
- /* check that we can find a preshared secret */
- struct connection *c = st->st_connection;
-
- if (get_preshared_secret(c) == NULL)
- {
- char mid[BUF_LEN]
- , hid[BUF_LEN];
-
- idtoa(&c->spd.this.id, mid, sizeof(mid));
- if (his_id_was_instantiated(c))
- strcpy(hid, "%any");
- else
- idtoa(&c->spd.that.id, hid, sizeof(hid));
- ugh = builddiag("Can't authenticate: no preshared key found for `%s' and `%s'"
- , mid, hid);
- }
- ta.auth = val;
+ ugh = find_preshared_key(st);
+ ta.auth = OAKLEY_PRESHARED_KEY;
+ }
+ break;
+ case XAUTHInitPreShared:
+ if ((iap & POLICY_XAUTH_PSK) == LEMPTY || !xauth_init)
+ {
+ ugh = "policy does not allow XAUTHInitPreShared authentication";
+ }
+ else
+ {
+ ugh = find_preshared_key(st);
+ ta.auth = XAUTHInitPreShared;
+ }
+ break;
+ case XAUTHRespPreShared:
+ if ((iap & POLICY_XAUTH_PSK) == LEMPTY || xauth_init)
+ {
+ ugh = "policy does not allow XAUTHRespPreShared authentication";
+ }
+ else
+ {
+ ugh = find_preshared_key(st);
+ ta.auth = XAUTHRespPreShared;
}
break;
case OAKLEY_RSA_SIG:
@@ -1129,18 +1032,29 @@ parse_isakmp_sa_body(u_int32_t ipsecdoisit
}
else
{
- /* We'd like to check that we can find a public
- * key for him and a private key for us that is
- * suitable, but we don't yet have his
- * Id Payload, so it seems futile to try.
- * We can assume that if he proposes it, he
- * thinks we've got it. If we proposed it,
- * perhaps we know what we're doing.
- */
- ta.auth = val;
+ ta.auth = OAKLEY_RSA_SIG;
+ }
+ break;
+ case XAUTHInitRSA:
+ if ((iap & POLICY_XAUTH_RSASIG) == LEMPTY || !xauth_init)
+ {
+ ugh = "policy does not allow XAUTHInitRSA authentication";
+ }
+ else
+ {
+ ta.auth = XAUTHInitRSA;
+ }
+ break;
+ case XAUTHRespRSA:
+ if ((iap & POLICY_XAUTH_RSASIG) == LEMPTY || xauth_init)
+ {
+ ugh = "policy does not allow XAUTHRespRSA authentication";
+ }
+ else
+ {
+ ta.auth = XAUTHRespRSA;
}
break;
-
default:
ugh = builddiag("Pluto does not support %s authentication"
, enum_show(&oakley_auth_names, val));
@@ -1194,10 +1108,23 @@ parse_isakmp_sa_body(u_int32_t ipsecdoisit
{
case OAKLEY_LIFE_SECONDS:
if (val > OAKLEY_ISAKMP_SA_LIFETIME_MAXIMUM)
+ {
+#ifdef CISCO_QUIRKS
+ plog("peer requested %lu seconds"
+ " which exceeds our limit %d seconds"
+ , (long) val
+ , OAKLEY_ISAKMP_SA_LIFETIME_MAXIMUM);
+ plog("lifetime reduced to %d seconds "
+ "(todo: IPSEC_RESPONDER_LIFETIME notification)"
+ , OAKLEY_ISAKMP_SA_LIFETIME_MAXIMUM);
+ val = OAKLEY_ISAKMP_SA_LIFETIME_MAXIMUM;
+#else
ugh = builddiag("peer requested %lu seconds"
" which exceeds our limit %d seconds"
, (long) val
, OAKLEY_ISAKMP_SA_LIFETIME_MAXIMUM);
+#endif
+ }
ta.life_seconds = val;
break;
case OAKLEY_LIFE_KILOBYTES:
diff --git a/programs/pluto/spdb.h b/programs/pluto/spdb.h
index 5eebf86cf..6cb92f036 100644
--- a/programs/pluto/spdb.h
+++ b/programs/pluto/spdb.h
@@ -11,7 +11,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: spdb.h,v 1.4 2006/04/22 21:59:20 as Exp $
+ * RCSID $Id: spdb.h,v 1.5 2007/01/10 00:36:19 as Exp $
*/
#ifndef _SPDB_H
@@ -60,10 +60,8 @@ struct db_sa {
*/
};
-/* The oakley sadb is subscripted by a bitset with members
- * from POLICY_PSK and POLICY_RSASIG.
- */
-extern struct db_sa oakley_sadb[1 << 2];
+/* The oakley sadb */
+extern struct db_sa oakley_sadb;
/* The ipsec sadb is subscripted by a bitset with members
* from POLICY_ENCRYPT, POLICY_AUTHENTICATE, POLICY_COMPRESS
@@ -90,14 +88,15 @@ extern notification_t preparse_isakmp_sa_body(
extern notification_t parse_isakmp_policy(
pb_stream *proposal_pbs, /* body of proposal Payload */
u_int notrans, /* number of transforms */
- lset_t *policy); /* RSA or PSK policy */
+ lset_t *policy); /* RSA, PSK or XAUTH policy */
extern notification_t parse_isakmp_sa_body(
u_int32_t ipsecdoisit, /* IPsec DOI SIT bitset */
pb_stream *proposal_pbs, /* body of proposal Payload */
struct isakmp_proposal *proposal,
pb_stream *r_sa_pbs, /* if non-NULL, where to emit winning SA */
- struct state *st); /* current state object */
+ struct state *st, /* current state object */
+ bool initiator); /* is caller initiator? */
extern notification_t parse_ipsec_sa_body(
pb_stream *sa_pbs, /* body of input SA Payload */
diff --git a/programs/pluto/state.h b/programs/pluto/state.h
index c7212fd1a..d885d145d 100644
--- a/programs/pluto/state.h
+++ b/programs/pluto/state.h
@@ -12,7 +12,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: state.h,v 1.12 2006/10/17 10:30:54 as Exp $
+ * RCSID $Id: state.h,v 1.13 2007/01/10 00:36:19 as Exp $
*/
#include <sys/types.h>
@@ -212,7 +212,13 @@ struct state
bool vars_set;
bool started;
} st_modecfg;
-
+
+ struct {
+ int attempt;
+ bool started;
+ bool status;
+ } st_xauth;
+
#ifdef NAT_TRAVERSAL
u_int32_t nat_traversal;
ip_address nat_oa;
diff --git a/programs/pluto/vendor.c b/programs/pluto/vendor.c
index cbb26a5ef..3e2e0768a 100644
--- a/programs/pluto/vendor.c
+++ b/programs/pluto/vendor.c
@@ -11,7 +11,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: vendor.c,v 1.41 2006/10/19 15:21:08 as Exp $
+ * RCSID $Id: vendor.c,v 1.43 2007/01/10 00:31:36 as Exp $
*/
#include <stdlib.h>
@@ -164,6 +164,9 @@ static struct vid_struct _vid_tab[] = {
{ VID_CISCO3K, VID_KEEP | VID_SUBSTRING_MATCH,
NULL, "Cisco VPN 3000 Series" , "\x1f\x07\xf7\x0e\xaa\x65\x14\xd3\xb0\xfa\x96\x54\x2a\x50", 14},
+ { VID_CISCO_IOS, VID_KEEP | VID_SUBSTRING_MATCH,
+ NULL, "Cisco IOS Device", "\x3e\x98\x40\x48", 4},
+
/*
* Timestep VID seen:
* - 54494d455354455020312053475720313532302033313520322e303145303133
@@ -204,8 +207,10 @@ static struct vid_struct _vid_tab[] = {
DEC_MD5_VID(STRONGSWAN_4_0_3, "strongSwan 4.0.3")
DEC_MD5_VID(STRONGSWAN_4_0_4, "strongSwan 4.0.4")
DEC_MD5_VID(STRONGSWAN_4_0_5, "strongSwan 4.0.5")
+ DEC_MD5_VID(STRONGSWAN_4_0_6, "strongSwan 4.0.6")
- DEC_MD5_VID(STRONGSWAN, "strongSwan 2.8.0")
+ DEC_MD5_VID(STRONGSWAN, "strongSwan 2.8.1")
+ DEC_MD5_VID(STRONGSWAN_2_8_0, "strongSwan 2.8.0")
DEC_MD5_VID(STRONGSWAN_2_7_3, "strongSwan 2.7.3")
DEC_MD5_VID(STRONGSWAN_2_7_2, "strongSwan 2.7.2")
DEC_MD5_VID(STRONGSWAN_2_7_1, "strongSwan 2.7.1")
@@ -260,6 +265,12 @@ static struct vid_struct _vid_tab[] = {
DEC_MD5_VID(INITIAL_CONTACT, "Vid-Initial-Contact")
+ /**
+ * Cisco VPN 3000
+ */
+ { VID_MISC_FRAGMENTATION, VID_MD5HASH | VID_SUBSTRING_DUMPHEXA,
+ "FRAGMENTATION", NULL, NULL, 0 },
+
/* -- */
{ 0, 0, NULL, NULL, NULL, 0 }
@@ -386,6 +397,9 @@ handle_known_vendorid (struct msg_digest *md
md->dpd = TRUE;
vid_useful = TRUE;
break;
+ case VID_MISC_XAUTH:
+ vid_useful = TRUE;
+ break;
default:
break;
}
diff --git a/programs/pluto/vendor.h b/programs/pluto/vendor.h
index c7f70a480..060311b92 100644
--- a/programs/pluto/vendor.h
+++ b/programs/pluto/vendor.h
@@ -11,7 +11,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: vendor.h,v 1.36 2006/10/19 15:21:08 as Exp $
+ * RCSID $Id: vendor.h,v 1.38 2007/01/10 00:31:36 as Exp $
*/
#ifndef _VENDOR_H_
@@ -45,41 +45,43 @@ enum known_vendorid {
VID_SSH_IPSEC_4_2_0 = 24,
VID_CISCO_UNITY = 25,
VID_CISCO3K = 26,
- VID_TIMESTEP = 27,
- VID_SAFENET = 28,
- VID_MACOSX = 29,
- VID_OPENSWAN2 = 30,
- VID_NCP_SERVER = 31,
- VID_NCP_CLIENT = 32,
- VID_STRONGSWAN = 33,
- VID_STRONGSWAN_2_2_0 = 34,
- VID_STRONGSWAN_2_2_1 = 35,
- VID_STRONGSWAN_2_2_2 = 36,
- VID_STRONGSWAN_2_3_0 = 37,
- VID_STRONGSWAN_2_3_1 = 38,
- VID_STRONGSWAN_2_3_2 = 39,
- VID_STRONGSWAN_2_4_0 = 40,
- VID_STRONGSWAN_2_4_1 = 41,
- VID_STRONGSWAN_2_4_2 = 42,
- VID_STRONGSWAN_2_4_3 = 43,
- VID_STRONGSWAN_2_4_4 = 44,
- VID_STRONGSWAN_2_5_0 = 45,
- VID_STRONGSWAN_2_5_1 = 46,
- VID_STRONGSWAN_2_5_2 = 47,
- VID_STRONGSWAN_2_5_3 = 48,
- VID_STRONGSWAN_2_5_4 = 49,
- VID_STRONGSWAN_2_5_5 = 50,
- VID_STRONGSWAN_2_5_6 = 51,
- VID_STRONGSWAN_2_5_7 = 52,
- VID_STRONGSWAN_2_6_0 = 53,
- VID_STRONGSWAN_2_6_1 = 54,
- VID_STRONGSWAN_2_6_2 = 55,
- VID_STRONGSWAN_2_6_3 = 56,
- VID_STRONGSWAN_2_6_4 = 57,
- VID_STRONGSWAN_2_7_0 = 58,
- VID_STRONGSWAN_2_7_1 = 59,
- VID_STRONGSWAN_2_7_2 = 60,
- VID_STRONGSWAN_2_7_3 = 61,
+ VID_CISCO_IOS = 27,
+ VID_TIMESTEP = 28,
+ VID_SAFENET = 29,
+ VID_MACOSX = 30,
+ VID_OPENSWAN2 = 31,
+ VID_NCP_SERVER = 32,
+ VID_NCP_CLIENT = 33,
+ VID_STRONGSWAN = 34,
+ VID_STRONGSWAN_2_2_0 = 35,
+ VID_STRONGSWAN_2_2_1 = 36,
+ VID_STRONGSWAN_2_2_2 = 37,
+ VID_STRONGSWAN_2_3_0 = 38,
+ VID_STRONGSWAN_2_3_1 = 39,
+ VID_STRONGSWAN_2_3_2 = 40,
+ VID_STRONGSWAN_2_4_0 = 41,
+ VID_STRONGSWAN_2_4_1 = 42,
+ VID_STRONGSWAN_2_4_2 = 43,
+ VID_STRONGSWAN_2_4_3 = 44,
+ VID_STRONGSWAN_2_4_4 = 45,
+ VID_STRONGSWAN_2_5_0 = 46,
+ VID_STRONGSWAN_2_5_1 = 47,
+ VID_STRONGSWAN_2_5_2 = 48,
+ VID_STRONGSWAN_2_5_3 = 49,
+ VID_STRONGSWAN_2_5_4 = 50,
+ VID_STRONGSWAN_2_5_5 = 51,
+ VID_STRONGSWAN_2_5_6 = 52,
+ VID_STRONGSWAN_2_5_7 = 53,
+ VID_STRONGSWAN_2_6_0 = 54,
+ VID_STRONGSWAN_2_6_1 = 55,
+ VID_STRONGSWAN_2_6_2 = 56,
+ VID_STRONGSWAN_2_6_3 = 57,
+ VID_STRONGSWAN_2_6_4 = 58,
+ VID_STRONGSWAN_2_7_0 = 59,
+ VID_STRONGSWAN_2_7_1 = 60,
+ VID_STRONGSWAN_2_7_2 = 61,
+ VID_STRONGSWAN_2_7_3 = 62,
+ VID_STRONGSWAN_2_8_0 = 63,
VID_STRONGSWAN_4_0_0 = 70,
VID_STRONGSWAN_4_0_1 = 71,
@@ -87,6 +89,7 @@ enum known_vendorid {
VID_STRONGSWAN_4_0_3 = 73,
VID_STRONGSWAN_4_0_4 = 74,
VID_STRONGSWAN_4_0_5 = 75,
+ VID_STRONGSWAN_4_0_6 = 76,
/* 101 - 200 : NAT-Traversal */
VID_NATT_STENBERG_01 =101,
@@ -104,7 +107,8 @@ enum known_vendorid {
VID_MISC_DPD =202,
VID_MISC_HEARTBEAT_NOTIFY =203,
VID_MISC_FRAGMENTATION =204,
- VID_INITIAL_CONTACT =205
+ VID_INITIAL_CONTACT =205,
+ VID_CISCO3K_FRAGMENTATION =206
};
void init_vendorid(void);
diff --git a/programs/pluto/xauth.c b/programs/pluto/xauth.c
new file mode 100644
index 000000000..c33ad9b3d
--- /dev/null
+++ b/programs/pluto/xauth.c
@@ -0,0 +1,77 @@
+/* Initialization and finalization of the dynamic XAUTH module
+ * Copyright (C) 2006 Andreas Steffen
+ * Hochschule fuer Technik Rapperswil, Switzerland
+ *
+ * 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 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ *
+ * RCSID $Id: xauth.c,v 1.1 2007/01/11 21:48:41 as Exp $
+ */
+
+#include <dlfcn.h>
+
+#include <freeswan.h>
+
+#include "constants.h"
+#include "defs.h"
+#include "xauth.h"
+#include "keys.h"
+#include "log.h"
+
+void
+xauth_init(void)
+{
+#ifdef XAUTH_DEFAULT_LIB
+ xauth_module.handle = dlopen(XAUTH_DEFAULT_LIB, RTLD_NOW);
+
+ if (xauth_module.handle != NULL)
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("xauth module '%s' loading'", XAUTH_DEFAULT_LIB)
+ )
+ xauth_module.get_secret = (bool (*) (const xauth_t*))
+ dlsym(xauth_module.handle, "get_secret");
+ DBG(DBG_CONTROL,
+ if (xauth_module.get_secret != NULL)
+ {
+ DBG_log("xauth module: found get_secret() function");
+ }
+ )
+ xauth_module.verify_secret = (bool (*) (const xauth_t*))
+ dlsym(xauth_module.handle, "verify_secret");
+ DBG(DBG_CONTROL,
+ if (xauth_module.verify_secret != NULL)
+ {
+ DBG_log("xauth module: found verify_secret() function");
+ }
+ )
+ }
+#endif
+ /* any null function pointers will be filled in by default functions */
+ xauth_defaults();
+}
+
+void
+xauth_finalize(void)
+{
+ if (xauth_module.handle != NULL)
+ {
+ if (dlclose(xauth_module.handle))
+ {
+ plog("failed to unload xauth module");
+ }
+ else
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("xauth module unloaded")
+ )
+ }
+ }
+}
diff --git a/programs/pluto/xauth.h b/programs/pluto/xauth.h
new file mode 100644
index 000000000..371e443ef
--- /dev/null
+++ b/programs/pluto/xauth.h
@@ -0,0 +1,41 @@
+/* Interface definition of the XAUTH server and|or client module
+ * Copyright (C) 2006 Andreas Steffen
+ * Hochschule fuer Technik Rapperswil, Switzerland
+ *
+ * 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 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ *
+ * RCSID $Id: xauth.h,v 1.1 2007/01/11 21:48:41 as Exp $
+ */
+
+#ifndef _XAUTH_H
+#define _XAUTH_H
+
+/* XAUTH credentials */
+
+struct chunk_t;
+
+typedef struct {
+ chunk_t user_name;
+ chunk_t user_password;
+} xauth_t;
+
+typedef struct {
+ void *handle;
+ bool (*get_secret) (xauth_t *xauth_secret);
+ bool (*verify_secret) (const xauth_t *xauth_secret);
+} xauth_module_t;
+
+extern xauth_module_t xauth_module;
+
+extern void xauth_init(void);
+extern void xauth_finalize(void);
+
+#endif /* _XAUTH_H */