| /* |
| * CDDL HEADER START |
| * |
| * The contents of this file are subject to the terms of the |
| * Common Development and Distribution License (the "License"). |
| * You may not use this file except in compliance with the License. |
| * |
| * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE |
| * or http://www.opensolaris.org/os/licensing. |
| * See the License for the specific language governing permissions |
| * and limitations under the License. |
| * |
| * When distributing Covered Code, include this CDDL HEADER in each |
| * file and include the License file at usr/src/OPENSOLARIS.LICENSE. |
| * If applicable, add the following below this CDDL HEADER, with the |
| * fields enclosed by brackets "[]" replaced with your own identifying |
| * information: Portions Copyright [yyyy] [name of copyright owner] |
| * |
| * CDDL HEADER END |
| */ |
| /* |
| * Copyright 2006 Sun Microsystems, Inc. All rights reserved. |
| * Use is subject to license terms. |
| */ |
| |
| #pragma ident "%Z%%M% %I% %E% SMI" |
| |
| #include <string.h> |
| #include <stdlib.h> |
| #include <bsm/devices.h> |
| #include <bsm/devalloc.h> |
| |
| char *strtok_r(char *, const char *, char **); |
| |
| /* externs from getdaent.c */ |
| extern char *trim_white(char *); |
| extern int pack_white(char *); |
| extern char *getdadmfield(char *, char *); |
| extern int getdadmline(char *, int, FILE *); |
| |
| extern char *_strdup_null(char *); |
| |
| static struct _dadefbuff { |
| FILE *_dadeff; |
| /* pointer into /etc/security/tsol/devalloc_defaults */ |
| da_defs_t _interpdadefs; |
| char _interpdadefline[DA_BUFSIZE + 1]; |
| char *_DADEFS; |
| } *__dadefbuff; |
| |
| #define dadeff (_df->_dadeff) |
| #define interpdadefs (_df->_interpdadefs) |
| #define interpdadefline (_df->_interpdadefline) |
| #define DADEFS_FILE (_df->_DADEFS) |
| |
| static da_defs_t *dadef_interpret(char *); |
| int dadef_matchtype(da_defs_t *, char *); |
| |
| /* |
| * _dadefalloc - |
| * allocates common buffers and structures. |
| * returns pointer to the new structure, else returns NULL on error. |
| */ |
| static struct _dadefbuff * |
| _dadefalloc(void) |
| { |
| struct _dadefbuff *_df = __dadefbuff; |
| |
| if (_df == NULL) { |
| _df = (struct _dadefbuff *)calloc((unsigned)1, |
| (unsigned)sizeof (*__dadefbuff)); |
| if (_df == NULL) |
| return (NULL); |
| DADEFS_FILE = "/etc/security/tsol/devalloc_defaults"; |
| __dadefbuff = _df; |
| } |
| |
| return (__dadefbuff); |
| } |
| |
| /* |
| * setdadefent - |
| * rewinds devalloc_defaults file to the begining. |
| */ |
| |
| void |
| setdadefent(void) |
| { |
| struct _dadefbuff *_df = _dadefalloc(); |
| |
| if (_df == NULL) |
| return; |
| if (dadeff == NULL) |
| dadeff = fopen(DADEFS_FILE, "r"); |
| else |
| rewind(dadeff); |
| } |
| |
| /* |
| * enddadefent - |
| * closes devalloc_defaults file. |
| */ |
| |
| void |
| enddadefent(void) |
| { |
| struct _dadefbuff *_df = _dadefalloc(); |
| |
| if (_df == NULL) |
| return; |
| if (dadeff != NULL) { |
| (void) fclose(dadeff); |
| dadeff = NULL; |
| } |
| } |
| |
| void |
| freedadefent(da_defs_t *da_def) |
| { |
| if (da_def == NULL) |
| return; |
| _kva_free(da_def->devopts); |
| da_def->devopts = NULL; |
| } |
| |
| /* |
| * getdadefent - |
| * When first called, returns a pointer to the first da_defs_t |
| * structure in devalloc_defaults; thereafter, it returns a pointer to the |
| * next da_defs_t structure in the file. Thus, successive calls can be |
| * used to search the entire file. |
| * call to getdadefent should be bracketed by setdadefent and enddadefent. |
| * returns NULL on error. |
| */ |
| da_defs_t * |
| getdadefent(void) |
| { |
| char line1[DA_BUFSIZE + 1]; |
| da_defs_t *da_def; |
| struct _dadefbuff *_df = _dadefalloc(); |
| |
| if ((_df == 0) || (dadeff == NULL)) |
| return (NULL); |
| |
| while (getdadmline(line1, (int)sizeof (line1), dadeff) != 0) { |
| if ((da_def = dadef_interpret(line1)) == NULL) |
| continue; |
| return (da_def); |
| } |
| |
| return (NULL); |
| } |
| |
| /* |
| * getdadeftype - |
| * searches from the beginning of devalloc_defaults for the device |
| * specified by its type. |
| * call to getdadeftype should be bracketed by setdadefent and enddadefent. |
| * returns pointer to da_defs_t for the device if it is found, else |
| * returns NULL if device not found or in case of error. |
| */ |
| da_defs_t * |
| getdadeftype(char *type) |
| { |
| char line1[DA_BUFSIZE + 1]; |
| da_defs_t *da_def; |
| struct _dadefbuff *_df = _dadefalloc(); |
| |
| if ((type == NULL) || (_df == NULL) || (dadeff == NULL)) |
| return (NULL); |
| |
| while (getdadmline(line1, (int)sizeof (line1), dadeff) != 0) { |
| if (strstr(line1, type) == NULL) |
| continue; |
| if ((da_def = dadef_interpret(line1)) == NULL) |
| continue; |
| if (dadef_matchtype(da_def, type)) |
| return (da_def); |
| freedadefent(da_def); |
| } |
| |
| return (NULL); |
| } |
| |
| /* |
| * dadef_matchtype - |
| * checks if the specified da_defs_t is for the device type specified. |
| * returns 1 if match found, else, returns 0. |
| */ |
| int |
| dadef_matchtype(da_defs_t *da_def, char *type) |
| { |
| if (da_def->devtype == NULL) |
| return (0); |
| |
| return ((strcmp(da_def->devtype, type) == 0)); |
| } |
| |
| /* |
| * dadef_interpret - |
| * parses val and initializes pointers in da_defs_t. |
| * returns pointer to parsed da_defs_t entry, else returns NULL on error. |
| */ |
| static da_defs_t * |
| dadef_interpret(char *val) |
| { |
| struct _dadefbuff *_df = _dadefalloc(); |
| int i; |
| char *opts; |
| kva_t *kvap; |
| kv_t *kvp; |
| |
| if (_df == NULL) |
| return (NULL); |
| |
| (void) strcpy(interpdadefline, val); |
| interpdadefs.devtype = getdadmfield(interpdadefline, KV_TOKEN_DELIMIT); |
| opts = getdadmfield(NULL, KV_TOKEN_DELIMIT); |
| interpdadefs.devopts = NULL; |
| if (interpdadefs.devtype == NULL) |
| return (NULL); |
| if (opts != NULL) |
| interpdadefs.devopts = |
| _str2kva(opts, KV_ASSIGN, KV_DELIMITER); |
| /* remove any extraneous whitespace in the options */ |
| if ((kvap = interpdadefs.devopts) != NULL) { |
| for (i = 0, kvp = kvap->data; i < kvap->length; i++, kvp++) { |
| (void) pack_white(kvp->key); |
| (void) pack_white(kvp->value); |
| } |
| } |
| |
| return (&interpdadefs); |
| } |