/**************************************************************************/
/* */
/* These are the XSELinux functions for the Notebook X-Windows demos. */
/* They are used to retrieve contexts and add them as required for the */
/* X-Windows Object Manager test examples. */
/* */
/* Note that the XError handling could be improved by using the */
/* appropriate X functions, however the current set-up seems to work ok. */
/* (even though a bit messy). */
/* */
/* Copyright (C) 2010 Richard Haines */
/* */
/* This program is free software: you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation, either version 3 of the License, or */
/* (at your option) any later version. */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see . */
/* */
/**************************************************************************/
#include
#include
#include
#include
#include "Xlib-selinux.h"
#define ENFORCING 1
// Declare the function that will plug the _XReply Error handler.
// This would normally be called first when sending X_SELinux..
// functions to the X-server. The CatchXErrorHandler() is then
// called meaning that the error message will be flagged twice.
// The catchXreplyErrorHandlerFlag stops reporting it for the
// second time.
int CatchXreplyErrorHandler (); // Declare the function
// Declare the function that will plug the XError handler when we use
// the X_SELinuxSet... functions to set a security context. Need to plug
// this or the default handler will just exit displaying the generic Xerror.
int CatchXErrorHandler ();
// This flag is used to indicate that an XError has already been detected
// and displayed using the CatchXreplyErrorHandler() function that will
// set it to xTrue. The CatchXErrorHandler() function will ignore the error
// then set this flag to xFalse.
static int catchXreplyErrorHandlerFlag = xFalse;
// Have this flag for functions 12, 13, 19, 20 & 22 to detect "Access Denied"
// errors. This is set to xTrue before the _XReply is actioned in these
// functions with the CatchXErrorHandler() and XReplyError() functions
// setting it to xFalse.
//
// An AVC message is generated for "Access Denied", however the 12, 13,
// 19, 20 & 22 functions return an errno with BadAlloc set (as failed
// to allocate a SID ???).
// I think an Access Denied should generate an XError of BadAccess (16).
//
// What seems to happen for Access Denied is that the functions 12, 13, 19,
// 20 & 22 _XReply fails via the "if (! _Xreply ...)" statement with -1
// (even though this has been plugged by the CatchXreplyErrorHandler).
// The failure will call the XReplyError() function that will check various
// flags such as "enforcing mode", then generate an "Access Denied" message
// if required.
//
static int checkAccessDeniedFlag = xFalse;
static const char *functionCodes [] = {
"SELinuxQueryVersion (0)",
"SELinuxSetDeviceCreateContext (1)",
"SELinuxGetDeviceCreateContext (2)",
"SELinuxSetDeviceContext (3)",
"SELinuxGetDeviceContext (4)",
"SELinuxSetWindowCreateContext (5)",
"SELinuxGetWindowCreateContext (6)",
"SELinuxGetWindowContext (7)",
"SELinuxSetPropertyCreateContext (8)",
"SELinuxGetPropertyCreateContext (9)",
"SELinuxSetPropertyUseContext (10)",
"SELinuxGetPropertyUseContext (11)",
"SELinuxGetPropertyContext (12)",
"SELinuxGetPropertyDataContext (13)",
"SELinuxListProperties (14)",
"SELinuxSetSelectionCreateContext (15)",
"SELinuxGetSelectionCreateContext (16)",
"SELinuxSetSelectionUseContext (17)",
"SELinuxGetSelectionUseContext (18)",
"SELinuxGetSelectionContext (19)",
"SELinuxGetSelectionDataContext (20)",
"SELinuxListSelections (21)",
"SELinuxGetClientContext (22)"
};
// This is global and used by the various test prgrams
int X_SELinuxExtensionOpcode;
// This global handle will be used to output the information from the
// functions. It would be stdout or a file.
extern FILE *outputPtr;
// The CatchXErrorHandler function captures any errors when any of
// the XLib functions are called. This allows XErrors to be captured
// and displayed, then let the application continue to run (as the
// normal XError handler would just display the error and exit.
// Note that the errors are only displayed if they have not been
// previously displayed by the CatchXreplyErrorHandler() function.
//
int CatchXErrorHandler (Display *dpy, XErrorEvent *error)
{
//printf ("CatchXErrorHandler()\n");
if (catchXreplyErrorHandlerFlag == xFalse) {
// Got here because of an XLib XError detected with no corresponding _XReply
// error, so just display a general error message with all the gory details
// and then give some detail on ones that have been seen to give an idea why
// they failed (only seen invalid context so far when using the ..Set..
// functions with invalid context info).
if (error->request_code == X_SELinuxExtensionOpcode) {
switch (error->error_code) {
case BadValue: // 2
fprintf (outputPtr, "%s returned BadValue - could be invalid context\n", functionCodes [error->minor_code]);
break;
case BadLength: // 16
fprintf (outputPtr, "%s returned BadLength - could be context = NULL\n", functionCodes [error->minor_code]);
break;
default:
fprintf (outputPtr, "%s returned an XError: %d\n", functionCodes [error->minor_code], error->error_code);
break;
}
} else
fprintf (outputPtr, "Detected XError: %d for Major opcode: %d Minor opcode: %d With ResourceID: %d\n", error->error_code, error->request_code, error->minor_code, error->resourceid);
}
catchXreplyErrorHandlerFlag = xFalse;
checkAccessDeniedFlag = xFalse;
return 1;
}
// This function catches _XReply errors (but NOT the "if (! _XReply ..) -1
// failures) and displays a message. The CatchXErrorHandler() handler is always
// called next so the catchXreplyErrorHandlerFlag is set to xTrue so the error
// is not reported twice. The xError struct is defined in Xproto.h
//
int CatchXreplyErrorHandler (Display *dpy, xError *err, XExtCodes *codes, int *ret_code)
{
//printf ("CatchXreplyErrorHandler()\n");
catchXreplyErrorHandlerFlag = xTrue;
fprintf (outputPtr, "The %s function returned an _XReply error:\n", functionCodes [err->minorCode]);
if (outputPtr != stdout)
printf ("The %s function returned an _XReply error: %d\n", functionCodes [err->minorCode], err->errorCode);
switch (err->errorCode) {
case BadRequest: // 1
fprintf (outputPtr, "BadRequest - An invalid SELinux function call\n");
break;
case BadValue: // 2
fprintf (outputPtr, "BadValue - Lookup failed for resourceID: %d (could also be invalid context)\n", err->resourceID);
break;
case BadWindow: // 3
fprintf (outputPtr, "BadWindow - Check WindowID: %d\n", err->resourceID);
break;
case BadMatch: // 8
fprintf (outputPtr, "BadMatch - Lookup failed for resourceID: %d\n", err->resourceID);
break;
case BadAccess: // 10
fprintf (outputPtr, "BadAccess - Lookup failed for resourceID: %d\n", err->errorCode, err->resourceID);
break;
case BadAlloc: // 11
fprintf (outputPtr, "BadAlloc - Generally allocation of resourceID: %d\n", err->resourceID);
break;
case BadLength: // 16
fprintf (outputPtr, "BadLength - A context is the wrong length (resourceID: %d)\n", err->resourceID);
break;
default:
fprintf (outputPtr, "_XReply XError: %d ResourceID: %d\n", err->errorCode, err->resourceID);
break;
}
return 0;
}
// Need this function as:
// Always seem to get the BadAlloc message (or is it EAGAIN ?) in errno when
// _XReply fails via the "if (! _Xreply ...)" statement with -1 even though
// this has been plugged by the CatchXreplyErrorHandler.
// However the only case where it seems to be relevant is when obtaining the
// security context of a client (func 22) or Atoms (funcs 12, 13, 19 & 20)
// when in enforcing mode and access is not allowed. Therefore have this bit of
// code that checks various bits. See the checkAccessDeniedFlag comments above.
//
int XReplyError (Display *dpy, int minorOpcode)
{
if (errno != BadAlloc) { // or is it EAGAIN ???
fprintf (outputPtr, "The %s function _XReply returned errno: %d\n", functionCodes [minorOpcode], errno);
if (outputPtr != stdout)
printf ("The %s function _XReply returned errno: %d\n", functionCodes [minorOpcode], errno);
UnlockDisplay (dpy);
SyncHandle ();
return (0);
}
// Use this to check the error return from an _XReply as BadAlloc means access
// denied when in enforcing mode for functions 12, 13 & 22.
if ((security_getenforce () == ENFORCING) && (checkAccessDeniedFlag == xTrue)) {
fprintf (outputPtr, "The BadAlloc error in Enforcing Mode means \"Access Denied\"\n");
if (outputPtr != stdout)
printf ("The BadAlloc error in Enforcing Mode means \"Access Denied\"\n");
UnlockDisplay (dpy);
SyncHandle ();
checkAccessDeniedFlag = xFalse;
return (0);
}
else {
//// To stop screen clutter don't display the error for errno == BadAlloc as
//// already caught by the XError handler anyway.
// fprintf (outputPtr, "The %s function _XReply returned errno: %d\n", functionCodes [minorOpcode], errno);
// if (outputPtr != stdout)
// printf ("The %s function _XReply returned errno: %d\n", functionCodes [minorOpcode], errno);
UnlockDisplay (dpy);
SyncHandle ();
return (0);
}
}
/**************************************************************************/
/* */
/* START XSELinux FUNCTIONS */
/* These are the X_SELinux functions that are called by the various test */
/* programs. This could be written as a library service with better */
/* handling of the X_SELinuxExtensionOpcode and FILE *outputPtr stuff. */
/* */
/**************************************************************************/
// SELinuxQueryVersion = 0 - This function has the wrong
// xSELinuxQueryVersionReq size. See Xlib-selinux.h
SELinuxQueryVersion (Display *dpy)
{
xSELinuxQueryVersionReq *req;
xSELinuxQueryVersionReply rep;
LockDisplay (dpy);
GetReq (SELinuxQueryVersion, req);
req->reqType = X_SELinuxExtensionOpcode;
req->SELinuxReqType = X_SELinuxQueryVersion;
if (!_XReply (dpy, (xReply *)&rep, 0, xTrue)) {
XReplyError (dpy, X_SELinuxQueryVersion);
return (-1);
}
UnlockDisplay (dpy);
SyncHandle ();
fprintf (outputPtr, "SELinuxQueryVersion - Major Version: %d Minor Version: %d\n", rep.server_major, rep.server_minor);
}
// Get the SELinuxSetDeviceCreateContext = 1
SELinuxSetDeviceCreateContext (Display *dpy, char * buffer)
{
xSELinuxSetDeviceCreateContextReq *req;
long nbytes;
fprintf (outputPtr, "SELinuxSetDeviceCreateContext - Setting Context: %s\n", buffer);
LockDisplay (dpy);
GetReq (SELinuxSetDeviceCreateContext, req);
req->reqType = X_SELinuxExtensionOpcode;
req->SELinuxReqType = X_SELinuxSetDeviceCreateContext;
nbytes = req->context_len = strlen (buffer);
req->length += (nbytes + 3) >> 2; /* round up to mult of 4 */
_XSend (dpy, buffer, nbytes); // Can use _XSend or Data as no difference
// Data (dpy, buffer, nbytes);
// This function does not specify a reply, however we need to check that
// the context given is valid, This is done on the next X call, so using
// XSynchronize() to force a return (as _XFlush() does not do this as
// the buffer is clear anyway). If an error is detected, then it goes
// to our CaptureXErrorHandler() function that gives a message and
// allows the function to continue. I'm sure there is a better way
// to do this but !!!
// _XFlush (dpy);
XSynchronize (dpy, xTrue);
UnlockDisplay (dpy);
SyncHandle ();
XSynchronize (dpy, xFalse);
}
// SELinuxGetDeviceCreateContext = 2
SELinuxGetDeviceCreateContext (Display *dpy)
{
xSELinuxGetDeviceCreateContextReq *req;
xSELinuxGetDeviceCreateContextReply rep;
char deviceContext [100];
LockDisplay (dpy);
GetReq (SELinuxGetDeviceCreateContext, req);
req->reqType = X_SELinuxExtensionOpcode;
req->SELinuxReqType = X_SELinuxGetDeviceCreateContext;
if (!_XReply (dpy, (xReply *)&rep, 0, xFalse)) {
XReplyError (dpy, X_SELinuxGetDeviceCreateContext);
return (-1);
}
if (rep.context_len == 0)
fprintf (outputPtr, "SELinuxGetDeviceCreateContext - No Context available\n");
else {
_XReadPad (dpy, deviceContext, rep.context_len);
fprintf (outputPtr, "SELinuxGetDeviceCreateContext - Context: %s\n", deviceContext);
}
UnlockDisplay (dpy);
SyncHandle ();
}
// Get the SELinuxSetDeviceCreateContext = 3
SELinuxSetDeviceContext (Display *dpy, char * buffer, long device_id)
{
xSELinuxSetDeviceContextReq *req;
long nbytes;
fprintf (outputPtr, "SELinuxSetDeviceContext - Setting Context: %s for Device ID %d\n", buffer, device_id);
LockDisplay (dpy);
GetReq (SELinuxSetDeviceContext, req);
req->reqType = X_SELinuxExtensionOpcode;
req->SELinuxReqType = X_SELinuxSetDeviceContext;
req->id = device_id;
nbytes = req->context_len = strlen(buffer);
req->length += (nbytes + 3) >> 2; /* round up to mult of 4 */
// _XSend (dpy, buffer, nbytes);
Data (dpy, buffer, nbytes);
// See the SELinuxSetDeviceCreateContext() function for the reason why
// the XSynchronize() functions are called.
XSynchronize (dpy, xTrue);
UnlockDisplay (dpy);
SyncHandle ();
XSynchronize (dpy, xFalse);
}
// SELinuxGetDeviceContext = 4
SELinuxGetDeviceContext (Display *dpy, int deviceID)
{
xSELinuxGetDeviceContextReq *req;
xSELinuxGetDeviceContextReply rep;
char deviceContext [100];
LockDisplay (dpy);
GetReq (SELinuxGetDeviceContext, req);
req->reqType = X_SELinuxExtensionOpcode;
req->SELinuxReqType = X_SELinuxGetDeviceContext;
req->id = deviceID;
if (!_XReply (dpy, (xReply *)&rep, 0, xFalse)) {
XReplyError (dpy, X_SELinuxGetDeviceContext);
return (-1);
}
if (rep.context_len == 0)
fprintf (outputPtr, "SELinuxGetDeviceContext - No Context available\n");
else {
_XReadPad (dpy, deviceContext, rep.context_len);
fprintf (outputPtr, "SELinuxGetDeviceContext - DeviceID: %d\nDevice Context: %s\n", deviceID, deviceContext);
}
UnlockDisplay (dpy);
SyncHandle ();
}
// Get the SELinuxSetWindowCreateContext = 5
SELinuxSetWindowCreateContext (Display *dpy, char * buffer)
{
xSELinuxSetWindowCreateContextReq *req;
long nbytes;
fprintf (outputPtr, "SELinuxSetWindowCreateContext - Setting Context: %s\n", buffer);
LockDisplay (dpy);
GetReq (SELinuxSetWindowCreateContext, req);
req->reqType = X_SELinuxExtensionOpcode;
req->SELinuxReqType = X_SELinuxSetWindowCreateContext;
nbytes = req->context_len = strlen(buffer);
req->length += (nbytes + 3) >> 2; /* round up to mult of 4 */
_XSend (dpy, buffer, nbytes);
// Data (dpy, buffer, nbytes);
// See the SELinuxSetDeviceCreateContext() function for the reason why
// the XSynchronize() functions are called.
XSynchronize (dpy, xTrue);
UnlockDisplay (dpy);
SyncHandle ();
XSynchronize (dpy, xFalse);
}
// SELinuxGetWindowCreateContext = 6
SELinuxGetWindowCreateContext (Display *dpy)
{
xSELinuxGetWindowCreateContextReq *req;
xSELinuxGetWindowCreateContextReply rep;
char windowContext [100];
LockDisplay (dpy);
GetReq (SELinuxGetWindowCreateContext, req);
req->reqType = X_SELinuxExtensionOpcode;
req->SELinuxReqType = X_SELinuxGetWindowCreateContext;
if (!_XReply (dpy, (xReply *)&rep, 0, xFalse)) {
XReplyError (dpy, X_SELinuxGetWindowCreateContext);
return (-1);
}
if (rep.context_len == 0)
fprintf (outputPtr, "SELinuxGetWindowCreateContext - No Context available\n");
else {
_XReadPad (dpy, windowContext, rep.context_len);
fprintf (outputPtr, "SELinuxGetWindowCreateContext - Context: %s\n", windowContext);
}
UnlockDisplay (dpy);
SyncHandle ();
}
// SELinuxGetWindowContext = 7
SELinuxGetWindowContext (Display *dpy, Window windowID)
{
xSELinuxGetWindowContextReq *req;
xSELinuxGetWindowContextReply rep;
char windowContext [100];
LockDisplay (dpy);
GetReq (SELinuxGetWindowContext, req);
req->reqType = X_SELinuxExtensionOpcode;
req->SELinuxReqType = X_SELinuxGetWindowContext;
req->id = windowID;
if (!_XReply (dpy, (xReply *)&rep, 0, xFalse)) {
XReplyError (dpy, X_SELinuxGetWindowContext);
return (-1);
}
if (rep.context_len == 0)
fprintf (outputPtr, "SELinuxGetWindowContext - No Context available\n");
else {
_XReadPad (dpy, windowContext, rep.context_len);
fprintf (outputPtr, "SELinuxGetWindowContext - WinID: %d\nWindow Context: %s\n", windowID, windowContext);
}
UnlockDisplay (dpy);
SyncHandle ();
}
// Get the SELinuxSetPropertyCreateContext = 8
SELinuxSetPropertyCreateContext (Display *dpy, char * buffer)
{
xSELinuxSetPropertyCreateContextReq *req;
long nbytes;
fprintf (outputPtr, "SELinuxSetPropertyCreateContext - Setting Context: %s\n", buffer);
LockDisplay (dpy);
GetReq (SELinuxSetPropertyCreateContext, req);
req->reqType = X_SELinuxExtensionOpcode;
req->SELinuxReqType = X_SELinuxSetPropertyCreateContext;
nbytes = req->context_len = strlen(buffer);
req->length += (nbytes + 3) >> 2; /* round up to mult of 4 */
_XSend (dpy, buffer, nbytes);
// Data (dpy, buffer, nbytes);
// See the SELinuxSetDeviceCreateContext() function for the reason why
// the XSynchronize() functions are called.
XSynchronize (dpy, xTrue);
UnlockDisplay (dpy);
SyncHandle ();
XSynchronize (dpy, xFalse);
}
// SELinuxGetPropertyCreateContext = 9
SELinuxGetPropertyCreateContext (Display *dpy)
{
xSELinuxGetPropertyCreateContextReq *req;
xSELinuxGetPropertyCreateContextReply rep;
char propertyContext [100];
LockDisplay (dpy);
GetReq (SELinuxGetPropertyCreateContext, req);
req->reqType = X_SELinuxExtensionOpcode;
req->SELinuxReqType = X_SELinuxGetPropertyCreateContext;
if (!_XReply (dpy, (xReply *)&rep, 0, xFalse)) {
XReplyError (dpy, X_SELinuxGetPropertyCreateContext);
return (-1);
}
if (rep.context_len == 0)
fprintf (outputPtr, "SELinuxGetPropertyCreateContext - No Context available\n");
else {
_XReadPad (dpy, propertyContext, rep.context_len);
fprintf (outputPtr, "SELinuxGetPropertyCreateContext - Context: %s\n", propertyContext);
}
UnlockDisplay (dpy);
SyncHandle ();
}
// Get the SELinuxSetPropertyUseContext = 10
SELinuxSetPropertyUseContext (Display *dpy, char * buffer)
{
xSELinuxSetPropertyUseContextReq *req;
long nbytes;
fprintf (outputPtr, "SELinuxSetPropertyUseContext - Setting Context: %s\n", buffer);
LockDisplay (dpy);
GetReq (SELinuxSetPropertyUseContext, req);
req->reqType = X_SELinuxExtensionOpcode;
req->SELinuxReqType = X_SELinuxSetPropertyUseContext;
nbytes = req->context_len = strlen(buffer);
req->length += (nbytes + 3) >> 2; /* round up to mult of 4 */
// _XSend (dpy, buffer, nbytes);
Data (dpy, buffer, nbytes);
// See the SELinuxSetDeviceCreateContext() function for the reason why
// the XSynchronize() functions are called.
XSynchronize (dpy, xTrue);
UnlockDisplay (dpy);
SyncHandle ();
XSynchronize (dpy, xFalse);
}
// SELinuxGetPropertyUseContext = 11
SELinuxGetPropertyUseContext (Display *dpy)
{
xSELinuxGetPropertyUseContextReq *req;
xSELinuxGetPropertyUseContextReply rep;
char propertyContext [100];
LockDisplay (dpy);
GetReq (SELinuxGetPropertyUseContext, req);
req->reqType = X_SELinuxExtensionOpcode;
req->SELinuxReqType = X_SELinuxGetPropertyUseContext;
if (!_XReply (dpy, (xReply *)&rep, 0, xFalse)) {
XReplyError (dpy, X_SELinuxGetPropertyUseContext);
return (-1);
}
if (rep.context_len == 0)
fprintf (outputPtr, "SELinuxGetPropertyUseContext - No Context available\n");
else {
_XReadPad (dpy, propertyContext, rep.context_len);
fprintf (outputPtr, "SELinuxGetPropertyUseContext - Context: %s\n", propertyContext);
}
UnlockDisplay (dpy);
SyncHandle ();
}
// SELinuxGetPropertyContext = 12
SELinuxGetPropertyContext (Display *dpy, Window windowID, Atom propertyAtom)
{
xSELinuxGetPropertyContextReq *req;
xSELinuxGetPropertyContextReply rep;
char propertyContext [100];
LockDisplay (dpy);
GetReq (SELinuxGetPropertyContext, req);
req->reqType = X_SELinuxExtensionOpcode;
req->SELinuxReqType = X_SELinuxGetPropertyContext;
req->property = propertyAtom;
req->window = windowID;
// Indicate that function 12, 13, 19, 20 or 22 are being called:
checkAccessDeniedFlag = xTrue;
if (!_XReply (dpy, (xReply *)&rep, 0, xFalse)) {
XReplyError (dpy, X_SELinuxGetPropertyContext);
return (-1);
}
_XReadPad (dpy, propertyContext, rep.context_len);
fprintf (outputPtr, "SELinuxGetPropertyContext - WinID: %d Atom: %s \nContext: %s\n", windowID, (XGetAtomName (dpy, propertyAtom)), propertyContext);
UnlockDisplay (dpy);
SyncHandle ();
checkAccessDeniedFlag = xFalse;
}
// SELinuxGetPropertyDataContext = 13
SELinuxGetPropertyDataContext (Display *dpy, Window windowID, Atom propertyAtom)
{
xSELinuxGetPropertyDataContextReq *req;
xSELinuxGetPropertyDataContextReply rep;
char propertyContext [100];
LockDisplay (dpy);
GetReq (SELinuxGetPropertyDataContext, req);
req->reqType = X_SELinuxExtensionOpcode;
req->SELinuxReqType = X_SELinuxGetPropertyDataContext;
req->property = propertyAtom;
req->window = windowID;
// Indicate that function 12, 13, 19, 20 or 22 are being called:
checkAccessDeniedFlag = xTrue;
if (!_XReply (dpy, (xReply *)&rep, 0, xFalse)) {
XReplyError (dpy, X_SELinuxGetPropertyDataContext);
return (-1);
}
_XReadPad (dpy, propertyContext, rep.context_len);
fprintf (outputPtr, "SELinuxGetPropertyDataContext - WinID: %d Atom: %s \nContext: %s\n", windowID, (XGetAtomName (dpy, propertyAtom)), propertyContext);
UnlockDisplay (dpy);
SyncHandle ();
checkAccessDeniedFlag = xFalse;
}
// SELinuxListProperties = 14
SELinuxListProperties (Display *dpy, Window windowID)
{
xSELinuxListPropertiesReq *req;
xSELinuxListPropertiesReply rep;
xSELinuxListItem xlist_item;
xSELinuxListItemEntry *info_struct = NULL;
char propertyList [100];
char context [100];
int i;
LockDisplay (dpy);
GetReq (SELinuxListProperties, req);
req->reqType = X_SELinuxExtensionOpcode;
req->SELinuxReqType = X_SELinuxListProperties;
req->id = windowID;
if (!_XReply (dpy, (xReply *)&rep, 0, xFalse)) {
XReplyError (dpy, X_SELinuxListProperties);
return (-1);
}
info_struct = Xmalloc((sizeof (xSELinuxListItemEntry) * rep.length) + sizeof (CARD32));
if(rep.count) {
for(i = 0; i < rep.count; i++) {
// Read initial info that has Atom name and context sizes:
_XReadPad (dpy, (char *)&xlist_item, sz_xSELinuxListItem);
// Add these to the holding structure for later printing:
info_struct[i].atom_name = (Atom)xlist_item.name;
info_struct[i].object_context_len = xlist_item.object_context_len;
info_struct[i].data_context_len = xlist_item.data_context_len;
// Read the object context string and copy to the holding structure:
_XReadPad (dpy, propertyList, xlist_item.object_context_len);
if (!strncpy ((char *)&info_struct[i].object_context, propertyList, (int)xlist_item.object_context_len)) {
UnlockDisplay (dpy);
SyncHandle ();
perror ("strncpy function failed");
exit (1);
}
// Read the data context string and copy to the holding structure:
_XReadPad (dpy, propertyList, xlist_item.data_context_len);
if (!strncpy ((char *)&info_struct[i].data_context, propertyList, (int)xlist_item.data_context_len))
fprintf (outputPtr, "strncpy function failed\n");
}
} else
_XEatData(dpy, rep.length << 2);
UnlockDisplay (dpy);
SyncHandle ();
// Done with _XRead processes, so need to print off the information.
fprintf (outputPtr, "SELinuxListProperties found %d properties for WinID: %d\n", rep.count, windowID);
for (i = 0; i < rep.count; i++) {
fprintf (outputPtr, "\nSELinuxListProperties (%d of %d) - Atom: %s\n", i+1, rep.count, (XGetAtomName (dpy, (Atom)info_struct[i].atom_name)));
fprintf (outputPtr, "Object Context: %s\n", (char *)&info_struct[i].object_context);
fprintf (outputPtr, "Data Context: %s\n", (char *)&info_struct[i].data_context);
}
Xfree (info_struct);
}
// Get the SELinuxSetSelectionCreateContext = 15
SELinuxSetSelectionCreateContext (Display *dpy, char * buffer)
{
xSELinuxSetSelectionCreateContextReq *req;
long nbytes;
fprintf (outputPtr, "SELinuxSetSelectionCreateContext - Setting Context: %s\n", buffer);
LockDisplay (dpy);
GetReq (SELinuxSetSelectionCreateContext, req);
req->reqType = X_SELinuxExtensionOpcode;
req->SELinuxReqType = X_SELinuxSetSelectionCreateContext;
nbytes = req->context_len = strlen (buffer);
req->length += (nbytes + 3) >> 2; /* round up to mult of 4 */
// _XSend (dpy, buffer, nbytes);
Data (dpy, buffer, nbytes);
// See the SELinuxSetDeviceCreateContext() function for the reason why
// the XSynchronize() functions are called.
XSynchronize (dpy, xTrue);
UnlockDisplay (dpy);
SyncHandle ();
XSynchronize (dpy, xFalse);
}
// SELinuxGetSelectionCreateContext = 16
SELinuxGetSelectionCreateContext (Display *dpy)
{
xSELinuxGetSelectionCreateContextReq *req;
xSELinuxGetSelectionCreateContextReply rep;
char selectionContext [100];
LockDisplay (dpy);
GetReq (SELinuxGetSelectionCreateContext, req);
req->reqType = X_SELinuxExtensionOpcode;
req->SELinuxReqType = X_SELinuxGetSelectionCreateContext;
if (!_XReply (dpy, (xReply *)&rep, 0, xFalse)) {
XReplyError (dpy, X_SELinuxGetSelectionCreateContext);
return (-1);
}
if (rep.context_len == 0)
fprintf (outputPtr, "SELinuxGetSelectionCreateContext - No Context available\n");
else {
_XReadPad (dpy, selectionContext, rep.context_len);
fprintf (outputPtr, "SELinuxGetSelectionCreateContext - Context: %s\n", selectionContext);
}
UnlockDisplay (dpy);
SyncHandle ();
}
// Get the SELinuxSetSelectionUseContext = 17
SELinuxSetSelectionUseContext (Display *dpy, char * buffer)
{
xSELinuxSetSelectionUseContextReq *req;
long nbytes;
fprintf (outputPtr, "SELinuxSetSelectionUseContext - Setting Context: %s\n", buffer);
LockDisplay (dpy);
GetReq (SELinuxSetSelectionUseContext, req);
req->reqType = X_SELinuxExtensionOpcode;
req->SELinuxReqType = X_SELinuxSetSelectionUseContext;
nbytes = req->context_len = strlen (buffer);
req->length += (nbytes + 3) >> 2; /* round up to mult of 4 */
// _XSend (dpy, buffer, nbytes);
Data (dpy, buffer, nbytes);
// See the SELinuxSetDeviceCreateContext() function for the reason why
// the XSynchronize() functions are called.
XSynchronize (dpy, xTrue);
UnlockDisplay (dpy);
SyncHandle ();
XSynchronize (dpy, xFalse);
}
// Get the SELinuxGetSelectionUseContext = 18
SELinuxGetSelectionUseContext (Display *dpy)
{
xSELinuxGetSelectionUseContextReq *req;
xSELinuxGetSelectionUseContextReply rep;
char selectionContext [100];
LockDisplay (dpy);
GetReq (SELinuxGetSelectionUseContext, req);
req->reqType = X_SELinuxExtensionOpcode;
req->SELinuxReqType = X_SELinuxGetSelectionUseContext;
if (!_XReply (dpy, (xReply *)&rep, 0, xFalse)) {
XReplyError (dpy, X_SELinuxGetSelectionUseContext);
return (-1);
}
if (rep.context_len == 0)
fprintf (outputPtr, "SELinuxGetSelectionUseContext - No Context available\n");
else {
_XReadPad (dpy, selectionContext, rep.context_len);
fprintf (outputPtr, "SELinuxGetSelectionUseContext - Context: %s\n", selectionContext);
}
UnlockDisplay (dpy);
SyncHandle ();
}
// Get the SELinuxGetSelectionContext = 19
SELinuxGetSelectionContext (Display *dpy, Atom selectionAtom)
{
xSELinuxGetSelectionContextReq *req;
xSELinuxGetSelectionContextReply rep;
char selectionContext [100];
LockDisplay (dpy);
GetReq (SELinuxGetSelectionContext, req);
req->reqType = X_SELinuxExtensionOpcode;
req->SELinuxReqType = X_SELinuxGetSelectionContext;
req->id = selectionAtom;
// Indicate that function 12, 13, 19, 20 or 22 are being called:
checkAccessDeniedFlag = xTrue;
if (!_XReply (dpy, (xReply *)&rep, 0, xFalse)) {
XReplyError (dpy, X_SELinuxGetSelectionContext);
return (-1);
}
_XReadPad (dpy, selectionContext, rep.context_len);
fprintf (outputPtr, "SELinuxGetSelectionContext - Atom: %s\nContext: %s\n", (XGetAtomName (dpy, selectionAtom)), selectionContext);
// fprintf (outputPtr, "This is the context for x_selection OBJECT\n");
UnlockDisplay (dpy);
SyncHandle ();
// Indicate that function 12, 13, 19, 20 or 22 are being called:
checkAccessDeniedFlag = xTrue;
}
// Get the SELinuxGetSelectionDataContext = 20
SELinuxGetSelectionDataContext (Display *dpy, Atom selectionAtom)
{
xSELinuxGetSelectionDataContextReq *req;
xSELinuxGetSelectionDataContextReply rep;
char selectionContext [100];
LockDisplay (dpy);
GetReq (SELinuxGetSelectionDataContext, req);
req->reqType = X_SELinuxExtensionOpcode;
req->SELinuxReqType = X_SELinuxGetSelectionDataContext;
req->id = selectionAtom;
// Indicate that function 12, 13, 19, 20 or 22 are being called:
checkAccessDeniedFlag = xTrue;
if (!_XReply (dpy, (xReply *)&rep, 0, xFalse)) {
XReplyError (dpy, X_SELinuxGetSelectionDataContext);
return (-1);
}
_XReadPad (dpy, selectionContext, rep.context_len);
fprintf (outputPtr, "SELinuxGetSelectionDataContext - Atom: %s\nContext: %s\n", (XGetAtomName (dpy, selectionAtom)), selectionContext);
// fprintf (outputPtr, "This is the context for x_application_data OBJECT\n");
UnlockDisplay (dpy);
SyncHandle ();
// Indicate that function 12, 13, 19, 20 or 22 are being called:
checkAccessDeniedFlag = xTrue;
}
// Get the SELinuxListSelections = 21
SELinuxListSelections (Display *dpy)
{
xSELinuxListSelectionsReq *req;
xSELinuxListSelectionsReply rep;
xSELinuxListItem xlist_item;
xSELinuxListItemEntry *info_struct = NULL;
char selectionList [600];
char context [100];
int i;
LockDisplay (dpy);
GetReq (SELinuxListSelections, req);
req->reqType = X_SELinuxExtensionOpcode;
req->SELinuxReqType = X_SELinuxListSelections;
if (!_XReply (dpy, (xReply *)&rep, 0, xFalse)) {
XReplyError (dpy, X_SELinuxListSelections);
return (-1);
}
info_struct = Xmalloc((sizeof (xSELinuxListItemEntry) * rep.length) + sizeof (CARD32));
if(rep.count) {
for(i = 0; i < rep.count; i++) {
// Read initial info that has Atom name and context sizes:
_XReadPad (dpy, (char *)&xlist_item, sz_xSELinuxListItem);
// Add these to the holding structure for later printing:
info_struct[i].atom_name = (Atom)xlist_item.name;
info_struct[i].object_context_len = xlist_item.object_context_len;
info_struct[i].data_context_len = xlist_item.data_context_len;
// Read the object context string and copy to the holding structure:
_XReadPad (dpy, selectionList, xlist_item.object_context_len);
if (!strncpy ((char *)&info_struct[i].object_context, selectionList, (int)xlist_item.object_context_len))
fprintf (outputPtr, "strncpy function failed\n");
// Read the data context string and copy to the holding structure:
_XReadPad (dpy, selectionList, xlist_item.data_context_len);
if (!strncpy ((char *)&info_struct[i].data_context, selectionList, (int)xlist_item.data_context_len))
fprintf (outputPtr, "strncpy function failed\n");
}
} else
_XEatData(dpy, rep.length << 2);
UnlockDisplay (dpy);
SyncHandle ();
// Done with _XRead processes, so need to print off the information.
for (i = 0; i < rep.count; i++) {
fprintf (outputPtr, "\nSELinuxListSelections (%d of %d) - Atom: %s\n", i+1, rep.count, (XGetAtomName (dpy, (Atom)info_struct[i].atom_name)));
fprintf (outputPtr, "Object Context: %s\n", (char *)&info_struct[i].object_context);
fprintf (outputPtr, "Data Context: %s\n", (char *)&info_struct[i].data_context);
}
Xfree (info_struct);
}
//
// When reading a client context that this function does not have
// permission to read will not result in an error being detected by
// the _XReply CatchXreplyError() function. Instead the _XReply
// call will fail with 'false' and the XReplyError() function
// will then check the errno return as described in the XReplyError()
// function. Also see the "checkAccessDeniedFlag" comments as
// to why this flag is present.
//
// SELinuxGetClientContext = 22
SELinuxGetClientContext (Display *dpy, Window resourceID)
{
xSELinuxGetClientContextReq *req;
xSELinuxGetClientContextReply rep;
char resourceContext [100];
LockDisplay (dpy);
GetReq (SELinuxGetClientContext, req);
req->reqType = X_SELinuxExtensionOpcode;
req->SELinuxReqType = X_SELinuxGetClientContext;
req->id = resourceID;
// Indicate that function 12, 13, 19, 20 or 22 are being called:
checkAccessDeniedFlag = xTrue;
if (!_XReply (dpy, (xReply *)&rep, 0, xFalse)) {
XReplyError (dpy, X_SELinuxGetClientContext);
return (-1);
}
if (rep.context_len == 0)
fprintf (outputPtr, "SELinuxGetClientContext - No Context available\n");
else {
_XReadPad (dpy, resourceContext, rep.context_len);
fprintf (outputPtr, "SELinuxGetClientContext - WinID: %d\nClient Context: %s\n", resourceID, resourceContext);
}
checkAccessDeniedFlag = xFalse;
UnlockDisplay (dpy);
SyncHandle ();
}