authutil.c revision c5629e66
1/* $Xorg: authutil.c,v 1.5 2001/02/09 02:03:26 xorgcvs Exp $ */
2/* $XdotOrg: xc/lib/ICE/authutil.c,v 1.3 2005/05/17 20:53:55 sandmann Exp $ */
3/******************************************************************************
4
5
6Copyright 1993, 1998  The Open Group
7
8Permission to use, copy, modify, distribute, and sell this software and its
9documentation for any purpose is hereby granted without fee, provided that
10the above copyright notice appear in all copies and that both that
11copyright notice and this permission notice appear in supporting
12documentation.
13
14The above copyright notice and this permission notice shall be included in
15all copies or substantial portions of the Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
20OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
24Except as contained in this notice, the name of The Open Group shall not be
25used in advertising or otherwise to promote the sale, use or other dealings
26in this Software without prior written authorization from The Open Group.
27
28Author: Ralph Mor, X Consortium
29******************************************************************************/
30/* $XFree86: authutil.c,v 3.9 2002/05/31 18:45:41 dawes Exp $ */
31
32#ifdef HAVE_CONFIG_H
33#include <config.h>
34#endif
35#include <X11/ICE/ICElib.h>
36#include "ICElibint.h"
37#include <X11/ICE/ICEutil.h>
38#include <X11/Xos.h>
39#include <sys/stat.h>
40#include <errno.h>
41
42#include <time.h>
43#define Time_t time_t
44#ifdef __UNIXOS2__
45extern char* getenv(const char*);
46#define link rename
47#endif
48#ifndef X_NOT_POSIX
49#include <unistd.h>
50#else
51#ifndef WIN32
52extern unsigned	sleep ();
53#else
54#define link rename
55#endif
56#endif
57
58static Status read_short (FILE *file, unsigned short *shortp);
59static Status read_string (FILE *file, char **stringp);
60static Status read_counted_string (FILE *file, unsigned short *countp, char **stringp);
61static Status write_short (FILE *file, unsigned short s);
62static Status write_string (FILE *file, char *string);
63static Status write_counted_string (FILE *file, unsigned short count, char *string);
64
65
66
67/*
68 * The following routines are for manipulating the .ICEauthority file
69 * These are utility functions - they are not part of the standard
70 * ICE library specification.
71 */
72
73char *
74IceAuthFileName (void)
75{
76    static char slashDotICEauthority[] = "/.ICEauthority";
77    char    	*name;
78    static char	*buf;
79    static int	bsize;
80    int	    	size;
81#if defined(WIN32) || defined(__UNIXOS2__)
82#ifndef PATH_MAX
83#define PATH_MAX 512
84#endif
85    char    	dir[PATH_MAX];
86#endif
87
88    if ((name = getenv ("ICEAUTHORITY")))
89	return (name);
90
91    name = getenv ("HOME");
92
93    if (!name)
94    {
95#ifdef WIN32
96    register char *ptr1;
97    register char *ptr2;
98    int len1 = 0, len2 = 0;
99
100    if ((ptr1 = getenv("HOMEDRIVE")) && (ptr2 = getenv("HOMEDIR"))) {
101	len1 = strlen (ptr1);
102	len2 = strlen (ptr2);
103    } else if ((ptr2 = getenv("USERNAME"))) {
104	len1 = strlen (ptr1 = "/users/");
105	len2 = strlen (ptr2);
106    }
107    if ((len1 + len2 + 1) < PATH_MAX) {
108	sprintf (dir, "%s%s", ptr1, (ptr2) ? ptr2 : "");
109	name = dir;
110    }
111    if (!name)
112#endif
113#ifdef __UNIXOS2__
114	strcpy (dir,"c:");
115	name = dir;
116	if (!name)
117#endif
118	return (NULL);
119    }
120
121    size = strlen (name) + strlen (&slashDotICEauthority[1]) + 2;
122
123    if (size > bsize)
124    {
125	if (buf)
126	    free (buf);
127	buf = malloc ((unsigned) size);
128	if (!buf)
129	    return (NULL);
130	bsize = size;
131    }
132
133    strcpy (buf, name);
134    strcat (buf, slashDotICEauthority + (name[1] == '\0' ? 1 : 0));
135
136    return (buf);
137}
138
139
140
141int
142IceLockAuthFile (
143	char	*file_name,
144	int	retries,
145	int	timeout,
146	long	dead
147)
148{
149    char	creat_name[1025], link_name[1025];
150    struct stat	statb;
151    Time_t	now;
152    int		creat_fd = -1;
153
154    if ((int) strlen (file_name) > 1022)
155	return (IceAuthLockError);
156
157    strcpy (creat_name, file_name);
158    strcat (creat_name, "-c");
159    strcpy (link_name, file_name);
160    strcat (link_name, "-l");
161
162    if (stat (creat_name, &statb) != -1)
163    {
164	now = time ((Time_t *) 0);
165
166	/*
167	 * NFS may cause ctime to be before now, special
168	 * case a 0 deadtime to force lock removal
169	 */
170
171	if (dead == 0 || now - statb.st_ctime > dead)
172	{
173	    unlink (creat_name);
174	    unlink (link_name);
175	}
176    }
177
178    while (retries > 0)
179    {
180	if (creat_fd == -1)
181	{
182	    creat_fd = creat (creat_name, 0666);
183
184	    if (creat_fd == -1)
185	    {
186		if (errno != EACCES)
187		    return (IceAuthLockError);
188	    }
189	    else
190		close (creat_fd);
191	}
192
193	if (creat_fd != -1)
194	{
195	    if (link (creat_name, link_name) != -1)
196		return (IceAuthLockSuccess);
197
198	    if (errno == ENOENT)
199	    {
200		creat_fd = -1;	/* force re-creat next time around */
201		continue;
202	    }
203
204	    if (errno != EEXIST)
205		return (IceAuthLockError);
206	}
207
208	sleep ((unsigned) timeout);
209	--retries;
210    }
211
212    return (IceAuthLockTimeout);
213}
214
215
216
217void
218IceUnlockAuthFile (
219	char	*file_name
220)
221{
222#ifndef WIN32
223    char	creat_name[1025];
224#endif
225    char	link_name[1025];
226
227    if ((int) strlen (file_name) > 1022)
228	return;
229
230#ifndef WIN32
231    strcpy (creat_name, file_name);
232    strcat (creat_name, "-c");
233#endif
234    strcpy (link_name, file_name);
235    strcat (link_name, "-l");
236
237#ifndef WIN32
238    unlink (creat_name);
239#endif
240    unlink (link_name);
241}
242
243
244
245IceAuthFileEntry *
246IceReadAuthFileEntry (
247	FILE	*auth_file
248)
249{
250    IceAuthFileEntry   	local;
251    IceAuthFileEntry   	*ret;
252
253    local.protocol_name = NULL;
254    local.protocol_data = NULL;
255    local.network_id = NULL;
256    local.auth_name = NULL;
257    local.auth_data = NULL;
258
259    if (!read_string (auth_file, &local.protocol_name))
260	return (NULL);
261
262    if (!read_counted_string (auth_file,
263	&local.protocol_data_length, &local.protocol_data))
264	goto bad;
265
266    if (!read_string (auth_file, &local.network_id))
267	goto bad;
268
269    if (!read_string (auth_file, &local.auth_name))
270	goto bad;
271
272    if (!read_counted_string (auth_file,
273	&local.auth_data_length, &local.auth_data))
274	goto bad;
275
276    if (!(ret = (IceAuthFileEntry *) malloc (sizeof (IceAuthFileEntry))))
277	goto bad;
278
279    *ret = local;
280
281    return (ret);
282
283 bad:
284
285    if (local.protocol_name) free (local.protocol_name);
286    if (local.protocol_data) free (local.protocol_data);
287    if (local.network_id) free (local.network_id);
288    if (local.auth_name) free (local.auth_name);
289    if (local.auth_data) free (local.auth_data);
290
291    return (NULL);
292}
293
294
295
296void
297IceFreeAuthFileEntry (
298	IceAuthFileEntry	*auth
299)
300{
301    if (auth)
302    {
303	if (auth->protocol_name) free (auth->protocol_name);
304	if (auth->protocol_data) free (auth->protocol_data);
305	if (auth->network_id) free (auth->network_id);
306	if (auth->auth_name) free (auth->auth_name);
307	if (auth->auth_data) free (auth->auth_data);
308	free ((char *) auth);
309    }
310}
311
312
313
314Status
315IceWriteAuthFileEntry (
316	FILE			*auth_file,
317	IceAuthFileEntry	*auth
318)
319{
320    if (!write_string (auth_file, auth->protocol_name))
321	return (0);
322
323    if (!write_counted_string (auth_file,
324	auth->protocol_data_length, auth->protocol_data))
325	return (0);
326
327    if (!write_string (auth_file, auth->network_id))
328	return (0);
329
330    if (!write_string (auth_file, auth->auth_name))
331	return (0);
332
333    if (!write_counted_string (auth_file,
334	auth->auth_data_length, auth->auth_data))
335	return (0);
336
337    return (1);
338}
339
340
341
342IceAuthFileEntry *
343IceGetAuthFileEntry (
344	char	*protocol_name,
345	char	*network_id,
346	char	*auth_name
347)
348{
349    FILE    		*auth_file;
350    char    		*filename;
351    IceAuthFileEntry    *entry;
352
353    if (!(filename = IceAuthFileName ()))
354	return (NULL);
355
356    if (access (filename, R_OK) != 0)		/* checks REAL id */
357	return (NULL);
358
359    if (!(auth_file = fopen (filename, "rb")))
360	return (NULL);
361
362    for (;;)
363    {
364	if (!(entry = IceReadAuthFileEntry (auth_file)))
365	    break;
366
367	if (strcmp (protocol_name, entry->protocol_name) == 0 &&
368	    strcmp (network_id, entry->network_id) == 0 &&
369            strcmp (auth_name, entry->auth_name) == 0)
370	{
371	    break;
372	}
373
374	IceFreeAuthFileEntry (entry);
375    }
376
377    fclose (auth_file);
378
379    return (entry);
380}
381
382
383
384/*
385 * local routines
386 */
387
388static Status
389read_short (FILE *file, unsigned short *shortp)
390{
391    unsigned char   file_short[2];
392
393    if (fread ((char *) file_short, (int) sizeof (file_short), 1, file) != 1)
394	return (0);
395
396    *shortp = file_short[0] * 256 + file_short[1];
397    return (1);
398}
399
400
401static Status
402read_string (FILE *file, char **stringp)
403
404{
405    unsigned short  len;
406    char	    *data;
407
408    if (!read_short (file, &len))
409	return (0);
410
411    data = malloc ((unsigned) len + 1);
412
413    if (!data)
414	    return (0);
415
416    if (len != 0)
417    {
418	if (fread (data, (int) sizeof (char), (int) len, file) != len)
419	{
420	    free (data);
421	    return (0);
422	}
423
424    }
425    data[len] = '\0';
426
427    *stringp = data;
428
429    return (1);
430}
431
432
433static Status
434read_counted_string (FILE *file, unsigned short	*countp, char **stringp)
435{
436    unsigned short  len;
437    char	    *data;
438
439    if (!read_short (file, &len))
440	return (0);
441
442    if (len == 0)
443    {
444	data = NULL;
445    }
446    else
447    {
448    	data = malloc ((unsigned) len);
449
450    	if (!data)
451	    return (0);
452
453    	if (fread (data, (int) sizeof (char), (int) len, file) != len)
454	{
455	    free (data);
456	    return (0);
457    	}
458    }
459
460    *stringp = data;
461    *countp = len;
462
463    return (1);
464}
465
466
467static Status
468write_short (FILE *file, unsigned short s)
469{
470    unsigned char   file_short[2];
471
472    file_short[0] = (s & (unsigned) 0xff00) >> 8;
473    file_short[1] = s & 0xff;
474
475    if (fwrite ((char *) file_short, (int) sizeof (file_short), 1, file) != 1)
476	return (0);
477
478    return (1);
479}
480
481
482static Status
483write_string (FILE *file, char *string)
484{
485    unsigned short count = strlen (string);
486
487    if (!write_short (file, count))
488	return (0);
489
490    if (fwrite (string, (int) sizeof (char), (int) count, file) != count)
491	return (0);
492
493    return (1);
494}
495
496
497static Status
498write_counted_string (FILE *file, unsigned short count, char *string)
499{
500    if (!write_short (file, count))
501	return (0);
502
503    if (fwrite (string, (int) sizeof (char), (int) count, file) != count)
504	return (0);
505
506    return (1);
507}
508