xref: /titanic_52/usr/src/lib/libbsm/common/getdment.c (revision d58fda4376e4bf67072ce2e69f6f47036f9dbb68)
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  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <stdio.h>
30 #include <string.h>
31 #include <malloc.h>
32 #include <bsm/devices.h>
33 #include <sys/errno.h>
34 
35 #define	MAXINT 0x7fffffff;
36 
37 static struct _dmapbuff {
38 	devmap_t _NULLDM;
39 	FILE *_dmapf;	/* pointer into /etc/security/device_maps */
40 	devmap_t _interpdevmap;
41 	char _interpline[BUFSIZ + 1];
42 	char *_DEVMAP;
43 } *__dmapbuff;
44 
45 #define	NULLDM (_dmap->_NULLDM)
46 #define	dmapf (_dmap->_dmapf)
47 #define	interpdevmap (_dmap->_interpdevmap)
48 #define	interpline (_dmap->_interpline)
49 #define	DEVMAP (_dmap->_DEVMAP)
50 static devmap_t  *interpret();
51 static int matchdev();
52 static int matchname();
53 /*
54  * trim_white(ptr) trims off leading and trailing white space from a NULL
55  * terminated string pointed to by "ptr". The leading white space is skipped
56  * by moving the pointer forward. The trailing white space is removed by
57  * nulling the white space characters.  The pointer is returned to the white
58  * string. If the resulting string is null in length then a NULL pointer is
59  * returned. If "ptr" is NULL then a NULL pointer is returned.
60  */
61 static char *
62 trim_white(char *ptr)
63 {
64 	register char  *tptr;
65 	register int    cnt;
66 	if (ptr == NULL)
67 		return (NULL);
68 	while ((*ptr == ' ') || (*ptr == '\t')) {
69 		ptr++;
70 	}
71 	cnt = strlen(ptr);
72 	if (cnt != 0) {
73 		tptr = ptr + cnt - 1;
74 		while ((*tptr == ' ') || (*tptr == '\t')) {
75 			*tptr = '\0';
76 			tptr--;
77 		}
78 	}
79 	if (*ptr == NULL)
80 		return (NULL);
81 	return (ptr);
82 }
83 /*
84  * scan string pointed to by pointer "p"
85  * find next colin or end of line. Null it and
86  * return pointer to next char.
87  */
88 static char *
89 dmapskip(register char *p)
90 {
91 	while (*p && *p != ':' && *p != '\n')
92 		++p;
93 	if (*p == '\n')
94 		*p = '\0';
95 	else if (*p != '\0')
96 		*p++ = '\0';
97 	return (p);
98 }
99 /*
100  * scan string pointed to by pointer "p"
101  * find next colin or end of line. Null it and
102  * return pointer to next char.
103  */
104 static char *
105 dmapdskip(register char *p)
106 {
107 	while (*p && *p != ' ' && *p != '\n')
108 		++p;
109 	if (*p != '\0')
110 		*p++ = '\0';
111 	return (p);
112 }
113 
114 /*
115  * _dmapalloc() allocates common buffers and structures used by the device
116  * maps library routines. Then returns a pointer to a structure.  The
117  * returned pointer will be null if there is an error condition.
118  */
119 static struct _dmapbuff *
120 _dmapalloc(void)
121 {
122 	register struct _dmapbuff *_dmap = __dmapbuff;
123 
124 	if (_dmap == 0) {
125 		_dmap = (struct _dmapbuff *)
126 			calloc((unsigned)1, (unsigned)sizeof (*__dmapbuff));
127 		if (_dmap == 0)
128 			return (0);
129 		DEVMAP = "/etc/security/device_maps";
130 		__dmapbuff = _dmap;
131 	}
132 	return (__dmapbuff);
133 }
134 /*
135  * getdmapline(buff,len,stream) reads one device maps line from "stream" into
136  * "buff" on "len" bytes.  Continued lines from "stream" are concatinated
137  * into one line in "buff". Comments are removed from "buff". The number of
138  * characters in "buff" is returned.  If no characters are read or an error
139  * occured then "0" is returned
140  */
141 static int
142 getdmapline(char *buff, int len, FILE *stream)
143 {
144 	register struct _dmapbuff *_dmap = _dmapalloc();
145 	char *cp;
146 	char *ccp;
147 	size_t tmpcnt;
148 	int charcnt = 0;
149 	int fileerr = 0;
150 	int contline;
151 	if (_dmap == 0)
152 		return (0);
153 	do {
154 		cp = buff;
155 		*cp = NULL;
156 		do {
157 			if ((len - charcnt <= 1) ||
158 			    (fgets(cp, len - charcnt, stream) == NULL)) {
159 				fileerr = 1;
160 				break;
161 			}
162 			ccp = strpbrk(cp, "\\\n");
163 			if (ccp != NULL) {
164 				if (*ccp == '\\')
165 					contline = 1;
166 				else
167 					contline = 0;
168 				*ccp = NULL;
169 			}
170 			tmpcnt = strlen(cp);
171 			if (tmpcnt != 0) {
172 				cp += tmpcnt;
173 				charcnt += tmpcnt;
174 			}
175 		} while ((contline) || (charcnt == 0));
176 		ccp = strpbrk(buff, "#");
177 		if (ccp != NULL)
178 			*ccp = NULL;
179 		charcnt = strlen(buff);
180 	} while ((fileerr == 0) && (charcnt == 0));
181 	if (fileerr && !charcnt)
182 		return (0);
183 	else
184 		return (charcnt);
185 }
186 char
187 *getdmapfield(char *ptr)
188 {
189 	static	char	*tptr;
190 	if (ptr == NULL)
191 		ptr = tptr;
192 	if (ptr == NULL)
193 		return (NULL);
194 	tptr = dmapskip(ptr);
195 	ptr = trim_white(ptr);
196 	if (ptr == NULL)
197 		return (NULL);
198 	if (*ptr == NULL)
199 		return (NULL);
200 	return (ptr);
201 }
202 char
203 *getdmapdfield(char *ptr)
204 {
205 	static	char	*tptr;
206 	if (ptr != NULL) {
207 		ptr = trim_white(ptr);
208 	} else {
209 		ptr = tptr;
210 	}
211 	if (ptr == NULL)
212 		return (NULL);
213 	tptr = dmapdskip(ptr);
214 	if (ptr == NULL)
215 		return (NULL);
216 	if (*ptr == NULL)
217 		return (NULL);
218 	return (ptr);
219 }
220 /*
221  * getdmapdev(dev) searches from the beginning of the file until a logical
222  * device matching "dev" is found and returns a pointer to the particular
223  * structure in which it was found.  If an EOF or an error is encountered on
224  * reading, these functions return a NULL pointer.
225  */
226 devmap_t *
227 getdmapdev(register char  *name)
228 {
229 	register struct _dmapbuff *_dmap = _dmapalloc();
230 	devmap_t *dmap;
231 	char line[BUFSIZ + 1];
232 
233 	if (_dmap == 0)
234 		return (0);
235 	setdmapent();
236 	if (!dmapf)
237 		return (NULL);
238 	while (getdmapline(line, (int)sizeof (line), dmapf) != 0) {
239 		if ((dmap = interpret(line)) == NULL)
240 			continue;
241 		if (matchdev(&dmap, name)) {
242 			enddmapent();
243 			return (dmap);
244 		}
245 	}
246 	enddmapent();
247 	return (NULL);
248 }
249 /*
250  * getdmapnam(name) searches from the beginning of the file until a audit-name
251  * matching "name" is found and returns a pointer to the particular structure
252  * in which it was found.  If an EOF or an error is encountered on reading,
253  * these functions return a NULL pointer.
254  */
255 devmap_t *
256 getdmapnam(register char  *name)
257 {
258 	register struct _dmapbuff *_dmap = _dmapalloc();
259 	devmap_t *dmap;
260 	char line[BUFSIZ + 1];
261 
262 	if (_dmap == 0)
263 		return (0);
264 	setdmapent();
265 	if (!dmapf)
266 		return (NULL);
267 	while (getdmapline(line, (int)sizeof (line), dmapf) != 0) {
268 		if ((dmap = interpret(line)) == NULL)
269 			continue;
270 		if (matchname(&dmap, name)) {
271 			enddmapent();
272 			return (dmap);
273 		}
274 	}
275 	enddmapent();
276 	return (NULL);
277 }
278 
279 /*
280  * setdmapent() essentially rewinds the device_maps file to the begining.
281  */
282 
283 void
284 setdmapent(void)
285 {
286 	register struct _dmapbuff *_dmap = _dmapalloc();
287 
288 
289 	if (_dmap == 0)
290 		return;
291 
292 	if (dmapf == NULL) {
293 		dmapf = fopen(DEVMAP, "r");
294 	} else
295 		rewind(dmapf);
296 }
297 
298 
299 /*
300  * enddmapent() may be called to close the device_maps file when processing
301  * is complete.
302  */
303 
304 void
305 enddmapent(void)
306 {
307 	register struct _dmapbuff *_dmap = _dmapalloc();
308 
309 	if (_dmap == 0)
310 		return;
311 	if (dmapf != NULL) {
312 		(void) fclose(dmapf);
313 		dmapf = NULL;
314 	}
315 }
316 
317 
318 /*
319  * setdmapfile(name) changes the default device_maps file to "name" thus
320  * allowing alternate device_maps files to be used.  Note: it does not
321  * close the previous file . If this is desired, enddmapent should be called
322  * prior to it.
323  */
324 void
325 setdmapfile(char *file)
326 {
327 	register struct _dmapbuff *_dmap = _dmapalloc();
328 
329 	if (_dmap == 0)
330 		return;
331 	if (dmapf != NULL) {
332 		(void) fclose(dmapf);
333 		dmapf = NULL;
334 	}
335 	DEVMAP = file;
336 }
337 /*
338  * getdmaptype(tp) When first called, returns a pointer to the
339  * first devmap_t structure in the file with device-type matching
340  * "tp"; thereafter, it returns a pointer to the next devmap_t
341  * structure in the file with device-type matching "tp".
342  * Thus successive calls can be used to search the
343  * entire file for entries having device-type matching "tp".
344  * A null pointer is returned on error.
345  */
346 devmap_t *
347 getdmaptype(char *tp)
348 {
349 	register struct _dmapbuff *_dmap = _dmapalloc();
350 	char line1[BUFSIZ + 1];
351 	devmap_t *dmap;
352 
353 	if (_dmap == 0)
354 		return (0);
355 	if (dmapf == NULL && (dmapf = fopen(DEVMAP, "r")) == NULL) {
356 		return (NULL);
357 	}
358 	do {
359 		if (getdmapline(line1, (int)sizeof (line1), dmapf) == 0)
360 			return (NULL);
361 
362 		if ((dmap = interpret(line1)) == NULL)
363 			return (NULL);
364 	} while (strcmp(tp, dmap->dmap_devtype) != 0);
365 	return (dmap);
366 }
367 
368 /*
369  * getdmapent() When first called, returns a pointer to the first devmap_t
370  * structure in the file; thereafter, it returns a pointer to the next devmap_t
371  * structure in the file. Thus successive calls can be used to search the
372  * entire file.  A null pointer is returned on error.
373  */
374 devmap_t *
375 getdmapent(void)
376 {
377 	register struct _dmapbuff *_dmap = _dmapalloc();
378 	char line1[BUFSIZ + 1];
379 	devmap_t *dmap;
380 
381 	if (_dmap == 0)
382 		return (0);
383 	if (dmapf == NULL && (dmapf = fopen(DEVMAP, "r")) == NULL) {
384 		return (NULL);
385 	}
386 	if (getdmapline(line1, (int)sizeof (line1), dmapf) == 0)
387 		return (NULL);
388 
389 	if ((dmap = interpret(line1)) == NULL)
390 		return (NULL);
391 	return (dmap);
392 }
393 /*
394  * matchdev(dmapp,dev) The dev_list in the structure pointed to by "dmapp" is
395  * searched for string "dev".  If a match occures then a "1" is returned
396  * otherwise a "0" is returned.
397  */
398 static int
399 matchdev(devmap_t **dmapp, char *dev)
400 {
401 	register struct _dmapbuff *_dmap = _dmapalloc();
402 	devmap_t *dmap = *dmapp;
403 	char tmpdev[BUFSIZ + 1];
404 	int charcnt;
405 	int tmpcnt;
406 	char *cp;
407 	char *tcp;
408 	char *last;
409 	charcnt = strlen(dev);
410 	if (_dmap == 0)
411 		return (0);
412 	if (dmap->dmap_devlist == NULL)
413 		return (0);
414 	(void) strcpy(tmpdev, dmap->dmap_devlist);
415 	tcp = tmpdev;
416 	while ((cp = strtok_r(tcp, " ", &last)) != NULL) {
417 		tcp = NULL;
418 		tmpcnt = strlen(cp);
419 		if (tmpcnt != charcnt)
420 			continue;
421 		if (strcmp(cp, dev) == 0)
422 			return (1);
423 	}
424 	return (0);
425 }
426 /*
427  * matchname(dmapp,name) The audit-name in the structure pointed to by "dmapp"
428  * is searched for string "name".  If a match occures then a "1" is returned
429  * otherwise a "0" is returned.
430  */
431 static int
432 matchname(devmap_t **dmapp, char *name)
433 {
434 	register struct _dmapbuff *_dmap = _dmapalloc();
435 	devmap_t *dmap = *dmapp;
436 
437 	if (_dmap == 0)
438 		return (0);
439 	if (dmap->dmap_devname == NULL)
440 		return (0);
441 	if (strlen(dmap->dmap_devname) != strlen(name))
442 		return (0);
443 	if (strcmp(dmap->dmap_devname, name) == 0)
444 		return (1);
445 	return (0);
446 }
447 /*
448  * interpret(val) string "val" is parsed and the pointers in a devmap_t
449  * structure are initialized to point to fields in "val". A pointer to this
450  * structure is returned.
451  */
452 static devmap_t  *
453 interpret(char *val)
454 {
455 	register struct _dmapbuff *_dmap = _dmapalloc();
456 
457 	if (_dmap == 0)
458 		return (0);
459 	(void) strcpy(interpline, val);
460 	interpdevmap.dmap_devname = getdmapfield(interpline);
461 	interpdevmap.dmap_devtype = getdmapfield((char *)NULL);
462 	interpdevmap.dmap_devlist = getdmapfield((char *)NULL);
463 
464 	return (&interpdevmap);
465 }
466