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.
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.
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]
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
31 #include <tsol/label.h>
32 #include <bsm/devices.h>
33 #include <bsm/devalloc.h>
35 extern char *_strdup_null(char *);
37 static struct _dabuff
{
38 FILE *_daf
; /* pointer into /etc/security/device_allocate */
39 devalloc_t _interpdevalloc
;
40 char _interpdaline
[DA_BUFSIZE
+ 1];
44 #define daf (_da->_daf)
45 #define interpdevalloc (_da->_interpdevalloc)
46 #define interpdaline (_da->_interpdaline)
47 #define DEVALLOC_FILE (_da->_DEVALLOC)
48 static devalloc_t
*da_interpret(char *);
50 int da_matchname(devalloc_t
*, char *);
51 int da_matchtype(devalloc_t
*, char *);
53 static int system_labeled
= 0;
57 * trims off leading and trailing white space from input string.
58 * The leading white space is skipped by moving the pointer forward.
59 * The trailing white space is removed by nulling the white space
61 * returns pointer to non-white string, else returns NULL if input string
62 * is null or if the resulting string has zero length.
73 tptr
= ptr
+ strlen(ptr
);
74 while (tptr
!= ptr
&& isspace(tptr
[-1]))
85 * trims off multiple occurrences of white space from input string.
86 * returns the number of spaces retained
97 while (isspace(*tptr
))
100 while ((ch
= *tptr
) != '\0' && !isspace(ch
)) {
104 while (isspace(*tptr
))
118 * reads one device_alloc/device_maps line from stream into buff of len
119 * bytes. Continued lines from stream are concatenated into one line in
120 * buff. Comments are removed from buff.
121 * returns the number of characters in buff, else returns 0 if no
122 * characters are read or an error occurred.
125 getdadmline(char *buff
, int len
, FILE *stream
)
139 if (fgets(cp
, len
- charcnt
, stream
) == NULL
) {
143 ccp
= strchr(cp
, '\n');
145 if (ccp
!= cp
&& ccp
[-1] == '\\') {
156 } while ((contline
) || (charcnt
== 0));
157 ccp
= strpbrk(buff
, "#");
160 charcnt
= strlen(buff
);
161 } while ((fileerr
== 0) && (charcnt
== 0));
163 if (fileerr
&& !charcnt
)
171 * allocates common buffers and structures.
172 * returns pointer to the new structure, else returns NULL on error.
174 static struct _dabuff
*
177 struct _dabuff
*_da
= __dabuff
;
180 _da
= (struct _dabuff
*)calloc((unsigned)1,
181 (unsigned)sizeof (*__dabuff
));
184 DEVALLOC_FILE
= "/etc/security/device_allocate";
187 system_labeled
= is_system_labeled();
195 * gets individual fields separated by skip in ptr.
198 getdadmfield(char *ptr
, char *skip
)
200 static char *tptr
= NULL
;
203 /* check for a continuing search */
206 /* check for source end */
207 if (ptr
== NULL
|| *ptr
== '\0')
209 /* find terminator */
210 pend
= strpbrk(ptr
, skip
);
211 /* terminate and set continuation pointer */
218 * trim off any surrounding white space, return what's left
221 return (trim_white(ptr
));
226 * rewinds the device_allocate file to the begining.
232 struct _dabuff
*_da
= _daalloc();
237 daf
= fopen(DEVALLOC_FILE
, "rF");
244 * closes device_allocate file.
250 struct _dabuff
*_da
= _daalloc();
262 * changes the default device_allocate file to the one specified.
263 * It does not close the previous file. If this is desired, enddaent
264 * should be called prior to setdafile.
267 setdafile(char *file
)
269 struct _dabuff
*_da
= _daalloc();
277 DEVALLOC_FILE
= file
;
281 freedaent(devalloc_t
*dap
)
285 _kva_free(dap
->da_devopts
);
286 dap
->da_devopts
= NULL
;
291 * checks if device_allocate has string DEVICE_ALLOCATION=ON or
292 * DEVICE_ALLOCATION=OFF string in it.
293 * returns 1 if the string is DEVICE_ALLOCATION=ON, 0 if it is
294 * DEVICE_ALLOCATION=OFF, -1 if neither string present.
300 char line1
[DA_BUFSIZE
+ 1];
301 struct _dabuff
*_da
= _daalloc();
304 if ((_da
== NULL
) || (daf
== NULL
)) {
308 while (getdadmline(line1
, (int)sizeof (line1
), daf
) != 0) {
309 if (strncmp(line1
, DA_ON_STR
, (strlen(DA_ON_STR
) - 1)) == 0) {
312 } else if (strncmp(line1
, DA_OFF_STR
,
313 (strlen(DA_OFF_STR
) - 1)) == 0) {
325 * When first called, returns a pointer to the first devalloc_t
326 * structure in device_allocate; thereafter, it returns a pointer to the
327 * next devalloc_t structure in the file. Thus, successive calls can be
328 * used to search the entire file.
329 * call to getdaent should be bracketed by setdaent and enddaent.
330 * returns NULL on error.
335 char line1
[DA_BUFSIZE
+ 1];
337 struct _dabuff
*_da
= _daalloc();
339 if ((_da
== 0) || (daf
== NULL
))
342 while (getdadmline(line1
, (int)sizeof (line1
), daf
) != 0) {
343 if ((strncmp(line1
, DA_ON_STR
, (strlen(DA_ON_STR
) - 1)) == 0) ||
344 (strncmp(line1
, DA_OFF_STR
, (strlen(DA_OFF_STR
) - 1)) == 0))
346 if ((da
= da_interpret(line1
)) == NULL
)
356 * searches from the beginning of device_allocate for the device specified
358 * call to getdanam should be bracketed by setdaent and enddaent.
359 * returns pointer to devalloc_t for the device if it is found, else
360 * returns NULL if device not found or in case of error.
365 char line
[DA_BUFSIZE
+ 1];
367 struct _dabuff
*_da
= _daalloc();
369 if ((name
== NULL
) || (_da
== 0) || (daf
== NULL
))
372 while (getdadmline(line
, (int)sizeof (line
), daf
) != 0) {
373 if (strstr(line
, name
) == NULL
)
375 if ((da
= da_interpret(line
)) == NULL
)
377 if (da_matchname(da
, name
)) {
389 * searches from the beginning of device_allocate for the device specified
391 * call to getdatype should be bracketed by setdaent and enddaent.
392 * returns pointer to devalloc_t for the device if it is found, else
393 * returns NULL if device not found or in case of error.
396 getdatype(char *type
)
398 char line1
[DA_BUFSIZE
+ 1];
400 struct _dabuff
*_da
= _daalloc();
402 if ((type
== NULL
) || (_da
== NULL
) || (daf
== NULL
))
405 while (getdadmline(line1
, (int)sizeof (line1
), daf
) != 0) {
406 if (strstr(line1
, type
) == NULL
)
408 if ((da
= da_interpret(line1
)) == NULL
)
410 if (da_matchtype(da
, type
))
420 * checks if the specified devalloc_t is for the device specified.
421 * returns 1 if it is, else returns 0.
424 da_matchname(devalloc_t
*dap
, char *name
)
426 if (dap
->da_devname
== NULL
)
429 return ((strcmp(dap
->da_devname
, name
) == 0));
434 * checks if the specified devalloc_t is for the device type specified.
435 * returns 1 if match found, else, returns 0.
438 da_matchtype(devalloc_t
*da
, char *type
)
440 if (da
->da_devtype
== NULL
)
443 return ((strcmp(da
->da_devtype
, type
) == 0));
448 * calls da_matchname or da_matchdev as appropriate.
451 da_match(devalloc_t
*dap
, da_args
*dargs
)
453 if (dargs
->devinfo
->devname
)
454 return (da_matchname(dap
, dargs
->devinfo
->devname
));
455 else if (dargs
->devinfo
->devtype
)
456 return (da_matchtype(dap
, dargs
->devinfo
->devtype
));
463 * parses val and initializes pointers in devalloc_t.
464 * returns pointer to parsed devalloc_t entry, else returns NULL on error.
467 da_interpret(char *val
)
469 struct _dabuff
*_da
= _daalloc();
478 (void) strcpy(interpdaline
, val
);
479 interpdevalloc
.da_devname
= getdadmfield(interpdaline
, KV_DELIMITER
);
480 interpdevalloc
.da_devtype
= getdadmfield(NULL
, KV_DELIMITER
);
481 opts
= getdadmfield(NULL
, KV_DELIMITER
);
482 (void) getdadmfield(NULL
, KV_DELIMITER
); /* reserved field */
483 interpdevalloc
.da_devauth
= getdadmfield(NULL
, KV_DELIMITER
);
484 interpdevalloc
.da_devexec
= getdadmfield(NULL
, KV_DELIMITER
);
485 interpdevalloc
.da_devopts
= NULL
;
486 if (interpdevalloc
.da_devname
== NULL
||
487 interpdevalloc
.da_devtype
== NULL
)
489 if ((opts
!= NULL
) &&
490 (strncmp(opts
, DA_RESERVED
, strlen(DA_RESERVED
)) != 0)) {
491 interpdevalloc
.da_devopts
=
492 _str2kva(opts
, KV_ASSIGN
, KV_TOKEN_DELIMIT
);
494 /* remove any extraneous whitespace in the options */
495 if ((kvap
= interpdevalloc
.da_devopts
) != NULL
) {
496 for (i
= 0, kvp
= kvap
->data
; i
< kvap
->length
; i
++, kvp
++) {
497 (void) pack_white(kvp
->key
);
498 (void) pack_white(kvp
->value
);
502 if (system_labeled
) {
503 /* if label range is not defined, use the default range. */
505 char *minstr
= NULL
, *maxstr
= NULL
;
507 kv_t
*ndata
= NULL
, *odata
= NULL
;
510 nlen
= 2; /* minlabel, maxlabel */
512 nlen
+= kvap
->length
;
513 if ((minstr
= kva_match(kvap
, DAOPT_MINLABEL
)) == NULL
)
515 if ((maxstr
= kva_match(kvap
, DAOPT_MAXLABEL
)) == NULL
)
518 if ((minstr
!= NULL
) && (maxstr
!= NULL
))
520 * label range provided; we don't need to construct
524 nkvap
= _new_kva(nlen
);
527 for (i
= 0; i
< kvap
->length
; i
++) {
529 ndata
[i
].key
= _strdup_null(odata
[i
].key
);
530 ndata
[i
].value
= _strdup_null(odata
[i
].value
);
534 if (minstr
== NULL
) {
535 ndata
[i
].key
= strdup(DAOPT_MINLABEL
);
536 ndata
[i
].value
= strdup(DA_DEFAULT_MIN
);
540 if (maxstr
== NULL
) {
541 ndata
[i
].key
= strdup(DAOPT_MAXLABEL
);
542 ndata
[i
].value
= strdup(DA_DEFAULT_MAX
);
545 interpdevalloc
.da_devopts
= nkvap
;
549 return (&interpdevalloc
);