| /* |
| * 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" |
| |
| |
| /* |
| * Miscellaneous user interfaces to trusted label functions. |
| * |
| */ |
| |
| |
| #include <ctype.h> |
| #include <stdlib.h> |
| #include <strings.h> |
| |
| #include <sys/mman.h> |
| |
| #include <tsol/label.h> |
| |
| #include "labeld.h" |
| #include "clnt.h" |
| #include <sys/tsol/label_macro.h> |
| #include <secdb.h> |
| #include <user_attr.h> |
| |
| static bslabel_t slow, shigh; /* static Admin Low and High SLs */ |
| static bclear_t clow, chigh; /* static Admin Low and High CLRs */ |
| |
| static char color[MAXCOLOR]; |
| |
| |
| #define incall callp->param.acall.cargs.inset_arg |
| #define inret callp->param.aret.rvals.inset_ret |
| /* |
| * blinset - Check in a label set. |
| * |
| * Entry label = Sensitivity Label to check. |
| * id = Label set identifier of set to check. |
| * |
| * Exit None. |
| * |
| * Returns -1, If label set unavailable, or server failure. |
| * 0, If label not in label set. |
| * 1, If label is in the label set. |
| * |
| * Calls __call_labeld(BLINSET), BLTYPE, BSLLOW, BSLHIGH. |
| * |
| * Uses slow, shigh. |
| */ |
| |
| int |
| blinset(const bslabel_t *label, const set_id *id) |
| { |
| if (id->type == SYSTEM_ACCREDITATION_RANGE) { |
| if (!BLTYPE(&slow, SUN_SL_ID)) { |
| /* initialize static labels. */ |
| |
| BSLLOW(&slow); |
| BSLHIGH(&shigh); |
| } |
| |
| if (BLTYPE(label, SUN_SL_ID) && |
| (BLEQUAL(label, &slow) || BLEQUAL(label, &shigh))) |
| |
| return (1); |
| } |
| if (id->type == USER_ACCREDITATION_RANGE || |
| id->type == SYSTEM_ACCREDITATION_RANGE) { |
| labeld_data_t call; |
| labeld_data_t *callp = &call; |
| size_t bufsize = sizeof (labeld_data_t); |
| size_t datasize = CALL_SIZE(inset_call_t, 0); |
| |
| call.callop = BLINSET; |
| incall.label = *label; |
| incall.type = id->type; |
| |
| if (__call_labeld(&callp, &bufsize, &datasize) != SUCCESS) { |
| /* process error */ |
| |
| return (-1); |
| } |
| return (inret.inset); |
| } else { |
| /* |
| * Only System and User Accreditation Ranges presently |
| * implemented. |
| */ |
| return (-1); |
| } |
| } |
| #undef incall |
| #undef inret |
| |
| #define slvcall callp->param.acall.cargs.slvalid_arg |
| #define slvret callp->param.aret.rvals.slvalid_ret |
| /* |
| * bslvalid - Check Sensitivity Label for validity. |
| * |
| * Entry label = Sensitivity Label to check. |
| * |
| * Exit None. |
| * |
| * Returns -1, If unable to access label encodings file, or server failure. |
| * 0, If label not valid. |
| * 1, If label is valid. |
| * |
| * Calls __call_labeld(BSLVALID), BLTYPE, BSLLOW, BSLHIGH. |
| * |
| * Uses slow, shigh. |
| * |
| */ |
| |
| int |
| bslvalid(const bslabel_t *label) |
| { |
| labeld_data_t call; |
| labeld_data_t *callp = &call; |
| size_t bufsize = sizeof (labeld_data_t); |
| size_t datasize = CALL_SIZE(slvalid_call_t, 0); |
| |
| if (!BLTYPE(&slow, SUN_SL_ID)) { |
| /* initialize static labels. */ |
| |
| BSLLOW(&slow); |
| BSLHIGH(&shigh); |
| } |
| |
| if (BLTYPE(label, SUN_SL_ID) && |
| (BLEQUAL(label, &slow) || BLEQUAL(label, &shigh))) { |
| |
| return (1); |
| } |
| |
| call.callop = BSLVALID; |
| slvcall.label = *label; |
| |
| if (__call_labeld(&callp, &bufsize, &datasize) != SUCCESS) { |
| /* process error */ |
| |
| return (-1); |
| } |
| return (slvret.valid); |
| } |
| #undef slvcall |
| #undef slvret |
| |
| #define clrvcall callp->param.acall.cargs.clrvalid_arg |
| #define clrvret callp->param.aret.rvals.clrvalid_ret |
| /* |
| * bclearvalid - Check Clearance for validity. |
| * |
| * Entry clearance = Clearance to check. |
| * |
| * Exit None. |
| * |
| * Returns -1, If unable to access label encodings file, or server failure. |
| * 0, If label not valid. |
| * 1, If label is valid. |
| * |
| * Calls __call_labeld(BCLEARVALID), BLTYPE, BCLEARLOW, BCLEARHIGH. |
| * |
| * Uses clow, chigh. |
| * |
| */ |
| |
| int |
| bclearvalid(const bclear_t *clearance) |
| { |
| labeld_data_t call; |
| labeld_data_t *callp = &call; |
| size_t bufsize = sizeof (labeld_data_t); |
| size_t datasize = CALL_SIZE(clrvalid_call_t, 0); |
| |
| if (!BLTYPE(&clow, SUN_CLR_ID)) { |
| /* initialize static labels. */ |
| |
| BCLEARLOW(&clow); |
| BCLEARHIGH(&chigh); |
| } |
| |
| if (BLTYPE(clearance, SUN_CLR_ID) && |
| (BLEQUAL(clearance, &clow) || BLEQUAL(clearance, &chigh))) { |
| |
| return (1); |
| } |
| |
| call.callop = BCLEARVALID; |
| clrvcall.clear = *clearance; |
| |
| if (__call_labeld(&callp, &bufsize, &datasize) != SUCCESS) { |
| /* process error */ |
| |
| return (-1); |
| } |
| return (clrvret.valid); |
| } |
| #undef clrvcall |
| #undef clrvret |
| |
| #define inforet callp->param.aret.rvals.info_ret |
| /* |
| * labelinfo - Get information about the label encodings file. |
| * |
| * Entry info = Address of label_info structure to update. |
| * |
| * Exit info = Updated. |
| * |
| * Returns -1, If unable to access label encodings file, or server failure. |
| * 1, If successful. |
| * |
| * Calls __call_labeld(LABELINFO). |
| */ |
| |
| int |
| labelinfo(struct label_info *info) |
| { |
| labeld_data_t call; |
| labeld_data_t *callp = &call; |
| size_t bufsize = sizeof (labeld_data_t); |
| size_t datasize = CALL_SIZE(info_call_t, 0); |
| int rval; |
| |
| call.callop = LABELINFO; |
| |
| if ((rval = __call_labeld(&callp, &bufsize, &datasize)) != SUCCESS) { |
| /* process error */ |
| |
| return (-1); |
| } |
| *info = inforet.info; |
| return (rval); |
| } |
| #undef inforet |
| |
| #define lvret callp->param.aret.rvals.vers_ret |
| /* |
| * labelvers - Get version string of the label encodings file. |
| * |
| * Entry version = Address of string pointer to return. |
| * len = Length of string if pre-allocated. |
| * |
| * Exit version = Updated. |
| * |
| * Returns -1, If unable to access label encodings file, or server failure. |
| * 0, If unable to allocate version string, |
| * or pre-allocated version string to short |
| * (and **version = '\0'). |
| * length (including null) of version string, If successful. |
| * |
| * Calls __call_labeld(LABELVERS) |
| * malloc, strlen. |
| */ |
| |
| ssize_t |
| labelvers(char **version, size_t len) |
| { |
| labeld_data_t call; |
| labeld_data_t *callp = &call; |
| size_t bufsize = sizeof (labeld_data_t); |
| size_t datasize = CALL_SIZE(vers_call_t, 0); |
| size_t ver_len; |
| |
| call.callop = LABELVERS; |
| |
| if (__call_labeld(&callp, &bufsize, &datasize) != SUCCESS) { |
| |
| if (callp != &call) |
| /* release return buffer */ |
| (void) munmap((void *)callp, bufsize); |
| return (-1); |
| } |
| |
| /* unpack length */ |
| |
| ver_len = strlen(lvret.vers) + 1; |
| if (*version == NULL) { |
| if ((*version = malloc(ver_len)) == NULL) { |
| if (callp != &call) |
| /* release return buffer */ |
| (void) munmap((void *)callp, bufsize); |
| return (0); |
| } |
| } else if (ver_len > len) { |
| **version = '\0'; |
| if (callp != &call) |
| /* release return buffer */ |
| (void) munmap((void *)callp, bufsize); |
| return (0); |
| } |
| (void) strcpy(*version, lvret.vers); |
| |
| if (callp != &call) |
| /* release return buffer */ |
| (void) munmap((void *)callp, bufsize); |
| return (ver_len); |
| } /* labelvers */ |
| #undef lvret |
| |
| #define ccall callp->param.acall.cargs.color_arg |
| #define cret callp->param.aret.rvals.color_ret |
| /* |
| * bltocolor - get ASCII color name of label. |
| * |
| * Entry label = Sensitivity Level of color to get. |
| * size = Size of the color_name array. |
| * color_name = Storage for ASCII color name string to be returned. |
| * |
| * Exit None. |
| * |
| * Returns NULL, If error (label encodings file not accessible, |
| * invalid label, no color for this label). |
| * Address of color_name parameter containing ASCII color name |
| * defined for the label. |
| * |
| * Calls __call_labeld(BLTOCOLOR), strlen. |
| */ |
| |
| char * |
| bltocolor_r(const blevel_t *label, size_t size, char *color_name) |
| { |
| labeld_data_t call; |
| labeld_data_t *callp = &call; |
| size_t bufsize = sizeof (labeld_data_t); |
| size_t datasize = CALL_SIZE(color_call_t, 0); |
| char *colorp; |
| |
| call.callop = BLTOCOLOR; |
| ccall.label = *label; |
| |
| if ((__call_labeld(&callp, &bufsize, &datasize) != SUCCESS) || |
| (callp->reterr != 0) || |
| (strlen(cret.color) >= size)) { |
| |
| if (callp != &call) |
| /* release return buffer */ |
| (void) munmap((void *)callp, bufsize); |
| return (NULL); |
| } |
| |
| colorp = strcpy(color_name, cret.color); |
| |
| if (callp != &call) |
| /* release return buffer */ |
| (void) munmap((void *)callp, bufsize); |
| return (colorp); |
| } /* bltocolor_r */ |
| #undef ccall |
| #undef cret |
| |
| /* |
| * bltocolor - get ASCII color name of label. |
| * |
| * Entry label = Sensitivity Level of color to get. |
| * |
| * Exit None. |
| * |
| * Returns NULL, If error (label encodings file not accessible, |
| * invalid label, no color for this label). |
| * Address of statically allocated string containing ASCII |
| * color name defined for the classification contained |
| * in label. |
| * |
| * Uses color. |
| * |
| * Calls bltocolor_r. |
| */ |
| |
| char * |
| bltocolor(const blevel_t *label) |
| { |
| return (bltocolor_r(label, sizeof (color), color)); |
| } /* bltocolor */ |
| |
| blevel_t * |
| blabel_alloc(void) |
| { |
| return (m_label_alloc(MAC_LABEL)); |
| } |
| |
| void |
| blabel_free(blevel_t *label_p) |
| { |
| free(label_p); |
| } |
| |
| size_t |
| blabel_size(void) |
| { |
| return (sizeof (blevel_t)); |
| } |
| |
| /* |
| * getuserrange - get label range for user |
| * |
| * Entry username of user |
| * |
| * Exit None. |
| * |
| * Returns NULL, If memory allocation failure or userdefs failure. |
| * otherwise returns the allocates m_range_t with the |
| * user's min and max labels set. |
| */ |
| |
| m_range_t * |
| getuserrange(const char *username) |
| { |
| char *kv_str = NULL; |
| userattr_t *userp = NULL; |
| m_range_t *range; |
| int err; |
| |
| /* |
| * Get some memory |
| */ |
| |
| if ((range = malloc(sizeof (m_range_t))) == NULL) { |
| return (NULL); |
| } |
| if ((range->lower_bound = m_label_alloc(MAC_LABEL)) == NULL) { |
| free(range); |
| return (NULL); |
| } |
| if ((range->upper_bound = m_label_alloc(USER_CLEAR)) == NULL) { |
| m_label_free(range->lower_bound); |
| free(range); |
| return (NULL); |
| } |
| /* |
| * Since user_attr entries are optional, start with |
| * the system default values |
| */ |
| if ((userdefs(range->lower_bound, range->upper_bound)) == -1) { |
| m_label_free(range->lower_bound); |
| m_label_free(range->upper_bound); |
| free(range); |
| return (NULL); |
| } |
| /* |
| * If the user has an explicit min_label or clearance, |
| * then use it instead. |
| */ |
| if ((userp = getusernam(username)) == NULL) { |
| return (range); |
| } |
| if ((kv_str = kva_match(userp->attr, USERATTR_MINLABEL)) != NULL) |
| (void) stobsl(kv_str, range->lower_bound, NO_CORRECTION, &err); |
| if ((kv_str = kva_match(userp->attr, USERATTR_CLEARANCE)) != NULL) |
| (void) stobclear(kv_str, range->upper_bound, NO_CORRECTION, |
| &err); |
| free_userattr(userp); |
| return (range); |
| } |