Home | History | Annotate | Download | only in common
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  *
     25  * From	"tsol_tndb_parser.c	7.24	01/09/05 SMI; TSOL 2.x"
     26  *
     27  * These functions parse entries in the "tnzonecfg" (zone configuration) file.
     28  * Each entry in this file has five fields, separated by a colon.  These fields
     29  * are:
     30  *
     31  *	zone name : label : flags : zone-specific MLPs : global MLPs
     32  *
     33  * The fourth and fifth fields contain subfields consisting of MLP entries
     34  * separated by semicolons.  The MLP entries are of the form:
     35  *
     36  *	port[-port]/protocol
     37  *
     38  * In order to help preserve sanity, we do not allow more than four unescaped
     39  * colons in a line, nor any unescaped ';' characters in the non-MLP fields.
     40  * Such things are indicative of typing errors, not intentional configuration.
     41  */
     42 
     43 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     44 
     45 #include <ctype.h>
     46 #include <stdlib.h>
     47 #include <stddef.h>
     48 #include <string.h>
     49 #include <strings.h>
     50 #include <libtsnet.h>
     51 #include <tsol/label.h>
     52 #include <sys/types.h>
     53 #include <sys/socket.h>
     54 #include <netinet/in.h>
     55 #include <nss.h>
     56 #include <errno.h>
     57 #include <secdb.h>
     58 
     59 /*
     60  * Parse an MLP specification in port1-port2/proto or port/proto form.
     61  */
     62 static int
     63 str_to_mlp(char *mlp_str, tsol_mlp_t *zone_mlp)
     64 {
     65 	char *fieldp;
     66 	char *lasts, *cp;
     67 	int i;
     68 	ulong_t ulv;
     69 	struct protoent proto;
     70 	char gbuf[1024];
     71 
     72 	(void) memset(zone_mlp, 0, sizeof (tsol_mlp_t));
     73 
     74 	fieldp = strtok_r(mlp_str, KV_DELIMITER, &lasts);
     75 	if (fieldp == NULL)
     76 		return (-1);
     77 
     78 	errno = 0;
     79 	for (i = 0; fieldp != NULL && i < NMLP_MAX; i++) {
     80 		ulv = strtoul(fieldp, &cp, 0);
     81 		zone_mlp[i].mlp_port = (uint16_t)ulv;
     82 		zone_mlp[i].mlp_port_upper = 0;
     83 		if (errno != 0 || ulv > 65535)
     84 			return (-1);
     85 		if (*cp == '-') {
     86 			ulv = strtol(cp + 1, &cp, 0);
     87 			zone_mlp[i].mlp_port_upper = (uint16_t)ulv;
     88 			if (errno != 0 || ulv > 65535)
     89 				return (-1);
     90 		}
     91 		if (*cp != '/')
     92 			return (-1);
     93 		fieldp = cp + 1;
     94 		ulv = strtol(fieldp, &cp, 0);
     95 		if (errno == 0 && ulv <= 255 && *cp == '\0')
     96 			zone_mlp->mlp_ipp = (uint8_t)ulv;
     97 		else if (getprotobyname_r(fieldp, &proto, gbuf,
     98 		    sizeof (gbuf)) != NULL)
     99 			zone_mlp->mlp_ipp = proto.p_proto;
    100 		else
    101 			return (-1);
    102 		fieldp = strtok_r(NULL, KV_DELIMITER, &lasts);
    103 	}
    104 	return (0);
    105 }
    106 
    107 static boolean_t
    108 parse_mlp_list(tsol_mlp_t **list, char *str, int *errp, char **errstrp)
    109 {
    110 	int mmax;
    111 	tsol_mlp_t *mlp;
    112 	char *tokp, *finally;
    113 	int mc;
    114 
    115 	mmax = 0;
    116 	if ((mlp = *list) != NULL) {
    117 		while (!TSOL_MLP_END(mlp)) {
    118 			mmax++;
    119 			mlp++;
    120 		}
    121 		mmax++;
    122 	}
    123 	mlp = *list;
    124 	tokp = strtok_r(str, KV_DELIMITER, &finally);
    125 	for (mc = 0; tokp != NULL; mc++) {
    126 		if (mc >= mmax) {
    127 			mmax += 8;
    128 			mlp = realloc(mlp, mmax * sizeof (*mlp));
    129 			if (mlp == NULL) {
    130 				*errp = LTSNET_SYSERR;
    131 				*errstrp = tokp;
    132 				return (B_FALSE);
    133 			}
    134 			*list = mlp;
    135 		}
    136 		if (str_to_mlp(tokp, mlp + mc) == -1) {
    137 			*errp = LTSNET_ILL_MLP;
    138 			*errstrp = tokp;
    139 			return (B_FALSE);
    140 		}
    141 		tokp = strtok_r(NULL, KV_DELIMITER, &finally);
    142 	}
    143 	if (mc >= mmax) {
    144 		mlp = realloc(mlp, (mmax + 1) * sizeof (*mlp));
    145 		if (mlp == NULL) {
    146 			*errp = LTSNET_SYSERR;
    147 			*errstrp = finally;
    148 			return (B_FALSE);
    149 		}
    150 		*list = mlp;
    151 	}
    152 	(void) memset(mlp + mc, 0, sizeof (*mlp));
    153 	return (B_TRUE);
    154 }
    155 
    156 tsol_zcent_t *
    157 tsol_sgetzcent(const char *instr, int *errp, char **errstrp)
    158 {
    159 	int err;
    160 	char *errstr;
    161 	tsol_zcent_t *zc;
    162 	const char *nextf;
    163 	char *cp;
    164 	char fieldbuf[1024];
    165 
    166 	/*
    167 	 * The user can specify NULL pointers for these.  Make sure that we
    168 	 * don't have to deal with checking for NULL everywhere by just
    169 	 * pointing to our own variables if the user gives NULL.
    170 	 */
    171 	if (errp == NULL)
    172 		errp = &err;
    173 	if (errstrp == NULL)
    174 		errstrp = &errstr;
    175 
    176 	/* The default, unless we find a more specific error locus. */
    177 	*errstrp = (char *)instr;
    178 
    179 	if ((zc = calloc(1, sizeof (*zc))) == NULL) {
    180 		*errp = LTSNET_SYSERR;
    181 		return (NULL);
    182 	}
    183 
    184 	/* First, parse off the zone name. */
    185 	instr = parse_entry(zc->zc_name, sizeof (zc->zc_name), instr, "#;:\n");
    186 	if (zc->zc_name[0] == '\0') {
    187 		*errstrp = (char *)instr;
    188 		if (*instr == '\0' || *instr == '#' || *instr == '\n')
    189 			*errp = LTSNET_EMPTY;
    190 		else if (*instr == ':')
    191 			*errp = LTSNET_NO_NAME;
    192 		else
    193 			*errp = LTSNET_ILL_NAME;
    194 		goto err_ret;
    195 	}
    196 	if (*instr != ':') {
    197 		*errstrp = (char *)instr;
    198 		if (*instr == '=' || *instr == ';')
    199 			*errp = LTSNET_ILL_NAME;
    200 		else
    201 			*errp = LTSNET_ILL_ENTRY;
    202 		goto err_ret;
    203 	}
    204 	instr++;
    205 
    206 	/* Field two: parse off the label. */
    207 	nextf = parse_entry(fieldbuf, sizeof (fieldbuf), instr, "#;:\n");
    208 	if (*nextf != ':') {
    209 		*errstrp = (char *)nextf;
    210 		*errp = LTSNET_ILL_ENTRY;
    211 		goto err_ret;
    212 	}
    213 	if (fieldbuf[0] == '\0') {
    214 		*errstrp = (char *)instr;
    215 		*errp = LTSNET_NO_LABEL;
    216 		goto err_ret;
    217 	}
    218 	if (stobsl(fieldbuf, &zc->zc_label, NO_CORRECTION, &err) == 0) {
    219 		*errstrp = (char *)instr;
    220 		*errp = LTSNET_ILL_LABEL;
    221 		goto err_ret;
    222 	}
    223 	instr = nextf + 1;
    224 
    225 	/* The kernel will apply the system doi to the zone label later */
    226 	zc->zc_doi = 0;
    227 
    228 	/* Field three: get match flag */
    229 	errno = 0;
    230 	zc->zc_match = (uchar_t)strtol(instr, &cp, 0);
    231 	if (errno != 0 || (*cp != ':' && *cp != '\0')) {
    232 		*errp = LTSNET_ILL_FLAG;
    233 		*errstrp = (char *)instr;
    234 		goto err_ret;
    235 	}
    236 	if (*cp != ':') {
    237 		*errp = LTSNET_ILL_VALDELIM;
    238 		*errstrp = cp;
    239 		goto err_ret;
    240 	}
    241 	instr = cp + 1;
    242 
    243 	/* Field four: get zone-specific MLP list. */
    244 	nextf = parse_entry(fieldbuf, sizeof (fieldbuf), instr, "#:\n");
    245 	if (*nextf != ':') {
    246 		*errstrp = (char *)nextf;
    247 		*errp = LTSNET_ILL_ENTRY;
    248 		goto err_ret;
    249 	}
    250 	if (!parse_mlp_list(&zc->zc_private_mlp, fieldbuf, errp, errstrp)) {
    251 		*errstrp = (char *)instr + (*errstrp - fieldbuf);
    252 		goto err_ret;
    253 	}
    254 	instr = nextf + 1;
    255 
    256 	/* Field five: get global MLP list. */
    257 	nextf = parse_entry(fieldbuf, sizeof (fieldbuf), instr, "#:\n");
    258 	if (*nextf != '\0' && *nextf != '#' && !isspace(*nextf)) {
    259 		*errstrp = (char *)nextf;
    260 		*errp = LTSNET_ILL_ENTRY;
    261 		goto err_ret;
    262 	}
    263 	if (!parse_mlp_list(&zc->zc_shared_mlp, fieldbuf, errp, errstrp)) {
    264 		*errstrp = (char *)instr + (*errstrp - fieldbuf);
    265 		goto err_ret;
    266 	}
    267 
    268 	return (zc);
    269 
    270 err_ret:
    271 	err = errno;
    272 	tsol_freezcent(zc);
    273 	errno = err;
    274 	return (NULL);
    275 }
    276 
    277 void
    278 tsol_freezcent(tsol_zcent_t *zc)
    279 {
    280 	if (zc != NULL) {
    281 		free(zc->zc_private_mlp);
    282 		free(zc->zc_shared_mlp);
    283 		free(zc);
    284 	}
    285 }
    286