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