xref: /illumos-gate/usr/src/lib/libbsm/common/getdaent.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 
23 /*
24  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
25  * Use is subject to license terms.
26  */
27 
28 #pragma ident	"%Z%%M%	%I%	%E% SMI"
29 
30 #include <stdio.h>
31 #include <string.h>
32 #include <malloc.h>
33 #include <bsm/devices.h>
34 
35 #define	MAXINT 0x7fffffff;
36 #ifdef SunOS_CMW
37 extern char	*calloc();
38 #endif
39 
40 static struct _dabuff {
41 	devalloc_t _NULLDA;
42 	FILE *_daf;	/* pointer into /etc/security/device_allocate */
43 	devalloc_t _interpdevalloc;
44 	char _interpline[BUFSIZ + 1];
45 	char *_DEVALLOC;
46 } *__dabuff;
47 
48 #define	NULLDA (_da->_NULLDA)
49 #define	daf (_da->_daf)
50 #define	interpdevalloc (_da->_interpdevalloc)
51 #define	interpline (_da->_interpline)
52 #define	DEVALLOC (_da->_DEVALLOC)
53 static devalloc_t  *interpret();
54 static int matchname();
55 
56 /*
57  * trim_white(ptr) trims off leading and trailing white space from a NULL
58  * terminated string pointed to by "ptr". The leading white space is skipped
59  * by moving the pointer forward. The trailing white space is removed by
60  * nulling the white space characters.  The pointer is returned to the white
61  * string. If the resulting string is null in length then a NULL pointer is
62  * returned. If "ptr" is NULL then a NULL pointer is returned.
63  */
64 static char	*
65 trim_white(ptr)
66 char	*ptr;
67 {
68 	register char	*tptr;
69 	register int	cnt;
70 	if (ptr == NULL)
71 		return (NULL);
72 	while ((*ptr == ' ') || (*ptr == '\t')) {
73 		ptr++;
74 	}
75 	cnt = strlen(ptr);
76 	if (cnt != 0) {
77 		tptr = ptr + cnt - 1;
78 		while ((*tptr == ' ') || (*tptr == '\t')) {
79 			*tptr = '\0';
80 			tptr--;
81 		}
82 	}
83 	if (*ptr == NULL)
84 		return (NULL);
85 	return (ptr);
86 }
87 
88 
89 /*
90  * scan string pointed to by pointer "p"
91  * find next colin or end of line. Null it and
92  * return pointer to next char.
93  */
94 static char	*
95 daskip(p)
96 register char	*p;
97 {
98 	while (*p && *p != ';' && *p != '\n')
99 		++p;
100 	if (*p == '\n')
101 		*p = '\0';
102 	else if (*p != '\0')
103 		*p++ = '\0';
104 	return (p);
105 }
106 
107 
108 /*
109  * scan string pointed to by pointer "p"
110  * find next colin or end of line. Null it and
111  * return pointer to next char.
112  */
113 static char	*
114 dadskip(p)
115 register char	*p;
116 {
117 	while (*p && *p != ' ' && *p != '\n')
118 		++p;
119 	if (*p != '\0')
120 		*p++ = '\0';
121 	return (p);
122 }
123 
124 
125 /*
126  * _daalloc() allocates common buffers and structures used by the device
127  * allocate library routines. Then returns a pointer to a structure.  The
128  * returned pointer will be null if there is an error condition.
129  */
130 static struct _dabuff *
131 _daalloc()
132 {
133 	register struct _dabuff *_da = __dabuff;
134 
135 	if (_da == 0) {
136 		_da = (struct _dabuff *)
137 		calloc((size_t)1, sizeof (*__dabuff));
138 		if (_da == 0)
139 			return (0);
140 		DEVALLOC = "/etc/security/device_allocate";
141 		__dabuff = _da;
142 	}
143 	return (__dabuff);
144 }
145 
146 
147 /*
148  * getdaline(buff,len,stream) reads one device allocate line from "stream" into
149  * "buff" on "len" bytes.  Continued lines from "stream" are concatinated
150  * into one line in "buff". Comments are removed from "buff". The number of
151  * characters in "buff" is returned.  If no characters are read or an err or
152  * occured then "0" is returned
153  */
154 static int
155 getdaline(buff, len, stream)
156 	char *buff;
157 	int len;
158 	FILE *stream;
159 {
160 	register struct _dabuff *_da = _daalloc();
161 	char	*cp;
162 	char	*ccp;
163 	int	tmpcnt;
164 	int	charcnt = 0;
165 	int	fileerr = 0;
166 	int	contline;
167 	if (_da == 0)
168 		return (0);
169 	do {
170 		cp = buff;
171 		*cp = NULL;
172 		do {
173 			if (fgets(cp, len - charcnt, stream) == NULL) {
174 				fileerr = 1;
175 				break;
176 			}
177 			ccp = strpbrk(cp, "\\\n");
178 			if (ccp != NULL) {
179 				if (*ccp == '\\')
180 					contline = 1;
181 					else
182 					contline = 0;
183 				*ccp = NULL;
184 			}
185 			tmpcnt = strlen(cp);
186 			if (tmpcnt != 0) {
187 				cp += tmpcnt;
188 				charcnt += tmpcnt;
189 			}
190 		} while ((contline) || (charcnt == 0));
191 		ccp = strpbrk(buff, "#");
192 		if (ccp != NULL)
193 			*ccp = NULL;
194 		charcnt = strlen(buff);
195 	} while ((fileerr == 0) && (charcnt == 0));
196 	if (fileerr)
197 		return (0);
198 		else
199 		return (charcnt);
200 }
201 
202 char	*
203 getdafield(ptr)
204 char	*ptr;
205 {
206 	static char	*tptr;
207 	if (ptr == NULL)
208 		ptr = tptr;
209 	if (ptr == NULL)
210 		return (NULL);
211 	tptr = daskip(ptr);
212 	ptr = trim_white(ptr);
213 	if (ptr == NULL)
214 		return (NULL);
215 	if (*ptr == NULL)
216 		return (NULL);
217 	return (ptr);
218 }
219 
220 char	*
221 getdadfield(ptr)
222 char	*ptr;
223 {
224 	static char	*tptr;
225 	if (ptr != NULL) {
226 		ptr = trim_white(ptr);
227 	} else {
228 		ptr = tptr;
229 	}
230 	if (ptr == NULL)
231 		return (NULL);
232 	tptr = dadskip(ptr);
233 	if (ptr == NULL)
234 		return (NULL);
235 	if (*ptr == NULL)
236 		return (NULL);
237 	return (ptr);
238 }
239 
240 /*
241  * getdadev(dev) searches from the beginning of the file until a logical
242  * device matching "dev" is found and returns a pointer to the particular
243  * structure in which it was found.  If an EOF or an error is encountered on
244  * reading, these functions return a NULL pointer.
245  */
246 #ifdef NOTDEF
247 devalloc_t *
248 getdadev(name)
249 	register char	*name;
250 {
251 	register struct _dabuff *_da = _daalloc();
252 	devalloc_t *da;
253 	char	line[BUFSIZ + 1];
254 
255 	if (_da == 0)
256 		return (0);
257 	setdaent();
258 	if (!daf)
259 		return ((devalloc_t *)NULL);
260 	while (getdaline(line, sizeof (line), daf) != 0) {
261 		if ((da = interpret(line)) == NULL)
262 			continue;
263 		if (matchdev(&da, name)) {
264 			enddaent();
265 			return (da);
266 		}
267 	}
268 	enddaent();
269 	return ((devalloc_t *)NULL);
270 }
271 
272 
273 #endif /* NOTDEF */
274 
275 /*
276  * getdanam(name) searches from the beginning of the file until a audit-name
277  * matching "name" is found and returns a pointer to the particular structure
278  * in which it was found.  If an EOF or an error is encountered on reading,
279  * these functions return a NULL pointer.
280  */
281 devalloc_t *
282 getdanam(name)
283 	register char	*name;
284 {
285 	register struct _dabuff *_da = _daalloc();
286 	devalloc_t *da;
287 	char line[BUFSIZ + 1];
288 
289 	if (_da == 0)
290 		return (0);
291 	setdaent();
292 	if (!daf)
293 		return ((devalloc_t *)NULL);
294 	while (getdaline(line, (int)sizeof (line), daf) != 0) {
295 		if ((da = interpret(line)) == NULL)
296 			continue;
297 		if (matchname(&da, name)) {
298 			enddaent();
299 			return (da);
300 		}
301 	}
302 	enddaent();
303 	return ((devalloc_t *)NULL);
304 }
305 
306 
307 /*
308  * setdaent() essentially rewinds the device_allocate file to the begining.
309  */
310 
311 void
312 setdaent()
313 {
314 	register struct _dabuff *_da = _daalloc();
315 
316 	if (_da == 0)
317 		return;
318 	if (daf == NULL) {
319 		daf = fopen(DEVALLOC, "r");
320 	} else
321 		rewind(daf);
322 }
323 
324 
325 /*
326  * enddaent() may be called to close the device_allocate file when processing
327  * is complete.
328  */
329 
330 void
331 enddaent()
332 {
333 	register struct _dabuff *_da = _daalloc();
334 
335 	if (_da == 0)
336 		return;
337 	if (daf != NULL) {
338 		(void) fclose(daf);
339 		daf = NULL;
340 	}
341 }
342 
343 
344 /*
345  * setdafile(name) changes the default device_allocate file to "name" thus
346  * allowing alternate device_allocate files to be used.  Note: it does not
347  * close the previous file . If this is desired, enddaent should be called
348  * prior to it.
349  */
350 void
351 setdafile(file)
352 char	*file;
353 {
354 	register struct _dabuff *_da = _daalloc();
355 
356 	if (_da == 0)
357 		return;
358 	if (daf != NULL) {
359 		(void) fclose(daf);
360 		daf = NULL;
361 	}
362 	DEVALLOC = file;
363 }
364 
365 
366 /*
367  * getdatype(tp) When first called, returns a pointer to the
368  * first devalloc_t structure in the file with device-type matching
369  * "tp"; thereafter, it returns a pointer to the next devalloc_t
370  * structure in the file with device-type matching "tp".
371  * Thus successive calls can be used to search the
372  * entire file for entries having device-type matching "tp".
373  * A null pointer is returned on error.
374  */
375 devalloc_t *
376 getdatype(tp)
377 	char	*tp;
378 {
379 	register struct _dabuff *_da = _daalloc();
380 	char line1[BUFSIZ + 1];
381 	devalloc_t *da;
382 
383 	if (_da == 0)
384 		return (0);
385 	if (daf == NULL && (daf = fopen(DEVALLOC, "r")) == NULL) {
386 		return (NULL);
387 	}
388 	do {
389 		if (getdaline(line1, (int)sizeof (line1), daf) == 0)
390 			return (NULL);
391 
392 		if ((da = interpret(line1)) == NULL)
393 			return (NULL);
394 	} while (strcmp(tp, da->da_devtype) != 0);
395 	return (da);
396 }
397 
398 
399 /*
400  * getdaent() When first called, returns a pointer to the first devalloc_t
401  * structure in the file; thereafter, it returns a pointer to the next
402  * devalloc_t structure in the file. Thus successive calls can be used to
403  * search the entire file.  A null pointer is returned on error.
404  */
405 devalloc_t *
406 getdaent()
407 {
408 	register struct _dabuff *_da = _daalloc();
409 	char line1[BUFSIZ + 1];
410 	devalloc_t *da;
411 
412 	if (_da == 0)
413 		return (0);
414 	if (daf == NULL && (daf = fopen(DEVALLOC, "r")) == NULL) {
415 		return (NULL);
416 	}
417 	if (getdaline(line1, (int)sizeof (line1), daf) == 0)
418 		return (NULL);
419 
420 	if ((da = interpret(line1)) == NULL)
421 		return (NULL);
422 	return (da);
423 }
424 
425 
426 /*
427  * matchdev(dap,dev) The dev_list in the structure pointed to by "dap" is
428  * searched for string "dev".  If a match occures then a "1" is returned
429  * otherwise a "0" is returned.
430  */
431 #ifdef NOTDEF
432 static
433 matchdev(dap, dev)
434 	devalloc_t **dap;
435 	char	*dev;
436 {
437 	register struct _dabuff *_da = _daalloc();
438 	devalloc_t *da = *dap;
439 	char tmpdev[BUFSIZ + 1];
440 	int	charcnt;
441 	int	tmpcnt;
442 	char	*cp;
443 	char	*tcp;
444 	char	*last;
445 
446 	charcnt = strlen(dev);
447 	if (_da == 0)
448 		return (0);
449 	if (da->da_devlist == NULL)
450 		return (0);
451 	(void) strcpy(tmpdev, da->da_devlist);
452 	tcp = tmpdev;
453 	while ((cp = strtok_r(tcp, " ", &last)) != NULL) {
454 		tcp = NULL;
455 		tmpcnt = strlen(cp);
456 		if (tmpcnt != charcnt)
457 			continue;
458 		if (strcmp(cp, dev) == 0)
459 			return (1);
460 	}
461 	return (0);
462 }
463 
464 #endif /* NOTDEF */
465 /*
466  * matchname(dap,name) The audit-name in the structure pointed to by "dap" is
467  * searched for string "name".  If a match occures then a "1" is returned
468  * otherwise a "0" is returned.
469  */
470 static int
471 matchname(dap, name)
472 	devalloc_t **dap;
473 	char *name;
474 {
475 	register struct _dabuff *_da = _daalloc();
476 	devalloc_t *da = *dap;
477 
478 	if (_da == 0)
479 		return (0);
480 	if (da->da_devname == NULL)
481 		return (0);
482 	if (strlen(da->da_devname) != strlen(name))
483 		return (0);
484 	if (strcmp(da->da_devname, name) == 0)
485 		return (1);
486 	return (0);
487 }
488 
489 
490 /*
491  * interpret(val) string "val" is parsed and the pointers in a devalloc_t
492  * structure are initialized to point to fields in "val". A pointer to this
493  * structure is returned.
494  */
495 static devalloc_t  *
496 interpret(val)
497 char	*val;
498 {
499 	register struct _dabuff *_da = _daalloc();
500 
501 	if (_da == 0)
502 		return (0);
503 	(void) strcpy(interpline, val);
504 	interpdevalloc.da_devname = getdafield(interpline);
505 	interpdevalloc.da_devtype = getdafield((char *)NULL);
506 	interpdevalloc.da_devmin = getdafield((char *)NULL);
507 	interpdevalloc.da_devmax = getdafield((char *)NULL);
508 	interpdevalloc.da_devauth = getdafield((char *)NULL);
509 	interpdevalloc.da_devexec = getdafield((char *)NULL);
510 
511 	return (&interpdevalloc);
512 }
513