authutil.c revision 266e564d
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{
77    static char slashDotICEauthority[] = "/.ICEauthority";
78    char    	*name;
79    static char	*buf;
80    static int	bsize;
81    int	    	size;
82#if defined(WIN32) || defined(__UNIXOS2__)
83#ifndef PATH_MAX
84#define PATH_MAX 512
85#endif
86    char    	dir[PATH_MAX];
87#endif
88
89    if ((name = getenv ("ICEAUTHORITY")))
90	return (name);
91
92    name = getenv ("HOME");
93
94    if (!name)
95    {
96#ifdef WIN32
97    register char *ptr1;
98    register char *ptr2;
99    int len1 = 0, len2 = 0;
100
101    if ((ptr1 = getenv("HOMEDRIVE")) && (ptr2 = getenv("HOMEDIR"))) {
102	len1 = strlen (ptr1);
103	len2 = strlen (ptr2);
104    } else if (ptr2 = getenv("USERNAME")) {
105	len1 = strlen (ptr1 = "/users/");
106	len2 = strlen (ptr2);
107    }
108    if ((len1 + len2 + 1) < PATH_MAX) {
109	sprintf (dir, "%s%s", ptr1, (ptr2) ? ptr2 : "");
110	name = dir;
111    }
112    if (!name)
113#endif
114#ifdef __UNIXOS2__
115	strcpy (dir,"c:");
116	name = dir;
117	if (!name)
118#endif
119	return (NULL);
120    }
121
122    size = strlen (name) + strlen (&slashDotICEauthority[1]) + 2;
123
124    if (size > bsize)
125    {
126	if (buf)
127	    free (buf);
128	buf = malloc ((unsigned) size);
129	if (!buf)
130	    return (NULL);
131	bsize = size;
132    }
133
134    strcpy (buf, name);
135    strcat (buf, slashDotICEauthority + (name[1] == '\0' ? 1 : 0));
136
137    return (buf);
138}
139
140
141
142int
143IceLockAuthFile (file_name, retries, timeout, dead)
144
145char	*file_name;
146int	retries;
147int	timeout;
148long	dead;
149
150{
151    char	creat_name[1025], link_name[1025];
152    struct stat	statb;
153    Time_t	now;
154    int		creat_fd = -1;
155
156    if ((int) strlen (file_name) > 1022)
157	return (IceAuthLockError);
158
159    strcpy (creat_name, file_name);
160    strcat (creat_name, "-c");
161    strcpy (link_name, file_name);
162    strcat (link_name, "-l");
163
164    if (stat (creat_name, &statb) != -1)
165    {
166	now = time ((Time_t *) 0);
167
168	/*
169	 * NFS may cause ctime to be before now, special
170	 * case a 0 deadtime to force lock removal
171	 */
172
173	if (dead == 0 || now - statb.st_ctime > dead)
174	{
175	    unlink (creat_name);
176	    unlink (link_name);
177	}
178    }
179
180    while (retries > 0)
181    {
182	if (creat_fd == -1)
183	{
184	    creat_fd = creat (creat_name, 0666);
185
186	    if (creat_fd == -1)
187	    {
188		if (errno != EACCES)
189		    return (IceAuthLockError);
190	    }
191	    else
192		close (creat_fd);
193	}
194
195	if (creat_fd != -1)
196	{
197	    if (link (creat_name, link_name) != -1)
198		return (IceAuthLockSuccess);
199
200	    if (errno == ENOENT)
201	    {
202		creat_fd = -1;	/* force re-creat next time around */
203		continue;
204	    }
205
206	    if (errno != EEXIST)
207		return (IceAuthLockError);
208	}
209
210	sleep ((unsigned) timeout);
211	--retries;
212    }
213
214    return (IceAuthLockTimeout);
215}
216
217
218
219void
220IceUnlockAuthFile (file_name)
221
222char	*file_name;
223
224{
225#ifndef WIN32
226    char	creat_name[1025];
227#endif
228    char	link_name[1025];
229
230    if ((int) strlen (file_name) > 1022)
231	return;
232
233#ifndef WIN32
234    strcpy (creat_name, file_name);
235    strcat (creat_name, "-c");
236#endif
237    strcpy (link_name, file_name);
238    strcat (link_name, "-l");
239
240#ifndef WIN32
241    unlink (creat_name);
242#endif
243    unlink (link_name);
244}
245
246
247
248IceAuthFileEntry *
249IceReadAuthFileEntry (auth_file)
250
251FILE	*auth_file;
252
253{
254    IceAuthFileEntry   	local;
255    IceAuthFileEntry   	*ret;
256
257    local.protocol_name = NULL;
258    local.protocol_data = NULL;
259    local.network_id = NULL;
260    local.auth_name = NULL;
261    local.auth_data = NULL;
262
263    if (!read_string (auth_file, &local.protocol_name))
264	return (NULL);
265
266    if (!read_counted_string (auth_file,
267	&local.protocol_data_length, &local.protocol_data))
268	goto bad;
269
270    if (!read_string (auth_file, &local.network_id))
271	goto bad;
272
273    if (!read_string (auth_file, &local.auth_name))
274	goto bad;
275
276    if (!read_counted_string (auth_file,
277	&local.auth_data_length, &local.auth_data))
278	goto bad;
279
280    if (!(ret = (IceAuthFileEntry *) malloc (sizeof (IceAuthFileEntry))))
281	goto bad;
282
283    *ret = local;
284
285    return (ret);
286
287 bad:
288
289    if (local.protocol_name) free (local.protocol_name);
290    if (local.protocol_data) free (local.protocol_data);
291    if (local.network_id) free (local.network_id);
292    if (local.auth_name) free (local.auth_name);
293    if (local.auth_data) free (local.auth_data);
294
295    return (NULL);
296}
297
298
299
300void
301IceFreeAuthFileEntry (auth)
302
303IceAuthFileEntry	*auth;
304
305{
306    if (auth)
307    {
308	if (auth->protocol_name) free (auth->protocol_name);
309	if (auth->protocol_data) free (auth->protocol_data);
310	if (auth->network_id) free (auth->network_id);
311	if (auth->auth_name) free (auth->auth_name);
312	if (auth->auth_data) free (auth->auth_data);
313	free ((char *) auth);
314    }
315}
316
317
318
319Status
320IceWriteAuthFileEntry (auth_file, auth)
321
322FILE			*auth_file;
323IceAuthFileEntry	*auth;
324
325{
326    if (!write_string (auth_file, auth->protocol_name))
327	return (0);
328
329    if (!write_counted_string (auth_file,
330	auth->protocol_data_length, auth->protocol_data))
331	return (0);
332
333    if (!write_string (auth_file, auth->network_id))
334	return (0);
335
336    if (!write_string (auth_file, auth->auth_name))
337	return (0);
338
339    if (!write_counted_string (auth_file,
340	auth->auth_data_length, auth->auth_data))
341	return (0);
342
343    return (1);
344}
345
346
347
348IceAuthFileEntry *
349IceGetAuthFileEntry (protocol_name, network_id, auth_name)
350
351char	*protocol_name;
352char	*network_id;
353char	*auth_name;
354
355{
356    FILE    		*auth_file;
357    char    		*filename;
358    IceAuthFileEntry    *entry;
359
360    if (!(filename = IceAuthFileName ()))
361	return (NULL);
362
363    if (access (filename, R_OK) != 0)		/* checks REAL id */
364	return (NULL);
365
366    if (!(auth_file = fopen (filename, "rb")))
367	return (NULL);
368
369    for (;;)
370    {
371	if (!(entry = IceReadAuthFileEntry (auth_file)))
372	    break;
373
374	if (strcmp (protocol_name, entry->protocol_name) == 0 &&
375	    strcmp (network_id, entry->network_id) == 0 &&
376            strcmp (auth_name, entry->auth_name) == 0)
377	{
378	    break;
379	}
380
381	IceFreeAuthFileEntry (entry);
382    }
383
384    fclose (auth_file);
385
386    return (entry);
387}
388
389
390
391/*
392 * local routines
393 */
394
395static Status
396read_short (FILE *file, unsigned short *shortp)
397{
398    unsigned char   file_short[2];
399
400    if (fread ((char *) file_short, (int) sizeof (file_short), 1, file) != 1)
401	return (0);
402
403    *shortp = file_short[0] * 256 + file_short[1];
404    return (1);
405}
406
407
408static Status
409read_string (FILE *file, char **stringp)
410
411{
412    unsigned short  len;
413    char	    *data;
414
415    if (!read_short (file, &len))
416	return (0);
417
418    data = malloc ((unsigned) len + 1);
419
420    if (!data)
421	    return (0);
422
423    if (len != 0)
424    {
425	if (fread (data, (int) sizeof (char), (int) len, file) != len)
426	{
427	    free (data);
428	    return (0);
429	}
430
431    }
432    data[len] = '\0';
433
434    *stringp = data;
435
436    return (1);
437}
438
439
440static Status
441read_counted_string (FILE *file, unsigned short	*countp, char **stringp)
442{
443    unsigned short  len;
444    char	    *data;
445
446    if (!read_short (file, &len))
447	return (0);
448
449    if (len == 0)
450    {
451	data = 0;
452    }
453    else
454    {
455    	data = malloc ((unsigned) len);
456
457    	if (!data)
458	    return (0);
459
460    	if (fread (data, (int) sizeof (char), (int) len, file) != len)
461	{
462	    free (data);
463	    return (0);
464    	}
465    }
466
467    *stringp = data;
468    *countp = len;
469
470    return (1);
471}
472
473
474static Status
475write_short (FILE *file, unsigned short s)
476{
477    unsigned char   file_short[2];
478
479    file_short[0] = (s & (unsigned) 0xff00) >> 8;
480    file_short[1] = s & 0xff;
481
482    if (fwrite ((char *) file_short, (int) sizeof (file_short), 1, file) != 1)
483	return (0);
484
485    return (1);
486}
487
488
489static Status
490write_string (FILE *file, char *string)
491{
492    unsigned short count = strlen (string);
493
494    if (!write_short (file, count))
495	return (0);
496
497    if (fwrite (string, (int) sizeof (char), (int) count, file) != count)
498	return (0);
499
500    return (1);
501}
502
503
504static Status
505write_counted_string (FILE *file, unsigned short count, char *string)
506{
507    if (!write_short (file, count))
508	return (0);
509
510    if (fwrite (string, (int) sizeof (char), (int) count, file) != count)
511	return (0);
512
513    return (1);
514}
515