xref: /illumos-gate/usr/src/lib/libbsm/common/getdadefs.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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, "rF");
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