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