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