📄 connections.c
字号:
static boolextract_end(struct end *dst, const struct whack_end *src, const char *which){ bool same_ca = FALSE; /* decode id, if any */ if (src->id == NULL) { dst->id.kind = ID_NONE; } else { err_t ugh = atoid(src->id, &dst->id, TRUE); if (ugh != NULL) { loglog(RC_BADID, "bad %s --id: %s (ignored)", which, ugh); dst->id = empty_id; /* ignore bad one */ } } dst->ca = empty_chunk; /* decode CA distinguished name, if any */ if (src->ca != NULL) { if streq(src->ca, "%same") same_ca = TRUE; else if (!streq(src->ca, "%any")) { err_t ugh; dst->ca.ptr = temporary_cyclic_buffer(); ugh = atodn(src->ca, &dst->ca); if (ugh != NULL) { openswan_log("bad CA string '%s': %s (ignored)", src->ca, ugh); dst->ca = empty_chunk; } } } if(src->sendcert == cert_forcedtype) { /* certificate is a blob */ dst->cert.forced = TRUE; dst->cert.type = src->certtype; load_cert(TRUE, src->cert, "forced cert", &dst->cert); } else { /* load local end certificate and extract ID, if any */ load_end_certificate(src->cert, dst); } /* does id has wildcards? */ dst->has_id_wildcards = id_count_wildcards(&dst->id) > 0; /* decode group attributes, if any */ decode_groups(src->groups, &dst->groups); /* the rest is simple copying of corresponding fields */ dst->host_addr = src->host_addr; dst->host_nexthop = src->host_nexthop; dst->host_srcip = src->host_srcip; dst->client = src->client;#ifdef MODECFG dst->modecfg_server = src->modecfg_server; dst->modecfg_client = src->modecfg_client;#endif#ifdef XAUTH dst->xauth_server = src->xauth_server; dst->xauth_client = src->xauth_client;#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 = IKE_UDP_PORT; if(src->host_port != IKE_UDP_PORT) { dst->host_port = src->host_port; dst->host_port_specific = TRUE; } 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(__FUNCTION__ , &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; alg_info_ike = NULL; 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 ike=\"%s\"" , wm->esp); return; } loglog(RC_NOALGO , "esp string error: %s" , ugh? ugh : "Unknown"); return; } else if ((wm->ike == NULL || alg_info_ike != NULL) && 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; } c->alg_esp = clone_str(wm->esp, "esp string"); }#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); ); if (c->alg_info_ike) { if (c->alg_info_ike->alg_info_cnt==0) { loglog(RC_NOALGO , "got 0 transforms for ike=\"%s\"" , wm->ike); return; } } else { loglog(RC_NOALGO , "ike string error: %s" , ugh? ugh : "Unknown"); return; } c->alg_ike = clone_str(wm->ike, "ike string"); }#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)); ); } else { loglog(RC_FATAL, "attempt to load incomplete connection"); }}/* 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; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -