static int load_conn (struct starter_config *cfg , struct starter_conn *conn , struct config_parsed *cfgp , struct section_list *sl , bool alsoprocessing , bool defaultconn , bool resolvip , err_t *perr) { unsigned int err; err = 0; 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 1; } /* now, process the also's */ if (conn->alsos) free_list(conn->alsos); conn->alsos = new_list(conn->strings[KSF_ALSO]); if(alsoprocessing && conn->alsos) { unsigned int alsosize; char **alsos; struct section_list *sl1; /* reset all of the "beenhere" flags: can not also= and alsoflip= the same conn, btw. */ for(sl1 = cfgp->sections.tqh_first; sl1 != NULL; sl1 = sl1->link.tqe_next) { sl1->beenhere = FALSE; } sl->beenhere = TRUE; /* count them */ alsos = conn->alsos; conn->alsos = NULL; for(alsosize=0; alsos[alsosize]!=NULL; alsosize++); starter_log(LOG_LEVEL_DEBUG, "# conn %s processing alsos", conn->name); conn->alsos = process_alsos(cfg, conn, cfgp, alsos, alsosize, FALSE, perr); if(conn->strings[KSF_ALSOFLIP]) { alsos = new_list(conn->strings[KSF_ALSOFLIP]); for(alsosize=0; alsos[alsosize]!=NULL; alsosize++); starter_log(LOG_LEVEL_DEBUG, "# conn %s processing alsoflips", conn->name); conn->also_flips = process_alsos(cfg, conn, cfgp, alsos, alsosize, TRUE, perr); } } #ifdef PARSER_TYPE_DEBUG /* translate strings/numbers into conn items */ starter_log(LOG_LEVEL_DEBUG, "#checking options_set[KBF_TYPE,%d]=%d %d\n", 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_UDPENCAP: /* no way to specify this yet! */ 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; } } 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); conn->policy |= conn->options[KBF_AUTHBY]; #if STARTER_POLICY_DEBUG starter_log(LOG_LEVEL_DEBUG, "%s: setting conn->policy=%08x (%08x)\n", conn->name, (unsigned int)conn->policy, conn->options[KBF_AUTHBY]); #endif } 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); 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"); } starter_log(LOG_LEVEL_DEBUG,"connection's policy label: %s", conn->policy_label); #endif #if 0 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"); } #endif if(conn->strings_set[KSF_IKE]) { conn->ike = clone_str(conn->strings[KSF_IKE],"KSF_IKE"); } 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]) { switch(conn->options[KBF_IKEv2]) { case fo_never: conn->policy &= ~POLICY_IKEV2_ALLOW; break; case fo_permit: /* this is the default for now */ conn->policy |= POLICY_IKEV2_ALLOW; break; case fo_propose: conn->policy |= POLICY_IKEV2_ALLOW|POLICY_IKEV2_PROPOSE; break; case fo_insist: conn->policy |= POLICY_IKEV1_DISABLE; conn->policy |= POLICY_IKEV2_ALLOW|POLICY_IKEV2_PROPOSE; 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(conn, &conn->left, TRUE, resolvip, perr); err += validate_end(conn, &conn->right, FALSE, 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; }
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; }
static bool load_conn( #ifdef DNSSEC struct ub_ctx *dnsctx, #endif struct starter_conn *conn, const struct config_parsed *cfgp, struct section_list *sl, bool alsoprocessing, bool defaultconn, bool resolvip, err_t *perr) { bool err; /* turn all of the keyword/value pairs into options/strings in left/right */ err = translate_conn(conn, sl, defaultconn ? k_default : k_set, perr); move_comment_list(&conn->comments, &sl->comments); if (err) return err; if (conn->strings[KSCF_ALSO] != NULL && !alsoprocessing) { starter_log(LOG_LEVEL_INFO, "also= is not valid in section '%s'", sl->name); /* ??? should we not set *perr? */ return TRUE; /* error */ } /* now, process the also's */ if (conn->alsos != NULL) FREE_LIST(conn->alsos); conn->alsos = new_list(conn->strings[KSCF_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 been there, then process it. */ if (sl1 != NULL && !sl1->beenhere) { conn->strings_set[KSCF_ALSO] = FALSE; pfreeany(conn->strings[KSCF_ALSO]); conn->strings[KSCF_ALSO] = NULL; sl1->beenhere = TRUE; /* translate things, but do not replace earlier settings! */ err |= translate_conn(conn, sl1, k_set, perr); if (conn->strings[KSCF_ALSO] != NULL) { /* now, check out the KSCF_ALSO, and extend list if we need to */ char **newalsos = new_list( conn->strings[KSCF_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); /* ??? should we not set *perr? */ return TRUE; /* error */ } } if (conn->options_set[KBF_TYPE]) { switch ((enum keyword_satype)conn->options[KBF_TYPE]) { case KS_TUNNEL: if (conn->options_set[KBF_AUTHBY] && conn->options[KBF_AUTHBY] == POLICY_AUTH_NEVER) { *perr = "connection type=tunnel must not specify authby=never"; return TRUE; } conn->policy |= POLICY_TUNNEL; conn->policy &= ~POLICY_SHUNT_MASK; break; case KS_TRANSPORT: if (conn->options_set[KBF_AUTHBY] && conn->options[KBF_AUTHBY] == POLICY_AUTH_NEVER) { *perr = "connection type=transport must not specify authby=never"; return TRUE; } conn->policy &= ~POLICY_TUNNEL; conn->policy &= ~POLICY_SHUNT_MASK; break; case KS_PASSTHROUGH: if (!conn->options_set[KBF_AUTHBY] || conn->options[KBF_AUTHBY] != POLICY_AUTH_NEVER) { *perr = "connection type=passthrough must specify authby=never"; } conn->policy &= ~(POLICY_ENCRYPT | POLICY_AUTHENTICATE | POLICY_TUNNEL | POLICY_RSASIG); conn->policy &= ~POLICY_SHUNT_MASK; conn->policy |= POLICY_SHUNT_PASS; break; case KS_DROP: if (!conn->options_set[KBF_AUTHBY] || conn->options[KBF_AUTHBY] != POLICY_AUTH_NEVER) { *perr = "connection type=drop must specify authby=never"; } conn->policy &= ~(POLICY_ENCRYPT | POLICY_AUTHENTICATE | POLICY_TUNNEL | POLICY_RSASIG); conn->policy &= ~POLICY_SHUNT_MASK; conn->policy |= POLICY_SHUNT_DROP; break; case KS_REJECT: if (!conn->options_set[KBF_AUTHBY] || conn->options[KBF_AUTHBY] != POLICY_AUTH_NEVER) { *perr = "connection type=drop must specify authby=never"; } 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; conn->policy |= conn->options[KBF_AUTHBY]; } 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); # define str_to_conn(member, kscf) { \ if (conn->strings_set[kscf]) \ conn->member = clone_str(conn->strings[kscf], #kscf); \ } str_to_conn(esp, KSCF_ESP); #ifdef HAVE_LABELED_IPSEC str_to_conn(policy_label, KSCF_POLICY_LABEL); if (conn->policy_label != NULL) starter_log(LOG_LEVEL_DEBUG, "connection's policy label: %s", conn->policy_label); #endif str_to_conn(ike, KSCF_IKE); str_to_conn(modecfg_dns1, KSCF_MODECFGDNS1); str_to_conn(modecfg_dns2, KSCF_MODECFGDNS2); str_to_conn(modecfg_domain, KSCF_MODECFGDOMAIN); str_to_conn(modecfg_banner, KSCF_MODECFGBANNER); /* mark-in= and mark-out= override mark= */ str_to_conn(conn_mark_in, KSCF_CONN_MARK_BOTH); str_to_conn(conn_mark_out, KSCF_CONN_MARK_BOTH); str_to_conn(conn_mark_in, KSCF_CONN_MARK_IN); str_to_conn(conn_mark_out, KSCF_CONN_MARK_OUT); str_to_conn(vti_iface, KSCF_VTI_IFACE); str_to_conn(connalias, KSCF_CONNALIAS); # undef str_to_conn 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 pv2 = LEMPTY; switch (conn->options[KBF_IKEv2]) { case fo_never: pv2 = POLICY_IKEV1_ALLOW; break; case fo_permit: /* this is the default for now */ pv2 = POLICY_IKEV1_ALLOW | POLICY_IKEV2_ALLOW; break; case fo_propose: pv2 = POLICY_IKEV1_ALLOW | POLICY_IKEV2_ALLOW | POLICY_IKEV2_PROPOSE; break; case fo_insist: pv2 = POLICY_IKEV2_ALLOW | POLICY_IKEV2_PROPOSE; break; } conn->policy = (conn->policy & ~POLICY_IKEV2_MASK) | pv2; } if (conn->options_set[KBF_ESN]) { conn->policy &= ~(POLICY_ESN_NO | POLICY_ESN_YES); switch (conn->options[KBF_ESN]) { case esn_yes: conn->policy |= POLICY_ESN_YES; break; case esn_no: /* this is the default for now */ conn->policy |= POLICY_ESN_NO; break; case esn_either: conn->policy |= POLICY_ESN_NO | POLICY_ESN_YES; break; } } if (conn->options_set[KBF_IKE_FRAG]) { conn->policy &= ~(POLICY_IKE_FRAG_ALLOW | POLICY_IKE_FRAG_FORCE); switch (conn->options[KBF_IKE_FRAG]) { case ynf_no: 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]) { conn->policy &= ~(POLICY_SAREF_TRACK | POLICY_SAREF_TRACK_CONNTRACK); 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: break; } } /* * some options are set as part of our default, but * some make no sense for shunts, so remove those again */ if (NEVER_NEGOTIATE(conn->policy)) { /* remove IPsec related options */ conn->policy &= ~(POLICY_PFS | POLICY_COMPRESS | POLICY_ESN_NO | POLICY_ESN_YES | POLICY_SAREF_TRACK | POLICY_SAREF_TRACK_CONNTRACK); /* remove IKE related options */ conn->policy &= ~(POLICY_IKEV1_ALLOW | POLICY_IKEV2_ALLOW | POLICY_IKEV2_PROPOSE | POLICY_IKE_FRAG_ALLOW | POLICY_IKE_FRAG_FORCE); } err |= validate_end( #ifdef DNSSEC dnsctx, #endif conn, &conn->left, "left", resolvip, perr); err |= validate_end( #ifdef DNSSEC dnsctx, #endif 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; }