⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 connections.c

📁 ipsec vpn
💻 C
📖 第 1 页 / 共 5 页
字号:
		    }		    DBG(DBG_OPPO,			DBG_log("comparing best %s to %s"				, best->name, c->name));		    for (bestsr = &best->spd; best!=c && bestsr; bestsr=bestsr->next)		    {			if (!subnetinsubnet(&bestsr->this.client, &sr->this.client)			|| (samesubnet(&bestsr->this.client, &sr->this.client)			     && !subnetinsubnet(&bestsr->that.client						, &sr->that.client)))			{			    best = c;			}		    }		}	    }	}    }    if (best == NULL    || NEVER_NEGOTIATE(best->policy)    || (best->policy & POLICY_OPPO) == LEMPTY    || best->kind != CK_TEMPLATE)	return NULL;    else	return oppo_instantiate(best, &gw->gw_id.ip_addr, NULL, gw			      , our_client, peer_client);}boolorient(struct connection *c){    struct spd_route *sr;    if (!oriented(*c))    {	struct iface_port *p;	for (sr = &c->spd; sr; sr = sr->next)	{	    /* Note: this loop does not stop when it finds a match:	     * it continues checking to catch any ambiguity.	     */	    for (p = interfaces; p != NULL; p = p->next)	    {#ifdef NAT_TRAVERSAL		if (p->ike_float) continue;#endif		for (;;)		{		    /* check if this interface matches this end */		    if (sameaddr(&sr->this.host_addr, &p->ip_addr)			&& (kern_interface != NO_KERNEL			    || sr->this.host_port == pluto_port))		    {			if (oriented(*c))			{			    if (c->interface->ip_dev == p->ip_dev)				loglog(RC_LOG_SERIOUS				       , "both sides of \"%s\" are our interface %s!"				       , c->name, p->ip_dev->id_rname);			    else				loglog(RC_LOG_SERIOUS, "two interfaces match \"%s\" (%s, %s)"				       , c->name, c->interface->ip_dev->id_rname, p->ip_dev->id_rname);			    c->interface = NULL;	/* withdraw orientation */			    return FALSE;			}			c->interface = p;		    }		    /* done with this interface if it doesn't match that end */		    if (!(sameaddr(&sr->that.host_addr, &p->ip_addr)			  && (kern_interface!=NO_KERNEL			      || sr->that.host_port == pluto_port)))			break;		    /* swap ends and try again.		     * It is a little tricky to see that this loop will stop.		     * Only continue if the far side matches.		     * If both sides match, there is an error-out.		     */		    {			struct end t = sr->this;			sr->this = sr->that;			sr->that = t;		    }		}	    }	}    }    return oriented(*c);}voidinitiate_connection(const char *name, int whackfd		    , lset_t moredebug		    , enum crypto_importance importance){    struct connection *c = con_by_name(name, TRUE);    if (c != NULL)    {	set_cur_connection(c);	/* turn on any extra debugging asked for */	c->extra_debugging |= moredebug;	if (!oriented(*c))	{	    loglog(RC_ORIENT, "We cannot identify ourselves with either end of this connection.");	}	else if (NEVER_NEGOTIATE(c->policy))	{	    loglog(RC_INITSHUNT		, "cannot initiate an authby=never connection");	}	else if (c->kind != CK_PERMANENT)	{	    if (isanyaddr(&c->spd.that.host_addr))		loglog(RC_NOPEERIP, "cannot initiate connection without knowing peer IP address (kind=%s)"		       , enum_show(&connection_kind_names, c->kind));	    else		loglog(RC_WILDCARD, "cannot initiate connection with ID wildcards (kind=%s)"		       , enum_show(&connection_kind_names, c->kind));	}	else	{	    /* We will only request an IPsec SA if policy isn't empty	     * (ignoring Main Mode items).	     * This is a fudge, but not yet important.	     * If we are to proceed asynchronously, whackfd will be NULL_FD.	     */	    c->policy |= POLICY_UP;	    if(c->policy & POLICY_ENCRYPT) {		struct alg_info_esp *alg = c->alg_info_esp;		struct db_sa *phase2_sa = kernel_alg_makedb(alg, TRUE);				if(alg != NULL && phase2_sa == NULL) {		    whack_log(RC_NOALGO, "can not initiate: no acceptable kernel algorithms loaded");		    reset_cur_connection();		    close_any(whackfd);		    return;		}		free_sa(phase2_sa);	    }#ifdef SMARTCARD	    /* do we have to prompt for a PIN code? */	    if (c->spd.this.sc != NULL && !c->spd.this.sc->valid && whackfd != NULL_FD)		scx_get_pin(c->spd.this.sc, whackfd);	    if (c->spd.this.sc != NULL && !c->spd.this.sc->valid)	    {		loglog(RC_NOVALIDPIN, "cannot initiate connection without valid PIN");	    }	    else#endif	    {		ipsecdoi_initiate(whackfd, c, c->policy, 1				  , SOS_NOBODY, importance);		whackfd = NULL_FD;	/* protect from close */	    }	}	reset_cur_connection();    }    close_any(whackfd);}/* (Possibly) Opportunistic Initiation: * Knowing clients (single IP addresses), try to build an tunnel. * This may involve discovering a gateway and instantiating an * Opportunistic connection.  Called when a packet is caught by * a %trap, or when whack --oppohere --oppothere is used. * It may turn out that an existing or non-opporunistic connnection * can handle the traffic. * * Most of the code will be restarted if an ADNS request is made * to discover the gateway.  The only difference between the first * and second entry is whether gateways_from_dns is NULL or not. *	initiate_opportunistic: initial entrypoint *	continue_oppo: where we pickup when ADNS result arrives *	initiate_opportunistic_body: main body shared by above routines *	cannot_oppo: a helper function to log a diagnostic * This structure repeats a lot of code when the ADNS result arrives. * This seems like a waste, but anything learned the first time through * may no longer be true! * * After the first IKE message is sent, the regular state machinery * carries negotiation forward. */enum find_oppo_step {    fos_start,    fos_myid_ip_txt,    fos_myid_hostname_txt,    fos_myid_ip_key,    fos_myid_hostname_key,    fos_our_client,    fos_our_txt,#ifdef USE_KEYRR    fos_our_key,#endif /* USE_KEYRR */    fos_his_client,    fos_done};#ifdef DEBUGstatic const char *const oppo_step_name[] = {    "fos_start",    "fos_myid_ip_txt",    "fos_myid_hostname_txt",    "fos_myid_ip_key",    "fos_myid_hostname_key",    "fos_our_client",    "fos_our_txt",#ifdef USE_KEYRR    "fos_our_key",#endif /* USE_KEYRR */    "fos_his_client",    "fos_done"};#endif /* DEBUG */struct find_oppo_bundle {    enum find_oppo_step step;    err_t want;    bool failure_ok;		/* if true, continue_oppo should not die on DNS failure */    ip_address our_client;	/* not pointer! */    ip_address peer_client;    int transport_proto;    bool held;    policy_prio_t policy_prio;    ipsec_spi_t failure_shunt;	/* in host order!  0 for delete. */    int whackfd;};struct find_oppo_continuation {    struct adns_continuation ac;	/* common prefix */    struct find_oppo_bundle b;};static voidcannot_oppo(struct connection *c	    , struct find_oppo_bundle *b	    , err_t ugh){    char pcb[ADDRTOT_BUF];    char ocb[ADDRTOT_BUF];    addrtot(&b->peer_client, 0, pcb, sizeof(pcb));    addrtot(&b->our_client, 0, ocb, sizeof(ocb));    openswan_log("Can not opportunistically initiate for %s to %s: %s"		 , ocb, pcb, ugh);    whack_log(RC_OPPOFAILURE	, "Can not opportunistically initiate for %s to %s: %s"	, ocb, pcb, ugh);    if (c != NULL && c->policy_next != NULL)    {	/* there is some policy that comes afterwards */	struct spd_route *shunt_spd;	struct connection *nc = c->policy_next;	struct state *st;	passert(c->kind == CK_TEMPLATE);	passert(c->policy_next->kind == CK_PERMANENT);	DBG(DBG_OPPO, DBG_log("OE failed for %s to %s, but %s overrides shunt"			      , ocb, pcb, c->policy_next->name));	/*	 * okay, here we need add to the "next" policy, which is ought	 * to be an instance.	 * We will add another entry to the spd_route list for the specific	 * situation that we have.	 */	shunt_spd = clone_thing(nc->spd, "shunt eroute policy");	shunt_spd->next = nc->spd.next;	nc->spd.next = shunt_spd;	happy(addrtosubnet(&b->peer_client, &shunt_spd->that.client));	if (sameaddr(&b->peer_client, &shunt_spd->that.host_addr))	    shunt_spd->that.has_client = FALSE;	/*	 * override the tunnel destination with the one from the secondaried	 * policy	 */	shunt_spd->that.host_addr = nc->spd.that.host_addr;	/* now, lookup the state, and poke it up.	 */	st = state_with_serialno(nc->newest_ipsec_sa);	/* XXX what to do if the IPSEC SA has died? */	passert(st != NULL);	/* link the new connection instance to the state's list of	 * connections	 */	DBG(DBG_OPPO, DBG_log("installing state: %ld for %s to %s"			      , nc->newest_ipsec_sa			      , ocb, pcb));#ifdef DEBUG	if (DBGP(DBG_OPPO | DBG_CONTROLMORE))	{	    char state_buf[LOG_WIDTH];	    char state_buf2[LOG_WIDTH];	    time_t n = now();	    fmt_state(st, n, state_buf, sizeof(state_buf)		      , state_buf2, sizeof(state_buf2));	    DBG_log("cannot_oppo, failure SA1: %s", state_buf);	    DBG_log("cannot_oppo, failure SA2: %s", state_buf2);	}#endif /* DEBUG */	if (!route_and_eroute(c, shunt_spd, st))	{	    whack_log(RC_OPPOFAILURE		      , "failed to instantiate shunt policy %s for %s to %s"		      , c->name		      , ocb, pcb);	}	return;    }#ifdef KLIPS    if (b->held)    {	/* Replace HOLD with b->failure_shunt.	 * If no b->failure_shunt specified, use SPI_PASS -- THIS MAY CHANGE.	 */	if (b->failure_shunt == 0)	{	    DBG(DBG_OPPO, DBG_log("no explicit failure shunt for %s to %s; installing %%pass"				  , ocb, pcb));	}	(void) replace_bare_shunt(&b->our_client, &b->peer_client	    , b->policy_prio	    , b->failure_shunt	    , b->failure_shunt != 0	    , b->transport_proto	    , ugh);    }#endif}static void initiate_opportunistic_body(struct find_oppo_bundle *b    , struct adns_continuation *ac, err_t ac_ugh);	/* forward */voidinitiate_opportunistic(const ip_address *our_client, const ip_address *peer_client, int transport_proto UNUSED, bool held, int whackfd, err_t why){    struct find_oppo_bundle b;    b.want = why;	/* fudge */    b.failure_ok = FALSE;    b.our_client = *our_client;    b.peer_client = *peer_client;    b.transport_proto = 0;    b.held = held;    b.policy_prio = BOTTOM_PRIO;    b.failure_shunt = 0;    b.whackfd = whackfd;    b.step = fos_start;    initiate_opportunistic_body(&b, NULL, NULL);}static voidcontinue_oppo(struct adns_continuation *acr, err_t ugh){    struct find_oppo_continuation *cr = (void *)acr;	/* inherit, damn you! */    struct connection *c;    bool was_held = cr->b.held;    int whackfd = cr->b.whackfd;    /* note: cr->id has no resources; cr->sgw_id is id_none:     * neither need freeing.     */    whack_log_fd = whackfd;#ifdef KLIPS    /* Discover and record whether %hold has gone away.     * This could have happened while we were awaiting DNS.     * We must check BEFORE any call to cannot_oppo.     */    if (was_held)	cr->b.held = has_bare_hold(&cr->b.our_client, &cr->b.peer_client	    , cr->b.transport_proto);#endif#ifdef DEBUG    /* if we're going to ignore the error, at least note it in debugging log */    if (cr->b.failure_ok && ugh != NULL)    {	DBG(DBG_CONTROL | DBG_DNS,	    {		char ocb[ADDRTOT_BUF];		char pcb[ADDRTOT_BUF];		addrtot(&cr->b.our_client, 0, ocb, sizeof(ocb));		addrtot(&cr->b.peer_client, 0, pcb, sizeof(pcb));		DBG_log("continuing from failed DNS lookup for %s, %s to %s: %s"		    , cr->b.want, ocb, pcb, ugh);	    });    }#endif    if (!cr->b.failure_ok && ugh != NULL)    {	c = find_connection_for_clients(NULL, &cr->b.our_client, &cr->b.peer_client	    , cr->b.transport_proto);	cannot_oppo(c, &cr->b		    , builddiag("%s: %s", cr->b.want, ugh));    }    else if (was_held && !cr->b.held)    {	/* was_held indicates we were started due to a %trap firing	 * (as opposed to a "whack --oppohere --oppothere").	 * Since the %hold has gone, we can assume that somebody else	 * has beaten us to the punch.  We can go home.  But lets log it.	 */	char ocb[ADDRTOT_BUF];	char pcb[ADDRTOT_BUF];	addrtot(&cr->b.our_client, 0, ocb, sizeof(ocb));	addrtot(&cr->b.peer_client, 0, pcb, sizeof(pcb));	loglog(RC_COMMENT	    , "%%hold otherwise handled during DNS lookup for Opportunistic Initiation for %s to %s"	    , ocb, pcb);    }    else    {	initiate_opportunistic_body(&cr->b, &cr->ac, ugh);	whackfd = NULL_FD;	/* was handed off */    }    whack_log_fd = NULL_FD;    close_any(whackfd);}#ifdef USE_KEYRRstatic err_tcheck_key_recs(enum myid_state try_state, const struct connection *c, struct adns_continuation *ac){    /* Check if KEY lookup yielded good results.     * Looking up based on our ID.  Used if     * client is ourself, or if TXT had no public key.     * Note: if c is different this time, there is     * a chance that we did the wrong query.     * If so, treat as a kind of failure.     */    enum myid_state old_myid_state = myid_state;    const struct RSA_private_key *our_RSA_pri;    err_t ugh = NULL;    myid_state = try_state;    if (old_myid_state != myid_state    && old_myid_state == MYID_SPECIFIED)    {	ugh = "%myid was specified while we were guessing";    }    else if ((our_RSA_pri = get_RSA_private_key(c)) == NULL)    {	ugh = "we don't know our own RSA key";    }    else if (!same_id(&ac->id, &c->spd.this.id))    {	ugh = "our ID changed 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -