/*
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include <stdio.h>
#include "auditwrite.h"
#include <bsm/audit_uevents.h>
#include <ucred.h>
#include <netdb.h>
#include <strings.h>
#include <string.h>
#include <pwd.h>
#include <unistd.h>
#include <zone.h>
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include "misc.h"
#include "osdep.h"
#include "tsol.h"
#include "inputstr.h"
#include "extnsionst.h"
#include "dixstruct.h"
#include "xace.h"
#include "xacestr.h"
#ifdef PANORAMIX
#include "../Xext/panoramiXsrv.h"
#endif
#ifdef XCSECURITY
#include "../Xext/securitysrv.h"
#endif
#include "tsolpolicy.h"
#define BadCmapCookie 0
static int ProcTsolDispatch(ClientPtr);
static int ProcSetPolyInstInfo(ClientPtr);
static int ProcSetPropLabel(ClientPtr);
static int ProcSetPropUID(ClientPtr);
static int ProcSetResLabel(ClientPtr);
static int ProcSetResUID(ClientPtr);
static int ProcGetClientAttributes(ClientPtr);
static int ProcGetClientLabel(ClientPtr);
static int ProcGetPropAttributes(ClientPtr);
static int ProcGetResAttributes(ClientPtr);
static int ProcMakeTPWindow(ClientPtr);
static int ProcMakeTrustedWindow(ClientPtr);
static int ProcMakeUntrustedWindow(ClientPtr);
static int SProcTsolDispatch(ClientPtr);
static int SProcSetPolyInstInfo(ClientPtr);
static int SProcSetPropLabel(ClientPtr);
static int SProcSetPropUID(ClientPtr);
static int SProcSetResLabel(ClientPtr);
static int SProcSetResUID(ClientPtr);
static int SProcGetClientAttributes(ClientPtr);
static int SProcGetClientLabel(ClientPtr);
static int SProcGetPropAttributes(ClientPtr);
static int SProcGetResAttributes(ClientPtr);
static int SProcMakeTPWindow(ClientPtr);
static int SProcMakeTrustedWindow(ClientPtr);
static int SProcMakeUntrustedWindow(ClientPtr);
static unsigned char TsolReqCode = 0;
int tsol_mac_enabled;
static int OwnerUIDint;
/*
* Key to lookup devPrivate data in various structures
*/
char *name, unsigned int data_length,
/* XACE hook callbacks */
static CALLBACK(TsolCheckExtensionAccess);
static CALLBACK(TsolCheckPropertyAccess);
static CALLBACK(TsolCheckResourceIDAccess);
static CALLBACK(TsolCheckSendAccess);
static CALLBACK(TsolCheckReceiveAccess);
static CALLBACK(TsolCheckSelectionAccess);
static CALLBACK(TsolProcessKeyboard);
/* other callbacks */
static CALLBACK(TsolClientStateCallback);
static CALLBACK(TsolSelectionCallback);
extern priv_set_t *pset_win_mac_write;
extern priv_set_t *pset_win_dac_write;
extern priv_set_t *pset_win_config;
extern RESTYPE RREventType;
/*
* Initialize the extension. Main entry point for this loadable
* module.
*/
_X_EXPORT void
TsolExtensionInit(void)
{
int i;
/* sleep(20); */
if (is_system_labeled()) {
} else {
/* DAC support can be added in future */
return;
}
init_xtsol();
ErrorF("TsolExtensionInit: AddExtension failed for X Trusted Extensions\n");
return;
}
return;
return;
/* Allocate storage in devPrivates */
sizeof (TsolInfoRec))) {
ErrorF("TsolExtensionInit: Cannot allocate client private.\n");
return;
}
sizeof (TsolResRec))) {
ErrorF("TsolExtensionInit: Cannot allocate pixmap private.\n");
return;
}
sizeof (TsolResRec))) {
ErrorF("TsolExtensionInit: Cannot allocate window private.\n");
return;
}
sizeof (TsolResRec))) {
ErrorF("TsolExtensionInit: Cannot allocate property private.\n");
return;
}
sizeof (TsolResRec))) {
ErrorF("TsolExtensionInit: Cannot allocate selection private.\n");
return;
}
sizeof (HotKeyRec))) {
ErrorF("TsolExtensionInit: Cannot allocate device private.\n");
return;
}
/* Initialize the client info for server itself */
if (serverClient) {
"client id %d (pid %d)",
}
}
UpdateTsolNode(0, NULL);
/* Initialize security hooks */
pSecHook = &tsolSecHook;
/* Save original Proc vectors */
for (i = 0; i < PROCVECTORSIZE; i++) {
TsolSavedProcVector[i] = ProcVector[i];
}
}
static CALLBACK(
{
switch (rtype) {
case RT_WINDOW:
case RT_PIXMAP:
/* Drawables policy */
break;
case RT_GC:
case RT_CURSOR:
case RT_FONT:
break;
default:
/*
* Handle other resource types.
* In RANDR extension, usual window policy is
* enforced before checking for RREventType.
*/
if (rtype == RREventType) {
}
break;
}
}
static
{
case SelectionClientClose:
}
/* fall through to reset the SL */
case SelectionWindowDestroy:
break;
default:
/* All others handled in SelectionAccess handler */
break;
}
}
static
{
switch (client->clientState) {
case ClientStateInitial:
/* Got a new connection */
break;
case ClientStateRunning:
break;
case ClientStateRetained: /* client disconnected */
break;
case ClientStateGone:
}
/* Audit disconnect */
}
break;
default:
break;
}
}
static void
{
}
/*
* Dispatch routine
*
*/
static int
{
int retval;
{
case X_SetPolyInstInfo:
break;
case X_SetPropLabel:
break;
case X_SetPropUID:
break;
case X_SetResLabel:
break;
case X_SetResUID:
break;
case X_GetClientAttributes:
break;
case X_GetClientLabel:
break;
case X_GetPropAttributes:
break;
case X_GetResAttributes:
break;
case X_MakeTPWindow:
break;
case X_MakeTrustedWindow:
break;
case X_MakeUntrustedWindow:
break;
default:
retval = BadRequest;
}
return (retval);
}
static int
{
int retval;
{
case X_SetPolyInstInfo:
break;
case X_SetPropLabel:
break;
case X_SetPropUID:
break;
case X_SetResLabel:
break;
case X_SetResUID:
break;
case X_GetClientAttributes:
break;
case X_GetClientLabel:
break;
case X_GetPropAttributes:
break;
case X_GetResAttributes:
break;
case X_MakeTPWindow:
break;
case X_MakeTrustedWindow:
break;
case X_MakeUntrustedWindow:
break;
default:
retval = BadRequest;
}
return (retval);
}
/*
* Individual routines
*/
static int
{
return (ProcSetPolyInstInfo(client));
}
static int
{
return (ProcSetPropLabel(client));
}
static int
{
return (ProcSetPropUID(client));
}
static int
{
return (ProcSetResLabel(client));
}
static int
{
return (ProcSetResUID(client));
}
static int
{
return (ProcGetClientAttributes(client));
}
static int
{
return (ProcGetClientLabel(client));
}
static int
{
return (ProcGetPropAttributes(client));
}
static int
{
return (ProcGetResAttributes(client));
}
static int
{
return (ProcMakeTPWindow(client));
}
static int
{
return (ProcMakeTrustedWindow(client));
}
static int
{
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
*/
static int
{
extern priv_set_t *pset_win_mac_write;
/* Requires win_mac_write privilege */
return (BadAccess);
}
return (client->noClientException);
}
static int
{
int rc;
return rc;
if (!pWin)
{
return (BadWindow);
}
{
return (BadAtom);
}
/* first see if property already exists */
while (pProp)
{
break;
}
if (!pProp)
{
/* property does not exist */
return (BadAtom);
}
/* Requires win_mac_write privilege */
return (BadAccess);
}
/* Initialize property created internally by server */
}
return (client->noClientException);
}
static int
{
int rc;
return rc;
if (!pWin)
{
return (BadWindow);
}
{
return (BadAtom);
}
/* first see if property already exists */
while (pProp)
{
break;
}
if (!pProp)
{
/* property does not exist */
return (BadAtom);
}
/* Requires win_mac_write privilege */
return (BadAccess);
}
/* Initialize property created internally by server */
return (client->noClientException);
}
static int
{
int rc;
/* Requires win_mac_write privilege */
return (BadAccess);
}
switch (stuff->resourceType) {
case SESSIONHI: /* set server session HI */
return (client->noClientException);
case SESSIONLO: /* set server session LO */
return (client->noClientException);
case IsWindow:
return rc;
if (pWin)
{
}
else
{
return (BadWindow);
}
break;
case IsPixmap:
return rc;
if (pMap)
{
}
else
{
return (BadPixmap);
}
break;
default:
return (BadValue);
}
}
/* generate the notify event for windows */
{
return rc;
}
return (client->noClientException);
}
static int
{
int ScreenNumber;
int rc;
extern priv_set_t *pset_win_dac_write;
switch (stuff->resourceType)
{
case STRIPEHEIGHT:
if (!HasTrustedPath(tsolinfo))
return (BadAccess);
/* set Screen Stripe Size */
return (client->noClientException);
case RES_OUID:
if (!HasTrustedPath(tsolinfo))
return (BadAccess);
return (client->noClientException);
case IsWindow:
return rc;
if (pWin)
{
}
else
{
return (BadWindow);
}
break;
case IsPixmap:
return rc;
if (pMap)
{
}
else
{
return (BadPixmap);
}
break;
default:
return (BadValue);
}
/* Requires win_dac_write privilege */
return (BadAccess);
}
return (client->noClientException);
}
static int
{
int n;
int rc;
.length = 0
};
/* Valid window check */
return rc;
{
return (BadWindow);
}
/* Transfer the client info to reply rec */
{
}
return (client->noClientException);
}
static int
{
int n;
int reply_length = 0;
int rc;
.length = 0,
.blabel_bytes = 0
};
/* Valid window check */
return rc;
{
return (BadWindow);
}
/* allocate temp storage for labels */
return (BadAlloc);
/* fill the fields as per request mask */
{
}
{
write_to_client = 1;
}
{
}
if (write_to_client == 1)
{
}
return (client->noClientException);
}
static int
{
int n;
int reply_length = 0;
int rc;
.length = 0,
.sllength = 0,
.illength = 0
};
return rc;
{
return (BadAtom);
}
/* first see if property already exists */
while (pProp)
{
if (tsolpolyinstinfo.enabled) {
break; /* match found */
} else {
break; /* match found */
}
}
}
}
if (!pProp)
{
/* property does not exist, use window's attributes */
}
{
}
/* allocate temp storage for labels */
return (BadAlloc);
/* fill the fields as per request mask */
{
}
{
write_to_client = 1;
}
{
}
if (write_to_client == 1)
{
}
return (client->noClientException);
}
static int
{
int n;
int reply_length = 0;
int rc;
.length = 0,
.sllength = 0,
.illength = 0,
.iillength = 0
};
{
}
{
}
{
return rc;
}
{
return rc;
}
{
}
/* allocate temp storage for labels */
return (BadAlloc);
/* fill the fields as per request mask */
{
}
{
write_to_client = 1;
}
{
}
if (write_to_client == 1)
{
}
return (client->noClientException);
}
int
{
int rc;
/*
* Session type single-level? This is set by the
* label builder
*/
return (client->noClientException);
}
#if defined(PANORAMIX)
if (!noPanoramiXExtension)
{
int j;
return rc;
{
return rc;
/* window should not be root but child of root */
{
return (BadWindow);
}
{
}
}
} else
#endif
{
return rc;
/* window should not be root but child of root */
{
return (BadWindow);
}
{
}
}
/*
* Force kbd & ptr ungrab. This will cause
* a client
*/
return (client->noClientException);
}
/*
* Turn on window's Trusted bit
*/
static int
{
int rc;
return rc;
/* window should not be root but child of root */
{
return (BadWindow);
}
if (!HasTrustedPath(tsolinfo))
return (BadAccess);
/* Turn on Trusted bit of the window */
return (client->noClientException);
}
/*
* Turn off window's Trusted bit
*/
static int
{
int rc;
return rc;
/* window should not be root but child of root */
{
return (BadWindow);
}
if (!HasTrustedPath(tsolinfo))
return (BadAccess);
tsolinfo->forced_trust = 0;
return (client->noClientException);
}
/*
* Break keyboard & ptr grabs of clients other than
* the requesting client.
* Called from ProcMakeTPWindow.
*/
static void
{
if (kbdgrab) {
}
if (ptrgrab) {
}
}
/*
* Trusted Network interface module. Uses tsix API
*/
extern tsol_host_type_t tsol_getrhtype(char *);
static void
{
/* Get client attributes from the socket */
TSOL_LOG_PREFIX "Cannot get client attributes"
" for %s, getpeerucred failed: %s\n",
return;
}
/* Extract individual fields from the cred structure */
get the real process name out of /proc in the future
*/
/* Set privileges */
if (tsolMultiLevel) {
} else {
}
} else {
}
}
/*
* For remote hosts, the uid is determined during access control
* using Secure RPC
*/
} else {
}
/* Set Trusted Path for local clients */
}else {
}
else
tsolinfo->forced_trust = 0;
/* Set reasonable defaults for remote clients */
int errcode;
/* Use NI_NUMERICHOST to avoid DNS lookup */
if (errcode) {
} else {
}
}
}
/* setup audit context */
} else {
}
/* Audit id */
}
/* session id */
/* Audit mask */
} else {
} else {
}
}
ucred_free(uc);
}
static char *
{
char *temp_inmsg;
struct svc_req r;
memset((char *)&r, 0, sizeof(r));
goto bad1;
/* decode into msg */
goto bad2;
/* do the authentication */
goto bad2;
}
#ifdef SVR4
#else
#endif
goto bad2;
}
bad2:
free(r.rq_clntcred);
bad1:
return ((char *)0); /* ((struct authdes_cred *) NULL); */
}
static Bool
{
}
extern int getdomainname(char *, int);
static XID
unsigned int data_length, char *data,
{
char audit_ret;
int client_gidlen;
char *fullname;
/* Retrieve uid from SecureRPC */
ErrorF("Unable to authenticate Secure RPC client");
} else {
if (netname2user(fullname,
&client_uid, &client_gid,
&client_gidlen, &client_gidlist)) {
} else {
ErrorF("netname2user failed");
}
}
}
}
}
/*
* 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 (HasTrustedPath(tsolinfo)) {
}
} else {
/*
* Workstation Owner set, client must be within label
* range or have trusted path
*/
(HasTrustedPath(tsolinfo))) {
}
} else {
/* Allow root from global zone */
} else {
/*
* Access check based on uid. Check if
* roles or other uids have been added by
* xhost +role@
*/
return ((XID)-1);
}
} else {
}
}
}
}
/* Audit the connection */
audit_val = 1;
} else {
audit_ret = 0; /* success */
audit_val = 0;
}
if (system_audit_on &&
int status;
case AF_INET:
break;
case AF_INET6:
break;
}
} else {
}
if (!status)
}
return (auth_token);
}
static CALLBACK(
{
/* int count = rec->count; */
{
if (!hotkey->initialized)
{
}
}
}
static CALLBACK(
{
return;
}
return;
}
#ifndef NO_TSOL_DEBUG_MESSAGES
"TsolCheckSendAccess(%s, %s) = %s\n",
}
#endif /* !NO_TSOL_DEBUG_MESSAGES */
}
static CALLBACK(
{
}
static CALLBACK(
{
int reqtype;
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)) {
} else {
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.
*/
break;
}
if (polySelection) {
/* for poly-selections, search from the beginning to see if sl,uid match */
break;
}
}
if (pSel) {
/* found a match */
} else {
/*
* Doesn't match yet; we'll get called again
* After it gets created.
*/
}
} else {
/* Assign the sl & uid */
}
break;
case X_GetSelectionOwner:
case X_ConvertSelection:
if (polySelection) {
/* for poly-selections, search from the beginning to see if sl,uid match */
break;
}
}
if (pSel) {
} else {
/*
* Doesn't match yet; we'll get called again
* After it gets created.
*/
return;
}
}
/*
* Selection Agent processing. Override the owner
*/
if (!HasWinSelection(tsolinfo) &&
} else {
if (HasWinSelection(tsolinfo) &&
}
}
break;
default:
#ifndef NO_TSOL_DEBUG_MESSAGES
"policy not implemented for CheckSelectionAccess(%s, %s, %s, %s) = %s\n",
#endif /* !NO_TSOL_DEBUG_MESSAGES */
break;
}
}
static CALLBACK(
{
int reqtype;
if (!polyprop) {
if (WindowIsRoot(pWin)) {
if (client == serverClient)
else
} else {
}
}
/* If current property is not accessible, move on to
* next one for ListProperty
*/
}
} else {
/* Handle polyinstantiated property */
if (!(access_mode & DixCreateAccess)) {
return;
}
} else {
/* search for a matching (sl, uid) pair */
while (pProp) {
break; /* match found */
}
if (pProp) {
} else {
}
}
}
#ifndef NO_TSOL_DEBUG_MESSAGES
"TsolCheckPropertyAccess(%s, 0x%x, %s, %s) = %s\n",
#endif /* !NO_TSOL_DEBUG_MESSAGES */
}
}
static CALLBACK(
{
} else {
}
}
#ifdef UNUSED
/*
* Return TRUE if host is cipso
*/
int
{
char *rhost;
extern tsol_host_type_t tsol_getrhtype(char *);
perror("getsockname: failed\n");
return FALSE;
}
return TRUE;
}
return FALSE;
}
#endif