📄 spdb_struct.c
字号:
break; } } break; case OAKLEY_GROUP_DESCRIPTION | ISAKMP_ATTR_AF_TV: ta.group = lookup_group(val); if (ta.group == NULL) { ugh = "only OAKLEY_GROUP_MODP1024 and OAKLEY_GROUP_MODP1536 supported"; break; } break; case OAKLEY_LIFE_TYPE | ISAKMP_ATTR_AF_TV: switch (val) { case OAKLEY_LIFE_SECONDS: case OAKLEY_LIFE_KILOBYTES: if (LHAS(seen_durations, val)) { loglog(RC_LOG_SERIOUS , "attribute OAKLEY_LIFE_TYPE value %s repeated" , enum_show(&oakley_lifetime_names, val)); return BAD_PROPOSAL_SYNTAX; } seen_durations |= LELEM(val); life_type = val; break; default: ugh = builddiag("unknown value %s" , enum_show(&oakley_lifetime_names, val)); break; } break; case OAKLEY_LIFE_DURATION | ISAKMP_ATTR_AF_TLV: val = decode_long_duration(&attr_pbs); /* fall through */ case OAKLEY_LIFE_DURATION | ISAKMP_ATTR_AF_TV: if (!LHAS(seen_attrs, OAKLEY_LIFE_TYPE)) { ugh = "OAKLEY_LIFE_DURATION attribute not preceded by OAKLEY_LIFE_TYPE attribute"; break; } seen_attrs &= ~(LELEM(OAKLEY_LIFE_DURATION) | LELEM(OAKLEY_LIFE_TYPE)); switch (life_type) { case OAKLEY_LIFE_SECONDS: if (val > OAKLEY_ISAKMP_SA_LIFETIME_MAXIMUM) ugh = builddiag("peer requested %lu seconds" " which exceeds our limit %d seconds" , (long) val , OAKLEY_ISAKMP_SA_LIFETIME_MAXIMUM); ta.life_seconds = val; break; case OAKLEY_LIFE_KILOBYTES: ta.life_kilobytes = val; break; default: bad_case(life_type); } break;#ifdef IKE_ALG case OAKLEY_KEY_LENGTH | ISAKMP_ATTR_AF_TV: if ((seen_attrs & LELEM(OAKLEY_ENCRYPTION_ALGORITHM)) == 0) { ugh = "OAKLEY_KEY_LENGTH attribute not preceded by OAKLEY_ENCRYPTION_ALGORITHM attribute"; break; } if (ta.encrypter == NULL) { ugh = "NULL encrypter with seen OAKLEY_ENCRYPTION_ALGORITHM"; break; } /* * check if this keylen is compatible with * specified alg_info_ike */ if (!ike_alg_enc_ok(ta.encrypt, val, c->alg_info_ike, &ugh)) { ugh = "peer proposed key_len not valid for encrypt algo setup specified"; } ta.enckeylen=val; break;#else case OAKLEY_KEY_LENGTH | ISAKMP_ATTR_AF_TV:#endif#if 0 /* not yet supported */ case OAKLEY_GROUP_TYPE | ISAKMP_ATTR_AF_TV: case OAKLEY_PRF | ISAKMP_ATTR_AF_TV: case OAKLEY_FIELD_SIZE | ISAKMP_ATTR_AF_TV: case OAKLEY_GROUP_PRIME | ISAKMP_ATTR_AF_TV: case OAKLEY_GROUP_PRIME | ISAKMP_ATTR_AF_TLV: case OAKLEY_GROUP_GENERATOR_ONE | ISAKMP_ATTR_AF_TV: case OAKLEY_GROUP_GENERATOR_ONE | ISAKMP_ATTR_AF_TLV: case OAKLEY_GROUP_GENERATOR_TWO | ISAKMP_ATTR_AF_TV: case OAKLEY_GROUP_GENERATOR_TWO | ISAKMP_ATTR_AF_TLV: case OAKLEY_GROUP_CURVE_A | ISAKMP_ATTR_AF_TV: case OAKLEY_GROUP_CURVE_A | ISAKMP_ATTR_AF_TLV: case OAKLEY_GROUP_CURVE_B | ISAKMP_ATTR_AF_TV: case OAKLEY_GROUP_CURVE_B | ISAKMP_ATTR_AF_TLV: case OAKLEY_GROUP_ORDER | ISAKMP_ATTR_AF_TV: case OAKLEY_GROUP_ORDER | ISAKMP_ATTR_AF_TLV:#endif default: ugh = "unsupported OAKLEY attribute"; break; } if (ugh != NULL) { loglog(RC_LOG_SERIOUS, "%s. Attribute %s" , ugh, enum_show(&oakley_attr_names, a.isaat_af_type)); break; } }#ifdef IKE_ALG /* * ML: at last check for allowed transforms in alg_info_ike * (ALG_INFO_F_STRICT flag) */ if (ugh == NULL) { if (!ike_alg_ok_final(ta.encrypt, ta.enckeylen, ta.hash, ta.group ? ta.group->group : -1, c->alg_info_ike)) { ugh = "OAKLEY proposal refused"; } }#endif if (ugh == NULL) { /* a little more checking is in order */ { lset_t missing = ~seen_attrs & (LELEM(OAKLEY_ENCRYPTION_ALGORITHM) | LELEM(OAKLEY_HASH_ALGORITHM) | LELEM(OAKLEY_AUTHENTICATION_METHOD) | LELEM(OAKLEY_GROUP_DESCRIPTION)); if (missing) { loglog(RC_LOG_SERIOUS, "missing mandatory attribute(s) %s in Oakley Transform %u" , bitnamesof(oakley_attr_bit_names, missing) , trans.isat_transnum); return BAD_PROPOSAL_SYNTAX; } } /* We must have liked this transform. * Lets finish early and leave. */ DBG(DBG_PARSING | DBG_CRYPT , DBG_log("Oakley Transform %u accepted", trans.isat_transnum)); if (r_sa_pbs != NULL) { struct isakmp_proposal r_proposal = proposal; pb_stream r_proposal_pbs; struct isakmp_transform r_trans = trans; pb_stream r_trans_pbs; /* Situation */ if (!out_struct(&ipsecdoisit, &ipsec_sit_desc, r_sa_pbs, NULL)) impossible(); /* Proposal */#ifdef EMIT_ISAKMP_SPI r_proposal.isap_spisize = COOKIE_SIZE;#else r_proposal.isap_spisize = 0;#endif r_proposal.isap_notrans = 1; if (!out_struct(&r_proposal, &isakmp_proposal_desc, r_sa_pbs, &r_proposal_pbs)) impossible(); /* SPI */#ifdef EMIT_ISAKMP_SPI if (!out_raw(my_cookie, COOKIE_SIZE, &r_proposal_pbs, "SPI")) impossible(); r_proposal.isap_spisize = COOKIE_SIZE;#else /* none (0) */#endif /* Transform */ r_trans.isat_np = ISAKMP_NEXT_NONE; if (!out_struct(&r_trans, &isakmp_isakmp_transform_desc, &r_proposal_pbs, &r_trans_pbs)) impossible(); if (!out_raw(attr_start, attr_len, &r_trans_pbs, "attributes")) impossible(); close_output_pbs(&r_trans_pbs); close_output_pbs(&r_proposal_pbs); close_output_pbs(r_sa_pbs); } /* ??? If selection, we used to save the proposal in state. * We never used it. From proposal_pbs.start, * length pbs_room(&proposal_pbs) */ /* copy over the results */ st->st_oakley = ta; return NOTHING_WRONG; } /* on to next transform */ no_trans_left--; if (trans.isat_np == ISAKMP_NEXT_NONE) { if (no_trans_left != 0) { loglog(RC_LOG_SERIOUS, "number of Transform Payloads disagrees with Oakley Proposal Payload"); return BAD_PROPOSAL_SYNTAX; } break; } if (trans.isat_np != ISAKMP_NEXT_T) { loglog(RC_LOG_SERIOUS, "unexpected %s payload in Oakley Proposal" , enum_show(&payload_names, proposal.isap_np)); return BAD_PROPOSAL_SYNTAX; } } loglog(RC_LOG_SERIOUS, "no acceptable Oakley Transform"); return NO_PROPOSAL_CHOSEN;}#if defined(AGGRESSIVE)/* Initialize st_oakley field of state for use when initiating in * aggressive mode. * * This should probably get more of its parameters, like what group to use, * from the connection specification, but it's not there yet. * This should ideally be done by passing them via whack. * *//* XXX MCR. I suspect that actually all of this is redundent */boolinit_am_st_oakley(struct state *st, lset_t policy){ struct oakley_trans_attrs ta; struct db_attr *enc, *hash, *auth, *grp; struct db_trans *trans; struct db_prop *prop; struct db_prop_conj *cprop; struct db_sa *sa; struct db_sa *revised_sadb; struct connection *c = st->st_connection; unsigned int policy_index = POLICY_ISAKMP(policy , c->spd.this.xauth_server , c->spd.this.xauth_client); memset(&ta, 0, sizeof(ta)); /* When this SA expires (seconds) */ ta.life_seconds = st->st_connection->sa_ike_life_seconds; ta.life_kilobytes = 1000000; passert(policy_index < elemsof(oakley_am_sadb)); sa = &oakley_am_sadb[policy_index]; revised_sadb=oakley_alg_makedb(st->st_connection->alg_info_ike , sa, 1); if(revised_sadb == NULL) { return FALSE; } passert(revised_sadb->prop_conj_cnt == 1); cprop = &revised_sadb->prop_conjs[0]; passert(cprop->prop_cnt == 1); prop = &cprop->props[0]; passert(prop->trans_cnt == 1); trans = &prop->trans[0]; passert(trans->attr_cnt == 4); enc = &trans->attrs[0]; hash = &trans->attrs[1]; auth = &trans->attrs[2]; grp = &trans->attrs[3]; DBG(DBG_CONTROL , DBG_log("initiating aggressive mode with IKE=E=%d-H=%d-M=%d" , enc->val , hash->val , grp->val)); passert(enc->type == OAKLEY_ENCRYPTION_ALGORITHM); ta.encrypt = enc->val; /* OAKLEY_ENCRYPTION_ALGORITHM */ ta.encrypter = crypto_get_encrypter(ta.encrypt); passert(ta.encrypter != NULL); ta.enckeylen = ta.encrypter->keydeflen; passert(hash->type == OAKLEY_HASH_ALGORITHM); ta.hash = hash->val; /* OAKLEY_HASH_ALGORITHM */ ta.hasher = crypto_get_hasher(ta.hash); passert(ta.hasher != NULL); passert(auth->type == OAKLEY_AUTHENTICATION_METHOD); ta.auth = auth->val; /* OAKLEY_AUTHENTICATION_METHOD */ passert(grp->type == OAKLEY_GROUP_DESCRIPTION); ta.group = lookup_group(grp->val); /* OAKLEY_GROUP_DESCRIPTION */ passert(ta.group != NULL); st->st_oakley = ta; return TRUE;}#endif/** * Parse the body of an IPsec SA Payload (i.e. Phase 2 / Quick Mode). * * The main routine is parse_ipsec_sa_body; other functions defined * between here and there are just helpers. * * 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 into it. * * 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! * * Only IPsec DOI is accepted (what is the ISAKMP DOI?). * Error response is rudimentary. * * Since all ISAKMP groups in all SA Payloads must match, st->st_pfs_group * holds this across multiple payloads. * &unset_group signifies not yet "set"; NULL signifies NONE. * * This routine is used by quick_inI1_outR1() and quick_inR1_outI2(). */static const struct ipsec_trans_attrs null_ipsec_trans_attrs = { 0, /* transid (NULL, for now) */ 0, /* spi */ SA_LIFE_DURATION_DEFAULT, /* life_seconds */ SA_LIFE_DURATION_K_DEFAULT, /* life_kilobytes */ ENCAPSULATION_MODE_UNSPECIFIED, /* encapsulation */ AUTH_ALGORITHM_NONE, /* auth */ 0, /* key_len */ 0, /* key_rounds */};static boolparse_ipsec_transform(struct isakmp_transform *trans, struct ipsec_trans_attrs *attrs, pb_stream *prop_pbs, pb_stream *trans_pbs, struct_desc *trans_desc, int previous_transnum /* or -1 if none */, bool selection, bool is_last, bool is_ipcomp, struct state *st) /* current state object */{ lset_t seen_attrs = 0 , seen_durations = 0; u_int16_t life_type; const struct oakley_group_desc *pfs_group = NULL; if (!in_struct(trans, trans_desc, prop_pbs, trans_pbs)) return FALSE; if (trans->isat_transnum <= previous_transnum) { loglog(RC_LOG_SERIOUS, "Transform Numbers in Proposal are not monotonically increasing"); return FALSE; } switch (trans->isat_np) { case ISAKMP_NEXT_T: if (is_last) { loglog(RC_LOG_SERIOUS, "Proposal Payload has more Transforms than specified"); return FALSE; } break; case ISAKMP_NEXT_NONE: if (!is_last) { loglog(RC_LOG_SERIOUS, "Proposal Payload has fewer Transforms than specified"); return FALSE; } break; default: loglog(RC_LOG_SERIOUS, "expecting Transform Payload, but found %s in Proposal" , enum_show(&payload_names, trans->isat_np)); return FALSE; } *attrs = null_ipsec_trans_attrs; attrs->transid = trans->isat_transid; while (pbs_left(trans_pbs) != 0) { struct isakmp_attribute a; pb_stream attr_pbs; enum_names *vdesc; u_int32_t val; /* room for larger value */ bool ipcomp_inappropriate = is_ipcomp; /* will get reset if OK */ if (!in_struct(&a, &isakmp_ipsec_attribute_desc, trans_pbs, &attr_pbs)) return FALSE; 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 IPsec Transform %u" , enum_show(&ipsec_attr_names, a.isaat_af_type) , trans->isat_transnum); return FALSE; } seen_attrs |= LELEM(a.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK); val = a.isaat_lv; vdesc = ipsec_attr_val_descs[a.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK]; if (vdesc != NULL) { if (enum_name(vdesc, val) == NULL) { loglog(RC_LOG_SERIOUS, "invalid value %u for attribute %s in IPsec Transform" , (unsigned)val, enum_show(&ipsec_attr_names, a.isaat_af_type)); return FALSE; } DBG(DBG_PARSING , if ((a.isaat_af_type & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV) DBG_log(" [%u is %s]" , (unsigned)val, enum_show(vdesc, val))); } switch (a.isaat_af_type) { case SA_LIFE_TYPE | ISAKMP_ATTR_AF_TV: ipcomp_inappropriate = FALSE; if (LHAS(seen_durations, val)) { loglog(RC_LOG_SERIOUS, "attribute SA_LIFE_TYPE value %s repeated in message"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -