master
ブランチ master
ShaderPlayground / deps / xlibre / include / X11 / Xtrans / Xtransutil.c
14.5 KB、631行 生 Blame 履歴
1/*
2
3Copyright 1993, 1994, 1998 The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included
12in all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20OTHER DEALINGS IN THE SOFTWARE.
21
22Except as contained in this notice, the name of The Open Group shall
23not be used in advertising or otherwise to promote the sale, use or
24other dealings in this Software without prior written authorization
25from The Open Group.
26
27 * Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA
28 *
29 * All Rights Reserved
30 *
31 * Permission to use, copy, modify, and distribute this software and its
32 * documentation for any purpose and without fee is hereby granted, provided
33 * that the above copyright notice appear in all copies and that both that
34 * copyright notice and this permission notice appear in supporting
35 * documentation, and that the name NCR not be used in advertising
36 * or publicity pertaining to distribution of the software without specific,
37 * written prior permission. NCR makes no representations about the
38 * suitability of this software for any purpose. It is provided "as is"
39 * without express or implied warranty.
40 *
41 * NCRS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
42 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
43 * NO EVENT SHALL NCR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
44 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
45 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
46 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
47 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
48 */
49
50/*
51 * These are some utility functions created for convenience or to provide
52 * an interface that is similar to an existing interface. These are built
53 * only using the Transport Independent API, and have no knowledge of
54 * the internal implementation.
55 */
56
57#ifdef XTHREADS
58#include <X11/Xthreads.h>
59#endif
60#ifdef WIN32
61#include <X11/Xlibint.h>
62#include <X11/Xwinsock.h>
63#endif
64
65#if defined(IPv6) && !defined(AF_INET6)
66#error "Cannot build IPv6 support without AF_INET6"
67#endif
68
69/* Temporary workaround for consumers whose configure scripts were
70 generated with pre-1.6 versions of xtrans.m4 */
71#if defined(IPv6) && !defined(HAVE_INET_NTOP)
72#define HAVE_INET_NTOP
73#endif
74
75#ifdef X11_t
76
77/*
78 * These values come from X.h and Xauth.h, and MUST match them. Some
79 * of these values are also defined by the ChangeHost protocol message.
80 */
81
82#define FamilyInternet 0 /* IPv4 */
83#define FamilyDECnet 1
84#define FamilyChaos 2
85#define FamilyInternet6 6
86#define FamilyAmoeba 33
87#define FamilyLocalHost 252
88#define FamilyKrb5Principal 253
89#define FamilyNetname 254
90#define FamilyLocal 256
91#define FamilyWild 65535
92
93/*
94 * TRANS(ConvertAddress) converts a sockaddr based address to an
95 * X authorization based address. Some of this is defined as part of
96 * the ChangeHost protocol. The rest is just done in a consistent manner.
97 */
98
99int
100TRANS(ConvertAddress)(int *familyp, int *addrlenp, Xtransaddr **addrp)
101
102{
103
104 prmsg(2,"ConvertAddress(%d,%d,%p)\n",*familyp,*addrlenp,*addrp);
105
106 switch( *familyp )
107 {
108#if defined(TCPCONN)
109 case AF_INET:
110 {
111 /*
112 * Check for the BSD hack localhost address 127.0.0.1.
113 * In this case, we are really FamilyLocal.
114 */
115
116 struct sockaddr_in saddr;
117 int len = sizeof(saddr.sin_addr.s_addr);
118 char *cp = (char *) &saddr.sin_addr.s_addr;
119
120 memcpy (&saddr, *addrp, sizeof (struct sockaddr_in));
121
122 if ((len == 4) && (cp[0] == 127) && (cp[1] == 0) &&
123 (cp[2] == 0) && (cp[3] == 1))
124 {
125 *familyp=FamilyLocal;
126 }
127 else
128 {
129 *familyp=FamilyInternet;
130 *addrlenp=len;
131 memcpy(*addrp,&saddr.sin_addr,len);
132 }
133 break;
134 }
135
136#ifdef IPv6
137 case AF_INET6:
138 {
139 struct sockaddr_in6 saddr6;
140
141 memcpy (&saddr6, *addrp, sizeof (struct sockaddr_in6));
142
143 if (IN6_IS_ADDR_LOOPBACK(&saddr6.sin6_addr))
144 {
145 *familyp=FamilyLocal;
146 }
147 else if (IN6_IS_ADDR_V4MAPPED(&(saddr6.sin6_addr))) {
148 char *cp = (char *) &saddr6.sin6_addr.s6_addr[12];
149
150 if ((cp[0] == 127) && (cp[1] == 0) &&
151 (cp[2] == 0) && (cp[3] == 1))
152 {
153 *familyp=FamilyLocal;
154 }
155 else
156 {
157 *familyp=FamilyInternet;
158 *addrlenp = sizeof (struct in_addr);
159 memcpy(*addrp,cp,*addrlenp);
160 }
161 }
162 else
163 {
164 *familyp=FamilyInternet6;
165 *addrlenp=sizeof(saddr6.sin6_addr);
166 memcpy(*addrp,&saddr6.sin6_addr,sizeof(saddr6.sin6_addr));
167 }
168 break;
169 }
170#endif /* IPv6 */
171#endif /* defined(TCPCONN) */
172
173
174#if defined(UNIXCONN) || defined(LOCALCONN)
175 case AF_UNIX:
176 {
177 *familyp=FamilyLocal;
178 break;
179 }
180#endif /* defined(UNIXCONN) || defined(LOCALCONN) */
181
182
183 default:
184 prmsg(1,"ConvertAddress: Unknown family type %d\n",
185 *familyp);
186 return -1;
187 }
188
189
190 if (*familyp == FamilyLocal)
191 {
192 /*
193 * In the case of a local connection, we need to get the
194 * host name for authentication.
195 */
196
197 char hostnamebuf[256];
198 int len = TRANS(GetHostname) (hostnamebuf, sizeof hostnamebuf);
199
200 if (len > 0) {
201 if (*addrp && *addrlenp < (len + 1))
202 {
203 free (*addrp);
204 *addrp = NULL;
205 }
206 if (!*addrp)
207 *addrp = malloc (len + 1);
208 if (*addrp) {
209 strcpy ((char *) *addrp, hostnamebuf);
210 *addrlenp = len;
211 } else {
212 *addrlenp = 0;
213 }
214 }
215 else
216 {
217 if (*addrp)
218 free (*addrp);
219 *addrp = NULL;
220 *addrlenp = 0;
221 }
222 }
223
224 return 0;
225}
226
227#endif /* X11_t */
228
229#ifdef ICE_t
230
231/* Needed for _XGethostbyaddr usage in TRANS(GetPeerNetworkId) */
232# if defined(TCPCONN) || defined(UNIXCONN)
233# define X_INCLUDE_NETDB_H
234# define XOS_USE_NO_LOCKING
235# include <X11/Xos_r.h>
236# endif
237
238#include <signal.h>
239
240char *
241TRANS(GetMyNetworkId) (XtransConnInfo ciptr)
242
243{
244 int family = ciptr->family;
245 char *addr = ciptr->addr;
246 char hostnamebuf[256];
247 char *networkId = NULL;
248 const char *transName = ciptr->transptr->TransName;
249
250 if (gethostname (hostnamebuf, sizeof (hostnamebuf)) < 0)
251 {
252 return (NULL);
253 }
254
255 switch (family)
256 {
257#if defined(UNIXCONN) || defined(LOCALCONN)
258 case AF_UNIX:
259 {
260 struct sockaddr_un *saddr = (struct sockaddr_un *) addr;
261 networkId = malloc (3 + strlen (transName) +
262 strlen (hostnamebuf) + strlen (saddr->sun_path));
263 if (networkId != NULL)
264 sprintf (networkId, "%s/%s:%s", transName,
265 hostnamebuf, saddr->sun_path);
266 break;
267 }
268#endif /* defined(UNIXCONN) || defined(LOCALCONN) */
269
270#if defined(TCPCONN)
271 case AF_INET:
272#ifdef IPv6
273 case AF_INET6:
274#endif
275 {
276 struct sockaddr_in *saddr = (struct sockaddr_in *) addr;
277#ifdef IPv6
278 struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *) addr;
279#endif
280 int portnum;
281 char portnumbuf[10];
282
283
284#ifdef IPv6
285 if (family == AF_INET6)
286 portnum = ntohs (saddr6->sin6_port);
287 else
288#endif
289 portnum = ntohs (saddr->sin_port);
290
291 snprintf (portnumbuf, sizeof(portnumbuf), "%d", portnum);
292 networkId = malloc (3 + strlen (transName) +
293 strlen (hostnamebuf) + strlen (portnumbuf));
294 if (networkId != NULL)
295 sprintf (networkId, "%s/%s:%s", transName, hostnamebuf, portnumbuf);
296 break;
297 }
298#endif /* defined(TCPCONN) */
299
300
301 default:
302 break;
303 }
304
305 return (networkId);
306}
307
308#include <setjmp.h>
309static jmp_buf env;
310
311#ifdef SIGALRM
312static volatile int nameserver_timedout = 0;
313
314static void
315nameserver_lost(int sig _X_UNUSED)
316{
317 nameserver_timedout = 1;
318 longjmp (env, -1);
319 /* NOTREACHED */
320}
321#endif /* SIGALARM */
322
323
324char *
325TRANS(GetPeerNetworkId) (XtransConnInfo ciptr)
326
327{
328 int family = ciptr->family;
329 char *peer_addr = ciptr->peeraddr;
330 char *hostname;
331 char addrbuf[256];
332 const char *addr = NULL;
333
334 switch (family)
335 {
336 case AF_UNSPEC:
337#if defined(UNIXCONN) || defined(LOCALCONN)
338 case AF_UNIX:
339 {
340 if (gethostname (addrbuf, sizeof (addrbuf)) == 0)
341 addr = addrbuf;
342 break;
343 }
344#endif /* defined(UNIXCONN) || defined(LOCALCONN) */
345
346#if defined(TCPCONN)
347 case AF_INET:
348#ifdef IPv6
349 case AF_INET6:
350#endif
351 {
352 struct sockaddr_in *saddr = (struct sockaddr_in *) peer_addr;
353#ifdef IPv6
354 struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *) peer_addr;
355#endif
356 char *address;
357 int addresslen;
358#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
359 _Xgethostbynameparams hparams;
360#endif
361 struct hostent * volatile hostp = NULL;
362
363#ifdef IPv6
364 if (family == AF_INET6)
365 {
366 address = (char *) &saddr6->sin6_addr;
367 addresslen = sizeof (saddr6->sin6_addr);
368 }
369 else
370#endif
371 {
372 address = (char *) &saddr->sin_addr;
373 addresslen = sizeof (saddr->sin_addr);
374 }
375
376#ifdef SIGALRM
377 /*
378 * gethostbyaddr can take a LONG time if the host does not exist.
379 * Assume that if it does not respond in NAMESERVER_TIMEOUT seconds
380 * that something is wrong and do not make the user wait.
381 * gethostbyaddr will continue after a signal, so we have to
382 * jump out of it.
383 */
384
385 nameserver_timedout = 0;
386 signal (SIGALRM, nameserver_lost);
387 alarm (4);
388 if (setjmp(env) == 0) {
389#endif
390 hostp = _XGethostbyaddr (address, addresslen, family, hparams);
391#ifdef SIGALRM
392 }
393 alarm (0);
394#endif
395 if (hostp != NULL)
396 addr = hostp->h_name;
397 else
398#ifdef HAVE_INET_NTOP
399 addr = inet_ntop (family, address, addrbuf, sizeof (addrbuf));
400#else
401 addr = inet_ntoa (saddr->sin_addr);
402#endif
403 break;
404 }
405
406#endif /* defined(TCPCONN) */
407
408
409 default:
410 return (NULL);
411 }
412
413
414 hostname = malloc (strlen (ciptr->transptr->TransName) +
415 (addr ? strlen (addr) : 0) + 2);
416 if (hostname)
417 {
418 strcpy (hostname, ciptr->transptr->TransName);
419 strcat (hostname, "/");
420 if (addr)
421 strcat (hostname, addr);
422 }
423 return (hostname);
424}
425
426#endif /* ICE_t */
427
428
429#if defined(WIN32) && defined(TCPCONN)
430int
431TRANS(WSAStartup) (void)
432{
433 static WSADATA wsadata;
434
435 prmsg (2,"WSAStartup()\n");
436
437 if (!wsadata.wVersion && WSAStartup(MAKEWORD(2,2), &wsadata))
438 return 1;
439 return 0;
440}
441#endif
442
443#ifdef TRANS_SERVER
444#include <sys/types.h>
445#include <sys/stat.h>
446#include <errno.h>
447
448#if !defined(S_IFLNK) && !defined(S_ISLNK)
449#undef lstat
450#define lstat(a,b) stat(a,b)
451#endif
452
453#define FAIL_IF_NOMODE 1
454#define FAIL_IF_NOT_ROOT 2
455#define WARN_NO_ACCESS 4
456
457/*
458 * We make the assumption that when the 'sticky' (t) bit is requested
459 * it's not save if the directory has non-root ownership or the sticky
460 * bit cannot be set and fail.
461 */
462static int
463trans_mkdir(const char *path, int mode)
464{
465 struct stat buf;
466
467 if (lstat(path, &buf) != 0) {
468 if (errno != ENOENT) {
469 prmsg(1, "mkdir: ERROR: (l)stat failed for %s (%d)\n",
470 path, errno);
471 return -1;
472 }
473 /* Dir doesn't exist. Try to create it */
474
475#if !defined(WIN32) && !defined(__CYGWIN__)
476 /*
477 * 'sticky' bit requested: assume application makes
478 * certain security implications. If effective user ID
479 * is != 0: fail as we may not be able to meet them.
480 */
481 if (geteuid() != 0) {
482 if (mode & 01000) {
483 prmsg(1, "mkdir: ERROR: euid != 0,"
484 "directory %s will not be created.\n",
485 path);
486#ifdef FAIL_HARD
487 return -1;
488#endif
489 } else {
490 prmsg(1, "mkdir: Cannot create %s with root ownership\n",
491 path);
492 }
493 }
494#endif
495
496#ifndef WIN32
497 if (mkdir(path, mode) == 0) {
498 if (chmod(path, mode)) {
499 prmsg(1, "mkdir: ERROR: Mode of %s should be set to %04o\n",
500 path, mode);
501#ifdef FAIL_HARD
502 return -1;
503#endif
504 }
505#else
506 if (mkdir(path) == 0) {
507#endif
508 } else {
509 prmsg(1, "mkdir: ERROR: Cannot create %s\n",
510 path);
511 return -1;
512 }
513
514 return 0;
515
516 } else {
517 if (S_ISDIR(buf.st_mode)) {
518 int updateOwner = 0;
519 int updateMode = 0;
520 int updatedOwner = 0;
521 int updatedMode = 0;
522 int status = 0;
523 /* Check if the directory's ownership is OK. */
524 if (buf.st_uid != 0)
525 updateOwner = 1;
526
527 /*
528 * Check if the directory's mode is OK. An exact match isn't
529 * required, just a mode that isn't more permissive than the
530 * one requested.
531 */
532 if ((~mode) & 0077 & buf.st_mode)
533 updateMode = 1;
534
535 /*
536 * If the directory is not writeable not everybody may
537 * be able to create sockets. Therefore warn if mode
538 * cannot be fixed.
539 */
540 if ((~buf.st_mode) & 0022 & mode) {
541 updateMode = 1;
542 status |= WARN_NO_ACCESS;
543 }
544
545 /*
546 * If 'sticky' bit is requested fail if owner isn't root
547 * as we assume the caller makes certain security implications
548 */
549 if (mode & 01000) {
550 status |= FAIL_IF_NOT_ROOT;
551 if (!(buf.st_mode & 01000)) {
552 status |= FAIL_IF_NOMODE;
553 updateMode = 1;
554 }
555 }
556
557#ifdef HAS_FCHOWN
558 /*
559 * If fchown(2) and fchmod(2) are available, try to correct the
560 * directory's owner and mode. Otherwise it isn't safe to attempt
561 * to do this.
562 */
563 if (updateMode || updateOwner) {
564 int fd = -1;
565 struct stat fbuf;
566 if ((fd = open(path, O_RDONLY)) != -1) {
567 if (fstat(fd, &fbuf) == -1) {
568 prmsg(1, "mkdir: ERROR: fstat failed for %s (%d)\n",
569 path, errno);
570 close(fd);
571 return -1;
572 }
573 /*
574 * Verify that we've opened the same directory as was
575 * checked above.
576 */
577 if (!S_ISDIR(fbuf.st_mode) ||
578 buf.st_dev != fbuf.st_dev ||
579 buf.st_ino != fbuf.st_ino) {
580 prmsg(1, "mkdir: ERROR: inode for %s changed\n",
581 path);
582 close(fd);
583 return -1;
584 }
585 if (updateOwner && fchown(fd, 0, 0) == 0)
586 updatedOwner = 1;
587 if (updateMode && fchmod(fd, mode) == 0)
588 updatedMode = 1;
589 close(fd);
590 }
591 }
592#endif
593
594 if (updateOwner && !updatedOwner) {
595#ifdef FAIL_HARD
596 if (status & FAIL_IF_NOT_ROOT) {
597 prmsg(1, "mkdir: ERROR: Owner of %s must be set to root\n",
598 path);
599 return -1;
600 }
601#endif
602#if !defined(__APPLE_CC__) && !defined(__CYGWIN__)
603 prmsg(1, "mkdir: Owner of %s should be set to root\n",
604 path);
605#endif
606 }
607
608 if (updateMode && !updatedMode) {
609#ifdef FAIL_HARD
610 if (status & FAIL_IF_NOMODE) {
611 prmsg(1, "mkdir: ERROR: Mode of %s must be set to %04o\n",
612 path, mode);
613 return -1;
614 }
615#endif
616 prmsg(1, "mkdir: Mode of %s should be set to %04o\n",
617 path, mode);
618 if (status & WARN_NO_ACCESS) {
619 prmsg(1, "mkdir: this may cause subsequent errors\n");
620 }
621 }
622 return 0;
623 }
624 return -1;
625 }
626
627 /* In all other cases, fail */
628 return -1;
629}
630
631#endif /* TRANS_SERVER */