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