📄 demux.c
字号:
/* demultiplex incoming IKE messages * Copyright (C) 1997 Angelos D. Keromytis. * Copyright (C) 1998-2002 D. Hugh Redelmeier. * * 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: demux.c,v 1.187 2004/12/09 06:24:29 mcr Exp $ *//* Ordering Constraints on Payloads * * rfc2409: The Internet Key Exchange (IKE) * * 5 Exchanges: * "The SA payload MUST precede all other payloads in a phase 1 exchange." * * "Except where otherwise noted, there are no requirements for ISAKMP * payloads in any message to be in any particular order." * * 5.3 Phase 1 Authenticated With a Revised Mode of Public Key Encryption: * * "If the HASH payload is sent it MUST be the first payload of the * second message exchange and MUST be followed by the encrypted * nonce. If the HASH payload is not sent, the first payload of the * second message exchange MUST be the encrypted nonce." * * "Save the requirements on the location of the optional HASH payload * and the mandatory nonce payload there are no further payload * requirements. All payloads-- in whatever order-- following the * encrypted nonce MUST be encrypted with Ke_i or Ke_r depending on the * direction." * * 5.5 Phase 2 - Quick Mode * * "In Quick Mode, a HASH payload MUST immediately follow the ISAKMP * header and a SA payload MUST immediately follow the HASH." * [NOTE: there may be more than one SA payload, so this is not * totally reasonable. Probably all SAs should be so constrained.] * * "If ISAKMP is acting as a client negotiator on behalf of another * party, the identities of the parties MUST be passed as IDci and * then IDcr." * * "With the exception of the HASH, SA, and the optional ID payloads, * there are no payload ordering restrictions on Quick Mode." *//* Unfolding of Identity -- a central mystery * * This concerns Phase 1 identities, those of the IKE hosts. * These are the only ones that are authenticated. Phase 2 * identities are for IPsec SAs. * * There are three case of interest: * * (1) We initiate, based on a whack command specifying a Connection. * We know the identity of the peer from the Connection. * * (2) (to be implemented) we initiate based on a flow from our client * to some IP address. * We immediately know one of the peer's client IP addresses from * the flow. We must use this to figure out the peer's IP address * and Id. To be solved. * * (3) We respond to an IKE negotiation. * We immediately know the peer's IP address. * We get an ID Payload in Main I2. * * Unfortunately, this is too late for a number of things: * - the ISAKMP SA proposals have already been made (Main I1) * AND one accepted (Main R1) * - the SA includes a specification of the type of ID * authentication so this is negotiated without being told the ID. * - with Preshared Key authentication, Main I2 is encrypted * using the key, so it cannot be decoded to reveal the ID * without knowing (or guessing) which key to use. * * There are three reasonable choices here for the responder: * + assume that the initiator is making wise offers since it * knows the IDs involved. We can balk later (but not gracefully) * when we find the actual initiator ID * + attempt to infer identity by IP address. Again, we can balk * when the true identity is revealed. Actually, it is enough * to infer properties of the identity (eg. SA properties and * PSK, if needed). * + make all properties universal so discrimination based on * identity isn't required. For example, always accept the same * kinds of encryption. Accept Public Key Id authentication * since the Initiator presumably has our public key and thinks * we must have / can find his. This approach is weakest * for preshared key since the actual key must be known to * decrypt the Initiator's ID Payload. * These choices can be blended. For example, a class of Identities * can be inferred, sufficient to select a preshared key but not * sufficient to infer a unique identity. */#include <stdio.h>#include <stdlib.h>#include <stddef.h>#include <string.h>#include <unistd.h>#include <errno.h>#include <sys/types.h>#include <sys/time.h> /* only used for belt-and-suspenders select call */#include <sys/poll.h> /* only used for forensic poll call */#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <sys/queue.h>#if defined(IP_RECVERR) && defined(MSG_ERRQUEUE)# include <asm/types.h> /* for __u8, __u32 */# include <linux/errqueue.h># include <sys/uio.h> /* struct iovec */#endif#include <openswan.h>#include "constants.h"#include "oswlog.h"#include "defs.h"#include "cookie.h"#include "id.h"#include "x509.h"#include "pgp.h"#include "certs.h"#include "smartcard.h"#ifdef XAUTH_USEPAM#include <security/pam_appl.h>#endif#include "connections.h" /* needs id.h */#include "state.h"#include "packet.h"#include "md5.h"#include "sha1.h"#include "crypto.h" /* requires sha1.h and md5.h */#include "ike_alg.h"#include "log.h"#include "demux.h" /* needs packet.h */#include "ipsec_doi.h" /* needs demux.h and state.h */#include "timer.h"#include "whack.h" /* requires connections.h */#include "server.h"#ifdef XAUTH#include "xauth.h"#endif#ifdef NAT_TRAVERSAL#include "nat_traversal.h"#endif#include "vendor.h"/* This file does basic header checking and demux of * incoming packets. *//* forward declarations */static bool read_packet(struct msg_digest *md);static void process_packet(struct msg_digest **mdp);/* Reply messages are built in this buffer. * Only one state transition function can be using it at a time * so suspended STFs must save and restore it. * It could be an auto variable of complete_state_transition except for the fact * that when a suspended STF resumes, its reply message buffer * must be at the same location -- there are pointers into it. */u_int8_t reply_buffer[MAX_OUTPUT_UDP_SIZE];/* state_microcode is a tuple of information parameterizing certain * centralized processing of a packet. For example, it roughly * specifies what payloads are expected in this message. * The microcode is selected primarily based on the state. * In Phase 1, the payload structure often depends on the * authentication technique, so that too plays a part in selecting * the state_microcode to use. */struct state_microcode { enum state_kind state, next_state; lset_t flags; lset_t req_payloads; /* required payloads (allows just one) */ lset_t opt_payloads; /* optional payloads (any mumber) */ /* if not ISAKMP_NEXT_NONE, process_packet will emit HDR with this as np */ u_int8_t first_out_payload; enum event_type timeout_event; state_transition_fn *processor;};/* State Microcode Flags, in several groups *//* Oakley Auth values: to which auth values does this entry apply? * Most entries will use SMF_ALL_AUTH because they apply to all. * Note: SMF_ALL_AUTH matches 0 for those circumstances when no auth * has been set. */#define SMF_ALL_AUTH LRANGE(0, OAKLEY_AUTH_ROOF-1)#define SMF_PSK_AUTH LELEM(OAKLEY_PRESHARED_KEY)#define SMF_DS_AUTH (LELEM(OAKLEY_DSS_SIG) | LELEM(OAKLEY_RSA_SIG))#define SMF_PKE_AUTH (LELEM(OAKLEY_RSA_ENC) | LELEM(OAKLEY_ELGAMAL_ENC))#define SMF_RPKE_AUTH (LELEM(OAKLEY_RSA_ENC_REV) | LELEM(OAKLEY_ELGAMAL_ENC_REV))/* misc flags */#define SMF_INITIATOR LELEM(OAKLEY_AUTH_ROOF + 0)#define SMF_FIRST_ENCRYPTED_INPUT LELEM(OAKLEY_AUTH_ROOF + 1)#define SMF_INPUT_ENCRYPTED LELEM(OAKLEY_AUTH_ROOF + 2)#define SMF_OUTPUT_ENCRYPTED LELEM(OAKLEY_AUTH_ROOF + 3)#define SMF_RETRANSMIT_ON_DUPLICATE LELEM(OAKLEY_AUTH_ROOF + 4)#define SMF_ENCRYPTED (SMF_INPUT_ENCRYPTED | SMF_OUTPUT_ENCRYPTED)/* this state generates a reply message */#define SMF_REPLY LELEM(OAKLEY_AUTH_ROOF + 5)/* this state completes P1, so any pending P2 negotiations should start */#define SMF_RELEASE_PENDING_P2 LELEM(OAKLEY_AUTH_ROOF + 6)/* if we have canoncalized the authentication from XAUTH mode */#define SMF_XAUTH_AUTH LELEM(OAKLEY_AUTH_ROOF + 7)/* end of flags */static state_transition_fn /* forward declaration */ unexpected, informational;/* state_microcode_table is a table of all state_microcode tuples. * It must be in order of state (the first element). * After initialization, ike_microcode_index[s] points to the * first entry in state_microcode_table for state s. * Remember that each state name in Main or Quick Mode describes * what has happened in the past, not what this message is. */static const struct state_microcode *ike_microcode_index[STATE_IKE_ROOF - STATE_IKE_FLOOR];static const struct state_microcode state_microcode_table[] = {#define PT(n) ISAKMP_NEXT_##n#define P(n) LELEM(PT(n)) /***** Phase 1 Main Mode *****/ /* No state for main_outI1: --> HDR, SA */ /* STATE_MAIN_R0: I1 --> R1 * HDR, SA --> HDR, SA */ { STATE_MAIN_R0, STATE_MAIN_R1 , SMF_ALL_AUTH | SMF_REPLY , P(SA), P(VID) | P(CR), PT(NONE) , EVENT_RETRANSMIT, main_inI1_outR1}, /* STATE_MAIN_I1: R1 --> I2 * HDR, SA --> auth dependent * SMF_PSK_AUTH, SMF_DS_AUTH: --> HDR, KE, Ni * SMF_PKE_AUTH: * --> HDR, KE, [ HASH(1), ] <IDi1_b>PubKey_r, <Ni_b>PubKey_r * SMF_RPKE_AUTH: * --> HDR, [ HASH(1), ] <Ni_b>Pubkey_r, <KE_b>Ke_i, <IDi1_b>Ke_i [,<<Cert-I_b>Ke_i] * Note: since we don't know auth at start, we cannot differentiate * microcode entries based on it. */ { STATE_MAIN_I1, STATE_MAIN_I2 , SMF_ALL_AUTH | SMF_INITIATOR | SMF_REPLY , P(SA), P(VID) | P(CR), PT(NONE) /* don't know yet */ , EVENT_RETRANSMIT, main_inR1_outI2 }, /* STATE_MAIN_R1: I2 --> R2 * SMF_PSK_AUTH, SMF_DS_AUTH: HDR, KE, Ni --> HDR, KE, Nr * SMF_PKE_AUTH: HDR, KE, [ HASH(1), ] <IDi1_b>PubKey_r, <Ni_b>PubKey_r * --> HDR, KE, <IDr1_b>PubKey_i, <Nr_b>PubKey_i * SMF_RPKE_AUTH: * HDR, [ HASH(1), ] <Ni_b>Pubkey_r, <KE_b>Ke_i, <IDi1_b>Ke_i [,<<Cert-I_b>Ke_i] * --> HDR, <Nr_b>PubKey_i, <KE_b>Ke_r, <IDr1_b>Ke_r */ { STATE_MAIN_R1, STATE_MAIN_R2 , SMF_PSK_AUTH | SMF_DS_AUTH | SMF_REPLY#ifdef NAT_TRAVERSAL , P(KE) | P(NONCE), P(VID) | P(CR) | P(NATD_RFC), PT(KE)#else , P(KE) | P(NONCE), P(VID) | P(CR), PT(KE)#endif , EVENT_RETRANSMIT, main_inI2_outR2 }, { STATE_MAIN_R1, STATE_UNDEFINED , SMF_PKE_AUTH | SMF_REPLY , P(KE) | P(ID) | P(NONCE), P(VID) | P(CR) | P(HASH), PT(KE) , EVENT_RETRANSMIT, unexpected /* ??? not yet implemented */ }, { STATE_MAIN_R1, STATE_UNDEFINED , SMF_RPKE_AUTH | SMF_REPLY , P(NONCE) | P(KE) | P(ID), P(VID) | P(CR) | P(HASH) | P(CERT), PT(NONCE) , EVENT_RETRANSMIT, unexpected /* ??? not yet implemented */ }, /* for states from here on, output message must be encrypted */ /* STATE_MAIN_I2: R2 --> I3 * SMF_PSK_AUTH: HDR, KE, Nr --> HDR*, IDi1, HASH_I * SMF_DS_AUTH: HDR, KE, Nr --> HDR*, IDi1, [ CERT, ] SIG_I * SMF_PKE_AUTH: HDR, KE, <IDr1_b>PubKey_i, <Nr_b>PubKey_i * --> HDR*, HASH_I * SMF_RPKE_AUTH: HDR, <Nr_b>PubKey_i, <KE_b>Ke_r, <IDr1_b>Ke_r * --> HDR*, HASH_I */ { STATE_MAIN_I2, STATE_MAIN_I3 , SMF_PSK_AUTH | SMF_DS_AUTH | SMF_INITIATOR | SMF_OUTPUT_ENCRYPTED | SMF_REPLY#ifdef NAT_TRAVERSAL , P(KE) | P(NONCE), P(VID) | P(CR) | P(NATD_RFC), PT(ID)#else , P(KE) | P(NONCE), P(VID) | P(CR), PT(ID)#endif , EVENT_RETRANSMIT, main_inR2_outI3 }, { STATE_MAIN_I2, STATE_UNDEFINED , SMF_PKE_AUTH | SMF_INITIATOR | SMF_OUTPUT_ENCRYPTED | SMF_REPLY , P(KE) | P(ID) | P(NONCE), P(VID) | P(CR), PT(HASH) , EVENT_RETRANSMIT, unexpected /* ??? not yet implemented */ }, { STATE_MAIN_I2, STATE_UNDEFINED , SMF_ALL_AUTH | SMF_INITIATOR | SMF_OUTPUT_ENCRYPTED | SMF_REPLY , P(NONCE) | P(KE) | P(ID), P(VID) | P(CR), PT(HASH) , EVENT_RETRANSMIT, unexpected /* ??? not yet implemented */ }, /* for states from here on, input message must be encrypted */ /* STATE_MAIN_R2: I3 --> R3 * SMF_PSK_AUTH: HDR*, IDi1, HASH_I --> HDR*, IDr1, HASH_R * SMF_DS_AUTH: HDR*, IDi1, [ CERT, ] SIG_I --> HDR*, IDr1, [ CERT, ] SIG_R * SMF_PKE_AUTH, SMF_RPKE_AUTH: HDR*, HASH_I --> HDR*, HASH_R */ { STATE_MAIN_R2, STATE_MAIN_R3 , SMF_PSK_AUTH | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED | SMF_REPLY | SMF_RELEASE_PENDING_P2 , P(ID) | P(HASH), P(VID) | P(CR), PT(NONE) , EVENT_SA_REPLACE, main_inI3_outR3 }, { STATE_MAIN_R2, STATE_MAIN_R3 , SMF_DS_AUTH | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED | SMF_REPLY | SMF_RELEASE_PENDING_P2 , P(ID) | P(SIG), P(VID) | P(CR) | P(CERT), PT(NONE) , EVENT_SA_REPLACE, main_inI3_outR3 }, { STATE_MAIN_R2, STATE_UNDEFINED , SMF_PKE_AUTH | SMF_RPKE_AUTH | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED | SMF_REPLY | SMF_RELEASE_PENDING_P2 , P(HASH), P(VID) | P(CR), PT(NONE) , EVENT_SA_REPLACE, unexpected /* ??? not yet implemented */ }, /* STATE_MAIN_I3: R3 --> done * SMF_PSK_AUTH: HDR*, IDr1, HASH_R --> done * SMF_DS_AUTH: HDR*, IDr1, [ CERT, ] SIG_R --> done * SMF_PKE_AUTH, SMF_RPKE_AUTH: HDR*, HASH_R --> done * May initiate quick mode by calling quick_outI1 */ { STATE_MAIN_I3, STATE_MAIN_I4 , SMF_PSK_AUTH | SMF_INITIATOR | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2 , P(ID) | P(HASH), P(VID) | P(CR), PT(NONE) , EVENT_SA_REPLACE, main_inR3 }, { STATE_MAIN_I3, STATE_MAIN_I4 , SMF_DS_AUTH | SMF_INITIATOR | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2 , P(ID) | P(SIG), P(VID) | P(CR) | P(CERT), PT(NONE) , EVENT_SA_REPLACE, main_inR3 }, { STATE_MAIN_I3, STATE_UNDEFINED , SMF_PKE_AUTH | SMF_RPKE_AUTH | SMF_INITIATOR | SMF_FIRST_ENCRYPTED_INPUT | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2 , P(HASH), P(VID) | P(CR), PT(NONE) , EVENT_SA_REPLACE, unexpected /* ??? not yet implemented */ }, /* STATE_MAIN_R3: can only get here due to packet loss */ { STATE_MAIN_R3, STATE_UNDEFINED , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_RETRANSMIT_ON_DUPLICATE , LEMPTY, LEMPTY , PT(NONE), EVENT_NULL, unexpected }, /* STATE_MAIN_I4: can only get here due to packet loss */ { STATE_MAIN_I4, STATE_UNDEFINED , SMF_ALL_AUTH | SMF_INITIATOR | SMF_ENCRYPTED , LEMPTY, LEMPTY , PT(NONE), EVENT_NULL, unexpected }, /***** Phase 1 Aggressive Mode *****/ /* No state for aggr_outI1: -->HDR, SA, KE, Ni, IDii */ /* STATE_AGGR_R0: * SMF_PSK_AUTH: HDR, SA, KE, Ni, IDii * --> HDR, SA, KE, Nr, IDir, HASH_R * SMF_DS_AUTH: HDR, KE, Nr, SIG --> HDR*, IDi1, HASH_I */ { STATE_AGGR_R0, STATE_AGGR_R1, SMF_PSK_AUTH| SMF_REPLY, P(SA) | P(KE) | P(NONCE) | P(ID), P(VID), PT(NONE), EVENT_RETRANSMIT, aggr_inI1_outR1_psk }, { STATE_AGGR_R0, STATE_AGGR_R1, SMF_DS_AUTH | SMF_REPLY, P(SA) | P(KE) | P(NONCE) | P(ID), P(VID), PT(NONE), EVENT_RETRANSMIT, aggr_inI1_outR1_rsasig }, /* STATE_AGGR_I1: * SMF_PSK_AUTH: HDR, SA, KE, Nr, IDir, HASH_R * --> HDR*, HASH_I * SMF_DS_AUTH: HDR, SA, KE, Nr, IDir, SIG_R * --> HDR*, SIG_I */ { STATE_AGGR_I1, STATE_AGGR_I2, SMF_PSK_AUTH | SMF_INITIATOR | SMF_OUTPUT_ENCRYPTED | SMF_REPLY | SMF_RELEASE_PENDING_P2, P(SA) | P(KE) | P(NONCE) | P(ID) | P(HASH), P(VID) | P(NATD_RFC) , PT(NONE), EVENT_SA_REPLACE, aggr_inR1_outI2 }, { STATE_AGGR_I1, STATE_AGGR_I2, SMF_DS_AUTH | SMF_INITIATOR | SMF_OUTPUT_ENCRYPTED | SMF_REPLY | SMF_RELEASE_PENDING_P2, P(SA) | P(KE) | P(NONCE) | P(ID) | P(SIG), P(VID) | P(NATD_RFC) , PT(NONE),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -