145916cd2Sjpk /*
245916cd2Sjpk  * CDDL HEADER START
345916cd2Sjpk  *
445916cd2Sjpk  * The contents of this file are subject to the terms of the
545916cd2Sjpk  * Common Development and Distribution License (the "License").
645916cd2Sjpk  * You may not use this file except in compliance with the License.
745916cd2Sjpk  *
845916cd2Sjpk  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
945916cd2Sjpk  * or http://www.opensolaris.org/os/licensing.
1045916cd2Sjpk  * See the License for the specific language governing permissions
1145916cd2Sjpk  * and limitations under the License.
1245916cd2Sjpk  *
1345916cd2Sjpk  * When distributing Covered Code, include this CDDL HEADER in each
1445916cd2Sjpk  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1545916cd2Sjpk  * If applicable, add the following below this CDDL HEADER, with the
1645916cd2Sjpk  * fields enclosed by brackets "[]" replaced with your own identifying
1745916cd2Sjpk  * information: Portions Copyright [yyyy] [name of copyright owner]
1845916cd2Sjpk  *
1945916cd2Sjpk  * CDDL HEADER END
2045916cd2Sjpk  */
2145916cd2Sjpk /*
22*7b0bedd4SRic Aleshire  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
2345916cd2Sjpk  * Use is subject to license terms.
2445916cd2Sjpk  *
2545916cd2Sjpk  * From	"tsol_tndb_parser.c	7.24	01/09/05 SMI; TSOL 2.x"
2645916cd2Sjpk  *
2745916cd2Sjpk  * These functions parse entries in the "tnrhtp" (remote host template) file.
2845916cd2Sjpk  * Each entry in this file has two fields, separated by a colon.  The first
2945916cd2Sjpk  * field is the template name.  The second is a list of "key=value" attributes,
3045916cd2Sjpk  * separated by semicolons.
3145916cd2Sjpk  *
3245916cd2Sjpk  * In order to help preserve sanity, we do not allow more than one unescaped
3345916cd2Sjpk  * colon in a line, nor any unescaped '=' or ';' characters in the template
3445916cd2Sjpk  * name.  Such things are indicative of typing errors, not intentional
3545916cd2Sjpk  * configuration.
3645916cd2Sjpk  */
3745916cd2Sjpk 
3845916cd2Sjpk #include <stdio.h>
3945916cd2Sjpk #include <ctype.h>
4045916cd2Sjpk #include <stdlib.h>
4145916cd2Sjpk #include <stddef.h>
4245916cd2Sjpk #include <string.h>
4345916cd2Sjpk #include <strings.h>
4445916cd2Sjpk #include <libtsnet.h>
4545916cd2Sjpk #include <tsol/label.h>
46b9dac67bSrica #include <sys/tsol/label_macro.h>
4745916cd2Sjpk #include <sys/types.h>
4845916cd2Sjpk #include <nss.h>
4945916cd2Sjpk #include <secdb.h>
5045916cd2Sjpk #include <errno.h>
5145916cd2Sjpk 
5245916cd2Sjpk static int
get_tn_doi(tsol_tpent_t * tpentp,kva_t * kv)5345916cd2Sjpk get_tn_doi(tsol_tpent_t *tpentp, kva_t *kv)
5445916cd2Sjpk {
5545916cd2Sjpk 	char	*cp;
5645916cd2Sjpk 	char	*val = NULL;
5745916cd2Sjpk 
5845916cd2Sjpk 	val = kva_match(kv, TP_DOI);
5945916cd2Sjpk 	if (val == NULL)
6045916cd2Sjpk 		return (LTSNET_NO_DOI);
6145916cd2Sjpk 
6245916cd2Sjpk 	errno = 0;
6345916cd2Sjpk 	tpentp->tp_doi = strtol(val, &cp, 0);
6445916cd2Sjpk 	if (errno != 0)
6545916cd2Sjpk 		return (LTSNET_SYSERR);
6645916cd2Sjpk 	if (*cp != '\0')
6745916cd2Sjpk 		return (LTSNET_ILL_DOI);
6845916cd2Sjpk 
6945916cd2Sjpk 	return (0);
7045916cd2Sjpk }
7145916cd2Sjpk 
7245916cd2Sjpk static int
get_tn_sl_range(brange_t * range,char * min,char * max)7345916cd2Sjpk get_tn_sl_range(brange_t *range, char *min, char *max)
7445916cd2Sjpk {
75*7b0bedd4SRic Aleshire 	m_label_t	*slp;
7645916cd2Sjpk 
7745916cd2Sjpk 	if (min == NULL && max == NULL)
7845916cd2Sjpk 		return (LTSNET_NO_RANGE);
7945916cd2Sjpk 	if (min == NULL)
8045916cd2Sjpk 		return (LTSNET_NO_LOWERBOUND);
8145916cd2Sjpk 	if (max == NULL)
8245916cd2Sjpk 		return (LTSNET_NO_UPPERBOUND);
8345916cd2Sjpk 
84*7b0bedd4SRic Aleshire 	slp = &range->lower_bound;
85*7b0bedd4SRic Aleshire 	if (str_to_label(min, &slp, MAC_LABEL, L_NO_CORRECTION, NULL) != 0)
8645916cd2Sjpk 		return (LTSNET_ILL_LOWERBOUND);
87*7b0bedd4SRic Aleshire 	slp = &range->upper_bound;
88*7b0bedd4SRic Aleshire 	if (str_to_label(max, &slp, MAC_LABEL, L_NO_CORRECTION, NULL) != 0)
8945916cd2Sjpk 		return (LTSNET_ILL_UPPERBOUND);
9045916cd2Sjpk 	if (!bldominates(&range->upper_bound, &range->lower_bound))
9145916cd2Sjpk 		return (LTSNET_ILL_RANGE);
9245916cd2Sjpk 
9345916cd2Sjpk 	return (0);
9445916cd2Sjpk }
9545916cd2Sjpk 
9645916cd2Sjpk static int
get_tn_sl_set(blset_t * labelset,char * setstr)9745916cd2Sjpk get_tn_sl_set(blset_t *labelset, char *setstr)
9845916cd2Sjpk {
99*7b0bedd4SRic Aleshire 	int		sc;
10045916cd2Sjpk 	char		*tokp, *finally;
101*7b0bedd4SRic Aleshire 	m_label_t	*labels, *slp;
10245916cd2Sjpk 
10345916cd2Sjpk 	(void) memset(labelset, 0, sizeof (blset_t));
104*7b0bedd4SRic Aleshire 	labels = (m_label_t *)labelset;
10545916cd2Sjpk 	tokp = strtok_r(setstr, TNDB_COMMA, &finally);
10645916cd2Sjpk 	for (sc = 0; tokp != NULL && sc < NSLS_MAX; sc++) {
107*7b0bedd4SRic Aleshire 		slp = &labels[sc];
108*7b0bedd4SRic Aleshire 		if (str_to_label(tokp, &slp, MAC_LABEL, L_NO_CORRECTION,
109*7b0bedd4SRic Aleshire 		    NULL) != 0)
11045916cd2Sjpk 			return (LTSNET_ILL_LABEL);
11145916cd2Sjpk 		tokp = strtok_r(NULL, TNDB_COMMA, &finally);
11245916cd2Sjpk 	}
11345916cd2Sjpk 	if (tokp != NULL && sc >= NSLS_MAX)
11445916cd2Sjpk 		return (LTSNET_SET_TOO_BIG);
11545916cd2Sjpk 
11645916cd2Sjpk 	return (0);
11745916cd2Sjpk }
11845916cd2Sjpk 
11945916cd2Sjpk static int
parse_remainder(tsol_tpent_t * tpentp,kva_t * kv)12045916cd2Sjpk parse_remainder(tsol_tpent_t *tpentp, kva_t *kv)
12145916cd2Sjpk {
12245916cd2Sjpk 	int	err = 0;
12345916cd2Sjpk 	char	*val = NULL;
12445916cd2Sjpk 	char	*val2 = NULL;
12545916cd2Sjpk 
12645916cd2Sjpk 	val = kva_match(kv, TP_HOSTTYPE);
12745916cd2Sjpk 
12845916cd2Sjpk 	if (val == NULL)
12945916cd2Sjpk 		return (LTSNET_NO_HOSTTYPE);
13045916cd2Sjpk 	if (strcasecmp(val, TP_UNLABELED) == 0)
13145916cd2Sjpk 		tpentp->host_type = UNLABELED;
13245916cd2Sjpk 	else if (strcasecmp(val, TP_CIPSO) == 0)
13345916cd2Sjpk 		tpentp->host_type = SUN_CIPSO;
13445916cd2Sjpk 	else
13545916cd2Sjpk 		return (LTSNET_ILL_HOSTTYPE);
13645916cd2Sjpk 
13745916cd2Sjpk 	/*
13845916cd2Sjpk 	 * parse fields by host type -
13945916cd2Sjpk 	 * add on to the following if statement for each new host type.
14045916cd2Sjpk 	 */
14145916cd2Sjpk 	if (tpentp->host_type == UNLABELED) {
142*7b0bedd4SRic Aleshire 		m_label_t	*slp;
143*7b0bedd4SRic Aleshire 
14445916cd2Sjpk 		tpentp->tp_mask_unl = 0;
14545916cd2Sjpk 		/*
14645916cd2Sjpk 		 * doi
14745916cd2Sjpk 		 */
14845916cd2Sjpk 		if ((err = get_tn_doi(tpentp, kv)) != 0)
14945916cd2Sjpk 			return (err);
15045916cd2Sjpk 		tpentp->tp_mask_unl |= TSOL_MSK_CIPSO_DOI;
15145916cd2Sjpk 		/*
15245916cd2Sjpk 		 * default label
15345916cd2Sjpk 		 */
15445916cd2Sjpk 		val = kva_match(kv, TP_DEFLABEL);
15545916cd2Sjpk 		if (val == NULL)
15645916cd2Sjpk 			return (LTSNET_NO_LABEL);
157*7b0bedd4SRic Aleshire 		slp = &tpentp->tp_def_label;
158*7b0bedd4SRic Aleshire 		if (str_to_label(val, &slp, MAC_LABEL, L_NO_CORRECTION,
159*7b0bedd4SRic Aleshire 		    NULL) != 0)
16045916cd2Sjpk 			return (LTSNET_ILL_LABEL);
16145916cd2Sjpk 		tpentp->tp_mask_unl |= TSOL_MSK_DEF_LABEL;
16245916cd2Sjpk 		/*
16345916cd2Sjpk 		 * check label range
16445916cd2Sjpk 		 */
16545916cd2Sjpk 		val = kva_match(kv, TP_MINLABEL);
16645916cd2Sjpk 		val2 = kva_match(kv, TP_MAXLABEL);
16745916cd2Sjpk 		if (val == NULL && val2 == NULL) {
168*7b0bedd4SRic Aleshire 			m_label_t	*llow = NULL;
16945916cd2Sjpk 			/*
17045916cd2Sjpk 			 * This is the old format.  Use ADMIN_LOW to SL of the
17145916cd2Sjpk 			 * default label as the gw_sl_range.
17245916cd2Sjpk 			 */
173*7b0bedd4SRic Aleshire 			if (str_to_label(ADMIN_LOW, &llow, MAC_LABEL,
174*7b0bedd4SRic Aleshire 			    L_NO_CORRECTION, NULL) == -1)
175*7b0bedd4SRic Aleshire 				return (LTSNET_ILL_LABEL);
176*7b0bedd4SRic Aleshire 			tpentp->tp_gw_sl_range.lower_bound = *llow;
177*7b0bedd4SRic Aleshire 			m_label_free(llow);
17845916cd2Sjpk 			tpentp->tp_gw_sl_range.upper_bound =
17945916cd2Sjpk 			    tpentp->tp_def_label;
18045916cd2Sjpk 		} else {
18145916cd2Sjpk 			err = get_tn_sl_range(&tpentp->tp_gw_sl_range, val,
18245916cd2Sjpk 			    val2);
18345916cd2Sjpk 			if (err != 0)
18445916cd2Sjpk 				return (err);
18545916cd2Sjpk 		}
18645916cd2Sjpk 		tpentp->tp_mask_unl |= TSOL_MSK_SL_RANGE_TSOL;
18745916cd2Sjpk 
18845916cd2Sjpk 		/*
18945916cd2Sjpk 		 * also label set, if present.  (optional)
19045916cd2Sjpk 		 */
19145916cd2Sjpk 		val = kva_match(kv, TP_SET);
19245916cd2Sjpk 		if (val != NULL) {
19345916cd2Sjpk 			err = get_tn_sl_set(&tpentp->tp_gw_sl_set, val);
19445916cd2Sjpk 			if (err != 0)
19545916cd2Sjpk 				return (err);
19645916cd2Sjpk 			tpentp->tp_mask_cipso |= TSOL_MSK_SL_RANGE_TSOL;
19745916cd2Sjpk 		}
19845916cd2Sjpk 	} else {
19945916cd2Sjpk 		tpentp->tp_mask_cipso = 0;
20045916cd2Sjpk 		/*
20145916cd2Sjpk 		 * doi
20245916cd2Sjpk 		 */
20345916cd2Sjpk 		if ((err = get_tn_doi(tpentp, kv)) != 0)
20445916cd2Sjpk 			return (err);
20545916cd2Sjpk 		tpentp->tp_mask_cipso |= TSOL_MSK_CIPSO_DOI;
20645916cd2Sjpk 		/*
20745916cd2Sjpk 		 * label range
20845916cd2Sjpk 		 */
20945916cd2Sjpk 		val = kva_match(kv, TP_MINLABEL);
21045916cd2Sjpk 		val2 = kva_match(kv, TP_MAXLABEL);
21145916cd2Sjpk 		err = get_tn_sl_range(&tpentp->tp_sl_range_cipso, val, val2);
21245916cd2Sjpk 		if (err != 0)
21345916cd2Sjpk 			return (err);
21445916cd2Sjpk 		tpentp->tp_mask_cipso |= TSOL_MSK_SL_RANGE_TSOL;
21545916cd2Sjpk 		/*
21645916cd2Sjpk 		 * also label set, if present.  (optional)
21745916cd2Sjpk 		 */
21845916cd2Sjpk 		val = kva_match(kv, TP_SET);
21945916cd2Sjpk 		if (val != NULL) {
22045916cd2Sjpk 			err = get_tn_sl_set(&tpentp->tp_sl_set_cipso, val);
22145916cd2Sjpk 			if (err != 0)
22245916cd2Sjpk 				return (err);
22345916cd2Sjpk 			tpentp->tp_mask_cipso |= TSOL_MSK_SL_RANGE_TSOL;
22445916cd2Sjpk 		}
22545916cd2Sjpk 
22645916cd2Sjpk 		/* CIPSO entries don't support default labels */
22745916cd2Sjpk 		val = kva_match(kv, TP_DEFLABEL);
22845916cd2Sjpk 		if (val != NULL)
22945916cd2Sjpk 			return (LTSNET_BAD_TYPE);
23045916cd2Sjpk 	}
23145916cd2Sjpk 
23245916cd2Sjpk 	return (0);
23345916cd2Sjpk }
23445916cd2Sjpk 
23545916cd2Sjpk tsol_tpent_t *
tpstr_to_ent(tsol_tpstr_t * tpstrp,int * errp,char ** errstrp)23645916cd2Sjpk tpstr_to_ent(tsol_tpstr_t *tpstrp, int *errp, char **errstrp)
23745916cd2Sjpk {
23845916cd2Sjpk 	int		err = 0;
23945916cd2Sjpk 	char		*errstr;
24045916cd2Sjpk 	char		*template = tpstrp->template;
24145916cd2Sjpk 	char		*attrs = tpstrp->attrs;
24245916cd2Sjpk 	kva_t		*kv;
24345916cd2Sjpk 	tsol_tpent_t	*tpentp = NULL;
24445916cd2Sjpk 
24545916cd2Sjpk 	/*
24645916cd2Sjpk 	 * The user can specify NULL pointers for these.  Make sure that we
24745916cd2Sjpk 	 * don't have to deal with checking for NULL everywhere by just
24845916cd2Sjpk 	 * pointing to our own variables if the user gives NULL.
24945916cd2Sjpk 	 */
25045916cd2Sjpk 	if (errp == NULL)
25145916cd2Sjpk 		errp = &err;
25245916cd2Sjpk 	if (errstrp == NULL)
25345916cd2Sjpk 		errstrp = &errstr;
25445916cd2Sjpk 	/* The default, unless we find a more specific error locus. */
25545916cd2Sjpk 	*errstrp = template;
25645916cd2Sjpk 
25745916cd2Sjpk 	if (template == NULL || *template == '#' || *template == '\n') {
25845916cd2Sjpk 		*errp = LTSNET_EMPTY;
25945916cd2Sjpk 		if (attrs && *attrs != '\0' && *attrs != '#' && *attrs != '\n')
26045916cd2Sjpk 			*errstrp = attrs;
26145916cd2Sjpk 		else if (template == NULL)
26245916cd2Sjpk 			*errstrp = "   ";
26345916cd2Sjpk 		goto err_ret;
26445916cd2Sjpk 	}
26545916cd2Sjpk 	if (*template == '\0') {
26645916cd2Sjpk 		*errp = LTSNET_NO_NAME;
26745916cd2Sjpk 		if (attrs && *attrs != '\0' && *attrs != '#' && *attrs != '\n')
268*7b0bedd4SRic Aleshire 			*errstrp = attrs;
26945916cd2Sjpk 		goto err_ret;
27045916cd2Sjpk 	}
27145916cd2Sjpk 	if (attrs == NULL || *attrs == '\0' || *attrs == '#' ||
27245916cd2Sjpk 	    *attrs == '\n') {
27345916cd2Sjpk 		*errp = LTSNET_NO_ATTRS;
27445916cd2Sjpk 		goto err_ret;
27545916cd2Sjpk 	}
27645916cd2Sjpk 	if ((tpentp = calloc(1, sizeof (*tpentp))) == NULL) {
27745916cd2Sjpk 		*errp = LTSNET_SYSERR;
27845916cd2Sjpk 		return (NULL);
27945916cd2Sjpk 	}
2801f041b17Ston 	if ((strlcpy(tpentp->name, template, sizeof (tpentp->name)) >=
2811f041b17Ston 	    sizeof (tpentp->name)) ||
2821f041b17Ston 	    strpbrk(tpentp->name, TN_RESERVED) != NULL) {
2834b484e00Ston 		*errp = LTSNET_ILL_NAME;
28445916cd2Sjpk 		goto err_ret;
2854b484e00Ston 	}
28645916cd2Sjpk 	kv = _str2kva(attrs, KV_ASSIGN, KV_DELIMITER);
28745916cd2Sjpk 	*errp = parse_remainder(tpentp, kv);
28845916cd2Sjpk 	_kva_free(kv);
28945916cd2Sjpk 	if (*errp == 0) {
29045916cd2Sjpk #ifdef	DEBUG
29145916cd2Sjpk 		(void) fprintf(stdout, "tpstr_to_ent: %s:%s\n", tpentp->name,
29245916cd2Sjpk 		    attrs);
29345916cd2Sjpk #endif	/* DEBUG */
29445916cd2Sjpk 
29545916cd2Sjpk 		return (tpentp);
29645916cd2Sjpk 	}
29745916cd2Sjpk 
29845916cd2Sjpk err_ret:
29945916cd2Sjpk 	err = errno;
30045916cd2Sjpk 	tsol_freetpent(tpentp);
30145916cd2Sjpk 	errno = err;
30245916cd2Sjpk #ifdef	DEBUG
30345916cd2Sjpk 	(void) fprintf(stderr, "\ntpstr_to_ent: %s:%s\n",
30445916cd2Sjpk 	    *errstrp, (char *)tsol_strerror(*errp, errno));
30545916cd2Sjpk #endif	/* DEBUG */
30645916cd2Sjpk 
30745916cd2Sjpk 	return (NULL);
30845916cd2Sjpk }
30945916cd2Sjpk 
31045916cd2Sjpk void
tsol_freetpent(tsol_tpent_t * tp)31145916cd2Sjpk tsol_freetpent(tsol_tpent_t *tp)
31245916cd2Sjpk {
31345916cd2Sjpk 	if (tp != NULL)
31445916cd2Sjpk 		free(tp);
31545916cd2Sjpk }
316