| File: | xdm/auth.c |
| Location: | line 501, column 23 |
| Description: | Call to 'malloc' has an allocation size of 0 bytes |
| 1 | /* | |||
| 2 | ||||
| 3 | Copyright 1988, 1998 The Open Group | |||
| 4 | ||||
| 5 | Permission to use, copy, modify, distribute, and sell this software and its | |||
| 6 | documentation for any purpose is hereby granted without fee, provided that | |||
| 7 | the above copyright notice appear in all copies and that both that | |||
| 8 | copyright notice and this permission notice appear in supporting | |||
| 9 | documentation. | |||
| 10 | ||||
| 11 | The above copyright notice and this permission notice shall be included | |||
| 12 | in all copies or substantial portions of the Software. | |||
| 13 | ||||
| 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |||
| 15 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |||
| 17 | IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR | |||
| 18 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |||
| 19 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |||
| 20 | OTHER DEALINGS IN THE SOFTWARE. | |||
| 21 | ||||
| 22 | Except as contained in this notice, the name of The Open Group shall | |||
| 23 | not be used in advertising or otherwise to promote the sale, use or | |||
| 24 | other dealings in this Software without prior written authorization | |||
| 25 | from The Open Group. | |||
| 26 | ||||
| 27 | */ | |||
| 28 | ||||
| 29 | /* | |||
| 30 | * xdm - display manager daemon | |||
| 31 | * Author: Keith Packard, MIT X Consortium | |||
| 32 | * | |||
| 33 | * auth.c | |||
| 34 | * | |||
| 35 | * maintain the authorization generation daemon | |||
| 36 | */ | |||
| 37 | ||||
| 38 | #include <X11/X.h> | |||
| 39 | #include <X11/Xlibint.h> | |||
| 40 | #include <sys/types.h> | |||
| 41 | #include <sys/stat.h> | |||
| 42 | ||||
| 43 | #include "dm.h" | |||
| 44 | #include "dm_auth.h" | |||
| 45 | #include "dm_error.h" | |||
| 46 | ||||
| 47 | #include <errno(*__error()).h> | |||
| 48 | ||||
| 49 | #include <sys/ioctl.h> | |||
| 50 | ||||
| 51 | #ifdef TCPCONN1 | |||
| 52 | # include "dm_socket.h" | |||
| 53 | #endif | |||
| 54 | ||||
| 55 | #if defined(hpux) | |||
| 56 | # include <sys/utsname.h> | |||
| 57 | #endif | |||
| 58 | ||||
| 59 | #if defined(SYSV) && defined(i386) | |||
| 60 | # include <sys/stream.h> | |||
| 61 | #endif /* i386 */ | |||
| 62 | ||||
| 63 | #ifdef SVR4 | |||
| 64 | # include <netdb.h> | |||
| 65 | # include <sys/sockio.h> | |||
| 66 | # include <sys/stropts.h> | |||
| 67 | #endif | |||
| 68 | #ifdef __convex__ | |||
| 69 | # include <sync/queue.h> | |||
| 70 | # include <sync/sema.h> | |||
| 71 | #endif | |||
| 72 | #ifdef __GNU__ | |||
| 73 | # include <netdb.h> | |||
| 74 | # undef SIOCGIFCONF(((__uint32_t)0x80000000|(__uint32_t)0x40000000) | ((sizeof(struct ifconf) & 0x1fff) << 16) | ((('i')) << 8) | ( (36))) | |||
| 75 | #else /* __GNU__ */ | |||
| 76 | # include <net/if.h> | |||
| 77 | #endif /* __GNU__ */ | |||
| 78 | ||||
| 79 | #if defined(TCPCONN1) && !defined(WIN32) | |||
| 80 | # include <netinet/in.h> | |||
| 81 | #endif | |||
| 82 | ||||
| 83 | /* Solaris provides an extended interface SIOCGLIFCONF for IPv6 support. | |||
| 84 | */ | |||
| 85 | #ifdef SIOCGLIFCONF | |||
| 86 | # define USE_SIOCGLIFCONF | |||
| 87 | #endif | |||
| 88 | ||||
| 89 | #if (defined(SVR4) && !defined(sun)) && \ | |||
| 90 | defined(SIOCGIFCONF(((__uint32_t)0x80000000|(__uint32_t)0x40000000) | ((sizeof(struct ifconf) & 0x1fff) << 16) | ((('i')) << 8) | ( (36)))) && !defined(USE_SIOCGLIFCONF) | |||
| 91 | # define SYSV_SIOCGIFCONF | |||
| 92 | #endif | |||
| 93 | ||||
| 94 | #ifdef HAVE_SYS_PARAM_H1 | |||
| 95 | # include <sys/param.h> | |||
| 96 | # ifdef BSD199506 | |||
| 97 | # if (BSD199506 >= 199103) | |||
| 98 | # define VARIABLE_IFREQ | |||
| 99 | # endif | |||
| 100 | # endif | |||
| 101 | #endif | |||
| 102 | ||||
| 103 | #ifdef __UNIXOS2__ | |||
| 104 | # define link rename | |||
| 105 | int chown(int a,int b,int c) {} | |||
| 106 | # include <io.h> | |||
| 107 | #endif | |||
| 108 | ||||
| 109 | struct AuthProtocol { | |||
| 110 | unsigned short name_length; | |||
| 111 | const char *name; | |||
| 112 | void (*InitAuth)(unsigned short len, char *name); | |||
| 113 | Xauth *(*GetAuth)(unsigned short len, char *name); | |||
| 114 | void (*GetXdmcpAuth)( | |||
| 115 | struct protoDisplay *pdpy, | |||
| 116 | unsigned short authorizationNameLen, | |||
| 117 | char *authorizationName); | |||
| 118 | int inited; | |||
| 119 | }; | |||
| 120 | ||||
| 121 | static struct AuthProtocol AuthProtocols[] = { | |||
| 122 | { (unsigned short) 18, "MIT-MAGIC-COOKIE-1", | |||
| 123 | MitInitAuth, MitGetAuth, NULL((void*)0) | |||
| 124 | }, | |||
| 125 | #ifdef HASXDMAUTH1 | |||
| 126 | { (unsigned short) 19, "XDM-AUTHORIZATION-1", | |||
| 127 | XdmInitAuth, XdmGetAuth, XdmGetXdmcpAuth, | |||
| 128 | }, | |||
| 129 | #endif | |||
| 130 | #ifdef SECURE_RPC | |||
| 131 | { (unsigned short) 9, "SUN-DES-1", | |||
| 132 | SecureRPCInitAuth, SecureRPCGetAuth, NULL((void*)0), | |||
| 133 | }, | |||
| 134 | #endif | |||
| 135 | #ifdef K5AUTH | |||
| 136 | { (unsigned short) 14, "MIT-KERBEROS-5", | |||
| 137 | Krb5InitAuth, Krb5GetAuth, NULL((void*)0), | |||
| 138 | }, | |||
| 139 | #endif | |||
| 140 | }; | |||
| 141 | ||||
| 142 | #define NUM_AUTHORIZATION(sizeof (AuthProtocols) / sizeof (AuthProtocols[0])) (sizeof (AuthProtocols) / sizeof (AuthProtocols[0])) | |||
| 143 | ||||
| 144 | static struct AuthProtocol * | |||
| 145 | findProtocol (unsigned short name_length, char *name) | |||
| 146 | { | |||
| 147 | int i; | |||
| 148 | ||||
| 149 | for (i = 0; i < NUM_AUTHORIZATION(sizeof (AuthProtocols) / sizeof (AuthProtocols[0])); i++) | |||
| 150 | if (AuthProtocols[i].name_length == name_length && | |||
| 151 | memcmp(AuthProtocols[i].name, name, name_length) == 0) | |||
| 152 | { | |||
| 153 | return &AuthProtocols[i]; | |||
| 154 | } | |||
| 155 | return (struct AuthProtocol *) 0; | |||
| 156 | } | |||
| 157 | ||||
| 158 | int | |||
| 159 | ValidAuthorization (unsigned short name_length, char *name) | |||
| 160 | { | |||
| 161 | if (findProtocol (name_length, name)) | |||
| 162 | return TRUE1; | |||
| 163 | return FALSE0; | |||
| 164 | } | |||
| 165 | ||||
| 166 | static Xauth * | |||
| 167 | GenerateAuthorization (unsigned short name_length, char *name) | |||
| 168 | { | |||
| 169 | struct AuthProtocol *a; | |||
| 170 | Xauth *auth = NULL((void*)0); | |||
| 171 | int i; | |||
| 172 | ||||
| 173 | Debug ("GenerateAuthorization %*.*s\n", | |||
| 174 | name_length, name_length, name); | |||
| 175 | a = findProtocol (name_length, name); | |||
| 176 | if (a) | |||
| 177 | { | |||
| 178 | if (!a->inited) | |||
| 179 | { | |||
| 180 | (*a->InitAuth) (name_length, name); | |||
| 181 | a->inited = TRUE1; | |||
| 182 | } | |||
| 183 | auth = (*a->GetAuth) (name_length, name); | |||
| 184 | if (auth) | |||
| 185 | { | |||
| 186 | Debug ("Got %p (%d %*.*s) ", auth, | |||
| 187 | auth->name_length, auth->name_length, | |||
| 188 | auth->name_length, auth->name); | |||
| 189 | for (i = 0; i < (int)auth->data_length; i++) | |||
| 190 | Debug (" %02x", auth->data[i] & 0xff); | |||
| 191 | Debug ("\n"); | |||
| 192 | } | |||
| 193 | else | |||
| 194 | Debug ("Got (null)\n"); | |||
| 195 | } | |||
| 196 | else | |||
| 197 | { | |||
| 198 | Debug ("Unknown authorization %*.*s\n", name_length, name_length, name); | |||
| 199 | } | |||
| 200 | return auth; | |||
| 201 | } | |||
| 202 | ||||
| 203 | #ifdef XDMCP | |||
| 204 | ||||
| 205 | void | |||
| 206 | SetProtoDisplayAuthorization ( | |||
| 207 | struct protoDisplay *pdpy, | |||
| 208 | unsigned short authorizationNameLen, | |||
| 209 | char *authorizationName) | |||
| 210 | { | |||
| 211 | struct AuthProtocol *a; | |||
| 212 | Xauth *auth; | |||
| 213 | ||||
| 214 | a = findProtocol (authorizationNameLen, authorizationName); | |||
| 215 | pdpy->xdmcpAuthorization = pdpy->fileAuthorization = NULL((void*)0); | |||
| 216 | if (a) | |||
| 217 | { | |||
| 218 | if (!a->inited) | |||
| 219 | { | |||
| 220 | (*a->InitAuth) (authorizationNameLen, authorizationName); | |||
| 221 | a->inited = TRUE1; | |||
| 222 | } | |||
| 223 | if (a->GetXdmcpAuth) | |||
| 224 | { | |||
| 225 | (*a->GetXdmcpAuth) (pdpy, authorizationNameLen, authorizationName); | |||
| 226 | auth = pdpy->xdmcpAuthorization; | |||
| 227 | } | |||
| 228 | else | |||
| 229 | { | |||
| 230 | auth = (*a->GetAuth) (authorizationNameLen, authorizationName); | |||
| 231 | pdpy->fileAuthorization = auth; | |||
| 232 | pdpy->xdmcpAuthorization = NULL((void*)0); | |||
| 233 | } | |||
| 234 | if (auth) | |||
| 235 | Debug ("Got %p (%d %*.*s)\n", auth, | |||
| 236 | auth->name_length, auth->name_length, | |||
| 237 | auth->name_length, auth->name); | |||
| 238 | else | |||
| 239 | Debug ("Got (null)\n"); | |||
| 240 | } | |||
| 241 | } | |||
| 242 | ||||
| 243 | #endif /* XDMCP */ | |||
| 244 | ||||
| 245 | void | |||
| 246 | CleanUpFileName (char *src, char *dst, int len) | |||
| 247 | { | |||
| 248 | while (*src) { | |||
| 249 | if (--len <= 0) | |||
| 250 | break; | |||
| 251 | switch (*src & 0x7f) | |||
| 252 | { | |||
| 253 | case '/': | |||
| 254 | *dst++ = '_'; | |||
| 255 | break; | |||
| 256 | case '-': | |||
| 257 | *dst++ = '.'; | |||
| 258 | break; | |||
| 259 | default: | |||
| 260 | *dst++ = (*src & 0x7f); | |||
| 261 | } | |||
| 262 | ++src; | |||
| 263 | } | |||
| 264 | *dst = '\0'; | |||
| 265 | } | |||
| 266 | ||||
| 267 | /* Checks to see if specified directory exists, makes it if not | |||
| 268 | * Returns: 0 if already exists, 1 if created, < 0 if error occured | |||
| 269 | */ | |||
| 270 | static int | |||
| 271 | CheckServerAuthDir (const char *path, struct stat *statb, int mode) | |||
| 272 | { | |||
| 273 | int r = stat(path, statb); | |||
| 274 | ||||
| 275 | if (r != 0) { | |||
| 276 | if (errno(*__error()) == ENOENT2) { | |||
| 277 | r = mkdir(path, mode); | |||
| 278 | if (r < 0) { | |||
| 279 | LogError ("cannot make authentication directory %s: %s\n", | |||
| 280 | path, _SysErrorMsg (errno(*__error()))); | |||
| 281 | } else { | |||
| 282 | r = 1; | |||
| 283 | } | |||
| 284 | } else { | |||
| 285 | LogError ("cannot access authentication directory %s: %s\n", | |||
| 286 | path, _SysErrorMsg (errno(*__error()))); | |||
| 287 | } | |||
| 288 | } else { /* Directory already exists */ | |||
| 289 | if (!S_ISDIR(statb->st_mode)(((statb->st_mode) & 0170000) == 0040000)) { | |||
| 290 | LogError ("cannot make authentication directory %s: %s\n", | |||
| 291 | path, "file with that name already exists"); | |||
| 292 | return -1; | |||
| 293 | } | |||
| 294 | } | |||
| 295 | ||||
| 296 | return r; | |||
| 297 | } | |||
| 298 | ||||
| 299 | static char authdir1[] = "authdir"; | |||
| 300 | static char authdir2[] = "authfiles"; | |||
| 301 | ||||
| 302 | static int | |||
| 303 | MakeServerAuthFile (struct display *d, FILE ** file) | |||
| 304 | { | |||
| 305 | int len; | |||
| 306 | #ifdef MAXNAMELEN | |||
| 307 | # define NAMELEN255 MAXNAMELEN | |||
| 308 | #else | |||
| 309 | # define NAMELEN255 255 | |||
| 310 | #endif | |||
| 311 | char cleanname[NAMELEN255]; | |||
| 312 | int r; | |||
| 313 | #ifdef HAVE_MKSTEMP1 | |||
| 314 | int fd; | |||
| 315 | #endif | |||
| 316 | struct stat statb; | |||
| 317 | ||||
| 318 | *file = NULL((void*)0); | |||
| 319 | ||||
| 320 | if (!d->authFile) { | |||
| 321 | if (d->clientAuthFile && *d->clientAuthFile) { | |||
| 322 | d->authFile = strdup(d->clientAuthFile); | |||
| 323 | if (!d->authFile) | |||
| 324 | return FALSE0; | |||
| 325 | } else { | |||
| 326 | CleanUpFileName (d->name, cleanname, NAMELEN255 - 8); | |||
| 327 | ||||
| 328 | /* Make authDir if it doesn't already exist */ | |||
| 329 | r = CheckServerAuthDir(authDir, &statb, 0755); | |||
| 330 | if (r < 0) { | |||
| 331 | return FALSE0; | |||
| 332 | } | |||
| 333 | ||||
| 334 | len = strlen (authDir) + strlen (authdir1) + strlen (authdir2) | |||
| 335 | + strlen (cleanname) + 14; | |||
| 336 | d->authFile = malloc (len); | |||
| 337 | if (!d->authFile) | |||
| 338 | return FALSE0; | |||
| 339 | ||||
| 340 | snprintf (d->authFile, len, "%s/%s", authDir, authdir1)__builtin___snprintf_chk (d->authFile, len, 0, __builtin_object_size (d->authFile, 2 > 1 ? 1 : 0), "%s/%s", authDir, authdir1 ); | |||
| 341 | r = CheckServerAuthDir(d->authFile, &statb, 0700); | |||
| 342 | if (r == 0) { | |||
| 343 | if (statb.st_uid != 0) | |||
| 344 | (void) chown(d->authFile, 0, statb.st_gid); | |||
| 345 | if ((statb.st_mode & 0077) != 0) | |||
| 346 | (void) chmod(d->authFile, statb.st_mode & 0700); | |||
| 347 | } else if (r < 0) { | |||
| 348 | free (d->authFile); | |||
| 349 | d->authFile = NULL((void*)0); | |||
| 350 | return FALSE0; | |||
| 351 | } | |||
| 352 | ||||
| 353 | snprintf (d->authFile, len, "%s/%s/%s",__builtin___snprintf_chk (d->authFile, len, 0, __builtin_object_size (d->authFile, 2 > 1 ? 1 : 0), "%s/%s/%s", authDir, authdir1 , authdir2) | |||
| 354 | authDir, authdir1, authdir2)__builtin___snprintf_chk (d->authFile, len, 0, __builtin_object_size (d->authFile, 2 > 1 ? 1 : 0), "%s/%s/%s", authDir, authdir1 , authdir2); | |||
| 355 | r = CheckServerAuthDir(d->authFile, &statb, 0700); | |||
| 356 | if (r < 0) { | |||
| 357 | free (d->authFile); | |||
| 358 | d->authFile = NULL((void*)0); | |||
| 359 | return FALSE0; | |||
| 360 | } | |||
| 361 | snprintf (d->authFile, len, "%s/%s/%s/A%s-XXXXXX",__builtin___snprintf_chk (d->authFile, len, 0, __builtin_object_size (d->authFile, 2 > 1 ? 1 : 0), "%s/%s/%s/A%s-XXXXXX", authDir , authdir1, authdir2, cleanname) | |||
| 362 | authDir, authdir1, authdir2, cleanname)__builtin___snprintf_chk (d->authFile, len, 0, __builtin_object_size (d->authFile, 2 > 1 ? 1 : 0), "%s/%s/%s/A%s-XXXXXX", authDir , authdir1, authdir2, cleanname); | |||
| 363 | #ifdef HAVE_MKSTEMP1 | |||
| 364 | fd = mkstemp (d->authFile); | |||
| 365 | if (fd < 0) { | |||
| 366 | LogError ("cannot make authentication file %s: %s\n", | |||
| 367 | d->authFile, _SysErrorMsg (errno(*__error()))); | |||
| 368 | free (d->authFile); | |||
| 369 | d->authFile = NULL((void*)0); | |||
| 370 | return FALSE0; | |||
| 371 | } | |||
| 372 | ||||
| 373 | *file = fdopen(fd, "w"); | |||
| 374 | if (!*file) | |||
| 375 | (void) close (fd); | |||
| 376 | return TRUE1; | |||
| 377 | #else | |||
| 378 | (void) mktemp (d->authFile); | |||
| 379 | #endif | |||
| 380 | } | |||
| 381 | } | |||
| 382 | ||||
| 383 | (void) unlink (d->authFile); | |||
| 384 | *file = fopen (d->authFile, "w"); | |||
| 385 | return TRUE1; | |||
| 386 | } | |||
| 387 | ||||
| 388 | int | |||
| 389 | SaveServerAuthorizations ( | |||
| 390 | struct display *d, | |||
| 391 | Xauth **auths, | |||
| 392 | int count) | |||
| 393 | { | |||
| 394 | FILE *auth_file; | |||
| 395 | mode_t mask; | |||
| 396 | int ret; | |||
| 397 | int i; | |||
| 398 | const char dummy_auth[] = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" | |||
| 399 | "XXXXXXXXXXXXXXXXX"; /* 64 "X"s */ | |||
| 400 | int err = 0; | |||
| 401 | ||||
| 402 | mask = umask (0077); | |||
| 403 | ret = MakeServerAuthFile(d, &auth_file); | |||
| 404 | umask (mask); | |||
| 405 | if (!ret) | |||
| 406 | return FALSE0; | |||
| 407 | if (!auth_file) { | |||
| 408 | LogError ("cannot open server authorization file %s: %s\n", | |||
| 409 | d->authFile, _SysErrorMsg (errno(*__error()))); | |||
| 410 | ret = FALSE0; | |||
| 411 | } | |||
| 412 | else | |||
| 413 | { | |||
| 414 | Debug ("File: %s auth: %p\n", d->authFile, auths); | |||
| 415 | ret = TRUE1; | |||
| 416 | if (count == 0) | |||
| 417 | { | |||
| 418 | /* | |||
| 419 | * This is a crude hack to determine whether we really can | |||
| 420 | * write to the auth file even if we don't have real data | |||
| 421 | * to write right now. | |||
| 422 | */ | |||
| 423 | ||||
| 424 | /* | |||
| 425 | * Write garbage data to file to provoke ENOSPC and other | |||
| 426 | * errors. | |||
| 427 | */ | |||
| 428 | (void) fprintf (auth_file, "%s", dummy_auth); | |||
| 429 | (void) fflush (auth_file); | |||
| 430 | if (ferror (auth_file)) | |||
| 431 | { | |||
| 432 | err = errno(*__error()); | |||
| 433 | ret = FALSE0; | |||
| 434 | } | |||
| 435 | /* | |||
| 436 | * Rewind so that the garbage data is overwritten later. | |||
| 437 | */ | |||
| 438 | rewind(auth_file); | |||
| 439 | } | |||
| 440 | for (i = 0; i < count; i++) | |||
| 441 | { | |||
| 442 | /* | |||
| 443 | * User-based auths may not have data until | |||
| 444 | * a user logs in. In which case don't write | |||
| 445 | * to the auth file so xrdb and setup programs don't fail. | |||
| 446 | */ | |||
| 447 | if (auths[i]->data_length > 0) | |||
| 448 | if (!XauWriteAuth (auth_file, auths[i])) | |||
| 449 | { | |||
| 450 | Debug ("XauWriteAuth() failed\n"); | |||
| 451 | } | |||
| 452 | (void) fflush (auth_file); | |||
| 453 | if (ferror (auth_file)) | |||
| 454 | { | |||
| 455 | err = errno(*__error()); | |||
| 456 | ret = FALSE0; | |||
| 457 | } | |||
| 458 | } | |||
| 459 | /* | |||
| 460 | * XXX: This is not elegant, but stdio has no truncation function. | |||
| 461 | */ | |||
| 462 | if (ftruncate(fileno(auth_file), ftell(auth_file))) | |||
| 463 | { | |||
| 464 | Debug ("ftruncate() failed\n"); | |||
| 465 | } | |||
| 466 | fclose (auth_file); | |||
| 467 | ||||
| 468 | } | |||
| 469 | if (ret == FALSE0) | |||
| 470 | { | |||
| 471 | LogError ("Cannot write to server authorization file %s%s%s\n", | |||
| 472 | d->authFile, | |||
| 473 | err ? ": " : "", | |||
| 474 | err ? _SysErrorMsg (errno(*__error())) : ""); | |||
| 475 | free (d->authFile); | |||
| 476 | d->authFile = NULL((void*)0); | |||
| 477 | } | |||
| 478 | return ret; | |||
| 479 | } | |||
| 480 | ||||
| 481 | void | |||
| 482 | SetLocalAuthorization (struct display *d) | |||
| 483 | { | |||
| 484 | Xauth *auth, **auths; | |||
| 485 | int i, j; | |||
| 486 | ||||
| 487 | if (d->authorizations) | |||
| ||||
| 488 | { | |||
| 489 | for (i = 0; i < d->authNum; i++) | |||
| 490 | XauDisposeAuth (d->authorizations[i]); | |||
| 491 | free (d->authorizations); | |||
| 492 | d->authorizations = (Xauth **) NULL((void*)0); | |||
| 493 | d->authNum = 0; | |||
| 494 | } | |||
| 495 | if (!d->authNames) | |||
| 496 | return; | |||
| 497 | for (i = 0; d->authNames[i]; i++) | |||
| 498 | ; | |||
| 499 | d->authNameNum = i; | |||
| 500 | free (d->authNameLens); | |||
| 501 | d->authNameLens = malloc (d->authNameNum * sizeof (unsigned short)); | |||
| ||||
| 502 | if (!d->authNameLens) | |||
| 503 | return; | |||
| 504 | for (i = 0; i < d->authNameNum; i++) | |||
| 505 | d->authNameLens[i] = strlen (d->authNames[i]); | |||
| 506 | auths = malloc (d->authNameNum * sizeof (Xauth *)); | |||
| 507 | if (!auths) | |||
| 508 | return; | |||
| 509 | j = 0; | |||
| 510 | for (i = 0; i < d->authNameNum; i++) | |||
| 511 | { | |||
| 512 | auth = GenerateAuthorization (d->authNameLens[i], d->authNames[i]); | |||
| 513 | if (auth) | |||
| 514 | auths[j++] = auth; | |||
| 515 | } | |||
| 516 | if (SaveServerAuthorizations (d, auths, j)) | |||
| 517 | { | |||
| 518 | d->authorizations = auths; | |||
| 519 | d->authNum = j; | |||
| 520 | } | |||
| 521 | else | |||
| 522 | { | |||
| 523 | for (i = 0; i < j; i++) | |||
| 524 | XauDisposeAuth (auths[i]); | |||
| 525 | free (auths); | |||
| 526 | } | |||
| 527 | } | |||
| 528 | ||||
| 529 | /* | |||
| 530 | * Set the authorization to use for xdm's initial connection | |||
| 531 | * to the X server. Cannot use user-based authorizations | |||
| 532 | * because no one has logged in yet, so we don't have any | |||
| 533 | * user credentials. | |||
| 534 | * Well, actually we could use SUN-DES-1 because we tell the server | |||
| 535 | * to allow root in. This is bogus and should be fixed. | |||
| 536 | */ | |||
| 537 | void | |||
| 538 | SetAuthorization (struct display *d) | |||
| 539 | { | |||
| 540 | register Xauth **auth = d->authorizations; | |||
| 541 | int i; | |||
| 542 | ||||
| 543 | for (i = 0; i < d->authNum; i++) | |||
| 544 | { | |||
| 545 | if (auth[i]->name_length == 9 && | |||
| 546 | memcmp(auth[i]->name, "SUN-DES-1", 9) == 0) | |||
| 547 | continue; | |||
| 548 | if (auth[i]->name_length == 14 && | |||
| 549 | memcmp(auth[i]->name, "MIT-KERBEROS-5", 14) == 0) | |||
| 550 | continue; | |||
| 551 | XSetAuthorization (auth[i]->name, (int) auth[i]->name_length, | |||
| 552 | auth[i]->data, (int) auth[i]->data_length); | |||
| 553 | } | |||
| 554 | } | |||
| 555 | ||||
| 556 | static int | |||
| 557 | openFiles (char *name, char *new_name, FILE **oldp, FILE **newp) | |||
| 558 | { | |||
| 559 | mode_t mask; | |||
| 560 | int newfd; | |||
| 561 | ||||
| 562 | strcpy (new_name, name)__builtin___strcpy_chk (new_name, name, __builtin_object_size (new_name, 2 > 1 ? 1 : 0)); | |||
| 563 | strcat (new_name, "-n")__builtin___strcat_chk (new_name, "-n", __builtin_object_size (new_name, 2 > 1 ? 1 : 0)); | |||
| 564 | /* | |||
| 565 | * Set safe umask for file creation operations. | |||
| 566 | */ | |||
| 567 | mask = umask (0077); | |||
| 568 | /* | |||
| 569 | * Unlink the authorization file we intend to create, and then open | |||
| 570 | * it with O_CREAT | O_EXCL to avoid race-based symlink attacks. | |||
| 571 | */ | |||
| 572 | (void) unlink (new_name); | |||
| 573 | newfd = open (new_name, O_WRONLY0x0001 | O_CREAT0x0200 | O_EXCL0x0800, 0600); | |||
| 574 | if (newfd >= 0) { | |||
| 575 | *newp = fdopen (newfd, "w"); | |||
| 576 | if (*newp == NULL((void*)0)) | |||
| 577 | close(newfd); | |||
| 578 | } | |||
| 579 | else | |||
| 580 | { | |||
| 581 | LogError ("Cannot create file %s: %s\n", new_name, | |||
| 582 | _SysErrorMsg (errno(*__error()))); | |||
| 583 | *newp = NULL((void*)0); | |||
| 584 | } | |||
| 585 | /* | |||
| 586 | * There are no more attempts to create files after this point; | |||
| 587 | * restore the original umask. | |||
| 588 | */ | |||
| 589 | (void) umask (mask); | |||
| 590 | if (!*newp) { | |||
| 591 | Debug ("can't open new file %s\n", new_name); | |||
| 592 | return 0; | |||
| 593 | } | |||
| 594 | if (!*oldp) | |||
| 595 | *oldp = fopen (name, "r"); | |||
| 596 | Debug ("opens succeeded %s %s\n", name, new_name); | |||
| 597 | return 1; | |||
| 598 | } | |||
| 599 | ||||
| 600 | static int | |||
| 601 | binaryEqual (char *a, char *b, unsigned short len) | |||
| 602 | { | |||
| 603 | while (len-- > 0) | |||
| 604 | if (*a++ != *b++) | |||
| 605 | return FALSE0; | |||
| 606 | return TRUE1; | |||
| 607 | } | |||
| 608 | ||||
| 609 | static void | |||
| 610 | dumpBytes (unsigned short len, char *data) | |||
| 611 | { | |||
| 612 | unsigned short i; | |||
| 613 | ||||
| 614 | Debug ("%d: ", len); | |||
| 615 | for (i = 0; i < len; i++) | |||
| 616 | Debug ("%02x ", data[i] & 0377); | |||
| 617 | Debug ("\n"); | |||
| 618 | } | |||
| 619 | ||||
| 620 | static void | |||
| 621 | dumpAuth (Xauth *auth) | |||
| 622 | { | |||
| 623 | Debug ("family: %d\n", auth->family); | |||
| 624 | Debug ("addr: "); | |||
| 625 | dumpBytes (auth->address_length, auth->address); | |||
| 626 | Debug ("number: "); | |||
| 627 | dumpBytes (auth->number_length, auth->number); | |||
| 628 | Debug ("name: "); | |||
| 629 | dumpBytes (auth->name_length, auth->name); | |||
| 630 | Debug ("data: "); | |||
| 631 | dumpBytes (auth->data_length, auth->data); | |||
| 632 | } | |||
| 633 | ||||
| 634 | struct addrList { | |||
| 635 | unsigned short family; | |||
| 636 | unsigned short address_length; | |||
| 637 | char *address; | |||
| 638 | unsigned short number_length; | |||
| 639 | char *number; | |||
| 640 | unsigned short name_length; | |||
| 641 | char *name; | |||
| 642 | struct addrList *next; | |||
| 643 | }; | |||
| 644 | ||||
| 645 | static struct addrList *addrs; | |||
| 646 | ||||
| 647 | static void | |||
| 648 | initAddrs (void) | |||
| 649 | { | |||
| 650 | addrs = NULL((void*)0); | |||
| 651 | } | |||
| 652 | ||||
| 653 | static void | |||
| 654 | doneAddrs (void) | |||
| 655 | { | |||
| 656 | struct addrList *a, *n; | |||
| 657 | for (a = addrs; a; a = n) { | |||
| 658 | n = a->next; | |||
| 659 | free (a->address); | |||
| 660 | free (a->number); | |||
| 661 | free (a); | |||
| 662 | } | |||
| 663 | } | |||
| 664 | ||||
| 665 | static int checkEntry (Xauth *auth); | |||
| 666 | ||||
| 667 | static void | |||
| 668 | saveEntry (Xauth *auth) | |||
| 669 | { | |||
| 670 | struct addrList *new; | |||
| 671 | ||||
| 672 | new = malloc (sizeof (struct addrList)); | |||
| 673 | if (!new) { | |||
| 674 | LogOutOfMem ("saveEntry"); | |||
| 675 | return; | |||
| 676 | } | |||
| 677 | if ((new->address_length = auth->address_length) > 0) { | |||
| 678 | new->address = malloc (auth->address_length); | |||
| 679 | if (!new->address) { | |||
| 680 | LogOutOfMem ("saveEntry"); | |||
| 681 | free (new); | |||
| 682 | return; | |||
| 683 | } | |||
| 684 | memmove( new->address, auth->address, (int) auth->address_length)__builtin___memmove_chk (new->address, auth->address, ( int) auth->address_length, __builtin_object_size (new-> address, 0)); | |||
| 685 | } else | |||
| 686 | new->address = NULL((void*)0); | |||
| 687 | if ((new->number_length = auth->number_length) > 0) { | |||
| 688 | new->number = malloc (auth->number_length); | |||
| 689 | if (!new->number) { | |||
| 690 | LogOutOfMem ("saveEntry"); | |||
| 691 | free (new->address); | |||
| 692 | free (new); | |||
| 693 | return; | |||
| 694 | } | |||
| 695 | memmove( new->number, auth->number, (int) auth->number_length)__builtin___memmove_chk (new->number, auth->number, (int ) auth->number_length, __builtin_object_size (new->number , 0)); | |||
| 696 | } else | |||
| 697 | new->number = NULL((void*)0); | |||
| 698 | if ((new->name_length = auth->name_length) > 0) { | |||
| 699 | new->name = malloc (auth->name_length); | |||
| 700 | if (!new->name) { | |||
| 701 | LogOutOfMem ("saveEntry"); | |||
| 702 | free (new->number); | |||
| 703 | free (new->address); | |||
| 704 | free (new); | |||
| 705 | return; | |||
| 706 | } | |||
| 707 | memmove( new->name, auth->name, (int) auth->name_length)__builtin___memmove_chk (new->name, auth->name, (int) auth ->name_length, __builtin_object_size (new->name, 0)); | |||
| 708 | } else | |||
| 709 | new->name = NULL((void*)0); | |||
| 710 | new->family = auth->family; | |||
| 711 | new->next = addrs; | |||
| 712 | addrs = new; | |||
| 713 | } | |||
| 714 | ||||
| 715 | static int | |||
| 716 | checkEntry (Xauth *auth) | |||
| 717 | { | |||
| 718 | struct addrList *a; | |||
| 719 | ||||
| 720 | for (a = addrs; a; a = a->next) { | |||
| 721 | if (a->family == auth->family && | |||
| 722 | a->address_length == auth->address_length && | |||
| 723 | binaryEqual (a->address, auth->address, auth->address_length) && | |||
| 724 | a->number_length == auth->number_length && | |||
| 725 | binaryEqual (a->number, auth->number, auth->number_length) && | |||
| 726 | a->name_length == auth->name_length && | |||
| 727 | binaryEqual (a->name, auth->name, auth->name_length)) | |||
| 728 | { | |||
| 729 | return 1; | |||
| 730 | } | |||
| 731 | } | |||
| 732 | return 0; | |||
| 733 | } | |||
| 734 | ||||
| 735 | static int doWrite; | |||
| 736 | ||||
| 737 | static void | |||
| 738 | writeAuth (FILE *file, Xauth *auth) | |||
| 739 | { | |||
| 740 | if (debugLevel >= 15) { /* normally too verbose */ | |||
| 741 | Debug ("writeAuth: doWrite = %d\n", doWrite); | |||
| 742 | dumpAuth (auth); /* does Debug only */ | |||
| 743 | } | |||
| 744 | if (doWrite) | |||
| 745 | XauWriteAuth (file, auth); | |||
| 746 | } | |||
| 747 | ||||
| 748 | static void | |||
| 749 | writeAddr ( | |||
| 750 | int family, | |||
| 751 | int addr_length, | |||
| 752 | char *addr, | |||
| 753 | FILE *file, | |||
| 754 | Xauth *auth) | |||
| 755 | { | |||
| 756 | auth->family = (unsigned short) family; | |||
| 757 | auth->address_length = addr_length; | |||
| 758 | auth->address = addr; | |||
| 759 | Debug ("writeAddr: writing and saving an entry\n"); | |||
| 760 | writeAuth (file, auth); | |||
| 761 | saveEntry (auth); | |||
| 762 | } | |||
| 763 | ||||
| 764 | static void | |||
| 765 | DefineLocal (FILE *file, Xauth *auth) | |||
| 766 | { | |||
| 767 | char displayname[100]; | |||
| 768 | int len = _XGetHostname (displayname, sizeof(displayname)); | |||
| 769 | ||||
| 770 | /* Make sure this produces the same string as _XGetHostname in lib/X/XlibInt.c. | |||
| 771 | * Otherwise, Xau will not be able to find your cookies in the Xauthority file. | |||
| 772 | * | |||
| 773 | * Note: POSIX says that the ``nodename'' member of utsname does _not_ have | |||
| 774 | * to have sufficient information for interfacing to the network, | |||
| 775 | * and so, you may be better off using gethostname (if it exists). | |||
| 776 | */ | |||
| 777 | ||||
| 778 | #if defined(hpux) | |||
| 779 | /* | |||
| 780 | * For HP-UX, HP's Xlib expects a fully-qualified domain name, which | |||
| 781 | * is achieved by using gethostname(). For compatability, we must | |||
| 782 | * also still create the entry using uname(). | |||
| 783 | */ | |||
| 784 | char tmp_displayname[100]; | |||
| 785 | struct utsname name; | |||
| 786 | ||||
| 787 | tmp_displayname[0] = 0; | |||
| 788 | uname(&name); | |||
| 789 | snprintf(tmp_displayname, sizeof(tmp_displayname), "%s", name.nodename)__builtin___snprintf_chk (tmp_displayname, sizeof(tmp_displayname ), 0, __builtin_object_size (tmp_displayname, 2 > 1 ? 1 : 0 ), "%s", name.nodename); | |||
| 790 | writeAddr (FamilyLocal(256), strlen (tmp_displayname), tmp_displayname, | |||
| 791 | file, auth); | |||
| 792 | ||||
| 793 | /* | |||
| 794 | * If _XGetHostname() returned the same value as uname(), don't | |||
| 795 | * write a duplicate entry. | |||
| 796 | */ | |||
| 797 | if (strcmp (displayname, tmp_displayname)) | |||
| 798 | #endif | |||
| 799 | ||||
| 800 | writeAddr (FamilyLocal(256), len, displayname, file, auth); | |||
| 801 | } | |||
| 802 | ||||
| 803 | #ifdef HAVE_GETIFADDRS1 | |||
| 804 | # include <ifaddrs.h> | |||
| 805 | ||||
| 806 | static void | |||
| 807 | DefineSelf(int fd, FILE *file, Xauth *auth) | |||
| 808 | { | |||
| 809 | struct ifaddrs *ifap, *ifr; | |||
| 810 | char *addr; | |||
| 811 | int family, len; | |||
| 812 | ||||
| 813 | Debug("DefineSelf\n"); | |||
| 814 | if (getifaddrs(&ifap) < 0) | |||
| 815 | return; | |||
| 816 | for (ifr = ifap; ifr != NULL((void*)0); ifr = ifr->ifa_next) { | |||
| 817 | len = sizeof(*(ifr->ifa_addr)); | |||
| 818 | family = ConvertAddr((XdmcpNetaddr)(ifr->ifa_addr), &len, &addr); | |||
| 819 | if (family == -1 || family == FamilyLocal(256)) | |||
| 820 | continue; | |||
| 821 | /* | |||
| 822 | * don't write out 'localhost' entries, as | |||
| 823 | * they may conflict with other local entries. | |||
| 824 | * DefineLocal will always be called to add | |||
| 825 | * the local entry anyway, so this one can | |||
| 826 | * be tossed. | |||
| 827 | */ | |||
| 828 | if (family == FamilyInternet0 && len == 4 && addr[0] == 127) | |||
| 829 | { | |||
| 830 | Debug ("Skipping localhost address\n"); | |||
| 831 | continue; | |||
| 832 | } | |||
| 833 | # if defined(IPv61) && defined(AF_INET630) | |||
| 834 | if(family == FamilyInternet66) { | |||
| 835 | if (IN6_IS_ADDR_LOOPBACK(((struct in6_addr *)addr))((*(const __uint32_t *)(const void *)(&(((struct in6_addr *)addr))->__u6_addr.__u6_addr8[0]) == 0) && (*(const __uint32_t *)(const void *)(&(((struct in6_addr *)addr)) ->__u6_addr.__u6_addr8[4]) == 0) && (*(const __uint32_t *)(const void *)(&(((struct in6_addr *)addr))->__u6_addr .__u6_addr8[8]) == 0) && (*(const __uint32_t *)(const void *)(&(((struct in6_addr *)addr))->__u6_addr.__u6_addr8 [12]) == (__builtin_constant_p(1) ? ((__uint32_t)((((__uint32_t )(1) & 0xff000000) >> 24) | (((__uint32_t)(1) & 0x00ff0000) >> 8) | (((__uint32_t)(1) & 0x0000ff00 ) << 8) | (((__uint32_t)(1) & 0x000000ff) << 24 ))) : _OSSwapInt32(1))))) { | |||
| 836 | Debug ("Skipping IPv6 localhost address\n"); | |||
| 837 | continue; | |||
| 838 | } | |||
| 839 | /* Also skip XDM-AUTHORIZATION-1 */ | |||
| 840 | if (auth->name_length == 19 && | |||
| 841 | strcmp(auth->name, "XDM-AUTHORIZATION-1") == 0) { | |||
| 842 | Debug ("Skipping IPv6 XDM-AUTHORIZATION-1\n"); | |||
| 843 | continue; | |||
| 844 | } | |||
| 845 | } | |||
| 846 | # endif | |||
| 847 | writeAddr(family, len, addr, file, auth); | |||
| 848 | } | |||
| 849 | freeifaddrs(ifap); | |||
| 850 | Debug("DefineSelf done\n"); | |||
| 851 | } | |||
| 852 | #else /* GETIFADDRS */ | |||
| 853 | ||||
| 854 | # ifdef SYSV_SIOCGIFCONF | |||
| 855 | ||||
| 856 | /* Deal with different SIOCGIFCONF ioctl semantics on SYSV, SVR4 */ | |||
| 857 | ||||
| 858 | static int | |||
| 859 | ifioctl (int fd, int cmd, char *arg) | |||
| 860 | { | |||
| 861 | struct strioctl ioc; | |||
| 862 | int ret; | |||
| 863 | ||||
| 864 | bzero((char *) &ioc, sizeof(ioc))__builtin___memset_chk ((char *) &ioc, 0, sizeof(ioc), __builtin_object_size ((char *) &ioc, 0)); | |||
| 865 | ioc.ic_cmd = cmd; | |||
| 866 | ioc.ic_timout = 0; | |||
| 867 | if (cmd == SIOCGIFCONF(((__uint32_t)0x80000000|(__uint32_t)0x40000000) | ((sizeof(struct ifconf) & 0x1fff) << 16) | ((('i')) << 8) | ( (36)))) | |||
| 868 | { | |||
| 869 | ioc.ic_len = ((struct ifconf *) arg)->ifc_len; | |||
| 870 | ioc.ic_dp = ((struct ifconf *) arg)->ifc_bufifc_ifcu.ifcu_buf; | |||
| 871 | } | |||
| 872 | else | |||
| 873 | { | |||
| 874 | ioc.ic_len = sizeof(struct ifreq); | |||
| 875 | ioc.ic_dp = arg; | |||
| 876 | } | |||
| 877 | ret = ioctl(fd, I_STR, (char *) &ioc); | |||
| 878 | if (ret >= 0 && cmd == SIOCGIFCONF(((__uint32_t)0x80000000|(__uint32_t)0x40000000) | ((sizeof(struct ifconf) & 0x1fff) << 16) | ((('i')) << 8) | ( (36)))) | |||
| 879 | ((struct ifconf *) arg)->ifc_len = ioc.ic_len; | |||
| 880 | return(ret); | |||
| 881 | } | |||
| 882 | # else /* SYSV_SIOCGIFCONF */ | |||
| 883 | # define ifioctl ioctl | |||
| 884 | # endif /* SYSV_SIOCGIFCONF */ | |||
| 885 | ||||
| 886 | ||||
| 887 | ||||
| 888 | # if defined(SIOCGIFCONF(((__uint32_t)0x80000000|(__uint32_t)0x40000000) | ((sizeof(struct ifconf) & 0x1fff) << 16) | ((('i')) << 8) | ( (36)))) || defined (USE_SIOCGLIFCONF) | |||
| 889 | ||||
| 890 | # ifdef USE_SIOCGLIFCONF | |||
| 891 | # define ifr_type struct lifreq | |||
| 892 | # else | |||
| 893 | # define ifr_type struct ifreq | |||
| 894 | # endif | |||
| 895 | ||||
| 896 | /* Handle variable length ifreq in BNR2 and later */ | |||
| 897 | # ifdef VARIABLE_IFREQ | |||
| 898 | # define ifr_size(p) (sizeof (struct ifreq) + \ | |||
| 899 | (p->ifr_addrifr_ifru.ifru_addr.sa_len > sizeof (p->ifr_addrifr_ifru.ifru_addr) ? \ | |||
| 900 | p->ifr_addrifr_ifru.ifru_addr.sa_len - sizeof (p->ifr_addrifr_ifru.ifru_addr) : 0)) | |||
| 901 | # else | |||
| 902 | # define ifr_size(p) (sizeof (ifr_type)) | |||
| 903 | # endif | |||
| 904 | ||||
| 905 | /* Define this host for access control. Find all the hosts the OS knows about | |||
| 906 | * for this fd and add them to the selfhosts list. | |||
| 907 | */ | |||
| 908 | static void | |||
| 909 | DefineSelf (int fd, FILE *file, Xauth *auth) | |||
| 910 | { | |||
| 911 | char buf[2048], *cp, *cplim; | |||
| 912 | int len; | |||
| 913 | char *addr; | |||
| 914 | int family; | |||
| 915 | register ifr_type *ifr; | |||
| 916 | # ifdef USE_SIOCGLIFCONF | |||
| 917 | void * bufptr = buf; | |||
| 918 | size_t buflen = sizeof(buf); | |||
| 919 | struct lifconf ifc; | |||
| 920 | # ifdef SIOCGLIFNUM | |||
| 921 | struct lifnum ifn; | |||
| 922 | # endif | |||
| 923 | # else | |||
| 924 | struct ifconf ifc; | |||
| 925 | # endif | |||
| 926 | ||||
| 927 | # if defined(SIOCGLIFNUM) && defined(SIOCGLIFCONF) | |||
| 928 | ifn.lifn_family = AF_UNSPEC0; | |||
| 929 | ifn.lifn_flags = 0; | |||
| 930 | if (ioctl (fd, (int) SIOCGLIFNUM, (char *) &ifn) < 0) | |||
| 931 | LogError ("Failed getting interface count"); | |||
| 932 | if (buflen < (ifn.lifn_count * sizeof(struct lifreq))) { | |||
| 933 | buflen = ifn.lifn_count * sizeof(struct lifreq); | |||
| 934 | bufptr = malloc(buflen); | |||
| 935 | } | |||
| 936 | # endif | |||
| 937 | ||||
| 938 | # ifdef USE_SIOCGLIFCONF | |||
| 939 | ifc.lifc_family = AF_UNSPEC0; | |||
| 940 | ifc.lifc_flags = 0; | |||
| 941 | ifc.lifc_len = buflen; | |||
| 942 | ifc.lifc_buf = bufptr; | |||
| 943 | ||||
| 944 | # define IFC_IOCTL_REQ SIOCGLIFCONF | |||
| 945 | # define IFC_IFC_REQ ifc.lifc_req | |||
| 946 | # define IFC_IFC_LEN ifc.lifc_len | |||
| 947 | # define IFR_IFR_ADDR ifr->lifr_addr | |||
| 948 | # define IFR_IFR_NAME ifr->lifr_name | |||
| 949 | ||||
| 950 | # else | |||
| 951 | ifc.ifc_len = sizeof (buf); | |||
| 952 | ifc.ifc_bufifc_ifcu.ifcu_buf = buf; | |||
| 953 | ||||
| 954 | # define IFC_IOCTL_REQ SIOCGIFCONF(((__uint32_t)0x80000000|(__uint32_t)0x40000000) | ((sizeof(struct ifconf) & 0x1fff) << 16) | ((('i')) << 8) | ( (36))) | |||
| 955 | # define IFC_IFC_REQ ifc.ifc_reqifc_ifcu.ifcu_req | |||
| 956 | # define IFC_IFC_LEN ifc.ifc_len | |||
| 957 | # define IFR_IFR_ADDR ifr->ifr_addrifr_ifru.ifru_addr | |||
| 958 | # define IFR_IFR_NAME ifr->ifr_name | |||
| 959 | # endif | |||
| 960 | ||||
| 961 | if (ifioctl (fd, IFC_IOCTL_REQ, (char *) &ifc) < 0) { | |||
| 962 | LogError ("Trouble getting network interface configuration"); | |||
| 963 | ||||
| 964 | # ifdef USE_SIOCGLIFCONF | |||
| 965 | if (bufptr != buf) { | |||
| 966 | free(bufptr); | |||
| 967 | } | |||
| 968 | # endif | |||
| 969 | return; | |||
| 970 | } | |||
| 971 | ||||
| 972 | cplim = (char *) IFC_IFC_REQ + IFC_IFC_LEN; | |||
| 973 | ||||
| 974 | for (cp = (char *) IFC_IFC_REQ; cp < cplim; cp += ifr_size (ifr)) | |||
| 975 | { | |||
| 976 | ifr = (ifr_type *) cp; | |||
| 977 | family = ConvertAddr ((XdmcpNetaddr) &IFR_IFR_ADDR, &len, &addr); | |||
| 978 | if (family < 0) | |||
| 979 | continue; | |||
| 980 | ||||
| 981 | if (len == 0) | |||
| 982 | { | |||
| 983 | Debug ("Skipping zero length address\n"); | |||
| 984 | continue; | |||
| 985 | } | |||
| 986 | /* | |||
| 987 | * don't write out 'localhost' entries, as | |||
| 988 | * they may conflict with other local entries. | |||
| 989 | * DefineLocal will always be called to add | |||
| 990 | * the local entry anyway, so this one can | |||
| 991 | * be tossed. | |||
| 992 | */ | |||
| 993 | if (family == FamilyInternet0 && len == 4 && | |||
| 994 | addr[0] == 127 && addr[1] == 0 && | |||
| 995 | addr[2] == 0 && addr[3] == 1) | |||
| 996 | { | |||
| 997 | Debug ("Skipping localhost address\n"); | |||
| 998 | continue; | |||
| 999 | } | |||
| 1000 | # if defined(IPv61) && defined(AF_INET630) | |||
| 1001 | if (family == FamilyInternet66) { | |||
| 1002 | if (IN6_IS_ADDR_LOOPBACK(((struct in6_addr *)addr))((*(const __uint32_t *)(const void *)(&(((struct in6_addr *)addr))->__u6_addr.__u6_addr8[0]) == 0) && (*(const __uint32_t *)(const void *)(&(((struct in6_addr *)addr)) ->__u6_addr.__u6_addr8[4]) == 0) && (*(const __uint32_t *)(const void *)(&(((struct in6_addr *)addr))->__u6_addr .__u6_addr8[8]) == 0) && (*(const __uint32_t *)(const void *)(&(((struct in6_addr *)addr))->__u6_addr.__u6_addr8 [12]) == (__builtin_constant_p(1) ? ((__uint32_t)((((__uint32_t )(1) & 0xff000000) >> 24) | (((__uint32_t)(1) & 0x00ff0000) >> 8) | (((__uint32_t)(1) & 0x0000ff00 ) << 8) | (((__uint32_t)(1) & 0x000000ff) << 24 ))) : _OSSwapInt32(1))))) { | |||
| 1003 | Debug ("Skipping IPv6 localhost address\n"); | |||
| 1004 | continue; | |||
| 1005 | } | |||
| 1006 | /* Also skip XDM-AUTHORIZATION-1 */ | |||
| 1007 | if (auth->name_length == 19 && | |||
| 1008 | strcmp(auth->name, "XDM-AUTHORIZATION-1") == 0) { | |||
| 1009 | Debug ("Skipping IPv6 XDM-AUTHORIZATION-1\n"); | |||
| 1010 | continue; | |||
| 1011 | } | |||
| 1012 | } | |||
| 1013 | # endif | |||
| 1014 | Debug ("DefineSelf: write network address, length %d\n", len); | |||
| 1015 | writeAddr (family, len, addr, file, auth); | |||
| 1016 | } | |||
| 1017 | } | |||
| 1018 | ||||
| 1019 | # else /* SIOCGIFCONF */ | |||
| 1020 | ||||
| 1021 | /* Define this host for access control. Find all the hosts the OS knows about | |||
| 1022 | * for this fd and add them to the selfhosts list. | |||
| 1023 | */ | |||
| 1024 | static void | |||
| 1025 | DefineSelf (int fd, int file, int auth) | |||
| 1026 | { | |||
| 1027 | register int n; | |||
| 1028 | int len; | |||
| 1029 | caddr_t addr; | |||
| 1030 | int family; | |||
| 1031 | ||||
| 1032 | struct utsname name; | |||
| 1033 | register struct hostent *hp; | |||
| 1034 | ||||
| 1035 | union { | |||
| 1036 | struct sockaddr sa; | |||
| 1037 | struct sockaddr_in in; | |||
| 1038 | } saddr; | |||
| 1039 | ||||
| 1040 | struct sockaddr_in *inetaddr; | |||
| 1041 | ||||
| 1042 | /* hpux: | |||
| 1043 | * Why not use gethostname()? Well, at least on my system, I've had to | |||
| 1044 | * make an ugly kernel patch to get a name longer than 8 characters, and | |||
| 1045 | * uname() lets me access to the whole string (it smashes release, you | |||
| 1046 | * see), whereas gethostname() kindly truncates it for me. | |||
| 1047 | */ | |||
| 1048 | uname(&name); | |||
| 1049 | hp = gethostbyname (name.nodename); | |||
| 1050 | if (hp != NULL((void*)0)) { | |||
| 1051 | saddr.sa.sa_family = hp->h_addrtype; | |||
| 1052 | inetaddr = (struct sockaddr_in *) (&(saddr.sa)); | |||
| 1053 | memmove( (char *) &(inetaddr->sin_addr), (char *) hp->h_addr, (int) hp->h_length)__builtin___memmove_chk ((char *) &(inetaddr->sin_addr ), (char *) hp->h_addr, (int) hp->h_length, __builtin_object_size ((char *) &(inetaddr->sin_addr), 0)); | |||
| 1054 | family = ConvertAddr ( &(saddr.sa), &len, &addr); | |||
| 1055 | if ( family >= 0) { | |||
| 1056 | writeAddr (FamilyInternet0, sizeof (inetaddr->sin_addr), | |||
| 1057 | (char *) (&inetaddr->sin_addr), file, auth); | |||
| 1058 | } | |||
| 1059 | } | |||
| 1060 | } | |||
| 1061 | ||||
| 1062 | ||||
| 1063 | # endif /* SIOCGIFCONF else */ | |||
| 1064 | #endif /* HAVE_GETIFADDRS */ | |||
| 1065 | ||||
| 1066 | static void | |||
| 1067 | setAuthNumber (Xauth *auth, char *name) | |||
| 1068 | { | |||
| 1069 | char *colon; | |||
| 1070 | char *dot, *number; | |||
| 1071 | ||||
| 1072 | Debug ("setAuthNumber %s\n", name); | |||
| 1073 | colon = strrchr(name, ':'); | |||
| 1074 | if (colon) { | |||
| 1075 | ++colon; | |||
| 1076 | dot = strchr(colon, '.'); | |||
| 1077 | if (dot) | |||
| 1078 | auth->number_length = dot - colon; | |||
| 1079 | else | |||
| 1080 | auth->number_length = strlen (colon); | |||
| 1081 | number = malloc (auth->number_length + 1); | |||
| 1082 | if (number) { | |||
| 1083 | strncpy (number, colon, auth->number_length)__builtin___strncpy_chk (number, colon, auth->number_length , __builtin_object_size (number, 2 > 1 ? 1 : 0)); | |||
| 1084 | number[auth->number_length] = '\0'; | |||
| 1085 | } else { | |||
| 1086 | LogOutOfMem ("setAuthNumber"); | |||
| 1087 | auth->number_length = 0; | |||
| 1088 | } | |||
| 1089 | auth->number = number; | |||
| 1090 | Debug ("setAuthNumber: %s\n", number); | |||
| 1091 | } | |||
| 1092 | } | |||
| 1093 | ||||
| 1094 | static void | |||
| 1095 | writeLocalAuth (FILE *file, Xauth *auth, char *name) | |||
| 1096 | { | |||
| 1097 | int fd; | |||
| 1098 | ||||
| 1099 | Debug ("writeLocalAuth: %s %.*s\n", name, auth->name_length, auth->name); | |||
| 1100 | setAuthNumber (auth, name); | |||
| 1101 | #ifdef TCPCONN1 | |||
| 1102 | # if defined(IPv61) && defined(AF_INET630) | |||
| 1103 | fd = socket (AF_INET630, SOCK_STREAM1, 0); | |||
| 1104 | if (fd < 0) | |||
| 1105 | # endif | |||
| 1106 | fd = socket (AF_INET2, SOCK_STREAM1, 0); | |||
| 1107 | DefineSelf (fd, file, auth); | |||
| 1108 | close (fd); | |||
| 1109 | #endif | |||
| 1110 | DefineLocal (file, auth); | |||
| 1111 | } | |||
| 1112 | ||||
| 1113 | #ifdef XDMCP | |||
| 1114 | ||||
| 1115 | static void | |||
| 1116 | writeRemoteAuth (FILE *file, Xauth *auth, XdmcpNetaddr peer, int peerlen, char *name) | |||
| 1117 | { | |||
| 1118 | int family = FamilyLocal(256); | |||
| 1119 | char *addr; | |||
| 1120 | ||||
| 1121 | Debug ("writeRemoteAuth: %s %.*s\n", name, auth->name_length, auth->name); | |||
| 1122 | if (!peer || peerlen < 2) | |||
| 1123 | return; | |||
| 1124 | setAuthNumber (auth, name); | |||
| 1125 | family = ConvertAddr (peer, &peerlen, &addr); | |||
| 1126 | Debug ("writeRemoteAuth: family %d\n", family); | |||
| 1127 | if (family != FamilyLocal(256)) | |||
| 1128 | { | |||
| 1129 | Debug ("writeRemoteAuth: %d, %d, %x\n", | |||
| 1130 | family, peerlen, *(int *)addr); | |||
| 1131 | writeAddr (family, peerlen, addr, file, auth); | |||
| 1132 | } | |||
| 1133 | else | |||
| 1134 | { | |||
| 1135 | writeLocalAuth (file, auth, name); | |||
| 1136 | } | |||
| 1137 | } | |||
| 1138 | ||||
| 1139 | #endif /* XDMCP */ | |||
| 1140 | ||||
| 1141 | void | |||
| 1142 | SetUserAuthorization (struct display *d, struct verify_info *verify) | |||
| 1143 | { | |||
| 1144 | FILE *old = NULL((void*)0), *new; | |||
| 1145 | char home_name[1024], backup_name[1024], new_name[1024]; | |||
| 1146 | char *name = NULL((void*)0); | |||
| 1147 | char *home; | |||
| 1148 | char *envname = NULL((void*)0); | |||
| 1149 | int lockStatus; | |||
| 1150 | Xauth *entry, **auths; | |||
| 1151 | int setenv = 0; | |||
| 1152 | struct stat statb; | |||
| 1153 | int i; | |||
| 1154 | int magicCookie; | |||
| 1155 | int data_len; | |||
| 1156 | #ifdef HAVE_MKSTEMP1 | |||
| 1157 | int fd; | |||
| 1158 | #endif | |||
| 1159 | ||||
| 1160 | Debug ("SetUserAuthorization\n"); | |||
| 1161 | auths = d->authorizations; | |||
| 1162 | if (auths) { | |||
| 1163 | home = getEnv (verify->userEnviron, "HOME"); | |||
| 1164 | lockStatus = LOCK_ERROR1; | |||
| 1165 | if (home) { | |||
| 1166 | snprintf (home_name, sizeof(home_name), "%s/.Xauthority", home)__builtin___snprintf_chk (home_name, sizeof(home_name), 0, __builtin_object_size (home_name, 2 > 1 ? 1 : 0), "%s/.Xauthority", home); | |||
| 1167 | Debug ("XauLockAuth %s\n", home_name); | |||
| 1168 | lockStatus = XauLockAuth (home_name, 1, 2, 10); | |||
| 1169 | Debug ("Lock is %d\n", lockStatus); | |||
| 1170 | if (lockStatus == LOCK_SUCCESS0) { | |||
| 1171 | if (openFiles (home_name, new_name, &old, &new) | |||
| 1172 | && (old != NULL((void*)0)) && (new != NULL((void*)0))) { | |||
| 1173 | name = home_name; | |||
| 1174 | setenv = 0; | |||
| 1175 | } else { | |||
| 1176 | Debug ("openFiles failed\n"); | |||
| 1177 | XauUnlockAuth (home_name); | |||
| 1178 | lockStatus = LOCK_ERROR1; | |||
| 1179 | if (old != NULL((void*)0)) { | |||
| 1180 | (void) fclose (old); | |||
| 1181 | old = NULL((void*)0); | |||
| 1182 | } | |||
| 1183 | if (new != NULL((void*)0)) | |||
| 1184 | (void) fclose (new); | |||
| 1185 | } | |||
| 1186 | } | |||
| 1187 | } | |||
| 1188 | if (lockStatus != LOCK_SUCCESS0) { | |||
| 1189 | snprintf (backup_name, sizeof(backup_name),__builtin___snprintf_chk (backup_name, sizeof(backup_name), 0 , __builtin_object_size (backup_name, 2 > 1 ? 1 : 0), "%s/.XauthXXXXXX" , d->userAuthDir) | |||
| 1190 | "%s/.XauthXXXXXX", d->userAuthDir)__builtin___snprintf_chk (backup_name, sizeof(backup_name), 0 , __builtin_object_size (backup_name, 2 > 1 ? 1 : 0), "%s/.XauthXXXXXX" , d->userAuthDir); | |||
| 1191 | #ifdef HAVE_MKSTEMP1 | |||
| 1192 | fd = mkstemp (backup_name); | |||
| 1193 | if (fd >= 0) { | |||
| 1194 | old = fdopen (fd, "r"); | |||
| 1195 | if (old == NULL((void*)0)) | |||
| 1196 | (void) close(fd); | |||
| 1197 | } | |||
| 1198 | ||||
| 1199 | if (old != NULL((void*)0)) | |||
| 1200 | #else | |||
| 1201 | (void) mktemp (backup_name); | |||
| 1202 | #endif | |||
| 1203 | { | |||
| 1204 | lockStatus = XauLockAuth (backup_name, 1, 2, 10); | |||
| 1205 | Debug ("backup lock is %d\n", lockStatus); | |||
| 1206 | if (lockStatus == LOCK_SUCCESS0) { | |||
| 1207 | if (openFiles (backup_name, new_name, &old, &new) | |||
| 1208 | && (old != NULL((void*)0)) && (new != NULL((void*)0))) { | |||
| 1209 | name = backup_name; | |||
| 1210 | setenv = 1; | |||
| 1211 | } else { | |||
| 1212 | XauUnlockAuth (backup_name); | |||
| 1213 | lockStatus = LOCK_ERROR1; | |||
| 1214 | if (old != NULL((void*)0)) { | |||
| 1215 | (void) fclose (old); | |||
| 1216 | old = NULL((void*)0); | |||
| 1217 | } | |||
| 1218 | if (new != NULL((void*)0)) | |||
| 1219 | (void) fclose (new); | |||
| 1220 | } | |||
| 1221 | #ifdef HAVE_MKSTEMP1 | |||
| 1222 | } else { | |||
| 1223 | (void) fclose (old); | |||
| 1224 | #endif | |||
| 1225 | } | |||
| 1226 | } | |||
| 1227 | } | |||
| 1228 | if (lockStatus != LOCK_SUCCESS0) { | |||
| 1229 | Debug ("can't lock auth file %s or backup %s\n", | |||
| 1230 | home_name, backup_name); | |||
| 1231 | LogError ("can't lock authorization file %s or backup %s\n", | |||
| 1232 | home_name, backup_name); | |||
| 1233 | return; | |||
| 1234 | } | |||
| 1235 | initAddrs (); | |||
| 1236 | doWrite = 1; | |||
| 1237 | Debug ("%d authorization protocols for %s\n", d->authNum, d->name); | |||
| 1238 | /* | |||
| 1239 | * Write MIT-MAGIC-COOKIE-1 authorization first, so that | |||
| 1240 | * R4 clients which only knew that, and used the first | |||
| 1241 | * matching entry will continue to function | |||
| 1242 | */ | |||
| 1243 | magicCookie = -1; | |||
| 1244 | for (i = 0; i < d->authNum; i++) | |||
| 1245 | { | |||
| 1246 | if (auths[i]->name_length == 18 && | |||
| 1247 | !strncmp (auths[i]->name, "MIT-MAGIC-COOKIE-1", 18)) | |||
| 1248 | { | |||
| 1249 | magicCookie = i; | |||
| 1250 | if (d->displayType.location == Local1) | |||
| 1251 | writeLocalAuth (new, auths[i], d->name); | |||
| 1252 | #ifdef XDMCP | |||
| 1253 | else | |||
| 1254 | writeRemoteAuth (new, auths[i], d->peer, d->peerlen, d->name); | |||
| 1255 | #endif | |||
| 1256 | break; | |||
| 1257 | } | |||
| 1258 | } | |||
| 1259 | /* now write other authorizations */ | |||
| 1260 | for (i = 0; i < d->authNum; i++) | |||
| 1261 | { | |||
| 1262 | if (i != magicCookie) | |||
| 1263 | { | |||
| 1264 | data_len = auths[i]->data_length; | |||
| 1265 | /* client will just use default Kerberos cache, so don't | |||
| 1266 | * even write cache info into the authority file. | |||
| 1267 | */ | |||
| 1268 | if (auths[i]->name_length == 14 && | |||
| 1269 | !strncmp (auths[i]->name, "MIT-KERBEROS-5", 14)) | |||
| 1270 | auths[i]->data_length = 0; | |||
| 1271 | if (d->displayType.location == Local1) | |||
| 1272 | writeLocalAuth (new, auths[i], d->name); | |||
| 1273 | #ifdef XDMCP | |||
| 1274 | else | |||
| 1275 | writeRemoteAuth (new, auths[i], d->peer, d->peerlen, d->name); | |||
| 1276 | #endif | |||
| 1277 | auths[i]->data_length = data_len; | |||
| 1278 | } | |||
| 1279 | } | |||
| 1280 | if (old) { | |||
| 1281 | if (fstat (fileno (old), &statb) != -1) | |||
| 1282 | chmod (new_name, (int) (statb.st_mode & 0777)); | |||
| 1283 | /*SUPPRESS 560*/ | |||
| 1284 | while ((entry = XauReadAuth (old))) { | |||
| 1285 | if (!checkEntry (entry)) | |||
| 1286 | { | |||
| 1287 | Debug ("Writing an entry\n"); | |||
| 1288 | writeAuth (new, entry); | |||
| 1289 | } | |||
| 1290 | XauDisposeAuth (entry); | |||
| 1291 | } | |||
| 1292 | fclose (old); | |||
| 1293 | } | |||
| 1294 | doneAddrs (); | |||
| 1295 | fclose (new); | |||
| 1296 | if (unlink (name) == -1) | |||
| 1297 | if (errno(*__error()) != ENOENT2) | |||
| 1298 | LogError ("cannot remove old authorization file %s: %s\n", | |||
| 1299 | name, _SysErrorMsg (errno(*__error()))); | |||
| 1300 | envname = name; | |||
| 1301 | if (link (new_name, name) == -1) { | |||
| 1302 | LogError ("cannot link temporary authorization file %s to old " | |||
| 1303 | "location %s: %s\n", new_name, name, | |||
| 1304 | _SysErrorMsg (errno(*__error()))); | |||
| 1305 | setenv = 1; | |||
| 1306 | envname = new_name; | |||
| 1307 | } else { | |||
| 1308 | Debug ("authorization file %s successfully updated\n", name); | |||
| 1309 | if (unlink (new_name)) | |||
| 1310 | if (errno(*__error()) != ENOENT2) | |||
| 1311 | LogError ("cannot remove new authorization file %s:" | |||
| 1312 | " %s\n", new_name, _SysErrorMsg (errno(*__error()))); | |||
| 1313 | } | |||
| 1314 | if (setenv) { | |||
| 1315 | verify->userEnviron = setEnv (verify->userEnviron, | |||
| 1316 | "XAUTHORITY", envname); | |||
| 1317 | verify->systemEnviron = setEnv (verify->systemEnviron, | |||
| 1318 | "XAUTHORITY", envname); | |||
| 1319 | } | |||
| 1320 | XauUnlockAuth (name); | |||
| 1321 | if (envname) | |||
| 1322 | chown (envname, verify->uid, verify->gid); | |||
| 1323 | } | |||
| 1324 | Debug ("done SetUserAuthorization\n"); | |||
| 1325 | } | |||
| 1326 | ||||
| 1327 | void | |||
| 1328 | RemoveUserAuthorization (struct display *d, struct verify_info *verify) | |||
| 1329 | { | |||
| 1330 | char *home; | |||
| 1331 | Xauth **auths, *entry; | |||
| 1332 | char name[1024], new_name[1024]; | |||
| 1333 | int lockStatus; | |||
| 1334 | FILE *old, *new; | |||
| 1335 | struct stat statb; | |||
| 1336 | int i; | |||
| 1337 | ||||
| 1338 | if (!(auths = d->authorizations)) | |||
| 1339 | return; | |||
| 1340 | home = getEnv (verify->userEnviron, "HOME"); | |||
| 1341 | if (!home) | |||
| 1342 | return; | |||
| 1343 | Debug ("RemoveUserAuthorization\n"); | |||
| 1344 | snprintf(name, sizeof(name), "%s/.Xauthority", home)__builtin___snprintf_chk (name, sizeof(name), 0, __builtin_object_size (name, 2 > 1 ? 1 : 0), "%s/.Xauthority", home); | |||
| 1345 | Debug ("XauLockAuth %s\n", name); | |||
| 1346 | lockStatus = XauLockAuth (name, 1, 2, 10); | |||
| 1347 | Debug ("Lock is %d\n", lockStatus); | |||
| 1348 | if (lockStatus != LOCK_SUCCESS0) | |||
| 1349 | return; | |||
| 1350 | old = NULL((void*)0); | |||
| 1351 | if (openFiles (name, new_name, &old, &new)) | |||
| 1352 | { | |||
| 1353 | initAddrs (); | |||
| 1354 | doWrite = 0; | |||
| 1355 | for (i = 0; i < d->authNum; i++) | |||
| 1356 | { | |||
| 1357 | if (d->displayType.location == Local1) | |||
| 1358 | writeLocalAuth (new, auths[i], d->name); | |||
| 1359 | #ifdef XDMCP | |||
| 1360 | else | |||
| 1361 | writeRemoteAuth (new, auths[i], d->peer, d->peerlen, d->name); | |||
| 1362 | #endif | |||
| 1363 | } | |||
| 1364 | doWrite = 1; | |||
| 1365 | if (old) { | |||
| 1366 | if (fstat (fileno (old), &statb) != -1) | |||
| 1367 | chmod (new_name, (int) (statb.st_mode & 0777)); | |||
| 1368 | /*SUPPRESS 560*/ | |||
| 1369 | while ((entry = XauReadAuth (old))) { | |||
| 1370 | if (!checkEntry (entry)) | |||
| 1371 | { | |||
| 1372 | Debug ("Writing an entry\n"); | |||
| 1373 | writeAuth (new, entry); | |||
| 1374 | } | |||
| 1375 | XauDisposeAuth (entry); | |||
| 1376 | } | |||
| 1377 | fclose (old); | |||
| 1378 | } | |||
| 1379 | doneAddrs (); | |||
| 1380 | fclose (new); | |||
| 1381 | if (unlink (name) == -1) | |||
| 1382 | if (errno(*__error()) != ENOENT2) | |||
| 1383 | LogError ("cannot remove new authorization file %s: %s\n", | |||
| 1384 | name, _SysErrorMsg (errno(*__error()))); | |||
| 1385 | if (link (new_name, name) == -1) { | |||
| 1386 | LogError ("cannot link temporary authorization file %s to old " | |||
| 1387 | "location %s: %s\n", new_name, name, | |||
| 1388 | _SysErrorMsg (errno(*__error()))); | |||
| 1389 | } else { | |||
| 1390 | Debug ("authorization file %s successfully updated\n", name); | |||
| 1391 | if (unlink (new_name)) | |||
| 1392 | if (errno(*__error()) != ENOENT2) | |||
| 1393 | LogError ("cannot remove new authorization file %s:" | |||
| 1394 | " %s\n", new_name, _SysErrorMsg (errno(*__error()))); | |||
| 1395 | } | |||
| 1396 | } | |||
| 1397 | XauUnlockAuth (name); | |||
| 1398 | } |