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 *
_dadefalloc(void)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
setdadefent(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, "rF");
95 else
96 rewind(dadeff);
97 }
98
99 /*
100 * enddadefent -
101 * closes devalloc_defaults file.
102 */
103
104 void
enddadefent(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
freedadefent(da_defs_t * da_def)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 *
getdadefent(void)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 *
getdadeftype(char * type)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
dadef_matchtype(da_defs_t * da_def,char * type)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 *
dadef_interpret(char * val)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