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