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 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <string.h> 29 #include <stdlib.h> 30 #include <bsm/devices.h> 31 #include <bsm/devalloc.h> 32 33 char *strtok_r(char *, const char *, char **); 34 35 /* externs from getdaent.c */ 36 extern char *trim_white(char *); 37 extern int pack_white(char *); 38 extern char *getdadmfield(char *, char *); 39 extern int getdadmline(char *, int, FILE *); 40 41 extern char *_strdup_null(char *); 42 43 static struct _dadefbuff { 44 FILE *_dadeff; 45 /* pointer into /etc/security/tsol/devalloc_defaults */ 46 da_defs_t _interpdadefs; 47 char _interpdadefline[DA_BUFSIZE + 1]; 48 char *_DADEFS; 49 } *__dadefbuff; 50 51 #define dadeff (_df->_dadeff) 52 #define interpdadefs (_df->_interpdadefs) 53 #define interpdadefline (_df->_interpdadefline) 54 #define DADEFS_FILE (_df->_DADEFS) 55 56 static da_defs_t *dadef_interpret(char *); 57 int dadef_matchtype(da_defs_t *, char *); 58 59 /* 60 * _dadefalloc - 61 * allocates common buffers and structures. 62 * returns pointer to the new structure, else returns NULL on error. 63 */ 64 static struct _dadefbuff * 65 _dadefalloc(void) 66 { 67 struct _dadefbuff *_df = __dadefbuff; 68 69 if (_df == NULL) { 70 _df = (struct _dadefbuff *)calloc((unsigned)1, 71 (unsigned)sizeof (*__dadefbuff)); 72 if (_df == NULL) 73 return (NULL); 74 DADEFS_FILE = "/etc/security/tsol/devalloc_defaults"; 75 __dadefbuff = _df; 76 } 77 78 return (__dadefbuff); 79 } 80 81 /* 82 * setdadefent - 83 * rewinds devalloc_defaults file to the begining. 84 */ 85 86 void 87 setdadefent(void) 88 { 89 struct _dadefbuff *_df = _dadefalloc(); 90 91 if (_df == NULL) 92 return; 93 if (dadeff == NULL) 94 dadeff = fopen(DADEFS_FILE, "r"); 95 else 96 rewind(dadeff); 97 } 98 99 /* 100 * enddadefent - 101 * closes devalloc_defaults file. 102 */ 103 104 void 105 enddadefent(void) 106 { 107 struct _dadefbuff *_df = _dadefalloc(); 108 109 if (_df == NULL) 110 return; 111 if (dadeff != NULL) { 112 (void) fclose(dadeff); 113 dadeff = NULL; 114 } 115 } 116 117 void 118 freedadefent(da_defs_t *da_def) 119 { 120 if (da_def == NULL) 121 return; 122 _kva_free(da_def->devopts); 123 da_def->devopts = NULL; 124 } 125 126 /* 127 * getdadefent - 128 * When first called, returns a pointer to the first da_defs_t 129 * structure in devalloc_defaults; thereafter, it returns a pointer to the 130 * next da_defs_t structure in the file. Thus, successive calls can be 131 * used to search the entire file. 132 * call to getdadefent should be bracketed by setdadefent and enddadefent. 133 * returns NULL on error. 134 */ 135 da_defs_t * 136 getdadefent(void) 137 { 138 char line1[DA_BUFSIZE + 1]; 139 da_defs_t *da_def; 140 struct _dadefbuff *_df = _dadefalloc(); 141 142 if ((_df == 0) || (dadeff == NULL)) 143 return (NULL); 144 145 while (getdadmline(line1, (int)sizeof (line1), dadeff) != 0) { 146 if ((da_def = dadef_interpret(line1)) == NULL) 147 continue; 148 return (da_def); 149 } 150 151 return (NULL); 152 } 153 154 /* 155 * getdadeftype - 156 * searches from the beginning of devalloc_defaults for the device 157 * specified by its type. 158 * call to getdadeftype should be bracketed by setdadefent and enddadefent. 159 * returns pointer to da_defs_t for the device if it is found, else 160 * returns NULL if device not found or in case of error. 161 */ 162 da_defs_t * 163 getdadeftype(char *type) 164 { 165 char line1[DA_BUFSIZE + 1]; 166 da_defs_t *da_def; 167 struct _dadefbuff *_df = _dadefalloc(); 168 169 if ((type == NULL) || (_df == NULL) || (dadeff == NULL)) 170 return (NULL); 171 172 while (getdadmline(line1, (int)sizeof (line1), dadeff) != 0) { 173 if (strstr(line1, type) == NULL) 174 continue; 175 if ((da_def = dadef_interpret(line1)) == NULL) 176 continue; 177 if (dadef_matchtype(da_def, type)) 178 return (da_def); 179 freedadefent(da_def); 180 } 181 182 return (NULL); 183 } 184 185 /* 186 * dadef_matchtype - 187 * checks if the specified da_defs_t is for the device type specified. 188 * returns 1 if match found, else, returns 0. 189 */ 190 int 191 dadef_matchtype(da_defs_t *da_def, char *type) 192 { 193 if (da_def->devtype == NULL) 194 return (0); 195 196 return ((strcmp(da_def->devtype, type) == 0)); 197 } 198 199 /* 200 * dadef_interpret - 201 * parses val and initializes pointers in da_defs_t. 202 * returns pointer to parsed da_defs_t entry, else returns NULL on error. 203 */ 204 static da_defs_t * 205 dadef_interpret(char *val) 206 { 207 struct _dadefbuff *_df = _dadefalloc(); 208 int i; 209 char *opts; 210 kva_t *kvap; 211 kv_t *kvp; 212 213 if (_df == NULL) 214 return (NULL); 215 216 (void) strcpy(interpdadefline, val); 217 interpdadefs.devtype = getdadmfield(interpdadefline, KV_TOKEN_DELIMIT); 218 opts = getdadmfield(NULL, KV_TOKEN_DELIMIT); 219 interpdadefs.devopts = NULL; 220 if (interpdadefs.devtype == NULL) 221 return (NULL); 222 if (opts != NULL) 223 interpdadefs.devopts = 224 _str2kva(opts, KV_ASSIGN, KV_DELIMITER); 225 /* remove any extraneous whitespace in the options */ 226 if ((kvap = interpdadefs.devopts) != NULL) { 227 for (i = 0, kvp = kvap->data; i < kvap->length; i++, kvp++) { 228 (void) pack_white(kvp->key); 229 (void) pack_white(kvp->value); 230 } 231 } 232 233 return (&interpdadefs); 234 } 235