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