tsolextension.c revision 705
98N/A/* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
98N/A *
380N/A * Permission is hereby granted, free of charge, to any person obtaining a
98N/A * copy of this software and associated documentation files (the
98N/A * "Software"), to deal in the Software without restriction, including
98N/A * without limitation the rights to use, copy, modify, merge, publish,
98N/A * distribute, and/or sell copies of the Software, and to permit persons
98N/A * to whom the Software is furnished to do so, provided that the above
98N/A * copyright notice(s) and this permission notice appear in all copies of
98N/A * the Software and that both the above copyright notice(s) and this
98N/A * permission notice appear in supporting documentation.
98N/A *
98N/A * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
98N/A * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
98N/A * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
98N/A * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
98N/A * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
98N/A * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
98N/A * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
98N/A * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
98N/A * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
98N/A *
98N/A * Except as contained in this notice, the name of a copyright holder
98N/A * shall not be used in advertising or otherwise to promote the sale, use
98N/A * or other dealings in this Software without prior written authorization
98N/A * of the copyright holder.
98N/A */
98N/A
98N/A#pragma ident "@(#)tsolextension.c 1.39 09/05/15 SMI"
98N/A
380N/A#include <stdio.h>
98N/A#include "auditwrite.h"
98N/A#include <bsm/libbsm.h>
98N/A#include <bsm/audit_uevents.h>
156N/A#include <sys/param.h>
98N/A#include <sys/types.h>
98N/A#include <sys/socket.h>
98N/A#include <sys/wait.h>
98N/A#include <ucred.h>
98N/A#include <netinet/in.h>
156N/A#include <netdb.h>
98N/A#include <arpa/inet.h>
98N/A#include <sys/tsol/tndb.h>
156N/A#include <strings.h>
98N/A#include <string.h>
98N/A#include <pwd.h>
98N/A#include <unistd.h>
98N/A#include <sys/stat.h>
98N/A#include <rpc/rpc.h>
98N/A#include <zone.h>
98N/A
98N/A
98N/A#define NEED_REPLIES
98N/A
98N/A#ifdef HAVE_DIX_CONFIG_H
98N/A#include <dix-config.h>
98N/A#endif
98N/A
98N/A#include "misc.h"
98N/A#include "osdep.h"
98N/A#include <X11/Xauth.h>
98N/A#include "tsol.h"
159N/A#include "inputstr.h"
98N/A#include "extnsionst.h"
98N/A#include "dixstruct.h"
98N/A#include "xace.h"
98N/A#include "xacestr.h"
98N/A#ifdef PANORAMIX
98N/A#include "../Xext/panoramiXsrv.h"
98N/A#endif
98N/A#ifdef XCSECURITY
98N/A#define _SECURITY_SERVER
98N/A#include "security.h"
199N/A#include "../Xext/securitysrv.h"
98N/A#endif
98N/A#include "tsolpolicy.h"
98N/A
98N/A#define BadCmapCookie 0
257N/A#define Tsolextension 0x0080 /* Tsol extensions begin at 128 */
98N/A#define MAX_SCREENS 3 /* screens allowed */
98N/A#define EXTNSIZE 128
98N/A
98N/A#define SECURE_RPC_AUTH "SUN-DES-1"
98N/A#define SECURE_RPC_LEN 9
98N/A
98N/Astatic int ProcTsolDispatch(ClientPtr);
98N/Astatic int ProcSetPolyInstInfo(ClientPtr);
98N/Astatic int ProcSetPropLabel(ClientPtr);
98N/Astatic int ProcSetPropUID(ClientPtr);
98N/Astatic int ProcSetResLabel(ClientPtr);
98N/Astatic int ProcSetResUID(ClientPtr);
98N/Astatic int ProcGetClientAttributes(ClientPtr);
98N/Astatic int ProcGetClientLabel(ClientPtr);
98N/Astatic int ProcGetPropAttributes(ClientPtr);
98N/Astatic int ProcGetResAttributes(ClientPtr);
156N/Astatic int ProcMakeTPWindow(ClientPtr);
156N/Astatic int ProcMakeTrustedWindow(ClientPtr);
98N/Astatic int ProcMakeUntrustedWindow(ClientPtr);
98N/A
98N/Astatic int SProcTsolDispatch(ClientPtr);
98N/Astatic int SProcSetPolyInstInfo(ClientPtr);
98N/Astatic int SProcSetPropLabel(ClientPtr);
98N/Astatic int SProcSetPropUID(ClientPtr);
98N/Astatic int SProcSetResLabel(ClientPtr);
98N/Astatic int SProcSetResUID(ClientPtr);
98N/Astatic int SProcGetClientAttributes(ClientPtr);
98N/Astatic int SProcGetClientLabel(ClientPtr);
98N/Astatic int SProcGetPropAttributes(ClientPtr);
98N/Astatic int SProcGetResAttributes(ClientPtr);
98N/Astatic int SProcMakeTPWindow(ClientPtr);
98N/Astatic int SProcMakeTrustedWindow(ClientPtr);
380N/Astatic int SProcMakeUntrustedWindow(ClientPtr);
380N/A
380N/Astatic void TsolReset(ExtensionEntry *extension);
98N/Astatic void BreakAllGrabs(ClientPtr client);
98N/A
98N/Astatic unsigned char TsolReqCode = 0;
98N/Astatic int tsolEventBase = -1;
98N/Astatic int ScreenStripeHeight[MAX_SCREENS] = {0, 0};
98N/A
98N/Astatic HotKeyRec hotkey = {FALSE, 0, 0, 0, 0};
int tsolMultiLevel = TRUE;
static int OwnerUIDint;
static Selection *tsol_sel_agnt = NULL; /* entry in CurrentSelection to get seln */
static Atom tsol_atom_sel_agnt = 0; /* selection agent atom created during init */
int (*TsolSavedProcVector[PROCVECTORSIZE])(ClientPtr client);
int (*TsolSavedSwappedProcVector[PROCVECTORSIZE])(ClientPtr client);
static SecurityHook tsolSecHook;
static XID TsolCheckAuthorization (unsigned int name_length,
char *name, unsigned int data_length,
char *data, ClientPtr client, char **reason);
static void TsolSetClientInfo(ClientPtr client);
/* XACE hook callbacks */
static CALLBACK(TsolCheckExtensionAccess);
static CALLBACK(TsolCheckPropertyAccess);
static CALLBACK(TsolCheckResourceIDAccess);
static CALLBACK(TsolCheckSendAccess);
static CALLBACK(TsolCheckReceiveAccess);
static CALLBACK(TsolCheckDeviceAccess);
static CALLBACK(TsolCheckSelectionAccess);
static CALLBACK(TsolProcessKeyboard);
/* other callbacks */
static CALLBACK(TsolClientStateCallback);
static CALLBACK(TsolSelectionCallback);
/*
* Initialize the extension. Main entry point for this loadable
* module.
*/
_X_EXPORT void
TsolExtensionInit(void)
{
ExtensionEntry *extEntry;
int i;
/* sleep(20); */
/* This extension is supported on a labeled system */
if (!is_system_labeled()) {
return;
}
tsolMultiLevel = TRUE;
(void) setpflags(PRIV_AWARE, 1);
init_xtsol();
init_win_privsets();
extEntry = AddExtension(TSOLNAME, TSOL_NUM_EVENTS, TSOL_NUM_ERRORS,
ProcTsolDispatch, SProcTsolDispatch, TsolReset,
StandardMinorOpcode);
if (extEntry == NULL) {
ErrorF("TsolExtensionInit: AddExtension failed for X Trusted Extensions\n");
return;
}
TsolReqCode = (unsigned char) extEntry->base;
tsolEventBase = extEntry->eventBase;
if (!AddCallback(&ClientStateCallback, TsolClientStateCallback, NULL))
return;
if (!AddCallback(&SelectionCallback, TsolSelectionCallback, NULL))
return;
/* Allocate storage in devPrivates */
if (!dixRequestPrivate(tsolPrivKey, sizeof (TsolPrivRec))) {
ErrorF("TsolExtensionInit: Cannot allocate devPrivate.\n");
return;
}
/* Initialize the client info for server itself */
if (serverClient) {
TsolInfoPtr tsolinfo = GetClientTsolInfo(serverClient);
if (tsolinfo->sl == NULL) {
tsolinfo->sl = (bslabel_t *)lookupSL_low();
tsolinfo->uid = 0;
tsolinfo->pid = getpid();
snprintf(tsolinfo->pname, MAXNAME, "client id %d (pid %d)",
serverClient->index, tsolinfo->pid);
}
}
LoadTsolConfig();
MakeTSOLAtoms();
UpdateTsolNode();
tsol_atom_sel_agnt = MakeAtom("_TSOL_SEL_AGNT", 14, 1);
/* Initialize security hooks */
tsolSecHook.CheckAuthorization = TsolCheckAuthorization;
/*
tsolSecHook.DeleteClientFromAnySelections = TsolDeleteClientFromAnySelections;
tsolSecHook.DeleteWindowFromAnySelections = TsolDeleteWindowFromAnySelections;
*/
pSecHook = &tsolSecHook;
XaceRegisterCallback(XACE_RESOURCE_ACCESS, TsolCheckResourceIDAccess, NULL);
XaceRegisterCallback(XACE_PROPERTY_ACCESS, TsolCheckPropertyAccess, NULL);
XaceRegisterCallback(XACE_SEND_ACCESS, TsolCheckSendAccess, NULL);
XaceRegisterCallback(XACE_RECEIVE_ACCESS, TsolCheckReceiveAccess, NULL);
XaceRegisterCallback(XACE_EXT_ACCESS, TsolCheckExtensionAccess, NULL);
XaceRegisterCallback(XACE_DEVICE_ACCESS, TsolCheckDeviceAccess, NULL);
XaceRegisterCallback(XACE_SELECTION_ACCESS, TsolCheckSelectionAccess, NULL);
XaceRegisterCallback(XACE_KEY_AVAIL, TsolProcessKeyboard, NULL);
XaceRegisterCallback(XACE_AUDIT_BEGIN, TsolAuditStart, NULL);
XaceRegisterCallback(XACE_AUDIT_END, TsolAuditEnd, NULL);
/* Save original Proc vectors */
for (i = 0; i < PROCVECTORSIZE; i++) {
TsolSavedProcVector[i] = ProcVector[i];
TsolSavedSwappedProcVector[i] = SwappedProcVector[i];
}
/* Replace some of the original Proc vectors with our own TBD */
ProcVector[X_InternAtom] = ProcTsolInternAtom;
ProcVector[X_CreateWindow] = ProcTsolCreateWindow;
ProcVector[X_ChangeWindowAttributes] = ProcTsolChangeWindowAttributes;
ProcVector[X_ConfigureWindow] = ProcTsolConfigureWindow;
ProcVector[X_CirculateWindow] = ProcTsolCirculateWindow;
ProcVector[X_ReparentWindow] = ProcTsolReparentWindow;
ProcVector[X_GetGeometry] = ProcTsolGetGeometry;
ProcVector[X_GrabServer] = ProcTsolGrabServer;
ProcVector[X_UngrabServer] = ProcTsolUngrabServer;
ProcVector[X_SetScreenSaver] = ProcTsolSetScreenSaver;
ProcVector[X_ChangeHosts] = ProcTsolChangeHosts;
ProcVector[X_SetAccessControl] = ProcTsolChangeAccessControl;
ProcVector[X_KillClient] = ProcTsolKillClient;
ProcVector[X_SetFontPath] = ProcTsolSetFontPath;
ProcVector[X_SetCloseDownMode] = ProcTsolChangeCloseDownMode;
ProcVector[X_ListInstalledColormaps] = ProcTsolListInstalledColormaps;
/* ProcVector[X_GetImage] = ProcTsolGetImage; */
ProcVector[X_QueryTree] = ProcTsolQueryTree;
ProcVector[X_QueryPointer] = ProcTsolQueryPointer;
ProcVector[X_QueryExtension] = ProcTsolQueryExtension;
ProcVector[X_ListExtensions] = ProcTsolListExtensions;
ProcVector[X_MapWindow] = ProcTsolMapWindow;
ProcVector[X_MapSubwindows] = ProcTsolMapSubwindows;
ProcVector[X_CopyArea] = ProcTsolCopyArea;
ProcVector[X_CopyPlane] = ProcTsolCopyPlane;
ProcVector[X_PolySegment] = ProcTsolPolySegment;
ProcVector[X_PolyRectangle] = ProcTsolPolyRectangle;
}
static CALLBACK(
TsolCheckResourceIDAccess)
{
XaceResourceAccessRec *rec = calldata;
ClientPtr client = rec->client;
XID id = rec->id;
RESTYPE rtype = rec->rtype;
pointer rval = rec->res;
Mask access_mode = rec->access_mode;
Mask check_mode = access_mode;
TsolInfoPtr tsolinfo;
int msgType;
int msgVerb;
int reqtype;
if (client->requestBuffer) {
reqtype = MAJOROP; /* protocol */
} else {
reqtype = -1;
}
#define CHECK_RESOURCE_POLICY(DIX_MODE, TSOL_TYPE, TSOL_MODE, VAL, ID) \
if (check_mode & (DIX_MODE)) { \
rec->status = xtsol_policy((TSOL_TYPE), (TSOL_MODE), \
(VAL), (ID), client, TSOL_ALL, &reqtype); \
check_mode &= ~(DIX_MODE); \
}
switch (rtype) {
case RT_GC:
CHECK_RESOURCE_POLICY(DixCreateAccess, TSOL_RES_GC, TSOL_CREATE,
NULL, id);
/* id must be non-zero for read/modify/destroy access */
if (id != 0) {
CHECK_RESOURCE_POLICY((DixReadAccess|DixGetAttrAccess|DixUseAccess),
TSOL_RES_GC, TSOL_READ, NULL, id);
CHECK_RESOURCE_POLICY((DixWriteAccess|DixSetAttrAccess),
TSOL_RES_GC, TSOL_MODIFY, NULL, id);
CHECK_RESOURCE_POLICY(DixDestroyAccess, TSOL_RES_GC, TSOL_DESTROY,
NULL, id);
}
break;
case RT_WINDOW: /* Drawables */
switch (reqtype) {
case X_SetInputFocus:
CHECK_RESOURCE_POLICY(DixSetAttrAccess,
TSOL_RES_FOCUSWIN, TSOL_MODIFY, rval, 0);
break;
case X_GetInputFocus:
CHECK_RESOURCE_POLICY(DixGetAttrAccess,
TSOL_RES_FOCUSWIN, TSOL_READ, rval, 0);
break;
case X_ChangeWindowAttributes:
CHECK_RESOURCE_POLICY((DixSetAttrAccess|DixReceiveAccess),
TSOL_RES_WINDOW, TSOL_SPECIAL, rval, 0);
if (rec->status != Success) {
WindowPtr pWin = (WindowPtr)rval;
if (WindowIsRoot(pWin))
rec->status = Success;
}
break;
case X_GrabPointer:
case X_UngrabPointer:
case X_GrabKeyboard:
case X_UngrabKeyboard:
case X_GrabKey:
case X_UngrabKey:
case X_GrabButton:
case X_UngrabButton:
CHECK_RESOURCE_POLICY(DixSetAttrAccess,
TSOL_RES_GRABWIN, TSOL_MODIFY, rval, 0);
break;
default:
/* CreateWindow, policy check on the parent */
CHECK_RESOURCE_POLICY((DixAddAccess|DixRemoveAccess),
TSOL_RES_WINDOW, TSOL_CREATE, rval, 0);
/* Newly created window. Just initialize it. */
if (check_mode & DixCreateAccess) {
TsolInitWindow(client, (WindowPtr) rval);
check_mode &= ~(DixCreateAccess);
}
CHECK_RESOURCE_POLICY((DixReadAccess|DixGetAttrAccess|DixListAccess),
TSOL_RES_WINDOW, TSOL_READ, rval, 0);
CHECK_RESOURCE_POLICY((DixWriteAccess|DixSetAttrAccess|DixShowAccess|
DixHideAccess|DixManageAccess),
TSOL_RES_WINDOW, TSOL_MODIFY, rval, 0);
CHECK_RESOURCE_POLICY(DixDestroyAccess, TSOL_RES_WINDOW,
TSOL_DESTROY, rval, 0);
/* Event access, actual policy is implemented in the hook */
CHECK_RESOURCE_POLICY(DixSendAccess, TSOL_RES_WINDOW,
TSOL_SPECIAL, rval, 0);
CHECK_RESOURCE_POLICY(DixReceiveAccess, TSOL_RES_WINDOW,
TSOL_SPECIAL, rval, 0);
/* Property related access */
CHECK_RESOURCE_POLICY((DixGetPropAccess|DixListPropAccess),
TSOL_RES_PROPWIN, TSOL_READ, rval, 0);
CHECK_RESOURCE_POLICY(DixSetPropAccess,
TSOL_RES_PROPWIN, TSOL_MODIFY, rval, 0);
break;
}
/* The rest falls through to code shared with RT_PIXMAP */
case RT_PIXMAP:
/* Drawing operations use pixel access policy */
switch (reqtype) {
case X_CreatePixmap:
/* Newly created window. Just initialize it. */
if (check_mode & DixCreateAccess) {
TsolInitPixmap(client, (PixmapPtr) rval);
check_mode &= ~(DixCreateAccess);
}
break;
case X_PolyPoint:
case X_PolyLine:
case X_PolyArc:
case X_FillPoly:
case X_PolyFillRectangle:
case X_PolyFillArc:
case X_PutImage:
case X_PolyText8:
case X_PolyText16:
case X_ImageText8:
case X_ImageText16:
CHECK_RESOURCE_POLICY((DixReadAccess | DixBlendAccess),
TSOL_RES_PIXEL, TSOL_READ, rval, 0);
CHECK_RESOURCE_POLICY(DixWriteAccess,
TSOL_RES_PIXEL, TSOL_MODIFY, rval, 0);
break;
case X_GetImage:
case X_ClearArea:
rec->status = Success;
break;
default:
if (check_mode & (DixReadAccess|DixWriteAccess)) {
check_mode &= ~(DixReadAccess|DixWriteAccess);
rec->status = Success;
}
/*
CHECK_RESOURCE_POLICY(DixReadAccess,
TSOL_RES_PIXMAP, TSOL_READ, rval, 0);
CHECK_RESOURCE_POLICY(DixWriteAccess,
TSOL_RES_PIXMAP, TSOL_MODIFY, rval, 0);
*/
break;
}
break;
case RT_CURSOR:
CHECK_RESOURCE_POLICY((DixUseAccess|DixWriteAccess),
TSOL_RES_CURSOR, TSOL_MODIFY, NULL, id);
CHECK_RESOURCE_POLICY(DixCreateAccess,
TSOL_RES_CURSOR, TSOL_CREATE, NULL, id);
break;
case RT_FONT:
CHECK_RESOURCE_POLICY(DixUseAccess,
TSOL_RES_CURSOR, TSOL_READ, NULL, id);
break;
default:
rec->status = Success;
break;
}
#ifndef NO_TSOL_DEBUG_MESSAGES
if (check_mode) { /* Any access mode bits not yet handled ? */
LogMessageVerb(X_NOT_IMPLEMENTED, TSOL_MSG_UNIMPLEMENTED,
TSOL_LOG_PREFIX
"policy not implemented for CheckResourceAccess, "
"rtype=0x%x (%s), mode=0x%x (%s)\n",
(int) rtype, TsolResourceTypeString(rtype),
check_mode, TsolDixAccessModeNameString(check_mode));
}
#endif /* !NO_TSOL_DEBUG_MESSAGES */
if (rec->status != Success) {
msgType = X_ERROR;
msgVerb = TSOL_MSG_ERROR;
} else {
#ifdef NO_TSOL_DEBUG_MESSAGES
/* rest of the function is just printing error or debug messages */
return;
#else
/* Trace messages for debugging */
msgType = X_INFO;
msgVerb = TSOL_MSG_ACCESS_TRACE;
#endif /* NO_TSOL_DEBUG_MESSAGES */
}
tsolinfo = GetClientTsolInfo(client);
LogMessageVerb(msgType, msgVerb,
TSOL_LOG_PREFIX
"CheckResourceAccess(%s, %s, 0x%x, %s, %s) = %s\n",
tsolinfo->pname,
TsolResourceTypeString(rtype), id,
TsolDixAccessModeNameString(access_mode),
TsolRequestNameString(reqtype),
TsolErrorNameString(rec->status));
}
static
CALLBACK(TsolSelectionCallback)
{
SelectionInfoRec *pselinfo = (SelectionInfoRec *)calldata;
Selection *pSel = pselinfo->selection;
TsolSelnPtr tsolseln = TsolSelectionPriv(pSel);
switch (pselinfo->kind) {
case SelectionClientClose:
if (tsol_sel_agnt && pSel->selection == tsol_sel_agnt->selection) {
tsol_sel_agnt = NULL; /* selection manager died. */
}
/* fall through to reset the SL */
case SelectionWindowDestroy:
tsolseln->sl = NULL;
break;
default:
/* All others handled in SelectionAccess handler */
break;
}
}
static
CALLBACK(TsolClientStateCallback)
{
NewClientInfoRec *pci = (NewClientInfoRec *)calldata;
ClientPtr client = pci->client;
TsolInfoPtr tsolinfo = TsolClientPriv(client);
switch (client->clientState) {
case ClientStateInitial:
/* Got a new connection */
TsolSetClientInfo(client);
break;
case ClientStateRunning:
break;
case ClientStateRetained: /* client disconnected */
break;
case ClientStateGone:
if (tpwin && wClient(tpwin) == client)
tpwin = NULL; /* reset tpwin */
if (tsolinfo != NULL && tsolinfo->privs != NULL) {
priv_freeset(tsolinfo->privs);
}
/* Audit disconnect */
if (system_audit_on && (au_preselect(AUE_ClientDisconnect, &(tsolinfo->amask),
AU_PRS_BOTH, AU_PRS_USECACHE) == 1)) {
auditwrite(AW_PRESELECT, &(tsolinfo->amask),AW_END);
auditwrite(AW_EVENTNUM, AUE_ClientDisconnect,
AW_XCLIENT, client->index,
AW_SLABEL, tsolinfo->sl,
AW_RETURN, 0, 0, AW_WRITE, AW_END);
tsolinfo->flags &= ~TSOL_DOXAUDIT;
tsolinfo->flags &= ~TSOL_AUDITEVENT;
auditwrite(AW_FLUSH, AW_END);
auditwrite(AW_DISCARDRD, tsolinfo->asaverd, AW_END);
auditwrite(AW_NOPRESELECT, AW_END);
}
break;
default:
break;
}
}
static void
TsolReset(ExtensionEntry *extension)
{
free_win_privsets();
XaceDeleteCallback(XACE_RESOURCE_ACCESS, TsolCheckResourceIDAccess, NULL);
XaceDeleteCallback(XACE_PROPERTY_ACCESS, TsolCheckPropertyAccess, NULL);
XaceDeleteCallback(XACE_SEND_ACCESS, TsolCheckSendAccess, NULL);
XaceDeleteCallback(XACE_RECEIVE_ACCESS, TsolCheckReceiveAccess, NULL);
XaceDeleteCallback(XACE_EXT_ACCESS, TsolCheckExtensionAccess, NULL);
XaceDeleteCallback(XACE_DEVICE_ACCESS, TsolCheckDeviceAccess, NULL);
XaceDeleteCallback(XACE_SELECTION_ACCESS, TsolCheckSelectionAccess, NULL);
XaceDeleteCallback(XACE_KEY_AVAIL, TsolProcessKeyboard, NULL);
XaceDeleteCallback(XACE_AUDIT_BEGIN, TsolAuditStart, NULL);
XaceDeleteCallback(XACE_AUDIT_END, TsolAuditEnd, NULL);
}
/*
* Dispatch routine
*
*/
static int
ProcTsolDispatch(register ClientPtr client)
{
int retval;
REQUEST(xReq);
switch (stuff->data)
{
case X_SetPolyInstInfo:
retval = ProcSetPolyInstInfo(client);
break;
case X_SetPropLabel:
retval = ProcSetPropLabel(client);
break;
case X_SetPropUID:
retval = ProcSetPropUID(client);
break;
case X_SetResLabel:
retval = ProcSetResLabel(client);
break;
case X_SetResUID:
retval = ProcSetResUID(client);
break;
case X_GetClientAttributes:
retval = ProcGetClientAttributes(client);
break;
case X_GetClientLabel:
retval = ProcGetClientLabel(client);
break;
case X_GetPropAttributes:
retval = ProcGetPropAttributes(client);
break;
case X_GetResAttributes:
retval = ProcGetResAttributes(client);
break;
case X_MakeTPWindow:
retval = ProcMakeTPWindow(client);
break;
case X_MakeTrustedWindow:
retval = ProcMakeTrustedWindow(client);
break;
case X_MakeUntrustedWindow:
retval = ProcMakeUntrustedWindow(client);
break;
default:
SendErrorToClient(client, TsolReqCode, stuff->data, 0, BadRequest);
retval = BadRequest;
}
return (retval);
}
static int
SProcTsolDispatch(register ClientPtr client)
{
int n;
int retval;
REQUEST(xReq);
swaps(&stuff->length, n);
switch (stuff->data)
{
case X_SetPolyInstInfo:
retval = SProcSetPolyInstInfo(client);
break;
case X_SetPropLabel:
retval = SProcSetPropLabel(client);
break;
case X_SetPropUID:
retval = SProcSetPropUID(client);
break;
case X_SetResLabel:
retval = SProcSetResLabel(client);
break;
case X_SetResUID:
retval = SProcSetResUID(client);
break;
case X_GetClientAttributes:
retval = SProcGetClientAttributes(client);
break;
case X_GetClientLabel:
retval = SProcGetClientLabel(client);
break;
case X_GetPropAttributes:
retval = SProcGetPropAttributes(client);
break;
case X_GetResAttributes:
retval = SProcGetResAttributes(client);
break;
case X_MakeTPWindow:
retval = SProcMakeTPWindow(client);
break;
case X_MakeTrustedWindow:
retval = SProcMakeTrustedWindow(client);
break;
case X_MakeUntrustedWindow:
retval = SProcMakeUntrustedWindow(client);
break;
default:
SendErrorToClient(client, TsolReqCode, stuff->data, 0, BadRequest);
retval = BadRequest;
}
return (retval);
}
/*
* Individual routines
*/
static int
SProcSetPolyInstInfo(ClientPtr client)
{
int n;
REQUEST(xSetPolyInstInfoReq);
swapl(&stuff->uid, n);
swapl(&stuff->enabled, n);
swaps(&stuff->sllength, n);
return (ProcSetPolyInstInfo(client));
}
static int
SProcSetPropLabel(ClientPtr client)
{
int n;
REQUEST(xSetPropLabelReq);
swapl(&stuff->id, n);
swapl(&stuff->atom, n);
swaps(&stuff->labelType, n);
swaps(&stuff->sllength, n);
swaps(&stuff->illength, n);
return (ProcSetPropLabel(client));
}
static int
SProcSetPropUID(ClientPtr client)
{
int n;
REQUEST(xSetPropUIDReq);
swapl(&stuff->id, n);
swapl(&stuff->atom, n);
swapl(&stuff->uid, n);
return (ProcSetPropUID(client));
}
static int
SProcSetResLabel(ClientPtr client)
{
int n;
REQUEST(xSetResLabelReq);
swapl(&stuff->id, n);
swaps(&stuff->resourceType, n);
swaps(&stuff->labelType, n);
swaps(&stuff->sllength, n);
swaps(&stuff->illength, n);
return (ProcSetResLabel(client));
}
static int
SProcSetResUID(ClientPtr client)
{
int n;
REQUEST(xSetResUIDReq);
swapl(&stuff->id, n);
swaps(&stuff->resourceType, n);
swapl(&stuff->uid, n);
return (ProcSetResUID(client));
}
static int
SProcGetClientAttributes(ClientPtr client)
{
int n;
REQUEST(xGetClientAttributesReq);
swapl(&stuff->id, n);
return (ProcGetClientAttributes(client));
}
static int
SProcGetClientLabel(ClientPtr client)
{
int n;
REQUEST(xGetClientLabelReq);
swapl(&stuff->id, n);
swaps(&stuff->mask, n);
return (ProcGetClientLabel(client));
}
static int
SProcGetPropAttributes(ClientPtr client)
{
int n;
REQUEST(xGetPropAttributesReq);
swapl(&stuff->id, n);
swapl(&stuff->atom, n);
swaps(&stuff->mask, n);
return (ProcGetPropAttributes(client));
}
static int
SProcGetResAttributes(ClientPtr client)
{
int n;
REQUEST(xGetResAttributesReq);
swapl(&stuff->id, n);
swaps(&stuff->resourceType, n);
swaps(&stuff->mask, n);
return (ProcGetResAttributes(client));
}
static int
SProcMakeTPWindow(ClientPtr client)
{
int n;
REQUEST(xMakeTPWindowReq);
swapl(&stuff->id, n);
return (ProcMakeTPWindow(client));
}
static int
SProcMakeTrustedWindow(ClientPtr client)
{
int n;
REQUEST(xMakeTrustedWindowReq);
swapl(&stuff->id, n);
return (ProcMakeTrustedWindow(client));
}
static int
SProcMakeUntrustedWindow(ClientPtr client)
{
int n;
REQUEST(xMakeUntrustedWindowReq);
swapl(&stuff->id, n);
return (ProcMakeUntrustedWindow(client));
}
/*
* Set PolyInstantiation Info.
* Normally a get(prop) will
* get the prop. that has match sl, uid of the client. Setting
* enabled to true will get only the prop. corresponding to
* sl, uid specified instead of that of client. This is used
* by dtwm/dtfile in special motif lib.
*/
static int
ProcSetPolyInstInfo(ClientPtr client)
{
bslabel_t *sl;
int err_code;
REQUEST(xSetPolyInstInfoReq);
REQUEST_AT_LEAST_SIZE(xSetPolyInstInfoReq);
/*
* Check for policy here
*/
if ((err_code = xtsol_policy(TSOL_RES_POLYINFO, TSOL_MODIFY, NULL, 0,
client, TSOL_ALL, &(MAJOROP))))
{
return (err_code);
}
sl = (bslabel_t *)(stuff + 1);
tsolpolyinstinfo.enabled = stuff->enabled;
tsolpolyinstinfo.uid = (uid_t) stuff->uid;
tsolpolyinstinfo.sl = lookupSL(sl);
return (client->noClientException);
}
static int
ProcSetPropLabel(ClientPtr client)
{
bslabel_t *sl;
WindowPtr pWin;
TsolPropPtr tsolprop;
PropertyPtr pProp;
int err_code;
int rc;
REQUEST(xSetPropLabelReq);
REQUEST_AT_LEAST_SIZE(xSetPropLabelReq);
rc = dixLookupWindow(&pWin, stuff->id, client, DixReadAccess);
if (rc != Success)
return rc;
if (!pWin)
{
client->errorValue = stuff->id;
return (BadWindow);
}
if ((err_code = xtsol_policy(TSOL_RES_WINDOW, TSOL_MODIFY, pWin, 0,
client, TSOL_ALL, &(MAJOROP))))
{
return (err_code);
}
if (!ValidAtom(stuff->atom))
{
client->errorValue = stuff->atom;
return (BadAtom);
}
/* first see if property already exists */
pProp = wUserProps (pWin);
while (pProp)
{
if (pProp->propertyName == stuff->atom)
break;
pProp = pProp->next;
}
if (!pProp)
{
/* property does not exist */
client->errorValue = stuff->atom;
return (BadAtom);
}
/* Initialize property created internally by server */
tsolprop = TsolPropertyPriv(pProp);
sl = (bslabel_t *)(stuff + 1);
if (!blequal(tsolprop->sl, sl))
{
if ((err_code = xtsol_policy(TSOL_RES_SL, TSOL_MODIFY, sl, 0,
client, TSOL_ALL, tsolprop->sl)))
{
return (err_code);
}
tsolprop->sl = lookupSL(sl);
}
return (client->noClientException);
}
static int
ProcSetPropUID(ClientPtr client)
{
WindowPtr pWin;
TsolPropPtr tsolprop;
PropertyPtr pProp;
int err_code;
int rc;
REQUEST(xSetPropUIDReq);
REQUEST_SIZE_MATCH(xSetPropUIDReq);
rc = dixLookupWindow(&pWin, stuff->id, client, DixReadAccess);
if (rc != Success)
return rc;
if (!pWin)
{
client->errorValue = stuff->id;
return (BadWindow);
}
if (!ValidAtom(stuff->atom))
{
client->errorValue = stuff->atom;
return (BadAtom);
}
/* first see if property already exists */
pProp = wUserProps (pWin);
while (pProp)
{
if (pProp->propertyName == stuff->atom)
break;
pProp = pProp->next;
}
if (!pProp)
{
/* property does not exist */
client->errorValue = stuff->atom;
return (BadAtom);
}
if ((err_code = xtsol_policy(TSOL_RES_UID, TSOL_MODIFY, NULL, 0,
client, TSOL_ALL, &(MAJOROP))))
{
return (err_code);
}
/* Initialize property created internally by server */
tsolprop = TsolPropertyPriv(pProp);
tsolprop->uid = stuff->uid;
return (client->noClientException);
}
static int
ProcSetResLabel(ClientPtr client)
{
bslabel_t *sl;
PixmapPtr pMap;
WindowPtr pWin;
xEvent message;
TsolResPtr tsolres;
int err_code;
int rc;
REQUEST(xSetResLabelReq);
REQUEST_AT_LEAST_SIZE(xSetResLabelReq);
sl = (bslabel_t *)(stuff + 1);
switch (stuff->resourceType)
{
case SESSIONHI: /* set server session HI */
if ((err_code = xtsol_policy(TSOL_RES_SL, TSOL_MODIFY, sl, 0,
client, TSOL_ALL, NULL)))
{
return (err_code);
}
memcpy(&SessionHI, sl, SL_SIZE);
return (client->noClientException);
case SESSIONLO: /* set server session LO */
if ((err_code = xtsol_policy(TSOL_RES_SL, TSOL_MODIFY, sl, 0,
client, TSOL_ALL, NULL)))
{
return (err_code);
}
memcpy(&SessionLO, sl, SL_SIZE);
return (client->noClientException);
case IsWindow:
rc = dixLookupWindow(&pWin, stuff->id, client, DixWriteAccess);
if (rc != Success)
return rc;
if (pWin)
{
tsolres = TsolWindowPriv(pWin);
}
else
{
client->errorValue = stuff->id;
return (BadWindow);
}
break;
case IsPixmap:
rc = dixLookupResource((pointer *)&pMap, stuff->id, RT_PIXMAP,
client, DixWriteAccess);
if (rc != Success)
return rc;
if (pMap)
{
tsolres = TsolPixmapPriv(pMap);
}
else
{
client->errorValue = stuff->id;
return (BadPixmap);
}
break;
default:
client->errorValue = stuff->resourceType;
return (BadValue);
}
if (!blequal(tsolres->sl, sl))
{
if ((err_code = xtsol_policy(TSOL_RES_SL, TSOL_MODIFY, sl, 0,
client, TSOL_ALL, tsolres->sl)))
{
return (err_code);
}
tsolres->sl = lookupSL(sl);
}
/* generate the notify event for windows */
if (stuff->resourceType == IsWindow)
{
rc = dixLookupWindow(&pWin, stuff->id, client, DixReadAccess);
if (rc != Success)
return rc;
message.u.u.type = ClientMessage; /* 33 */
message.u.u.detail = 32;
message.u.clientMessage.window = RootOf(pWin);
message.u.clientMessage.u.l.type =
MakeAtom("_TSOL_CMWLABEL_CHANGE", 21, 1);
message.u.clientMessage.u.l.longs0 = RootOfClient(pWin);
message.u.clientMessage.u.l.longs1 = stuff->id;
DeliverEventsToWindow(PickPointer(client), pWin, &message, 1,
SubstructureRedirectMask, NullGrab, 0);
}
return (client->noClientException);
}
static int
ProcSetResUID(ClientPtr client)
{
int ScreenNumber;
PixmapPtr pMap;
WindowPtr pWin;
TsolResPtr tsolres;
int err_code;
int rc;
REQUEST(xSetResUIDReq);
REQUEST_SIZE_MATCH(xSetResUIDReq);
switch (stuff->resourceType)
{
case STRIPEHEIGHT:
if ((err_code = xtsol_policy(TSOL_RES_STRIPE, TSOL_MODIFY, NULL, 0,
client, TSOL_ALL, &(MAJOROP))))
{
return (err_code);
}
StripeHeight = stuff->uid;
ScreenNumber = stuff->id;
/* set Screen Stripe Size */
DoScreenStripeHeight(ScreenNumber);
ScreenStripeHeight [ScreenNumber] = StripeHeight;
return (client->noClientException);
case RES_OUID:
if ((err_code = xtsol_policy(TSOL_RES_WOWNER, TSOL_MODIFY, NULL, 0,
client, TSOL_ALL, &(MAJOROP))))
{
return (err_code);
}
OwnerUID = stuff->uid;
OwnerUIDint = OwnerUID;
AddUID(&OwnerUIDint);
return (client->noClientException);
case IsWindow:
rc = dixLookupWindow(&pWin, stuff->id, client, DixWriteAccess);
if (rc != Success)
return rc;
if (pWin)
{
tsolres = TsolWindowPriv(pWin);
}
else
{
client->errorValue = stuff->id;
return (BadWindow);
}
break;
case IsPixmap:
rc = dixLookupResource((pointer *)&pMap, stuff->id, RT_PIXMAP,
client, DixWriteAccess);
if (rc != Success)
return rc;
if (pMap)
{
tsolres = TsolPixmapPriv(pMap);
}
else
{
client->errorValue = stuff->id;
return (BadPixmap);
}
break;
default:
return (BadValue);
}
if ((err_code = xtsol_policy(TSOL_RES_UID, TSOL_MODIFY, NULL, 0,
client, TSOL_ALL, &(MAJOROP))))
{
return (err_code);
}
tsolres->uid = stuff->uid;
return (client->noClientException);
}
static int
ProcGetClientAttributes(ClientPtr client)
{
int n;
int err_code;
int rc;
ClientPtr res_client; /* resource owner client */
TsolInfoPtr tsolinfo, res_tsolinfo;
WindowPtr pWin;
xGetClientAttributesReply rep;
REQUEST(xGetClientAttributesReq);
REQUEST_SIZE_MATCH(xGetClientAttributesReq);
/* Valid window check */
rc = dixLookupWindow(&pWin, stuff->id, client, DixReadAccess);
if (rc != Success)
return rc;
if (!(res_client = clients[CLIENT_ID(stuff->id)]))
{
client->errorValue = stuff->id;
return (BadWindow);
}
if ((err_code = xtsol_policy(TSOL_RES_CLIENT, TSOL_READ, NULL, stuff->id,
client, TSOL_ALL, &(MAJOROP))))
{
return (err_code);
}
tsolinfo = GetClientTsolInfo(client);
res_tsolinfo = GetClientTsolInfo(res_client);
/* Transfer the client info to reply rec */
rep.type = X_Reply;
rep.sequenceNumber = client->sequence;
rep.trustflag = (res_tsolinfo->forced_trust == 1
|| res_tsolinfo->trusted_path) ? (BYTE)1 : (BYTE)0;
rep.uid = (CARD32) res_tsolinfo->uid;
rep.pid = (CARD32) res_tsolinfo->pid;
rep.gid = (CARD32) res_tsolinfo->gid;
rep.auditid = (CARD32) res_tsolinfo->auid;
rep.sessionid = (CARD32) res_tsolinfo->asid;
rep.iaddr = (CARD32) res_tsolinfo->iaddr;
rep.length = (CARD32) 0;
if (client->swapped)
{
swaps(&rep.sequenceNumber, n);
swapl(&rep.length, n);
swapl(&rep.uid, n);
swapl(&rep.pid, n);
swapl(&rep.gid, n);
swapl(&rep.auditid, n);
swapl(&rep.sessionid, n);
swapl(&rep.iaddr, n);
}
WriteToClient(client, sizeof(xGetClientAttributesReply), (char *)&rep);
return (client->noClientException);
}
static int
ProcGetClientLabel(ClientPtr client)
{
int n;
int reply_length = 0;
int rc;
int err_code;
Bool write_to_client = 0;
bslabel_t *sl;
ClientPtr res_client; /* resource owner client */
TsolInfoPtr tsolinfo, res_tsolinfo;
WindowPtr pWin;
xGenericReply rep;
REQUEST(xGetClientLabelReq);
REQUEST_SIZE_MATCH(xGetClientLabelReq);
/* Valid window check */
rc = dixLookupWindow(&pWin, stuff->id, client, DixReadAccess);
if (rc != Success)
return rc;
if (!(res_client = clients[CLIENT_ID(stuff->id)]))
{
client->errorValue = stuff->id;
return (BadWindow);
}
if ((err_code = xtsol_policy(TSOL_RES_CLIENT, TSOL_READ, NULL, stuff->id,
client, TSOL_ALL, &(MAJOROP))))
{
return (err_code);
}
tsolinfo = GetClientTsolInfo(client);
res_tsolinfo = GetClientTsolInfo(res_client);
/* Transfer the client info to reply rec */
rep.type = X_Reply;
rep.sequenceNumber = client->sequence;
/* allocate temp storage for labels */
sl = (bslabel_t *)(xalloc(SL_SIZE));
rep.data00 = rep.data01 = 0;
if (sl == NULL)
return (BadAlloc);
/* fill the fields as per request mask */
if (stuff->mask & RES_SL)
{
memcpy(sl, res_tsolinfo->sl, SL_SIZE);
rep.data00 = SL_SIZE;
}
rep.length = (CARD32)(rep.data00)/4;
if (rep.length > 0)
{
reply_length = rep.length*4;
write_to_client = 1;
}
if (client->swapped)
{
swaps(&rep.sequenceNumber, n);
swapl(&rep.length, n);
swapl(&rep.data00, n);
swapl(&rep.data01, n);
}
WriteToClient(client, sizeof(xGenericReply), (char *)&rep);
if (write_to_client == 1)
{
WriteToClient(client, reply_length, (char *)sl);
}
xfree(sl);
return (client->noClientException);
}
static int
ProcGetPropAttributes(ClientPtr client)
{
int n;
int reply_length = 0;
int rc;
Bool write_to_client = 0;
PropertyPtr pProp;
bslabel_t *sl;
WindowPtr pWin;
TsolPropPtr tsolprop;
TsolResPtr tsolres;
TsolInfoPtr tsolinfo = GetClientTsolInfo(client);
xGetPropAttributesReply rep;
REQUEST(xGetPropAttributesReq);
REQUEST_SIZE_MATCH(xGetPropAttributesReq);
rc = dixLookupWindow(&pWin, stuff->id, client, DixReadAccess);
if (rc != Success)
return rc;
if (!ValidAtom(stuff->atom))
{
client->errorValue = stuff->atom;
return (BadAtom);
}
/* first see if property already exists */
pProp = wUserProps (pWin);
while (pProp)
{
tsolprop = TsolPropertyPriv(pProp);
if (pProp->propertyName == stuff->atom) {
if (tsolpolyinstinfo.enabled) {
if (tsolprop->uid == tsolpolyinstinfo.uid &&
tsolprop->sl == tsolpolyinstinfo.sl)
break; /* match found */
} else {
if (tsolprop->uid == tsolinfo->uid &&
tsolprop->sl == tsolinfo->sl) {
break; /* match found */
}
}
}
pProp = pProp->next;
}
if (!pProp)
{
/* property does not exist, use window's attributes */
tsolres = TsolWindowPriv(pWin);
tsolprop = NULL;
}
if (stuff->mask & RES_UID)
{
rep.uid = tsolprop ? tsolprop->uid : tsolres->uid;
}
/* allocate temp storage for labels */
sl = (bslabel_t *)(xalloc(SL_SIZE));
rep.sllength = rep.illength = 0;
if (sl == NULL)
return (BadAlloc);
/* fill the fields as per request mask */
if (stuff->mask & RES_SL)
{
memcpy(sl, tsolprop ? tsolprop->sl : tsolres->sl, SL_SIZE);
rep.sllength = SL_SIZE;
}
rep.type = X_Reply;
rep.sequenceNumber = client->sequence;
rep.length = (CARD32) (rep.sllength)/4;
if (rep.length > 0)
{
reply_length = rep.length*4;
write_to_client = 1;
}
if (client->swapped)
{
swaps(&rep.sequenceNumber, n);
swapl(&rep.length, n);
swapl(&rep.uid, n);
swaps(&rep.sllength, n);
swaps(&rep.illength, n);
}
WriteToClient(client, sizeof(xGetPropAttributesReply), (char *)&rep);
if (write_to_client == 1)
{
WriteToClient(client, reply_length, (char *)sl);
}
xfree(sl);
return (client->noClientException);
}
static int
ProcGetResAttributes(ClientPtr client)
{
int n;
int reply_length = 0;
int rc;
Bool write_to_client = 0;
bslabel_t *sl;
PixmapPtr pMap;
WindowPtr pWin;
TsolResPtr tsolres = NULL;
xGetResAttributesReply rep;
REQUEST(xGetResAttributesReq);
REQUEST_SIZE_MATCH(xGetResAttributesReq);
if (stuff->mask & RES_STRIPE)
{
rep.uid = ScreenStripeHeight[stuff->id];
}
if (stuff->mask & RES_OUID)
{
rep.owneruid = OwnerUID;
}
if (stuff->resourceType == IsWindow &&
(stuff->mask & (RES_UID | RES_SL )))
{
rc = dixLookupWindow(&pWin, stuff->id, client, DixReadAccess);
if (rc != Success)
return rc;
tsolres = TsolWindowPriv(pWin);
}
if (stuff->resourceType == IsPixmap &&
(stuff->mask & (RES_UID | RES_SL )))
{
rc = dixLookupResource((pointer *)&pMap, stuff->id, RT_PIXMAP,
client, DixWriteAccess);
if (rc != Success)
return rc;
tsolres = TsolPixmapPriv(pMap);
}
if (stuff->mask & RES_UID)
{
rep.uid = tsolres->uid;
}
/* allocate temp storage for labels */
sl = (bslabel_t *)(xalloc(SL_SIZE));
rep.sllength = rep.illength = rep.iillength = 0;
if (sl == NULL)
return (BadAlloc);
/* fill the fields as per request mask */
if (stuff->mask & RES_SL)
{
memcpy(sl, tsolres->sl, SL_SIZE);
rep.sllength = SL_SIZE;
}
rep.type = X_Reply;
rep.sequenceNumber = client->sequence;
rep.length = (CARD32) (rep.sllength)/4;
if (rep.length > 0)
{
reply_length = rep.length*4;
write_to_client = 1;
}
if (client->swapped)
{
swaps(&rep.sequenceNumber, n);
swapl(&rep.length, n);
swapl(&rep.uid, n);
swapl(&rep.owneruid, n);
swaps(&rep.sllength, n);
swaps(&rep.illength, n);
swaps(&rep.iillength, n);
}
WriteToClient(client, sizeof(xGetResAttributesReply), (char *)&rep);
if (write_to_client == 1)
{
WriteToClient(client, reply_length, (char *)sl);
}
xfree(sl);
return (client->noClientException);
}
int
ProcMakeTPWindow(ClientPtr client)
{
WindowPtr pWin = NULL, pParent;
int rc;
int err_code;
TsolInfoPtr tsolinfo;
REQUEST(xMakeTPWindowReq);
REQUEST_SIZE_MATCH(xMakeTPWindowReq);
/*
* Session type single-level? This is set by the
* label builder
*/
tsolinfo = GetClientTsolInfo(client);
if (tsolinfo && HasTrustedPath(tsolinfo) &&
blequal(&SessionLO, &SessionHI) && stuff->id == 0) {
tsolMultiLevel = FALSE;
return (client->noClientException);
}
#if defined(PANORAMIX)
if (!noPanoramiXExtension)
{
PanoramiXRes *panres = NULL;
int j;
if ((panres = (PanoramiXRes *)LookupIDByType(stuff->id, XRT_WINDOW))
== NULL)
return BadWindow;
FOR_NSCREENS_BACKWARD(j)
{
rc = dixLookupWindow(&pWin, panres->info[j].id,
client, DixWriteAccess);
if (rc != Success)
return rc;
/* window should not be root but child of root */
if (!pWin || (!pWin->parent))
{
client->errorValue = stuff->id;
return (BadWindow);
}
if ((err_code = xtsol_policy(TSOL_RES_TPWIN, TSOL_MODIFY, pWin,
0, client, TSOL_ALL, &(MAJOROP))))
{
return (err_code);
}
pParent = pWin->parent;
if (pParent->firstChild != pWin)
{
tpwin = (WindowPtr)NULL;
ReflectStackChange(pWin, pParent->firstChild, VTStack);
}
}
} else
#endif
{
rc = dixLookupWindow(&pWin, stuff->id, client, DixWriteAccess);
if (rc != Success)
return rc;
/* window should not be root but child of root */
if (!pWin || (!pWin->parent))
{
client->errorValue = stuff->id;
return (BadWindow);
}
if ((err_code = xtsol_policy(TSOL_RES_TPWIN, TSOL_MODIFY, pWin, 0,
client, TSOL_ALL, &(MAJOROP))))
{
return (err_code);
}
pParent = pWin->parent;
if (pParent->firstChild != pWin)
{
tpwin = (WindowPtr)NULL;
ReflectStackChange(pWin, pParent->firstChild, VTStack);
}
}
tpwin = pWin;
/*
* Force kbd & ptr ungrab. This will cause
* screen to lock even when kbd/ptr grabbed by
* a client
*/
BreakAllGrabs(client);
return (client->noClientException);
}
/*
* Turn on window's Trusted bit
*/
static int
ProcMakeTrustedWindow(ClientPtr client)
{
WindowPtr pWin;
int rc;
int err_code;
TsolInfoPtr tsolinfo;
REQUEST(xMakeTrustedWindowReq);
REQUEST_SIZE_MATCH(xMakeTrustedWindowReq);
rc = dixLookupWindow(&pWin, stuff->id, client, DixWriteAccess);
if (rc != Success)
return rc;
/* window should not be root but child of root */
if (!pWin || (!pWin->parent))
{
client->errorValue = stuff->id;
return (BadWindow);
}
if ((err_code = xtsol_policy(TSOL_RES_TPWIN, TSOL_MODIFY, pWin, 0,
client, TSOL_ALL, &(MAJOROP))))
{
return (err_code);
}
tsolinfo = GetClientTsolInfo(client);
/* Turn on Trusted bit of the window */
tsolinfo->forced_trust = 1;
return (client->noClientException);
}
/*
* Turn off window's Trusted bit
*/
static int
ProcMakeUntrustedWindow(ClientPtr client)
{
WindowPtr pWin;
int rc;
int err_code;
TsolInfoPtr tsolinfo;
REQUEST(xMakeUntrustedWindowReq);
REQUEST_SIZE_MATCH(xMakeUntrustedWindowReq);
rc = dixLookupWindow(&pWin, stuff->id, client, DixWriteAccess);
if (rc != Success)
return rc;
/* window should not be root but child of root */
if (!pWin || (!pWin->parent))
{
client->errorValue = stuff->id;
return (BadWindow);
}
if ((err_code = xtsol_policy(TSOL_RES_TPWIN, TSOL_MODIFY, pWin, 0,
client, TSOL_ALL, &(MAJOROP))))
{
return (err_code);
}
tsolinfo = GetClientTsolInfo(client);
tsolinfo->forced_trust = 0;
tsolinfo->trusted_path = FALSE;
return (client->noClientException);
}
/*
* Break keyboard & ptr grabs of clients other than
* the requesting client.
* Called from ProcMakeTPWindow.
*/
static void
BreakAllGrabs(ClientPtr client)
{
ClientPtr grabclient;
DeviceIntPtr keybd = PickKeyboard(client);
GrabPtr kbdgrab = keybd->deviceGrab.grab;
DeviceIntPtr mouse = PickPointer(client);
GrabPtr ptrgrab = mouse->deviceGrab.grab;
if (kbdgrab) {
grabclient = clients[CLIENT_ID(kbdgrab->resource)];
if (client->index != grabclient->index)
(*keybd->deviceGrab.DeactivateGrab)(keybd);
}
if (ptrgrab) {
grabclient = clients[CLIENT_ID(ptrgrab->resource)];
if (client->index != grabclient->index)
(*mouse->deviceGrab.DeactivateGrab)(mouse);
}
}
/*
* Trusted Network interface module. Uses tsix API
*/
extern au_id_t ucred_getauid(const ucred_t *uc);
extern au_asid_t ucred_getasid(const ucred_t *uc);
extern const au_mask_t *ucred_getamask(const ucred_t *uc);
extern tsol_host_type_t tsol_getrhtype(char *);
static void
TsolSetClientInfo(ClientPtr client)
{
bslabel_t *sl;
bslabel_t admin_low;
priv_set_t *privs;
const au_mask_t *amask;
socklen_t namelen;
struct auditinfo auinfo;
struct auditinfo *pauinfo;
OsCommPtr oc = (OsCommPtr)client->osPrivate;
int fd = oc->fd;
ucred_t *uc = NULL;
TsolInfoPtr tsolinfo = TsolClientPriv(client);
/* Get client attributes from the socket */
if (getpeerucred(fd, &uc) == -1) {
const char *errmsg = strerror(errno);
tsolinfo->uid = (uid_t)(-1);
tsolinfo->sl = NULL;
snprintf(tsolinfo->pname, MAXNAME,
"client id %d (pid unknown)", client->index);
LogMessageVerb(X_ERROR, TSOL_MSG_ERROR,
TSOL_LOG_PREFIX "Cannot get client attributes"
" for %s, getpeerucred failed: %s\n",
tsolinfo->pname, errmsg);
return;
}
/* Extract individual fields from the cred structure */
tsolinfo->zid = ucred_getzoneid(uc);
tsolinfo->uid = ucred_getruid(uc);
tsolinfo->euid = ucred_geteuid(uc);
tsolinfo->gid = ucred_getrgid(uc);
tsolinfo->egid = ucred_getegid(uc);
tsolinfo->pid = ucred_getpid(uc);
sl = ucred_getlabel(uc);
tsolinfo->sl = (bslabel_t *)lookupSL(sl);
/* store a string for debug/error messages - would be nice to
get the real process name out of /proc in the future
*/
snprintf(tsolinfo->pname, MAXNAME, "client id %d (pid %d)",
client->index, tsolinfo->pid);
/* Set privileges */
if ((tsolinfo->privs = priv_allocset()) != NULL) {
if (tsolMultiLevel) {
privs = (priv_set_t *)ucred_getprivset(uc, PRIV_EFFECTIVE);
if (privs == NULL) {
priv_emptyset(tsolinfo->privs);
} else {
priv_copyset(privs, tsolinfo->privs);
}
} else {
priv_fillset(tsolinfo->privs);
}
}
tsolinfo->priv_debug = FALSE;
/*
* For remote hosts, the uid is determined during access control
* using Secure RPC
*/
if (tsolinfo->zid == (zoneid_t)-1) {
tsolinfo->client_type = CLIENT_REMOTE;
} else {
tsolinfo->client_type = CLIENT_LOCAL;
}
/* Set Trusted Path for local clients */
if (tsolinfo->zid == GLOBAL_ZONEID) {
tsolinfo->trusted_path = TRUE;
}else {
tsolinfo->trusted_path = FALSE;
}
if (tsolinfo->trusted_path || !tsolMultiLevel)
setClientTrustLevel(client, XSecurityClientTrusted);
else
setClientTrustLevel(client, XSecurityClientUntrusted);
tsolinfo->forced_trust = 0;
tsolinfo->iaddr = 0;
bsllow(&admin_low);
/* Set reasonable defaults for remote clients */
namelen = sizeof (tsolinfo->saddr);
if (getpeername(fd, (struct sockaddr *)&tsolinfo->saddr, &namelen) == 0
&& (tsolinfo->client_type == CLIENT_REMOTE)) {
int errcode;
char hostbuf[NI_MAXHOST];
tsol_host_type_t host_type;
/* Use NI_NUMERICHOST to avoid DNS lookup */
errcode = getnameinfo((struct sockaddr *)&(tsolinfo->saddr), namelen,
hostbuf, sizeof(hostbuf), NULL, 0, NI_NUMERICHOST);
if (errcode) {
perror(gai_strerror(errcode));
} else {
host_type = tsol_getrhtype(hostbuf);
if ((host_type == SUN_CIPSO) &&
blequal(tsolinfo->sl, &admin_low)) {
tsolinfo->trusted_path = TRUE;
setClientTrustLevel(client,
XSecurityClientTrusted);
priv_fillset(tsolinfo->privs);
}
}
}
/* setup audit context */
if (getaudit(&auinfo) == 0) {
pauinfo = &auinfo;
} else {
pauinfo = NULL;
}
/* Audit id */
tsolinfo->auid = ucred_getauid(uc);
if (tsolinfo->auid == AU_NOAUDITID) {
tsolinfo->auid = UID_NOBODY;
}
/* session id */
tsolinfo->asid = ucred_getasid(uc);
/* Audit mask */
if ((amask = ucred_getamask(uc)) != NULL) {
tsolinfo->amask = *amask;
} else {
if (pauinfo != NULL) {
tsolinfo->amask = pauinfo->ai_mask;
} else {
tsolinfo->amask.am_failure = 0; /* clear the masks */
tsolinfo->amask.am_success = 0;
}
}
tsolinfo->asaverd = 0;
ucred_free(uc);
}
static enum auth_stat tsol_why;
extern bool_t xdr_opaque_auth(XDR *, struct opaque_auth *);
static char *
tsol_authdes_decode(char *inmsg, int len)
{
struct rpc_msg msg;
char cred_area[MAX_AUTH_BYTES];
char verf_area[MAX_AUTH_BYTES];
char *temp_inmsg;
struct svc_req r;
bool_t res0, res1;
XDR xdr;
SVCXPRT xprt;
temp_inmsg = (char *) xalloc(len);
memmove(temp_inmsg, inmsg, len);
memset((char *)&msg, 0, sizeof(msg));
memset((char *)&r, 0, sizeof(r));
memset(cred_area, 0, sizeof(cred_area));
memset(verf_area, 0, sizeof(verf_area));
msg.rm_call.cb_cred.oa_base = cred_area;
msg.rm_call.cb_verf.oa_base = verf_area;
tsol_why = AUTH_FAILED;
xdrmem_create(&xdr, temp_inmsg, len, XDR_DECODE);
if ((r.rq_clntcred = (caddr_t) xalloc(MAX_AUTH_BYTES)) == NULL)
goto bad1;
r.rq_xprt = &xprt;
/* decode into msg */
res0 = xdr_opaque_auth(&xdr, &(msg.rm_call.cb_cred));
res1 = xdr_opaque_auth(&xdr, &(msg.rm_call.cb_verf));
if ( ! (res0 && res1) )
goto bad2;
/* do the authentication */
r.rq_cred = msg.rm_call.cb_cred; /* read by opaque stuff */
if (r.rq_cred.oa_flavor != AUTH_DES) {
tsol_why = AUTH_TOOWEAK;
goto bad2;
}
#ifdef SVR4
if ((tsol_why = __authenticate(&r, &msg)) != AUTH_OK) {
#else
if ((tsol_why = _authenticate(&r, &msg)) != AUTH_OK) {
#endif
goto bad2;
}
return (((struct authdes_cred *) r.rq_clntcred)->adc_fullname.name);
bad2:
Xfree(r.rq_clntcred);
bad1:
return ((char *)0); /* ((struct authdes_cred *) NULL); */
}
static Bool
TsolCheckNetName (unsigned char *addr, short len, pointer closure)
{
return (len == (short) strlen ((char *) closure) &&
strncmp ((char *) addr, (char *) closure, len) == 0);
}
extern int getdomainname(char *, int);
static XID
TsolCheckAuthorization(unsigned int name_length, char *name,
unsigned int data_length, char *data,
ClientPtr client, char **reason)
{
char domainname[128];
char netname[128];
char audit_ret;
u_int audit_val;
uid_t client_uid;
gid_t client_gid;
int client_gidlen;
char *fullname;
gid_t client_gidlist;
XID auth_token = (XID)(-1);
TsolInfoPtr tsolinfo = GetClientTsolInfo(client);
if (tsolinfo->uid == (uid_t) -1) {
/* Retrieve uid from SecureRPC */
if (strncmp(name, SECURE_RPC_AUTH, (size_t)name_length) == 0) {
fullname = tsol_authdes_decode(data, data_length);
if (fullname == NULL) {
ErrorF("Unable to authenticate Secure RPC client");
} else {
if (netname2user(fullname,
&client_uid, &client_gid,
&client_gidlen, &client_gidlist)) {
tsolinfo->uid = client_uid;
} else {
ErrorF("netname2user failed");
}
}
}
}
if (tsolinfo->uid == (uid_t)-1) {
tsolinfo->uid = UID_NOBODY; /* uid not available */
}
/*
* For multilevel desktop, limit connections to the trusted path
* i.e. global zone until a user logs in and the trusted stripe
* is in place. Unlabeled connections are rejected.
*/
if ((OwnerUID == (uid_t )(-1)) || (tsolMultiLevel && tpwin == NULL)) {
if (HasTrustedPath(tsolinfo)) {
auth_token = CheckAuthorization(name_length, name, data_length,
data, client, reason);
}
} else {
/*
* Workstation Owner set, client must be within label
* range or have trusted path
*/
if (tsolinfo->uid == OwnerUID) {
if ((tsolinfo->sl != NULL &&
(bldominates(tsolinfo->sl, &SessionLO) &&
bldominates(&SessionHI, tsolinfo->sl))) ||
(HasTrustedPath(tsolinfo))) {
auth_token = (XID)(tsolinfo->uid);
}
} else {
/* Allow root from global zone */
if (tsolinfo->uid == 0 && HasTrustedPath(tsolinfo)) {
auth_token = (XID)(tsolinfo->uid);
} else {
/*
* Access check based on uid. Check if
* roles or other uids have been added by
* xhost +role@
*/
getdomainname(domainname, sizeof(domainname));
if (!user2netname(netname, tsolinfo->uid, domainname)) {
return ((XID)-1);
}
if (ForEachHostInFamily (FamilyNetname, TsolCheckNetName,
(pointer) netname)) {
return ((XID)(tsolinfo->uid));
} else {
return (CheckAuthorization(name_length, name, data_length,
data, client, reason));
}
}
}
}
/* Audit the connection */
if (auth_token == (XID)(-1)) {
audit_ret = (char )-1; /* failure */
audit_val = 1;
} else {
audit_ret = 0; /* success */
audit_val = 0;
}
if (system_audit_on &&
(au_preselect(AUE_ClientConnect, &(tsolinfo->amask),
AU_PRS_BOTH, AU_PRS_USECACHE) == 1)) {
int status;
u_short connect_port = 0;
struct in_addr *connect_addr = NULL;
struct sockaddr_in *sin;
struct sockaddr_in6 *sin6;
switch (tsolinfo->saddr.ss_family) {
case AF_INET:
sin = (struct sockaddr_in *)&(tsolinfo->saddr);
connect_addr = &(sin->sin_addr);
connect_port = sin->sin_port;
break;
case AF_INET6:
sin6 = (struct sockaddr_in6 *)&(tsolinfo->saddr);
connect_addr = (struct in_addr *)&(sin6->sin6_addr);
connect_port = sin6->sin6_port;
break;
}
if (connect_addr == NULL || connect_port == 0) {
status = auditwrite(AW_EVENTNUM, AUE_ClientConnect,
AW_XCLIENT, client->index,
AW_SLABEL, tsolinfo->sl,
AW_RETURN, audit_ret, audit_val,
AW_WRITE, AW_END);
} else {
status = auditwrite(AW_EVENTNUM, AUE_ClientConnect,
AW_XCLIENT, client->index,
AW_SLABEL, tsolinfo->sl,
AW_INADDR, connect_addr,
AW_IPORT, connect_port,
AW_RETURN, audit_ret, audit_val,
AW_WRITE, AW_END);
}
if (!status)
(void) auditwrite(AW_FLUSH, AW_END);
tsolinfo->flags &= ~TSOL_DOXAUDIT;
tsolinfo->flags &= ~TSOL_AUDITEVENT;
}
return (auth_token);
}
static CALLBACK(
TsolProcessKeyboard)
{
XaceKeyAvailRec *rec = (XaceKeyAvailRec *) calldata;
xEvent *xE = rec->event;
DeviceIntPtr keybd = rec->keybd;
/* int count = rec->count; */
KeyClassPtr keyc = keybd->key;
if (xE->u.u.type == KeyPress)
{
if (!hotkey.initialized)
InitHotKey(&hotkey);
if (((xE->u.u.detail == hotkey.key) &&
(keyc->state != 0 && keyc->state == hotkey.shift)) ||
((xE->u.u.detail == hotkey.altkey) &&
(keyc->state != 0 && keyc->state == hotkey.altshift)))
HandleHotKey(keybd);
}
}
static CALLBACK(
TsolCheckSendAccess)
{
XaceSendAccessRec *rec = (XaceSendAccessRec *) calldata;
ClientPtr client = rec->client;
WindowPtr pWin = rec->pWin;
if (client == NULL) {
rec->status = Success;
return;
}
rec->status = xtsol_policy(TSOL_RES_EVENTWIN, TSOL_MODIFY,
pWin, 0, client, TSOL_ALL, (&(MAJOROP)));
}
static CALLBACK(
TsolCheckReceiveAccess)
{
XaceReceiveAccessRec *rec = (XaceReceiveAccessRec *) calldata;
rec->status = Success;
}
static CALLBACK(
TsolCheckDeviceAccess)
{
XaceDeviceAccessRec *rec = (XaceDeviceAccessRec *) calldata;
ClientPtr client = rec->client;
Mask access_mode = rec->access_mode;
int reqtype;
TsolInfoPtr tsolinfo;
if (client->requestBuffer) {
reqtype = MAJOROP; /* protocol */
} else {
reqtype = -1;
}
/*
* The Create case seems to be for initialization, so we don't
* want it to fail and there isn't a corresponding protocol request type.
*/
if (access_mode & DixCreateAccess) {
rec->status = Success;
return;
}
switch (reqtype) {
case X_Bell:
rec->status = xtsol_policy(TSOL_RES_BELL, TSOL_MODIFY,
NULL, 0, client, TSOL_ALL, &(MAJOROP));
break;
case X_GetPointerControl:
rec->status = xtsol_policy(TSOL_RES_PTRCTL, TSOL_READ,
NULL, 0, client, TSOL_ALL, &(MAJOROP));
break;
case X_ChangePointerControl:
rec->status = xtsol_policy(TSOL_RES_PTRCTL, TSOL_MODIFY,
NULL, 0, client, TSOL_ALL, &(MAJOROP));
break;
case X_GetKeyboardControl:
rec->status = xtsol_policy(TSOL_RES_KBDCTL, TSOL_READ,
NULL, 0, client, TSOL_ALL, &(MAJOROP));
break;
case X_ChangeKeyboardControl:
rec->status = xtsol_policy(TSOL_RES_KBDCTL, TSOL_MODIFY,
NULL, 0, client, TSOL_ALL, &(MAJOROP));
break;
case X_GetKeyboardMapping:
rec->status = xtsol_policy(TSOL_RES_KEYMAP, TSOL_READ,
NULL, 0, client, TSOL_ALL, &(MAJOROP));
break;
case X_ChangeKeyboardMapping:
rec->status = xtsol_policy(TSOL_RES_KEYMAP, TSOL_MODIFY,
NULL, 0, client, TSOL_ALL, &(MAJOROP));
break;
case X_GetMotionEvents:
rec->status = xtsol_policy(TSOL_RES_PTRMOTION, TSOL_READ,
NULL, 0, client, TSOL_ALL, &(MAJOROP));
break;
case X_QueryKeymap:
rec->status = xtsol_policy(TSOL_RES_KEYMAP, TSOL_READ,
NULL, 0, client, TSOL_ALL, &(MAJOROP));
break;
case X_SetModifierMapping:
rec->status = xtsol_policy(TSOL_RES_MODMAP, TSOL_MODIFY,
NULL, 0, client, TSOL_ALL, &(MAJOROP));
break;
default:
#ifndef NO_TSOL_DEBUG_MESSAGES
tsolinfo = GetClientTsolInfo(client);
LogMessageVerb(X_NOT_IMPLEMENTED, TSOL_MSG_UNIMPLEMENTED,
TSOL_LOG_PREFIX
"policy not implemented for CheckDeviceAccess(%s, %s, %s) = %s\n",
tsolinfo->pname,
TsolDixAccessModeNameString(access_mode),
TsolRequestNameString(reqtype),
TsolErrorNameString(rec->status));
#endif /* !NO_TSOL_DEBUG_MESSAGES */
rec->status = Success;
break;
}
}
static CALLBACK(
TsolCheckSelectionAccess)
{
XaceSelectionAccessRec *rec = (XaceSelectionAccessRec *) calldata;
ClientPtr client = rec->client;
Selection *pSel = *rec->ppSel;
Atom selAtom = pSel->selection;
Mask access_mode = rec->access_mode;
int reqtype;
TsolSelnPtr tsolseln;
TsolInfoPtr tsolinfo; /* tsol client info */
tsolinfo = GetClientTsolInfo(client);
int polySelection = PolySelection(selAtom);
rec->status = Success;
if (client->requestBuffer) {
reqtype = MAJOROP; /* protocol */
} else {
reqtype = -1;
}
switch (reqtype) {
case X_SetSelectionOwner:
/*
* Special processing for selection agent. This is how
* we know who to redirect privileged ConvertSelection requests.
* This is also used to fake the onwership of GetSelectionOwner requests.
*/
if (selAtom == tsol_atom_sel_agnt) {
if (HasWinSelection(tsolinfo)) {
if (tsolinfo->flags & TSOL_AUDITEVENT)
auditwrite(AW_USEOFPRIV, 1, PRIV_WIN_SELECTION,
AW_APPEND, AW_END);
tsol_sel_agnt = pSel; /* owner of this seln */
} else {
if (tsolinfo->flags & TSOL_AUDITEVENT)
auditwrite(AW_USEOFPRIV, 0, PRIV_WIN_SELECTION,
AW_APPEND, AW_END);
client->errorValue = selAtom;
rec->status = BadAtom;
return;
}
}
/*
* The callback function is only called if at least one matching selection exists.
* If it has no tsol attributes then we know it is the only match so we don't need to
* check for polyinstantiation. Just initialize it and return.
*/
tsolseln = TsolSelectionPriv(pSel);
if (tsolseln->sl == NULL) {
tsolseln->sl = tsolinfo->sl;
tsolseln->uid = tsolinfo->uid;
break;
}
if (polySelection) {
/* for poly-selections, search from the beginning to see if sl,uid match */
for (pSel = CurrentSelections; pSel; pSel = pSel->next) {
if (pSel->selection == selAtom) {
tsolseln = TsolSelectionPriv(pSel);
if (tsolseln->uid == tsolinfo->uid &&
tsolseln->sl == tsolinfo->sl)
break;
}
}
if (pSel) {
/* found a match */
*rec->ppSel = pSel;
} else {
/*
* Doesn't match yet; we'll get called again
* After it gets created.
*/
rec->status = BadMatch;
}
} else {
/* Assign the sl & uid */
tsolseln->sl = tsolinfo->sl;
tsolseln->uid = tsolinfo->uid;
}
break;
case X_GetSelectionOwner:
case X_ConvertSelection:
if (polySelection) {
/* for poly-selections, search from the beginning to see if sl,uid match */
for (pSel = CurrentSelections; pSel; pSel = pSel->next) {
if (pSel->selection == selAtom) {
tsolseln = TsolSelectionPriv(pSel);
if (tsolseln->uid == tsolinfo->uid &&
tsolseln->sl == tsolinfo->sl)
break;
}
}
if (pSel) {
*rec->ppSel = pSel; /* found match */
} else {
/*
* Doesn't match yet; we'll get called again
* After it gets created.
*/
rec->status = BadMatch;
return;
}
}
/*
* Selection Agent processing. Override the owner
*/
tsolseln = TsolSelectionPriv(pSel);
if (!HasWinSelection(tsolinfo) &&
(tsolseln->uid != tsolinfo->uid ||
tsolseln->sl != tsolinfo->sl) &&
pSel->window != None && tsol_sel_agnt != NULL) {
pSel = tsol_sel_agnt;
} else {
if (HasWinSelection(tsolinfo) &&
(tsolinfo->flags & TSOL_AUDITEVENT)) {
auditwrite(AW_USEOFPRIV, 1, PRIV_WIN_SELECTION, AW_APPEND, AW_END);
}
}
*rec->ppSel = pSel;
break;
default:
#ifndef NO_TSOL_DEBUG_MESSAGES
tsolinfo = GetClientTsolInfo(client);
LogMessageVerb(X_NOT_IMPLEMENTED, TSOL_MSG_UNIMPLEMENTED,
TSOL_LOG_PREFIX
"policy not implemented for CheckSelectionAccess(%s, %s, %s, %s) = %s\n",
tsolinfo->pname,
TsolDixAccessModeNameString(access_mode),
TsolRequestNameString(reqtype),
NameForAtom(selAtom),
TsolErrorNameString(rec->status));
#endif /* !NO_TSOL_DEBUG_MESSAGES */
break;
}
}
static CALLBACK(
TsolCheckPropertyAccess)
{
XacePropertyAccessRec *rec = (XacePropertyAccessRec *) calldata;
ClientPtr client = rec->client;
WindowPtr pWin = rec->pWin;
PropertyPtr pProp = *rec->ppProp;
Atom propertyName = pProp->propertyName;
Mask access_mode = rec->access_mode;
TsolInfoPtr tsolinfo = GetClientTsolInfo(client);
int reqtype;
TsolPropPtr tsolprop;
TsolResPtr tsolres;
int tsol_method;
Status retcode;
if (client->requestBuffer) {
reqtype = MAJOROP; /* protocol */
} else {
reqtype = -1;
}
if (pProp != NULL) {
int polyprop = PolyProperty(propertyName, pWin);
tsolprop = TsolPropertyPriv(pProp);
if (!polyprop) {
tsolres = TsolWindowPriv(pWin);
if (tsolprop->sl == NULL) {
/* Initialize with label/uid etc */
if (WindowIsRoot(pWin)) {
tsolprop->sl = tsolinfo->sl; /* use client's sl/uid */
tsolprop->uid = tsolinfo->uid;
tsolprop->pid = tsolinfo->pid;
} else {
tsolprop->sl = tsolres->sl; /* use window's sl/uid */
tsolprop->uid = tsolres->uid;
tsolprop->pid = tsolres->pid;
}
}
if (access_mode & (DixReadAccess | DixGetAttrAccess))
tsol_method = TSOL_READ;
else
tsol_method = TSOL_MODIFY;
retcode = xtsol_policy(TSOL_RES_PROPERTY, tsol_method, pProp, 0,
client, TSOL_ALL, &reqtype);
if (retcode != Success && (access_mode & DixGetAttrAccess)) {
/* If current property is not accessible, move on to
* next one for ListProperty
*/
retcode = Success;
*rec->ppProp = pProp->next; /* ignore failurefor List Prop */
}
rec->status = retcode;
} else {
/* Handle polyinstantiated property */
if (tsolprop->sl == NULL) { /* New PolyProp */
if (!(access_mode & DixCreateAccess)) {
rec->status = BadImplementation;
return;
}
/* Initialize with label/uid */
tsolprop->sl = tsolinfo->sl;
tsolprop->uid = tsolinfo->uid;
tsolprop->next = (TsolPropPtr)NULL;
rec->status = Success;
} else {
/* search for a matching (sl, uid) pair */
while (pProp) {
tsolprop = TsolPropertyPriv(pProp);
if (pProp->propertyName == propertyName &&
tsolprop->sl == tsolinfo->sl &&
tsolprop->uid == tsolinfo->uid)
break; /* match found */
pProp = pProp->next;
}
if (pProp) {
*rec->ppProp = pProp; /* found */
rec->status = Success;
} else {
rec->status = BadMatch;
}
}
}
#ifndef NO_TSOL_DEBUG_MESSAGES
LogMessageVerb(X_INFO, TSOL_MSG_ACCESS_TRACE,
TSOL_LOG_PREFIX
"TsolCheckPropertyAccess(%s, 0x%x, %s, %s) = %s\n",
tsolinfo->pname, pWin->drawable.id,
NameForAtom(propertyName),
TsolDixAccessModeNameString(access_mode),
TsolPolicyReturnString(rec->status));
#endif /* !NO_TSOL_DEBUG_MESSAGES */
}
}
static CALLBACK(
TsolCheckExtensionAccess)
{
XaceExtAccessRec *rec = (XaceExtAccessRec *) calldata;
if (TsolDisabledExtension(rec->ext->name)) {
rec->status = BadAccess;
}
}
#ifdef UNUSED
/*
* Return TRUE if host is cipso
*/
int
host_is_cipso(int fd)
{
struct sockaddr sname;
socklen_t namelen;
char *rhost;
tsol_host_type_t host_type;
struct sockaddr_in *so = (struct sockaddr_in *)&sname;
extern tsol_host_type_t tsol_getrhtype(char *);
namelen = sizeof (sname);
if (getpeername(fd, &sname, &namelen) == -1) {
perror("getsockname: failed\n");
return FALSE;
}
rhost = inet_ntoa(so->sin_addr);
host_type = tsol_getrhtype(rhost);
if (host_type == SUN_CIPSO) {
return TRUE;
}
return FALSE;
}
#endif