/*
* 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"
/*
* Label library contract private interfaces.
*
* Binary labels to String labels with dimming word lists.
* Dimming word list titles.
* Default user labels.
*/
#include <locale.h>
#include <stdlib.h>
#include <stdio.h>
#include <strings.h>
#include <sys/mman.h>
#include <tsol/label.h>
#include "clnt.h"
#include "labeld.h"
/*
* cvt memory:
*
* cvt: char *long_words[display_size]; Pointers to long words
* char *short_words[display_size]; Pointers to short words
* dim: char display[display_size]; Dim | Set
*
* strings associated with long and short words.
*
*/
/*
* Sensitivity Label words.
*/
static char *slcvt = NULL;
static int slcvtsize = 0;
static char *sldim;
static char *slstring = NULL;
static int slstringsize = 0;
static brange_t sbounds;
/*
* Clearance words.
*/
static char *clrcvt = NULL;
static int clrcvtsize = 0;
static char *clrdim;
static char *clrstring = NULL;
static int clrstringsize = 0;
static brange_t cbounds;
static
int
alloc_words(char **words, const size_t size)
{
if (*words == NULL) {
if ((*words = malloc(size)) == NULL)
return (0);
} else {
if ((*words = realloc(*words, size)) == NULL) {
return (0);
}
}
return (1);
}
/*
* build_strings - Build the static strings and dimming list for a
* converted label.
*
* Entry new_string = Newly converted string.
* new_words_size = Size of words associated with newly converted
* label.
* number_of_words = Number of words associated with newly
* converted label.
* full = 1, if static words lists to be updated.
* 0, if only string and dimming list to be updated.
*
* Exit static_string_size = Updated if needed.
* static_string = Updated to new label string.
* static_words_size = Updated if needed.
* static_words = Updated to new words list, if needed.
* static_dimming = Updated to new dimming state.
* long_words = Updated to new long words pointers, if needed.
* short_words = Updated to new short words pointers, if needed.
*
*
* Returns 0, If unable to allocate memory.
* 1, If successful.
*
* Calls alloc_string, alloc_words, memcpy, strcpy, strlen.
*/
static
int
build_strings(int *static_string_size, char **static_string, char *new_string,
int *static_words_size, int new_words_size, char **static_words,
char **static_dimming, int number_of_words, char *long_words,
char *short_words, char *dimming_list, int full)
{
char **l;
char **s;
char *w;
char *l_w = long_words;
char *s_w = short_words;
int i;
int len;
int newsize;
if (*static_string_size == 0) { /* Allocate string memory. */
if ((*static_string_size = alloc_string(static_string,
*static_string_size, 'C')) == 0)
/* can't get string memory for string */
return (0);
}
again:
if (*static_string_size < (int)strlen(new_string)+1) {
/* need longer string */
if ((newsize = alloc_string(static_string, *static_string_size,
'C')) == 0)
/* can't get more string memory */
return (0);
*static_string_size += newsize;
goto again;
}
bcopy(new_string, *static_string, strlen(new_string) + 1);
if (full) {
if (*static_words_size < new_words_size &&
!alloc_words(static_words, new_words_size)) {
/* can't get more words memory */
return (0);
} else {
*static_words_size = new_words_size;
}
/*LINTED*/
l = (char **)*static_words;
s = l + number_of_words;
*static_dimming = (char *)(s + number_of_words);
w = *static_dimming + number_of_words;
for (i = 0; i < number_of_words; i++) {
*l = w;
(void) strcpy(w, l_w);
w += (len = strlen(l_w) + 1);
l_w += len;
if (*s_w == '\000') {
*s = NULL;
s_w++;
} else {
*s = w;
(void) strcpy(w, s_w);
w += (len = strlen(s_w) + 1);
s_w += len;
}
l++;
s++;
} /* for each word entry */
} /* if (full) */
bcopy(dimming_list, *static_dimming, number_of_words);
return (1);
} /* build_strings */
#define bsfcall callp->param.acall.cargs.bslcvt_arg
#define bsfret callp->param.aret.rvals.bslcvt_ret
/*
* bslcvtfull - Convert Sensitivity Label and initialize static
* information.
*
* Entry label = Sensitivity Label to convert and get dimming list.
* This label should lie within the bounds or the
* results may not be meaningful.
* bounds = Lower and upper bounds for words lists. Must be
* dominated by clearance.
* flags = VIEW_INTERNAL, don't promote/demote admin low/high.
* VIEW_EXTERNAL, promote/demote admin low/high.
*
* Exit string = ASCII coded Sensitivity Label.
* long_words = Array of pointers to visible long word names.
* short_words = Array of pointers to visible short word names.
* display = Array of indicators as to whether the word is present
* in the converted label (CVT_SET), and/or changeable
* (CVT_DIM).
* first_compartment = Zero based index of first compartment.
* display_size = Number of entries in the display/words lists.
*
* Returns -1, If unable to access label encodings database, or
* invalid label.
* 0, If unable to allocate static memory.
* 1, If successful.
*
* Calls RPC - LABELS_BSLCONVERT, STTBLEVEL, SETBSLABEL, TCLNT,
* build_strings, clnt_call, clnt_perror.
*
* Uses sbounds, slrcvt, slrcvtsize, slrdim, slrstring,
* slrstringsize.
*/
int
bslcvtfull(const bslabel_t *label, const blrange_t *bounds, int flags,
char **string, char **long_words[], char **short_words[], char *display[],
int *first_compartment, int *display_size)
{
labeld_data_t call;
labeld_data_t *callp = &call;
size_t bufsize = sizeof (labeld_data_t);
size_t datasize = CALL_SIZE(bslcvt_call_t, 0);
int new_words_size;
int rval;
call.callop = BSLCVT;
bsfcall.label = *label;
bsfcall.bounds.upper_bound = *bounds->upper_bound;
bsfcall.bounds.lower_bound = *bounds->lower_bound;
bsfcall.flags = LABELS_FULL_CONVERT;
set_label_view(&bsfcall.flags, flags);
if ((rval = __call_labeld(&callp, &bufsize, &datasize)) == NOSERVER) {
#ifdef DEBUG
(void) fprintf(stderr, "No label server.\n");
#endif /* DEBUG */
return (-1);
} else if (rval != SUCCESS) {
return (-1);
} else {
if (callp->reterr != 0)
return (-1);
}
*first_compartment = bsfret.first_comp;
*display_size = bsfret.d_len;
new_words_size = bsfret.l_len + bsfret.s_len + bsfret.d_len +
(2 * sizeof (char *)) * bsfret.d_len;
if (build_strings(&slstringsize, &slstring, &bsfret.buf[bsfret.string],
&slcvtsize, new_words_size, &slcvt, &sldim, bsfret.d_len,
&bsfret.buf[bsfret.lwords], &bsfret.buf[bsfret.swords],
&bsfret.buf[bsfret.dim], 1) != 1) {
if (callp != &call)
/* release return buffer */
(void) munmap((void *)callp, bufsize);
return (0);
}
/* save for bslcvt call */
sbounds.upper_bound = *bounds->upper_bound;
sbounds.lower_bound = *bounds->lower_bound;
*string = slstring;
*display = sldim;
/*LINTED*/
*long_words = (char **)slcvt;
/*LINTED*/
*short_words = (char **)(slcvt + *display_size * sizeof (char *));
if (callp != &call)
/* release return buffer */
(void) munmap((void *)callp, bufsize);
return (1);
} /* bslcvtfull */
#undef bsfcall
#undef bsfret
#define bsccall callp->param.acall.cargs.bslcvt_arg
#define bscret callp->param.aret.rvals.bslcvt_ret
/*
* bslcvt - Convert Sensitivity Label and update dimming information.
*
* Entry label = Sensitivity Label to convert and get dimming list.
* This label should lie within the bounds of the
* corresponding bslcvtfull call or the results may
* not be meaningful.
* flags = VIEW_INTERNAL, don't promote/demote admin low/high.
* VIEW_EXTERNAL, promote/demote admin low/high.
*
* Exit string = ASCII coded Sensitivity Label.
* display = Array of indicators as to whether the word is present
* in the converted label (CVT_SET), and/or changeable
* (CVT_DIM).
*
* Returns -1, If unable to access label encodings database, or
* invalid label.
* 0, If unable to allocate static memory.
* 1, If successful.
*
* Calls RPC - LABELS_BSLCONVERT, SETBLEVEL, SETBSLABEL, build_strings
* clnt_call, clnt_perror.
*
* Uses sbounds, slrdim, slrstring.
*/
int
bslcvt(const bslabel_t *label, int flags, char **string, char *display[])
{
labeld_data_t call;
labeld_data_t *callp = &call;
size_t bufsize = sizeof (labeld_data_t);
size_t datasize = CALL_SIZE(bslcvt_call_t, 0);
int rval;
if (slcvt == NULL)
return (-1); /* conversion not initialized */
call.callop = BSLCVT;
bsccall.label = *label;
bsccall.bounds = sbounds; /* save from last bslcvtfull() call */
bsccall.flags = 0;
set_label_view(&bsccall.flags, flags);
if ((rval = __call_labeld(&callp, &bufsize, &datasize)) == NOSERVER) {
#ifdef DEBUG
(void) fprintf(stderr, "No label server.\n");
#endif /* DEBUG */
return (-1);
} else if (rval != SUCCESS) {
return (-1);
} else {
if (callp->reterr != 0)
return (-1);
}
if (build_strings(&slstringsize, &slstring, &bscret.buf[bscret.string],
&slcvtsize, 0, &slcvt, &sldim, bscret.d_len,
&bscret.buf[bscret.lwords], &bscret.buf[bscret.swords],
&bscret.buf[bscret.dim], 0) != 1) {
if (callp != &call)
/* release return buffer */
(void) munmap((void *)callp, bufsize);
return (0);
}
*string = slstring;
*display = sldim;
if (callp != &call)
/* release return buffer */
(void) munmap((void *)callp, bufsize);
return (1);
} /* bslcvt */
#undef bsccall
#undef bscret
#define bcfcall callp->param.acall.cargs.bclearcvt_arg
#define bcfret callp->param.aret.rvals.bclearcvt_ret
/*
* bclearcvtfull - Convert Clearance and initialize static information.
*
* Entry clearance = Clearance to convert and get dimming list.
* This clearance should lie within the bounds or
* the results may not be meaningful.
* bounds = Lower and upper bounds for words lists. Must be
* dominated by clearance.
* flags = VIEW_INTERNAL, don't promote/demote admin low/high.
* VIEW_EXTERNAL, promote/demote admin low/high.
*
* Exit string = ASCII coded Clearance.
* long_words = Array of pointers to visible long word names.
* short_words = Array of pointers to visible short word names.
* display = Array of indicators as to whether the word is present
* in the converted label (CVT_SET), and/or changeable
* (CVT_DIM).
* first_compartment = Zero based index of first compartment.
* display_size = Number of entries in the display/words lists.
*
* Returns -1, If unable to access label encodings database, or
* invalid label.
* 0, If unable to allocate static memory.
* 1, If successful.
*
* Calls RPC - LABELS_BCLEARCONVERT, SETBCLEAR, SETBLEVEL, TCLNT,
* build_strings, clnt_call, clnt_perror.
*
* Uses cbounds, clrcvt, clrcvtsize, clrdim, clrstring,
* clrstringsize.
*/
int
bclearcvtfull(const bclear_t *clearance, const blrange_t *bounds,
int flags, char **string, char **long_words[], char **short_words[],
char *display[], int *first_compartment, int *display_size)
{
labeld_data_t call;
labeld_data_t *callp = &call;
size_t bufsize = sizeof (labeld_data_t);
size_t datasize = CALL_SIZE(bclearcvt_call_t, 0);
int new_words_size;
int rval;
call.callop = BCLEARCVT;
bcfcall.clear = *clearance;
bcfcall.bounds.upper_bound = *bounds->upper_bound;
bcfcall.bounds.lower_bound = *bounds->lower_bound;
bcfcall.flags = LABELS_FULL_CONVERT;
set_label_view(&bcfcall.flags, flags);
if ((rval = __call_labeld(&callp, &bufsize, &datasize)) == NOSERVER) {
#ifdef DEBUG
(void) fprintf(stderr, "No label server.\n");
#endif /* DEBUG */
return (-1);
} else if (rval != SUCCESS) {
return (-1);
} else {
if (callp->reterr != 0)
return (-1);
}
*first_compartment = bcfret.first_comp;
*display_size = bcfret.d_len;
new_words_size = bcfret.l_len + bcfret.s_len + bcfret.d_len +
(2 * sizeof (char *)) * bcfret.d_len;
if (build_strings(&clrstringsize, &clrstring,
&bcfret.buf[bcfret.string],
&clrcvtsize, new_words_size, &clrcvt,
&clrdim, bcfret.d_len,
&bcfret.buf[bcfret.lwords], &bcfret.buf[bcfret.swords],
&bcfret.buf[bcfret.dim], 1) != 1) {
if (callp != &call)
/* release return buffer */
(void) munmap((void *)callp, bufsize);
return (0);
}
/* save for bclearcvt call */
cbounds.upper_bound = *bounds->upper_bound;
cbounds.lower_bound = *bounds->lower_bound;
*string = clrstring;
*display = clrdim;
/*LINTED*/
*long_words = (char **)clrcvt;
/*LINTED*/
*short_words = (char **)(clrcvt + *display_size * sizeof (char *));
if (callp != &call)
/* release return buffer */
(void) munmap((void *)callp, bufsize);
return (1);
} /* bclearcvtfull */
#undef bcfcall
#undef bcfret
#define bcccall callp->param.acall.cargs.bclearcvt_arg
#define bccret callp->param.aret.rvals.bclearcvt_ret
/*
* bclearcvt - Convert Clearance and update dimming inforamtion.
*
* Entry clearance = Clearance to convert and get dimming list.
* This clearance should lie within the bounds of the
* corresponding bclearcvtfull call or the results may
* not be meaningful.
* flags = VIEW_INTERNAL, don't promote/demote admin low/high.
* VIEW_EXTERNAL, promote/demote admin low/high.
*
* Exit string = ASCII coded Clearance.
* display = Array of indicators as to whether the word is present
* in the converted label (CVT_SET), and/or changeable
* (CVT_DIM).
*
* Returns -1, If unable to access label encodings database, or
* invalid label.
* 0, If unable to allocate static memory.
* 1, If successful.
*
* Calls RPC - LABELS_BCLEARCONVERT, SETBCLEAR, SETBLEVEL, build_strings,
* clnt_call, clnt_perror.
*
* Uses cbounds, clrdim, clrstring.
*/
int
bclearcvt(const bclear_t *clearance, int flags, char **string,
char *display[])
{
labeld_data_t call;
labeld_data_t *callp = &call;
size_t bufsize = sizeof (labeld_data_t);
size_t datasize = CALL_SIZE(bclearcvt_call_t, 0);
int rval;
if (clrcvt == NULL)
return (-1); /* conversion not initialized */
call.callop = BCLEARCVT;
bcccall.clear = *clearance;
bcccall.bounds = cbounds; /* save from last bslcvtfull() call */
bcccall.flags = 0;
set_label_view(&bcccall.flags, flags);
if ((rval = __call_labeld(&callp, &bufsize, &datasize)) == NOSERVER) {
#ifdef DEBUG
(void) fprintf(stderr, "No label server.\n");
#endif /* DEBUG */
return (-1);
} else if (rval != SUCCESS) {
return (-1);
} else {
if (callp->reterr != 0)
return (-1);
}
if (build_strings(&clrstringsize, &clrstring,
&bccret.buf[bccret.string],
&clrcvtsize, 0, &clrcvt, &clrdim, bccret.d_len,
&bccret.buf[bccret.lwords], &bccret.buf[bccret.swords],
&bccret.buf[bccret.dim], 0) != 1) {
if (callp != &call)
/* release return buffer */
(void) munmap((void *)callp, bufsize);
return (0);
}
*string = clrstring;
*display = clrdim;
if (callp != &call)
/* release return buffer */
(void) munmap((void *)callp, bufsize);
return (1);
} /* bclearcvt */
#undef bcccall
#undef bccret
#define lfret callp->param.aret.rvals.fields_ret
/*
* labelfields - Return names for the label fields.
*
* Entry None
*
* Exit fields = Updated.
*
* Returns -1, If unable to access label encodings file, or
* labels server failure.
* 0, If unable to allocate memory.
* 1, If successful.
*
* Calls __call_labeld(LABELFIELDS).
*/
int
labelfields(struct name_fields *fields)
{
labeld_data_t call;
labeld_data_t *callp = &call;
size_t bufsize = sizeof (labeld_data_t);
size_t datasize = CALL_SIZE(fields_call_t, 0);
int rval;
call.callop = LABELFIELDS;
if ((rval = __call_labeld(&callp, &bufsize, &datasize)) != SUCCESS) {
if (callp != &call)
/* release return buffer */
(void) munmap((void *)callp, bufsize);
return (-1);
}
/* unpack results */
if ((fields->class_name = strdup(&lfret.buf[lfret.classi])) == NULL) {
if (callp != &call)
/* release return buffer */
(void) munmap((void *)callp, bufsize);
return (0);
}
if ((fields->comps_name = strdup(&lfret.buf[lfret.compsi])) == NULL) {
free(fields->class_name);
if (callp != &call)
/* release return buffer */
(void) munmap((void *)callp, bufsize);
return (0);
}
if ((fields->marks_name = strdup(&lfret.buf[lfret.marksi])) == NULL) {
free(fields->class_name);
free(fields->comps_name);
if (callp != &call)
/* release return buffer */
(void) munmap((void *)callp, bufsize);
return (0);
}
if (callp != &call)
/* release return buffer */
(void) munmap((void *)callp, bufsize);
return (rval);
} /* labelfields */
#undef lfret
#define udret callp->param.aret.rvals.udefs_ret
/*
* userdefs - Get default user Sensitivity Label and/or Clearance.
*
* Entry None.
*
* Exit sl = default user Sensitivity Label.
* clear = default user Clearance.
*
* Returns -1, If unable to access label encodings file, or
* labels server failure.
* 1, If successful.
*
* Calls __call_labeld(UDEFS).
*/
int
userdefs(bslabel_t *sl, bclear_t *clear)
{
labeld_data_t call;
labeld_data_t *callp = &call;
size_t bufsize = sizeof (labeld_data_t);
size_t datasize = CALL_SIZE(udefs_call_t, 0);
int rval;
call.callop = UDEFS;
if ((rval = __call_labeld(&callp, &bufsize, &datasize)) != SUCCESS) {
/* process error */
return (-1);
}
if (sl != NULL)
*sl = udret.sl;
if (clear != NULL)
*clear = udret.clear;
return (rval);
} /* userdefs */
#undef udret