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