📄 connections.c
字号:
#endif dst->protocol = src->protocol; dst->port = src->port; dst->has_port_wildcard = src->has_port_wildcard; dst->key_from_DNS_on_demand = src->key_from_DNS_on_demand; dst->has_client = src->has_client; dst->has_client_wildcard = src->has_client_wildcard; dst->updown = src->updown; dst->host_port = src->host_port; DBG(DBG_CONTROL, DBG_log("sendcert is %d", src->sendcert)); dst->sendcert = src->sendcert; return same_ca;}static boolcheck_connection_end(const struct whack_end *this, const struct whack_end *that, const struct whack_message *wm){ if (wm->addr_family != addrtypeof(&this->host_addr) || wm->addr_family != addrtypeof(&this->host_nexthop) || (this->has_client? wm->tunnel_addr_family : wm->addr_family) != subnettypeof(&this->client) || subnettypeof(&this->client) != subnettypeof(&that->client)) { /* this should have been diagnosed by whack, so we need not be clear * !!! overloaded use of RC_CLASH */ loglog(RC_CLASH, "address family inconsistency in connection"); return FALSE; } if (isanyaddr(&that->host_addr)) { /* other side is wildcard: we must check if other conditions met */ if (isanyaddr(&this->host_addr)) { loglog(RC_ORIENT, "connection must specify host IP address for our side"); return FALSE; } else if (!NEVER_NEGOTIATE(wm->policy)) { /* check that all main mode RW IKE policies agree because we must * implement them before the correct connection is known. * We cannot enforce this for other non-RW connections because * differentiation is possible when a command specifies which * to initiate. * aggressive mode IKE policies do not have to agree amongst * themselves as the ID is known from the outset. */ const struct connection *c = NULL; c = find_host_pair_connections(&this->host_addr , this->host_port, (const ip_address *)NULL, that->host_port); for (; c != NULL; c = c->hp_next) { if (c->policy & POLICY_AGGRESSIVE) continue; if (!NEVER_NEGOTIATE(c->policy) && ((c->policy ^ wm->policy) & (POLICY_PSK | POLICY_RSASIG))) { loglog(RC_CLASH , "authentication method disagrees with \"%s\", which is also for an unspecified peer" , c->name); return FALSE; } } } }#ifdef VIRTUAL_IP if ((this->virt) && (!isanyaddr(&this->host_addr) || this->has_client)) { loglog(RC_CLASH, "virtual IP must only be used with %%any and without client"); return FALSE; }#endif return TRUE; /* happy */}struct connection *find_connection_by_reqid(uint32_t reqid){ struct connection *c; reqid &= ~3; for (c = connections; c != NULL; c = c->ac_next) { if (c->spd.reqid == reqid) return c; } return NULL;}static uint32_tgen_reqid(void){ uint32_t start; static uint32_t reqid = IPSEC_MANUAL_REQID_MAX & ~3; start = reqid; do { reqid += 4; if (reqid == 0) reqid = (IPSEC_MANUAL_REQID_MAX & ~3) + 4; if (!find_connection_by_reqid(reqid)) return reqid; } while (reqid != start); exit_log("unable to allocate reqid");}voidadd_connection(const struct whack_message *wm){ struct alg_info_ike *alg_info_ike; const char *ugh; if (con_by_name(wm->name, FALSE) != NULL) { loglog(RC_DUPNAME, "attempt to redefine connection \"%s\"", wm->name); } else if (wm->right.protocol != wm->left.protocol) { /* this should haven been diagnosed by whack * !!! overloaded use of RC_CLASH */ loglog(RC_CLASH, "the protocol must be the same for leftport and rightport"); } else if(wm->ike != NULL && ((alg_info_ike = alg_info_ike_create_from_str(wm->ike, &ugh))==NULL || alg_info_ike->alg_info_cnt==0)) { if (alg_info_ike!= NULL && alg_info_ike->alg_info_cnt==0) { loglog(RC_NOALGO , "got 0 transforms for esp=\"%s\"" , wm->esp); return; } loglog(RC_NOALGO , "esp string error: %s" , ugh? ugh : "Unknown"); return; } else if (check_connection_end(&wm->right, &wm->left, wm) && check_connection_end(&wm->left, &wm->right, wm)) { bool same_rightca, same_leftca; struct connection *c = alloc_thing(struct connection, "struct connection"); same_rightca = same_leftca = FALSE; c->name = wm->name; c->policy = wm->policy; DBG(DBG_CONTROL, DBG_log("Added new connection %s with policy %s" , c->name , prettypolicy(c->policy))); if ((c->policy & POLICY_COMPRESS) && !can_do_IPcomp) loglog(RC_COMMENT , "ignoring --compress in \"%s\" because KLIPS is not configured to do IPCOMP" , c->name); c->alg_info_esp = NULL;#ifdef KERNEL_ALG if (wm->esp) { DBG(DBG_CONTROL, DBG_log("from whack: got --esp=%s", wm->esp ? wm->esp: "NULL")); c->alg_info_esp = alg_info_esp_create_from_str(wm->esp? wm->esp : "", &ugh, FALSE); DBG(DBG_CRYPT|DBG_CONTROL, static char buf[256]="<NULL>"; if (c->alg_info_esp) alg_info_snprint(buf, sizeof(buf), (struct alg_info *)c->alg_info_esp, TRUE); DBG_log("esp string values: %s", buf); ); if (c->alg_info_esp) { if (c->alg_info_esp->alg_info_cnt==0) { loglog(RC_NOALGO , "got 0 transforms for esp=\"%s\"" , wm->esp); return; } } else { loglog(RC_NOALGO , "esp string error: %s" , ugh? ugh : "Unknown"); return; } }#endif c->alg_info_ike = NULL;#ifdef IKE_ALG if (wm->ike) { c->alg_info_ike = alg_info_ike; DBG(DBG_CONTROL, DBG_log("from whack: got --ike=%s", wm->ike)); DBG(DBG_CRYPT|DBG_CONTROL, char buf[256]; alg_info_snprint(buf, sizeof(buf), (struct alg_info *)c->alg_info_ike, TRUE); DBG_log("ike string values: %s", buf); ); }#endif c->sa_ike_life_seconds = wm->sa_ike_life_seconds; c->sa_ipsec_life_seconds = wm->sa_ipsec_life_seconds; c->sa_rekey_margin = wm->sa_rekey_margin; c->sa_rekey_fuzz = wm->sa_rekey_fuzz; c->sa_keying_tries = wm->sa_keying_tries; /* RFC 3706 DPD */ c->dpd_delay = wm->dpd_delay; c->dpd_timeout = wm->dpd_timeout; c->dpd_action = wm->dpd_action; c->forceencaps = wm->forceencaps; c->addr_family = wm->addr_family; c->tunnel_addr_family = wm->tunnel_addr_family; c->requested_ca = NULL; same_leftca = extract_end(&c->spd.this, &wm->left, "left"); same_rightca = extract_end(&c->spd.that, &wm->right, "right"); if (same_rightca) c->spd.that.ca = c->spd.this.ca; else if (same_leftca) c->spd.this.ca = c->spd.that.ca; default_end(&c->spd.this, &c->spd.that.host_addr); default_end(&c->spd.that, &c->spd.this.host_addr); /* force any wildcard host IP address, any wildcard subnet * or any wildcard ID to that end */ if (isanyaddr(&c->spd.this.host_addr) || c->spd.this.has_client_wildcard || c->spd.this.has_port_wildcard || c->spd.this.has_id_wildcards) { struct end t = c->spd.this; c->spd.this = c->spd.that; c->spd.that = t; } c->spd.next = NULL; c->spd.reqid = gen_reqid(); /* set internal fields */ c->instance_serial = 0; c->ac_next = connections; connections = c; c->interface = NULL; c->spd.routing = RT_UNROUTED; c->newest_isakmp_sa = SOS_NOBODY; c->newest_ipsec_sa = SOS_NOBODY; c->spd.eroute_owner = SOS_NOBODY; if (c->policy & POLICY_GROUP) { c->kind = CK_GROUP; add_group(c); } else if ((isanyaddr(&c->spd.that.host_addr) && !NEVER_NEGOTIATE(c->policy)) || c->spd.that.has_client_wildcard || c->spd.that.has_port_wildcard || ((c->policy & POLICY_SHUNT_MASK) == 0 && c->spd.that.has_id_wildcards )) { DBG(DBG_CONTROL, DBG_log("based upon policy, the connection is a template.")); /* Opportunistic or Road Warrior or wildcard client subnet * or wildcard ID */ c->kind = CK_TEMPLATE; } else { c->kind = CK_PERMANENT; } set_policy_prio(c); /* must be after kind is set */#ifdef DEBUG c->extra_debugging = wm->debugging;#endif c->gw_info = NULL;#ifdef VIRTUAL_IP passert(!(wm->left.virt && wm->right.virt)); if (wm->left.virt || wm->right.virt) { passert(isanyaddr(&c->spd.that.host_addr)); c->spd.that.virt = create_virtual(c, wm->left.virt ? wm->left.virt : wm->right.virt); if (c->spd.that.virt) c->spd.that.has_client = TRUE; }#endif unshare_connection_strings(c);#ifdef KERNEL_ALG alg_info_addref((struct alg_info *)c->alg_info_esp);#endif#ifdef IKE_ALG alg_info_addref((struct alg_info *)c->alg_info_ike);#endif (void)orient(c); connect_to_host_pair(c); /* log all about this connection */ openswan_log("added connection description \"%s\"", c->name); DBG(DBG_CONTROL, char topo[CONNECTION_BUF]; (void) format_connection(topo, sizeof(topo), c, &c->spd); DBG_log("%s", topo); /* Make sure that address families can be correctly inferred * from printed ends. */ passert(c->addr_family == addrtypeof(&c->spd.this.host_addr) && c->addr_family == addrtypeof(&c->spd.this.host_nexthop) && (c->spd.this.has_client? c->tunnel_addr_family : c->addr_family) == subnettypeof(&c->spd.this.client) && c->addr_family == addrtypeof(&c->spd.that.host_addr) && c->addr_family == addrtypeof(&c->spd.that.host_nexthop) && (c->spd.that.has_client? c->tunnel_addr_family : c->addr_family) == subnettypeof(&c->spd.that.client)); DBG_log("ike_life: %lus; ipsec_life: %lus; rekey_margin: %lus;" " rekey_fuzz: %lu%%; keyingtries: %lu; policy: %s" , (unsigned long) c->sa_ike_life_seconds , (unsigned long) c->sa_ipsec_life_seconds , (unsigned long) c->sa_rekey_margin , (unsigned long) c->sa_rekey_fuzz , (unsigned long) c->sa_keying_tries , prettypolicy(c->policy)); ); }}/* Derive a template connection from a group connection and target. * Similar to instantiate(). Happens at whack --listen. * Returns name of new connection. May be NULL. * Caller is responsible for pfreeing. */char *add_group_instance(struct connection *group, const ip_subnet *target){ char namebuf[100] , targetbuf[SUBNETTOT_BUF]; struct connection *t; char *name = NULL; passert(group->kind == CK_GROUP); passert(oriented(*group)); /* manufacture a unique name for this template */ subnettot(target, 0, targetbuf, sizeof(targetbuf)); snprintf(namebuf, sizeof(namebuf), "%s#%s", group->name, targetbuf); if (con_by_name(namebuf, FALSE) != NULL) { loglog(RC_DUPNAME, "group name + target yields duplicate name \"%s\"" , namebuf); } else { t = clone_thing(*group, "group instance"); t->name = namebuf; unshare_connection_strings(t); name = clone_str(t->name, "group instance name"); t->spd.that.client = *target; t->policy &= ~(POLICY_GROUP | POLICY_GROUTED); t->kind = isanyaddr(&t->spd.that.host_addr) && !NEVER_NEGOTIATE(t->policy) ? CK_TEMPLATE : CK_INSTANCE; /* reset log file info */ t->log_file_name = NULL; t->log_file = NULL; t->log_file_err = FALSE; t->spd.reqid = gen_reqid();#ifdef VIRTUAL_IP if (t->spd.that.virt) { DBG_log("virtual_ip not supported in group instance"); t->spd.that.virt = NULL; }#endif /* add to connections list */ t->ac_next = connections; connections = t; /* same host_pair as parent: stick after parent on list */ group->hp_next = t; /* route if group is routed */ if (group->policy & POLICY_GROUTED) { if (!trap_connection(t)) whack_log(RC_ROUTE, "could not route"); } } return name;}/* an old target has disappeared for a group: delete instance */voidremove_group_instance(const struct connection *group USED_BY_DEBUG, const char *name){ passert(group->kind == CK_GROUP); passert(oriented(*group)); delete_connections_by_name(name, FALSE);}/* Common part of instantiating a Road Warrior or Opportunistic connection. * his_id can be used to carry over an ID discovered in Phase 1. * It must not disagree with the one in c, but if that is unspecified, * the new connection will use his_id. * If his_id is NULL, and c.that.id is uninstantiated (ID_NONE), the * new connection will continue to have an uninstantiated that.id. * Note: instantiation does not affect port numbers. * * Note that instantiate can only deal with a single SPD/eroute. */static struct connection *instantiate(struct connection *c, const ip_address *him#ifdef NAT_TRAVERSAL, u_int16_t his_port#endif, const struct id *his_id){ struct connection *d; int wildcards; passert(c->kind == CK_TEMPLATE); passert(c->spd.next == NULL); c->instance_serial++; d = clone_thing(*c, "temporary connection"); if (his_id != NULL) { passert(match_id(his_id, &d->spd.that.id, &wildcards)); d->spd.that.id = *his_id; d->spd.that.has_id_wildcards = FALSE; } unshare_connection_strings(d); unshare_ietfAttrList(&d->spd.this.groups); unshare_ietfAttrList(&d->spd.that.groups);#ifdef KERNEL_ALG alg_info_addref((struct alg_info *)d->alg_info_esp);#endif#ifdef IKE_ALG alg_info_addref((struct alg_info *)d->alg_info_ike);#endif d->kind = CK_INSTANCE; passert(oriented(*d)); d->spd.that.host_addr = *him; setportof(htons(c->spd.that.port), &d->spd.that.host_addr);#ifdef NAT_TRAVERSAL if (his_port) d->spd.that.host_port = his_port;#endif default_end(&d->spd.that, &d->spd.this.host_addr); /* We cannot guess what our next_hop should be, but if it was * explicitly specified as 0.0.0.0, we set it to be him. * (whack will not allow nexthop to be elided in RW case.) */ default_end(&d->spd.this, &d->spd.that.host_addr); d->spd.next = NULL; d->spd.reqid = gen_reqid(); /* set internal fields */ d->ac_next = connections; connections = d; d->spd.routing = RT_UNROUTED; d->newest_isakmp_sa = SOS_NOBODY; d->newest_ipsec_sa = SOS_NOBODY; d->spd.eroute_owner = SOS_NOBODY; /* reset log file info */ d->log_file_name = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -