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