xref: /OK3568_Linux_fs/external/xserver/os/auth.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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