Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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;
}