2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A/*
2N/A * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
2N/A * Use is subject to license terms.
2N/A */
2N/A
2N/A
2N/A/*
2N/A * Miscellaneous user interfaces to trusted label functions.
2N/A *
2N/A */
2N/A
2N/A
2N/A#include <ctype.h>
2N/A#include <stdlib.h>
2N/A#include <strings.h>
2N/A
2N/A#include <sys/mman.h>
2N/A
2N/A#include <tsol/label.h>
2N/A
2N/A#include "labeld.h"
2N/A#include "clnt.h"
2N/A#include <sys/tsol/label_macro.h>
2N/A#include <secdb.h>
2N/A#include <user_attr.h>
2N/A
2N/Astatic bslabel_t slow, shigh; /* static Admin Low and High SLs */
2N/Astatic bclear_t clow, chigh; /* static Admin Low and High CLRs */
2N/A
2N/Astatic char color[MAXCOLOR];
2N/A
2N/A
2N/A#define incall callp->param.acall.cargs.inset_arg
2N/A#define inret callp->param.aret.rvals.inset_ret
2N/A/*
2N/A * blinset - Check in a label set.
2N/A *
2N/A * Entry label = Sensitivity Label to check.
2N/A * id = Label set identifier of set to check.
2N/A *
2N/A * Exit None.
2N/A *
2N/A * Returns -1, If label set unavailable, or server failure.
2N/A * 0, If label not in label set.
2N/A * 1, If label is in the label set.
2N/A *
2N/A * Calls __call_labeld(BLINSET), BLTYPE, BSLLOW, BSLHIGH.
2N/A *
2N/A * Uses slow, shigh.
2N/A */
2N/A
2N/Aint
2N/Ablinset(const bslabel_t *label, const set_id *id)
2N/A{
2N/A if (id->type == SYSTEM_ACCREDITATION_RANGE) {
2N/A if (!BLTYPE(&slow, SUN_SL_ID)) {
2N/A /* initialize static labels. */
2N/A
2N/A BSLLOW(&slow);
2N/A BSLHIGH(&shigh);
2N/A }
2N/A
2N/A if (BLTYPE(label, SUN_SL_ID) &&
2N/A (BLEQUAL(label, &slow) || BLEQUAL(label, &shigh)))
2N/A
2N/A return (1);
2N/A }
2N/A if (id->type == USER_ACCREDITATION_RANGE ||
2N/A id->type == SYSTEM_ACCREDITATION_RANGE) {
2N/A labeld_data_t call;
2N/A labeld_data_t *callp = &call;
2N/A size_t bufsize = sizeof (labeld_data_t);
2N/A size_t datasize = CALL_SIZE(inset_call_t, 0);
2N/A
2N/A call.callop = BLINSET;
2N/A incall.label = *label;
2N/A incall.type = id->type;
2N/A
2N/A if (__call_labeld(&callp, &bufsize, &datasize) != SUCCESS) {
2N/A /* process error */
2N/A
2N/A return (-1);
2N/A }
2N/A return (inret.inset);
2N/A } else {
2N/A /*
2N/A * Only System and User Accreditation Ranges presently
2N/A * implemented.
2N/A */
2N/A return (-1);
2N/A }
2N/A}
2N/A#undef incall
2N/A#undef inret
2N/A
2N/A#define slvcall callp->param.acall.cargs.slvalid_arg
2N/A#define slvret callp->param.aret.rvals.slvalid_ret
2N/A/*
2N/A * bslvalid - Check Sensitivity Label for validity.
2N/A *
2N/A * Entry label = Sensitivity Label to check.
2N/A *
2N/A * Exit None.
2N/A *
2N/A * Returns -1, If unable to access label encodings file, or server failure.
2N/A * 0, If label not valid.
2N/A * 1, If label is valid.
2N/A *
2N/A * Calls __call_labeld(BSLVALID), BLTYPE, BSLLOW, BSLHIGH.
2N/A *
2N/A * Uses slow, shigh.
2N/A *
2N/A */
2N/A
2N/Aint
2N/Abslvalid(const bslabel_t *label)
2N/A{
2N/A labeld_data_t call;
2N/A labeld_data_t *callp = &call;
2N/A size_t bufsize = sizeof (labeld_data_t);
2N/A size_t datasize = CALL_SIZE(slvalid_call_t, 0);
2N/A
2N/A if (!BLTYPE(&slow, SUN_SL_ID)) {
2N/A /* initialize static labels. */
2N/A
2N/A BSLLOW(&slow);
2N/A BSLHIGH(&shigh);
2N/A }
2N/A
2N/A if (BLTYPE(label, SUN_SL_ID) &&
2N/A (BLEQUAL(label, &slow) || BLEQUAL(label, &shigh))) {
2N/A
2N/A return (1);
2N/A }
2N/A
2N/A call.callop = BSLVALID;
2N/A slvcall.label = *label;
2N/A
2N/A if (__call_labeld(&callp, &bufsize, &datasize) != SUCCESS) {
2N/A /* process error */
2N/A
2N/A return (-1);
2N/A }
2N/A return (slvret.valid);
2N/A}
2N/A#undef slvcall
2N/A#undef slvret
2N/A
2N/A#define clrvcall callp->param.acall.cargs.clrvalid_arg
2N/A#define clrvret callp->param.aret.rvals.clrvalid_ret
2N/A/*
2N/A * bclearvalid - Check Clearance for validity.
2N/A *
2N/A * Entry clearance = Clearance to check.
2N/A *
2N/A * Exit None.
2N/A *
2N/A * Returns -1, If unable to access label encodings file, or server failure.
2N/A * 0, If label not valid.
2N/A * 1, If label is valid.
2N/A *
2N/A * Calls __call_labeld(BCLEARVALID), BLTYPE, BCLEARLOW, BCLEARHIGH.
2N/A *
2N/A * Uses clow, chigh.
2N/A *
2N/A */
2N/A
2N/Aint
2N/Abclearvalid(const bclear_t *clearance)
2N/A{
2N/A labeld_data_t call;
2N/A labeld_data_t *callp = &call;
2N/A size_t bufsize = sizeof (labeld_data_t);
2N/A size_t datasize = CALL_SIZE(clrvalid_call_t, 0);
2N/A
2N/A if (!BLTYPE(&clow, SUN_CLR_ID)) {
2N/A /* initialize static labels. */
2N/A
2N/A BCLEARLOW(&clow);
2N/A BCLEARHIGH(&chigh);
2N/A }
2N/A
2N/A if (BLTYPE(clearance, SUN_CLR_ID) &&
2N/A (BLEQUAL(clearance, &clow) || BLEQUAL(clearance, &chigh))) {
2N/A
2N/A return (1);
2N/A }
2N/A
2N/A call.callop = BCLEARVALID;
2N/A clrvcall.clear = *clearance;
2N/A
2N/A if (__call_labeld(&callp, &bufsize, &datasize) != SUCCESS) {
2N/A /* process error */
2N/A
2N/A return (-1);
2N/A }
2N/A return (clrvret.valid);
2N/A}
2N/A#undef clrvcall
2N/A#undef clrvret
2N/A
2N/A#define inforet callp->param.aret.rvals.info_ret
2N/A/*
2N/A * labelinfo - Get information about the label encodings file.
2N/A *
2N/A * Entry info = Address of label_info structure to update.
2N/A *
2N/A * Exit info = Updated.
2N/A *
2N/A * Returns -1, If unable to access label encodings file, or server failure.
2N/A * 1, If successful.
2N/A *
2N/A * Calls __call_labeld(LABELINFO).
2N/A */
2N/A
2N/Aint
2N/Alabelinfo(struct label_info *info)
2N/A{
2N/A labeld_data_t call;
2N/A labeld_data_t *callp = &call;
2N/A size_t bufsize = sizeof (labeld_data_t);
2N/A size_t datasize = CALL_SIZE(info_call_t, 0);
2N/A int rval;
2N/A
2N/A call.callop = LABELINFO;
2N/A
2N/A if ((rval = __call_labeld(&callp, &bufsize, &datasize)) != SUCCESS) {
2N/A /* process error */
2N/A
2N/A return (-1);
2N/A }
2N/A *info = inforet.info;
2N/A return (rval);
2N/A}
2N/A#undef inforet
2N/A
2N/A#define lvret callp->param.aret.rvals.vers_ret
2N/A/*
2N/A * labelvers - Get version string of the label encodings file.
2N/A *
2N/A * Entry version = Address of string pointer to return.
2N/A * len = Length of string if pre-allocated.
2N/A *
2N/A * Exit version = Updated.
2N/A *
2N/A * Returns -1, If unable to access label encodings file, or server failure.
2N/A * 0, If unable to allocate version string,
2N/A * or pre-allocated version string to short
2N/A * (and **version = '\0').
2N/A * length (including null) of version string, If successful.
2N/A *
2N/A * Calls __call_labeld(LABELVERS)
2N/A * malloc, strlen.
2N/A */
2N/A
2N/Assize_t
2N/Alabelvers(char **version, size_t len)
2N/A{
2N/A labeld_data_t call;
2N/A labeld_data_t *callp = &call;
2N/A size_t bufsize = sizeof (labeld_data_t);
2N/A size_t datasize = CALL_SIZE(vers_call_t, 0);
2N/A size_t ver_len;
2N/A
2N/A call.callop = LABELVERS;
2N/A
2N/A if (__call_labeld(&callp, &bufsize, &datasize) != SUCCESS) {
2N/A
2N/A if (callp != &call)
2N/A /* release return buffer */
2N/A (void) munmap((void *)callp, bufsize);
2N/A return (-1);
2N/A }
2N/A
2N/A /* unpack length */
2N/A
2N/A ver_len = strlen(lvret.vers) + 1;
2N/A if (*version == NULL) {
2N/A if ((*version = malloc(ver_len)) == NULL) {
2N/A if (callp != &call)
2N/A /* release return buffer */
2N/A (void) munmap((void *)callp, bufsize);
2N/A return (0);
2N/A }
2N/A } else if (ver_len > len) {
2N/A **version = '\0';
2N/A if (callp != &call)
2N/A /* release return buffer */
2N/A (void) munmap((void *)callp, bufsize);
2N/A return (0);
2N/A }
2N/A (void) strcpy(*version, lvret.vers);
2N/A
2N/A if (callp != &call)
2N/A /* release return buffer */
2N/A (void) munmap((void *)callp, bufsize);
2N/A return (ver_len);
2N/A} /* labelvers */
2N/A#undef lvret
2N/A
2N/A#define ccall callp->param.acall.cargs.color_arg
2N/A#define cret callp->param.aret.rvals.color_ret
2N/A/*
2N/A * bltocolor - get ASCII color name of label.
2N/A *
2N/A * Entry label = Sensitivity Level of color to get.
2N/A * size = Size of the color_name array.
2N/A * color_name = Storage for ASCII color name string to be returned.
2N/A *
2N/A * Exit None.
2N/A *
2N/A * Returns NULL, If error (label encodings file not accessible,
2N/A * invalid label, no color for this label).
2N/A * Address of color_name parameter containing ASCII color name
2N/A * defined for the label.
2N/A *
2N/A * Calls __call_labeld(BLTOCOLOR), strlen.
2N/A */
2N/A
2N/Achar *
2N/Abltocolor_r(const blevel_t *label, size_t size, char *color_name)
2N/A{
2N/A labeld_data_t call;
2N/A labeld_data_t *callp = &call;
2N/A size_t bufsize = sizeof (labeld_data_t);
2N/A size_t datasize = CALL_SIZE(color_call_t, 0);
2N/A char *colorp;
2N/A
2N/A call.callop = BLTOCOLOR;
2N/A ccall.label = *label;
2N/A
2N/A if ((__call_labeld(&callp, &bufsize, &datasize) != SUCCESS) ||
2N/A (callp->reterr != 0) ||
2N/A (strlen(cret.color) >= size)) {
2N/A
2N/A if (callp != &call)
2N/A /* release return buffer */
2N/A (void) munmap((void *)callp, bufsize);
2N/A return (NULL);
2N/A }
2N/A
2N/A colorp = strcpy(color_name, cret.color);
2N/A
2N/A if (callp != &call)
2N/A /* release return buffer */
2N/A (void) munmap((void *)callp, bufsize);
2N/A return (colorp);
2N/A} /* bltocolor_r */
2N/A#undef ccall
2N/A#undef cret
2N/A
2N/A/*
2N/A * bltocolor - get ASCII color name of label.
2N/A *
2N/A * Entry label = Sensitivity Level of color to get.
2N/A *
2N/A * Exit None.
2N/A *
2N/A * Returns NULL, If error (label encodings file not accessible,
2N/A * invalid label, no color for this label).
2N/A * Address of statically allocated string containing ASCII
2N/A * color name defined for the classification contained
2N/A * in label.
2N/A *
2N/A * Uses color.
2N/A *
2N/A * Calls bltocolor_r.
2N/A */
2N/A
2N/Achar *
2N/Abltocolor(const blevel_t *label)
2N/A{
2N/A return (bltocolor_r(label, sizeof (color), color));
2N/A} /* bltocolor */
2N/A
2N/Ablevel_t *
2N/Ablabel_alloc(void)
2N/A{
2N/A return (m_label_alloc(MAC_LABEL));
2N/A}
2N/A
2N/Avoid
2N/Ablabel_free(blevel_t *label_p)
2N/A{
2N/A free(label_p);
2N/A}
2N/A
2N/Asize32_t
2N/Ablabel_size(void)
2N/A{
2N/A return (sizeof (blevel_t));
2N/A}
2N/A
2N/A/*
2N/A * getuserrange - get label range for user
2N/A *
2N/A * Entry username of user
2N/A *
2N/A * Exit None.
2N/A *
2N/A * Returns NULL, If memory allocation failure or userdefs failure.
2N/A * otherwise returns the allocates m_range_t with the
2N/A * user's min and max labels set.
2N/A */
2N/A
2N/Am_range_t *
2N/Agetuserrange(const char *username)
2N/A{
2N/A char *kv_str = NULL;
2N/A userattr_t *userp = NULL;
2N/A m_range_t *range;
2N/A m_label_t *def_min, *def_clr;
2N/A
2N/A /*
2N/A * Get some memory
2N/A */
2N/A
2N/A if ((range = malloc(sizeof (m_range_t))) == NULL) {
2N/A return (NULL);
2N/A }
2N/A if ((range->lower_bound = m_label_alloc(MAC_LABEL)) == NULL) {
2N/A free(range);
2N/A return (NULL);
2N/A }
2N/A def_min = range->lower_bound;
2N/A if ((range->upper_bound = m_label_alloc(USER_CLEAR)) == NULL) {
2N/A m_label_free(range->lower_bound);
2N/A free(range);
2N/A return (NULL);
2N/A }
2N/A def_clr = range->upper_bound;
2N/A
2N/A /* If the user has an explicit min_label or clearance, use it. */
2N/A if ((userp = getusernam(username)) != NULL) {
2N/A if ((kv_str = kva_match(userp->attr, USERATTR_MINLABEL))
2N/A != NULL) {
2N/A (void) str_to_label(kv_str, &range->lower_bound,
2N/A MAC_LABEL, L_NO_CORRECTION, NULL);
2N/A def_min = NULL; /* don't get default later */
2N/A }
2N/A if ((kv_str = kva_match(userp->attr, USERATTR_CLEARANCE))
2N/A != NULL) {
2N/A (void) str_to_label(kv_str, &range->upper_bound,
2N/A USER_CLEAR, L_NO_CORRECTION, NULL);
2N/A def_clr = NULL; /* don't get default later */
2N/A }
2N/A free_userattr(userp);
2N/A }
2N/A if (def_min || def_clr) {
2N/A /* Need to use system default clearance and/or min_label */
2N/A if ((userdefs(def_min, def_clr)) == -1) {
2N/A m_label_free(range->lower_bound);
2N/A m_label_free(range->upper_bound);
2N/A free(range);
2N/A return (NULL);
2N/A }
2N/A }
2N/A
2N/A return (range);
2N/A}