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 "tnzonecfg" (zone configuration) file. 2845916cd2Sjpk * Each entry in this file has five fields, separated by a colon. These fields 2945916cd2Sjpk * are: 3045916cd2Sjpk * 3145916cd2Sjpk * zone name : label : flags : zone-specific MLPs : global MLPs 3245916cd2Sjpk * 3345916cd2Sjpk * The fourth and fifth fields contain subfields consisting of MLP entries 3445916cd2Sjpk * separated by semicolons. The MLP entries are of the form: 3545916cd2Sjpk * 3645916cd2Sjpk * port[-port]/protocol 3745916cd2Sjpk * 3845916cd2Sjpk * In order to help preserve sanity, we do not allow more than four unescaped 3945916cd2Sjpk * colons in a line, nor any unescaped ';' characters in the non-MLP fields. 4045916cd2Sjpk * Such things are indicative of typing errors, not intentional configuration. 4145916cd2Sjpk */ 4245916cd2Sjpk 4345916cd2Sjpk #include <ctype.h> 4445916cd2Sjpk #include <stdlib.h> 4545916cd2Sjpk #include <stddef.h> 4645916cd2Sjpk #include <string.h> 4745916cd2Sjpk #include <strings.h> 4845916cd2Sjpk #include <libtsnet.h> 4945916cd2Sjpk #include <tsol/label.h> 5045916cd2Sjpk #include <sys/types.h> 5145916cd2Sjpk #include <sys/socket.h> 5245916cd2Sjpk #include <netinet/in.h> 5345916cd2Sjpk #include <nss.h> 5445916cd2Sjpk #include <errno.h> 5545916cd2Sjpk #include <secdb.h> 5645916cd2Sjpk 5745916cd2Sjpk /* 5845916cd2Sjpk * Parse an MLP specification in port1-port2/proto or port/proto form. 5945916cd2Sjpk */ 6045916cd2Sjpk static int 6145916cd2Sjpk str_to_mlp(char *mlp_str, tsol_mlp_t *zone_mlp) 6245916cd2Sjpk { 6345916cd2Sjpk char *fieldp; 6445916cd2Sjpk char *lasts, *cp; 6545916cd2Sjpk int i; 6645916cd2Sjpk ulong_t ulv; 6745916cd2Sjpk struct protoent proto; 6845916cd2Sjpk char gbuf[1024]; 6945916cd2Sjpk 7045916cd2Sjpk (void) memset(zone_mlp, 0, sizeof (tsol_mlp_t)); 7145916cd2Sjpk 7245916cd2Sjpk fieldp = strtok_r(mlp_str, KV_DELIMITER, &lasts); 7345916cd2Sjpk if (fieldp == NULL) 7445916cd2Sjpk return (-1); 7545916cd2Sjpk 7645916cd2Sjpk errno = 0; 7745916cd2Sjpk for (i = 0; fieldp != NULL && i < NMLP_MAX; i++) { 7845916cd2Sjpk ulv = strtoul(fieldp, &cp, 0); 7945916cd2Sjpk zone_mlp[i].mlp_port = (uint16_t)ulv; 8045916cd2Sjpk zone_mlp[i].mlp_port_upper = 0; 8145916cd2Sjpk if (errno != 0 || ulv > 65535) 8245916cd2Sjpk return (-1); 8345916cd2Sjpk if (*cp == '-') { 8445916cd2Sjpk ulv = strtol(cp + 1, &cp, 0); 8545916cd2Sjpk zone_mlp[i].mlp_port_upper = (uint16_t)ulv; 8645916cd2Sjpk if (errno != 0 || ulv > 65535) 8745916cd2Sjpk return (-1); 8845916cd2Sjpk } 8945916cd2Sjpk if (*cp != '/') 9045916cd2Sjpk return (-1); 9145916cd2Sjpk fieldp = cp + 1; 9245916cd2Sjpk ulv = strtol(fieldp, &cp, 0); 9345916cd2Sjpk if (errno == 0 && ulv <= 255 && *cp == '\0') 9445916cd2Sjpk zone_mlp->mlp_ipp = (uint8_t)ulv; 9545916cd2Sjpk else if (getprotobyname_r(fieldp, &proto, gbuf, 9645916cd2Sjpk sizeof (gbuf)) != NULL) 9745916cd2Sjpk zone_mlp->mlp_ipp = proto.p_proto; 9845916cd2Sjpk else 9945916cd2Sjpk return (-1); 10045916cd2Sjpk fieldp = strtok_r(NULL, KV_DELIMITER, &lasts); 10145916cd2Sjpk } 10245916cd2Sjpk return (0); 10345916cd2Sjpk } 10445916cd2Sjpk 10545916cd2Sjpk static boolean_t 10645916cd2Sjpk parse_mlp_list(tsol_mlp_t **list, char *str, int *errp, char **errstrp) 10745916cd2Sjpk { 10845916cd2Sjpk int mmax; 10945916cd2Sjpk tsol_mlp_t *mlp; 11045916cd2Sjpk char *tokp, *finally; 11145916cd2Sjpk int mc; 11245916cd2Sjpk 11345916cd2Sjpk mmax = 0; 11445916cd2Sjpk if ((mlp = *list) != NULL) { 11545916cd2Sjpk while (!TSOL_MLP_END(mlp)) { 11645916cd2Sjpk mmax++; 11745916cd2Sjpk mlp++; 11845916cd2Sjpk } 11945916cd2Sjpk mmax++; 12045916cd2Sjpk } 12145916cd2Sjpk mlp = *list; 12245916cd2Sjpk tokp = strtok_r(str, KV_DELIMITER, &finally); 12345916cd2Sjpk for (mc = 0; tokp != NULL; mc++) { 12445916cd2Sjpk if (mc >= mmax) { 12545916cd2Sjpk mmax += 8; 12645916cd2Sjpk mlp = realloc(mlp, mmax * sizeof (*mlp)); 12745916cd2Sjpk if (mlp == NULL) { 12845916cd2Sjpk *errp = LTSNET_SYSERR; 12945916cd2Sjpk *errstrp = tokp; 13045916cd2Sjpk return (B_FALSE); 13145916cd2Sjpk } 13245916cd2Sjpk *list = mlp; 13345916cd2Sjpk } 13445916cd2Sjpk if (str_to_mlp(tokp, mlp + mc) == -1) { 13545916cd2Sjpk *errp = LTSNET_ILL_MLP; 13645916cd2Sjpk *errstrp = tokp; 13745916cd2Sjpk return (B_FALSE); 13845916cd2Sjpk } 13945916cd2Sjpk tokp = strtok_r(NULL, KV_DELIMITER, &finally); 14045916cd2Sjpk } 14145916cd2Sjpk if (mc >= mmax) { 14245916cd2Sjpk mlp = realloc(mlp, (mmax + 1) * sizeof (*mlp)); 14345916cd2Sjpk if (mlp == NULL) { 14445916cd2Sjpk *errp = LTSNET_SYSERR; 14545916cd2Sjpk *errstrp = finally; 14645916cd2Sjpk return (B_FALSE); 14745916cd2Sjpk } 14845916cd2Sjpk *list = mlp; 14945916cd2Sjpk } 15045916cd2Sjpk (void) memset(mlp + mc, 0, sizeof (*mlp)); 15145916cd2Sjpk return (B_TRUE); 15245916cd2Sjpk } 15345916cd2Sjpk 15445916cd2Sjpk tsol_zcent_t * 15545916cd2Sjpk tsol_sgetzcent(const char *instr, int *errp, char **errstrp) 15645916cd2Sjpk { 15745916cd2Sjpk int err; 158*7b0bedd4SRic Aleshire m_label_t *slp; 15945916cd2Sjpk char *errstr; 16045916cd2Sjpk tsol_zcent_t *zc; 16145916cd2Sjpk const char *nextf; 16245916cd2Sjpk char *cp; 16345916cd2Sjpk char fieldbuf[1024]; 16445916cd2Sjpk 16545916cd2Sjpk /* 16645916cd2Sjpk * The user can specify NULL pointers for these. Make sure that we 16745916cd2Sjpk * don't have to deal with checking for NULL everywhere by just 16845916cd2Sjpk * pointing to our own variables if the user gives NULL. 16945916cd2Sjpk */ 17045916cd2Sjpk if (errp == NULL) 17145916cd2Sjpk errp = &err; 17245916cd2Sjpk if (errstrp == NULL) 17345916cd2Sjpk errstrp = &errstr; 17445916cd2Sjpk 17545916cd2Sjpk /* The default, unless we find a more specific error locus. */ 17645916cd2Sjpk *errstrp = (char *)instr; 17745916cd2Sjpk 17845916cd2Sjpk if ((zc = calloc(1, sizeof (*zc))) == NULL) { 17945916cd2Sjpk *errp = LTSNET_SYSERR; 18045916cd2Sjpk return (NULL); 18145916cd2Sjpk } 18245916cd2Sjpk 18345916cd2Sjpk /* First, parse off the zone name. */ 18445916cd2Sjpk instr = parse_entry(zc->zc_name, sizeof (zc->zc_name), instr, "#;:\n"); 18545916cd2Sjpk if (zc->zc_name[0] == '\0') { 18645916cd2Sjpk *errstrp = (char *)instr; 18745916cd2Sjpk if (*instr == '\0' || *instr == '#' || *instr == '\n') 18845916cd2Sjpk *errp = LTSNET_EMPTY; 18945916cd2Sjpk else if (*instr == ':') 19045916cd2Sjpk *errp = LTSNET_NO_NAME; 19145916cd2Sjpk else 19245916cd2Sjpk *errp = LTSNET_ILL_NAME; 19345916cd2Sjpk goto err_ret; 19445916cd2Sjpk } 19545916cd2Sjpk if (*instr != ':') { 19645916cd2Sjpk *errstrp = (char *)instr; 19745916cd2Sjpk if (*instr == '=' || *instr == ';') 19845916cd2Sjpk *errp = LTSNET_ILL_NAME; 19945916cd2Sjpk else 20045916cd2Sjpk *errp = LTSNET_ILL_ENTRY; 20145916cd2Sjpk goto err_ret; 20245916cd2Sjpk } 20345916cd2Sjpk instr++; 20445916cd2Sjpk 20545916cd2Sjpk /* Field two: parse off the label. */ 20645916cd2Sjpk nextf = parse_entry(fieldbuf, sizeof (fieldbuf), instr, "#;:\n"); 20745916cd2Sjpk if (*nextf != ':') { 20845916cd2Sjpk *errstrp = (char *)nextf; 20945916cd2Sjpk *errp = LTSNET_ILL_ENTRY; 21045916cd2Sjpk goto err_ret; 21145916cd2Sjpk } 21245916cd2Sjpk if (fieldbuf[0] == '\0') { 21345916cd2Sjpk *errstrp = (char *)instr; 21445916cd2Sjpk *errp = LTSNET_NO_LABEL; 21545916cd2Sjpk goto err_ret; 21645916cd2Sjpk } 217*7b0bedd4SRic Aleshire 218*7b0bedd4SRic Aleshire slp = &zc->zc_label; 219*7b0bedd4SRic Aleshire if (str_to_label(fieldbuf, &slp, MAC_LABEL, L_NO_CORRECTION, NULL) 220*7b0bedd4SRic Aleshire != 0) { 22145916cd2Sjpk *errstrp = (char *)instr; 22245916cd2Sjpk *errp = LTSNET_ILL_LABEL; 22345916cd2Sjpk goto err_ret; 22445916cd2Sjpk } 22545916cd2Sjpk instr = nextf + 1; 22645916cd2Sjpk 2277e6639c2Skp158701 /* The kernel will apply the system doi to the zone label later */ 2287e6639c2Skp158701 zc->zc_doi = 0; 22945916cd2Sjpk 23045916cd2Sjpk /* Field three: get match flag */ 23145916cd2Sjpk errno = 0; 23245916cd2Sjpk zc->zc_match = (uchar_t)strtol(instr, &cp, 0); 23345916cd2Sjpk if (errno != 0 || (*cp != ':' && *cp != '\0')) { 23445916cd2Sjpk *errp = LTSNET_ILL_FLAG; 23545916cd2Sjpk *errstrp = (char *)instr; 23645916cd2Sjpk goto err_ret; 23745916cd2Sjpk } 23845916cd2Sjpk if (*cp != ':') { 23945916cd2Sjpk *errp = LTSNET_ILL_VALDELIM; 24045916cd2Sjpk *errstrp = cp; 24145916cd2Sjpk goto err_ret; 24245916cd2Sjpk } 24345916cd2Sjpk instr = cp + 1; 24445916cd2Sjpk 24545916cd2Sjpk /* Field four: get zone-specific MLP list. */ 24645916cd2Sjpk nextf = parse_entry(fieldbuf, sizeof (fieldbuf), instr, "#:\n"); 24745916cd2Sjpk if (*nextf != ':') { 24845916cd2Sjpk *errstrp = (char *)nextf; 24945916cd2Sjpk *errp = LTSNET_ILL_ENTRY; 25045916cd2Sjpk goto err_ret; 25145916cd2Sjpk } 25245916cd2Sjpk if (!parse_mlp_list(&zc->zc_private_mlp, fieldbuf, errp, errstrp)) { 25345916cd2Sjpk *errstrp = (char *)instr + (*errstrp - fieldbuf); 25445916cd2Sjpk goto err_ret; 25545916cd2Sjpk } 25645916cd2Sjpk instr = nextf + 1; 25745916cd2Sjpk 25845916cd2Sjpk /* Field five: get global MLP list. */ 25945916cd2Sjpk nextf = parse_entry(fieldbuf, sizeof (fieldbuf), instr, "#:\n"); 26045916cd2Sjpk if (*nextf != '\0' && *nextf != '#' && !isspace(*nextf)) { 26145916cd2Sjpk *errstrp = (char *)nextf; 26245916cd2Sjpk *errp = LTSNET_ILL_ENTRY; 26345916cd2Sjpk goto err_ret; 26445916cd2Sjpk } 26545916cd2Sjpk if (!parse_mlp_list(&zc->zc_shared_mlp, fieldbuf, errp, errstrp)) { 26645916cd2Sjpk *errstrp = (char *)instr + (*errstrp - fieldbuf); 26745916cd2Sjpk goto err_ret; 26845916cd2Sjpk } 26945916cd2Sjpk 27045916cd2Sjpk return (zc); 27145916cd2Sjpk 27245916cd2Sjpk err_ret: 27345916cd2Sjpk err = errno; 27445916cd2Sjpk tsol_freezcent(zc); 27545916cd2Sjpk errno = err; 27645916cd2Sjpk return (NULL); 27745916cd2Sjpk } 27845916cd2Sjpk 27945916cd2Sjpk void 28045916cd2Sjpk tsol_freezcent(tsol_zcent_t *zc) 28145916cd2Sjpk { 28245916cd2Sjpk if (zc != NULL) { 28345916cd2Sjpk free(zc->zc_private_mlp); 28445916cd2Sjpk free(zc->zc_shared_mlp); 28545916cd2Sjpk free(zc); 28645916cd2Sjpk } 28745916cd2Sjpk } 288