1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun
3*4882a593Smuzhiyun Copyright 1988, 1998 The Open Group
4*4882a593Smuzhiyun
5*4882a593Smuzhiyun Permission to use, copy, modify, distribute, and sell this software and its
6*4882a593Smuzhiyun documentation for any purpose is hereby granted without fee, provided that
7*4882a593Smuzhiyun the above copyright notice appear in all copies and that both that
8*4882a593Smuzhiyun copyright notice and this permission notice appear in supporting
9*4882a593Smuzhiyun documentation.
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun The above copyright notice and this permission notice shall be included
12*4882a593Smuzhiyun in all copies or substantial portions of the Software.
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15*4882a593Smuzhiyun OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16*4882a593Smuzhiyun MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17*4882a593Smuzhiyun IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18*4882a593Smuzhiyun OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19*4882a593Smuzhiyun ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20*4882a593Smuzhiyun OTHER DEALINGS IN THE SOFTWARE.
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun Except as contained in this notice, the name of The Open Group shall
23*4882a593Smuzhiyun not be used in advertising or otherwise to promote the sale, use or
24*4882a593Smuzhiyun other dealings in this Software without prior written authorization
25*4882a593Smuzhiyun from The Open Group.
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun */
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun /*
30*4882a593Smuzhiyun * authorization hooks for the server
31*4882a593Smuzhiyun * Author: Keith Packard, MIT X Consortium
32*4882a593Smuzhiyun */
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
35*4882a593Smuzhiyun #include <dix-config.h>
36*4882a593Smuzhiyun #endif
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun #include <X11/X.h>
39*4882a593Smuzhiyun #include <X11/Xauth.h>
40*4882a593Smuzhiyun #include "misc.h"
41*4882a593Smuzhiyun #include "osdep.h"
42*4882a593Smuzhiyun #include "dixstruct.h"
43*4882a593Smuzhiyun #include <sys/types.h>
44*4882a593Smuzhiyun #include <sys/stat.h>
45*4882a593Smuzhiyun #include <errno.h>
46*4882a593Smuzhiyun #ifdef WIN32
47*4882a593Smuzhiyun #include <X11/Xw32defs.h>
48*4882a593Smuzhiyun #endif
49*4882a593Smuzhiyun #ifdef HAVE_LIBBSD
50*4882a593Smuzhiyun #include <bsd/stdlib.h> /* for arc4random_buf() */
51*4882a593Smuzhiyun #endif
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun struct protocol {
54*4882a593Smuzhiyun unsigned short name_length;
55*4882a593Smuzhiyun const char *name;
56*4882a593Smuzhiyun AuthAddCFunc Add; /* new authorization data */
57*4882a593Smuzhiyun AuthCheckFunc Check; /* verify client authorization data */
58*4882a593Smuzhiyun AuthRstCFunc Reset; /* delete all authorization data entries */
59*4882a593Smuzhiyun AuthFromIDFunc FromID; /* convert ID to cookie */
60*4882a593Smuzhiyun AuthRemCFunc Remove; /* remove a specific cookie */
61*4882a593Smuzhiyun #ifdef XCSECURITY
62*4882a593Smuzhiyun AuthGenCFunc Generate;
63*4882a593Smuzhiyun #endif
64*4882a593Smuzhiyun };
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun static struct protocol protocols[] = {
67*4882a593Smuzhiyun {(unsigned short) 18, "MIT-MAGIC-COOKIE-1",
68*4882a593Smuzhiyun MitAddCookie, MitCheckCookie, MitResetCookie,
69*4882a593Smuzhiyun MitFromID, MitRemoveCookie,
70*4882a593Smuzhiyun #ifdef XCSECURITY
71*4882a593Smuzhiyun MitGenerateCookie
72*4882a593Smuzhiyun #endif
73*4882a593Smuzhiyun },
74*4882a593Smuzhiyun #ifdef HASXDMAUTH
75*4882a593Smuzhiyun {(unsigned short) 19, "XDM-AUTHORIZATION-1",
76*4882a593Smuzhiyun XdmAddCookie, XdmCheckCookie, XdmResetCookie,
77*4882a593Smuzhiyun XdmFromID, XdmRemoveCookie,
78*4882a593Smuzhiyun #ifdef XCSECURITY
79*4882a593Smuzhiyun NULL
80*4882a593Smuzhiyun #endif
81*4882a593Smuzhiyun },
82*4882a593Smuzhiyun #endif
83*4882a593Smuzhiyun #ifdef SECURE_RPC
84*4882a593Smuzhiyun {(unsigned short) 9, "SUN-DES-1",
85*4882a593Smuzhiyun SecureRPCAdd, SecureRPCCheck, SecureRPCReset,
86*4882a593Smuzhiyun SecureRPCFromID, SecureRPCRemove,
87*4882a593Smuzhiyun #ifdef XCSECURITY
88*4882a593Smuzhiyun NULL
89*4882a593Smuzhiyun #endif
90*4882a593Smuzhiyun },
91*4882a593Smuzhiyun #endif
92*4882a593Smuzhiyun };
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun #define NUM_AUTHORIZATION ARRAY_SIZE(protocols)
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun /*
97*4882a593Smuzhiyun * Initialize all classes of authorization by reading the
98*4882a593Smuzhiyun * specified authorization file
99*4882a593Smuzhiyun */
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun static const char *authorization_file = NULL;
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun static Bool ShouldLoadAuth = TRUE;
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun void
InitAuthorization(const char * file_name)106*4882a593Smuzhiyun InitAuthorization(const char *file_name)
107*4882a593Smuzhiyun {
108*4882a593Smuzhiyun authorization_file = file_name;
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun static int
LoadAuthorization(void)112*4882a593Smuzhiyun LoadAuthorization(void)
113*4882a593Smuzhiyun {
114*4882a593Smuzhiyun FILE *f;
115*4882a593Smuzhiyun Xauth *auth;
116*4882a593Smuzhiyun int i;
117*4882a593Smuzhiyun int count = 0;
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun ShouldLoadAuth = FALSE;
120*4882a593Smuzhiyun if (!authorization_file)
121*4882a593Smuzhiyun return 0;
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun errno = 0;
124*4882a593Smuzhiyun f = Fopen(authorization_file, "r");
125*4882a593Smuzhiyun if (!f) {
126*4882a593Smuzhiyun LogMessageVerb(X_ERROR, 0,
127*4882a593Smuzhiyun "Failed to open authorization file \"%s\": %s\n",
128*4882a593Smuzhiyun authorization_file,
129*4882a593Smuzhiyun errno != 0 ? strerror(errno) : "Unknown error");
130*4882a593Smuzhiyun return -1;
131*4882a593Smuzhiyun }
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun while ((auth = XauReadAuth(f)) != 0) {
134*4882a593Smuzhiyun for (i = 0; i < NUM_AUTHORIZATION; i++) {
135*4882a593Smuzhiyun if (protocols[i].name_length == auth->name_length &&
136*4882a593Smuzhiyun memcmp(protocols[i].name, auth->name,
137*4882a593Smuzhiyun (int) auth->name_length) == 0 && protocols[i].Add) {
138*4882a593Smuzhiyun ++count;
139*4882a593Smuzhiyun (*protocols[i].Add) (auth->data_length, auth->data,
140*4882a593Smuzhiyun FakeClientID(0));
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun }
143*4882a593Smuzhiyun XauDisposeAuth(auth);
144*4882a593Smuzhiyun }
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun Fclose(f);
147*4882a593Smuzhiyun return count;
148*4882a593Smuzhiyun }
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun #ifdef XDMCP
151*4882a593Smuzhiyun /*
152*4882a593Smuzhiyun * XdmcpInit calls this function to discover all authorization
153*4882a593Smuzhiyun * schemes supported by the display
154*4882a593Smuzhiyun */
155*4882a593Smuzhiyun void
RegisterAuthorizations(void)156*4882a593Smuzhiyun RegisterAuthorizations(void)
157*4882a593Smuzhiyun {
158*4882a593Smuzhiyun int i;
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun for (i = 0; i < NUM_AUTHORIZATION; i++)
161*4882a593Smuzhiyun XdmcpRegisterAuthorization(protocols[i].name,
162*4882a593Smuzhiyun (int) protocols[i].name_length);
163*4882a593Smuzhiyun }
164*4882a593Smuzhiyun #endif
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun XID
CheckAuthorization(unsigned int name_length,const char * name,unsigned int data_length,const char * data,ClientPtr client,const char ** reason)167*4882a593Smuzhiyun CheckAuthorization(unsigned int name_length,
168*4882a593Smuzhiyun const char *name,
169*4882a593Smuzhiyun unsigned int data_length,
170*4882a593Smuzhiyun const char *data, ClientPtr client, const char **reason)
171*4882a593Smuzhiyun { /* failure message. NULL for default msg */
172*4882a593Smuzhiyun int i;
173*4882a593Smuzhiyun struct stat buf;
174*4882a593Smuzhiyun static time_t lastmod = 0;
175*4882a593Smuzhiyun static Bool loaded = FALSE;
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun if (!authorization_file || stat(authorization_file, &buf)) {
178*4882a593Smuzhiyun if (lastmod != 0) {
179*4882a593Smuzhiyun lastmod = 0;
180*4882a593Smuzhiyun ShouldLoadAuth = TRUE; /* stat lost, so force reload */
181*4882a593Smuzhiyun }
182*4882a593Smuzhiyun }
183*4882a593Smuzhiyun else if (buf.st_mtime > lastmod) {
184*4882a593Smuzhiyun lastmod = buf.st_mtime;
185*4882a593Smuzhiyun ShouldLoadAuth = TRUE;
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun if (ShouldLoadAuth) {
188*4882a593Smuzhiyun int loadauth = LoadAuthorization();
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun /*
191*4882a593Smuzhiyun * If the authorization file has at least one entry for this server,
192*4882a593Smuzhiyun * disable local access. (loadauth > 0)
193*4882a593Smuzhiyun *
194*4882a593Smuzhiyun * If there are zero entries (either initially or when the
195*4882a593Smuzhiyun * authorization file is later reloaded), or if a valid
196*4882a593Smuzhiyun * authorization file was never loaded, enable local access.
197*4882a593Smuzhiyun * (loadauth == 0 || !loaded)
198*4882a593Smuzhiyun *
199*4882a593Smuzhiyun * If the authorization file was loaded initially (with valid
200*4882a593Smuzhiyun * entries for this server), and reloading it later fails, don't
201*4882a593Smuzhiyun * change anything. (loadauth == -1 && loaded)
202*4882a593Smuzhiyun */
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun if (loadauth > 0) {
205*4882a593Smuzhiyun DisableLocalAccess(); /* got at least one */
206*4882a593Smuzhiyun loaded = TRUE;
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun else if (loadauth == 0 || !loaded)
209*4882a593Smuzhiyun EnableLocalAccess();
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun if (name_length) {
212*4882a593Smuzhiyun for (i = 0; i < NUM_AUTHORIZATION; i++) {
213*4882a593Smuzhiyun if (protocols[i].name_length == name_length &&
214*4882a593Smuzhiyun memcmp(protocols[i].name, name, (int) name_length) == 0) {
215*4882a593Smuzhiyun return (*protocols[i].Check) (data_length, data, client,
216*4882a593Smuzhiyun reason);
217*4882a593Smuzhiyun }
218*4882a593Smuzhiyun *reason = "Protocol not supported by server\n";
219*4882a593Smuzhiyun }
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun else
222*4882a593Smuzhiyun *reason = "No protocol specified\n";
223*4882a593Smuzhiyun return (XID) ~0L;
224*4882a593Smuzhiyun }
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun void
ResetAuthorization(void)227*4882a593Smuzhiyun ResetAuthorization(void)
228*4882a593Smuzhiyun {
229*4882a593Smuzhiyun int i;
230*4882a593Smuzhiyun
231*4882a593Smuzhiyun for (i = 0; i < NUM_AUTHORIZATION; i++)
232*4882a593Smuzhiyun if (protocols[i].Reset)
233*4882a593Smuzhiyun (*protocols[i].Reset) ();
234*4882a593Smuzhiyun ShouldLoadAuth = TRUE;
235*4882a593Smuzhiyun }
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun int
AuthorizationFromID(XID id,unsigned short * name_lenp,const char ** namep,unsigned short * data_lenp,char ** datap)238*4882a593Smuzhiyun AuthorizationFromID(XID id,
239*4882a593Smuzhiyun unsigned short *name_lenp,
240*4882a593Smuzhiyun const char **namep, unsigned short *data_lenp, char **datap)
241*4882a593Smuzhiyun {
242*4882a593Smuzhiyun int i;
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun for (i = 0; i < NUM_AUTHORIZATION; i++) {
245*4882a593Smuzhiyun if (protocols[i].FromID &&
246*4882a593Smuzhiyun (*protocols[i].FromID) (id, data_lenp, datap)) {
247*4882a593Smuzhiyun *name_lenp = protocols[i].name_length;
248*4882a593Smuzhiyun *namep = protocols[i].name;
249*4882a593Smuzhiyun return 1;
250*4882a593Smuzhiyun }
251*4882a593Smuzhiyun }
252*4882a593Smuzhiyun return 0;
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun int
RemoveAuthorization(unsigned short name_length,const char * name,unsigned short data_length,const char * data)256*4882a593Smuzhiyun RemoveAuthorization(unsigned short name_length,
257*4882a593Smuzhiyun const char *name,
258*4882a593Smuzhiyun unsigned short data_length, const char *data)
259*4882a593Smuzhiyun {
260*4882a593Smuzhiyun int i;
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun for (i = 0; i < NUM_AUTHORIZATION; i++) {
263*4882a593Smuzhiyun if (protocols[i].name_length == name_length &&
264*4882a593Smuzhiyun memcmp(protocols[i].name, name, (int) name_length) == 0 &&
265*4882a593Smuzhiyun protocols[i].Remove) {
266*4882a593Smuzhiyun return (*protocols[i].Remove) (data_length, data);
267*4882a593Smuzhiyun }
268*4882a593Smuzhiyun }
269*4882a593Smuzhiyun return 0;
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun int
AddAuthorization(unsigned name_length,const char * name,unsigned data_length,char * data)273*4882a593Smuzhiyun AddAuthorization(unsigned name_length, const char *name,
274*4882a593Smuzhiyun unsigned data_length, char *data)
275*4882a593Smuzhiyun {
276*4882a593Smuzhiyun int i;
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun for (i = 0; i < NUM_AUTHORIZATION; i++) {
279*4882a593Smuzhiyun if (protocols[i].name_length == name_length &&
280*4882a593Smuzhiyun memcmp(protocols[i].name, name, (int) name_length) == 0 &&
281*4882a593Smuzhiyun protocols[i].Add) {
282*4882a593Smuzhiyun return (*protocols[i].Add) (data_length, data, FakeClientID(0));
283*4882a593Smuzhiyun }
284*4882a593Smuzhiyun }
285*4882a593Smuzhiyun return 0;
286*4882a593Smuzhiyun }
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun #ifdef XCSECURITY
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun XID
GenerateAuthorization(unsigned name_length,const char * name,unsigned data_length,const char * data,unsigned * data_length_return,char ** data_return)291*4882a593Smuzhiyun GenerateAuthorization(unsigned name_length,
292*4882a593Smuzhiyun const char *name,
293*4882a593Smuzhiyun unsigned data_length,
294*4882a593Smuzhiyun const char *data,
295*4882a593Smuzhiyun unsigned *data_length_return, char **data_return)
296*4882a593Smuzhiyun {
297*4882a593Smuzhiyun int i;
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun for (i = 0; i < NUM_AUTHORIZATION; i++) {
300*4882a593Smuzhiyun if (protocols[i].name_length == name_length &&
301*4882a593Smuzhiyun memcmp(protocols[i].name, name, (int) name_length) == 0 &&
302*4882a593Smuzhiyun protocols[i].Generate) {
303*4882a593Smuzhiyun return (*protocols[i].Generate) (data_length, data,
304*4882a593Smuzhiyun FakeClientID(0),
305*4882a593Smuzhiyun data_length_return, data_return);
306*4882a593Smuzhiyun }
307*4882a593Smuzhiyun }
308*4882a593Smuzhiyun return -1;
309*4882a593Smuzhiyun }
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun #endif /* XCSECURITY */
312*4882a593Smuzhiyun
313*4882a593Smuzhiyun void
GenerateRandomData(int len,char * buf)314*4882a593Smuzhiyun GenerateRandomData(int len, char *buf)
315*4882a593Smuzhiyun {
316*4882a593Smuzhiyun #ifdef HAVE_ARC4RANDOM_BUF
317*4882a593Smuzhiyun arc4random_buf(buf, len);
318*4882a593Smuzhiyun #else
319*4882a593Smuzhiyun int fd;
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun fd = open("/dev/urandom", O_RDONLY);
322*4882a593Smuzhiyun read(fd, buf, len);
323*4882a593Smuzhiyun close(fd);
324*4882a593Smuzhiyun #endif
325*4882a593Smuzhiyun }
326