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 | } |