Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / lib / tt / lib / mp / mp_auth_functions.C
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $TOG: mp_auth_functions.C /main/3 1999/10/14 18:43:11 mgreess $ */
24 /******************************************************************************
25
26
27 Copyright 1993, 1998  The Open Group
28
29 All Rights Reserved.
30
31 The above copyright notice and this permission notice shall be included in
32 all copies or substantial portions of the Software.
33
34 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
35 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
36 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
37 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
38 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
39 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
40
41 Except as contained in this notice, the name of The Open Group shall not be
42 used in advertising or otherwise to promote the sale, use or other dealings
43 in this Software without prior written authorization from The Open Group.
44
45 Author: Ralph Mor, X Consortium
46 ******************************************************************************/
47 /*
48  * This file was copied and altered from libICE/authutil.c
49  * The 'Ice' prefix has been replaced by tt_ for functions
50  * and by _tt_ for data types.
51  */
52
53 #include <sys/stat.h>
54 #include <errno.h>
55 #include <stdlib.h>
56 #include <X11/Xos.h>
57 #include "mp/mp_auth_functions.h"
58
59 #ifdef X_NOT_STDC_ENV
60 extern int errno;
61 extern long time ();
62 extern char *getenv();
63 #define Time_t long
64 #else
65 #include <time.h>
66 #define Time_t time_t
67 #endif
68 #ifndef X_NOT_POSIX
69 #include <unistd.h>
70 #else
71 #ifndef WIN32
72 extern unsigned sleep ();
73 #else
74 #define link rename
75 #endif
76 #endif
77
78 static int read_short(FILE *, unsigned short *);
79 static int read_string(FILE *, char **);
80 static int read_counted_string(FILE *, unsigned short *, char **);
81 static int write_short(FILE *, unsigned short);
82 static int write_string(FILE *, char *);
83 static int write_counted_string(FILE *, unsigned short, char *);
84
85
86 \f
87 /*
88  * The following routines are for manipulating the .TTauthority file
89  */
90
91 char *
92 _tt_AuthFileName ()
93
94 {
95     static char slashDotTTauthority[] = "/.TTauthority";
96     char        *name;
97     static char *buf;
98     static int  bsize;
99     int         size;
100 #ifdef WIN32
101 #ifndef PATH_MAX
102 #define PATH_MAX 512
103 #endif
104     char        dir[PATH_MAX];
105 #endif
106
107     if (name = getenv ("TTAUTHORITY"))
108         return (name);
109
110     name = getenv ("HOME");
111
112     if (!name)
113     {
114 #ifdef WIN32
115     register char *ptr1;
116     register char *ptr2;
117     int len1 = 0, len2 = 0;
118
119     if ((ptr1 = getenv("HOMEDRIVE")) && (ptr2 = getenv("HOMEDIR"))) {
120         len1 = strlen (ptr1);
121         len2 = strlen (ptr2);
122     } else if (ptr2 = getenv("USERNAME")) {
123         len1 = strlen (ptr1 = "/users/");
124         len2 = strlen (ptr2);
125     }
126     if ((len1 + len2 + 1) < PATH_MAX) {
127         sprintf (dir, "%s%s", ptr1, (ptr2) ? ptr2 : "");
128         name = dir;
129     }
130     if (!name)
131 #endif
132         return (NULL);
133     }
134
135     size = strlen (name) + strlen (&slashDotTTauthority[1]) + 2;
136
137     if (size > bsize)
138     {
139         if (buf)
140             free (buf);
141         buf = (char*) malloc ((unsigned) size);
142         if (!buf)
143             return (NULL);
144         bsize = size;
145     }
146
147     strcpy (buf, name);
148     strcat (buf, slashDotTTauthority + (name[1] == '\0' ? 1 : 0));
149
150     return (buf);
151 }
152
153
154 \f
155 int
156 _tt_LockAuthFile(char *file_name, int retries, int timeout, long dead)
157 {
158     char        creat_name[1025], link_name[1025];
159     struct stat statb;
160     Time_t      now;
161     int         creat_fd = -1;
162
163     if ((int) strlen (file_name) > 1022)
164         return (_tt_AuthLockError);
165
166     strcpy (creat_name, file_name);
167     strcat (creat_name, "-c");
168     strcpy (link_name, file_name);
169     strcat (link_name, "-l");
170
171     if (stat (creat_name, &statb) != -1)
172     {
173         now = time ((Time_t *) 0);
174
175         /*
176          * NFS may cause ctime to be before now, special
177          * case a 0 deadtime to force lock removal
178          */
179
180         if (dead == 0 || now - statb.st_ctime > dead)
181         {
182             unlink (creat_name);
183             unlink (link_name);
184         }
185     }
186     
187     while (retries > 0)
188     {
189         if (creat_fd == -1)
190         {
191             creat_fd = creat (creat_name, 0666);
192
193             if (creat_fd == -1)
194             {
195                 if (errno != EACCES)
196                     return (_tt_AuthLockError);
197             }
198             else
199                 close (creat_fd);
200         }
201
202         if (creat_fd != -1)
203         {
204             if (link (creat_name, link_name) != -1)
205                 return (_tt_AuthLockSuccess);
206
207             if (errno == ENOENT)
208             {
209                 creat_fd = -1;  /* force re-creat next time around */
210                 continue;
211             }
212
213             if (errno != EEXIST)
214                 return (_tt_AuthLockError);
215         }
216
217         sleep ((unsigned) timeout);
218         --retries;
219     }
220
221     return (_tt_AuthLockTimeout);
222 }
223
224
225 \f
226 void
227 _tt_UnlockAuthFile(char *file_name)
228 {
229 #ifndef WIN32
230     char        creat_name[1025];
231 #endif
232     char        link_name[1025];
233
234     if ((int) strlen (file_name) > 1022)
235         return;
236
237 #ifndef WIN32
238     strcpy (creat_name, file_name);
239     strcat (creat_name, "-c");
240 #endif
241     strcpy (link_name, file_name);
242     strcat (link_name, "-l");
243
244 #ifndef WIN32
245     unlink (creat_name);
246 #endif
247     unlink (link_name);
248 }
249
250
251 \f
252 _tt_AuthFileEntry *
253 _tt_ReadAuthFileEntry(FILE *auth_file)
254 {
255     _tt_AuthFileEntry           local;
256     _tt_AuthFileEntry           *ret;
257
258     local.protocol_name = NULL;
259     local.protocol_data = NULL;
260     local.network_id = NULL;
261     local.auth_name = NULL;
262     local.auth_data = NULL;
263
264     if (!read_string (auth_file, &local.protocol_name))
265         return (NULL);
266
267     if (!read_counted_string (auth_file,
268         &local.protocol_data_length, &local.protocol_data))
269         goto bad;
270
271     if (!read_string (auth_file, &local.network_id))
272         goto bad;
273
274     if (!read_string (auth_file, &local.auth_name))
275         goto bad;
276
277     if (!read_counted_string (auth_file,
278         &local.auth_data_length, &local.auth_data))
279         goto bad;
280
281     if (!(ret = (_tt_AuthFileEntry *) malloc (sizeof (_tt_AuthFileEntry))))
282         goto bad;
283
284     *ret = local;
285
286     return (ret);
287
288  bad:
289
290     if (local.protocol_name) free (local.protocol_name);
291     if (local.protocol_data) free (local.protocol_data);
292     if (local.network_id) free (local.network_id);
293     if (local.auth_name) free (local.auth_name);
294     if (local.auth_data) free (local.auth_data);
295
296     return (NULL);
297 }
298
299
300 \f
301 void
302 _tt_FreeAuthFileEntry(_tt_AuthFileEntry *auth)
303 {
304     if (auth)
305     {
306         if (auth->protocol_name) free (auth->protocol_name);
307         if (auth->protocol_data) free (auth->protocol_data);
308         if (auth->network_id) free (auth->network_id);
309         if (auth->auth_name) free (auth->auth_name);
310         if (auth->auth_data) free (auth->auth_data);
311         free ((char *) auth);
312     }
313 }
314
315
316 \f
317 int
318 _tt_WriteAuthFileEntry(FILE *auth_file, _tt_AuthFileEntry *auth)
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 \f
342 _tt_AuthFileEntry *
343 _tt_GetAuthFileEntry(char *protocol_name, char *network_id, char *auth_name)
344 {
345     FILE                *auth_file;
346     char                *filename;
347     _tt_AuthFileEntry    *entry;
348
349     if (!(filename = _tt_AuthFileName ()))
350         return (NULL);
351
352     if (access (filename, R_OK) != 0)           /* checks REAL id */
353         return (NULL);
354
355     if (!(auth_file = fopen (filename, "rb")))
356         return (NULL);
357
358     for (;;)
359     {
360         if (!(entry = _tt_ReadAuthFileEntry (auth_file)))
361             break;
362
363         if (strcmp (protocol_name, entry->protocol_name) == 0 &&
364             strcmp (network_id, entry->network_id) == 0 &&
365             strcmp (auth_name, entry->auth_name) == 0)
366         {
367             break;
368         }
369
370         _tt_FreeAuthFileEntry (entry);
371     }
372
373     fclose (auth_file);
374
375     return (entry);
376 }
377
378
379 /*
380  * MIT-MAGIC-COOKIE-1 is a sample authentication method implemented by
381  * the SI.  It is not part of standard ICElib.
382  */
383
384 \f
385 char *
386 _tt_GenerateMagicCookie(int len)
387 {
388     char    *auth;
389     long    ldata[2];
390     int     seed;
391     int     value;
392     int     i;
393     
394     if ((auth = (char *) malloc (len + 1)) == NULL)
395         return (NULL);
396
397 #ifdef ITIMER_REAL
398     {
399         struct timeval  now;
400         X_GETTIMEOFDAY (&now);
401         ldata[0] = now.tv_sec;
402         ldata[1] = now.tv_usec;
403         seed = (int) ((ldata[0] << 11) ^ ldata[1]);
404     }
405 #else
406     {
407         long    time ();
408
409         ldata[0] = time ((long *) 0);
410         ldata[1] = getpid ();
411         seed = (int) (ldata[0]) + (ldata[1] << 16);
412     }
413 #endif
414     srand (seed);
415     for (i = 0; i < len; i++)
416     {
417         value = rand ();
418         auth[i] = (
419                   ( (value & 0xff000000) >> 24) ^
420                   ( (value & 0xff0000) >> 16) ^
421                   ( (value & 0xff00) >> 8)  ^
422                   ( (value & 0xff) )
423                   ) & 0xff;
424     }
425     auth[len] = '\0';
426
427     return (auth);
428 }
429
430 \f
431 /*
432  * local routines
433  */
434
435 static int
436 read_short(FILE *file, unsigned short *shortp)
437 {
438     unsigned char   file_short[2];
439
440     if (fread ((char *) file_short, (int) sizeof (file_short), 1, file) != 1)
441         return (0);
442
443     *shortp = file_short[0] * 256 + file_short[1];
444     return (1);
445 }
446
447
448 static int
449 read_string(FILE *file, char **stringp)
450 {
451     unsigned short  len;
452     char            *data;
453
454     if (!read_short (file, &len))
455         return (0);
456
457     if (len == 0)
458     {
459         data = 0;
460     }
461     else
462     {
463         data = (char*) malloc ((unsigned) len + 1);
464
465         if (!data)
466             return (0);
467
468         if (fread (data, (int) sizeof (char), (int) len, file) != len)
469         {
470             free (data);
471             return (0);
472         }
473
474         data[len] = '\0';
475     }
476
477     *stringp = data;
478
479     return (1);
480 }
481
482
483 static int
484 read_counted_string(FILE *file, unsigned short *countp, char **stringp)
485 {
486     unsigned short  len;
487     char            *data;
488
489     if (!read_short (file, &len))
490         return (0);
491
492     if (len == 0)
493     {
494         data = 0;
495     }
496     else
497     {
498         data = (char*) malloc ((unsigned) len);
499
500         if (!data)
501             return (0);
502
503         if (fread (data, (int) sizeof (char), (int) len, file) != len)
504         {
505             free (data);
506             return (0);
507         }
508     }
509
510     *stringp = data;
511     *countp = len;
512
513     return (1);
514 }
515
516
517 static int
518 write_short(FILE *file, unsigned short s)
519 {
520     unsigned char   file_short[2];
521
522     file_short[0] = (s & (unsigned) 0xff00) >> 8;
523     file_short[1] = s & 0xff;
524
525     if (fwrite ((char *) file_short, (int) sizeof (file_short), 1, file) != 1)
526         return (0);
527
528     return (1);
529 }
530
531
532 static int
533 write_string(FILE *file, char *string)
534 {
535     unsigned short count = strlen (string);
536
537     if (!write_short (file, count))
538         return (0);
539
540     if (fwrite (string, (int) sizeof (char), (int) count, file) != count)
541         return (0);
542
543     return (1);
544 }
545
546
547 static int
548 write_counted_string(FILE *file, unsigned short count, char *string)
549 {
550     if (!write_short (file, count))
551         return (0);
552
553     if (fwrite (string, (int) sizeof (char), (int) count, file) != count)
554         return (0);
555
556     return (1);
557 }