📄 spdb_struct.c
字号:
loglog(RC_LOG_SERIOUS, "IPsec SA contains two simultaneous AH Proposals"); return BAD_PROPOSAL_SYNTAX; } ah_seen = TRUE; ah_prop_pbs = next_proposal_pbs; ah_proposal = next_proposal; ah_spi = next_spi; break; case PROTO_IPSEC_ESP: if (esp_seen) { loglog(RC_LOG_SERIOUS, "IPsec SA contains two simultaneous ESP Proposals"); return BAD_PROPOSAL_SYNTAX; } esp_seen = TRUE; esp_prop_pbs = next_proposal_pbs; esp_proposal = next_proposal; esp_spi = next_spi; break; case PROTO_IPCOMP: if (ipcomp_seen) { loglog(RC_LOG_SERIOUS, "IPsec SA contains two simultaneous IPCOMP Proposals"); return BAD_PROPOSAL_SYNTAX; } ipcomp_seen = TRUE; ipcomp_prop_pbs = next_proposal_pbs; ipcomp_proposal = next_proposal; ipcomp_cpi = next_spi; break; default: loglog(RC_LOG_SERIOUS, "unexpected Protocol ID (%s) in IPsec Proposal" , enum_show(&protocol_names, next_proposal.isap_protoid)); return INVALID_PROTOCOL_ID; } /* refill next_proposal */ if (next_proposal.isap_np == ISAKMP_NEXT_NONE) { next_full = FALSE; break; } else if (next_proposal.isap_np != ISAKMP_NEXT_P) { loglog(RC_LOG_SERIOUS, "unexpected in Proposal: %s" , enum_show(&payload_names, next_proposal.isap_np)); return BAD_PROPOSAL_SYNTAX; } if (!in_struct(&next_proposal, &isakmp_proposal_desc, sa_pbs, &next_proposal_pbs)) return BAD_PROPOSAL_SYNTAX; } while (next_proposal.isap_proposal == propno); /* Now that we have all conjuncts, we should try * the Cartesian product of eachs tranforms! * At the moment, we take short-cuts on account of * our rudimentary hard-wired policy. * For now, we find an acceptable AH (if any) * and then an acceptable ESP. The only interaction * is that the ESP acceptance can know whether there * was an acceptable AH and hence not require an AUTH. */ if (ah_seen) { int previous_transnum = -1; int tn; for (tn = 0; tn != ah_proposal.isap_notrans; tn++) { int ok_transid = 0; bool ok_auth = FALSE; if (!parse_ipsec_transform(&ah_trans , &ah_attrs , &ah_prop_pbs , &ah_trans_pbs , &isakmp_ah_transform_desc , previous_transnum , selection , tn == ah_proposal.isap_notrans - 1 , FALSE , st)) return BAD_PROPOSAL_SYNTAX; previous_transnum = ah_trans.isat_transnum; /* we must understand ah_attrs.transid * COMBINED with ah_attrs.auth. * See RFC 2407 "IPsec DOI" section 4.4.3 * The following combinations are legal, * but we don't implement all of them: * It seems as if each auth algorithm * only applies to one ah transid. * AH_MD5, AUTH_ALGORITHM_HMAC_MD5 * AH_MD5, AUTH_ALGORITHM_KPDK (unimplemented) * AH_SHA, AUTH_ALGORITHM_HMAC_SHA1 * AH_DES, AUTH_ALGORITHM_DES_MAC (unimplemented) */ switch (ah_attrs.auth) { case AUTH_ALGORITHM_NONE: loglog(RC_LOG_SERIOUS, "AUTH_ALGORITHM attribute missing in AH Transform"); return BAD_PROPOSAL_SYNTAX; case AUTH_ALGORITHM_HMAC_MD5: ok_auth = TRUE; /* fall through */ case AUTH_ALGORITHM_KPDK: ok_transid = AH_MD5; break; case AUTH_ALGORITHM_HMAC_SHA1: ok_auth = TRUE; ok_transid = AH_SHA; break; case AUTH_ALGORITHM_DES_MAC: ok_transid = AH_DES; break; } if (ah_attrs.transid != ok_transid) { loglog(RC_LOG_SERIOUS, "%s attribute inappropriate in %s Transform" , enum_name(&auth_alg_names, ah_attrs.auth) , enum_show(&ah_transformid_names, ah_attrs.transid)); return BAD_PROPOSAL_SYNTAX; } if (!ok_auth) { DBG(DBG_CONTROL | DBG_CRYPT , DBG_log("%s attribute unsupported" " in %s Transform from %s" , enum_name(&auth_alg_names, ah_attrs.auth) , enum_show(&ah_transformid_names, ah_attrs.transid) , ip_str(&c->spd.that.host_addr))); continue; /* try another */ } break; /* we seem to be happy */ } if (tn == ah_proposal.isap_notrans) continue; /* we didn't find a nice one */ ah_attrs.spi = ah_spi; inner_proto = IPPROTO_AH; if (ah_attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL) tunnel_mode = TRUE; } if (esp_seen) { int previous_transnum = -1; int tn; err_t ugh; for (tn = 0; tn != esp_proposal.isap_notrans; tn++) { if (!parse_ipsec_transform(&esp_trans , &esp_attrs , &esp_prop_pbs , &esp_trans_pbs , &isakmp_esp_transform_desc , previous_transnum , selection , tn == esp_proposal.isap_notrans - 1 , FALSE , st)) return BAD_PROPOSAL_SYNTAX; previous_transnum = esp_trans.isat_transnum; ugh = "no alg";#ifdef KERNEL_ALG if(c->alg_info_esp) { ugh = kernel_alg_esp_enc_ok(esp_attrs.transid, esp_attrs.key_len, c->alg_info_esp); }#endif if(ugh != NULL) { switch (esp_attrs.transid) {#ifdef KERNEL_ALG /* strictly use runtime information */ case ESP_AES: case ESP_3DES: break;#endif #ifdef SUPPORT_ESP_NULL /* should be about as secure as AH-only */#warning "Building with ESP-Null" case ESP_NULL: if (esp_attrs.auth == AUTH_ALGORITHM_NONE) { loglog(RC_LOG_SERIOUS, "ESP_NULL requires auth algorithm"); return BAD_PROPOSAL_SYNTAX; } if (st->st_policy & POLICY_ENCRYPT) { DBG(DBG_CONTROL | DBG_CRYPT , DBG_log("ESP_NULL Transform Proposal from %s" " does not satisfy POLICY_ENCRYPT" , ip_str(&c->spd.that.host_addr))); continue; /* try another */ } break;#endif case ESP_DES: /* NOT safe */ loglog(RC_LOG_SERIOUS, "1DES was proposed, it is insecure"); default: loglog(RC_LOG_SERIOUS, "kernel algorithm does not like: %s", ugh); loglog(RC_LOG_SERIOUS, "unsupported ESP Transform %s from %s" , enum_show(&esp_transformid_names, esp_attrs.transid) , ip_str(&c->spd.that.host_addr)); continue; /* try another */ } }#ifdef KERNEL_ALG ugh = kernel_alg_esp_auth_ok(esp_attrs.auth, c->alg_info_esp);#endif if(ugh != NULL) { switch (esp_attrs.auth) { case AUTH_ALGORITHM_NONE: if (!ah_seen) { DBG(DBG_CONTROL | DBG_CRYPT , DBG_log("ESP from %s must either have AUTH or be combined with AH" , ip_str(&c->spd.that.host_addr))); continue; /* try another */ } break;#ifdef KERNEL_ALG /* strictly use runtime information */ case AUTH_ALGORITHM_HMAC_MD5: case AUTH_ALGORITHM_HMAC_SHA1: break;#endif default: loglog(RC_LOG_SERIOUS, "unsupported ESP auth alg %s from %s" , enum_show(&auth_alg_names, esp_attrs.auth) , ip_str(&c->spd.that.host_addr)); continue; /* try another */ } } if (ah_seen && ah_attrs.encapsulation != esp_attrs.encapsulation) { /* ??? This should be an error, but is it? */ loglog(RC_LOG_SERIOUS , "AH and ESP transforms disagree about encapsulation; TUNNEL presumed"); } break; /* we seem to be happy */ } if (tn == esp_proposal.isap_notrans) continue; /* we didn't find a nice one */#ifdef KERNEL_ALG /* * ML: at last check for allowed transforms in alg_info_esp * (ALG_INFO_F_STRICT flag) * */ if (c->alg_info_esp!=NULL && !kernel_alg_esp_ok_final(esp_attrs.transid, esp_attrs.key_len, esp_attrs.auth, c->alg_info_esp)) continue;#endif esp_attrs.spi = esp_spi; inner_proto = IPPROTO_ESP; if (esp_attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL) tunnel_mode = TRUE; } else if (st->st_policy & POLICY_ENCRYPT) { DBG(DBG_CONTROL | DBG_CRYPT , DBG_log("policy for \"%s\" requires encryption but ESP not in Proposal from %s" , c->name, ip_str(&c->spd.that.host_addr))); continue; /* we needed encryption, but didn't find ESP */ } else if ((st->st_policy & POLICY_AUTHENTICATE) && !ah_seen) { DBG(DBG_CONTROL | DBG_CRYPT , DBG_log("policy for \"%s\" requires authentication" " but none in Proposal from %s" , c->name, ip_str(&c->spd.that.host_addr))); continue; /* we need authentication, but we found neither ESP nor AH */ } if (ipcomp_seen) { int previous_transnum = -1; int tn;#ifdef NEVER /* we think IPcomp is working now */ /**** FUDGE TO PREVENT UNREQUESTED IPCOMP: **** NEEDED BECAUSE OUR IPCOMP IS EXPERIMENTAL (UNSTABLE). ****/ if (!(st->st_policy & POLICY_COMPRESS)) { plog("compression proposed by %s, but policy for \"%s\" forbids it" , ip_str(&c->spd.that.host_addr), c->name); continue; /* unwanted compression proposal */ }#endif if (!can_do_IPcomp) { openswan_log("compression proposed by %s, but KLIPS is not configured with IPCOMP" , ip_str(&c->spd.that.host_addr)); continue; } if (well_known_cpi != 0 && !ah_seen && !esp_seen) { openswan_log("illegal proposal: bare IPCOMP used with well-known CPI"); return BAD_PROPOSAL_SYNTAX; } for (tn = 0; tn != ipcomp_proposal.isap_notrans; tn++) { if (!parse_ipsec_transform(&ipcomp_trans , &ipcomp_attrs , &ipcomp_prop_pbs , &ipcomp_trans_pbs , &isakmp_ipcomp_transform_desc , previous_transnum , selection , tn == ipcomp_proposal.isap_notrans - 1 , TRUE , st)) return BAD_PROPOSAL_SYNTAX; previous_transnum = ipcomp_trans.isat_transnum; if (well_known_cpi != 0 && ipcomp_attrs.transid != well_known_cpi) { openswan_log("illegal proposal: IPCOMP well-known CPI disagrees with transform"); return BAD_PROPOSAL_SYNTAX; } switch (ipcomp_attrs.transid) { case IPCOMP_DEFLATE: /* all we can handle! */ break; default: DBG(DBG_CONTROL | DBG_CRYPT , DBG_log("unsupported IPCOMP Transform %s from %s" , enum_show(&ipcomp_transformid_names, ipcomp_attrs.transid) , ip_str(&c->spd.that.host_addr))); continue; /* try another */ } if (ah_seen && ah_attrs.encapsulation != ipcomp_attrs.encapsulation) { /* ??? This should be an error, but is it? */ DBG(DBG_CONTROL | DBG_CRYPT , DBG_log("AH and IPCOMP transforms disagree about encapsulation; TUNNEL presumed")); } else if (esp_seen && esp_attrs.encapsulation != ipcomp_attrs.encapsulation) { /* ??? This should be an error, but is it? */ DBG(DBG_CONTROL | DBG_CRYPT , DBG_log("ESP and IPCOMP transforms disagree about encapsulation; TUNNEL presumed")); } break; /* we seem to be happy */ } if (tn == ipcomp_proposal.isap_notrans) continue; /* we didn't find a nice one */ ipcomp_attrs.spi = ipcomp_cpi; inner_proto = IPPROTO_COMP; if (ipcomp_attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL) tunnel_mode = TRUE; } /* Eureka: we liked what we saw -- accept it. */ if (r_sa_pbs != NULL) { /* emit what we've accepted */ /* Situation */ if (!out_struct(&ipsecdoisit, &ipsec_sit_desc, r_sa_pbs, NULL)) impossible(); /* AH proposal */ if (ah_seen) echo_proposal(ah_proposal , ah_trans , esp_seen || ipcomp_seen? ISAKMP_NEXT_P : ISAKMP_NEXT_NONE , r_sa_pbs , &st->st_ah , &isakmp_ah_transform_desc , &ah_trans_pbs , &st->st_connection->spd , tunnel_mode && inner_proto == IPPROTO_AH); /* ESP proposal */ if (esp_seen) echo_proposal(esp_proposal , esp_trans , ipcomp_seen? ISAKMP_NEXT_P : ISAKMP_NEXT_NONE , r_sa_pbs , &st->st_esp , &isakmp_esp_transform_desc , &esp_trans_pbs , &st->st_connection->spd , tunnel_mode && inner_proto == IPPROTO_ESP); /* IPCOMP proposal */ if (ipcomp_seen) echo_proposal(ipcomp_proposal , ipcomp_trans , ISAKMP_NEXT_NONE , r_sa_pbs , &st->st_ipcomp , &isakmp_ipcomp_transform_desc , &ipcomp_trans_pbs , &st->st_connection->spd , tunnel_mode && inner_proto == IPPROTO_COMP); close_output_pbs(r_sa_pbs); } /* save decoded version of winning SA in state */ st->st_ah.present = ah_seen; if (ah_seen) st->st_ah.attrs = ah_attrs; st->st_esp.present = esp_seen; if (esp_seen) st->st_esp.attrs = esp_attrs; st->st_ipcomp.present = ipcomp_seen; if (ipcomp_seen) st->st_ipcomp.attrs = ipcomp_attrs; return NOTHING_WRONG; } loglog(RC_LOG_SERIOUS, "no acceptable Proposal in IPsec SA"); return NO_PROPOSAL_CHOSEN;}/* * Local Variables: * c-style: pluto * c-basic-offset: 4 * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -