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