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