void lsw_conf_setdefault(void) { char buf[PATH_MAX]; char *ipsec_conf_dir = FINALCONFDIR; char *ipsecd_dir = FINALCONFDDIR; char *conffile = FINALCONFFILE; char *var_dir = FINALVARDIR; char *env; #if 0 char *exec_dir = FINALLIBEXECDIR; char *lib_dir = FINALLIBDIR; char *sbin_dir = FINALSBINDIR; #endif memset(&global_oco, 0, sizeof(global_oco)); /* allocate them all to make it consistent */ ipsec_conf_dir = clone_str(ipsec_conf_dir, "default conf ipsec_conf_dir"); ipsecd_dir = clone_str(ipsecd_dir, "default conf ipsecd_dir"); conffile = clone_str(conffile, "default conf conffile"); var_dir = clone_str(var_dir, "default conf var_dir"); global_oco.rootdir = ""; global_oco.confddir= ipsecd_dir; global_oco.vardir = var_dir; global_oco.confdir = ipsec_conf_dir; global_oco.conffile = conffile; /* path to NSS password file */ snprintf(buf, sizeof(buf), "%s/nsspassword", global_oco.confddir); NSSPassword.data = clone_str(buf, "nss password file path"); NSSPassword.source = PW_FROMFILE; /* DBG_log("default setting of ipsec.d to %s", global_oco.confddir); */ }
void lsw_init_ipsecdir(const char *ipsec_dir) { if (!setup) lsw_conf_setdefault(); global_oco.confddir = clone_str(ipsec_dir, "override ipsec.d"); global_oco.nssdir = clone_str(ipsec_dir, "override nssdir"); lsw_conf_calculate(&global_oco); setup = TRUE; libreswan_log("adjusting ipsec.d to %s", global_oco.confddir); }
void osw_conf_setdefault(void) { char buf[PATH_MAX]; char *ipsec_conf_dir = FINALCONFDIR; char *ipsecd_dir = FINALCONFDDIR; char *conffile = FINALCONFFILE; char *var_dir = FINALVARDIR; char *env; #if 0 char *exec_dir = FINALLIBEXECDIR; char *lib_dir = FINALLIBDIR; char *sbin_dir = FINALSBINDIR; #endif memset(&global_oco, 0, sizeof(global_oco)); /* allocate them all to make it consistent */ ipsec_conf_dir = clone_str(ipsec_conf_dir, "default conf ipsec_conf_dir"); ipsecd_dir = clone_str(ipsecd_dir, "default conf ipsecd_dir"); conffile = clone_str(conffile, "default conf conffile"); var_dir = clone_str(var_dir, "default conf var_dir"); /* figure out what we are doing, look for variables in the environment */ if((env = getenv("IPSEC_CONFS")) != NULL) { pfree(ipsec_conf_dir); ipsec_conf_dir = clone_str(env, "ipsec_confs"); /* if they change IPSEC_CONFS, reassign ipsecd as well */ snprintf(buf, sizeof(buf), "%s/ipsec.d", ipsec_conf_dir); pfree(ipsecd_dir); ipsecd_dir = clone_str(buf, "ipsecdir"); /* if they change IPSEC_CONFS, reassign ipsec policies as well */ snprintf(buf, sizeof(buf), "%s/ipsec.conf", ipsec_conf_dir); pfree(conffile); conffile = clone_str(buf, "ipsec.conf"); } if((env = getenv("IPSEC_CONFFILE")) != NULL) { pfree(conffile); pfree(ipsec_conf_dir); conffile = clone_str(env, "ipsec.conf"); } global_oco.rootdir = ""; global_oco.confddir= ipsecd_dir; global_oco.vardir = var_dir; global_oco.confdir = ipsec_conf_dir; global_oco.conffile = conffile; #ifdef HAVE_LIBNSS /* path to NSS password file */ snprintf(buf, sizeof(buf), "%s/nsspassword", global_oco.confddir); NSSPassword.data = clone_str(buf, "nss password file path"); NSSPassword.source = PW_FROMFILE; #endif /* DBG_log("default setting of ipsec.d to %s", global_oco.confddir); */ }
static void osw_conf_calculate(struct osw_conf_options *oco) { char buf[PATH_MAX]; /* calculate paths to certain subdirs */ snprintf(buf, sizeof(buf), "%s" SUBDIRNAME("/acerts"), oco->confddir); oco->acerts_dir = clone_str(buf, "acert path"); snprintf(buf, sizeof(buf), "%s" SUBDIRNAME("/cacerts"), oco->confddir); oco->cacerts_dir = clone_str(buf, "cacert path"); snprintf(buf, sizeof(buf), "%s" SUBDIRNAME("/crls"), oco->confddir); oco->crls_dir = clone_str(buf, "crls path"); snprintf(buf, sizeof(buf), "%s" SUBDIRNAME("/private"), oco->confddir); oco->private_dir = clone_str(buf, "private path"); snprintf(buf, sizeof(buf), "%s" SUBDIRNAME("/certs"), oco->confddir); oco->certs_dir = clone_str(buf, "certs path"); snprintf(buf, sizeof(buf), "%s" SUBDIRNAME("/aacerts"), oco->confddir); oco->aacerts_dir = clone_str(buf, "aacerts path"); snprintf(buf, sizeof(buf), "%s" SUBDIRNAME("/ocspcerts"), oco->confddir); oco->ocspcerts_dir = clone_str(buf, "ocspcerts path"); snprintf(buf, sizeof(buf), "%s/policies", oco->confddir); oco->policies_dir = clone_str(buf, "policies path"); }
static void lsw_conf_calculate(struct lsw_conf_options *oco) { char buf[PATH_MAX]; /* will be phased out for NSS in the near future */ snprintf(buf, sizeof(buf), "%s" SUBDIRNAME("/cacerts"), oco->confddir); oco->cacerts_dir = clone_str(buf, "cacert path"); snprintf(buf, sizeof(buf), "%s" SUBDIRNAME("/crls"), oco->confddir); oco->crls_dir = clone_str(buf, "crls path"); /* old OE policies - might get re-used in the near future */ snprintf(buf, sizeof(buf), "%s/policies", oco->confddir); oco->policies_dir = clone_str(buf, "policies path"); }
static void key_add_continue(struct adns_continuation *ac, err_t ugh) { struct key_add_continuation *kc = (void *) ac; struct key_add_common *oc = kc->common; passert(whack_log_fd == NULL_FD); whack_log_fd = oc->whack_fd; if (ugh != NULL) { oc->diag[kc->lookingfor] = clone_str(ugh); } else { oc->success = TRUE; transfer_to_public_keys(kc->ac.gateways_from_dns #ifdef USE_KEYRR , &kc->ac.keys_from_dns #endif /* USE_KEYRR */ ); } oc->refCount--; key_add_merge(oc, ac->id); whack_log_fd = NULL_FD; }
static char * mapper_find_user(X509 *x509,void *context,int *mp) { if ( !x509 ) return NULL; if (match) { *mp = 1; return clone_str((char *)default_user); } return NULL; }
const struct osw_conf_options *osw_init_rootdir(const char *root_dir) { if(!setup) osw_conf_setdefault(); global_oco.rootdir = clone_str(root_dir, "override /"); osw_conf_calculate(&global_oco); setup = TRUE; return &global_oco; }
static void calc_myid_str(enum myid_state s) { /* preformat the ID name */ char buf[IDTOA_BUF]; idtoa(&myids[s], buf, IDTOA_BUF); /* replace() uses pfreeany() */ replace(myid_str[s], clone_str(buf, "myid string")); }
/* This is only used in testing/crypto (and formerly in testing/lib/libpluto) */ void lsw_init_rootdir(const char *root_dir) { if (!setup) lsw_conf_setdefault(); pfreeany(global_oco.rootdir); global_oco.rootdir = clone_str(root_dir, "override /"); lsw_conf_calculate(&global_oco); setup = TRUE; }
const struct osw_conf_options *osw_init_ipsecdir(const char *ipsec_dir) { if(!setup) osw_conf_setdefault(); global_oco.confddir = clone_str(ipsec_dir, "override ipsec.d"); osw_conf_calculate(&global_oco); setup = TRUE; openswan_log("adjusting ipsec.d to %s", global_oco.confddir); return &global_oco; }
/* Called to handle --interface <ifname> * Semantics: if specified, only these (real) interfaces are considered. */ bool use_interface(const char *rifn) { if (pluto_ifn_inst[0] == '\0') pluto_ifn_inst = clone_str(rifn, "genifn"); if (pluto_ifn_roof >= (int)elemsof(pluto_ifn)) { return FALSE; } else { pluto_ifn[pluto_ifn_roof++] = rifn; return TRUE; } }
struct starter_conn *alloc_add_conn(struct starter_config *cfg, const char *name) { struct starter_conn *conn = alloc_thing(struct starter_conn, "add_conn starter_conn"); conn_default(conn, &cfg->conn_default); conn->name = clone_str(name, "add conn name"); conn->desired_state = STARTUP_IGNORE; conn->state = STATE_FAILED; TAILQ_INIT(&conn->comments); TAILQ_INSERT_TAIL(&cfg->conns, conn, link); return conn; }
/* parses the certificate and return the email entry found, or NULL */ static char * krb_mapper_find_user(X509 *x509, void *context, int *match) { char *res; char **entries= cert_info(x509,CERT_KPN,ALGORITHM_NULL); if (!entries) { DBG("get_krb_principalname() failed"); return NULL; } DBG1("trying to map kpn entry '%s'",entries[0]); res = mapfile_find("none",entries[0],0,match); if (!res) { DBG("Error in map process"); return NULL; } return clone_str(res); }
/* parses the certificate and return the map of the first UID entry found If no UID found or map error, return NULL */ static char * uid_mapper_find_user(X509 *x509, void *context, int *match) { char *res; char **entries= cert_info(x509,CERT_UID,ALGORITHM_NULL); if (!entries) { DBG("get_unique_id() failed"); return NULL; } DBG1("trying to map uid entry '%s'",entries[0]); res = mapfile_find(mapfile,entries[0],ignorecase,match); if (!res) { DBG("Error in map process"); return NULL; } return clone_str(res); }
struct starter_conn *alloc_add_conn(struct starter_config *cfg, char *name, err_t *perr) { struct starter_conn *conn; conn = (struct starter_conn *)alloc_bytes(sizeof(struct starter_conn),"add_conn starter_conn"); zero(conn); conn_default(name, conn, &cfg->conn_default); conn->name = clone_str(name, "conn name"); conn->desired_state = STARTUP_NO; conn->state = STATE_FAILED; TAILQ_INIT(&conn->comments); TAILQ_INSERT_TAIL(&cfg->conns, conn, link); return conn; }
/* * handles left|rightfirewall and left|rightupdown parameters */ static void handle_firewall(const char *label, starter_end_t *end, starter_config_t *cfg) { if (end->firewall && (end->seen & LELEM(KW_FIREWALL - KW_END_FIRST))) { if (end->updown != NULL) { plog("# cannot have both %sfirewall and %supdown", label, label); cfg->err++; } else { end->updown = clone_str(firewall_defaults); end->firewall = FALSE; } } }
static void lsw_conf_setdefault(void) { char buf[PATH_MAX]; static const struct lsw_conf_options zero_oco; /* full of null pointers */ global_oco = zero_oco; /* allocate them all to make it consistent */ global_oco.rootdir = clone_str("","rootdir"); global_oco.confddir = clone_str(IPSEC_CONFDDIR, "default conf ipsecd_dir"); global_oco.vardir = clone_str(IPSEC_VARDIR, "default vardir"); global_oco.confdir = clone_str(IPSEC_CONFDIR, "default conf ipsec_conf_dir"); global_oco.conffile = clone_str(IPSEC_CONF, "default conf conffile"); global_oco.nssdir = clone_str(IPSEC_NSSDIR, "default nssdir"); /* path to NSS password file */ snprintf(buf, sizeof(buf), "%s/nsspassword", global_oco.confddir); NSSPassword.data = clone_str(buf, "nss password file path"); NSSPassword.source = PW_FROMFILE; }
/* * parse a conn section */ static void load_conn(starter_conn_t *conn, kw_list_t *kw, starter_config_t *cfg) { char *conn_name = (conn->name == NULL)? "%default":conn->name; for ( ; kw; kw = kw->next) { bool assigned = FALSE; kw_token_t token = kw->entry->token; if (token >= KW_LEFT_FIRST && token <= KW_LEFT_LAST) { kw_end(conn, &conn->left, token - KW_LEFT_FIRST + KW_END_FIRST , kw, conn_name, cfg); continue; } else if (token >= KW_RIGHT_FIRST && token <= KW_RIGHT_LAST) { kw_end(conn, &conn->right, token - KW_RIGHT_FIRST + KW_END_FIRST , kw, conn_name, cfg); continue; } if (token == KW_AUTO) { token = KW_CONN_SETUP; } else if (token == KW_ALSO) { if (cfg->parse_also) { also_t *also = malloc_thing(also_t); also->name = clone_str(kw->value); also->next = conn->also; conn->also = also; DBG(DBG_CONTROL, DBG_log(" also=%s", kw->value) ) } continue; } if (token < KW_CONN_FIRST || token > KW_CONN_LAST) { plog("# unsupported keyword '%s' in conn '%s'" , kw->entry->name, conn_name); cfg->err++; continue; } if (!assign_arg(token, KW_CONN_FIRST, kw, (char *)conn, &assigned)) { plog(" bad argument value in conn '%s'", conn_name); cfg->err++; continue; } if (assigned) continue; switch (token) { case KW_TYPE: conn->policy &= ~(POLICY_TUNNEL | POLICY_SHUNT_MASK); if (streq(kw->value, "tunnel")) { conn->policy |= POLICY_TUNNEL; } else if (streq(kw->value, "beet")) { conn->policy |= POLICY_BEET; } else if (streq(kw->value, "transport_proxy")) { conn->policy |= POLICY_PROXY; } else if (streq(kw->value, "passthrough") || streq(kw->value, "pass")) { conn->policy |= POLICY_SHUNT_PASS; } else if (streq(kw->value, "drop")) { conn->policy |= POLICY_SHUNT_DROP; } else if (streq(kw->value, "reject")) { conn->policy |= POLICY_SHUNT_REJECT; } else if (strcmp(kw->value, "transport") != 0) { plog("# bad policy value: %s=%s", kw->entry->name, kw->value); cfg->err++; } break; case KW_PFS: KW_POLICY_FLAG("yes", "no", POLICY_PFS) break; case KW_COMPRESS: KW_POLICY_FLAG("yes", "no", POLICY_COMPRESS) break; case KW_PMTUDISC: if (streq(kw->value, "no")) { conn->xfrm_flags |= XFRM_STATE_NOPMTUDISC; } break; case KW_IPSECDEV: conn->dev = get_ifindex(kw->value); if (conn->dev < 0) { cfg->err++; } break; case KW_ECN: if (streq(kw->value, "no")) { conn->xfrm_flags |= XFRM_STATE_NOECN; } break; case KW_AUTH: KW_POLICY_FLAG("ah", "esp", POLICY_AUTHENTICATE) break; case KW_AUTHBY: conn->policy &= ~(POLICY_ID_AUTH_MASK | POLICY_ENCRYPT); if (!(streq(kw->value, "never") || streq(kw->value, "eap"))) { char *value = kw->value; char *second = strchr(kw->value, '|'); if (second != NULL) { *second = '\0'; } /* also handles the cases secret|rsasig and rsasig|secret */ for (;;) { if (streq(value, "rsa") || streq(value, "rsasig") || streq(value, "ecdsa") || streq(value, "ecdsasig") || streq(value, "pubkey")) { conn->policy |= POLICY_PUBKEY | POLICY_ENCRYPT; } else if (streq(value, "secret") || streq(value, "psk")) { conn->policy |= POLICY_PSK | POLICY_ENCRYPT; } else if (streq(value, "xauthrsasig")) { conn->policy |= POLICY_XAUTH_RSASIG | POLICY_ENCRYPT; } else if (streq(value, "xauthpsk")) { conn->policy |= POLICY_XAUTH_PSK | POLICY_ENCRYPT; } else { plog("# bad policy value: %s=%s", kw->entry->name, kw->value); cfg->err++; break; } if (second == NULL) { break; } value = second; second = NULL; /* traverse the loop no more than twice */ } } break; case KW_EAP: { char *sep; /* check for vendor-type format */ sep = strchr(kw->value, '-'); if (sep) { *(sep++) = '\0'; conn->eap_type = atoi(kw->value); conn->eap_vendor = atoi(sep); if (conn->eap_type == 0 || conn->eap_vendor == 0) { plog("# invalid EAP type: %s=%s", kw->entry->name, kw->value); cfg->err++; } break; } if (streq(kw->value, "aka")) { conn->eap_type = 23; } else if (streq(kw->value, "sim")) { conn->eap_type = 18; } else if (streq(kw->value, "md5")) { conn->eap_type = 4; } else if (streq(kw->value, "gtc")) { conn->eap_type = 6; } else if (streq(kw->value, "mschapv2")) { conn->eap_type = 26; } else if (streq(kw->value, "radius")) { /* pseudo-type */ conn->eap_type = 253; } else { conn->eap_type = atoi(kw->value); if (conn->eap_type == 0) { plog("# unknown EAP type: %s=%s", kw->entry->name, kw->value); cfg->err++; } } break; } case KW_KEYINGTRIES: if (streq(kw->value, "%forever")) { conn->sa_keying_tries = 0; } else { char *endptr; conn->sa_keying_tries = strtoul(kw->value, &endptr, 10); if (*endptr != '\0') { plog("# bad integer value: %s=%s", kw->entry->name, kw->value); cfg->err++; } } break; case KW_REKEY: KW_POLICY_FLAG("no", "yes", POLICY_DONT_REKEY) break; case KW_REAUTH: KW_POLICY_FLAG("no", "yes", POLICY_DONT_REAUTH) break; case KW_MOBIKE: KW_POLICY_FLAG("yes", "no", POLICY_MOBIKE) break; case KW_FORCEENCAPS: KW_POLICY_FLAG("yes", "no", POLICY_FORCE_ENCAP) break; case KW_MODECONFIG: KW_POLICY_FLAG("push", "pull", POLICY_MODECFG_PUSH) break; case KW_XAUTH: KW_POLICY_FLAG("server", "client", POLICY_XAUTH_SERVER) break; default: break; } }
static void default_values(starter_config_t *cfg) { if (cfg == NULL) return; memset(cfg, 0, sizeof(struct starter_config)); /* is there enough space for all seen flags? */ assert(KW_SETUP_LAST - KW_SETUP_FIRST < sizeof(cfg->setup.seen) * BITS_PER_BYTE); assert(KW_CONN_LAST - KW_CONN_FIRST < sizeof(cfg->conn_default.seen) * BITS_PER_BYTE); assert(KW_END_LAST - KW_END_FIRST < sizeof(cfg->conn_default.right.seen) * BITS_PER_BYTE); assert(KW_CA_LAST - KW_CA_FIRST < sizeof(cfg->ca_default.seen) * BITS_PER_BYTE); cfg->setup.seen = LEMPTY; cfg->setup.fragicmp = TRUE; cfg->setup.hidetos = TRUE; cfg->setup.uniqueids = TRUE; cfg->setup.interfaces = new_list("%defaultroute"); #ifdef START_CHARON cfg->setup.charonstart = TRUE; #endif #ifdef START_PLUTO cfg->setup.plutostart = TRUE; #endif cfg->setup.pluto_ikeport = IKE_UDP_PORT; cfg->setup.ha_seqdiff_in = 0xFFFFFFFF; cfg->setup.ha_seqdiff_out = 0xFFFFFFFF; cfg->conn_default.seen = LEMPTY; cfg->conn_default.startup = STARTUP_NO; cfg->conn_default.state = STATE_IGNORE; cfg->conn_default.policy = POLICY_ENCRYPT | POLICY_TUNNEL | POLICY_PUBKEY | POLICY_PFS | POLICY_MOBIKE; cfg->conn_default.ike = clone_str(ike_defaults); cfg->conn_default.esp = clone_str(esp_defaults); cfg->conn_default.sa_ike_life_seconds = OAKLEY_ISAKMP_SA_LIFETIME_DEFAULT; cfg->conn_default.sa_ipsec_life_seconds = PLUTO_SA_LIFE_DURATION_DEFAULT; cfg->conn_default.sa_rekey_margin = SA_REPLACEMENT_MARGIN_DEFAULT; cfg->conn_default.sa_rekey_fuzz = SA_REPLACEMENT_FUZZ_DEFAULT; cfg->conn_default.sa_keying_tries = SA_REPLACEMENT_RETRIES_DEFAULT; cfg->conn_default.addr_family = AF_INET; cfg->conn_default.tunnel_addr_family = AF_INET; cfg->conn_default.xfrm_flags = 0; cfg->conn_default.install_policy = TRUE; cfg->conn_default.dev = 0; cfg->conn_default.dpd_delay = 30; /* seconds */ cfg->conn_default.dpd_timeout = 150; /* seconds */ cfg->conn_default.left.seen = LEMPTY; cfg->conn_default.right.seen = LEMPTY; cfg->conn_default.left.sendcert = CERT_SEND_IF_ASKED; cfg->conn_default.right.sendcert = CERT_SEND_IF_ASKED; anyaddr(AF_INET, &cfg->conn_default.left.addr); anyaddr(AF_INET, &cfg->conn_default.left.nexthop); anyaddr(AF_INET, &cfg->conn_default.right.addr); anyaddr(AF_INET, &cfg->conn_default.right.nexthop); cfg->conn_default.left.ikeport = 500; cfg->conn_default.right.ikeport = 500; cfg->ca_default.seen = LEMPTY; }
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++; }
static void key_add_request(const struct whack_message *msg) { struct id keyid; err_t ugh = atoid(msg->keyid, &keyid, FALSE, FALSE); if (ugh != NULL) { loglog(RC_BADID, "bad --keyid \"%s\": %s", msg->keyid, ugh); } else { if (!msg->whack_addkey) delete_public_keys(&pluto_pubkeys, &keyid, msg->pubkey_alg); if (msg->keyval.len == 0) { struct key_add_common *oc = alloc_thing(struct key_add_common, "key add common things"); enum key_add_attempt kaa; /* initialize state shared by queries */ oc->refCount = 0; oc->whack_fd = dup_any(whack_log_fd); oc->success = FALSE; for (kaa = ka_TXT; kaa != ka_roof; kaa++) { struct key_add_continuation *kc = alloc_thing( struct key_add_continuation, "key add continuation"); oc->diag[kaa] = NULL; oc->refCount++; kc->common = oc; kc->lookingfor = kaa; switch (kaa) { case ka_TXT: ugh = start_adns_query(&keyid, &keyid, /* same */ ns_t_txt, key_add_continue, &kc->ac); break; #ifdef USE_KEYRR case ka_KEY: ugh = start_adns_query(&keyid, NULL, ns_t_key, key_add_continue, &kc->ac); break; #endif /* USE_KEYRR */ default: bad_case(kaa); /* suppress gcc warning */ } if (ugh != NULL) { oc->diag[kaa] = clone_str(ugh, "early key add failure"); oc->refCount--; } } /* Done launching queries. * Handle total failure case. */ key_add_merge(oc, &keyid); } else { ugh = add_public_key(&keyid, DAL_LOCAL, msg->pubkey_alg, &msg->keyval, &pluto_pubkeys); if (ugh != NULL) loglog(RC_LOG_SERIOUS, "%s", ugh); } }
static void key_add_request(const whack_message_t *msg) { identification_t *key_id; key_id = identification_create_from_string(msg->keyid); if (!msg->whack_addkey) { delete_public_keys(key_id, msg->pubkey_alg, NULL, chunk_empty); } if (msg->keyval.len == 0) { struct key_add_common *oc = malloc_thing(struct key_add_common); enum key_add_attempt kaa; err_t ugh; /* initialize state shared by queries */ oc->refCount = 0; oc->whack_fd = dup_any(whack_log_fd); oc->success = FALSE; for (kaa = ka_TXT; kaa != ka_roof; kaa++) { struct key_add_continuation *kc; oc->diag[kaa] = NULL; oc->refCount++; kc = malloc_thing(struct key_add_continuation); kc->common = oc; kc->lookingfor = kaa; switch (kaa) { case ka_TXT: ugh = start_adns_query(key_id , key_id /* same */ , T_TXT , key_add_continue , &kc->ac); break; #ifdef USE_KEYRR case ka_KEY: ugh = start_adns_query(key_id , NULL , T_KEY , key_add_continue , &kc->ac); break; #endif /* USE_KEYRR */ default: bad_case(kaa); /* suppress gcc warning */ } if (ugh) { oc->diag[kaa] = clone_str(ugh); oc->refCount--; } } /* Done launching queries. Handle total failure case. */ key_add_merge(oc, key_id); } else { if (!add_public_key(key_id, DAL_LOCAL, msg->pubkey_alg, msg->keyval,
int main(int argc, char *argv[]) { int opt = 0; int autoall = 0; int configsetup = 0; int checkconfig = 0; char *export = "export"; /* display export before the foo=bar or not */ int listroute = 0, liststart = 0, listignore = 0, listadd = 0, listall = 0, dolist = 0, liststack = 0; struct starter_config *cfg = NULL; err_t err = NULL; char *confdir = NULL; char *configfile = NULL; char *varprefix = ""; int exit_status = 0; struct starter_conn *conn = NULL; char *ctlbase = NULL; bool resolvip = TRUE; /* default to looking up names */ #if 0 /* efence settings */ extern int EF_PROTECT_BELOW; extern int EF_PROTECT_FREE; EF_PROTECT_BELOW = 1; EF_PROTECT_FREE = 1; #endif progname = argv[0]; rootdir[0] = '\0'; tool_init_log(); while ((opt = getopt_long(argc, argv, "", longopts, 0)) != EOF) { switch (opt) { case 'h': /* usage: */ usage(); break; case 'a': autoall = 1; break; case 'D': verbose++; lex_verbosity++; break; case 'T': configsetup++; break; case 'K': checkconfig++; break; case 'N': export = ""; break; case 'C': configfile = clone_str(optarg, "config file name"); break; case 'c': ctlbase = clone_str(optarg, "control base"); break; case 'L': listadd = 1; dolist = 1; break; case 'r': listroute = 1; dolist = 1; break; case 's': liststart = 1; dolist = 1; break; case 'S': liststack = 1; dolist = 1; break; case 'i': listignore = 1; dolist = 1; break; case 'A': listall = 1; dolist = 1; break; case 'P': varprefix = optarg; break; case 'R': printf("setting rootdir=%s\n", optarg); jam_str(rootdir, sizeof(rootdir), optarg); break; case 'd': case 'n': printf("Warning: options --defaultroute and --defaultroutenexthop are obsolete and were ignored\n"); break; default: usage(); } } /* if nothing to add, then complain */ if (optind == argc && !autoall && !dolist && !configsetup && !checkconfig) usage(); if (verbose > 3) { yydebug = 1; } /* find config file */ if (confdir == NULL) confdir = IPSEC_CONFDIR; if (configfile == NULL) { /* ??? see code clone in programs/readwriteconf/readwriteconf.c */ configfile = alloc_bytes(strlen(confdir) + sizeof("/ipsec.conf"), "conf file"); /* calculate default value for configfile */ strcpy(configfile, confdir); /* safe: see allocation above */ if (configfile[0] != '\0' && configfile[strlen(configfile) - 1] != '/') strcat(configfile, "/"); /* safe: see allocation above */ strcat(configfile, "ipsec.conf"); /* safe: see allocation above */ } if (verbose) printf("opening file: %s\n", configfile); starter_use_log(verbose != 0, TRUE, verbose == 0); err = NULL; /* reset to no error */ if (configsetup || checkconfig || dolist) { /* skip if we have no use for them... causes delays */ resolvip = FALSE; } cfg = confread_load(configfile, &err, resolvip, ctlbase, configsetup); if (cfg == NULL) { fprintf(stderr, "cannot load config '%s': %s\n", configfile, err); exit(3); } else if (checkconfig) { confread_free(cfg); exit(0); } if (autoall) { if (verbose) printf("loading all conns according to their auto= settings\n"); /* * Load all conns marked as auto=add or better. * First, do the auto=route and auto=add conns to quickly * get routes in place, then do auto=start as these can be * slower. * This mimics behaviour of the old _plutoload */ if (verbose) printf(" Pass #1: Loading auto=add, auto=route and auto=start connections\n"); for (conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) { if (conn->desired_state == STARTUP_ADD || conn->desired_state == STARTUP_ONDEMAND || conn->desired_state == STARTUP_START) { if (verbose) printf(" %s", conn->name); starter_whack_add_conn(cfg, conn); } } /* * We loaded all connections. Now tell pluto to listen, * then route the conns and resolve default route. */ starter_whack_listen(cfg); if (verbose) printf(" Pass #2: Routing auto=route and auto=start connections\n"); for (conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) { if (conn->desired_state == STARTUP_ADD || conn->desired_state == STARTUP_ONDEMAND || conn->desired_state == STARTUP_START) { if (verbose) printf(" %s", conn->name); resolve_defaultroute(conn); if (conn->desired_state == STARTUP_ONDEMAND || conn->desired_state == STARTUP_START) { starter_whack_route_conn(cfg, conn); } } } if (verbose) printf(" Pass #3: Initiating auto=start connections\n"); for (conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) { if (conn->desired_state == STARTUP_START) { if (verbose) printf(" %s", conn->name); starter_whack_initiate_conn(cfg, conn); } } if (verbose) printf("\n"); } else { /* load named conns, regardless of their state */ int connum; if (verbose) printf("loading named conns:"); for (connum = optind; connum < argc; connum++) { char *connname = argv[connum]; if (verbose) printf(" %s", connname); for (conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) { if (streq(conn->name, connname)) { if (conn->state == STATE_ADDED) { printf("\nconn %s already added\n", conn->name); } else if (conn->state == STATE_FAILED) { printf("\nconn %s did not load properly\n", conn->name); } else { resolve_defaultroute(conn); exit_status = starter_whack_add_conn( cfg, conn); conn->state = STATE_ADDED; } break; } } if (conn == NULL) { /* * only if we don't find it, do we now look * for aliases */ for (conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) { if (conn->strings_set[KSF_CONNALIAS] && lsw_alias_cmp(connname, conn-> strings[KSF_CONNALIAS] )) { if (conn->state == STATE_ADDED) { printf("\nalias: %s conn %s already added\n", connname, conn->name); } else if (conn->state == STATE_FAILED) { printf("\nalias: %s conn %s did not load properly\n", connname, conn->name); } else { resolve_defaultroute( conn); exit_status = starter_whack_add_conn( cfg, conn); conn->state = STATE_ADDED; } break; } } } if (conn == NULL) { exit_status++; if (!verbose) { printf("conn '%s': not found (tried aliases)\n", connname); } else { printf(" (notfound)\n"); } } } } if (listall) { if (verbose) printf("listing all conns\n"); for (conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) printf("%s ", conn->name); printf("\n"); } else { if (listadd) { if (verbose) printf("listing all conns marked as auto=add\n"); /* list all conns marked as auto=add */ for (conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) { if (conn->desired_state == STARTUP_ADD) printf("%s ", conn->name); } } if (listroute) { if (verbose) printf("listing all conns marked as auto=route and auto=start\n"); /* * list all conns marked as auto=route or start or * better */ for (conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) { if (conn->desired_state == STARTUP_START || conn->desired_state == STARTUP_ONDEMAND) printf("%s ", conn->name); } } if (liststart && !listroute) { if (verbose) printf("listing all conns marked as auto=start\n"); /* list all conns marked as auto=start */ for (conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) { if (conn->desired_state == STARTUP_START) printf("%s ", conn->name); } } if (listignore) { if (verbose) printf("listing all conns marked as auto=ignore\n"); /* list all conns marked as auto=start */ for (conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) { if (conn->desired_state == STARTUP_IGNORE) printf("%s ", conn->name); } printf("\n"); } } if (liststack) { const struct keyword_def *kd; for (kd = ipsec_conf_keywords_v2; kd->keyname != NULL; kd++) { if (strstr(kd->keyname, "protostack")) { if (cfg->setup.strings[kd->field]) printf("%s\n", cfg->setup.strings[kd->field]); else /* implicit default */ printf("netkey\n"); } } confread_free(cfg); exit(0); } if (configsetup) { const struct keyword_def *kd; printf("%s %sconfreadstatus=''\n", export, varprefix); for (kd = ipsec_conf_keywords_v2; kd->keyname != NULL; kd++) { if ((kd->validity & kv_config) == 0) continue; switch (kd->type) { case kt_string: case kt_filename: case kt_dirname: case kt_loose_enum: if (cfg->setup.strings[kd->field]) { printf("%s %s%s='%s'\n", export, varprefix, kd->keyname, cfg->setup.strings[kd->field]); } break; case kt_bool: printf("%s %s%s='%s'\n", export, varprefix, kd->keyname, cfg->setup.options[kd->field] ? "yes" : "no"); break; case kt_list: printf("%s %s%s='", export, varprefix, kd->keyname); confwrite_list(stdout, "", cfg->setup.options[kd->field], kd); printf("'\n"); break; case kt_obsolete: printf("# obsolete option '%s%s' ignored\n", varprefix, kd->keyname); break; default: if (cfg->setup.options[kd->field] || cfg->setup.options_set[kd->field]) { printf("%s %s%s='%d'\n", export, varprefix, kd->keyname, cfg->setup.options[kd->field]); } break; } }
int main(int argc, char **argv) { #if 0 NSS_NoDB_Init("."); if (!test_aes_cbc(&algo_aes_cbc)) { printf("aes-cbc failed\n"); } if (!test_camellia_cbc(&algo_camellia_cbc)) { printf("camellia-cbc failed\n"); } if (!test_aes_ctr(&algo_aes_ctr)) { printf("aes-ctr failed\n"); } exit(0); #endif int lockfd; /* * We read the intentions for how to log from command line options * and the config file. Then we prepare to be able to log, but until * then log to stderr (better then nothing). Once we are ready to * actually do loggin according to the methods desired, we set the * variables for those methods */ bool log_to_stderr_desired = FALSE; bool log_to_file_desired = FALSE; { int i; /* MUST BE BEFORE ANY allocs */ for (i = 1; i < argc; ++i) { if (streq(argv[i], "--leak-detective")) leak_detective = TRUE; } } pluto_name = argv[0]; coredir = clone_str("/var/run/pluto", "coredir in main()"); pluto_vendorid = clone_str(ipsec_version_vendorid(), "vendorid in main()"); unsigned int keep_alive = 0; /* Overridden by virtual_private= in ipsec.conf */ char *virtual_private = NULL; libreswan_passert_fail = passert_fail; /* handle arguments */ for (;; ) { /* * Note: we don't like the way short options get parsed * by getopt_long, so we simply pass an empty string as * the list. It could be "hvdenp:l:s:" "NARXPECK". */ int longindex = -1; int c = getopt_long(argc, argv, "", long_opts, &longindex); const char *optname = NULL; err_t ugh = NULL; /* complaint from case */ unsigned long u = 0; /* scratch for case */ if (longindex != -1) { const char *optmeta; optname = long_opts[longindex].name; optmeta = optname + strlen(optname) + 1; /* after '\0' */ switch (optmeta[0]) { case '_': libreswan_log("warning: option \"--%s\" with '_' in its name is obsolete; use '-'", optname); break; case '>': libreswan_log("warning: option \"--%s\" is obsolete; use \"--%s\"", optname, optmeta + 1); break; case '!': libreswan_log("warning: option \"--%s\" is obsolete; ignored", optname); continue; /* ignore it! */ } } /* Note: "breaking" from case terminates loop */ switch (c) { case EOF: /* end of flags */ break; case 0: /* * Long option already handled by getopt_long. * Not currently used since we always set flag to NULL. */ continue; case ':': /* diagnostic already printed by getopt_long */ case '?': /* diagnostic already printed by getopt_long */ invocation_fail(NULL); break; case 'h': /* --help */ usage(); break; /* not actually reached */ case 'X': /* --leak-detective */ /* * This flag was already processed at the start of main() * because leak_detective must be immutable from before * the first alloc(). * If this option is specified, we must have already * set it at the start of main(), so assert it. */ passert(leak_detective); continue; case 'C': /* --coredir */ pfree(coredir); coredir = clone_str(optarg, "coredir via getopt"); continue; case 'V': /* --vendorid */ pfree(pluto_vendorid); coredir = clone_str(optarg, "pluto_vendorid via getopt"); continue; case 'S': /* --statsdir */ pfreeany(pluto_stats_binary); pluto_stats_binary = clone_str(optarg, "statsbin"); continue; case 'v': /* --version */ printf("%s%s\n", ipsec_version_string(), compile_time_interop_options); /* not exit_pluto because we are not initialized yet */ exit(0); break; /* not actually reached */ case 'j': /* --nhelpers */ if (streq(optarg, "-1")) { nhelpers = -1; } else { ugh = ttoulb(optarg, 0, 10, 1000, &u); if (ugh != NULL) break; nhelpers = u; } continue; case 'c': /* --seedbits */ pluto_nss_seedbits = atoi(optarg); if (pluto_nss_seedbits == 0) { printf("pluto: seedbits must be an integer > 0"); /* not exit_pluto because we are not initialized yet */ exit(PLUTO_EXIT_NSS_FAIL); } continue; #ifdef HAVE_LABELED_IPSEC case 'w': /* --secctx-attr-type */ ugh = ttoulb(optarg, 0, 0, 0xFFFF, &u); if (ugh != NULL) break; if (u != SECCTX && u != ECN_TUNNEL_or_old_SECCTX) { ugh = "must be a positive 32001 (default) or 10 (for backward compatibility)"; break; } secctx_attr_type = u; continue; #endif case 'd': /* --nofork*/ fork_desired = FALSE; continue; case 'e': /* --stderrlog */ log_to_stderr_desired = TRUE; continue; case 'g': /* --logfile */ pluto_log_file = optarg; log_to_file_desired = TRUE; continue; case 't': /* --log-no-time */ log_with_timestamp = FALSE; continue; case '7': /* --log-no-append */ log_append = FALSE; continue; case '8': /* --drop-oppo-null */ pluto_drop_oppo_null = TRUE; continue; case '9': /* --expire-bare-shunt <interval> */ ugh = ttoulb(optarg, 0, 10, 1000, &u); if (ugh != NULL) break; bare_shunt_interval = u; continue; case 'k': /* --use-klips */ kern_interface = USE_KLIPS; continue; case 'L': /* --listen ip_addr */ { ip_address lip; err_t e = ttoaddr(optarg, 0, AF_UNSPEC, &lip); if (e != NULL) { /* *??? should we continue on failure? * If not, use ugh mechanism. */ libreswan_log( "invalid listen argument ignored: %s\n", e); } else { pluto_listen = clone_str(optarg, "pluto_listen"); libreswan_log( "bind() will be filtered for %s\n", pluto_listen); } } continue; case 'M': /* --use-mast */ kern_interface = USE_MASTKLIPS; continue; case 'F': /* --use-bsdkame */ kern_interface = USE_BSDKAME; continue; case 'K': /* --use-netkey */ kern_interface = USE_NETKEY; continue; case 'n': /* --use-nostack */ kern_interface = NO_KERNEL; continue; case 'D': /* --force-busy */ pluto_ddos_mode = DDOS_FORCE_BUSY; continue; case 'U': /* --force-unlimited */ pluto_ddos_mode = DDOS_FORCE_UNLIMITED; continue; case 'Z': /* --curl-iface */ curl_iface = optarg; continue; case 'I': /* --curl-timeout */ ugh = ttoulb(optarg, 0, 10, 0xFFFF, &u); if (ugh != NULL) break; if (u <= 0) { ugh = "must not be < 1"; break; } curl_timeout = u; continue; case 'r': /* --strictcrlpolicy */ strict_crl_policy = TRUE; continue; case 'o': strict_ocsp_policy = TRUE; continue; case 'O': ocsp_enable = TRUE; continue; case 'Y': ocsp_default_uri = optarg; continue; case 'J': ocsp_trust_name = optarg; continue; case 'T': /* --ocsp_timeout <seconds> */ ugh = ttoulb(optarg, 0, 10, 0xFFFF, &u); if (ugh != NULL) break; if (u == 0) { ugh = "must not be 0"; break; } ocsp_timeout = u; continue; case 'x': /* --crlcheckinterval <seconds> */ ugh = ttoulb(optarg, 0, 10, TIME_T_MAX, &u); if (ugh != NULL) break; crl_check_interval = deltatime(u); continue; case 'u': /* --uniqueids */ uniqueIDs = TRUE; continue; case 'i': /* --interface <ifname|ifaddr> */ if (!use_interface(optarg)) { ugh = "too many --interface specifications"; break; } continue; /* * This option does not really work, as this is the "left" * site only, you also need --to --ikeport again later on * It will result in: yourport -> 500, still not bypassing * filters */ case 'p': /* --ikeport <portnumber> */ ugh = ttoulb(optarg, 0, 10, 0xFFFF, &u); if (ugh != NULL) break; if (u == 0) { ugh = "must not be 0"; break; } pluto_port = u; continue; case 'q': /* --natikeport <portnumber> */ ugh = ttoulb(optarg, 0, 10, 0xFFFF, &u); if (ugh != NULL) break; if (u == 0) { ugh = "must not be 0"; break; } pluto_nat_port = u; continue; case 'b': /* --ctlbase <path> */ /* * ??? work to be done here: * * snprintf returns the required space if there * isn't enough, not -1. * -1 indicates another kind of error. * * This appears to be the only place where the * ctlbase value is used yet it is set elsewhere. * (This isn't clear -- it may be OK.) */ ctlbase = optarg; if (snprintf(ctl_addr.sun_path, sizeof(ctl_addr.sun_path), "%s%s", ctlbase, CTL_SUFFIX) == -1) { ugh = "<path>" CTL_SUFFIX " too long for sun_path"; break; } if (snprintf(info_addr.sun_path, sizeof(info_addr.sun_path), "%s%s", ctlbase, INFO_SUFFIX) == -1) { ugh = "<path>" INFO_SUFFIX " too long for sun_path"; break; } if (snprintf(pluto_lock, sizeof(pluto_lock), "%s%s", ctlbase, LOCK_SUFFIX) == -1) { ugh = "<path>" LOCK_SUFFIX " must fit"; break; } continue; case 's': /* --secretsfile <secrets-file> */ lsw_conf_secretsfile(optarg); continue; case 'f': /* --ipsecdir <ipsec-dir> */ lsw_init_ipsecdir(optarg); continue; case 'N': /* --debug-none */ base_debugging = DBG_NONE; continue; case 'A': /* --debug-all */ base_debugging = DBG_ALL; continue; case 'P': /* --perpeerlogbase */ base_perpeer_logdir = optarg; continue; case 'l': /* --perpeerlog */ log_to_perpeer = TRUE; continue; case '2': /* --keep-alive <delay_secs> */ ugh = ttoulb(optarg, 0, 10, secs_per_day, &u); if (ugh != NULL) break; keep_alive = u; continue; case '5': /* --debug-nat-t */ base_debugging |= DBG_NATT; continue; case '6': /* --virtual-private */ virtual_private = optarg; continue; case 'z': /* --config */ { /* * Config struct to variables mapper. This will * overwrite all previously set options. Keep this * in the same order as long_opts[] is. */ struct starter_config *cfg = read_cfg_file(optarg); /* leak */ set_cfg_string(&pluto_log_file, cfg->setup.strings[KSF_PLUTOSTDERRLOG]); if (pluto_log_file != NULL) log_to_syslog = FALSE; /* plutofork= no longer supported via config file */ log_with_timestamp = cfg->setup.options[KBF_PLUTOSTDERRLOGTIME]; log_append = cfg->setup.options[KBF_PLUTOSTDERRLOGAPPEND]; pluto_drop_oppo_null = cfg->setup.options[KBF_DROP_OPPO_NULL]; pluto_ddos_mode = cfg->setup.options[KBF_DDOS_MODE]; if (cfg->setup.options[KBF_FORCEBUSY]) { /* force-busy is obsoleted, translate to ddos-mode= */ pluto_ddos_mode = cfg->setup.options[KBF_DDOS_MODE] = DDOS_FORCE_BUSY; } /* ddos-ike-threshold and max-halfopen-ike */ pluto_ddos_threshold = cfg->setup.options[KBF_DDOS_IKE_THRESHOLD]; pluto_max_halfopen = cfg->setup.options[KBF_MAX_HALFOPEN_IKE]; strict_crl_policy = cfg->setup.options[KBF_STRICTCRLPOLICY]; pluto_shunt_lifetime = deltatime(cfg->setup.options[KBF_SHUNTLIFETIME]); strict_ocsp_policy = cfg->setup.options[KBF_STRICTOCSPPOLICY]; ocsp_enable = cfg->setup.options[KBF_OCSPENABLE]; set_cfg_string(&ocsp_default_uri, cfg->setup.strings[KSF_OCSPURI]); ocsp_timeout = cfg->setup.options[KBF_OCSPTIMEOUT]; set_cfg_string(&ocsp_trust_name, cfg->setup.strings[KSF_OCSPTRUSTNAME]); crl_check_interval = deltatime( cfg->setup.options[KBF_CRLCHECKINTERVAL]); uniqueIDs = cfg->setup.options[KBF_UNIQUEIDS]; /* * We don't check interfaces= here because that part * has been dealt with in _stackmanager before we * started */ set_cfg_string(&pluto_listen, cfg->setup.strings[KSF_LISTEN]); /* --ikeport */ pluto_port = cfg->setup.options[KBF_IKEPORT]; /* --nflog-all */ /* only causes nflog nmber to show in ipsec status */ pluto_nflog_group = cfg->setup.options[KBF_NFLOG_ALL]; /* only causes nflog nmber to show in ipsec status */ pluto_xfrmlifetime = cfg->setup.options[KBF_XFRMLIFETIME]; /* no config option: ctlbase */ /* --secrets */ if (cfg->setup.strings[KSF_SECRETSFILE] && *cfg->setup.strings[KSF_SECRETSFILE]) { lsw_conf_secretsfile(cfg->setup.strings[KSF_SECRETSFILE]); } if (cfg->setup.strings[KSF_IPSECDIR] != NULL && *cfg->setup.strings[KSF_IPSECDIR] != 0) { /* --ipsecdir */ lsw_init_ipsecdir(cfg->setup.strings[KSF_IPSECDIR]); } /* --perpeerlog */ log_to_perpeer = cfg->setup.options[KBF_PERPEERLOG]; if (log_to_perpeer) { /* --perpeerlogbase */ if (cfg->setup.strings[KSF_PERPEERDIR]) { set_cfg_string(&base_perpeer_logdir, cfg->setup.strings[KSF_PERPEERDIR]); } else { base_perpeer_logdir = clone_str("/var/log/pluto/", "perpeer_logdir"); } } if (cfg->setup.strings[KSF_CURLIFACE]) { pfreeany(curl_iface); /* curl-iface= */ curl_iface = clone_str(cfg->setup.strings[KSF_CURLIFACE], "curl-iface= via --config"); } if (cfg->setup.options[KBF_CURLTIMEOUT]) curl_timeout = cfg->setup.options[KBF_CURLTIMEOUT]; if (cfg->setup.strings[KSF_DUMPDIR]) { pfree(coredir); /* dumpdir= */ coredir = clone_str(cfg->setup.strings[KSF_DUMPDIR], "coredir via --config"); } /* --vendorid */ if (cfg->setup.strings[KSF_MYVENDORID]) { pfree(pluto_vendorid); pluto_vendorid = clone_str(cfg->setup.strings[KSF_MYVENDORID], "pluto_vendorid via --config"); } /* no config option: pluto_adns_option */ if (cfg->setup.strings[KSF_STATSBINARY] != NULL) { if (access(cfg->setup.strings[KSF_STATSBINARY], X_OK) == 0) { pfreeany(pluto_stats_binary); /* statsbin= */ pluto_stats_binary = clone_str(cfg->setup.strings[KSF_STATSBINARY], "statsbin via --config"); libreswan_log("statsbinary set to %s", pluto_stats_binary); } else { libreswan_log("statsbinary= '%s' ignored - file does not exist or is not executable", pluto_stats_binary); } } pluto_nss_seedbits = cfg->setup.options[KBF_SEEDBITS]; pluto_nat_port = cfg->setup.options[KBF_NATIKEPORT]; keep_alive = cfg->setup.options[KBF_KEEPALIVE]; set_cfg_string(&virtual_private, cfg->setup.strings[KSF_VIRTUALPRIVATE]); nhelpers = cfg->setup.options[KBF_NHELPERS]; #ifdef HAVE_LABELED_IPSEC secctx_attr_type = cfg->setup.options[KBF_SECCTX]; #endif base_debugging = cfg->setup.options[KBF_PLUTODEBUG]; char *protostack = cfg->setup.strings[KSF_PROTOSTACK]; if (protostack == NULL || *protostack == '\0') { kern_interface = USE_NETKEY; } else if (streq(protostack, "none")) { kern_interface = NO_KERNEL; } else if (streq(protostack, "auto")) { libreswan_log( "The option protostack=auto is obsoleted, falling back to protostack=netkey\n"); kern_interface = USE_NETKEY; } else if (streq(protostack, "klips")) { kern_interface = USE_KLIPS; } else if (streq(protostack, "mast")) { kern_interface = USE_MASTKLIPS; } else if (streq(protostack, "netkey") || streq(protostack, "native")) { kern_interface = USE_NETKEY; } else if (streq(protostack, "bsd") || streq(protostack, "kame") || streq(protostack, "bsdkame")) { kern_interface = USE_BSDKAME; } else if (streq(protostack, "win2k")) { kern_interface = USE_WIN2K; } confread_free(cfg); continue; } default: if (DBG_OFFSET <= c && c < DBG_OFFSET + IMPAIR_roof_IX) { base_debugging |= LELEM(c - DBG_OFFSET); continue; } bad_case(c); } /* if ugh is set, bail with diagnostic */ if (ugh != NULL) { char mess[200]; if (longindex == -1) { snprintf(mess, sizeof(mess), "unknown option: %s", ugh); } else if (optarg == NULL) { snprintf(mess, sizeof(mess), "--%s option: %s", optname, ugh); } else { snprintf(mess, sizeof(mess), "--%s \"%s\" option: %s", optname, optarg, ugh); } invocation_fail(mess); } break; } if (optind != argc) invocation_fail("unexpected argument"); reset_debugging(); if (chdir(coredir) == -1) { int e = errno; libreswan_log("pluto: warning: chdir(\"%s\") to dumpdir failed (%d: %s)", coredir, e, strerror(e)); } oco = lsw_init_options(); lockfd = create_lock(); /* select between logging methods */ if (log_to_stderr_desired || log_to_file_desired) log_to_syslog = FALSE; if (!log_to_stderr_desired) log_to_stderr = FALSE; #if 0 if (kernel_ops->set_debug != NULL) (*kernel_ops->set_debug)(cur_debugging, DBG_log, DBG_log); #endif /* * create control socket. * We must create it before the parent process returns so that * there will be no race condition in using it. The easiest * place to do this is before the daemon fork. */ { err_t ugh = init_ctl_socket(); if (ugh != NULL) { fprintf(stderr, "pluto: FATAL: %s", ugh); exit_pluto(PLUTO_EXIT_SOCKET_FAIL); } } /* If not suppressed, do daemon fork */ if (fork_desired) { #if USE_DAEMON if (daemon(TRUE, TRUE) < 0) { fprintf(stderr, "pluto: FATAL: daemon failed (%d %s)\n", errno, strerror(errno)); exit_pluto(PLUTO_EXIT_FORK_FAIL); } /* * Parent just exits, so need to fill in our own PID * file. This is racy, since the file won't be * created until after the parent has exited. * * Since "ipsec start" invokes pluto with --nofork, it * is probably safer to leave this feature disabled * then implement it using the daemon call. */ (void) fill_lock(lockfd, getpid()); #elif USE_FORK { pid_t pid = fork(); if (pid < 0) { int e = errno; fprintf(stderr, "pluto: FATAL: fork failed (%d %s)\n", errno, strerror(e)); exit_pluto(PLUTO_EXIT_FORK_FAIL); } if (pid != 0) { /* * parent: die, after filling PID into lock * file. * must not use exit_pluto: lock would be * removed! */ exit(fill_lock(lockfd, pid) ? 0 : 1); } } #else fprintf(stderr, "pluto: FATAL: fork/daemon not supported\n"); exit_pluto(PLUTO_EXIT_FORK_FAIL); #endif if (setsid() < 0) { int e = errno; fprintf(stderr, "FATAL: setsid() failed in main(). Errno %d: %s\n", errno, strerror(e)); exit_pluto(PLUTO_EXIT_FAIL); } } else { /* no daemon fork: we have to fill in lock file */ (void) fill_lock(lockfd, getpid()); if (isatty(fileno(stdout))) { fprintf(stdout, "Pluto initialized\n"); fflush(stdout); } } /* * Close everything but ctl_fd and (if needed) stderr. * There is some danger that a library that we don't know * about is using some fd that we don't know about. * I guess we'll soon find out. */ { int i; for (i = getdtablesize() - 1; i >= 0; i--) /* Bad hack */ if ((!log_to_stderr || i != 2) && i != ctl_fd) close(i); /* make sure that stdin, stdout, stderr are reserved */ if (open("/dev/null", O_RDONLY) != 0) lsw_abort(); if (dup2(0, 1) != 1) lsw_abort(); if (!log_to_stderr && dup2(0, 2) != 2) lsw_abort(); } init_constants(); init_pluto_constants(); pluto_init_log(); if (!pluto_init_nss(oco->nssdb)) { loglog(RC_LOG_SERIOUS, "FATAL: NSS initialization failure"); exit_pluto(PLUTO_EXIT_NSS_FAIL); } libreswan_log("NSS crypto library initialized"); if (ocsp_enable) { if (!init_nss_ocsp(ocsp_default_uri, ocsp_trust_name, ocsp_timeout, strict_ocsp_policy)) { loglog(RC_LOG_SERIOUS, "Initializing NSS OCSP failed"); exit_pluto(PLUTO_EXIT_NSS_FAIL); } else { libreswan_log("NSS OCSP Enabled"); } } #ifdef HAVE_LIBCAP_NG /* * Drop capabilities - this generates a false positive valgrind warning * See: http://marc.info/?l=linux-security-module&m=125895232029657 * * We drop these after creating the pluto socket or else we can't * create a socket if the parent dir is non-root (eg openstack) */ capng_clear(CAPNG_SELECT_BOTH); capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE | CAPNG_PERMITTED, CAP_NET_BIND_SERVICE, CAP_NET_ADMIN, CAP_NET_RAW, CAP_IPC_LOCK, CAP_AUDIT_WRITE, /* for google authenticator pam */ CAP_SETGID, CAP_SETUID, CAP_DAC_READ_SEARCH, -1); /* * We need to retain some capabilities for our children (updown): * CAP_NET_ADMIN to change routes * CAP_NET_RAW for iptables -t mangle * CAP_DAC_READ_SEARCH for pam / google authenticator */ capng_updatev(CAPNG_ADD, CAPNG_BOUNDING_SET, CAP_NET_ADMIN, CAP_NET_RAW, CAP_DAC_READ_SEARCH, -1); capng_apply(CAPNG_SELECT_BOTH); libreswan_log("libcap-ng support [enabled]"); #else libreswan_log("libcap-ng support [disabled]"); #endif #ifdef FIPS_CHECK libreswan_log("FIPS HMAC integrity support [enabled]"); /* * FIPS mode requires two conditions to be true: * - FIPS Kernel mode: fips=1 kernel boot parameter * - FIPS Product mode: See FIPSPRODUCTCHECK in Makefile.inc * (in RHEL/Fedora, dracut-fips installs $FIPSPRODUCTCHECK) * * When FIPS mode, abort on self-check hmac failure. Otherwise, complain */ { if (DBGP(IMPAIR_FORCE_FIPS)) { libreswan_log("Forcing FIPS checks to true to emulate FIPS mode"); lsw_set_fips_mode(LSW_FIPS_ON); } enum lsw_fips_mode pluto_fips_mode = lsw_get_fips_mode(); bool nss_fips_mode = PK11_IsFIPS(); /* * Now verify the consequences. Always run the tests * as combinations such as NSS in fips mode but as out * of it could be bad. */ switch (pluto_fips_mode) { case LSW_FIPS_UNKNOWN: loglog(RC_LOG_SERIOUS, "ABORT: pluto FIPS mode could not be determined"); exit_pluto(PLUTO_EXIT_FIPS_FAIL); break; case LSW_FIPS_ON: libreswan_log("FIPS mode enabled for pluto daemon"); if (nss_fips_mode) { libreswan_log("NSS library is running in FIPS mode"); } else { loglog(RC_LOG_SERIOUS, "ABORT: pluto in FIPS mode but NSS library is not"); exit_pluto(PLUTO_EXIT_FIPS_FAIL); } break; case LSW_FIPS_OFF: libreswan_log("FIPS mode disabled for pluto daemon"); if (nss_fips_mode) { loglog(RC_LOG_SERIOUS, "Warning: NSS library is running in FIPS mode"); } break; case LSW_FIPS_UNSET: default: bad_case(pluto_fips_mode); } /* always run hmac check so we can print diagnostic */ bool fips_files = FIPSCHECK_verify_files(fips_package_files); if (fips_files) { libreswan_log("FIPS HMAC integrity verification self-test passed"); } else { loglog(RC_LOG_SERIOUS, "FIPS HMAC integrity verification self-test FAILED"); } if (pluto_fips_mode == LSW_FIPS_ON && !fips_files) { exit_pluto(PLUTO_EXIT_FIPS_FAIL); } } #else libreswan_log("FIPS HMAC integrity support [disabled]"); #endif #ifdef USE_LINUX_AUDIT linux_audit_init(); #else libreswan_log("Linux audit support [disabled]"); #endif { const char *vc = ipsec_version_code(); libreswan_log("Starting Pluto (Libreswan Version %s%s) pid:%u", vc, compile_time_interop_options, getpid()); } libreswan_log("core dump dir: %s", coredir); if (oco->secretsfile && *oco->secretsfile) libreswan_log("secrets file: %s", oco->secretsfile); libreswan_log(leak_detective ? "leak-detective enabled" : "leak-detective disabled"); /* Check for SAREF support */ #ifdef KLIPS_MAST #include <ipsec_saref.h> { int e, sk, saref; saref = 1; errno = 0; sk = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); e = setsockopt(sk, IPPROTO_IP, IP_IPSEC_REFINFO, &saref, sizeof(saref)); if (e == -1 ) libreswan_log("SAref support [disabled]: %s", strerror(errno)); else libreswan_log("SAref support [enabled]"); errno = 0; e = setsockopt(sk, IPPROTO_IP, IP_IPSEC_BINDREF, &saref, sizeof(saref)); if (e == -1 ) libreswan_log("SAbind support [disabled]: %s", strerror(errno)); else libreswan_log("SAbind support [enabled]"); close(sk); } #endif libreswan_log("NSS crypto [enabled]"); #ifdef XAUTH_HAVE_PAM libreswan_log("XAUTH PAM support [enabled]"); #else libreswan_log("XAUTH PAM support [disabled]"); #endif /* Log various impair-* functions if they were enabled */ if (DBGP(IMPAIR_BUST_MI2)) libreswan_log("Warning: IMPAIR_BUST_MI2 enabled"); if (DBGP(IMPAIR_BUST_MR2)) libreswan_log("Warning: IMPAIR_BUST_MR2 enabled"); if (DBGP(IMPAIR_SA_CREATION)) libreswan_log("Warning: IMPAIR_SA_CREATION enabled"); if (DBGP(IMPAIR_JACOB_TWO_TWO)) libreswan_log("Warning: IMPAIR_JACOB_TWO_TWO enabled"); if (DBGP(IMPAIR_DIE_ONINFO)) libreswan_log("Warning: IMPAIR_DIE_ONINFO enabled"); if (DBGP(IMPAIR_MAJOR_VERSION_BUMP)) libreswan_log("Warning: IMPAIR_MAJOR_VERSION_BUMP enabled"); if (DBGP(IMPAIR_MINOR_VERSION_BUMP)) libreswan_log("Warning: IMPAIR_MINOR_VERSION_BUMP enabled"); if (DBGP(IMPAIR_RETRANSMITS)) libreswan_log("Warning: IMPAIR_RETRANSMITS enabled"); if (DBGP(IMPAIR_SEND_BOGUS_ISAKMP_FLAG)) libreswan_log("Warning: IMPAIR_SEND_BOGUS_ISAKMP_FLAG enabled"); if (DBGP(IMPAIR_SEND_BOGUS_PAYLOAD_FLAG)) libreswan_log("Warning: IMPAIR_SEND_BOGUS_PAYLOAD_FLAG enabled"); if (DBGP(IMPAIR_SEND_IKEv2_KE)) libreswan_log("Warning: IMPAIR_SEND_IKEv2_KE enabled"); if (DBGP(IMPAIR_SEND_KEY_SIZE_CHECK)) libreswan_log("Warning: IMPAIR_SEND_KEY_SIZE_CHECK enabled"); if (DBGP(IMPAIR_SEND_NO_DELETE)) libreswan_log("Warning: IMPAIR_SEND_NO_DELETE enabled"); if (DBGP(IMPAIR_FORCE_FIPS)) libreswan_log("Warning: IMPAIR_FORCE_FIPS enabled"); if (DBGP(IMPAIR_SEND_NO_IKEV2_AUTH)) libreswan_log("Warning: IMPAIR_SEND_NO_IKEV2_AUTH enabled"); if (DBGP(IMPAIR_SEND_ZERO_GX)) libreswan_log("Warning: IMPAIR_SEND_ZERO_GX enabled"); if (DBGP(IMPAIR_SEND_BOGUS_DCOOKIE)) libreswan_log("Warning: IMPAIR_SEND_BOGUS_DCOOKIE enabled"); /* Initialize all of the various features */ init_nat_traversal(keep_alive); init_virtual_ip(virtual_private); /* obsoleted by nss code init_rnd_pool(); */ init_event_base(); init_secret(); init_states(); init_connections(); init_crypto(); init_crypto_helpers(nhelpers); init_demux(); init_kernel(); init_id(); init_vendorid(); #if defined(LIBCURL) || defined(LDAP_VER) init_fetch(); #endif load_crls(); #ifdef HAVE_LABELED_IPSEC init_avc(); #endif daily_log_event(); #ifdef USE_SYSTEMD_WATCHDOG pluto_sd_init(); #endif call_server(); return -1; /* Shouldn't ever reach this */ }
static int ldap_mapper_match_user(X509 *x509, const char *login, void *context) { int match_found = 0; int i=0; if ( 1 != ldap_get_certificate(login)){ DBG("ldap_get_certificate() failed"); match_found = 0; } else { /* TODO: maybe compare public keys instead of hashes */ while( i<certcnt && !match_found ) { #ifdef HAVE_NSS if ( x509 == ldap_x509[i]) { #else if ( 0 == X509_cmp(x509, ldap_x509[i])) { #endif DBG1("Certificate %d is matching", i); match_found = 1; } else { DBG1("Certificate %d is NOT matching", i); } i++; } if (certcnt) { #ifdef HAVE_NSS int rv; for (rv=0; rv<certcnt; rv++) if (ldap_x509[rv]) CERT_DestroyCertificate(ldap_x509[rv]); #endif free(ldap_x509); } certcnt=0; } return match_found; } static char * ldap_mapper_find_user(X509 *x509, void *context, int *match) { struct passwd *pw = NULL; char *found=NULL; setpwent(); while( (pw=getpwent()) !=NULL) { int res; DBG1("Trying to match certificate with user: '******'",pw->pw_name); res= ldap_mapper_match_user(x509,pw->pw_name,context); if (res) { DBG1("Certificate maps to user '%s'",pw->pw_name); found= clone_str(pw->pw_name); *match = 1; break; } else { DBG1("Certificate map to user '%s' failed",pw->pw_name); } } endpwent(); #ifdef false int res; res= ldap_mapper_match_user(x509,"wefel",context); if (res) { DBG("Certificate maps to user wefel"); found= clone_str("wefel"); } else { DBG("Certificate map to user wefel failed"); } #endif return found; } static mapper_module * init_mapper_st(scconf_block *blk, const char *name) { mapper_module *pt= malloc(sizeof(mapper_module)); if (!pt) return NULL; pt->name = name; pt->block = blk; pt->context = NULL; pt->entries = ldap_mapper_find_entries; pt->finder = ldap_mapper_find_user; pt->matcher = ldap_mapper_match_user; pt->deinit = mapper_module_end; return pt; }
static bool load_conn(struct ub_ctx *dnsctx, struct starter_conn *conn, struct config_parsed *cfgp, struct section_list *sl, bool alsoprocessing, bool defaultconn, bool resolvip, err_t *perr) { bool err = FALSE; err |= load_conn_basic(conn, sl, defaultconn ? k_default : k_set, perr); move_comment_list(&conn->comments, &sl->comments); if (err) return err; if (conn->strings[KSF_ALSO] != NULL && !alsoprocessing) { starter_log(LOG_LEVEL_INFO, "also= is not valid in section '%s'", sl->name); return TRUE; /* error */ } /* now, process the also's */ if (conn->alsos) FREE_LIST(conn->alsos); conn->alsos = new_list(conn->strings[KSF_ALSO]); if (alsoprocessing && conn->alsos != NULL) { struct section_list *sl1; /* note: for the duration of this loop body * conn->alsos is migrated to local variable alsos. */ char **alsos = conn->alsos; int alsosize; int alsoplace; conn->alsos = NULL; /* reset all of the "beenhere" flags */ for (sl1 = cfgp->sections.tqh_first; sl1 != NULL; sl1 = sl1->link.tqe_next) sl1->beenhere = FALSE; sl->beenhere = TRUE; /* count them */ for (alsosize = 0; alsos[alsosize] != NULL; alsosize++) ; alsoplace = 0; while (alsoplace < alsosize && alsos[alsoplace] != NULL && alsoplace < ALSO_LIMIT) { /* * for each also= listed, go find this section's keyword list, and * load it as well. This may extend the also= list (and the end), * which we handle by zeroing the also list, and adding to it after * checking for duplicates. */ for (sl1 = cfgp->sections.tqh_first; sl1 != NULL && !streq(alsos[alsoplace], sl1->name); sl1 = sl1->link.tqe_next) ; starter_log(LOG_LEVEL_DEBUG, "\twhile loading conn '%s' also including '%s'", conn->name, alsos[alsoplace]); /* * if we found something that matches by name, and we haven't be * there, then process it. */ if (sl1 && !sl1->beenhere) { conn->strings_set[KSF_ALSO] = FALSE; pfreeany(conn->strings[KSF_ALSO]); conn->strings[KSF_ALSO] = NULL; sl1->beenhere = TRUE; /* translate things, but do not replace earlier settings!*/ err |= translate_conn(conn, sl1, k_set, perr); if (conn->strings[KSF_ALSO] != NULL) { /* now, check out the KSF_ALSO, and extend list if we need to */ char **newalsos = new_list( conn->strings[KSF_ALSO]); if (newalsos != NULL) { char **ra; int newalsoplace; /* count them */ for (newalsoplace = 0; newalsos[newalsoplace] != NULL; newalsoplace++) ; /* extend conn->alss */ ra = alloc_bytes((alsosize + newalsoplace + 1) * sizeof(char *), "conn->alsos"); memcpy(ra, alsos, alsosize * sizeof(char *)); pfree(alsos); alsos = ra; for (newalsoplace = 0; newalsos[newalsoplace] != NULL; newalsoplace++) { assert(conn != NULL); assert(conn->name != NULL); starter_log( LOG_LEVEL_DEBUG, "\twhile processing section '%s' added also=%s", sl1->name, newalsos[newalsoplace]); alsos[alsosize++] = clone_str(newalsos[newalsoplace], "alsos"); } alsos[alsosize] = NULL; } FREE_LIST(newalsos); } } alsoplace++; } /* migrate alsos back to conn->alsos */ conn->alsos = alsos; if (alsoplace >= ALSO_LIMIT) { starter_log(LOG_LEVEL_INFO, "while loading conn '%s', too many also= used at section %s. Limit is %d", conn->name, alsos[alsoplace], ALSO_LIMIT); return TRUE; /* error */ } } #ifdef PARSER_TYPE_DEBUG /* translate strings/numbers into conn items */ starter_log(LOG_LEVEL_DEBUG, "#checking options_set[KBF_TYPE,%d]=%d %d", KBF_TYPE, conn->options_set[KBF_TYPE], conn->options[KBF_TYPE]); #endif if (conn->options_set[KBF_TYPE]) { switch ((enum keyword_satype)conn->options[KBF_TYPE]) { case KS_TUNNEL: conn->policy |= POLICY_TUNNEL; conn->policy &= ~POLICY_SHUNT_MASK; break; case KS_TRANSPORT: conn->policy &= ~POLICY_TUNNEL; conn->policy &= ~POLICY_SHUNT_MASK; break; case KS_PASSTHROUGH: conn->policy &= ~(POLICY_ENCRYPT | POLICY_AUTHENTICATE | POLICY_TUNNEL | POLICY_RSASIG); conn->policy &= ~POLICY_SHUNT_MASK; conn->policy |= POLICY_SHUNT_PASS; break; case KS_DROP: conn->policy &= ~(POLICY_ENCRYPT | POLICY_AUTHENTICATE | POLICY_TUNNEL | POLICY_RSASIG); conn->policy &= ~POLICY_SHUNT_MASK; conn->policy |= POLICY_SHUNT_DROP; break; case KS_REJECT: conn->policy &= ~(POLICY_ENCRYPT | POLICY_AUTHENTICATE | POLICY_TUNNEL | POLICY_RSASIG); conn->policy &= ~POLICY_SHUNT_MASK; conn->policy |= POLICY_SHUNT_REJECT; break; } } if (conn->options_set[KBF_FAILURESHUNT]) { conn->policy &= ~POLICY_FAIL_MASK; switch(conn->options[KBF_FAILURESHUNT]) { case KFS_FAIL_NONE: conn->policy |= POLICY_FAIL_NONE; break; case KFS_FAIL_PASS: conn->policy |= POLICY_FAIL_PASS; break; case KFS_FAIL_DROP: conn->policy |= POLICY_FAIL_DROP; break; case KFS_FAIL_REJECT: conn->policy |= POLICY_FAIL_REJECT; break; } } if (conn->options_set[KBF_NEGOTIATIONSHUNT]) { switch(conn->options[KBF_NEGOTIATIONSHUNT]) { case KNS_FAIL_PASS: conn->policy |= POLICY_NEGO_PASS; break; case KNS_FAIL_DROP: conn->policy &= ~POLICY_NEGO_PASS; break; } } KW_POLICY_FLAG(KBF_COMPRESS, POLICY_COMPRESS); KW_POLICY_FLAG(KBF_PFS, POLICY_PFS); /* reset authby flags */ if (conn->options_set[KBF_AUTHBY]) { conn->policy &= ~(POLICY_ID_AUTH_MASK); #ifdef FIPS_CHECK if (libreswan_fipsmode()) { if (LIN(POLICY_PSK, conn->options[KBF_AUTHBY])) { starter_log(LOG_LEVEL_INFO, "while loading conn '%s', PSK not allowed in FIPS mode with NSS", conn->name); return TRUE; /* error */ } } #endif conn->policy |= conn->options[KBF_AUTHBY]; #ifdef STARTER_POLICY_DEBUG starter_log(LOG_LEVEL_DEBUG, "%s: setting conn->policy=%08x (%08x)", conn->name, (unsigned int)conn->policy, conn->options[KBF_AUTHBY]); #endif } KW_POLICY_NEGATIVE_FLAG(KBF_IKEPAD, POLICY_NO_IKEPAD); KW_POLICY_NEGATIVE_FLAG(KBF_REKEY, POLICY_DONT_REKEY); KW_POLICY_FLAG(KBF_AGGRMODE, POLICY_AGGRESSIVE); KW_POLICY_FLAG(KBF_MODECONFIGPULL, POLICY_MODECFG_PULL); KW_POLICY_FLAG(KBF_OVERLAPIP, POLICY_OVERLAPIP); KW_POLICY_FLAG(KBF_IKEv2_ALLOW_NARROWING, POLICY_IKEV2_ALLOW_NARROWING); KW_POLICY_FLAG(KBF_IKEv2_PAM_AUTHORIZE, POLICY_IKEV2_PAM_AUTHORIZE); if (conn->strings_set[KSF_ESP]) conn->esp = clone_str(conn->strings[KSF_ESP],"KSF_ESP"); #ifdef HAVE_LABELED_IPSEC if (conn->strings_set[KSF_POLICY_LABEL]) conn->policy_label = clone_str(conn->strings[KSF_POLICY_LABEL],"KSF_POLICY_LABEL"); if (conn->policy_label != NULL) starter_log(LOG_LEVEL_DEBUG, "connection's policy label: %s", conn->policy_label); #endif if (conn->strings_set[KSF_IKE]) conn->ike = clone_str(conn->strings[KSF_IKE],"KSF_IKE"); if (conn->strings_set[KSF_MODECFGDNS1]) { conn->modecfg_dns1 = clone_str(conn->strings[KSF_MODECFGDNS1],"KSF_MODECFGDNS1"); } if (conn->strings_set[KSF_MODECFGDNS2]) { conn->modecfg_dns2 = clone_str(conn->strings[KSF_MODECFGDNS2], "KSF_MODECFGDNS2"); } if (conn->strings_set[KSF_MODECFGDOMAIN]) { conn->modecfg_domain = clone_str(conn->strings[KSF_MODECFGDOMAIN],"KSF_MODECFGDOMAIN"); } if (conn->strings_set[KSF_MODECFGBANNER]) { conn->modecfg_banner = clone_str(conn->strings[KSF_MODECFGBANNER],"KSF_MODECFGBANNER"); } if (conn->strings_set[KSF_CONNALIAS]) conn->connalias = clone_str(conn->strings[KSF_CONNALIAS],"KSF_CONNALIAS"); if (conn->options_set[KBF_PHASE2]) { conn->policy &= ~(POLICY_AUTHENTICATE | POLICY_ENCRYPT); conn->policy |= conn->options[KBF_PHASE2]; } if (conn->options_set[KBF_IKEv2]) { lset_t policy = LEMPTY; switch (conn->options[KBF_IKEv2]) { case fo_never: policy = POLICY_IKEV1_ALLOW; break; case fo_permit: /* this is the default for now */ policy = POLICY_IKEV1_ALLOW | POLICY_IKEV2_ALLOW; break; case fo_propose: policy = POLICY_IKEV1_ALLOW | POLICY_IKEV2_ALLOW | POLICY_IKEV2_PROPOSE; break; case fo_insist: policy = POLICY_IKEV2_ALLOW | POLICY_IKEV2_PROPOSE; break; } conn->policy = (conn->policy & ~POLICY_IKEV2_MASK) | policy; } if (conn->options_set[KBF_IKE_FRAG]) { switch (conn->options[KBF_IKE_FRAG]) { case ynf_no: conn->policy &= ~POLICY_IKE_FRAG_ALLOW; conn->policy &= ~POLICY_IKE_FRAG_FORCE; break; case ynf_yes: /* this is the default */ conn->policy |= POLICY_IKE_FRAG_ALLOW; break; case ynf_force: conn->policy |= POLICY_IKE_FRAG_ALLOW | POLICY_IKE_FRAG_FORCE; break; } } if (conn->options_set[KBF_SAREFTRACK]) { switch (conn->options[KBF_SAREFTRACK]) { case sat_yes: /* this is the default */ conn->policy |= POLICY_SAREF_TRACK; break; case sat_conntrack: conn->policy |= POLICY_SAREF_TRACK | POLICY_SAREF_TRACK_CONNTRACK; break; case sat_no: conn->policy &= ~POLICY_SAREF_TRACK; conn->policy &= ~POLICY_SAREF_TRACK_CONNTRACK; break; } } err |= validate_end(dnsctx, conn, &conn->left, "left", resolvip, perr); err |= validate_end(dnsctx, conn, &conn->right, "right", resolvip, perr); /* * TODO: * verify both ends are using the same inet family, if one end * is "%any" or "%defaultroute", then perhaps adjust it. * ensource this for left,leftnexthop,right,rightnexthop * Ideally, phase out connaddrfamily= which now wrongly assumes * left,leftnextop,leftsubnet are the same inet family * Currently, these tests are implicitely done, and wrongly * in case of 6in4 and 4in6 tunnels */ if (conn->options_set[KBF_AUTO]) conn->desired_state = conn->options[KBF_AUTO]; return err; }
/** * Set up hardcoded defaults, from data in programs/pluto/constants.h * * @param cfg starter_config struct * @return void */ void ipsecconf_default_values(struct starter_config *cfg) { zero(cfg); /* ??? pointer fields might not be NULLed */ TAILQ_INIT(&cfg->conns); /* config setup */ cfg->setup.options[KBF_FRAGICMP] = FALSE; /* see sysctl_ipsec_icmp in ipsec_proc.c */ cfg->setup.options[KBF_HIDETOS] = TRUE; cfg->setup.options[KBF_PLUTORESTARTONCRASH] = TRUE; cfg->setup.options[KBF_PLUTOSTDERRLOGTIME] = TRUE; cfg->setup.options[KBF_PLUTOSTDERRLOGAPPEND] = TRUE; cfg->setup.options[KBF_UNIQUEIDS] = TRUE; cfg->setup.options[KBF_PERPEERLOG] = FALSE; cfg->setup.options[KBF_IKEPORT] = IKE_UDP_PORT; cfg->setup.options[KBF_NFLOG_ALL] = 0; /* disabled per default */ cfg->setup.options[KBF_XFRMLIFETIME] = 300; /* not used by pluto itself */ cfg->setup.options[KBF_NHELPERS] = -1; /* see also plutomain.c */ cfg->setup.options[KBF_KEEPALIVE] = 0; /* config setup */ cfg->setup.options[KBF_NATIKEPORT] = NAT_IKE_UDP_PORT; cfg->setup.options[KBF_DDOS_IKE_TRESHOLD] = DEFAULT_IKE_SA_DDOS_TRESHOLD; cfg->setup.options[KBF_MAX_HALFOPEN_IKE] = DEFAULT_MAXIMUM_HALFOPEN_IKE_SA; cfg->setup.options[KBF_SHUNTLIFETIME] = PLUTO_SHUNT_LIFE_DURATION_DEFAULT; /* Don't inflict BSI requirements on everyone */ cfg->setup.options[KBF_SEEDBITS] = 0; #ifdef HAVE_LABELED_IPSEC cfg->setup.options[KBF_SECCTX] = SECCTX; #endif cfg->setup.options[KBF_DDOS_MODE] = DDOS_AUTO; /* conn %default */ cfg->conn_default.options[KBF_NAT_KEEPALIVE] = TRUE; /* per conn */ cfg->conn_default.options[KBF_TYPE] = KS_TUNNEL; cfg->conn_default.options[KBF_INITIAL_CONTACT] = FALSE; cfg->conn_default.options[KBF_CISCO_UNITY] = FALSE; cfg->conn_default.options[KBF_SEND_VENDORID] = FALSE; cfg->conn_default.options[KBF_REMOTEPEERTYPE] = NON_CISCO; cfg->conn_default.options[KBF_SHA2_TRUNCBUG] = FALSE; cfg->conn_default.options[KBF_IKEPAD] = TRUE; cfg->conn_default.options[KBF_IKEV1_NATT] = natt_both; /* Network Manager support */ #ifdef HAVE_NM cfg->conn_default.options[KBF_NMCONFIGURED] = FALSE; #endif #ifdef HAVE_LABELED_IPSEC cfg->conn_default.options[KBF_LABELED_IPSEC] = FALSE; #endif cfg->conn_default.options[KBF_XAUTHBY] = XAUTHBY_FILE; cfg->conn_default.options[KBF_XAUTHFAIL] = XAUTHFAIL_HARD; cfg->conn_default.policy = POLICY_RSASIG | POLICY_TUNNEL | POLICY_ENCRYPT | POLICY_PFS; cfg->conn_default.policy |= POLICY_IKEV1_ALLOW | POLICY_IKEV2_ALLOW; /* ikev2=permit */ cfg->conn_default.policy |= POLICY_SAREF_TRACK; /* sareftrack=yes */ cfg->conn_default.policy |= POLICY_IKE_FRAG_ALLOW; /* ike_frag=yes */ cfg->conn_default.options[KBF_IKELIFETIME] = OAKLEY_ISAKMP_SA_LIFETIME_DEFAULT; cfg->conn_default.options[KBF_RETRANSMIT_TIMEOUT] = RETRANSMIT_TIMEOUT_DEFAULT; cfg->conn_default.options[KBF_RETRANSMIT_INTERVAL] = RETRANSMIT_INTERVAL_DEFAULT; cfg->conn_default.options[KBF_SALIFETIME] = SA_LIFE_DURATION_DEFAULT; cfg->conn_default.options[KBF_REKEYMARGIN] = SA_REPLACEMENT_MARGIN_DEFAULT; cfg->conn_default.options[KBF_REKEYFUZZ] = SA_REPLACEMENT_FUZZ_DEFAULT; cfg->conn_default.options[KBF_KEYINGTRIES] = SA_REPLACEMENT_RETRIES_DEFAULT; /* now here is a sticker.. we want it on. But pluto has to be smarter first */ cfg->conn_default.options[KBF_OPPOENCRYPT] = FALSE; cfg->conn_default.options[KBF_CONNADDRFAMILY] = AF_INET; cfg->conn_default.left.addr_family = AF_INET; anyaddr(AF_INET, &cfg->conn_default.left.addr); cfg->conn_default.left.nexttype = KH_NOTSET; anyaddr(AF_INET, &cfg->conn_default.left.nexthop); cfg->conn_default.right.addr_family = AF_INET; anyaddr(AF_INET, &cfg->conn_default.right.addr); cfg->conn_default.right.nexttype = KH_NOTSET; anyaddr(AF_INET, &cfg->conn_default.right.nexthop); /* default is NOT to look in DNS */ cfg->conn_default.left.key_from_DNS_on_demand = FALSE; cfg->conn_default.right.key_from_DNS_on_demand = FALSE; cfg->conn_default.options[KBF_AUTO] = STARTUP_IGNORE; cfg->conn_default.state = STATE_LOADED; cfg->ctlbase = clone_str(CTL_FILE, "default base"); }
/** * Take keywords from ipsec.conf syntax and load into a conn struct * * * @param conn a connection definition * @param sl a section_list * @param assigned_value is set to either k_set, or k_default. * k_default is used when we are loading a conn that should be * considered to be a "default" value, and that replacing this * value is considered acceptable. * @return bool TRUE if unsuccessfull */ static bool translate_conn(struct starter_conn *conn, struct section_list *sl, enum keyword_set assigned_value, err_t *error) { bool err = FALSE; struct kw_list *kw; for (kw = sl->kw; kw; kw = kw->next) { ksf *the_strings = &conn->strings; str_set *set_strings = &conn->strings_set; knf *the_options = &conn->options; int_set *set_options = &conn->options_set; unsigned int field; if ((kw->keyword.keydef->validity & kv_conn) == 0) { /* this isn't valid in a conn! */ *error = (const char *)tmp_err; snprintf(tmp_err, sizeof(tmp_err), "keyword '%s' is not valid in a conn (%s)\n", kw->keyword.keydef->keyname, sl->name); starter_log(LOG_LEVEL_INFO, "%s", tmp_err); continue; } if (kw->keyword.keydef->validity & kv_leftright) { if (kw->keyword.keyleft) { the_strings = &conn->left.strings; the_options = &conn->left.options; set_strings = &conn->left.strings_set; set_options = &conn->left.options_set; } else { the_strings = &conn->right.strings; the_options = &conn->right.options; set_strings = &conn->right.strings_set; set_options = &conn->right.options_set; } } field = kw->keyword.keydef->field; #ifdef PARSER_TYPE_DEBUG starter_log(LOG_LEVEL_DEBUG, "#analyzing %s[%d] kwtype=%d", kw->keyword.keydef->keyname, field, kw->keyword.keydef->type); #endif assert(kw->keyword.keydef != NULL); switch (kw->keyword.keydef->type) { case kt_string: case kt_filename: case kt_dirname: case kt_bitstring: case kt_ipaddr: case kt_range: case kt_subnet: case kt_idtype: /* all treated as strings for now */ assert(kw->keyword.keydef->field < KEY_STRINGS_MAX); if ((*set_strings)[field] == k_set) { *error = tmp_err; snprintf(tmp_err, sizeof(tmp_err), "duplicate key '%s' in conn %s while processing def %s", kw->keyword.keydef->keyname, conn->name, sl->name); starter_log(LOG_LEVEL_INFO, "%s", tmp_err); if (kw->keyword.string == NULL || (*the_strings)[field] == NULL || !streq(kw->keyword.string, (*the_strings)[field])) { err = TRUE; break; } } pfreeany((*the_strings)[field]); if (kw->string == NULL) { *error = tmp_err; snprintf(tmp_err, sizeof(tmp_err), "Invalid %s value", kw->keyword.keydef->keyname); err = TRUE; break; } (*the_strings)[field] = clone_str(kw->string,"kt_idtype kw->string"); (*set_strings)[field] = assigned_value; break; case kt_appendstring: case kt_appendlist: /* implicitly, this field can have multiple values */ assert(kw->keyword.keydef->field < KEY_STRINGS_MAX); if ((*the_strings)[field] == NULL) { (*the_strings)[field] = clone_str(kw->string, "kt_appendlist kw->string"); } else { char *s = (*the_strings)[field]; size_t old_len = strlen(s); /* excludes '\0' */ size_t new_len = strlen(kw->string); char *n; n = alloc_bytes(old_len + 1 + new_len + 1, "kt_appendlist"); memcpy(n, s, old_len); n[old_len] = ' '; memcpy(n + old_len + 1, kw->string, new_len + 1); /* includes '\0' */ (*the_strings)[field] = n; pfree(s); } (*set_strings)[field] = TRUE; break; case kt_rsakey: case kt_loose_enum: assert(field < KEY_STRINGS_MAX); assert(field < KEY_NUMERIC_MAX); if ((*set_options)[field] == k_set) { *error = tmp_err; snprintf(tmp_err, sizeof(tmp_err), "duplicate key '%s' in conn %s while processing def %s", kw->keyword.keydef->keyname, conn->name, sl->name); starter_log(LOG_LEVEL_INFO, "%s", tmp_err); /* only fatal if we try to change values */ if ((*the_options)[field] != (int)kw->number || !((*the_options)[field] == LOOSE_ENUM_OTHER && kw->number == LOOSE_ENUM_OTHER && kw->keyword.string != NULL && (*the_strings)[field] != NULL && streq(kw->keyword.string, (*the_strings)[field]))) { err = TRUE; break; } } (*the_options)[field] = kw->number; if (kw->number == LOOSE_ENUM_OTHER) { assert(kw->keyword.string != NULL); pfreeany((*the_strings)[field]); (*the_strings)[field] = clone_str( kw->keyword.string, "kt_loose_enum kw->keyword.string"); } (*set_options)[field] = assigned_value; break; case kt_list: case kt_bool: case kt_invertbool: case kt_enum: case kt_number: case kt_time: case kt_percent: /* all treated as a number for now */ assert(field < KEY_NUMERIC_MAX); if ((*set_options)[field] == k_set) { *error = tmp_err; snprintf(tmp_err, sizeof(tmp_err), "duplicate key '%s' in conn %s while processing def %s", kw->keyword.keydef->keyname, conn->name, sl->name); starter_log(LOG_LEVEL_INFO, "%s", tmp_err); if ((*the_options)[field] != (int)kw->number) { err = TRUE; break; } } #if 0 starter_log(LOG_LEVEL_DEBUG, "#setting %s[%d]=%u", kw->keyword.keydef->keyname, field, kw->number); #endif (*the_options)[field] = kw->number; (*set_options)[field] = assigned_value; break; case kt_comment: break; case kt_obsolete: starter_log(LOG_LEVEL_INFO, "Warning: obsolete keyword '%s' ignored", kw->keyword.keydef->keyname); break; case kt_obsolete_quiet: starter_log(LOG_LEVEL_DEBUG, "Warning: obsolete keyword '%s' ignored", kw->keyword.keydef->keyname); break; } } return err; }
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 }