1caade7ccSmrg/* 2caade7ccSmrg 3caade7ccSmrgCopyright 1996, 1998 The Open Group 4caade7ccSmrg 5caade7ccSmrgPermission to use, copy, modify, distribute, and sell this software and its 6caade7ccSmrgdocumentation for any purpose is hereby granted without fee, provided that 7caade7ccSmrgthe above copyright notice appear in all copies and that both that 8caade7ccSmrgcopyright notice and this permission notice appear in supporting 9caade7ccSmrgdocumentation. 10caade7ccSmrg 11caade7ccSmrgThe above copyright notice and this permission notice shall be included in 12caade7ccSmrgall copies or substantial portions of the Software. 13caade7ccSmrg 14caade7ccSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15caade7ccSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16caade7ccSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17caade7ccSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18caade7ccSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19caade7ccSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20caade7ccSmrg 21caade7ccSmrgExcept as contained in this notice, the name of The Open Group shall not be 22caade7ccSmrgused in advertising or otherwise to promote the sale, use or other dealings 23caade7ccSmrgin this Software without prior written authorization from The Open Group. 24caade7ccSmrg 25caade7ccSmrg*/ 26caade7ccSmrg 27caade7ccSmrg#ifdef HAVE_CONFIG_H 28caade7ccSmrg#include <config.h> 29caade7ccSmrg#endif 30caade7ccSmrg#include <X11/Xlibint.h> 31caade7ccSmrg#include <stdio.h> 32caade7ccSmrg#include <X11/extensions/Xext.h> 33caade7ccSmrg#include <X11/extensions/extutil.h> 34485f0483Smrg#include <X11/extensions/securproto.h> 35485f0483Smrg#include <X11/extensions/security.h> 36cc4920e5Smrg#include <assert.h> 37caade7ccSmrg 38caade7ccSmrgstatic XExtensionInfo _Security_info_data; 39caade7ccSmrgstatic XExtensionInfo *Security_info = &_Security_info_data; 40af9a7ee5Smrgstatic const char *Security_extension_name = SECURITY_EXTENSION_NAME; 41caade7ccSmrg 42caade7ccSmrg#define SecurityCheckExtension(dpy,i,val) \ 43caade7ccSmrg XextCheckExtension (dpy, i, Security_extension_name, val) 44caade7ccSmrg#define SecuritySimpleCheckExtension(dpy,i) \ 45caade7ccSmrg XextSimpleCheckExtension (dpy, i, Security_extension_name) 46caade7ccSmrg 47caade7ccSmrg#define SecurityGetReq(name,req,info) GetReq (name, req); \ 48caade7ccSmrg req->reqType = info->codes->major_opcode; \ 49caade7ccSmrg req->securityReqType = X_##name; 50caade7ccSmrg 51caade7ccSmrg/***************************************************************************** 52caade7ccSmrg * * 53caade7ccSmrg * private utility routines * 54caade7ccSmrg * * 55caade7ccSmrg *****************************************************************************/ 56caade7ccSmrg 57caade7ccSmrg/* 58caade7ccSmrg * find_display - locate the display info block 59caade7ccSmrg */ 60caade7ccSmrgstatic int close_display(Display *dpy, XExtCodes *codes); 61caade7ccSmrgstatic Bool wire_to_event(Display *dpy, XEvent *event, xEvent *wire); 62caade7ccSmrgstatic Status event_to_wire(Display *dpy, XEvent *event, xEvent *wire); 63caade7ccSmrgstatic char *error_string(Display *dpy, int code, XExtCodes *codes, 64caade7ccSmrg char *buf, int n); 65caade7ccSmrg 66caade7ccSmrgstatic XExtensionHooks Security_extension_hooks = { 67caade7ccSmrg NULL, /* create_gc */ 68caade7ccSmrg NULL, /* copy_gc */ 69caade7ccSmrg NULL, /* flush_gc */ 70caade7ccSmrg NULL, /* free_gc */ 71caade7ccSmrg NULL, /* create_font */ 72caade7ccSmrg NULL, /* free_font */ 73caade7ccSmrg close_display, /* close_display */ 74caade7ccSmrg wire_to_event, /* wire_to_event */ 75caade7ccSmrg event_to_wire, /* event_to_wire */ 76caade7ccSmrg NULL, /* error */ 77caade7ccSmrg error_string /* error_string */ 78caade7ccSmrg}; 79caade7ccSmrg 80af9a7ee5Smrgstatic const char *security_error_list[] = { 81caade7ccSmrg "BadAuthorization", 82caade7ccSmrg "BadAuthorizationProtocol" 83caade7ccSmrg}; 84caade7ccSmrg 85caade7ccSmrgstatic XEXT_GENERATE_FIND_DISPLAY (find_display, Security_info, 86caade7ccSmrg Security_extension_name, 87caade7ccSmrg &Security_extension_hooks, 88caade7ccSmrg XSecurityNumberEvents, NULL) 89caade7ccSmrg 90caade7ccSmrgstatic XEXT_GENERATE_CLOSE_DISPLAY (close_display, Security_info) 91caade7ccSmrg 92caade7ccSmrgstatic 93caade7ccSmrgXEXT_GENERATE_ERROR_STRING(error_string, Security_extension_name, 94caade7ccSmrg XSecurityNumberErrors, security_error_list) 95caade7ccSmrg 96caade7ccSmrgstatic Bool 97caade7ccSmrgwire_to_event(Display *dpy, XEvent *event, xEvent *wire) 98caade7ccSmrg{ 99caade7ccSmrg XExtDisplayInfo *info = find_display(dpy); 100caade7ccSmrg 101caade7ccSmrg SecurityCheckExtension (dpy, info, False); 102caade7ccSmrg 103caade7ccSmrg switch ((wire->u.u.type & 0x7F) - info->codes->first_event) 104caade7ccSmrg { 105caade7ccSmrg case XSecurityAuthorizationRevoked: 106caade7ccSmrg { 107caade7ccSmrg xSecurityAuthorizationRevokedEvent *rwire = 108caade7ccSmrg (xSecurityAuthorizationRevokedEvent *)wire; 109caade7ccSmrg XSecurityAuthorizationRevokedEvent *revent = 110caade7ccSmrg (XSecurityAuthorizationRevokedEvent *)event; 111caade7ccSmrg 112caade7ccSmrg revent->type = rwire->type & 0x7F; 113caade7ccSmrg revent->serial = _XSetLastRequestRead(dpy, 114caade7ccSmrg (xGenericReply *) wire); 115caade7ccSmrg revent->send_event = (rwire->type & 0x80) != 0; 116caade7ccSmrg revent->display = dpy; 117caade7ccSmrg revent->auth_id = rwire->authId; 118caade7ccSmrg return True; 119caade7ccSmrg } 120caade7ccSmrg } 121caade7ccSmrg return False; 122caade7ccSmrg} 123caade7ccSmrg 124caade7ccSmrgstatic Status 125caade7ccSmrgevent_to_wire(Display *dpy, XEvent *event, xEvent *wire) 126caade7ccSmrg{ 127caade7ccSmrg XExtDisplayInfo *info = find_display(dpy); 128caade7ccSmrg 129caade7ccSmrg SecurityCheckExtension(dpy, info, False); 130caade7ccSmrg 131caade7ccSmrg switch ((event->type & 0x7F) - info->codes->first_event) 132caade7ccSmrg { 133caade7ccSmrg case XSecurityAuthorizationRevoked: 134caade7ccSmrg { 135caade7ccSmrg xSecurityAuthorizationRevokedEvent *rwire = 136caade7ccSmrg (xSecurityAuthorizationRevokedEvent *)wire; 137caade7ccSmrg XSecurityAuthorizationRevokedEvent *revent = 138caade7ccSmrg (XSecurityAuthorizationRevokedEvent *)event; 139caade7ccSmrg rwire->type = revent->type | (revent->send_event ? 0x80 : 0); 140caade7ccSmrg rwire->sequenceNumber = revent->serial & 0xFFFF; 141caade7ccSmrg return True; 142caade7ccSmrg } 143caade7ccSmrg } 144caade7ccSmrg return False; 145caade7ccSmrg} 146caade7ccSmrg 147caade7ccSmrg/***************************************************************************** 148caade7ccSmrg * * 149caade7ccSmrg * Security public interfaces * 150caade7ccSmrg * * 151caade7ccSmrg *****************************************************************************/ 152caade7ccSmrg 153caade7ccSmrgStatus XSecurityQueryExtension ( 154caade7ccSmrg Display *dpy, 155caade7ccSmrg int *major_version_return, 156caade7ccSmrg int *minor_version_return) 157caade7ccSmrg{ 158caade7ccSmrg XExtDisplayInfo *info = find_display (dpy); 159caade7ccSmrg xSecurityQueryVersionReply rep; 160caade7ccSmrg register xSecurityQueryVersionReq *req; 161caade7ccSmrg 162caade7ccSmrg if (!XextHasExtension (info)) 163caade7ccSmrg return (Status)0; /* failure */ 164caade7ccSmrg 165caade7ccSmrg LockDisplay (dpy); 166caade7ccSmrg SecurityGetReq (SecurityQueryVersion, req, info); 167caade7ccSmrg req->majorVersion = SECURITY_MAJOR_VERSION; 168caade7ccSmrg req->minorVersion = SECURITY_MINOR_VERSION; 169caade7ccSmrg 170caade7ccSmrg if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) { 171caade7ccSmrg UnlockDisplay (dpy); 172caade7ccSmrg SyncHandle (); 173caade7ccSmrg return (Status)0; /* failure */ 174caade7ccSmrg } 175caade7ccSmrg *major_version_return = rep.majorVersion; 176caade7ccSmrg *minor_version_return = rep.minorVersion; 177caade7ccSmrg UnlockDisplay (dpy); 178caade7ccSmrg 179caade7ccSmrg SyncHandle (); 180caade7ccSmrg 181caade7ccSmrg if (*major_version_return != SECURITY_MAJOR_VERSION) 182caade7ccSmrg return (Status)0; /* failure */ 183caade7ccSmrg else 184caade7ccSmrg return (Status)1; /* success */ 185caade7ccSmrg} 186caade7ccSmrg 187caade7ccSmrgXauth * 188caade7ccSmrgXSecurityAllocXauth(void) 189caade7ccSmrg{ 190caade7ccSmrg return Xcalloc(1, sizeof(Xauth)); 191caade7ccSmrg} 192caade7ccSmrg 193caade7ccSmrgvoid 194caade7ccSmrgXSecurityFreeXauth(Xauth *auth) 195caade7ccSmrg{ 196caade7ccSmrg XFree(auth); 197caade7ccSmrg} 198caade7ccSmrg 199cc4920e5Smrg#ifdef HAVE___BUILTIN_POPCOUNTL 200cc4920e5Smrg# define Ones __builtin_popcountl 201cc4920e5Smrg#else 202cc4920e5Smrg/* 203cc4920e5Smrg * Count the number of bits set to 1 in a 32-bit word. 204cc4920e5Smrg * Algorithm from MIT AI Lab Memo 239: "HAKMEM", ITEM 169. 205cc4920e5Smrg * http://dspace.mit.edu/handle/1721.1/6086 206cc4920e5Smrg */ 207cc4920e5Smrgstatic inline int 208caade7ccSmrgOnes(Mask mask) 209caade7ccSmrg{ 210caade7ccSmrg register Mask y; 211caade7ccSmrg 212cc4920e5Smrg y = (mask >> 1) & 033333333333; 213caade7ccSmrg y = mask - y - ((y >>1) & 033333333333); 214caade7ccSmrg return (((y + (y >> 3)) & 030707070707) % 077); 215caade7ccSmrg} 216cc4920e5Smrg#endif 217caade7ccSmrg 218caade7ccSmrgXauth * 219caade7ccSmrgXSecurityGenerateAuthorization( 220caade7ccSmrg Display *dpy, 221caade7ccSmrg Xauth *auth_in, 222caade7ccSmrg unsigned long valuemask, 223caade7ccSmrg XSecurityAuthorizationAttributes *attributes, 224caade7ccSmrg XSecurityAuthorization *auth_id_return) 225caade7ccSmrg{ 226caade7ccSmrg XExtDisplayInfo *info = find_display (dpy); 227caade7ccSmrg register xSecurityGenerateAuthorizationReq *req; 228caade7ccSmrg xSecurityGenerateAuthorizationReply rep; 229caade7ccSmrg Xauth *auth_return; 230cc4920e5Smrg unsigned long values[4]; 231caade7ccSmrg unsigned long *value = values; 232caade7ccSmrg unsigned int nvalues; 233caade7ccSmrg 234cc4920e5Smrg /* values array must have a slot for each possible valuemask value */ 235cc4920e5Smrg assert(Ones(XSecurityAllAuthorizationAttributes) 236cc4920e5Smrg == (sizeof(values) / sizeof(values[0]))); 237cc4920e5Smrg 238caade7ccSmrg *auth_id_return = 0; /* in case we fail */ 239caade7ccSmrg 240caade7ccSmrg /* make sure extension is available */ 241caade7ccSmrg 242caade7ccSmrg SecurityCheckExtension (dpy, info, (Xauth *)NULL); 243caade7ccSmrg 244caade7ccSmrg LockDisplay(dpy); 245caade7ccSmrg SecurityGetReq(SecurityGenerateAuthorization, req, info); 246caade7ccSmrg 247caade7ccSmrg req->nbytesAuthProto = auth_in->name_length; 248caade7ccSmrg req->nbytesAuthData = auth_in->data_length; 249caade7ccSmrg 250caade7ccSmrg /* adjust length to account for auth name and data */ 251caade7ccSmrg req->length += (auth_in->name_length + (unsigned)3) >> 2; 252caade7ccSmrg req->length += (auth_in->data_length + (unsigned)3) >> 2; 253caade7ccSmrg 254caade7ccSmrg /* adjust length to account for list of values */ 255caade7ccSmrg req->valueMask = valuemask & XSecurityAllAuthorizationAttributes; 256caade7ccSmrg nvalues = Ones(req->valueMask); 257caade7ccSmrg req->length += nvalues; 258caade7ccSmrg 259caade7ccSmrg /* send auth name and data */ 260caade7ccSmrg Data(dpy, auth_in->name, auth_in->name_length); 261caade7ccSmrg Data(dpy, auth_in->data, auth_in->data_length); 262caade7ccSmrg 263caade7ccSmrg /* send values */ 264caade7ccSmrg if (valuemask & XSecurityTimeout) *value++ = attributes->timeout; 265caade7ccSmrg if (valuemask & XSecurityTrustLevel) *value++ = attributes->trust_level; 266caade7ccSmrg if (valuemask & XSecurityGroup) *value++ = attributes->group; 267caade7ccSmrg if (valuemask & XSecurityEventMask) *value++ = attributes->event_mask; 268caade7ccSmrg 269caade7ccSmrg nvalues <<= 2; 270caade7ccSmrg Data32(dpy, (long *)values, (long)nvalues); 271caade7ccSmrg 272caade7ccSmrg if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) { 273caade7ccSmrg UnlockDisplay (dpy); 274caade7ccSmrg SyncHandle (); 275caade7ccSmrg return (Xauth *)NULL; 276caade7ccSmrg } 277caade7ccSmrg 278caade7ccSmrg *auth_id_return = rep.authId; 279caade7ccSmrg 280caade7ccSmrg /* Allocate space for the Xauth struct and the auth name and data all 281caade7ccSmrg * in one hunk. This lets XSecurityFreeXauth not have to care 282caade7ccSmrg * about whether the auth was allocated here or in 283caade7ccSmrg * XSecurityAllocXauth; in both cases, you just free one pointer. 284caade7ccSmrg */ 285caade7ccSmrg 2860760f5d2Smrg if ((auth_return = Xcalloc(1, 287caade7ccSmrg (sizeof(Xauth) + auth_in->name_length + rep.dataLength)))) 288caade7ccSmrg { 289caade7ccSmrg auth_return->data_length = rep.dataLength; 290caade7ccSmrg auth_return->data = (char *)&auth_return[1]; 291caade7ccSmrg _XReadPad(dpy, auth_return->data, (long)rep.dataLength); 292caade7ccSmrg 293caade7ccSmrg auth_return->name_length = auth_in->name_length; 294caade7ccSmrg auth_return->name = auth_return->data + auth_return->data_length; 295caade7ccSmrg memcpy(auth_return->name, auth_in->name, auth_return->name_length); 296caade7ccSmrg } 297caade7ccSmrg else 298caade7ccSmrg { 299af9a7ee5Smrg _XEatDataWords(dpy, rep.length); 300caade7ccSmrg } 301caade7ccSmrg 302caade7ccSmrg UnlockDisplay (dpy); 303caade7ccSmrg SyncHandle (); 304caade7ccSmrg return auth_return; 305caade7ccSmrg 306caade7ccSmrg} /* XSecurityGenerateAuthorization */ 307caade7ccSmrg 308caade7ccSmrgStatus 309caade7ccSmrgXSecurityRevokeAuthorization( 310caade7ccSmrg Display *dpy, 311caade7ccSmrg XSecurityAuthorization auth_id) 312caade7ccSmrg{ 313caade7ccSmrg XExtDisplayInfo *info = find_display (dpy); 314caade7ccSmrg xSecurityRevokeAuthorizationReq *req; 315caade7ccSmrg 316caade7ccSmrg SecurityCheckExtension (dpy, info, 0); 317caade7ccSmrg LockDisplay(dpy); 318caade7ccSmrg SecurityGetReq(SecurityRevokeAuthorization, req, info); 319caade7ccSmrg req->authId = auth_id; 320caade7ccSmrg UnlockDisplay (dpy); 321caade7ccSmrg SyncHandle (); 322caade7ccSmrg return 1; 323caade7ccSmrg} /* XSecurityRevokeAuthorization */ 324