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