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

📄 spdb_struct.c

📁 This a good VPN source
💻 C
📖 第 1 页 / 共 5 页
字号:
			, enum_show(&sa_lifetime_names, val));		    return FALSE;		}		seen_durations |= LELEM(val);		life_type = val;		break;	    case SA_LIFE_DURATION | ISAKMP_ATTR_AF_TLV:		val = decode_long_duration(&attr_pbs);		/* fall through */	    case SA_LIFE_DURATION | ISAKMP_ATTR_AF_TV:		ipcomp_inappropriate = FALSE;		if (!LHAS(seen_attrs, SA_LIFE_DURATION))		{		    loglog(RC_LOG_SERIOUS, "SA_LIFE_DURATION IPsec attribute not preceded by SA_LIFE_TYPE attribute");		    return FALSE;		}		seen_attrs &= ~(LELEM(SA_LIFE_DURATION) | LELEM(SA_LIFE_TYPE));		switch (life_type)		{		    case SA_LIFE_TYPE_SECONDS:			/* silently limit duration to our maximum */			attrs->life_seconds = val <= SA_LIFE_DURATION_MAXIMUM			    ? val : SA_LIFE_DURATION_MAXIMUM;			break;		    case SA_LIFE_TYPE_KBYTES:			attrs->life_kilobytes = val;			break;		    default:			bad_case(life_type);		}		break;	    case GROUP_DESCRIPTION | ISAKMP_ATTR_AF_TV:		if (is_ipcomp)		{		    /* Accept reluctantly.  Should not happen, according to		     * draft-shacham-ippcp-rfc2393bis-05.txt 4.1.		     */		    ipcomp_inappropriate = FALSE;		    loglog(RC_COMMENT			, "IPCA (IPcomp SA) contains GROUP_DESCRIPTION."			"  Ignoring inapproprate attribute.");		}		pfs_group = lookup_group(val);		if (pfs_group == NULL)		{		    loglog(RC_LOG_SERIOUS, "only OAKLEY_GROUP_MODP1024 and OAKLEY_GROUP_MODP1536 supported for PFS");		    return FALSE;		}		break;	    case ENCAPSULATION_MODE | ISAKMP_ATTR_AF_TV:		ipcomp_inappropriate = FALSE;#ifdef NAT_TRAVERSAL		switch (val) {			case ENCAPSULATION_MODE_TUNNEL:			case ENCAPSULATION_MODE_TRANSPORT:				if (st->nat_traversal & NAT_T_DETECTED) {					loglog(RC_LOG_SERIOUS,						"%s must only be used if "						"NAT-Traversal is not detected",						enum_name(&enc_mode_names, val));					/*					 * Accept it anyway because SSH-Sentinel does not					 * use UDP_TUNNEL or UDP_TRANSPORT for the diagnostic.					 *					 * remove when SSH-Sentinel is fixed					 */#ifdef I_DONT_CARE_OF_SSH_SENTINEL					return FALSE;#endif				}				attrs->encapsulation = val;				break;			case ENCAPSULATION_MODE_UDP_TRANSPORT_DRAFTS:#ifndef I_KNOW_TRANSPORT_MODE_HAS_SECURITY_CONCERN_BUT_I_WANT_IT				loglog(RC_LOG_SERIOUS,					"NAT-Traversal: Transport mode disabled due "					"to security concerns");				return FALSE;				break;#endif			case ENCAPSULATION_MODE_UDP_TUNNEL_DRAFTS:				if (st->nat_traversal & NAT_T_WITH_RFC_VALUES) {					loglog(RC_LOG_SERIOUS,						"%s must only be used with old IETF drafts",						enum_name(&enc_mode_names, val));					return FALSE;				}				else if (st->nat_traversal & NAT_T_DETECTED) {					attrs->encapsulation = val - ENCAPSULATION_MODE_UDP_TUNNEL_DRAFTS + ENCAPSULATION_MODE_TUNNEL;				}				else {					loglog(RC_LOG_SERIOUS,						"%s must only be used if "						"NAT-Traversal is detected",						enum_name(&enc_mode_names, val));					return FALSE;				}				break;			case ENCAPSULATION_MODE_UDP_TRANSPORT_RFC:#ifndef I_KNOW_TRANSPORT_MODE_HAS_SECURITY_CONCERN_BUT_I_WANT_IT				loglog(RC_LOG_SERIOUS,					"NAT-Traversal: Transport mode disabled due "					"to security concerns");				return FALSE;				break;#endif			case ENCAPSULATION_MODE_UDP_TUNNEL_RFC:				if ((st->nat_traversal & NAT_T_DETECTED) &&					(st->nat_traversal & NAT_T_WITH_RFC_VALUES)) {					attrs->encapsulation = val - ENCAPSULATION_MODE_UDP_TUNNEL_RFC + ENCAPSULATION_MODE_TUNNEL;				}				else if (st->nat_traversal & NAT_T_DETECTED) {					loglog(RC_LOG_SERIOUS,						"%s must only be used with NAT-T RFC",						enum_name(&enc_mode_names, val));					return FALSE;				}				else {					loglog(RC_LOG_SERIOUS,						"%s must only be used if "						"NAT-Traversal is detected",						enum_name(&enc_mode_names, val));					return FALSE;				}				break;			default:				loglog(RC_LOG_SERIOUS,					"unknown ENCAPSULATION_MODE %d in IPSec SA", val);				return FALSE;				break;		}#else		attrs->encapsulation = val;#endif		break;	    case AUTH_ALGORITHM | ISAKMP_ATTR_AF_TV:		attrs->auth = val;		break;	    case KEY_LENGTH | ISAKMP_ATTR_AF_TV:		attrs->key_len = val;		break;	    case KEY_ROUNDS | ISAKMP_ATTR_AF_TV:		attrs->key_rounds = val;		break;#if 0 /* not yet implemented */	    case COMPRESS_DICT_SIZE | ISAKMP_ATTR_AF_TV:		break;	    case COMPRESS_PRIVATE_ALG | ISAKMP_ATTR_AF_TV:		break;	    case SA_LIFE_DURATION | ISAKMP_ATTR_AF_TLV:		break;	    case COMPRESS_PRIVATE_ALG | ISAKMP_ATTR_AF_TLV:		break;#endif	    default:		loglog(RC_LOG_SERIOUS, "unsupported IPsec attribute %s"		    , enum_show(&ipsec_attr_names, a.isaat_af_type));		return FALSE;	}	if (ipcomp_inappropriate)	{	    loglog(RC_LOG_SERIOUS, "IPsec attribute %s inappropriate for IPCOMP"		, enum_show(&ipsec_attr_names, a.isaat_af_type));	    return FALSE;	}    }    /* Although an IPCOMP SA (IPCA) ought not to have a pfs_group,     * if it does, demand that it be consistent.     * See draft-shacham-ippcp-rfc2393bis-05.txt 4.1.     */    if (!is_ipcomp || pfs_group != NULL)    {	if (st->st_pfs_group == &unset_group)	    st->st_pfs_group = pfs_group;	if (st->st_pfs_group != pfs_group)	{	    loglog(RC_LOG_SERIOUS, "GROUP_DESCRIPTION inconsistent with that of %s in IPsec SA"		, selection? "the Proposal" : "a previous Transform");	    return FALSE;	}    }    if (LHAS(seen_attrs, SA_LIFE_DURATION))    {	loglog(RC_LOG_SERIOUS, "SA_LIFE_TYPE IPsec attribute not followed by SA_LIFE_DURATION attribute in message");	return FALSE;    }    if (!LHAS(seen_attrs, ENCAPSULATION_MODE))    {	if (is_ipcomp)	{	    /* draft-shacham-ippcp-rfc2393bis-05.txt 4.1:	     * "If the Encapsulation Mode is unspecified,	     * the default value of Transport Mode is assumed."	     * This contradicts/overrides the DOI (quuoted below).	     */	    attrs->encapsulation = ENCAPSULATION_MODE_TRANSPORT;	}	else	{	    /* ??? Technically, RFC 2407 (IPSEC DOI) 4.5 specifies that	     * the default is "unspecified (host-dependent)".	     * This makes little sense, so we demand that it be specified.	     */	    loglog(RC_LOG_SERIOUS, "IPsec Transform must specify ENCAPSULATION_MODE");	    return FALSE;	}    }    /* ??? should check for key_len and/or key_rounds if required */    return TRUE;}static voidecho_proposal(    struct isakmp_proposal r_proposal,	/* proposal to emit */    struct isakmp_transform r_trans,	/* winning transformation within it */    u_int8_t np,			/* Next Payload for proposal */    pb_stream *r_sa_pbs,		/* SA PBS into which to emit */    struct ipsec_proto_info *pi,	/* info about this protocol instance */    struct_desc *trans_desc,		/* descriptor for this transformation */    pb_stream *trans_pbs,		/* PBS for incoming transform */    struct spd_route *sr,		/* host details for the association */    bool tunnel_mode)			/* true for inner most tunnel SA */{    pb_stream r_proposal_pbs;    pb_stream r_trans_pbs;    /* Proposal */    r_proposal.isap_np = np;    r_proposal.isap_notrans = 1;    if (!out_struct(&r_proposal, &isakmp_proposal_desc, r_sa_pbs, &r_proposal_pbs))	impossible();    /* allocate and emit our CPI/SPI */    if (r_proposal.isap_protoid == PROTO_IPCOMP)    {	/* CPI is stored in network low order end of an	 * ipsec_spi_t.  So we start a couple of bytes in.	 * Note: we may fail to generate a satisfactory CPI,	 * but we'll ignore that.	 */	pi->our_spi = get_my_cpi(sr, tunnel_mode);	out_raw((u_char *) &pi->our_spi	     + IPSEC_DOI_SPI_SIZE - IPCOMP_CPI_SIZE	    , IPCOMP_CPI_SIZE	    , &r_proposal_pbs, "CPI");    }    else    {	pi->our_spi = get_ipsec_spi(pi->attrs.spi	    , r_proposal.isap_protoid == PROTO_IPSEC_AH ?		IPPROTO_AH : IPPROTO_ESP	    , sr	    , tunnel_mode);	/* XXX should check for errors */	out_raw((u_char *) &pi->our_spi, IPSEC_DOI_SPI_SIZE	    , &r_proposal_pbs, "SPI");    }    /* Transform */    r_trans.isat_np = ISAKMP_NEXT_NONE;    if (!out_struct(&r_trans, trans_desc, &r_proposal_pbs, &r_trans_pbs))	impossible();    /* Transform Attributes: pure echo */    trans_pbs->cur = trans_pbs->start + sizeof(struct isakmp_transform);    if (!out_raw(trans_pbs->cur, pbs_left(trans_pbs)    , &r_trans_pbs, "attributes"))	impossible();    close_output_pbs(&r_trans_pbs);    close_output_pbs(&r_proposal_pbs);}notification_tparse_ipsec_sa_body(    pb_stream *sa_pbs,		/* body of input SA Payload */    const struct isakmp_sa *sa,	/* header of input SA Payload */    pb_stream *r_sa_pbs,	/* if non-NULL, where to emit body of winning SA */    bool selection,		/* if this SA is a selection, only one transform may appear */    struct state *st)		/* current state object */{    const struct connection *c = st->st_connection;    u_int32_t ipsecdoisit;    pb_stream next_proposal_pbs;    struct isakmp_proposal next_proposal;    ipsec_spi_t next_spi;    bool next_full = TRUE;    /* DOI */    if (sa->isasa_doi != ISAKMP_DOI_IPSEC)    {	loglog(RC_LOG_SERIOUS, "Unknown or unsupported DOI %s", enum_show(&doi_names, sa->isasa_doi));	/* XXX Could send notification back */	return DOI_NOT_SUPPORTED;    }    /* Situation */    if (!in_struct(&ipsecdoisit, &ipsec_sit_desc, sa_pbs, NULL))	return SITUATION_NOT_SUPPORTED;    if (ipsecdoisit != SIT_IDENTITY_ONLY)    {	loglog(RC_LOG_SERIOUS, "unsupported IPsec DOI situation (%s)"	    , bitnamesof(sit_bit_names, ipsecdoisit));	/* XXX Could send notification back */	return SITUATION_NOT_SUPPORTED;    }    /* The rules for IPsec SAs are scattered.     * RFC 2408 "ISAKMP" section 4.2 gives some info.     * There may be multiple proposals.  Those with identical proposal     * numbers must be considered as conjuncts.  Those with different     * numbers are disjuncts.     * Each proposal may have several transforms, each considered     * an alternative.     * Each transform may have several attributes, all applying.     *     * To handle the way proposals are combined, we need to do a     * look-ahead.     */    if (!in_struct(&next_proposal, &isakmp_proposal_desc, sa_pbs, &next_proposal_pbs))	return BAD_PROPOSAL_SYNTAX;    /* for each conjunction of proposals... */    while (next_full)    {	int propno = next_proposal.isap_proposal;	pb_stream ah_prop_pbs, esp_prop_pbs, ipcomp_prop_pbs;	struct isakmp_proposal ah_proposal, esp_proposal, ipcomp_proposal;	ipsec_spi_t ah_spi, esp_spi, ipcomp_cpi;	bool ah_seen = FALSE, esp_seen = FALSE, ipcomp_seen = FALSE;	int inner_proto = 0;	bool tunnel_mode = FALSE;	u_int16_t well_known_cpi = 0;	pb_stream ah_trans_pbs, esp_trans_pbs, ipcomp_trans_pbs;	struct isakmp_transform ah_trans, esp_trans, ipcomp_trans;	struct ipsec_trans_attrs ah_attrs, esp_attrs, ipcomp_attrs;	/* for each proposal in the conjunction */	do {	    if (next_proposal.isap_protoid == PROTO_IPCOMP)	    {		/* IPCOMP CPI */		if (next_proposal.isap_spisize == IPSEC_DOI_SPI_SIZE)		{		    /* This code is to accommodate those peculiar		     * implementations that send a CPI in the bottom of an		     * SPI-sized field.		     * See draft-shacham-ippcp-rfc2393bis-05.txt 4.1		     */		    u_int8_t filler[IPSEC_DOI_SPI_SIZE - IPCOMP_CPI_SIZE];		    if (!in_raw(filler, sizeof(filler)		     , &next_proposal_pbs, "CPI filler")		    || !all_zero(filler, sizeof(filler)))			return INVALID_SPI;		}		else if (next_proposal.isap_spisize != IPCOMP_CPI_SIZE)		{		    loglog(RC_LOG_SERIOUS, "IPsec Proposal with improper CPI size (%u)"			, next_proposal.isap_spisize);		    return INVALID_SPI;		}		/* We store CPI in the low order of a network order		 * ipsec_spi_t.  So we start a couple of bytes in.		 */		zero(&next_spi);		if (!in_raw((u_char *)&next_spi		  + IPSEC_DOI_SPI_SIZE - IPCOMP_CPI_SIZE		, IPCOMP_CPI_SIZE, &next_proposal_pbs, "CPI"))		    return INVALID_SPI;		/* If sanity ruled, CPIs would have to be such that		 * the SAID (the triple (CPI, IPCOM, destination IP))		 * would be unique, just like for SPIs.  But there is a		 * perversion where CPIs can be well-known and consequently		 * the triple is not unique.  We hide this fact from		 * ourselves by fudging the top 16 bits to make		 * the property true internally!		 */		switch (ntohl(next_spi))		{		case IPCOMP_DEFLATE:		    well_known_cpi = ntohl(next_spi);		    next_spi = uniquify_his_cpi(next_spi, st);		    if (next_spi == 0)		    {			loglog(RC_LOG_SERIOUS			    , "IPsec Proposal contains well-known CPI that I cannot uniquify");			return INVALID_SPI;		    }		    break;		default:		    if (ntohl(next_spi) < IPCOMP_FIRST_NEGOTIATED		    || ntohl(next_spi) > IPCOMP_LAST_NEGOTIATED)		    {			loglog(RC_LOG_SERIOUS, "IPsec Proposal contains CPI from non-negotiated range (0x%lx)"			    , (unsigned long) ntohl(next_spi));			return INVALID_SPI;		    }		    break;		}	    }	    else	    {		/* AH or ESP SPI */		if (next_proposal.isap_spisize != IPSEC_DOI_SPI_SIZE)		{		    loglog(RC_LOG_SERIOUS, "IPsec Proposal with improper SPI size (%u)"			, next_proposal.isap_spisize);		    return INVALID_SPI;		}		if (!in_raw((u_char *)&next_spi, sizeof(next_spi), &next_proposal_pbs, "SPI"))		    return INVALID_SPI;		/* SPI value 0 is invalid and values 1-255 are reserved to IANA.		 * RFC 2402 (ESP) 2.4, RFC 2406 (AH) 2.1		 * IPCOMP???		 */		if (ntohl(next_spi) < IPSEC_DOI_SPI_MIN)		{		    loglog(RC_LOG_SERIOUS, "IPsec Proposal contains invalid SPI (0x%lx)"			, (unsigned long) ntohl(next_spi));		    return INVALID_SPI;		}	    }	    if (next_proposal.isap_notrans == 0)	    {		loglog(RC_LOG_SERIOUS, "IPsec Proposal contains no Transforms (skipped)");		continue;	    }	    switch (next_proposal.isap_protoid)	    {	    case PROTO_IPSEC_AH:		if (ah_seen)		{

⌨️ 快捷键说明

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