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

📄 spdb_struct.c

📁 This a good VPN source
💻 C
📖 第 1 页 / 共 5 页
字号:
return_out:#if defined(KERNEL_ALG) || defined(IKE_ALG)    if (revised_sadb)	free_sa(revised_sadb);#endif    return ret;}/** Handle long form of duration attribute. * The code is can only handle values that can fit in unsigned long. * "Clamping" is probably an acceptable way to impose this limitation. * * @param pbs PB Stream * @return u_int32_t duration, in seconds. */static u_int32_tdecode_long_duration(pb_stream *pbs){    u_int32_t val = 0;    /* ignore leading zeros */    while (pbs_left(pbs) != 0 && *pbs->cur == '\0')	pbs->cur++;    if (pbs_left(pbs) > sizeof(val))    {	/* "clamp" too large value to max representable value */	val -= 1;	/* portable way to get to maximum value */	DBG(DBG_PARSING, DBG_log("   too large duration clamped to: %lu"	    , (unsigned long)val));    }    else    {	/* decode number */	while (pbs_left(pbs) != 0)	    val = (val << BITS_PER_BYTE) | *pbs->cur++;	DBG(DBG_PARSING, DBG_log("   long duration: %lu", (unsigned long)val));    }    return val;}/** * Parse the body of an ISAKMP SA Payload (i.e. Phase 1 / Main Mode). * Various shortcuts are taken.  In particular, the policy, such as * it is, is hardwired. * * If r_sa is non-NULL, the body of an SA representing the selected * proposal is emitted. * * If "selection" is true, the SA is supposed to represent the * single tranform that the peer has accepted. * ??? We only check that it is acceptable, not that it is one that we offered! * * It also means that we are inR1, and this as implications when we are * doing XAUTH, as it changes the meaning of the XAUTHInit/XAUTHResp. * * Only IPsec DOI is accepted (what is the ISAKMP DOI?). * Error response is rudimentary. * * This routine is used by main_inI1_outR1() and main_inR1_outI2(). */notification_tparse_isakmp_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 winning SA */    bool selection,	/* if this SA is a selection, only one tranform			 * can appear. */    struct state *st)	/* current state object */{    u_int32_t ipsecdoisit;    pb_stream proposal_pbs;    struct isakmp_proposal proposal;    unsigned no_trans_left;    int last_transnum;    struct connection *c = st->st_connection;    struct spd_route *spd, *me = &c->spd;    bool xauth_init, xauth_resp;    const char *role;    xauth_init = xauth_resp = FALSE;    /* calculate the per-end policy which might apply */    for(spd = me; spd; spd = spd->next) {	if(selection)	{ /* this is the initiator, we have proposed, they have answered,	   * and we must decide if they proposed what we wanted.	   */	    role = "initiator";	    xauth_init = xauth_init | spd->this.xauth_client;	    xauth_resp = xauth_resp | spd->this.xauth_server;	}	else	{ /* this is the responder, they have proposed to us, what	   * are we willing to be?	   */	    role = "responder";	    xauth_init = xauth_init | spd->this.xauth_server;	    xauth_resp = xauth_resp | spd->this.xauth_client;	}    }    /* DOI */    if (sa->isasa_doi != ISAKMP_DOI_IPSEC)    {	loglog(RC_LOG_SERIOUS, "Unknown/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 ISAKMP SAs are scattered.     * RFC 2409 "IKE" section 5 says that there     * can only be one SA, and it can have only one proposal in it.     * There may well be multiple transforms.     */    if (!in_struct(&proposal, &isakmp_proposal_desc, sa_pbs, &proposal_pbs))	return PAYLOAD_MALFORMED;    if (proposal.isap_np != ISAKMP_NEXT_NONE)    {	loglog(RC_LOG_SERIOUS, "Proposal Payload must be alone in Oakley SA; found %s following Proposal"	    , enum_show(&payload_names, proposal.isap_np));	return PAYLOAD_MALFORMED;    }    if (proposal.isap_protoid != PROTO_ISAKMP)    {	loglog(RC_LOG_SERIOUS, "unexpected Protocol ID (%s) found in Oakley Proposal"	    , enum_show(&protocol_names, proposal.isap_protoid));	return INVALID_PROTOCOL_ID;    }    /* Just what should we accept for the SPI field?     * The RFC is sort of contradictory.  We will ignore the SPI     * as long as it is of the proper size.     *     * From RFC2408 2.4 Identifying Security Associations:     *   During phase 1 negotiations, the initiator and responder cookies     *   determine the ISAKMP SA. Therefore, the SPI field in the Proposal     *   payload is redundant and MAY be set to 0 or it MAY contain the     *   transmitting entity's cookie.     *     * From RFC2408 3.5 Proposal Payload:     *    o  SPI Size (1 octet) - Length in octets of the SPI as defined by     *       the Protocol-Id.  In the case of ISAKMP, the Initiator and     *       Responder cookie pair from the ISAKMP Header is the ISAKMP SPI,     *       therefore, the SPI Size is irrelevant and MAY be from zero (0) to     *       sixteen (16).  If the SPI Size is non-zero, the content of the     *       SPI field MUST be ignored.  If the SPI Size is not a multiple of     *       4 octets it will have some impact on the SPI field and the     *       alignment of all payloads in the message.  The Domain of     *       Interpretation (DOI) will dictate the SPI Size for other     *       protocols.     */    if (proposal.isap_spisize == 0)    {	/* empty (0) SPI -- fine */    }    else if (proposal.isap_spisize <= MAX_ISAKMP_SPI_SIZE)    {	u_char junk_spi[MAX_ISAKMP_SPI_SIZE];	if (!in_raw(junk_spi, proposal.isap_spisize, &proposal_pbs, "Oakley SPI"))	    return PAYLOAD_MALFORMED;    }    else    {	loglog(RC_LOG_SERIOUS, "invalid SPI size (%u) in Oakley Proposal"	    , (unsigned)proposal.isap_spisize);	return INVALID_SPI;    }    if (selection && proposal.isap_notrans != 1)    {	loglog(RC_LOG_SERIOUS, "a single Transform is required in a selecting Oakley Proposal; found %u"	    , (unsigned)proposal.isap_notrans);	return BAD_PROPOSAL_SYNTAX;    }    /* for each transform payload... */    last_transnum = -1;    no_trans_left = proposal.isap_notrans;    for (;;)    {	pb_stream trans_pbs;	u_char *attr_start;	size_t attr_len;	struct isakmp_transform trans;	lset_t seen_attrs = 0	    , seen_durations = 0;	u_int16_t life_type;	struct oakley_trans_attrs ta;	err_t ugh = NULL;	/* set to diagnostic when problem detected */	zero(&ta);	/* initialize only optional field in ta */	ta.life_seconds = OAKLEY_ISAKMP_SA_LIFETIME_DEFAULT;	/* When this SA expires (seconds) */	if (no_trans_left == 0)	{	    loglog(RC_LOG_SERIOUS, "number of Transform Payloads disagrees with Oakley Proposal Payload");	    return BAD_PROPOSAL_SYNTAX;	}	if (!in_struct(&trans, &isakmp_isakmp_transform_desc, &proposal_pbs, &trans_pbs))	    return BAD_PROPOSAL_SYNTAX;	if (trans.isat_transnum <= last_transnum)	{	    /* picky, picky, picky */	    loglog(RC_LOG_SERIOUS, "Transform Numbers are not monotonically increasing"		" in Oakley Proposal");	    return BAD_PROPOSAL_SYNTAX;	}	last_transnum = trans.isat_transnum;	if (trans.isat_transid != KEY_IKE)	{	    loglog(RC_LOG_SERIOUS, "expected KEY_IKE but found %s in Oakley Transform"		, enum_show(&isakmp_transformid_names, trans.isat_transid));	    return INVALID_TRANSFORM_ID;	}	attr_start = trans_pbs.cur;	attr_len = pbs_left(&trans_pbs);	/* process all the attributes that make up the transform */	while (pbs_left(&trans_pbs) != 0)	{	    struct isakmp_attribute a;	    pb_stream attr_pbs;	    u_int32_t val;	/* room for larger values */	    if (!in_struct(&a, &isakmp_oakley_attribute_desc, &trans_pbs, &attr_pbs))		return BAD_PROPOSAL_SYNTAX;	    passert((a.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK) < 32);	    if (LHAS(seen_attrs, a.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK))	    {		loglog(RC_LOG_SERIOUS, "repeated %s attribute in Oakley Transform %u"		    , enum_show(&oakley_attr_names, a.isaat_af_type)		    , trans.isat_transnum);		return BAD_PROPOSAL_SYNTAX;	    }	    seen_attrs |= LELEM(a.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK);	    val = a.isaat_lv;	    DBG(DBG_PARSING,	    {		enum_names *vdesc = oakley_attr_val_descs		    [a.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK];		if (vdesc != NULL)		{		    const char *nm = enum_name(vdesc, val);		    if (nm != NULL)			DBG_log("   [%u is %s]", (unsigned)val, nm);		}	    });	    switch (a.isaat_af_type)	    {		case OAKLEY_ENCRYPTION_ALGORITHM | ISAKMP_ATTR_AF_TV:#ifdef IKE_ALG		    if (ike_alg_enc_ok(val, 0, c->alg_info_ike, &ugh)) {		    /* if (ike_alg_enc_present(val)) { */			ta.encrypt = val;			ta.encrypter = crypto_get_encrypter(val);			ta.enckeylen = ta.encrypter->keydeflen;		    } else #endif		    switch (val)		    {		    case OAKLEY_3DES_CBC:			ta.encrypt = val;			ta.encrypter = crypto_get_encrypter(val);			break;   		    /* we don't feel DES is safe */		    case OAKLEY_DES_CBC:		    default:			ugh = builddiag("%s is not supported"			    , enum_show(&oakley_enc_names, val));		    }		    break;		case OAKLEY_HASH_ALGORITHM | ISAKMP_ATTR_AF_TV:#ifdef IKE_ALG		    if (ike_alg_hash_present(val)) {			ta.hash = val;			ta.hasher = crypto_get_hasher(val);		    } else #endif/* #else */		    switch (val)		    {		    case OAKLEY_MD5:		    case OAKLEY_SHA:			ta.hash = val;			ta.hasher = crypto_get_hasher(val);			break;		    default:			ugh = builddiag("%s is not supported"			    , enum_show(&oakley_hash_names, val));		    }/* #endif */		    break;		case OAKLEY_AUTHENTICATION_METHOD | ISAKMP_ATTR_AF_TV:		    {	            lset_t iap = st->st_policy & POLICY_ID_AUTH_MASK; 		    /* check that authentication method is acceptable */		    switch (val)		    {#ifdef XAUTH		    case XAUTHInitPreShared:			if(!xauth_init)			{			    ugh = builddiag("policy does not allow Extended Authentication (XAUTH) of initiator (we are %s)", role);			    break;			}			ta.xauth = val;			val = OAKLEY_PRESHARED_KEY;			goto psk;		    case XAUTHRespPreShared:			if(!xauth_resp)			{			    ugh = builddiag("policy does not allow Extended Authentication (XAUTH) of responder (we are %s)", role);			    break;			}			ta.xauth = val;			val = OAKLEY_PRESHARED_KEY;			/* No break; */#endif		    case OAKLEY_PRESHARED_KEY:#ifdef XAUTH		    psk:			if(xauth_init && ta.xauth == 0)			{			    ugh = builddiag("policy mandates Extended Authentication (XAUTH) with PSK of initiator (we are %s)", role);			    break;			}			if(xauth_resp && ta.xauth == 0)			{			    ugh = builddiag("policy mandates Extended Authentication (XAUTH) with PSK of responder (we are %s)", role);			    break;			}#endif			if ((iap & POLICY_PSK) == LEMPTY)			{			    ugh = "policy does not allow OAKLEY_PRESHARED_KEY authentication";			}			else			{			    /* check that we can find a preshared secret */			    struct connection *c = st->st_connection;			    if (get_preshared_secret(c) == NULL)			    {				char mid[IDTOA_BUF]				    , hid[IDTOA_BUF];				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;			}			break;#ifdef XAUTH		    case XAUTHInitRSA:			if(!xauth_init)			{			    ugh = builddiag("policy does not allow Extended Authentication (XAUTH) with RSA of initiator (we are %s)", role);			    break;			}			ta.xauth = val;			val = OAKLEY_RSA_SIG;			goto rsasig;		    case XAUTHRespRSA:			if(!xauth_resp)			{			    ugh = builddiag("policy does not allow Extended Authentication (XAUTH) with RSA of responder (we are %s)", role);			    break;			}			ta.xauth = val;			val = OAKLEY_RSA_SIG;			/* No break; */#endif					    case OAKLEY_RSA_SIG:#ifdef XAUTH		    rsasig:			if(xauth_init && ta.xauth == 0)			{			    ugh = builddiag("policy mandates Extended Authentication (XAUTH) with RSA of initiator (we are %s)", role);			    break;			}			if(xauth_resp && ta.xauth == 0)			{			    ugh = builddiag("policy mandates Extended Authentication (XAUTH) with RSA of responder (we are %s)", role);			    break;			}#endif			/* Accept if policy specifies RSASIG or is default */			if ((iap & POLICY_RSASIG) == LEMPTY)			{			    ugh = "policy does not allow OAKLEY_RSA_SIG authentication";			}			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;			}			break;		    default:			ugh = builddiag("Pluto does not support %s authentication"			    , enum_show(&oakley_auth_names, val));

⌨️ 快捷键说明

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