⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 demux.c

📁 This a good VPN source
💻 C
📖 第 1 页 / 共 5 页
字号:
	    }	    else if(st->st_connection->spd.this.xauth_client		    && st->st_state == STATE_XAUTH_I1)	    {	        /*		 * in this case, we got a new MODECFG message after I0, maybe		 * because it wants to start over again.		 */		from_state = STATE_XAUTH_I0;	    }	    else if(st->st_connection->spd.this.modecfg_server		    && IS_PHASE1(st->st_state))	    {		from_state = STATE_MODE_CFG_R0;	    }	    else if(st->st_connection->spd.this.modecfg_client		    && IS_PHASE1(st->st_state))	    {		from_state = STATE_MODE_CFG_R1;	    }	    else {		/* XXX check if we are being a mode config server here */		openswan_log("received MODECFG message when in state %s, and we aren't xauth client"		     , enum_name(&state_names, st->st_state));		return;	    }	}	else	{	    if(st->st_connection->spd.this.xauth_server	       && IS_PHASE1(st->st_state))	/* Switch from Phase1 to Mode Config */	    {		openswan_log("We were in phase 1, with no state, so we went to XAUTH_R0");		st->st_state = STATE_XAUTH_R0;	    }	    /* otherweise, this is fine, we continue in the state we are in */	    set_cur_state(st);	    from_state = st->st_state;	}	break;#endif#ifdef NOTYET    case ISAKMP_XCHG_NGRP:    case ISAKMP_XCHG_ACK_INFO:#endif    default:	openswan_log("unsupported exchange type %s in message"	    , enum_show(&exchange_names, md->hdr.isa_xchg));	SEND_NOTIFICATION(UNSUPPORTED_EXCHANGE_TYPE);	return;    }    /* We have found a from_state, and perhaps a state object.     * If we need to build a new state object,     * we wait until the packet has been sanity checked.     */    /* We don't support the Commit Flag.  It is such a bad feature.     * It isn't protected -- neither encrypted nor authenticated.     * A man in the middle turns it on, leading to DoS.     * We just ignore it, with a warning.     * By placing the check here, we could easily add a policy bit     * to a connection to suppress the warning.  This might be useful     * because the Commit Flag is expected from some peers.     */    if (md->hdr.isa_flags & ISAKMP_FLAG_COMMIT)    {	openswan_log("IKE message has the Commit Flag set but Pluto doesn't implement this feature; ignoring flag");    }    /* Set smc to describe this state's properties.     * Look up the appropriate microcode based on state and     * possibly Oakley Auth type.     */    passert(STATE_IKE_FLOOR <= from_state && from_state <= STATE_IKE_ROOF);    smc = ike_microcode_index[from_state - STATE_IKE_FLOOR];    if (st != NULL)    {      oakley_auth_t baseauth = xauth_calcbaseauth(st->st_oakley.auth);      while (!LHAS(smc->flags, baseauth))	{	  smc++;	  passert(smc->state == from_state);	}    }    /* Ignore a packet if the state has a suspended state transition     * Probably a duplicated packet but the original packet is not yet     * recorded in st->st_rpacket, so duplicate checking won't catch.     * ??? Should the packet be recorded earlier to improve diagnosis?     */    if (st != NULL && st->st_suspended_md != NULL)    {	loglog(RC_LOG, "discarding packet received during DNS lookup in %s"	    , enum_name(&state_names, st->st_state));	return;    }    /* Detect and handle duplicated packets.     * This won't work for the initial packet of an exchange     * because we won't have a state object to remember it.     * If we are in a non-receiving state (terminal), and the preceding     * state did transmit, then the duplicate may indicate that that     * transmission wasn't received -- retransmit it.     * Otherwise, just discard it.     * ??? Notification packets are like exchanges -- I hope that     * they are idempotent!     */    if (st != NULL    && st->st_rpacket.ptr != NULL    && st->st_rpacket.len == pbs_room(&md->packet_pbs)    && memcmp(st->st_rpacket.ptr, md->packet_pbs.start, st->st_rpacket.len) == 0)    {	if (smc->flags & SMF_RETRANSMIT_ON_DUPLICATE)	{	    if (st->st_retransmit < MAXIMUM_RETRANSMISSIONS)	    {		st->st_retransmit++;		loglog(RC_RETRANSMISSION		    , "retransmitting in response to duplicate packet; already %s"		    , enum_name(&state_names, st->st_state));		send_packet(st, "retransmit in response to duplicate");	    }	    else	    {		loglog(RC_LOG_SERIOUS, "discarding duplicate packet -- exhausted retransmission; already %s"		    , enum_name(&state_names, st->st_state));	    }	}	else	{	    loglog(RC_LOG_SERIOUS, "discarding duplicate packet; already %s"		, enum_name(&state_names, st->st_state));	}	return;    }    if (md->hdr.isa_flags & ISAKMP_FLAG_ENCRYPTION)    {	DBG(DBG_CRYPT, DBG_log("received encrypted packet from %s:%u"	    , ip_str(&md->sender), (unsigned)md->sender_port));	if (st == NULL)	{	    openswan_log("discarding encrypted message for an unknown ISAKMP SA");	    SEND_NOTIFICATION(PAYLOAD_MALFORMED /* XXX ? */);	    return;	}	if (st->st_skeyid_e.ptr == (u_char *) NULL)	{	    loglog(RC_LOG_SERIOUS, "discarding encrypted message"		" because we haven't yet negotiated keying materiel");	    SEND_NOTIFICATION(INVALID_FLAGS);	    return;	}	/* Mark as encrypted */	md->encrypted = TRUE;	DBG(DBG_CRYPT, DBG_log("decrypting %u bytes using algorithm %s"	    , (unsigned) pbs_left(&md->message_pbs)	    , enum_show(&oakley_enc_names, st->st_oakley.encrypt)));	/* do the specified decryption	 *	 * IV is from st->st_iv or (if new_iv_set) st->st_new_iv.	 * The new IV is placed in st->st_new_iv	 *	 * See RFC 2409 "IKE" Appendix B	 *	 * XXX The IV should only be updated really if the packet	 * is successfully processed.	 * We should keep this value, check for a success return	 * value from the parsing routines and then replace.	 *	 * Each post phase 1 exchange generates IVs from	 * the last phase 1 block, not the last block sent.	 */	{	    const struct encrypt_desc *e = st->st_oakley.encrypter;	    if (pbs_left(&md->message_pbs) % e->enc_blocksize != 0)	    {		loglog(RC_LOG_SERIOUS, "malformed message: not a multiple of encryption blocksize");		SEND_NOTIFICATION(PAYLOAD_MALFORMED);		return;	    }	    /* XXX Detect weak keys */	    /* grab a copy of raw packet (for duplicate packet detection) */	    clonetochunk(md->raw_packet, md->packet_pbs.start		, pbs_room(&md->packet_pbs), "raw packet");	    /* Decrypt everything after header */	    if (!new_iv_set)	    {		/* use old IV */		passert(st->st_iv_len <= sizeof(st->st_new_iv));		st->st_new_iv_len = st->st_iv_len;		init_new_iv(st);	    }	    crypto_cbc_encrypt(e, FALSE, md->message_pbs.cur, 			    pbs_left(&md->message_pbs) , st);	}	DBG_cond_dump(DBG_CRYPT, "decrypted:\n", md->message_pbs.cur	    , md->message_pbs.roof - md->message_pbs.cur);	DBG_cond_dump(DBG_CRYPT, "next IV:"	    , st->st_new_iv, st->st_new_iv_len);    }    else    {	/* packet was not encryped -- should it have been? */	if (smc->flags & SMF_INPUT_ENCRYPTED)	{	    loglog(RC_LOG_SERIOUS, "packet rejected: should have been encrypted");	    SEND_NOTIFICATION(INVALID_FLAGS);	    return;	}    }    /* Digest the message.     * Padding must be removed to make hashing work.     * Padding comes from encryption (so this code must be after decryption).     * Padding rules are described before the definition of     * struct isakmp_hdr in packet.h.     */    {	struct payload_digest *pd = md->digest;	int np = md->hdr.isa_np;	lset_t needed = smc->req_payloads;	const char *excuse	    = LIN(SMF_PSK_AUTH | SMF_FIRST_ENCRYPTED_INPUT, smc->flags)		? "probable authentication failure (mismatch of preshared secrets?): "		: "";	while (np != ISAKMP_NEXT_NONE)	{	    struct_desc *sd = np < ISAKMP_NEXT_ROOF? payload_descs[np] : NULL;	    if (pd == &md->digest[PAYLIMIT])	    {		loglog(RC_LOG_SERIOUS, "more than %d payloads in message; ignored", PAYLIMIT);		SEND_NOTIFICATION(PAYLOAD_MALFORMED);		return;	    }#ifdef NAT_TRAVERSAL	    switch (np)	    {		case ISAKMP_NEXT_NATD_RFC:		case ISAKMP_NEXT_NATOA_RFC:		    if ((!st) || (!(st->nat_traversal & NAT_T_WITH_RFC_VALUES))) {			/*			 * don't accept NAT-D/NAT-OA reloc directly in message, unless			 * we're using NAT-T RFC			 */			sd = NULL;		    }		    break;	    }#endif	    if (sd == NULL)	    {		/* payload type is out of range or requires special handling */		switch (np)		{		case ISAKMP_NEXT_ID:		    sd = IS_PHASE1(from_state)			? &isakmp_identification_desc : &isakmp_ipsec_identification_desc;		    break;#ifdef NAT_TRAVERSAL		case ISAKMP_NEXT_NATD_DRAFTS:		    np = ISAKMP_NEXT_NATD_RFC;  /* NAT-D relocated */		    sd = payload_descs[np];		    break;		case ISAKMP_NEXT_NATOA_DRAFTS:		    np = ISAKMP_NEXT_NATOA_RFC;  /* NAT-OA relocated */		    sd = payload_descs[np];		    break;#endif		default:		    loglog(RC_LOG_SERIOUS, "%smessage ignored because it contains an unknown or"			" unexpected payload type (%s) at the outermost level"			, excuse, enum_show(&payload_names, np));		    SEND_NOTIFICATION(INVALID_PAYLOAD_TYPE);		    return;		}	    }	    {		lset_t s = LELEM(np);		if (LDISJOINT(s		, needed | smc->opt_payloads| LELEM(ISAKMP_NEXT_N) | LELEM(ISAKMP_NEXT_D)))		{		    loglog(RC_LOG_SERIOUS, "%smessage ignored because it "			   "contains an unexpected payload type (%s)"			, excuse, enum_show(&payload_names, np));		    SEND_NOTIFICATION(INVALID_PAYLOAD_TYPE);		    return;		}		needed &= ~s;	    }	    if (!in_struct(&pd->payload, sd, &md->message_pbs, &pd->pbs))	    {		loglog(RC_LOG_SERIOUS, "%smalformed payload in packet", excuse);		SEND_NOTIFICATION(PAYLOAD_MALFORMED);		return;	    }	    /* place this payload at the end of the chain for this type */	    {		struct payload_digest **p;		for (p = &md->chain[np]; *p != NULL; p = &(*p)->next)		    ;		*p = pd;		pd->next = NULL;	    }	    np = pd->payload.generic.isag_np;	    pd++;	    /* since we've digested one payload happily, it is probably	     * the case that any decryption worked.  So we will not suggest	     * encryption failure as an excuse for subsequent payload	     * problems.	     */	    excuse = "";	}	md->digest_roof = pd;	DBG(DBG_PARSING,	    if (pbs_left(&md->message_pbs) != 0)		DBG_log("removing %d bytes of padding", (int) pbs_left(&md->message_pbs)));	md->message_pbs.roof = md->message_pbs.cur;	/* check that all mandatory payloads appeared */	if (needed != 0)	{	    loglog(RC_LOG_SERIOUS, "message for %s is missing payloads %s"		, enum_show(&state_names, from_state)		, bitnamesof(payload_name, needed));	    SEND_NOTIFICATION(PAYLOAD_MALFORMED);	    return;	}    }    /* more sanity checking: enforce most ordering constraints */    if (IS_PHASE1(from_state))    {	/* rfc2409: The Internet Key Exchange (IKE), 5 Exchanges:	 * "The SA payload MUST precede all other payloads in a phase 1 exchange."	 */	if (md->chain[ISAKMP_NEXT_SA] != NULL	&& md->hdr.isa_np != ISAKMP_NEXT_SA)	{	    loglog(RC_LOG_SERIOUS, "malformed Phase 1 message: does not start with an SA payload");	    SEND_NOTIFICATION(PAYLOAD_MALFORMED);	    return;	}    }    else if (IS_QUICK(from_state))    {	/* rfc2409: The Internet Key Exchange (IKE), 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."	 */	if (md->hdr.isa_np != ISAKMP_NEXT_HASH)	{	    loglog(RC_LOG_SERIOUS, "malformed Quick Mode message: does not start with a HASH payload");	    SEND_NOTIFICATION(PAYLOAD_MALFORMED);	    return;	}	{	    struct payload_digest *p;	    int i;	    for (p = md->chain[ISAKMP_NEXT_SA], i = 1; p != NULL	    ; p = p->next, i++)	    {		if (p != &md->digest[i])		{		    loglog(RC_LOG_SERIOUS, "malformed Quick Mode message: SA payload is in wrong position");		    SEND_NOTIFICATION(PAYLOAD_MALFORMED);		    return;		}	    }	}	/* rfc2409: The Internet Key Exchange (IKE), 5.5 Phase 2 - Quick Mode:	 * "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."	 */	{	    struct payload_digest *id = md->chain[ISAKMP_NEXT_ID];	    if (id != NULL)	    {		if (id->next == NULL || id->next->next != NULL)		{		    loglog(RC_LOG_SERIOUS, "malformed Quic

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -