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