tsolutils.c revision 1088
98N/A/*
98N/A * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
943N/A *
98N/A * Permission is hereby granted, free of charge, to any person obtaining a
98N/A * copy of this software and associated documentation files (the "Software"),
919N/A * to deal in the Software without restriction, including without limitation
919N/A * the rights to use, copy, modify, merge, publish, distribute, sublicense,
919N/A * and/or sell copies of the Software, and to permit persons to whom the
919N/A * Software is furnished to do so, subject to the following conditions:
919N/A *
919N/A * The above copyright notice and this permission notice (including the next
919N/A * paragraph) shall be included in all copies or substantial portions of the
919N/A * Software.
919N/A *
919N/A * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
919N/A * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
919N/A * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
919N/A * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
919N/A * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
919N/A * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
919N/A * DEALINGS IN THE SOFTWARE.
919N/A */
98N/A
98N/A
98N/A#ifdef HAVE_DIX_CONFIG_H
493N/A#include <dix-config.h>
493N/A#endif
98N/A
970N/A#include <stdio.h>
970N/A#include <X11/X.h>
970N/A#include <X11/Xproto.h>
970N/A#include <X11/Xprotostr.h>
970N/A#include "auditwrite.h"
970N/A#include <bsm/audit_uevents.h>
970N/A#include <regex.h>
970N/A#include <priv.h>
970N/A#include <X11/Xproto.h>
970N/A#include "windowstr.h"
970N/A#include "scrnintstr.h"
970N/A#include "xkbstr.h"
98N/A#include "xkbsrv.h"
753N/A#include "tsol.h"
98N/A#include "tsolinfo.h"
911N/A#include "tsolpolicy.h"
911N/A#include <X11/keysym.h>
911N/A#include "misc.h"
911N/A#include "inputstr.h"
98N/A#include "propertyst.h"
493N/A#include "panoramiXsrv.h"
493N/A#include "registry.h"
98N/A
98N/A#define MAX_SL_ENTRY 256
156N/A#define MAX_UID_ENTRY 64
156N/A#define ALLOCATED 1
493N/A#define EMPTIED 0
493N/A#define FamilyTSOL 5
493N/A#define TSOLUIDlength 4
493N/A
493N/A#define BOXES_OVERLAP(b1, b2) \
493N/A (!( ((b1)->x2 <= (b2)->x1) || \
493N/A ( ((b1)->x1 >= (b2)->x2)) || \
98N/A ( ((b1)->y2 <= (b2)->y1)) || \
98N/A ( ((b1)->y1 >= (b2)->y2)) ) )
98N/A
705N/ABool system_audit_on = FALSE;
705N/ABool priv_win_colormap = FALSE;
814N/ABool priv_win_config = FALSE;
814N/ABool priv_win_devices = FALSE;
606N/ABool priv_win_dga = FALSE;
606N/ABool priv_win_fontpath = FALSE;
606N/A
606N/A
705N/A/*
967N/A * The following need to be moved to tsolextension.c
606N/A * after all references in Xsun is pulled out
606N/A */
606N/AWindowPtr tpwin = NULL; /* only one trusted path window at a time */
606N/ATsolPolyInstInfoRec tsolpolyinstinfo;
606N/A#define TsolMaxPolyNameSize 80
606N/A/*
606N/A * Use the NodeRec struct in tsolinfo.h. This is referenced
606N/A * in policy routines. So we had to move it there
606N/A */
606N/Astatic TsolPolyAtomRec tsolpolyprop = {FALSE, 0, 0, NULL};
606N/Astatic TsolPolyAtomRec tsolpolyseln = {TRUE, 0, 0, NULL};
606N/A
606N/Abclear_t SessionHI; /* HI Clearance */
98N/Abclear_t SessionLO; /* LO Clearance */
970N/Aunsigned int StripeHeight = 0;
970N/Auid_t OwnerUID = (uid_t)(-1);
970N/Abslabel_t PublicObjSL;
493N/A
493N/AAtom tsol_lastAtom = None;
493N/Aint tsol_nodelength = 0;
98N/ATsolNodePtr tsol_node = NULL;
647N/A
606N/A/* This structure is used for protocol request ListHosts */
606N/Astruct xUIDreply
98N/A{
647N/A unsigned char family;
647N/A unsigned char pad;
647N/A unsigned short length;
647N/A int uid; /* uid type */
606N/A};
606N/A
98N/Astruct slentry
606N/A{
606N/A bslabel_t senlabel;
98N/A char allocated;
493N/A};
493N/A
98N/Astatic struct slentry sltable[MAX_SL_ENTRY];
705N/A
705N/A/* This table contains list of users who can connect to the server */
705N/Astruct uidentry
493N/A{
493N/A int userid; /* uid type */
493N/A char allocated;
705N/A};
705N/A
705N/Astatic struct uidentry uidtable[MAX_UID_ENTRY];
970N/A
970N/A/* Index must match with keywords */
970N/Astatic char *tsolconfig_keywords[] = {"atom", "property", "selection",
970N/A "extension", "privilege"};
970N/A
970N/A#define KEYWORDCOUNT sizeof(tsolconfig_keywords)/sizeof(char *)
970N/A
970N/Atypedef struct _TsolConfig
970N/A{
970N/A int count;
970N/A char **list;
970N/A} TsolConfigRec;
970N/A
970N/Astatic TsolConfigRec tsolconfig[KEYWORDCOUNT] = {
970N/A {0, NULL},
970N/A {0, NULL},
970N/A {0, NULL},
970N/A {0, NULL},
970N/A {0, NULL}
970N/A};
970N/A
970N/A#define TSOL_ATOMCOUNT 4
970N/Astatic const char *tsolatomnames[TSOL_ATOMCOUNT] = {
970N/A "_TSOL_CMWLABEL_CHANGE",
970N/A "_TSOL_GRABNOTIFY",
970N/A "_TSOL_CLIENT_TERM",
970N/A "_TSOL_SEL_AGNT"
970N/A};
970N/A
970N/Astatic void
970N/Ainit_TSOL_cached_SL(void)
970N/A{
970N/A sltable[0].allocated = ALLOCATED;
970N/A bsllow (&(sltable[0].senlabel));
970N/A
970N/A sltable[1].allocated = ALLOCATED;
970N/A bslhigh(&(sltable[1].senlabel));
970N/A
970N/A}
970N/A
970N/A/* Initialize UID table, this table should at least contains owner UID */
970N/Astatic void
970N/Ainit_TSOL_uid_table(void)
970N/A{
970N/A uidtable[0].allocated = ALLOCATED;
970N/A uidtable[0].userid = 0;
970N/A}
970N/A
970N/A#if UNUSED
970N/A/* Count how many valid entried in the uid table */
970N/Aint
970N/Acount_uid_table(void)
970N/A{
970N/A int i, count = 0;
970N/A
970N/A /* Search entire table */
970N/A for (i = 0; i < MAX_UID_ENTRY; i++)
970N/A {
970N/A if (uidtable[i].allocated == ALLOCATED)
970N/A count++;
970N/A }
970N/A return (count);
970N/A}
970N/A
970N/A/* return (1); if userid is in the table */
970N/Aint
970N/AlookupUID(int userid)
970N/A{
970N/A int i;
970N/A for (i = 0; i < MAX_UID_ENTRY; i++)
970N/A {
970N/A if (uidtable[i].allocated == ALLOCATED &&
970N/A uidtable[i].userid == userid)
970N/A {
970N/A return (1); /* yes, found it */
970N/A }
970N/A }
970N/A return (0); /* not found */
970N/A}
970N/A
970N/A/* Passed into a pointer to a storage which is used to store UID */
970N/A/* and nUid represents how many UID in the table(returned by count_uid_table) */
970N/Aint
970N/AListUID(
970N/A struct xUIDreply * uidaddr,
970N/A int nUid)
970N/A{
970N/A int i, j = 0;
970N/A
970N/A for (i = 0; i < MAX_UID_ENTRY; i++)
970N/A {
if (uidtable[i].allocated == ALLOCATED)
{
uidaddr[j].family = FamilyTSOL;
uidaddr[j].length = TSOLUIDlength;
uidaddr[j].uid = uidtable[i].userid;
j++;
}
}
if (nUid != j)
{
ErrorF("Invalid no. of uid entries? \n");
return (0);
}
return (1);
}
#endif /* UNUSED */
/* add userid into UIDtable */
int
AddUID(int *userid)
{
int i = 0;
/*
* Search entire uidtable, to prevent duplicate uid
* entry in the table
*/
while (i < MAX_UID_ENTRY)
{
if ((uidtable[i].allocated == ALLOCATED) &&
(uidtable[i].userid == *userid))
{
/* this uid entry is already in the table; no-op */
return (1); /* Success, uid in the table */
}
i++;
}
i = 0;
/*
* If we can find an empty entry, then add this uid
* into the table
*/
while (i < MAX_UID_ENTRY)
{
if (uidtable[i].allocated != ALLOCATED)
{
uidtable[i].allocated = ALLOCATED;
uidtable[i].userid = *userid;
return (1); /* Success, uid in the table */
}
i++;
}
/* uidtable overflow */
ErrorF("Server problem: Please enlarge the table size of uidtable \n");
return (0);
}
#if UNUSED
/* remove userid from UIDtable */
int
RemoveUID(int *userid)
{
int i = 0;
if (*userid == 0)
{
ErrorF("\n UID 0 can not be removed from server UID list");
return (0);
}
while (i < MAX_UID_ENTRY)
{
if ((uidtable[i].allocated == ALLOCATED) &&
(uidtable[i].userid == *userid))
{
/* delete this entry in the table */
uidtable[i].allocated = EMPTIED;
return (1); /* Success, uid in the table */
}
i++;
}
/* no such entry in the table, why delete it? no-op */
return (0);
}
#endif
bslabel_t *
lookupSL_low(void)
{
return (&(sltable[0].senlabel));
}
bslabel_t *
lookupSL(bslabel_t *slptr)
{
int i = 0;
if (slptr == NULL)
return (slptr);
while ((i < MAX_SL_ENTRY) && sltable[i].allocated == ALLOCATED)
{
if (blequal(slptr, &(sltable[i].senlabel)))
{
/* found a matching sensitivity label in sltable */
return (&(sltable[i].senlabel));
}
i++;
}
if (i < MAX_SL_ENTRY)
{
/*
* can't find a matching entry in sltable,
* however, we have empty entry to store this
* new sensitivity label; store it.
*/
sltable[i].allocated = ALLOCATED;
memcpy (&(sltable[i].senlabel), slptr, sizeof (bslabel_t));
return (&(sltable[i].senlabel));
}
/*
* no matching entry in sltable, and no room to
* store this new sensitivity label,
* the server needs to recomplie with a larger slabel
*/
ErrorF("Server problem: Please enlarge the table size of sltable \n");
return (NULL);
}
static const int padlength[4] = {0, 3, 2, 1};
/* Updated version based roughly on RREditConnectionInfo in randr/rrscreen.c */
int
DoScreenStripeHeight(int screen_num)
{
int i, j;
xConnSetup *connSetup;
char *vendor;
xPixmapFormat *formats;
xWindowRoot *root;
xDepth *depth;
xVisualType *visual;
ScreenPtr pScreen;
int old_height;
float height_mult;
connSetup = (xConnSetup *) ConnectionInfo;
vendor = (char *) connSetup + sizeof (xConnSetup);
formats = (xPixmapFormat *) ((char *) vendor +
connSetup->nbytesVendor +
padlength[connSetup->nbytesVendor & 3]);
root = (xWindowRoot *) ((char *) formats +
sizeof (xPixmapFormat) *
screenInfo.numPixmapFormats);
for (i = 0; i < screen_num; i++)
{
depth = (xDepth *) ((char *) root +
sizeof (xWindowRoot));
for (j = 0; j < (int)root->nDepths; j++)
{
visual = (xVisualType *) ((char *) depth +
sizeof (xDepth));
depth = (xDepth *) ((char *) visual +
depth->nVisuals *
sizeof (xVisualType));
}
root = (xWindowRoot *) ((char *) depth);
}
old_height = root->pixHeight;
if (noPanoramiXExtension)
{
pScreen = screenInfo.screens[screen_num];
root->pixHeight = pScreen->height - StripeHeight;
} else
{
root->pixHeight = PanoramiXPixHeight - StripeHeight;
}
/* compute new millimeter height */
height_mult = (1.0 * root->pixHeight) / old_height;
root->mmHeight *= height_mult;
return (0);
}
extern int cannot_audit(int); /* bsm function */
void
init_xtsol(void)
{
bclearhigh(&SessionHI);
bclearlow(&SessionLO);
bsllow(&PublicObjSL);
init_TSOL_cached_SL();
init_TSOL_uid_table();
if (cannot_audit(TRUE))
system_audit_on = FALSE;
else
system_audit_on = TRUE;
auditwrite(AW_QUEUE, XAUDIT_Q_SIZE, AW_END);
}
/*
* Converts keycode to keysym, helper function.
* Modelled after Xlib code
*/
static KeySym
KeycodetoKeysym(KeyCode keycode, int col, KeySymsPtr curKeySyms)
{
int per = curKeySyms->mapWidth;
KeySym *syms = curKeySyms->map;
KeySym lsym = 0, usym = 0;
if ((col < 0) || ((col >= per) && (col > 3)) ||
((int)keycode < curKeySyms->minKeyCode) ||
((int)keycode > curKeySyms->maxKeyCode))
return NoSymbol;
syms = &curKeySyms->map[(keycode - curKeySyms->minKeyCode) * per];
if (col < 4) {
if (col > 1) {
while ((per > 2) && (syms[per - 1] == NoSymbol))
per--;
if (per < 3)
col -= 2;
}
if ((per <= (col|1)) || (syms[col|1] == NoSymbol)) {
if (!(col & 1))
return lsym;
else if (usym == lsym)
return NoSymbol;
else
return usym;
}
}
return syms[col];
}
/*
* Converts keysym to a keycode
* Modelled after Xlib code
*/
static KeyCode
KeysymToKeycode(KeySym ks, KeySymsPtr curKeySyms)
{
int i, j;
for (j = 0; j < curKeySyms->mapWidth; j++) {
for (i = curKeySyms->minKeyCode; i <= curKeySyms->maxKeyCode; i++) {
if (KeycodetoKeysym((KeyCode) i, j, curKeySyms) == ks)
return i;
}
}
return 0;
}
/*
* converts a keysym to modifier equivalent mask
* Modelled after Xlib
*/
static unsigned
KeysymToModifier(KeySym ks, KeySymsPtr keysyms,
KeyCode *modifierKeyMap, int maxKeysPerModifier)
{
CARD8 code, mods;
KeySym *kmax;
KeySym *k;
kmax = keysyms->map + (keysyms->maxKeyCode - keysyms->minKeyCode + 1) *
keysyms->mapWidth;
k = keysyms->map;
mods = 0;
while (k < kmax) {
if (*k == ks ) {
int j = maxKeysPerModifier << 3;
code = (((k - keysyms->map) / keysyms->mapWidth) + keysyms->minKeyCode);
while (--j >= 0) {
if (code == modifierKeyMap[j])
mods |= (1 << (j / maxKeysPerModifier));
}
}
k++;
}
return mods;
}
/*
* Initialize Hot Key keys. On A Sun type 5/6 keyboard
* It's Meta(Diamond) + Stop. On a non-Sun keyboard, it's
* Alt + Break(Pause) key. Hold down the meta or alt key
* press stop or break key.
*
* NOTE:
* Both Left & Right keys for (Meta or Alt) return the
* same modifier mask
*/
void
InitHotKey(DeviceIntPtr keybd)
{
HotKeyPtr hk = TsolKeyboardPrivate(keybd);
KeySymsPtr curKeySyms = XkbGetCoreMap(keybd);
int rc;
int max_keys_per_mod = 0;
KeyCode *modkeymap = NULL;
rc = generate_modkeymap(serverClient, keybd,
&modkeymap, &max_keys_per_mod);
/* Meta + Stop */
hk->shift = KeysymToModifier(XK_Meta_L, curKeySyms,
modkeymap, max_keys_per_mod);
hk->key = KeysymToKeycode(XK_L1, curKeySyms);
/* Alt + Break/Pause */
hk->altshift = KeysymToModifier(XK_Alt_L, curKeySyms,
modkeymap, max_keys_per_mod);
hk->altkey = KeysymToKeycode(XK_Pause, curKeySyms);
hk->initialized = TRUE;
}
static void
UpdateTsolConfig(char *keyword, char *value)
{
int i;
int count;
char **newlist;
if (keyword == NULL || value == NULL)
return; /* ignore incomplete entries */
/* find a matching keyword */
for (i = 0; i < KEYWORDCOUNT; i++) {
if (strcmp(keyword, tsolconfig_keywords[i]) == 0) {
break;
}
}
/* Invalid keyword */
if (i >= KEYWORDCOUNT) {
ErrorF("Invalid keyword : %s\n", keyword);
return;
}
count = tsolconfig[i].count;
newlist = realloc(tsolconfig[i].list, (count + 1) * sizeof(char **));
if (newlist == NULL) {
ErrorF("Not enough memory for %s %s\n", keyword, value);
return;
}
newlist[count] = strdup(value);
tsolconfig[i].list = newlist;
tsolconfig[i].count++;
}
static void
InitPrivileges(void)
{
int i;
int count;
char **list;
count = tsolconfig[TSOL_PRIVILEGE].count;
list = tsolconfig[TSOL_PRIVILEGE].list;
for (i = 0; i < count; i++) {
if (strcmp(list[i], PRIV_WIN_COLORMAP) == 0)
priv_win_colormap = TRUE;
else if (strcmp(list[i], PRIV_WIN_CONFIG) == 0)
priv_win_config = TRUE;
else if (strcmp(list[i], PRIV_WIN_DEVICES) == 0)
priv_win_devices = TRUE;
else if (strcmp(list[i], PRIV_WIN_FONTPATH) == 0)
priv_win_fontpath = TRUE;
else if (strcmp(list[i], PRIV_WIN_DGA) == 0)
priv_win_dga = TRUE;
}
}
/*
* Load Trusted Solaris configuration file
*/
void
LoadTsolConfig(void)
{
FILE *fp;
char buf[BUFSIZ];
char *keyword;
char *value;
/* open the file from /etc first followed by /usr */
if ((fp = fopen(TSOLPOLICYFILE, "r")) == NULL) {
ErrorF("Cannot load %s. Some desktop applications may not\n"
"work correctly\n", TSOLPOLICYFILE);
return;
}
/* Read and parse the config file */
while (fgets(buf, sizeof (buf), fp) != NULL) {
/* ignore all comments, lines starting with white space */
if (buf[0] == '#' || isspace((int)buf[0]))
continue;
keyword = strtok(buf, " \t");
value = strtok(NULL, " \t\n");
UpdateTsolConfig(keyword, value);
}
InitPrivileges();
}
/*
* It does not really tell if this atom is to be polyinstantiated
* or not. Further check should be done to determine this.
*/
int
SpecialName(const char *string, int len)
{
return (MatchTsolConfig(string, len));
}
void
MakeTSOLAtoms(void)
{
int i;
char *atomname;
/* Create new TSOL atoms */
for (i = 0; i < TSOL_ATOMCOUNT; i++) {
if (MakeAtom(tsolatomnames[i], strlen(tsolatomnames[i]), TRUE) == None)
AtomError();
}
/* Create atoms defined in config file */
for (i = 0; i < tsolconfig[TSOL_ATOM].count; i++) {
atomname = tsolconfig[TSOL_ATOM].list[i];
if (MakeAtom(atomname, strlen(atomname), TRUE) == None) {
AtomError();
}
}
}
/*
* Names starting with a slash in selection.atoms and property.atoms
* are treated as regular expressions to be matched against the
* selection and property names. They may optionally end with a slash.
*/
static int
regexcompare(const char *string, int len, char *regexp)
{
int status;
regex_t compiledregexp;
char *regexpstrp;
int regexpstrlen;
char buffer[BUFSIZ];
if (regexp[0] == '/' && len < BUFSIZ) {
/* Extract regular expression from between slashes */
regexpstrp = regexp + 1;
regexpstrlen = strlen(regexpstrp);
if (regexpstrp[regexpstrlen - 1] == '/')
regexpstrp[regexpstrlen - 1] = '\0';
/* Compile the regular expression */
status = regcomp(&compiledregexp, regexpstrp,
REG_EXTENDED | REG_NOSUB);
if (status == 0) {
/* Make null-terminated copy of string */
memcpy(buffer, string, len);
buffer[len] = '\0';
/* Compare string to regular expression */
status = regexec(&compiledregexp,
buffer, (size_t) 0, NULL, 0);
regfree(&compiledregexp);
if (status == 0)
return (TRUE);
else
return (FALSE);
}
} else if (strncmp(string, regexp, len) == 0) {
return (TRUE);
}
return (FALSE);
}
int
MatchTsolConfig(const char *name, int len)
{
int i;
int count;
char **list;
unsigned int flags = 0;
count = tsolconfig[TSOL_PROPERTY].count;
list = tsolconfig[TSOL_PROPERTY].list;
for (i = 0; i < count; i++) {
if (regexcompare(name, len, list[i])) {
flags |= TSOLM_PROPERTY;
break;
}
}
count = tsolconfig[TSOL_SELECTION].count;
list = tsolconfig[TSOL_SELECTION].list;
for (i = 0; i < count; i++) {
if (regexcompare(name, len, list[i])) {
flags |= TSOLM_SELECTION;
break;
}
}
return (flags);
}
TsolInfoPtr
GetClientTsolInfo(ClientPtr client)
{
return TsolClientPrivate(client);
}
/* Property is polyinstantiated only on root window */
int
PolyProperty(Atom atom, WindowPtr pWin)
{
if (WindowIsRoot(pWin) &&
((!tsolpolyprop.polyinst && !(tsol_node[atom].IsSpecial & TSOLM_PROPERTY)) ||
(tsolpolyprop.polyinst && (tsol_node[atom].IsSpecial & TSOLM_PROPERTY))))
return TRUE;
return FALSE;
}
int
PolySelection(Atom atom)
{
if ((tsolpolyseln.polyinst && (tsol_node[atom].IsSpecial & TSOLM_SELECTION)) ||
(!tsolpolyseln.polyinst && !(tsol_node[atom].IsSpecial & TSOLM_SELECTION)))
return TRUE;
return FALSE;
}
/*
* client_private returns true if xid is owned/created by
* client or is a default server xid
*/
int
client_private (ClientPtr client, XID xid)
{
if (same_client(client, xid) || (xid & SERVER_BIT))
return TRUE;
else
return FALSE;
}
/*
* Same as TopClientWin()
* except that it returns a Window ID
* and not a ptr
*/
Window
RootOfClient(WindowPtr pWin)
{
if (pWin)
{
return (TopClientWin(pWin)->drawable.id);
}
return (NULL);
}
#ifdef UNUSED
/*
* Return root window of pWin
*/
WindowPtr
RootWin(WindowPtr pWin)
{
if (pWin)
{
while (pWin->parent)
pWin = pWin->parent;
}
return (pWin);
}
#endif
Window
RootOf(WindowPtr pWin)
{
if (pWin)
{
while (pWin->parent)
pWin = pWin->parent;
return (pWin->drawable.id);
}
return (NULL);
}
/*
* same_client returns true if xid is owned/created by
* client
*/
int
same_client (ClientPtr client, XID xid)
{
TsolInfoPtr tsolinfo_client;
TsolInfoPtr tsolinfo_xid;
ClientPtr xid_client;
if (CLIENT_ID(xid) == 0 || (clients[CLIENT_ID(xid)] == NULL))
return FALSE;
if((SERVER_BIT & xid) == 0)
{
if (client->index == CLIENT_ID(xid))
return TRUE;
xid_client = clients[CLIENT_ID(xid)];
tsolinfo_client = GetClientTsolInfo(client);
tsolinfo_xid = GetClientTsolInfo(xid_client);
if (tsolinfo_client && tsolinfo_xid && tsolinfo_client->pid > 0)
{
if (tsolinfo_client->pid == tsolinfo_xid->pid)
return TRUE;
}
}
return FALSE;
}
WindowPtr
AnyWindowOverlapsJustMe(
WindowPtr pWin,
WindowPtr pHead,
register BoxPtr box)
{
register WindowPtr pSib;
BoxRec sboxrec;
register BoxPtr sbox;
TsolResPtr win_res = TsolWindowPrivate(pWin);
for (pSib = pWin->prevSib; (pSib != NULL && pSib != pHead); pSib = pSib->prevSib)
{
TsolResPtr sib_res = TsolWindowPrivate(pSib);
if (pSib->mapped && !bldominates(win_res->sl, sib_res->sl))
{
sbox = WindowExtents(pSib, &sboxrec);
if (BOXES_OVERLAP(sbox, box)
#ifdef SHAPE
&& ShapeOverlap (pWin, box, pSib, sbox)
#endif
)
return(pSib);
}
}
return((WindowPtr)NULL);
}
/*
* Return Top level client window of pWin
*/
WindowPtr
TopClientWin(WindowPtr pWin)
{
ClientPtr client;
if (pWin)
{
client = wClient(pWin);
while (pWin->parent)
{
if (client != wClient(pWin->parent))
break;
pWin = pWin->parent;
}
}
return (pWin);
}
/*
* Matches in the list of disabled extensions via
* the policy file (TrustedExtensionsPolicy)
* Returns
* TRUE - if a match is found
* FALSE - otherwise
*/
int
TsolDisabledExtension(const char *extname)
{
int i;
for (i = 0; i < tsolconfig[TSOL_EXTENSION].count; i++) {
if (strcmp(extname, tsolconfig[TSOL_EXTENSION].list[i]) == 0) {
return TRUE;
}
}
return FALSE;
}
/*****************************************************************************/
/* Debug/error message utility functions */
/* Returns a string representation of the access mode for debugging messages */
_X_HIDDEN const char *
TsolDixAccessModeNameString(Mask access_mode) {
static char access_mode_str[1024];
int l = 0;
access_mode_str[0] = '\0';
#define APPEND_MODENAME_IF_SET(mode) \
if (access_mode & (mode)) \
l = strlcat(access_mode_str, #mode " | ", sizeof(access_mode_str))
APPEND_MODENAME_IF_SET(DixUnknownAccess);
APPEND_MODENAME_IF_SET(DixReadAccess);
APPEND_MODENAME_IF_SET(DixWriteAccess);
APPEND_MODENAME_IF_SET(DixDestroyAccess);
APPEND_MODENAME_IF_SET(DixCreateAccess);
APPEND_MODENAME_IF_SET(DixGetAttrAccess);
APPEND_MODENAME_IF_SET(DixSetAttrAccess);
APPEND_MODENAME_IF_SET(DixListPropAccess);
APPEND_MODENAME_IF_SET(DixGetPropAccess);
APPEND_MODENAME_IF_SET(DixSetPropAccess);
APPEND_MODENAME_IF_SET(DixGetFocusAccess);
APPEND_MODENAME_IF_SET(DixSetFocusAccess);
APPEND_MODENAME_IF_SET(DixListAccess);
APPEND_MODENAME_IF_SET(DixAddAccess);
APPEND_MODENAME_IF_SET(DixRemoveAccess);
APPEND_MODENAME_IF_SET(DixHideAccess);
APPEND_MODENAME_IF_SET(DixShowAccess);
APPEND_MODENAME_IF_SET(DixBlendAccess);
APPEND_MODENAME_IF_SET(DixGrabAccess);
APPEND_MODENAME_IF_SET(DixFreezeAccess);
APPEND_MODENAME_IF_SET(DixForceAccess);
APPEND_MODENAME_IF_SET(DixInstallAccess);
APPEND_MODENAME_IF_SET(DixUninstallAccess);
APPEND_MODENAME_IF_SET(DixSendAccess);
APPEND_MODENAME_IF_SET(DixReceiveAccess);
APPEND_MODENAME_IF_SET(DixUseAccess);
APPEND_MODENAME_IF_SET(DixManageAccess);
APPEND_MODENAME_IF_SET(DixDebugAccess);
APPEND_MODENAME_IF_SET(DixBellAccess);
if ( (l > 3) && (l < sizeof(access_mode_str)) ) {
/* strip off trailing " | " */
access_mode_str[l - 3] = '\0';
}
return access_mode_str;
}
/* Returns a string representation of the tsol policy for debugging messages */
_X_HIDDEN const char *
TsolPolicyReturnString(int pr)
{
if (pr == XTSOL_FAIL) {
return "FAIL";
} else if (pr == XTSOL_ALLOW) {
return "ALLOW";
} else if (pr == XTSOL_IGNORE) {
return "IGNORE";
} else {
static char str[32];
snprintf(str, sizeof(str), "<unknown value %d>", pr);
return str;
}
}
_X_HIDDEN const char *
TsolErrorNameString(int errcode)
{
const char *regentry = LookupErrorName(errcode);
if (strcmp(regentry, XREGISTRY_UNKNOWN) == 0) {
static char unknown_string[32];
snprintf(unknown_string, sizeof(unknown_string),
"error code #%d", errcode);
return unknown_string;
}
return regentry;
}
_X_HIDDEN const char *
TsolResourceTypeString(RESTYPE resource)
{
const char *regentry = LookupResourceName(resource);
if (strcmp(regentry, XREGISTRY_UNKNOWN) == 0) {
static char unknown_string[32];
snprintf(unknown_string, sizeof(unknown_string),
"resource type #%d", (uint_t) resource);
return unknown_string;
}
return regentry;
}
_X_HIDDEN const char *
TsolRequestNameString(int req)
{
const char *regentry;
if (req < 0) {
return "<no request>";
}
regentry = LookupMajorName(req);
if (strcmp(regentry, XREGISTRY_UNKNOWN) == 0) {
static char unknown_string[32];
snprintf(unknown_string, sizeof(unknown_string),
"request type #%d", req);
return unknown_string;
}
return regentry;
}