Exemplo n.º 1
0
static bool validate_end(struct ub_ctx *dnsctx ,
#endif
			struct starter_conn *conn_st,
			struct starter_end *end,
			const char *leftright,
			bool resolvip UNUSED,
			err_t *perr)
{
	err_t er = NULL;
	char *err_str = NULL;
	int family = conn_st->options[KBF_CONNADDRFAMILY];
	bool err = FALSE;

#  define ERR_FOUND(...) { err |= error_append(&err_str, __VA_ARGS__); }

	if (!end->options_set[KNCF_IP])
		conn_st->state = STATE_INCOMPLETE;

	end->addrtype = end->options[KNCF_IP];
	end->addr_family = family;

	/* validate the KSCF_IP/KNCF_IP */
	switch (end->addrtype) {
	case KH_ANY:
		anyaddr(family, &(end->addr));
		break;

	case KH_IFACE:
		/* generally, this doesn't show up at this stage */
		starter_log(LOG_LEVEL_DEBUG, "starter: %s is KH_IFACE", leftright);
		break;

	case KH_IPADDR:
		assert(end->strings[KSCF_IP] != NULL);

		if (end->strings[KSCF_IP][0] == '%') {
			pfree(end->iface);
			end->iface = clone_str(end->strings[KSCF_IP] + 1, "KH_IPADDR end->iface");
			if (!starter_iface_find(end->iface, family,
					       &end->addr,
					       &end->nexthop))
				conn_st->state = STATE_INVALID;
			/* not numeric, so set the type to the iface type */
			end->addrtype = KH_IFACE;
			break;
		}

		er = ttoaddr_num(end->strings[KNCF_IP], 0, family,
				    &(end->addr));
		if (er != NULL) {
			/* not numeric, so set the type to the string type */
			end->addrtype = KH_IPHOSTNAME;
		}

		if (end->id == NULL) {
			ipstr_buf b;

			end->id = clone_str(ipstr(&end->addr, &b), "end if");
		}
		break;

	case KH_OPPO:
		conn_st->policy |= POLICY_OPPORTUNISTIC;
		break;

	case KH_OPPOGROUP:
		conn_st->policy |= POLICY_OPPORTUNISTIC | POLICY_GROUP;
		break;

	case KH_GROUP:
		conn_st->policy |= POLICY_GROUP;
		break;

	case KH_IPHOSTNAME:
		/* generally, this doesn't show up at this stage */
		starter_log(LOG_LEVEL_DEBUG,
			    "starter: %s is KH_IPHOSTNAME", leftright);
		break;

	case KH_DEFAULTROUTE:
		starter_log(LOG_LEVEL_DEBUG,
			    "starter: %s is KH_DEFAULTROUTE", leftright);
		break;

	case KH_NOTSET:
		starter_log(LOG_LEVEL_DEBUG, "starter: %s is KH_NOTSET", leftright);
		break;
	}

	/* validate the KSCF_SUBNET */
	if (end->strings_set[KSCF_SUBNET]) {
		char *value = end->strings[KSCF_SUBNET];

		if (end->strings_set[KSCF_ADDRESSPOOL]) {
			ERR_FOUND("cannot specify both %ssubnet= and %saddresspool=", leftright,
				leftright);
		}

		if (startswith(value, "vhost:") || startswith(value, "vnet:")) {
			er = NULL;
			end->virt = clone_str(value, "validate_end item");
		} else {
			end->has_client = TRUE;
			er = ttosubnet(value, 0, family, &(end->subnet));
		}
		if (er != NULL)
			ERR_FOUND("bad subnet %ssubnet=%s [%s]", leftright,
				  value, er);
	}

	/* set nexthop address to something consistent, by default */
	anyaddr(family, &end->nexthop);
	anyaddr(addrtypeof(&end->addr), &end->nexthop);

	/* validate the KSCF_NEXTHOP */
	if (end->strings_set[KSCF_NEXTHOP]) {
		char *value = end->strings[KSCF_NEXTHOP];

		if (strcaseeq(value, "%defaultroute")) {
			end->nexttype = KH_DEFAULTROUTE;
		} else {
			if (tnatoaddr(value, strlen(value), AF_INET,
				      &(end->nexthop)) != NULL &&
			    tnatoaddr(value, strlen(value), AF_INET6,
				      &(end->nexthop)) != NULL) {
#ifdef DNSSEC
				starter_log(LOG_LEVEL_DEBUG,
					    "Calling unbound_resolve() for %snexthop value",
					    leftright);
				if (!unbound_resolve(dnsctx, value,
						strlen(value), AF_INET,
						&(end->nexthop)) &&
				    !unbound_resolve(dnsctx, value,
						strlen(value), AF_INET6,
						&(end->nexthop)))
					ERR_FOUND("bad value for %snexthop=%s\n",
						leftright, value);
#else
				er = ttoaddr(value, 0, family,
						&(end->nexthop));
				if (er != NULL)
					ERR_FOUND("bad value for %snexthop=%s [%s]",
						leftright, value,
						er);
#endif
			}
			end->nexttype = KH_IPADDR;
		}
	} else {
#if 0
		if (conn_st->policy & POLICY_OPPORTUNISTIC)
			end->nexttype = KH_DEFAULTROUTE;
#endif
		anyaddr(family, &end->nexthop);

		if (end->addrtype == KH_DEFAULTROUTE) {
			end->nexttype = KH_DEFAULTROUTE;
		}
	}

	/* validate the KSCF_ID */
	if (end->strings_set[KSCF_ID]) {
		char *value = end->strings[KSCF_ID];

		pfreeany(end->id);
		end->id = clone_str(value, "end->id");
	}

	if (end->options_set[KSCF_RSAKEY1]) {
		end->rsakey1_type = end->options[KSCF_RSAKEY1];
		end->rsakey2_type = end->options[KSCF_RSAKEY2];

		switch (end->options[KSCF_RSAKEY1]) {
		case PUBKEY_DNS:
		case PUBKEY_DNSONDEMAND:
			end->key_from_DNS_on_demand = TRUE;
			break;

		default:
			end->key_from_DNS_on_demand = FALSE;
			/* validate the KSCF_RSAKEY1/RSAKEY2 */
			if (end->strings[KSCF_RSAKEY1] != NULL) {
				char *value = end->strings[KSCF_RSAKEY1];

				pfreeany(end->rsakey1);
				end->rsakey1 = (unsigned char *)clone_str(value,"end->rsakey1");
			}
			if (end->strings[KSCF_RSAKEY2] != NULL) {
				char *value = end->strings[KSCF_RSAKEY2];

				pfreeany(end->rsakey2);
				end->rsakey2 = (unsigned char *)clone_str(value,"end->rsakey2");
			}
		}
	}

	/* validate the KSCF_SOURCEIP, if any, and if set,
	 * set the subnet to same value, if not set.
	 */
	if (end->strings_set[KSCF_SOURCEIP]) {
		char *value = end->strings[KSCF_SOURCEIP];

		if (tnatoaddr(value, strlen(value), AF_INET,
			      &(end->sourceip)) != NULL &&
		    tnatoaddr(value, strlen(value), AF_INET6,
			      &(end->sourceip)) != NULL) {
#ifdef DNSSEC
			starter_log(LOG_LEVEL_DEBUG,
				    "Calling unbound_resolve() for %ssourceip value",
				    leftright);
			if (!unbound_resolve(dnsctx, value,
					strlen(value), AF_INET,
					&(end->sourceip)) &&
			    !unbound_resolve(dnsctx, value,
					strlen(value), AF_INET6,
					&(end->sourceip)))
				ERR_FOUND("bad value for %ssourceip=%s\n",
					  leftright, value);
#else
			er = ttoaddr(value, 0, family, &(end->sourceip));
			if (er != NULL)
				ERR_FOUND("bad addr %ssourceip=%s [%s]",
					  leftright, value, er);
#endif
		} else {
			er = tnatoaddr(value, 0, family, &(end->sourceip));
			if (er != NULL)
				ERR_FOUND("bad numerical addr %ssourceip=%s [%s]",
					leftright, value, er);
		}
		if (!end->has_client) {
			starter_log(LOG_LEVEL_INFO,
				    "%ssourceip= used but not %ssubnet= defined, defaulting %ssubnet to %s",
				    leftright, leftright, leftright, value);
			er = addrtosubnet(&end->sourceip, &end->subnet);
			if (er != NULL) {
				ERR_FOUND("attempt to default %ssubnet from %s failed: %s",
					leftright, value, er);
			}
			end->has_client = TRUE;
			end->has_client_wildcard = FALSE;
		}
	}

	/* copy certificate path name */
	if (end->strings_set[KSCF_CERT])
		end->cert = clone_str(end->strings[KSCF_CERT], "KSCF_CERT");

	if (end->strings_set[KSCF_CA])
		end->ca = clone_str(end->strings[KSCF_CA], "KSCF_CA");

	if (end->strings_set[KSCF_UPDOWN])
		end->updown = clone_str(end->strings[KSCF_UPDOWN], "KSCF_UPDOWN");

	if (end->strings_set[KSCF_PROTOPORT]) {
		err_t ugh;
		char *value = end->strings[KSCF_PROTOPORT];

		ugh = ttoprotoport(value, 0, &end->protocol, &end->port,
				   &end->has_port_wildcard);

		if (ugh != NULL)
			ERR_FOUND("bad %sprotoport=%s [%s]", leftright, value,
				  ugh);
	}

	if (end->strings_set[KSCF_ADDRESSPOOL]) {
		char *addresspool = end->strings[KSCF_ADDRESSPOOL];

		if (end->strings_set[KSCF_SUBNET])
			ERR_FOUND("cannot specify both %ssubnet= and %saddresspool=",
				leftright, leftright);
		starter_log(LOG_LEVEL_DEBUG,
			    "connection's  %saddresspool set to: %s",
			    leftright, end->strings[KSCF_ADDRESSPOOL] );

		er = ttorange(addresspool, 0, AF_INET, &end->pool_range, TRUE);
		if (er != NULL)
			ERR_FOUND("bad %saddresspool=%s [%s]", leftright,
					addresspool, er);
	}

	if (end->options_set[KNCF_XAUTHSERVER] ||
	    end->options_set[KNCF_XAUTHCLIENT])
		conn_st->policy |= POLICY_XAUTH;

	/*
	   KSCF_SUBNETWITHIN    --- not sure what to do with it.
	   KSCF_ESPENCKEY       --- todo (manual keying)
	   KSCF_ESPAUTHKEY      --- todo (manual keying)
	   KSCF_SOURCEIP     = 16,
	   KSCF_MAX          = 19
	 */

	if (err)
		*perr = err_str;
	return err;
#  undef ERR_FOUND
}
Exemplo n.º 2
0
static void kw_end(starter_conn_t *conn, starter_end_t *end, kw_token_t token,
				   kw_list_t *kw, char *conn_name, starter_config_t *cfg)
{
	err_t ugh = NULL;
	bool assigned = FALSE;
	bool has_port_wildcard;        /* set if port is %any */

	char *name  = kw->entry->name;
	char *value = kw->value;

	if (!assign_arg(token, KW_END_FIRST, kw, (char *)end, &assigned))
		goto err;

	/* post processing of some keywords that were assigned automatically */
	switch (token)
	{
	case KW_SUBNET:
		if ((strlen(value) >= 6 && strncmp(value,"vhost:",6) == 0)
		||  (strlen(value) >= 5 && strncmp(value,"vnet:",5) == 0))
		{
			/* used by pluto only */
			end->has_virt = TRUE;
		}
		else
		{
			ip_subnet net;
			char *pos;
			int len = 0;

			end->has_client = TRUE;
			conn->tunnel_addr_family = ip_version(value);

			pos = strchr(value, ',');
			if (pos)
			{
				len = pos - value;
			}
			ugh = ttosubnet(value, len, ip_version(value), &net);
			if (ugh != NULL)
			{
				plog("# bad subnet: %s=%s [%s]", name, value, ugh);
				goto err;
			}
		}
		break;
	case KW_SOURCEIP:
		if (end->has_natip)
		{
			plog("# natip and sourceip cannot be defined at the same time");
			goto err;
		}
		if (value[0] == '%')
		{
			if (streq(value, "%modeconfig") || streq(value, "%modecfg") ||
				streq(value, "%config") || streq(value, "%cfg"))
			{
				/* request ip via config payload */
				free(end->sourceip);
				end->sourceip = NULL;
				end->sourceip_mask = 1;
			}
			else
			{	/* %poolname, strip %, serve ip requests */
				free(end->sourceip);
				end->sourceip = clone_str(value+1);
				end->sourceip_mask = 0;
			}
			end->modecfg = TRUE;
		}
		else
		{
			char *pos;
			ip_address addr;
			ip_subnet net;

			conn->tunnel_addr_family = ip_version(value);
			pos = strchr(value, '/');

			if (pos)
			{	/* CIDR notation, address pool */
				ugh = ttosubnet(value, 0, conn->tunnel_addr_family, &net);
				if (ugh != NULL)
				{
					plog("# bad subnet: %s=%s [%s]", name, value, ugh);
					goto err;
				 }
				*pos = '\0';
				free(end->sourceip);
				end->sourceip = clone_str(value);
				end->sourceip_mask = atoi(pos + 1);
			}
			else
			{	/* fixed srcip */
				ugh = ttoaddr(value, 0, conn->tunnel_addr_family, &addr);
				if (ugh != NULL)
				{
					plog("# bad addr: %s=%s [%s]", name, value, ugh);
					goto err;
				}
				end->sourceip_mask = (conn->tunnel_addr_family == AF_INET) ?
									  32 : 128;
			}
		}
		conn->policy |= POLICY_TUNNEL;
		break;
	case KW_SENDCERT:
		if (end->sendcert == CERT_YES_SEND)
		{
			end->sendcert = CERT_ALWAYS_SEND;
		}
		else if (end->sendcert == CERT_NO_SEND)
		{
			end->sendcert = CERT_NEVER_SEND;
		}
		break;
	default:
		break;
	}

	if (assigned)
		return;

	/* individual processing of keywords that were not assigned automatically */
	switch (token)
	{
	case KW_HOST:
		if (streq(value, "%defaultroute"))
		{
			if (cfg->defaultroute.defined)
			{
				end->addr    = cfg->defaultroute.addr;
				end->nexthop = cfg->defaultroute.nexthop;
			}
			else if (!cfg->defaultroute.supported)
			{
				plog("%%defaultroute not supported, fallback to %%any");
			}
			else
			{
				plog("# default route not known: %s=%s", name, value);
				goto err;
			}
		}
		else if (streq(value, "%any") || streq(value, "%any4"))
		{
			anyaddr(conn->addr_family, &end->addr);
		}
		else if (streq(value, "%any6"))
		{
			conn->addr_family = AF_INET6;
			anyaddr(conn->addr_family, &end->addr);
		}
		else if (streq(value, "%group"))
		{
			ip_address any;

			conn->policy |= POLICY_GROUP | POLICY_TUNNEL;
			anyaddr(conn->addr_family, &end->addr);
			anyaddr(conn->tunnel_addr_family, &any);
			end->has_client = TRUE;
		}
		else
		{
			/* check for allow_any prefix */
			if (value[0] == '%')
			{
				end->allow_any = TRUE;
				value++;
			}
			conn->addr_family = ip_version(value);
			ugh = ttoaddr(value, 0, conn->addr_family, &end->addr);
			if (ugh != NULL)
			{
				plog("# bad addr: %s=%s [%s]", name, value, ugh);
				if (streq(ugh, "does not look numeric and name lookup failed"))
				{
					end->dns_failed = TRUE;
					anyaddr(conn->addr_family, &end->addr);
				}
				else
				{
					goto err;
				}
			}
		}
		break;
	case KW_NEXTHOP:
		if (streq(value, "%defaultroute"))
		{
			if (cfg->defaultroute.defined)
			{
				end->nexthop = cfg->defaultroute.nexthop;
			}
			else
			{
				plog("# default route not known: %s=%s", name, value);
				goto err;
			}
		}
		else if (streq(value, "%direct"))
		{
			ugh = anyaddr(conn->addr_family, &end->nexthop);
		}
		else
		{
			conn->addr_family = ip_version(value);
			ugh = ttoaddr(value, 0, conn->addr_family, &end->nexthop);
		}
		if (ugh != NULL)
		{
			plog("# bad addr: %s=%s [%s]", name, value, ugh);
			goto err;
		}
		break;
	case KW_SUBNETWITHIN:
	{
		ip_subnet net;

		end->has_client = TRUE;
		end->has_client_wildcard = TRUE;
		conn->tunnel_addr_family = ip_version(value);

		ugh = ttosubnet(value, 0, ip_version(value), &net);
		if (ugh != NULL)
		{
			plog("# bad subnet: %s=%s [%s]", name, value, ugh);
			goto err;
		}
		end->subnet = clone_str(value);
		break;
	}
	case KW_PROTOPORT:
		ugh = ttoprotoport(value, 0, &end->protocol, &end->port, &has_port_wildcard);
		end->has_port_wildcard = has_port_wildcard;
		break;
	case KW_NATIP:
		if (end->sourceip)
		{
			plog("# natip and sourceip cannot be defined at the same time");
			goto err;
		}
		if (streq(value, "%defaultroute"))
		{
			char buf[64];

			if (cfg->defaultroute.defined)
			{
				addrtot(&cfg->defaultroute.addr, 0, buf, sizeof(buf));
				end->sourceip = clone_str(buf);
			}
			else
			{
				plog("# default route not known: %s=%s", name, value);
				goto err;
			}
		}
		else
		{
			ip_address addr;

			conn->tunnel_addr_family = ip_version(value);
			ugh = ttoaddr(value, 0, conn->tunnel_addr_family, &addr);
			if (ugh != NULL)
			{
				plog("# bad addr: %s=%s [%s]", name, value, ugh);
				goto err;
			}
			end->sourceip = clone_str(value);
		}
		end->has_natip = TRUE;
		conn->policy |= POLICY_TUNNEL;
		break;
	default:
		break;
	}
	return;

err:
	plog("  bad argument value in conn '%s'", conn_name);
	cfg->err++;
}
Exemplo n.º 3
0
/**
 * Validate that yes in fact we are one side of the tunnel
 *
 * The function checks that IP addresses are valid, nexthops are
 * present (if needed) as well as policies, and sets the leftID
 * from the left= if it isn't set.
 *
 * @param conn_st a connection definition
 * @param end a connection end
 * @param left boolean (are we 'left'? 1 = yes, 0 = no)
 * @param perr pointer to char containing error value
 * @return bool TRUE if failed
 */
static bool validate_end(struct starter_conn *conn_st
			, struct starter_end *end
			, bool left
			, bool resolvip UNUSED
			, err_t *perr)
{
    err_t er = NULL;
    char *err_str = NULL;
    const char *leftright=(left ? "left" : "right");
    int family = conn_st->options[KBF_CONNADDRFAMILY];
    bool err = FALSE;

#define ERR_FOUND(args...) do { err += error_append(&err_str, ##args); } while(0)

    if(!end->options_set[KNCF_IP]) {
	conn_st->state = STATE_INCOMPLETE;
    }

    end->addrtype=end->options[KNCF_IP];
    end->addr_family = family;

    /* validate the KSCF_IP/KNCF_IP */
    switch(end->addrtype) {
    case KH_ANY:
	anyaddr(family, &(end->addr));
	break;

    case KH_IFACE:
	/* generally, this doesn't show up at this stage */

	break;

    case KH_IPADDR:
        /* right=/left= */
	assert(end->strings[KSCF_IP] != NULL);

	if (end->strings[KSCF_IP][0]=='%') {
	    if (end->iface) pfree(end->iface);
            end->iface = clone_str(end->strings[KSCF_IP] + 1, "KH_IPADDR end->iface");
	    if (starter_iface_find(end->iface, family, &(end->addr),
				   &(end->nexthop)) == -1) {
	        conn_st->state = STATE_INVALID;
	    }
	    /* not numeric, so set the type to the iface type */
	    end->addrtype = KH_IFACE;
	    break;
	}

        er = ttoaddr_num(end->strings[KNCF_IP], 0, family, &(end->addr));
	if(er) {
	    /* not numeric, so set the type to the string type */
	    end->addrtype = KH_IPHOSTNAME;
	}

        if(end->id == NULL) {
            char idbuf[ADDRTOT_BUF];
            addrtot(&end->addr, 0, idbuf, sizeof(idbuf));

            end->id= clone_str(idbuf, "end id");
        }
	break;

    case KH_OPPO:
	conn_st->policy |= POLICY_OPPO;
	break;

    case KH_OPPOGROUP:
	conn_st->policy |= POLICY_OPPO|POLICY_GROUP;
	break;

    case KH_GROUP:
	conn_st->policy |= POLICY_GROUP;
	break;

    case KH_IPHOSTNAME:
        /* XXX */
	break;

    case KH_DEFAULTROUTE:
	break;

    case KH_NOTSET:
	break;
    }

    /* validate the KSCF_SUBNET */
    if(end->strings_set[KSCF_SUBNET])
    {
	char *value = end->strings[KSCF_SUBNET];

        if ( ((strlen(value)>=6) && (strncmp(value,"vhost:",6)==0)) ||
	     ((strlen(value)>=5) && (strncmp(value,"vnet:",5)==0)) ) {
	    er = NULL;
	    end->virt = clone_str(value, "end->virt");
	}
	else {
	    end->has_client = TRUE;
	    er = ttosubnet(value, 0, 0, &(end->subnet));
	}
	if (er) ERR_FOUND("bad subnet %ssubnet=%s [%s] family=%s", leftright, value, er, family2str(family));
    }

    /* set nexthop address to something consistent, by default */
    anyaddr(family, &end->nexthop);
    anyaddr(addrtypeof(&end->addr), &end->nexthop);

    /* validate the KSCF_NEXTHOP */
    if(end->strings_set[KSCF_NEXTHOP])
    {
	char *value = end->strings[KSCF_NEXTHOP];

	if(strcasecmp(value, "%defaultroute")==0) {
	    end->nexttype=KH_DEFAULTROUTE;
	} else {
            if (tnatoaddr(value, strlen(value), AF_INET,
                          &(end->nexthop)) != NULL &&
                tnatoaddr(value, strlen(value), AF_INET6,
                          &(end->nexthop)) != NULL) {
                er = ttoaddr(value, 0, family, &(end->nexthop));
                if (er) ERR_FOUND("bad addr %snexthop=%s [%s]", leftright, value, er);
            }
            end->nexttype = KH_IPADDR;
	}
    } else {
      if (end->addrtype == KH_DEFAULTROUTE) {
        end->nexttype = KH_DEFAULTROUTE;
      }
      anyaddr(family, &end->nexthop);
    }

    /* validate the KSCF_ID */
    if(end->strings_set[KSCF_ID])
    {
	char *value = end->strings[KSCF_ID];

        pfreeany(end->id);
        end->id = clone_str(value, "end->id");
    }

    if(end->options_set[KSCF_RSAKEY1]) {
	end->rsakey1_type = end->options[KSCF_RSAKEY1];
	end->rsakey2_type = end->options[KSCF_RSAKEY2];

	switch(end->rsakey1_type) {
	case PUBKEY_DNS:
	case PUBKEY_DNSONDEMAND:
	    end->key_from_DNS_on_demand = TRUE;
	    break;

	default:
	    end->key_from_DNS_on_demand = FALSE;
	    /* validate the KSCF_RSAKEY1/RSAKEY2 */
	    if(end->strings[KSCF_RSAKEY1] != NULL)
	    {
		char *value = end->strings[KSCF_RSAKEY1];

                pfreeany(end->rsakey1);
                end->rsakey1 = (unsigned char *)clone_str(value,"end->rsakey1");
	    }
	    if(end->strings[KSCF_RSAKEY2] != NULL)
	    {
		char *value = end->strings[KSCF_RSAKEY2];

                pfreeany(end->rsakey2);
                end->rsakey2 = (unsigned char *)clone_str(value,"end->rsakey2");
	    }
	}
    }

    /* validate the KSCF_SOURCEIP, if any, and if set,
     * set the subnet to same value, if not set.
     */
    if(end->strings_set[KSCF_SOURCEIP])
    {
	char *value = end->strings[KSCF_SOURCEIP];

	if (tnatoaddr(value, strlen(value), AF_INET, &(end->sourceip)) != NULL
	    && tnatoaddr(value, strlen(value), AF_INET6, &(end->sourceip)) != NULL) {

	    er = ttoaddr(value, 0, 0, &(end->sourceip));
	    if (er) ERR_FOUND("bad addr %ssourceip=%s [%s]", leftright, value, er);

	} else {
		er = tnatoaddr(value, 0, 0, &(end->sourceip));
		if (er) ERR_FOUND("bad numerical addr %ssourceip=%s [%s]", leftright, value, er);
	}

	if(!end->has_client) {
	    starter_log(LOG_LEVEL_INFO, "defaulting %ssubnet to %s\n", leftright, value);
	    er = addrtosubnet(&end->sourceip, &end->subnet);
	    if (er) ERR_FOUND("attempt to default %ssubnet from %s failed: %s", leftright, value, er);
	    end->has_client = TRUE;
	    end->has_client_wildcard = FALSE;
	}
    }

    /* copy certificate path name */
    if(end->strings_set[KSCF_CERT]) {
        end->cert = clone_str(end->strings[KSCF_CERT], "KSCF_CERT");
    }

    if(end->strings_set[KSCF_CA]) {
        end->ca = clone_str(end->strings[KSCF_CA], "KSCF_CA");
    }

    if(end->strings_set[KSCF_UPDOWN]) {
        end->updown = clone_str(end->strings[KSCF_UPDOWN], "KSCF_UPDOWN");
    }

    if(end->strings_set[KSCF_PROTOPORT]) {
	err_t ugh;
	char *value = end->strings[KSCF_PROTOPORT];

	ugh = ttoprotoport(value, 0, &end->protocol, &end->port, &end->has_port_wildcard);

	if (ugh) ERR_FOUND("bad %sprotoport=%s [%s]", leftright, value, ugh);
    }

    if (end->options_set[KNCF_XAUTHSERVER] ||
        end->options_set[KNCF_XAUTHCLIENT]) {
	conn_st->policy |= POLICY_XAUTH;
    }

    /*
    KSCF_SUBNETWITHIN    --- not sure what to do with it.
    KSCF_ESPENCKEY       --- todo (manual keying)
    KSCF_ESPAUTHKEY      --- todo (manual keying)
    KSCF_SOURCEIP     = 16,
    KSCF_MAX          = 19
    */

    if(err) *perr = err_str;
    return err;
#  undef ERR_FOUND
}