XSecurity.c revision af9a7ee5
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>
36af9a7ee5Smrg#include "eat.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
199caade7ccSmrgstatic int
200caade7ccSmrgOnes(Mask mask)
201caade7ccSmrg{
202caade7ccSmrg    register Mask y;
203caade7ccSmrg
204caade7ccSmrg    y = (mask >> 1) &033333333333;
205caade7ccSmrg    y = mask - y - ((y >>1) & 033333333333);
206caade7ccSmrg    return (((y + (y >> 3)) & 030707070707) % 077);
207caade7ccSmrg}
208caade7ccSmrg
209caade7ccSmrgXauth *
210caade7ccSmrgXSecurityGenerateAuthorization(
211caade7ccSmrg    Display *dpy,
212caade7ccSmrg    Xauth *auth_in,
213caade7ccSmrg    unsigned long valuemask,
214caade7ccSmrg    XSecurityAuthorizationAttributes *attributes,
215caade7ccSmrg    XSecurityAuthorization *auth_id_return)
216caade7ccSmrg{
217caade7ccSmrg    XExtDisplayInfo *info = find_display (dpy);
218caade7ccSmrg    register xSecurityGenerateAuthorizationReq *req;
219caade7ccSmrg    xSecurityGenerateAuthorizationReply rep;
220caade7ccSmrg    Xauth *auth_return;
221caade7ccSmrg    unsigned long values[3];
222caade7ccSmrg    unsigned long *value = values;
223caade7ccSmrg    unsigned int nvalues;
224caade7ccSmrg
225caade7ccSmrg    *auth_id_return = 0;  /* in case we fail */
226caade7ccSmrg
227caade7ccSmrg    /* make sure extension is available */
228caade7ccSmrg
229caade7ccSmrg    SecurityCheckExtension (dpy, info, (Xauth *)NULL);
230caade7ccSmrg
231caade7ccSmrg    LockDisplay(dpy);
232caade7ccSmrg    SecurityGetReq(SecurityGenerateAuthorization, req, info);
233caade7ccSmrg
234caade7ccSmrg    req->nbytesAuthProto = auth_in->name_length;
235caade7ccSmrg    req->nbytesAuthData  = auth_in->data_length;
236caade7ccSmrg
237caade7ccSmrg    /* adjust length to account for auth name and data */
238caade7ccSmrg    req->length += (auth_in->name_length + (unsigned)3) >> 2;
239caade7ccSmrg    req->length += (auth_in->data_length + (unsigned)3) >> 2;
240caade7ccSmrg
241caade7ccSmrg    /* adjust length to account for list of values */
242caade7ccSmrg    req->valueMask = valuemask & XSecurityAllAuthorizationAttributes;
243caade7ccSmrg    nvalues = Ones(req->valueMask);
244caade7ccSmrg    req->length += nvalues;
245caade7ccSmrg
246caade7ccSmrg    /* send auth name and data */
247caade7ccSmrg    Data(dpy, auth_in->name, auth_in->name_length);
248caade7ccSmrg    Data(dpy, auth_in->data, auth_in->data_length);
249caade7ccSmrg
250caade7ccSmrg    /* send values */
251caade7ccSmrg    if (valuemask & XSecurityTimeout)	 *value++ = attributes->timeout;
252caade7ccSmrg    if (valuemask & XSecurityTrustLevel) *value++ = attributes->trust_level;
253caade7ccSmrg    if (valuemask & XSecurityGroup)	 *value++ = attributes->group;
254caade7ccSmrg    if (valuemask & XSecurityEventMask)	 *value++ = attributes->event_mask;
255caade7ccSmrg
256caade7ccSmrg    nvalues <<= 2;
257caade7ccSmrg    Data32(dpy, (long *)values, (long)nvalues);
258caade7ccSmrg
259caade7ccSmrg    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
260caade7ccSmrg	UnlockDisplay (dpy);
261caade7ccSmrg	SyncHandle ();
262caade7ccSmrg	return (Xauth *)NULL;
263caade7ccSmrg    }
264caade7ccSmrg
265caade7ccSmrg    *auth_id_return = rep.authId;
266caade7ccSmrg
267caade7ccSmrg    /* Allocate space for the Xauth struct and the auth name and data all
268caade7ccSmrg     * in one hunk.  This lets XSecurityFreeXauth not have to care
269caade7ccSmrg     * about whether the auth was allocated here or in
270caade7ccSmrg     * XSecurityAllocXauth; in both cases, you just free one pointer.
271caade7ccSmrg     */
272caade7ccSmrg
273caade7ccSmrg    if ((auth_return = (Xauth *)Xcalloc(1,
274caade7ccSmrg		(sizeof(Xauth) + auth_in->name_length + rep.dataLength))))
275caade7ccSmrg    {
276caade7ccSmrg	auth_return->data_length = rep.dataLength;
277caade7ccSmrg	auth_return->data = (char *)&auth_return[1];
278caade7ccSmrg	_XReadPad(dpy, auth_return->data, (long)rep.dataLength);
279caade7ccSmrg
280caade7ccSmrg	auth_return->name_length = auth_in->name_length;
281caade7ccSmrg	auth_return->name = auth_return->data + auth_return->data_length;
282caade7ccSmrg	memcpy(auth_return->name, auth_in->name, auth_return->name_length);
283caade7ccSmrg    }
284caade7ccSmrg    else
285caade7ccSmrg    {
286af9a7ee5Smrg	_XEatDataWords(dpy, rep.length);
287caade7ccSmrg    }
288caade7ccSmrg
289caade7ccSmrg    UnlockDisplay (dpy);
290caade7ccSmrg    SyncHandle ();
291caade7ccSmrg    return auth_return;
292caade7ccSmrg
293caade7ccSmrg} /* XSecurityGenerateAuthorization */
294caade7ccSmrg
295caade7ccSmrgStatus
296caade7ccSmrgXSecurityRevokeAuthorization(
297caade7ccSmrg    Display *dpy,
298caade7ccSmrg    XSecurityAuthorization auth_id)
299caade7ccSmrg{
300caade7ccSmrg    XExtDisplayInfo *info = find_display (dpy);
301caade7ccSmrg    xSecurityRevokeAuthorizationReq *req;
302caade7ccSmrg
303caade7ccSmrg    SecurityCheckExtension (dpy, info, 0);
304caade7ccSmrg    LockDisplay(dpy);
305caade7ccSmrg    SecurityGetReq(SecurityRevokeAuthorization, req, info);
306caade7ccSmrg    req->authId = auth_id;
307caade7ccSmrg    UnlockDisplay (dpy);
308caade7ccSmrg    SyncHandle ();
309caade7ccSmrg    return 1;
310caade7ccSmrg} /* XSecurityRevokeAuthorization */
311