kernel.c
来自「ipsec vpn」· C语言 代码 · 共 2,050 行 · 第 1/5 页
C
2,050 行
if (st->st_ipcomp.present) { ipsec_spi_t ipcomp_spi = inbound? st->st_ipcomp.our_spi : st->st_ipcomp.attrs.spi; unsigned compalg; switch (st->st_ipcomp.attrs.transid) { case IPCOMP_DEFLATE: compalg = SADB_X_CALG_DEFLATE; break; default: loglog(RC_LOG_SERIOUS, "IPCOMP transform %s not implemented" , enum_name(&ipcomp_transformid_names, st->st_ipcomp.attrs.transid)); goto fail; } set_text_said(text_said, &dst.addr, ipcomp_spi, SA_COMP); said_next->src = &src.addr; said_next->dst = &dst.addr; said_next->src_client = &src_client; said_next->dst_client = &dst_client; said_next->spi = ipcomp_spi; said_next->satype = SADB_X_SATYPE_COMP; said_next->encalg = compalg; said_next->encapsulation = encapsulation; said_next->reqid = c->spd.reqid + 2; said_next->text_said = text_said; if (!kernel_ops->add_sa(said_next, replace)) { DBG_log("add_sa ipcomp failed"); goto fail; } said_next++; encapsulation = ENCAPSULATION_MODE_TRANSPORT; } /* set up ESP SA, if any */ if (st->st_esp.present) { ipsec_spi_t esp_spi = inbound? st->st_esp.our_spi : st->st_esp.attrs.spi; u_char *esp_dst_keymat = inbound? st->st_esp.our_keymat : st->st_esp.peer_keymat; const struct esp_info *ei; u_int16_t key_len; static const struct esp_info esp_info[] = { { FALSE, ESP_NULL, AUTH_ALGORITHM_HMAC_MD5, 0, HMAC_MD5_KEY_LEN, SADB_EALG_NULL, SADB_AALG_MD5HMAC }, { FALSE, ESP_NULL, AUTH_ALGORITHM_HMAC_SHA1, 0, HMAC_SHA1_KEY_LEN, SADB_EALG_NULL, SADB_AALG_SHA1HMAC }, { FALSE, ESP_DES, AUTH_ALGORITHM_NONE, DES_CBC_BLOCK_SIZE, 0, SADB_EALG_DESCBC, SADB_AALG_NONE }, { FALSE, ESP_DES, AUTH_ALGORITHM_HMAC_MD5, DES_CBC_BLOCK_SIZE, HMAC_MD5_KEY_LEN, SADB_EALG_DESCBC, SADB_AALG_MD5HMAC }, { FALSE, ESP_DES, AUTH_ALGORITHM_HMAC_SHA1, DES_CBC_BLOCK_SIZE, HMAC_SHA1_KEY_LEN, SADB_EALG_DESCBC, SADB_AALG_SHA1HMAC }, { FALSE, ESP_3DES, AUTH_ALGORITHM_NONE, DES_CBC_BLOCK_SIZE * 3, 0, SADB_EALG_3DESCBC, SADB_AALG_NONE }, { FALSE, ESP_3DES, AUTH_ALGORITHM_HMAC_MD5, DES_CBC_BLOCK_SIZE * 3, HMAC_MD5_KEY_LEN, SADB_EALG_3DESCBC, SADB_AALG_MD5HMAC }, { FALSE, ESP_3DES, AUTH_ALGORITHM_HMAC_SHA1, DES_CBC_BLOCK_SIZE * 3, HMAC_SHA1_KEY_LEN, SADB_EALG_3DESCBC, SADB_AALG_SHA1HMAC }, { FALSE, ESP_AES, AUTH_ALGORITHM_NONE, AES_CBC_BLOCK_SIZE, 0, SADB_X_EALG_AESCBC, SADB_AALG_NONE }, { FALSE, ESP_AES, AUTH_ALGORITHM_HMAC_MD5, AES_CBC_BLOCK_SIZE, HMAC_MD5_KEY_LEN, SADB_X_EALG_AESCBC, SADB_AALG_MD5HMAC }, { FALSE, ESP_AES, AUTH_ALGORITHM_HMAC_SHA1, AES_CBC_BLOCK_SIZE, HMAC_SHA1_KEY_LEN, SADB_X_EALG_AESCBC, SADB_AALG_SHA1HMAC }, }; //static const int esp_max = elemsof(esp_info); //int esp_count;#ifdef NAT_TRAVERSAL u_int8_t natt_type = 0; u_int16_t natt_sport = 0, natt_dport = 0; ip_address natt_oa; if (st->hidden_variables.st_nat_traversal & NAT_T_DETECTED) { if(st->hidden_variables.st_nat_traversal & NAT_T_WITH_PORT_FLOATING) { natt_type = ESPINUDP_WITH_NON_ESP; } else { natt_type = ESPINUDP_WITH_NON_IKE; } if(inbound) { natt_sport = st->st_remoteport; natt_dport = st->st_localport; } else { natt_sport = st->st_localport; natt_dport = st->st_remoteport; } natt_oa = st->hidden_variables.st_nat_oa; }#endif DBG(DBG_CRYPT , DBG_log("looking for alg with transid: %d keylen: %d auth: %d\n" , st->st_esp.attrs.transid , st->st_esp.attrs.key_len , st->st_esp.attrs.auth)); for (ei = esp_info; ; ei++) { /* if it is the last key entry, then ask algo */ if (ei == &esp_info[elemsof(esp_info)]) { /* Check for additional kernel alg */#ifdef KERNEL_ALG if ((ei=kernel_alg_esp_info(st->st_esp.attrs.transid, st->st_esp.attrs.key_len, st->st_esp.attrs.auth))!=NULL) { break; }#endif /* note: enum_show may use a static buffer, so two * calls in one printf would be a mistake. * enum_name does the same job, without a static buffer, * assuming the name will be found. */ loglog(RC_LOG_SERIOUS, "ESP transform %s(%d) / auth %s not implemented yet" , enum_name(&esp_transformid_names, st->st_esp.attrs.transid) , st->st_esp.attrs.key_len , enum_name(&auth_alg_names, st->st_esp.attrs.auth)); goto fail; } DBG(DBG_CRYPT , DBG_log("checking transid: %d keylen: %d auth: %d\n" , ei->transid, ei->enckeylen, ei->auth)); if (st->st_esp.attrs.transid == ei->transid && (st->st_esp.attrs.key_len ==0 || st->st_esp.attrs.key_len == ei->enckeylen*8) && st->st_esp.attrs.auth == ei->auth) break; } if (st->st_esp.attrs.transid != ei->transid && st->st_esp.attrs.key_len != ei->enckeylen*8 && st->st_esp.attrs.auth != ei->auth) { loglog(RC_LOG_SERIOUS, "failed to find key info for %s/%s" , enum_name(&esp_transformid_names, st->st_esp.attrs.transid) , enum_name(&auth_alg_names, st->st_esp.attrs.auth)); goto fail; } key_len = st->st_esp.attrs.key_len/8; if (key_len) { /* XXX: must change to check valid _range_ key_len */ if (key_len > ei->enckeylen) { loglog(RC_LOG_SERIOUS, "ESP transform %s passed key_len=%d > %d", enum_name(&esp_transformid_names, st->st_esp.attrs.transid), (int)key_len, (int)ei->enckeylen); goto fail; } } else { key_len = ei->enckeylen; } /* Grrrrr.... f*cking 7 bits jurassic algos */ /* 168 bits in kernel, need 192 bits for keymat_len */ if (ei->transid == ESP_3DES && key_len == 21) key_len = 24; /* 56 bits in kernel, need 64 bits for keymat_len */ if (ei->transid == ESP_DES && key_len == 7) key_len = 8; /* divide up keying material */ /* passert(st->st_esp.keymat_len == ei->enckeylen + ei->authkeylen); */ if(st->st_esp.keymat_len != key_len + ei->authkeylen) DBG_log("keymat_len=%d key_len=%d authkeylen=%d", st->st_esp.keymat_len, (int)key_len, (int)ei->authkeylen); passert(st->st_esp.keymat_len == (key_len + ei->authkeylen)); set_text_said(text_said, &dst.addr, esp_spi, SA_ESP); said_next->src = &src.addr; said_next->dst = &dst.addr; said_next->src_client = &src_client; said_next->dst_client = &dst_client; said_next->spi = esp_spi; said_next->satype = SADB_SATYPE_ESP; said_next->replay_window = kernel_ops->replay_window; said_next->authalg = ei->authalg; said_next->authkeylen = ei->authkeylen; /* said_next->authkey = esp_dst_keymat + ei->enckeylen; */ said_next->authkey = esp_dst_keymat + key_len; said_next->encalg = ei->encryptalg; /* said_next->enckeylen = ei->enckeylen; */ said_next->enckeylen = key_len; said_next->enckey = esp_dst_keymat; said_next->encapsulation = encapsulation; said_next->reqid = c->spd.reqid + 1;#ifdef NAT_TRAVERSAL said_next->natt_sport = natt_sport; said_next->natt_dport = natt_dport; said_next->transid = st->st_esp.attrs.transid; said_next->natt_type = natt_type; said_next->natt_oa = &natt_oa;#endif said_next->text_said = text_said; if (!kernel_ops->add_sa(said_next, replace)) goto fail; said_next++; encapsulation = ENCAPSULATION_MODE_TRANSPORT; } /* set up AH SA, if any */ if (st->st_ah.present) { ipsec_spi_t ah_spi = inbound? st->st_ah.our_spi : st->st_ah.attrs.spi; u_char *ah_dst_keymat = inbound? st->st_ah.our_keymat : st->st_ah.peer_keymat; unsigned char authalg; switch (st->st_ah.attrs.auth) { case AUTH_ALGORITHM_HMAC_MD5: authalg = SADB_AALG_MD5HMAC; break; case AUTH_ALGORITHM_HMAC_SHA1: authalg = SADB_AALG_SHA1HMAC; break; case AUTH_ALGORITHM_KPDK: case AUTH_ALGORITHM_DES_MAC: default: loglog(RC_LOG_SERIOUS, "%s not implemented yet" , enum_show(&auth_alg_names, st->st_ah.attrs.auth)); goto fail; } set_text_said(text_said, &dst.addr, ah_spi, SA_AH); said_next->src = &src.addr; said_next->dst = &dst.addr; said_next->src_client = &src_client; said_next->dst_client = &dst_client; said_next->spi = ah_spi; said_next->satype = SADB_SATYPE_AH; said_next->replay_window = kernel_ops->replay_window; said_next->authalg = authalg; said_next->authkeylen = st->st_ah.keymat_len; said_next->authkey = ah_dst_keymat; said_next->encapsulation = encapsulation; said_next->reqid = c->spd.reqid; said_next->text_said = text_said; if (!kernel_ops->add_sa(said_next, replace)) goto fail; said_next++; encapsulation = ENCAPSULATION_MODE_TRANSPORT; } if (st->st_ah.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL || st->st_esp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL || st->st_ipcomp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL) { encapsulation = ENCAPSULATION_MODE_TUNNEL; } if (kernel_ops->inbound_eroute ? c->spd.eroute_owner == SOS_NOBODY : encapsulation == ENCAPSULATION_MODE_TUNNEL) { /* If inbound, and policy does not specifie DISABLEARRIVALCHECK, * tell KLIPS to enforce the IP addresses appropriate for this tunnel. * Note reversed ends. * Not much to be done on failure. */ if (inbound && (c->policy & POLICY_DISABLEARRIVALCHECK) == 0) { struct pfkey_proto_info proto_info[4]; int i = 0; if (st->st_ipcomp.present) { proto_info[i].proto = IPPROTO_COMP; proto_info[i].encapsulation = st->st_ipcomp.attrs.encapsulation; proto_info[i].reqid = c->spd.reqid + 2; i++; } if (st->st_esp.present) { proto_info[i].proto = IPPROTO_ESP; proto_info[i].encapsulation = st->st_esp.attrs.encapsulation; proto_info[i].reqid = c->spd.reqid + 1; i++; } if (st->st_ah.present) { proto_info[i].proto = IPPROTO_AH; proto_info[i].encapsulation = st->st_ah.attrs.encapsulation; proto_info[i].reqid = c->spd.reqid; i++; } proto_info[i].proto = 0; if (kernel_ops->inbound_eroute && encapsulation == ENCAPSULATION_MODE_TUNNEL) { proto_info[0].encapsulation = ENCAPSULATION_MODE_TUNNEL; for (i = 1; proto_info[i].proto; i++) { proto_info[i].encapsulation = ENCAPSULATION_MODE_TRANSPORT; } } /* MCR - should be passed a spd_eroute structure here */ (void) raw_eroute(&c->spd.that.host_addr, &c->spd.that.client , &c->spd.this.host_addr, &c->spd.this.client , inner_spi, proto , c->spd.this.protocol , satype , proto_info, 0 , ERO_ADD_INBOUND, "add inbound"); } } /* If there are multiple SPIs, group them. */ if (kernel_ops->grp_sa && said_next > &said[1]) { struct kernel_sa *s; /* group SAs, two at a time, inner to outer (backwards in said[]) * The grouping is by pairs. So if said[] contains ah esp ipip, * the grouping would be ipip:esp, esp:ah. */ for (s = said; s < said_next-1; s++) { char text_said0[SATOT_BUF], text_said1[SATOT_BUF]; /* group s[1] and s[0], in that order */ set_text_said(text_said0, s[0].dst, s[0].spi, s[0].proto); set_text_said(text_said1, s[1].dst, s[1].spi, s[1].proto); DBG(DBG_KLIPS, DBG_log("grouping %s and %s", text_said1, text_said0)); s[0].text_said = text_said0; s[1].text_said = text_said1; if (!kernel_ops->grp_sa(s + 1, s)) goto fail; } /* could update said, but it will not be used */ }#ifdef DEBUG /* if the impaired is set, pretend this fails */ if(st->st_connection->extra_debugging & IMPAIR_SA_CREATION) { DBG_log("Impair SA creation is set, pretending to fail"); goto fail; }#endif return TRUE;fail: { /* undo the done SPIs */ while (said_next-- != said) { if(said_next->proto) { (void) del_spi(said_next->spi, said_next->proto , &src.addr, said_next->dst); } } return FALSE; }}/* teardown_ipsec_sa is a canibalized version of setup_ipsec_sa */static boolteardown_half_ipsec_sa(struct state *st, bool inbound){ /* We n
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?