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 2006 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 "tnrhtp" (remote host template) file. 28 * Each entry in this file has two fields, separated by a colon. The first 29 * field is the template name. The second is a list of "key=value" attributes, 30 * separated by semicolons. 31 * 32 * In order to help preserve sanity, we do not allow more than one unescaped 33 * colon in a line, nor any unescaped '=' or ';' characters in the template 34 * name. Such things are indicative of typing errors, not intentional 35 * configuration. 36 */ 37 38 #pragma ident "%Z%%M% %I% %E% SMI" 39 40 #include <stdio.h> 41 #include <ctype.h> 42 #include <stdlib.h> 43 #include <stddef.h> 44 #include <string.h> 45 #include <strings.h> 46 #include <libtsnet.h> 47 #include <tsol/label.h> 48 #include <sys/types.h> 49 #include <nss.h> 50 #include <secdb.h> 51 #include <errno.h> 52 53 static int 54 get_tn_doi(tsol_tpent_t *tpentp, kva_t *kv) 55 { 56 char *cp; 57 char *val = NULL; 58 59 val = kva_match(kv, TP_DOI); 60 if (val == NULL) 61 return (LTSNET_NO_DOI); 62 63 errno = 0; 64 tpentp->tp_doi = strtol(val, &cp, 0); 65 if (errno != 0) 66 return (LTSNET_SYSERR); 67 if (*cp != '\0') 68 return (LTSNET_ILL_DOI); 69 70 return (0); 71 } 72 73 static int 74 get_tn_sl_range(brange_t *range, char *min, char *max) 75 { 76 int err = 0; 77 78 if (min == NULL && max == NULL) 79 return (LTSNET_NO_RANGE); 80 if (min == NULL) 81 return (LTSNET_NO_LOWERBOUND); 82 if (max == NULL) 83 return (LTSNET_NO_UPPERBOUND); 84 85 if (stobsl(min, &range->lower_bound, NO_CORRECTION, &err) == 0) 86 return (LTSNET_ILL_LOWERBOUND); 87 if (stobsl(max, &range->upper_bound, NO_CORRECTION, &err) == 0) 88 return (LTSNET_ILL_UPPERBOUND); 89 if (!bldominates(&range->upper_bound, &range->lower_bound)) 90 return (LTSNET_ILL_RANGE); 91 92 return (0); 93 } 94 95 static int 96 get_tn_sl_set(blset_t *labelset, char *setstr) 97 { 98 int sc, err; 99 char *tokp, *finally; 100 bslabel_t *labels; 101 102 (void) memset(labelset, 0, sizeof (blset_t)); 103 labels = (bslabel_t *)labelset; 104 tokp = strtok_r(setstr, TNDB_COMMA, &finally); 105 for (sc = 0; tokp != NULL && sc < NSLS_MAX; sc++) { 106 if (stobsl(tokp, &labels[sc], NO_CORRECTION, &err) == 0) 107 return (LTSNET_ILL_LABEL); 108 tokp = strtok_r(NULL, TNDB_COMMA, &finally); 109 } 110 if (tokp != NULL && sc >= NSLS_MAX) 111 return (LTSNET_SET_TOO_BIG); 112 113 return (0); 114 } 115 116 static int 117 parse_remainder(tsol_tpent_t *tpentp, kva_t *kv) 118 { 119 int err = 0; 120 char *val = NULL; 121 char *val2 = NULL; 122 123 val = kva_match(kv, TP_HOSTTYPE); 124 125 if (val == NULL) 126 return (LTSNET_NO_HOSTTYPE); 127 if (strcasecmp(val, TP_UNLABELED) == 0) 128 tpentp->host_type = UNLABELED; 129 else if (strcasecmp(val, TP_CIPSO) == 0) 130 tpentp->host_type = SUN_CIPSO; 131 else 132 return (LTSNET_ILL_HOSTTYPE); 133 134 /* 135 * parse fields by host type - 136 * add on to the following if statement for each new host type. 137 */ 138 if (tpentp->host_type == UNLABELED) { 139 tpentp->tp_mask_unl = 0; 140 /* 141 * doi 142 */ 143 if ((err = get_tn_doi(tpentp, kv)) != 0) 144 return (err); 145 tpentp->tp_mask_unl |= TSOL_MSK_CIPSO_DOI; 146 /* 147 * default label 148 */ 149 val = kva_match(kv, TP_DEFLABEL); 150 if (val == NULL) 151 return (LTSNET_NO_LABEL); 152 if (stobsl(val, &tpentp->tp_def_label, NO_CORRECTION, 153 &err) == 0) 154 return (LTSNET_ILL_LABEL); 155 tpentp->tp_mask_unl |= TSOL_MSK_DEF_LABEL; 156 /* 157 * check label range 158 */ 159 val = kva_match(kv, TP_MINLABEL); 160 val2 = kva_match(kv, TP_MAXLABEL); 161 if (val == NULL && val2 == NULL) { 162 /* 163 * This is the old format. Use ADMIN_LOW to SL of the 164 * default label as the gw_sl_range. 165 */ 166 bsllow(&tpentp->tp_gw_sl_range.lower_bound); 167 tpentp->tp_gw_sl_range.upper_bound = 168 tpentp->tp_def_label; 169 } else { 170 err = get_tn_sl_range(&tpentp->tp_gw_sl_range, val, 171 val2); 172 if (err != 0) 173 return (err); 174 } 175 tpentp->tp_mask_unl |= TSOL_MSK_SL_RANGE_TSOL; 176 177 /* 178 * also label set, if present. (optional) 179 */ 180 val = kva_match(kv, TP_SET); 181 if (val != NULL) { 182 err = get_tn_sl_set(&tpentp->tp_gw_sl_set, val); 183 if (err != 0) 184 return (err); 185 tpentp->tp_mask_cipso |= TSOL_MSK_SL_RANGE_TSOL; 186 } 187 } else { 188 tpentp->tp_mask_cipso = 0; 189 /* 190 * doi 191 */ 192 if ((err = get_tn_doi(tpentp, kv)) != 0) 193 return (err); 194 tpentp->tp_mask_cipso |= TSOL_MSK_CIPSO_DOI; 195 /* 196 * label range 197 */ 198 val = kva_match(kv, TP_MINLABEL); 199 val2 = kva_match(kv, TP_MAXLABEL); 200 err = get_tn_sl_range(&tpentp->tp_sl_range_cipso, val, val2); 201 if (err != 0) 202 return (err); 203 tpentp->tp_mask_cipso |= TSOL_MSK_SL_RANGE_TSOL; 204 /* 205 * also label set, if present. (optional) 206 */ 207 val = kva_match(kv, TP_SET); 208 if (val != NULL) { 209 err = get_tn_sl_set(&tpentp->tp_sl_set_cipso, val); 210 if (err != 0) 211 return (err); 212 tpentp->tp_mask_cipso |= TSOL_MSK_SL_RANGE_TSOL; 213 } 214 215 /* CIPSO entries don't support default labels */ 216 val = kva_match(kv, TP_DEFLABEL); 217 if (val != NULL) 218 return (LTSNET_BAD_TYPE); 219 } 220 221 return (0); 222 } 223 224 tsol_tpent_t * 225 tpstr_to_ent(tsol_tpstr_t *tpstrp, int *errp, char **errstrp) 226 { 227 int err = 0; 228 char *errstr; 229 char *template = tpstrp->template; 230 char *attrs = tpstrp->attrs; 231 kva_t *kv; 232 tsol_tpent_t *tpentp = NULL; 233 234 /* 235 * The user can specify NULL pointers for these. Make sure that we 236 * don't have to deal with checking for NULL everywhere by just 237 * pointing to our own variables if the user gives NULL. 238 */ 239 if (errp == NULL) 240 errp = &err; 241 if (errstrp == NULL) 242 errstrp = &errstr; 243 /* The default, unless we find a more specific error locus. */ 244 *errstrp = template; 245 246 if (template == NULL || *template == '#' || *template == '\n') { 247 *errp = LTSNET_EMPTY; 248 if (attrs && *attrs != '\0' && *attrs != '#' && *attrs != '\n') 249 *errstrp = attrs; 250 else if (template == NULL) 251 *errstrp = " "; 252 goto err_ret; 253 } 254 if (*template == '\0') { 255 *errp = LTSNET_NO_NAME; 256 if (attrs && *attrs != '\0' && *attrs != '#' && *attrs != '\n') 257 *errstrp = attrs; 258 goto err_ret; 259 } 260 if (attrs == NULL || *attrs == '\0' || *attrs == '#' || 261 *attrs == '\n') { 262 *errp = LTSNET_NO_ATTRS; 263 goto err_ret; 264 } 265 if ((tpentp = calloc(1, sizeof (*tpentp))) == NULL) { 266 *errp = LTSNET_SYSERR; 267 return (NULL); 268 } 269 if (strlcpy(tpentp->name, template, sizeof (tpentp->name)) >= 270 sizeof (tpentp->name)) 271 goto err_ret; 272 kv = _str2kva(attrs, KV_ASSIGN, KV_DELIMITER); 273 *errp = parse_remainder(tpentp, kv); 274 _kva_free(kv); 275 if (*errp == 0) { 276 #ifdef DEBUG 277 (void) fprintf(stdout, "tpstr_to_ent: %s:%s\n", tpentp->name, 278 attrs); 279 #endif /* DEBUG */ 280 281 return (tpentp); 282 } 283 284 err_ret: 285 err = errno; 286 tsol_freetpent(tpentp); 287 errno = err; 288 #ifdef DEBUG 289 (void) fprintf(stderr, "\ntpstr_to_ent: %s:%s\n", 290 *errstrp, (char *)tsol_strerror(*errp, errno)); 291 #endif /* DEBUG */ 292 293 return (NULL); 294 } 295 296 void 297 tsol_freetpent(tsol_tpent_t *tp) 298 { 299 if (tp != NULL) 300 free(tp); 301 } 302