diff options
Diffstat (limited to 'programs')
29 files changed, 1903 insertions, 852 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 */ diff --git a/programs/starter/args.c b/programs/starter/args.c index 2b2853a20..9dece2dfb 100644 --- a/programs/starter/args.c +++ b/programs/starter/args.c @@ -12,7 +12,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * RCSID $Id: args.c,v 1.10 2006/10/19 14:58:30 as Exp $ + * RCSID $Id: args.c,v 1.11 2007/01/11 21:27:27 as Exp $ */ #include <stddef.h> @@ -192,6 +192,7 @@ static const token_info_t token_info[] = { ARG_TIME, offsetof(starter_conn_t, dpd_timeout), NULL }, { ARG_ENUM, offsetof(starter_conn_t, dpd_action), LST_dpd_action }, { ARG_MISC, 0, NULL /* KW_MODECONFIG */ }, + { ARG_MISC, 0, NULL /* KW_XAUTH */ }, /* ca section keywords */ { ARG_STR, offsetof(starter_ca_t, name), NULL }, diff --git a/programs/starter/confread.c b/programs/starter/confread.c index edd041ab4..63010685b 100644 --- a/programs/starter/confread.c +++ b/programs/starter/confread.c @@ -11,7 +11,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * RCSID $Id: confread.c,v 1.39 2006/10/19 14:58:30 as Exp $ + * RCSID $Id: confread.c,v 1.40 2007/01/11 21:27:27 as Exp $ */ #include <stddef.h> @@ -418,7 +418,7 @@ load_conn(starter_conn_t *conn, kw_list_t *kw, starter_config_t *cfg) KW_POLICY_FLAG("ah", "esp", POLICY_AUTHENTICATE) break; case KW_AUTHBY: - conn->policy &= ~(POLICY_RSASIG | POLICY_PSK | POLICY_ENCRYPT); + conn->policy &= ~(POLICY_ID_AUTH_MASK | POLICY_ENCRYPT); if (strcmp(kw->value, "never") != 0) { @@ -433,8 +433,12 @@ load_conn(starter_conn_t *conn, kw_list_t *kw, starter_config_t *cfg) { if (streq(value, "rsasig")) conn->policy |= POLICY_RSASIG | POLICY_ENCRYPT; - else if (streq(value, "secret")) + else if (streq(value, "secret") || streq(value, "psk")) conn->policy |= POLICY_PSK | POLICY_ENCRYPT; + else if (streq(value, "xauthrsasig")) + conn->policy |= POLICY_XAUTH_RSASIG | POLICY_ENCRYPT; + else if (streq(value, "xauthpsk")) + conn->policy |= POLICY_XAUTH_PSK | POLICY_ENCRYPT; else { plog("# bad policy value: %s=%s", kw->entry->name, kw->value); @@ -454,6 +458,9 @@ load_conn(starter_conn_t *conn, kw_list_t *kw, starter_config_t *cfg) case KW_MODECONFIG: KW_POLICY_FLAG("push", "pull", POLICY_MODECFG_PUSH) break; + case KW_XAUTH: + KW_POLICY_FLAG("server", "client", POLICY_XAUTH_SERVER) + break; default: break; } diff --git a/programs/starter/keywords.c b/programs/starter/keywords.c index 75be0a542..b06ee3c0c 100644 --- a/programs/starter/keywords.c +++ b/programs/starter/keywords.c @@ -44,7 +44,7 @@ error "gperf generated tables don't work with this execution character set. Plea * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * RCSID $Id: keywords.c,v 1.8 2006/10/19 14:58:30 as Exp $ + * RCSID $Id: keywords.c,v 1.9 2007/01/11 21:29:28 as Exp $ */ #include <string.h> @@ -56,7 +56,7 @@ struct kw_entry { kw_token_t token; }; -#define TOTAL_KEYWORDS 80 +#define TOTAL_KEYWORDS 81 #define MIN_WORD_LENGTH 3 #define MAX_WORD_LENGTH 17 #define MIN_HASH_VALUE 9 @@ -87,7 +87,7 @@ hash (str, len) 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 90, 157, 60, - 50, 25, 0, 10, 5, 65, 157, 65, 70, 5, + 50, 25, 0, 10, 30, 65, 157, 65, 70, 5, 0, 75, 35, 157, 10, 20, 5, 70, 157, 157, 157, 55, 0, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, @@ -114,7 +114,7 @@ static const struct kw_entry wordlist[] = {"leftupdown", KW_LEFTUPDOWN}, {""}, {""}, {"leftcert", KW_LEFTCERT,}, - {"auth", KW_AUTH}, + {""}, {"leftsubnet", KW_LEFTSUBNET}, {"leftsubnetwithin", KW_LEFTSUBNETWITHIN}, {"leftsendcert", KW_LEFTSENDCERT}, @@ -135,7 +135,9 @@ static const struct kw_entry wordlist[] = {"compress", KW_COMPRESS}, {"lefthostaccess", KW_LEFTHOSTACCESS}, {"interfaces", KW_INTERFACES}, - {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, + {"auth", KW_AUTH}, + {""}, {"rightgroups", KW_RIGHTGROUPS}, {""}, {"pfs", KW_PFS}, @@ -198,7 +200,7 @@ static const struct kw_entry wordlist[] = {"crluri2", KW_CRLURI2}, {"ldaphost", KW_LDAPHOST}, {"postpluto", KW_POSTPLUTO}, - {""}, + {"xauth", KW_XAUTH}, {"overridemtu", KW_OVERRIDEMTU}, {"rightca", KW_RIGHTCA}, {"prepluto", KW_PREPLUTO}, diff --git a/programs/starter/keywords.h b/programs/starter/keywords.h index be3aabf3b..4356b4947 100644 --- a/programs/starter/keywords.h +++ b/programs/starter/keywords.h @@ -12,7 +12,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * RCSID $Id: keywords.h,v 1.9 2006/10/19 14:57:56 as Exp $ + * RCSID $Id: keywords.h,v 1.10 2007/01/11 21:27:27 as Exp $ */ #ifndef _KEYWORDS_H_ @@ -77,9 +77,10 @@ typedef enum { KW_DPDTIMEOUT, KW_DPDACTION, KW_MODECONFIG, + KW_XAUTH, #define KW_CONN_FIRST KW_CONN_SETUP -#define KW_CONN_LAST KW_MODECONFIG +#define KW_CONN_LAST KW_XAUTH /* ca section keywords */ KW_CA_NAME, diff --git a/programs/starter/keywords.txt b/programs/starter/keywords.txt index fc9e49e47..6ad2d5fce 100644 --- a/programs/starter/keywords.txt +++ b/programs/starter/keywords.txt @@ -13,7 +13,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * RCSID $Id: keywords.txt,v 1.7 2006/10/19 14:57:56 as Exp $ + * RCSID $Id: keywords.txt,v 1.8 2007/01/11 21:27:51 as Exp $ */ #include <string.h> @@ -66,6 +66,7 @@ dpddelay, KW_DPDDELAY dpdtimeout, KW_DPDTIMEOUT dpdaction, KW_DPDACTION modeconfig, KW_MODECONFIG +xauth, KW_XAUTH cacert, KW_CACERT ldaphost, KW_LDAPHOST ldapbase, KW_LDAPBASE diff --git a/programs/starter/lex.yy.c b/programs/starter/lex.yy.c index 1626f1050..2c0dd040a 100644 --- a/programs/starter/lex.yy.c +++ b/programs/starter/lex.yy.c @@ -497,7 +497,7 @@ char *yytext; * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * RCSID $Id: lex.yy.c,v 1.4 2006/03/28 22:32:49 as Exp $ + * RCSID $Id: lex.yy.c,v 1.6 2007/01/14 18:37:25 as Exp $ */ #include <string.h> @@ -1706,10 +1706,10 @@ YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) * @note If you want to scan bytes that may contain NUL values, then use * yy_scan_bytes() instead. */ -YY_BUFFER_STATE yy_scan_string (yyconst char * __yystr ) +YY_BUFFER_STATE yy_scan_string (yyconst char * yystr ) { - return yy_scan_bytes(__yystr,strlen(__yystr) ); + return yy_scan_bytes(yystr,strlen(yystr) ); } /** Setup the input buffer state to scan the given bytes. The next call to yylex() will diff --git a/programs/starter/parser.tab.c b/programs/starter/parser.tab.c index bc21a2fd3..6e0061f89 100644 --- a/programs/starter/parser.tab.c +++ b/programs/starter/parser.tab.c @@ -1,7 +1,9 @@ -/* A Bison parser, made by GNU Bison 2.1. */ +/* A Bison parser, made by GNU Bison 2.2. */ -/* Skeleton parser for Yacc-like parsing with Bison, - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. +/* Skeleton implementation 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 it under the terms of the GNU General Public License as published by @@ -18,13 +20,21 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -/* As a special exception, when this file is copied by Bison into a - Bison output file, you may use that output file without restriction. - This special exception was added by the Free Software Foundation - in version 1.24 of Bison. */ +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + 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. */ -/* Written by Richard Stallman by simplifying the original so called - ``semantic'' parser. */ +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ /* All symbols defined below should begin with yy or YY, to avoid infringing on user name space. This should be done even for local @@ -37,7 +47,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "2.1" +#define YYBISON_VERSION "2.2" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -99,7 +109,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * RCSID $Id: parser.tab.c,v 1.5 2006/03/28 22:32:49 as Exp $ + * RCSID $Id: parser.tab.c,v 1.7 2007/01/14 18:37:25 as Exp $ */ #include <stdio.h> @@ -158,11 +168,13 @@ extern kw_entry_t *in_word_set (char *str, unsigned int len); # define YYTOKEN_TABLE 0 #endif -#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef union YYSTYPE #line 56 "parser.y" -typedef union YYSTYPE { char *s; } YYSTYPE; -/* Line 196 of yacc.c. */ -#line 166 "parser.tab.c" +{ char *s; } +/* Line 193 of yacc.c. */ +#line 177 "parser.tab.c" + YYSTYPE; # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 # define YYSTYPE_IS_TRIVIAL 1 @@ -173,23 +185,56 @@ typedef union YYSTYPE { char *s; } YYSTYPE; /* Copy the second part of user declarations. */ -/* Line 219 of yacc.c. */ -#line 178 "parser.tab.c" +/* Line 216 of yacc.c. */ +#line 190 "parser.tab.c" -#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) -# define YYSIZE_T __SIZE_TYPE__ +#ifdef short +# undef short #endif -#if ! defined (YYSIZE_T) && defined (size_t) -# define YYSIZE_T size_t + +#ifdef YYTYPE_UINT8 +typedef YYTYPE_UINT8 yytype_uint8; +#else +typedef unsigned char yytype_uint8; #endif -#if ! defined (YYSIZE_T) && (defined (__STDC__) || defined (__cplusplus)) -# include <stddef.h> /* INFRINGES ON USER NAME SPACE */ -# define YYSIZE_T size_t + +#ifdef YYTYPE_INT8 +typedef YYTYPE_INT8 yytype_int8; +#elif (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +typedef signed char yytype_int8; +#else +typedef short int yytype_int8; #endif -#if ! defined (YYSIZE_T) -# define YYSIZE_T unsigned int + +#ifdef YYTYPE_UINT16 +typedef YYTYPE_UINT16 yytype_uint16; +#else +typedef unsigned short int yytype_uint16; +#endif + +#ifdef YYTYPE_INT16 +typedef YYTYPE_INT16 yytype_int16; +#else +typedef short int yytype_int16; +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include <stddef.h> /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned int +# endif #endif +#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) + #ifndef YY_ # if YYENABLE_NLS # if ENABLE_NLS @@ -202,7 +247,32 @@ typedef union YYSTYPE { char *s; } YYSTYPE; # endif #endif -#if ! defined (yyoverflow) || YYERROR_VERBOSE +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YYUSE(e) ((void) (e)) +#else +# define YYUSE(e) /* empty */ +#endif + +/* Identity function, used to suppress warnings about constant conditions. */ +#ifndef lint +# define YYID(n) (n) +#else +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static int +YYID (int i) +#else +static int +YYID (i) + int i; +#endif +{ + return i; +} +#endif + +#if ! defined yyoverflow || YYERROR_VERBOSE /* The parser invokes alloca or malloc; define the necessary symbols. */ @@ -210,64 +280,76 @@ typedef union YYSTYPE { char *s; } YYSTYPE; # if YYSTACK_USE_ALLOCA # ifdef __GNUC__ # define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include <alloca.h> /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include <malloc.h> /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca # else # define YYSTACK_ALLOC alloca -# if defined (__STDC__) || defined (__cplusplus) +# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) # include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ -# define YYINCLUDED_STDLIB_H +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif # endif # endif # endif # endif # ifdef YYSTACK_ALLOC - /* Pacify GCC's `empty if-body' warning. */ -# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) # ifndef YYSTACK_ALLOC_MAXIMUM /* The OS might guarantee only one guard page at the bottom of the stack, and a page size can be as small as 4096 bytes. So we cannot safely invoke alloca (N) if N exceeds 4096. Use a slightly smaller number to allow for a few compiler-allocated temporary stack slots. */ -# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2005 */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ # endif # else # define YYSTACK_ALLOC YYMALLOC # define YYSTACK_FREE YYFREE # ifndef YYSTACK_ALLOC_MAXIMUM -# define YYSTACK_ALLOC_MAXIMUM ((YYSIZE_T) -1) +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM # endif -# ifdef __cplusplus -extern "C" { +# if (defined __cplusplus && ! defined _STDLIB_H \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif # endif # ifndef YYMALLOC # define YYMALLOC malloc -# if (! defined (malloc) && ! defined (YYINCLUDED_STDLIB_H) \ - && (defined (__STDC__) || defined (__cplusplus))) +# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free -# if (! defined (free) && ! defined (YYINCLUDED_STDLIB_H) \ - && (defined (__STDC__) || defined (__cplusplus))) +# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif # endif -# ifdef __cplusplus -} -# endif # endif -#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */ +#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ -#if (! defined (yyoverflow) \ - && (! defined (__cplusplus) \ - || (defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL))) +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union yyalloc { - short int yyss; + yytype_int16 yyss; YYSTYPE yyvs; }; @@ -277,13 +359,13 @@ union yyalloc /* The size of an array large to enough to hold all stacks, each with N elements. */ # define YYSTACK_BYTES(N) \ - ((N) * (sizeof (short int) + sizeof (YYSTYPE)) \ + ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + YYSTACK_GAP_MAXIMUM) /* Copy COUNT objects from FROM to TO. The source and destination do not overlap. */ # ifndef YYCOPY -# if defined (__GNUC__) && 1 < __GNUC__ +# if defined __GNUC__ && 1 < __GNUC__ # define YYCOPY(To, From, Count) \ __builtin_memcpy (To, From, (Count) * sizeof (*(From))) # else @@ -294,7 +376,7 @@ union yyalloc for (yyi = 0; yyi < (Count); yyi++) \ (To)[yyi] = (From)[yyi]; \ } \ - while (0) + while (YYID (0)) # endif # endif @@ -312,28 +394,22 @@ union yyalloc yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ yyptr += yynewbytes / sizeof (*yyptr); \ } \ - while (0) + while (YYID (0)) #endif -#if defined (__STDC__) || defined (__cplusplus) - typedef signed char yysigned_char; -#else - typedef short int yysigned_char; -#endif - -/* YYFINAL -- State number of the termination state. */ +/* YYFINAL -- State number of the termination state. */ #define YYFINAL 2 /* YYLAST -- Last index in YYTABLE. */ #define YYLAST 27 -/* YYNTOKENS -- Number of terminals. */ +/* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 13 -/* YYNNTS -- Number of nonterminals. */ +/* YYNNTS -- Number of nonterminals. */ #define YYNNTS 9 -/* YYNRULES -- Number of rules. */ +/* YYNRULES -- Number of rules. */ #define YYNRULES 18 -/* YYNRULES -- Number of states. */ +/* YYNRULES -- Number of states. */ #define YYNSTATES 34 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ @@ -344,7 +420,7 @@ union yyalloc ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) /* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ -static const unsigned char yytranslate[] = +static const yytype_uint8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -378,14 +454,14 @@ static const unsigned char yytranslate[] = #if YYDEBUG /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in YYRHS. */ -static const unsigned char yyprhs[] = +static const yytype_uint8 yyprhs[] = { 0, 0, 3, 6, 7, 11, 12, 18, 19, 25, 26, 32, 33, 38, 40, 45, 46, 50, 53 }; -/* YYRHS -- A `-1'-separated list of the rules' RHS. */ -static const yysigned_char yyrhs[] = +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const yytype_int8 yyrhs[] = { 14, 0, -1, 14, 15, -1, -1, 11, 12, 5, -1, -1, 6, 7, 5, 16, 20, -1, -1, 8, @@ -396,7 +472,7 @@ static const yysigned_char yyrhs[] = }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ -static const unsigned char yyrline[] = +static const yytype_uint8 yyrline[] = { 0, 67, 67, 68, 72, 77, 76, 82, 81, 99, 98, 115, 114, 120, 124, 125, 129, 154, 158 @@ -405,7 +481,7 @@ static const unsigned char yyrline[] = #if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. - First, the terminals, then, starting at YYNTOKENS, nonterminals. */ + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { "$end", "error", "$undefined", "EQUAL", "FIRST_SPACES", "EOL", "CONFIG", @@ -418,7 +494,7 @@ static const char *const yytname[] = # ifdef YYPRINT /* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to token YYLEX-NUM. */ -static const unsigned short int yytoknum[] = +static const yytype_uint16 yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267 @@ -426,14 +502,14 @@ static const unsigned short int yytoknum[] = # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ -static const unsigned char yyr1[] = +static const yytype_uint8 yyr1[] = { 0, 13, 14, 14, 15, 16, 15, 17, 15, 18, 15, 19, 15, 15, 20, 20, 21, 21, 21 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ -static const unsigned char yyr2[] = +static const yytype_uint8 yyr2[] = { 0, 2, 2, 0, 3, 0, 5, 0, 5, 0, 5, 0, 4, 1, 4, 0, 3, 2, 0 @@ -442,7 +518,7 @@ static const unsigned char yyr2[] = /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state STATE-NUM when YYTABLE doesn't specify something else to do. Zero means the default is an error. */ -static const unsigned char yydefact[] = +static const yytype_uint8 yydefact[] = { 3, 0, 1, 13, 0, 0, 0, 0, 0, 2, 0, 0, 0, 11, 0, 5, 7, 9, 0, 4, @@ -450,8 +526,8 @@ static const unsigned char yydefact[] = 17, 15, 16, 14 }; -/* YYDEFGOTO[NTERM-NUM]. */ -static const yysigned_char yydefgoto[] = +/* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int8 yydefgoto[] = { -1, 1, 9, 20, 21, 22, 18, 25, 29 }; @@ -459,7 +535,7 @@ static const yysigned_char yydefgoto[] = /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ #define YYPACT_NINF -20 -static const yysigned_char yypact[] = +static const yytype_int8 yypact[] = { -20, 0, -20, -20, -6, -8, -5, 1, 2, -20, 10, 11, 12, -20, 13, -20, -20, -20, 14, -20, @@ -468,7 +544,7 @@ static const yysigned_char yypact[] = }; /* YYPGOTO[NTERM-NUM]. */ -static const yysigned_char yypgoto[] = +static const yytype_int8 yypgoto[] = { -20, -20, -20, -20, -20, -20, -20, -19, -20 }; @@ -478,14 +554,14 @@ static const yysigned_char yypgoto[] = number is the opposite. If zero, do what YYDEFACT says. If YYTABLE_NINF, syntax error. */ #define YYTABLE_NINF -1 -static const unsigned char yytable[] = +static const yytype_uint8 yytable[] = { 2, 10, 26, 27, 11, 3, 4, 12, 5, 6, 7, 8, 33, 13, 14, 15, 16, 17, 19, 23, 24, 28, 30, 31, 0, 0, 0, 32 }; -static const yysigned_char yycheck[] = +static const yytype_int8 yycheck[] = { 0, 7, 21, 22, 12, 5, 6, 12, 8, 9, 10, 11, 31, 12, 12, 5, 5, 5, 5, 5, @@ -494,7 +570,7 @@ static const yysigned_char yycheck[] = /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ -static const unsigned char yystos[] = +static const yytype_uint8 yystos[] = { 0, 14, 0, 5, 6, 8, 9, 10, 11, 15, 7, 12, 12, 12, 12, 5, 5, 5, 19, 5, @@ -527,7 +603,7 @@ do \ yychar = (Token); \ yylval = (Value); \ yytoken = YYTRANSLATE (yychar); \ - YYPOPSTACK; \ + YYPOPSTACK (1); \ goto yybackup; \ } \ else \ @@ -535,7 +611,7 @@ do \ yyerror (YY_("syntax error: cannot back up")); \ YYERROR; \ } \ -while (0) +while (YYID (0)) #define YYTERROR 1 @@ -550,7 +626,7 @@ while (0) #ifndef YYLLOC_DEFAULT # define YYLLOC_DEFAULT(Current, Rhs, N) \ do \ - if (N) \ + if (YYID (N)) \ { \ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ @@ -564,7 +640,7 @@ while (0) (Current).first_column = (Current).last_column = \ YYRHSLOC (Rhs, 0).last_column; \ } \ - while (0) + while (YYID (0)) #endif @@ -576,8 +652,8 @@ while (0) # if YYLTYPE_IS_TRIVIAL # define YY_LOCATION_PRINT(File, Loc) \ fprintf (File, "%d.%d-%d.%d", \ - (Loc).first_line, (Loc).first_column, \ - (Loc).last_line, (Loc).last_column) + (Loc).first_line, (Loc).first_column, \ + (Loc).last_line, (Loc).last_column) # else # define YY_LOCATION_PRINT(File, Loc) ((void) 0) # endif @@ -604,36 +680,96 @@ while (0) do { \ if (yydebug) \ YYFPRINTF Args; \ -} while (0) +} while (YYID (0)) -# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ -do { \ - if (yydebug) \ - { \ - YYFPRINTF (stderr, "%s ", Title); \ - yysymprint (stderr, \ - Type, Value); \ - YYFPRINTF (stderr, "\n"); \ - } \ -} while (0) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (YYID (0)) + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_value_print (FILE *yyoutput, int yytype, const YYSTYPE * const yyvaluep) +#else +static void +yy_symbol_value_print (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + const YYSTYPE * const yyvaluep; +#endif +{ + if (!yyvaluep) + return; +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# else + YYUSE (yyoutput); +# endif + switch (yytype) + { + default: + break; + } +} + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_print (FILE *yyoutput, int yytype, const YYSTYPE * const yyvaluep) +#else +static void +yy_symbol_print (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + const YYSTYPE * const yyvaluep; +#endif +{ + if (yytype < YYNTOKENS) + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); + else + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + + yy_symbol_value_print (yyoutput, yytype, yyvaluep); + YYFPRINTF (yyoutput, ")"); +} /*------------------------------------------------------------------. | yy_stack_print -- Print the state stack from its BOTTOM up to its | | TOP (included). | `------------------------------------------------------------------*/ -#if defined (__STDC__) || defined (__cplusplus) +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) static void -yy_stack_print (short int *bottom, short int *top) +yy_stack_print (yytype_int16 *bottom, yytype_int16 *top) #else static void yy_stack_print (bottom, top) - short int *bottom; - short int *top; + yytype_int16 *bottom; + yytype_int16 *top; #endif { YYFPRINTF (stderr, "Stack now"); - for (/* Nothing. */; bottom <= top; ++bottom) + for (; bottom <= top; ++bottom) YYFPRINTF (stderr, " %d", *bottom); YYFPRINTF (stderr, "\n"); } @@ -642,37 +778,48 @@ yy_stack_print (bottom, top) do { \ if (yydebug) \ yy_stack_print ((Bottom), (Top)); \ -} while (0) +} while (YYID (0)) /*------------------------------------------------. | Report that the YYRULE is going to be reduced. | `------------------------------------------------*/ -#if defined (__STDC__) || defined (__cplusplus) +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) static void -yy_reduce_print (int yyrule) +yy_reduce_print (YYSTYPE *yyvsp, + int yyrule) #else static void -yy_reduce_print (yyrule) - int yyrule; +yy_reduce_print (yyvsp, yyrule + ) + YYSTYPE *yyvsp; + + int yyrule; #endif { + int yynrhs = yyr2[yyrule]; int yyi; unsigned long int yylno = yyrline[yyrule]; - YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu), ", - yyrule - 1, yylno); - /* Print the symbols being reduced, and their result. */ - for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++) - YYFPRINTF (stderr, "%s ", yytname[yyrhs[yyi]]); - YYFPRINTF (stderr, "-> %s\n", yytname[yyr1[yyrule]]); + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + fprintf (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], + &(yyvsp[(yyi + 1) - (yynrhs)]) + ); + fprintf (stderr, "\n"); + } } # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug) \ - yy_reduce_print (Rule); \ -} while (0) + yy_reduce_print (yyvsp, Rule); \ +} while (YYID (0)) /* Nonzero means print parse trace. It is left uninitialized so that multiple parsers can coexist. */ @@ -706,42 +853,44 @@ int yydebug; #if YYERROR_VERBOSE # ifndef yystrlen -# if defined (__GLIBC__) && defined (_STRING_H) +# if defined __GLIBC__ && defined _STRING_H # define yystrlen strlen # else /* Return the length of YYSTR. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) static YYSIZE_T -# if defined (__STDC__) || defined (__cplusplus) yystrlen (const char *yystr) -# else +#else +static YYSIZE_T yystrlen (yystr) - const char *yystr; -# endif + const char *yystr; +#endif { - const char *yys = yystr; - - while (*yys++ != '\0') + YYSIZE_T yylen; + for (yylen = 0; yystr[yylen]; yylen++) continue; - - return yys - yystr - 1; + return yylen; } # endif # endif # ifndef yystpcpy -# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE) +# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE # define yystpcpy stpcpy # else /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in YYDEST. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) static char * -# if defined (__STDC__) || defined (__cplusplus) yystpcpy (char *yydest, const char *yysrc) -# else +#else +static char * yystpcpy (yydest, yysrc) - char *yydest; - const char *yysrc; -# endif + char *yydest; + const char *yysrc; +#endif { char *yyd = yydest; const char *yys = yysrc; @@ -767,7 +916,7 @@ yytnamerr (char *yyres, const char *yystr) { if (*yystr == '"') { - size_t yyn = 0; + YYSIZE_T yyn = 0; char const *yyp = yystr; for (;;) @@ -802,53 +951,123 @@ yytnamerr (char *yyres, const char *yystr) } # endif -#endif /* YYERROR_VERBOSE */ - - - -#if YYDEBUG -/*--------------------------------. -| Print this symbol on YYOUTPUT. | -`--------------------------------*/ - -#if defined (__STDC__) || defined (__cplusplus) -static void -yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep) -#else -static void -yysymprint (yyoutput, yytype, yyvaluep) - FILE *yyoutput; - int yytype; - YYSTYPE *yyvaluep; -#endif +/* Copy into YYRESULT an error message about the unexpected token + YYCHAR while in state YYSTATE. Return the number of bytes copied, + including the terminating null byte. If YYRESULT is null, do not + copy anything; just return the number of bytes that would be + copied. As a special case, return 0 if an ordinary "syntax error" + message will do. Return YYSIZE_MAXIMUM if overflow occurs during + size calculation. */ +static YYSIZE_T +yysyntax_error (char *yyresult, int yystate, int yychar) { - /* Pacify ``unused variable'' warnings. */ - (void) yyvaluep; + int yyn = yypact[yystate]; - if (yytype < YYNTOKENS) - YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); + if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) + return 0; else - YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + { + int yytype = YYTRANSLATE (yychar); + YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + int yysize_overflow = 0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + int yyx; + +# if 0 + /* This is so xgettext sees the translatable formats that are + constructed on the fly. */ + YY_("syntax error, unexpected %s"); + YY_("syntax error, unexpected %s, expecting %s"); + YY_("syntax error, unexpected %s, expecting %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); +# endif + char *yyfmt; + char const *yyf; + static char const yyunexpected[] = "syntax error, unexpected %s"; + static char const yyexpecting[] = ", expecting %s"; + static char const yyor[] = " or %s"; + char yyformat[sizeof yyunexpected + + sizeof yyexpecting - 1 + + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) + * (sizeof yyor - 1))]; + char const *yyprefix = yyexpecting; + + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yycount = 1; + + yyarg[0] = yytname[yytype]; + yyfmt = yystpcpy (yyformat, yyunexpected); + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + yyformat[sizeof yyunexpected - 1] = '\0'; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + yyfmt = yystpcpy (yyfmt, yyprefix); + yyprefix = yyor; + } + yyf = YY_(yyformat); + yysize1 = yysize + yystrlen (yyf); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; -# ifdef YYPRINT - if (yytype < YYNTOKENS) - YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); -# endif - switch (yytype) - { - default: - break; + if (yysize_overflow) + return YYSIZE_MAXIMUM; + + if (yyresult) + { + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + char *yyp = yyresult; + int yyi = 0; + while ((*yyp = *yyf) != '\0') + { + if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyf += 2; + } + else + { + yyp++; + yyf++; + } + } + } + return yysize; } - YYFPRINTF (yyoutput, ")"); } +#endif /* YYERROR_VERBOSE */ + -#endif /* ! YYDEBUG */ /*-----------------------------------------------. | Release the memory associated to this symbol. | `-----------------------------------------------*/ -#if defined (__STDC__) || defined (__cplusplus) +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) static void yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) #else @@ -859,8 +1078,7 @@ yydestruct (yymsg, yytype, yyvaluep) YYSTYPE *yyvaluep; #endif { - /* Pacify ``unused variable'' warnings. */ - (void) yyvaluep; + YYUSE (yyvaluep); if (!yymsg) yymsg = "Deleting"; @@ -870,7 +1088,7 @@ yydestruct (yymsg, yytype, yyvaluep) { default: - break; + break; } } @@ -878,13 +1096,13 @@ yydestruct (yymsg, yytype, yyvaluep) /* Prevent warnings from -Wmissing-prototypes. */ #ifdef YYPARSE_PARAM -# if defined (__STDC__) || defined (__cplusplus) +#if defined __STDC__ || defined __cplusplus int yyparse (void *YYPARSE_PARAM); -# else +#else int yyparse (); -# endif +#endif #else /* ! YYPARSE_PARAM */ -#if defined (__STDC__) || defined (__cplusplus) +#if defined __STDC__ || defined __cplusplus int yyparse (void); #else int yyparse (); @@ -909,20 +1127,24 @@ int yynerrs; `----------*/ #ifdef YYPARSE_PARAM -# if defined (__STDC__) || defined (__cplusplus) -int yyparse (void *YYPARSE_PARAM) -# else -int yyparse (YYPARSE_PARAM) - void *YYPARSE_PARAM; -# endif +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void *YYPARSE_PARAM) +#else +int +yyparse (YYPARSE_PARAM) + void *YYPARSE_PARAM; +#endif #else /* ! YYPARSE_PARAM */ -#if defined (__STDC__) || defined (__cplusplus) +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) int yyparse (void) #else int yyparse () - ; + #endif #endif { @@ -934,6 +1156,12 @@ yyparse () int yyerrstatus; /* Look-ahead token as an internal (translated) token number. */ int yytoken = 0; +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +#endif /* Three stacks and their tools: `yyss': related to states, @@ -944,9 +1172,9 @@ yyparse () to reallocate them elsewhere. */ /* The state stack. */ - short int yyssa[YYINITDEPTH]; - short int *yyss = yyssa; - short int *yyssp; + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss = yyssa; + yytype_int16 *yyssp; /* The semantic value stack. */ YYSTYPE yyvsa[YYINITDEPTH]; @@ -955,7 +1183,7 @@ yyparse () -#define YYPOPSTACK (yyvsp--, yyssp--) +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) YYSIZE_T yystacksize = YYINITDEPTH; @@ -964,9 +1192,9 @@ yyparse () YYSTYPE yyval; - /* When reducing, the number of symbols on the RHS of the reduced - rule. */ - int yylen; + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; YYDPRINTF ((stderr, "Starting parse\n")); @@ -990,8 +1218,7 @@ yyparse () `------------------------------------------------------------*/ yynewstate: /* In all cases, when you get here, the value and location stacks - have just been pushed. so pushing a state here evens the stacks. - */ + have just been pushed. So pushing a state here evens the stacks. */ yyssp++; yysetstate: @@ -1004,11 +1231,11 @@ yyparse () #ifdef yyoverflow { - /* Give user a chance to reallocate the stack. Use copies of + /* Give user a chance to reallocate the stack. Use copies of these so that the &'s don't force the real ones into memory. */ YYSTYPE *yyvs1 = yyvs; - short int *yyss1 = yyss; + yytype_int16 *yyss1 = yyss; /* Each stack pointer address is followed by the size of the @@ -1036,7 +1263,7 @@ yyparse () yystacksize = YYMAXDEPTH; { - short int *yyss1 = yyss; + yytype_int16 *yyss1 = yyss; union yyalloc *yyptr = (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); if (! yyptr) @@ -1071,12 +1298,10 @@ yyparse () `-----------*/ yybackup: -/* Do appropriate processing given the current state. */ -/* Read a look-ahead token if we need one and don't already have one. */ -/* yyresume: */ + /* Do appropriate processing given the current state. Read a + look-ahead token if we need one and don't already have one. */ /* First try to decide what to do without reference to look-ahead token. */ - yyn = yypact[yystate]; if (yyn == YYPACT_NINF) goto yydefault; @@ -1118,22 +1343,21 @@ yybackup: if (yyn == YYFINAL) YYACCEPT; + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + /* Shift the look-ahead token. */ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); - /* Discard the token being shifted unless it is eof. */ + /* Discard the shifted token unless it is eof. */ if (yychar != YYEOF) yychar = YYEMPTY; + yystate = yyn; *++yyvsp = yylval; - - /* Count tokens shifted since error; after three, turn off error - status. */ - if (yyerrstatus) - yyerrstatus--; - - yystate = yyn; goto yynewstate; @@ -1171,7 +1395,7 @@ yyreduce: case 4: #line 73 "parser.y" { - free((yyvsp[-1].s)); + free((yyvsp[(2) - (3)].s)); ;} break; @@ -1189,7 +1413,7 @@ yyreduce: section_list_t *section = (section_list_t *)alloc_thing(section_list_t , "section_list_t"); - section->name = clone_str((yyvsp[-1].s), "conn section name"); + section->name = clone_str((yyvsp[(2) - (3)].s), "conn section name"); section->kw = NULL; section->next = NULL; _parser_kw = &(section->kw); @@ -1199,7 +1423,7 @@ yyreduce: _parser_cfg->conn_last->next = section; _parser_cfg->conn_last = section; _parser_kw_last = NULL; - free((yyvsp[-1].s)); + free((yyvsp[(2) - (3)].s)); ;} break; @@ -1208,7 +1432,7 @@ yyreduce: { section_list_t *section = (section_list_t *)alloc_thing(section_list_t , "section_list_t"); - section->name = clone_str((yyvsp[-1].s), "ca section name"); + section->name = clone_str((yyvsp[(2) - (3)].s), "ca section name"); section->kw = NULL; section->next = NULL; _parser_kw = &(section->kw); @@ -1218,7 +1442,7 @@ yyreduce: _parser_cfg->ca_last->next = section; _parser_cfg->ca_last = section; _parser_kw_last = NULL; - free((yyvsp[-1].s)); + free((yyvsp[(2) - (3)].s)); ;} break; @@ -1226,8 +1450,8 @@ yyreduce: #line 115 "parser.y" { extern void _parser_y_include (const char *f); - _parser_y_include((yyvsp[0].s)); - free((yyvsp[0].s)); + _parser_y_include((yyvsp[(2) - (2)].s)); + free((yyvsp[(2) - (2)].s)); ;} break; @@ -1235,18 +1459,18 @@ yyreduce: #line 130 "parser.y" { kw_list_t *new; - kw_entry_t *entry = in_word_set((yyvsp[-2].s), strlen((yyvsp[-2].s))); + kw_entry_t *entry = in_word_set((yyvsp[(1) - (3)].s), strlen((yyvsp[(1) - (3)].s))); if (entry == NULL) { - snprintf(errbuf, ERRSTRING_LEN, "unknown keyword '%s'", (yyvsp[-2].s)); + snprintf(errbuf, ERRSTRING_LEN, "unknown keyword '%s'", (yyvsp[(1) - (3)].s)); yyerror(errbuf); } else if (_parser_kw) { new = (kw_list_t *)alloc_thing(kw_list_t, "kw_list_t"); new->entry = entry; - new->value = clone_str((yyvsp[0].s), "kw_list value"); + new->value = clone_str((yyvsp[(3) - (3)].s), "kw_list value"); new->next = NULL; if (_parser_kw_last) _parser_kw_last->next = new; @@ -1254,29 +1478,27 @@ yyreduce: if (!*_parser_kw) *_parser_kw = new; } - free((yyvsp[-2].s)); - free((yyvsp[0].s)); + free((yyvsp[(1) - (3)].s)); + free((yyvsp[(3) - (3)].s)); ;} break; case 17: #line 155 "parser.y" { - free((yyvsp[-1].s)); + free((yyvsp[(1) - (2)].s)); ;} break; +/* Line 1267 of yacc.c. */ +#line 1496 "parser.tab.c" default: break; } + YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); -/* Line 1126 of yacc.c. */ -#line 1275 "parser.tab.c" - - yyvsp -= yylen; - yyssp -= yylen; - - + YYPOPSTACK (yylen); + yylen = 0; YY_STACK_PRINT (yyss, yyssp); *++yyvsp = yyval; @@ -1305,110 +1527,41 @@ yyerrlab: if (!yyerrstatus) { ++yynerrs; -#if YYERROR_VERBOSE - yyn = yypact[yystate]; - - if (YYPACT_NINF < yyn && yyn < YYLAST) - { - int yytype = YYTRANSLATE (yychar); - YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); - YYSIZE_T yysize = yysize0; - YYSIZE_T yysize1; - int yysize_overflow = 0; - char *yymsg = 0; -# define YYERROR_VERBOSE_ARGS_MAXIMUM 5 - char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; - int yyx; - -#if 0 - /* This is so xgettext sees the translatable formats that are - constructed on the fly. */ - YY_("syntax error, unexpected %s"); - YY_("syntax error, unexpected %s, expecting %s"); - YY_("syntax error, unexpected %s, expecting %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); -#endif - char *yyfmt; - char const *yyf; - static char const yyunexpected[] = "syntax error, unexpected %s"; - static char const yyexpecting[] = ", expecting %s"; - static char const yyor[] = " or %s"; - char yyformat[sizeof yyunexpected - + sizeof yyexpecting - 1 - + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) - * (sizeof yyor - 1))]; - char const *yyprefix = yyexpecting; - - /* Start YYX at -YYN if negative to avoid negative indexes in - YYCHECK. */ - int yyxbegin = yyn < 0 ? -yyn : 0; - - /* Stay within bounds of both yycheck and yytname. */ - int yychecklim = YYLAST - yyn; - int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; - int yycount = 1; - - yyarg[0] = yytname[yytype]; - yyfmt = yystpcpy (yyformat, yyunexpected); - - for (yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) +#if ! YYERROR_VERBOSE + yyerror (YY_("syntax error")); +#else + { + YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); + if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) + { + YYSIZE_T yyalloc = 2 * yysize; + if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) + yyalloc = YYSTACK_ALLOC_MAXIMUM; + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yyalloc); + if (yymsg) + yymsg_alloc = yyalloc; + else { - if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) - { - yycount = 1; - yysize = yysize0; - yyformat[sizeof yyunexpected - 1] = '\0'; - break; - } - yyarg[yycount++] = yytname[yyx]; - yysize1 = yysize + yytnamerr (0, yytname[yyx]); - yysize_overflow |= yysize1 < yysize; - yysize = yysize1; - yyfmt = yystpcpy (yyfmt, yyprefix); - yyprefix = yyor; + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; } + } - yyf = YY_(yyformat); - yysize1 = yysize + yystrlen (yyf); - yysize_overflow |= yysize1 < yysize; - yysize = yysize1; - - if (!yysize_overflow && yysize <= YYSTACK_ALLOC_MAXIMUM) - yymsg = (char *) YYSTACK_ALLOC (yysize); - if (yymsg) - { - /* Avoid sprintf, as that infringes on the user's name space. - Don't have undefined behavior even if the translation - produced a string with the wrong number of "%s"s. */ - char *yyp = yymsg; - int yyi = 0; - while ((*yyp = *yyf)) - { - if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) - { - yyp += yytnamerr (yyp, yyarg[yyi++]); - yyf += 2; - } - else - { - yyp++; - yyf++; - } - } - yyerror (yymsg); - YYSTACK_FREE (yymsg); - } - else - { - yyerror (YY_("syntax error")); + if (0 < yysize && yysize <= yymsg_alloc) + { + (void) yysyntax_error (yymsg, yystate, yychar); + yyerror (yymsg); + } + else + { + yyerror (YY_("syntax error")); + if (yysize != 0) goto yyexhaustedlab; - } - } - else -#endif /* YYERROR_VERBOSE */ - yyerror (YY_("syntax error")); + } + } +#endif } @@ -1419,14 +1572,15 @@ yyerrlab: error, discard it. */ if (yychar <= YYEOF) - { + { /* Return failure if at end of input. */ if (yychar == YYEOF) YYABORT; - } + } else { - yydestruct ("Error: discarding", yytoken, &yylval); + yydestruct ("Error: discarding", + yytoken, &yylval); yychar = YYEMPTY; } } @@ -1444,11 +1598,14 @@ yyerrorlab: /* Pacify compilers like GCC when the user code never invokes YYERROR and the label yyerrorlab therefore never appears in user code. */ - if (0) + if (/*CONSTCOND*/ 0) goto yyerrorlab; -yyvsp -= yylen; - yyssp -= yylen; + /* Do not reclaim the symbols of the rule which action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); yystate = *yyssp; goto yyerrlab1; @@ -1478,8 +1635,9 @@ yyerrlab1: YYABORT; - yydestruct ("Error: popping", yystos[yystate], yyvsp); - YYPOPSTACK; + yydestruct ("Error: popping", + yystos[yystate], yyvsp); + YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); } @@ -1490,7 +1648,7 @@ yyerrlab1: *++yyvsp = yylval; - /* Shift the error token. */ + /* Shift the error token. */ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); yystate = yyn; @@ -1525,16 +1683,24 @@ yyreturn: if (yychar != YYEOF && yychar != YYEMPTY) yydestruct ("Cleanup: discarding lookahead", yytoken, &yylval); + /* Do not reclaim the symbols of the rule which action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); while (yyssp != yyss) { yydestruct ("Cleanup: popping", yystos[*yyssp], yyvsp); - YYPOPSTACK; + YYPOPSTACK (1); } #ifndef yyoverflow if (yyss != yyssa) YYSTACK_FREE (yyss); #endif +#if YYERROR_VERBOSE + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); +#endif return yyresult; } diff --git a/programs/starter/parser.tab.h b/programs/starter/parser.tab.h index 1ded28fdb..b6a810f51 100644 --- a/programs/starter/parser.tab.h +++ b/programs/starter/parser.tab.h @@ -1,7 +1,9 @@ -/* A Bison parser, made by GNU Bison 2.1. */ +/* A Bison parser, made by GNU Bison 2.2. */ -/* Skeleton parser for Yacc-like parsing with Bison, - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. +/* 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 it under the terms of the GNU General Public License as published by @@ -18,10 +20,18 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -/* As a special exception, when this file is copied by Bison into a - Bison output file, you may use that output file without restriction. - This special exception was added by the Free Software Foundation - in version 1.24 of Bison. */ +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + 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 @@ -56,11 +66,13 @@ -#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef union YYSTYPE #line 56 "parser.y" -typedef union YYSTYPE { char *s; } YYSTYPE; -/* Line 1447 of yacc.c. */ -#line 64 "parser.tab.h" +{ char *s; } +/* Line 1528 of yacc.c. */ +#line 75 "parser.tab.h" + YYSTYPE; # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 # define YYSTYPE_IS_TRIVIAL 1 @@ -68,5 +80,3 @@ typedef union YYSTYPE { char *s; } YYSTYPE; extern YYSTYPE yylval; - - |