Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-12 09:12:48

0001 /*
0002 
0003 Copyright 1993, 1994, 1998  The Open Group
0004 
0005 Permission to use, copy, modify, distribute, and sell this software and its
0006 documentation for any purpose is hereby granted without fee, provided that
0007 the above copyright notice appear in all copies and that both that
0008 copyright notice and this permission notice appear in supporting
0009 documentation.
0010 
0011 The above copyright notice and this permission notice shall be included
0012 in all copies or substantial portions of the Software.
0013 
0014 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
0015 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
0016 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
0017 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020 OTHER DEALINGS IN THE SOFTWARE.
0021 
0022 Except as contained in this notice, the name of The Open Group shall
0023 not be used in advertising or otherwise to promote the sale, use or
0024 other dealings in this Software without prior written authorization
0025 from The Open Group.
0026 
0027  * Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA
0028  *
0029  * All Rights Reserved
0030  *
0031  * Permission to use, copy, modify, and distribute this software and its
0032  * documentation for any purpose and without fee is hereby granted, provided
0033  * that the above copyright notice appear in all copies and that both that
0034  * copyright notice and this permission notice appear in supporting
0035  * documentation, and that the name NCR not be used in advertising
0036  * or publicity pertaining to distribution of the software without specific,
0037  * written prior permission.  NCR makes no representations about the
0038  * suitability of this software for any purpose.  It is provided "as is"
0039  * without express or implied warranty.
0040  *
0041  * NCRS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
0042  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
0043  * NO EVENT SHALL NCR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
0044  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
0045  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
0046  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
0047  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
0048  */
0049 
0050 /*
0051  * These are some utility functions created for convenience or to provide
0052  * an interface that is similar to an existing interface. These are built
0053  * only using the Transport Independent API, and have no knowledge of
0054  * the internal implementation.
0055  */
0056 
0057 #ifdef XTHREADS
0058 #include <X11/Xthreads.h>
0059 #endif
0060 #ifdef WIN32
0061 #include <X11/Xlibint.h>
0062 #include <X11/Xwinsock.h>
0063 #endif
0064 
0065 #if defined(IPv6) && !defined(AF_INET6)
0066 #error "Cannot build IPv6 support without AF_INET6"
0067 #endif
0068 
0069 /* Temporary workaround for consumers whose configure scripts were
0070    generated with pre-1.6 versions of xtrans.m4 */
0071 #if defined(IPv6) && !defined(HAVE_INET_NTOP)
0072 #define HAVE_INET_NTOP
0073 #endif
0074 
0075 #ifdef X11_t
0076 
0077 /*
0078  * These values come from X.h and Xauth.h, and MUST match them. Some
0079  * of these values are also defined by the ChangeHost protocol message.
0080  */
0081 
0082 #define FamilyInternet      0   /* IPv4 */
0083 #define FamilyDECnet        1
0084 #define FamilyChaos     2
0085 #define FamilyInternet6     6
0086 #define FamilyAmoeba        33
0087 #define FamilyLocalHost     252
0088 #define FamilyKrb5Principal 253
0089 #define FamilyNetname       254
0090 #define FamilyLocal     256
0091 #define FamilyWild      65535
0092 
0093 /*
0094  * TRANS(ConvertAddress) converts a sockaddr based address to an
0095  * X authorization based address. Some of this is defined as part of
0096  * the ChangeHost protocol. The rest is just done in a consistent manner.
0097  */
0098 
0099 int
0100 TRANS(ConvertAddress)(int *familyp, int *addrlenp, Xtransaddr **addrp)
0101 
0102 {
0103 
0104     prmsg(2,"ConvertAddress(%d,%d,%p)\n",*familyp,*addrlenp,*addrp);
0105 
0106     switch( *familyp )
0107     {
0108 #if defined(TCPCONN)
0109     case AF_INET:
0110     {
0111     /*
0112      * Check for the BSD hack localhost address 127.0.0.1.
0113      * In this case, we are really FamilyLocal.
0114      */
0115 
0116     struct sockaddr_in saddr;
0117     int len = sizeof(saddr.sin_addr.s_addr);
0118     char *cp = (char *) &saddr.sin_addr.s_addr;
0119 
0120     memcpy (&saddr, *addrp, sizeof (struct sockaddr_in));
0121 
0122     if ((len == 4) && (cp[0] == 127) && (cp[1] == 0) &&
0123         (cp[2] == 0) && (cp[3] == 1))
0124     {
0125         *familyp=FamilyLocal;
0126     }
0127     else
0128     {
0129         *familyp=FamilyInternet;
0130         *addrlenp=len;
0131         memcpy(*addrp,&saddr.sin_addr,len);
0132     }
0133     break;
0134     }
0135 
0136 #ifdef IPv6
0137     case AF_INET6:
0138     {
0139     struct sockaddr_in6 saddr6;
0140 
0141     memcpy (&saddr6, *addrp, sizeof (struct sockaddr_in6));
0142 
0143     if (IN6_IS_ADDR_LOOPBACK(&saddr6.sin6_addr))
0144     {
0145         *familyp=FamilyLocal;
0146     }
0147     else if (IN6_IS_ADDR_V4MAPPED(&(saddr6.sin6_addr))) {
0148         char *cp = (char *) &saddr6.sin6_addr.s6_addr[12];
0149 
0150         if ((cp[0] == 127) && (cp[1] == 0) &&
0151           (cp[2] == 0) && (cp[3] == 1))
0152         {
0153         *familyp=FamilyLocal;
0154         }
0155         else
0156         {
0157         *familyp=FamilyInternet;
0158         *addrlenp = sizeof (struct in_addr);
0159         memcpy(*addrp,cp,*addrlenp);
0160         }
0161     }
0162     else
0163     {
0164         *familyp=FamilyInternet6;
0165         *addrlenp=sizeof(saddr6.sin6_addr);
0166         memcpy(*addrp,&saddr6.sin6_addr,sizeof(saddr6.sin6_addr));
0167     }
0168     break;
0169     }
0170 #endif /* IPv6 */
0171 #endif /* defined(TCPCONN) */
0172 
0173 
0174 #if defined(UNIXCONN) || defined(LOCALCONN)
0175     case AF_UNIX:
0176     {
0177     *familyp=FamilyLocal;
0178     break;
0179     }
0180 #endif /* defined(UNIXCONN) || defined(LOCALCONN) */
0181 
0182 
0183     default:
0184     prmsg(1,"ConvertAddress: Unknown family type %d\n",
0185           *familyp);
0186     return -1;
0187     }
0188 
0189 
0190     if (*familyp == FamilyLocal)
0191     {
0192     /*
0193      * In the case of a local connection, we need to get the
0194      * host name for authentication.
0195      */
0196 
0197     char hostnamebuf[256];
0198     int len = TRANS(GetHostname) (hostnamebuf, sizeof hostnamebuf);
0199 
0200     if (len > 0) {
0201         if (*addrp && *addrlenp < (len + 1))
0202         {
0203         free (*addrp);
0204         *addrp = NULL;
0205         }
0206         if (!*addrp)
0207         *addrp = malloc (len + 1);
0208         if (*addrp) {
0209         strcpy ((char *) *addrp, hostnamebuf);
0210         *addrlenp = len;
0211         } else {
0212         *addrlenp = 0;
0213         }
0214     }
0215     else
0216     {
0217         if (*addrp)
0218         free (*addrp);
0219         *addrp = NULL;
0220         *addrlenp = 0;
0221     }
0222     }
0223 
0224     return 0;
0225 }
0226 
0227 #endif /* X11_t */
0228 
0229 #ifdef ICE_t
0230 
0231 /* Needed for _XGethostbyaddr usage in TRANS(GetPeerNetworkId) */
0232 # if defined(TCPCONN) || defined(UNIXCONN)
0233 #  define X_INCLUDE_NETDB_H
0234 #  define XOS_USE_NO_LOCKING
0235 #  include <X11/Xos_r.h>
0236 # endif
0237 
0238 #include <signal.h>
0239 
0240 char *
0241 TRANS(GetMyNetworkId) (XtransConnInfo ciptr)
0242 
0243 {
0244     int     family = ciptr->family;
0245     char    *addr = ciptr->addr;
0246     char    hostnamebuf[256];
0247     char    *networkId = NULL;
0248     const char  *transName = ciptr->transptr->TransName;
0249 
0250     if (gethostname (hostnamebuf, sizeof (hostnamebuf)) < 0)
0251     {
0252     return (NULL);
0253     }
0254 
0255     switch (family)
0256     {
0257 #if defined(UNIXCONN) || defined(LOCALCONN)
0258     case AF_UNIX:
0259     {
0260     struct sockaddr_un *saddr = (struct sockaddr_un *) addr;
0261     networkId = malloc (3 + strlen (transName) +
0262         strlen (hostnamebuf) + strlen (saddr->sun_path));
0263     if (networkId != NULL)
0264         sprintf (networkId, "%s/%s:%s", transName,
0265              hostnamebuf, saddr->sun_path);
0266     break;
0267     }
0268 #endif /* defined(UNIXCONN) || defined(LOCALCONN) */
0269 
0270 #if defined(TCPCONN)
0271     case AF_INET:
0272 #ifdef IPv6
0273     case AF_INET6:
0274 #endif
0275     {
0276     struct sockaddr_in *saddr = (struct sockaddr_in *) addr;
0277 #ifdef IPv6
0278     struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *) addr;
0279 #endif
0280     int portnum;
0281     char portnumbuf[10];
0282 
0283 
0284 #ifdef IPv6
0285     if (family == AF_INET6)
0286         portnum = ntohs (saddr6->sin6_port);
0287     else
0288 #endif
0289         portnum = ntohs (saddr->sin_port);
0290 
0291     snprintf (portnumbuf, sizeof(portnumbuf), "%d", portnum);
0292     networkId = malloc (3 + strlen (transName) +
0293         strlen (hostnamebuf) + strlen (portnumbuf));
0294     if (networkId != NULL)
0295         sprintf (networkId, "%s/%s:%s", transName, hostnamebuf, portnumbuf);
0296     break;
0297     }
0298 #endif /* defined(TCPCONN) */
0299 
0300 
0301     default:
0302     break;
0303     }
0304 
0305     return (networkId);
0306 }
0307 
0308 #include <setjmp.h>
0309 static jmp_buf env;
0310 
0311 #ifdef SIGALRM
0312 static volatile int nameserver_timedout = 0;
0313 
0314 static void
0315 nameserver_lost(int sig _X_UNUSED)
0316 {
0317   nameserver_timedout = 1;
0318   longjmp (env, -1);
0319   /* NOTREACHED */
0320 }
0321 #endif /* SIGALARM */
0322 
0323 
0324 char *
0325 TRANS(GetPeerNetworkId) (XtransConnInfo ciptr)
0326 
0327 {
0328     int     family = ciptr->family;
0329     char    *peer_addr = ciptr->peeraddr;
0330     char    *hostname;
0331     char    addrbuf[256];
0332     const char  *addr = NULL;
0333 
0334     switch (family)
0335     {
0336     case AF_UNSPEC:
0337 #if defined(UNIXCONN) || defined(LOCALCONN)
0338     case AF_UNIX:
0339     {
0340     if (gethostname (addrbuf, sizeof (addrbuf)) == 0)
0341         addr = addrbuf;
0342     break;
0343     }
0344 #endif /* defined(UNIXCONN) || defined(LOCALCONN) */
0345 
0346 #if defined(TCPCONN)
0347     case AF_INET:
0348 #ifdef IPv6
0349     case AF_INET6:
0350 #endif
0351     {
0352     struct sockaddr_in *saddr = (struct sockaddr_in *) peer_addr;
0353 #ifdef IPv6
0354     struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *) peer_addr;
0355 #endif
0356     char *address;
0357     int addresslen;
0358 #ifdef XTHREADS_NEEDS_BYNAMEPARAMS
0359     _Xgethostbynameparams hparams;
0360 #endif
0361     struct hostent * volatile hostp = NULL;
0362 
0363 #ifdef IPv6
0364     if (family == AF_INET6)
0365     {
0366         address = (char *) &saddr6->sin6_addr;
0367         addresslen = sizeof (saddr6->sin6_addr);
0368     }
0369     else
0370 #endif
0371     {
0372         address = (char *) &saddr->sin_addr;
0373         addresslen = sizeof (saddr->sin_addr);
0374     }
0375 
0376 #ifdef SIGALRM
0377     /*
0378      * gethostbyaddr can take a LONG time if the host does not exist.
0379      * Assume that if it does not respond in NAMESERVER_TIMEOUT seconds
0380      * that something is wrong and do not make the user wait.
0381      * gethostbyaddr will continue after a signal, so we have to
0382      * jump out of it.
0383      */
0384 
0385     nameserver_timedout = 0;
0386     signal (SIGALRM, nameserver_lost);
0387     alarm (4);
0388     if (setjmp(env) == 0) {
0389 #endif
0390         hostp = _XGethostbyaddr (address, addresslen, family, hparams);
0391 #ifdef SIGALRM
0392     }
0393     alarm (0);
0394 #endif
0395     if (hostp != NULL)
0396       addr = hostp->h_name;
0397     else
0398 #ifdef HAVE_INET_NTOP
0399       addr = inet_ntop (family, address, addrbuf, sizeof (addrbuf));
0400 #else
0401       addr = inet_ntoa (saddr->sin_addr);
0402 #endif
0403     break;
0404     }
0405 
0406 #endif /* defined(TCPCONN) */
0407 
0408 
0409     default:
0410     return (NULL);
0411     }
0412 
0413 
0414     hostname = malloc (strlen (ciptr->transptr->TransName) +
0415                        (addr ? strlen (addr) : 0) + 2);
0416     if (hostname)
0417     {
0418     strcpy (hostname, ciptr->transptr->TransName);
0419     strcat (hostname, "/");
0420     if (addr)
0421         strcat (hostname, addr);
0422     }
0423     return (hostname);
0424 }
0425 
0426 #endif /* ICE_t */
0427 
0428 
0429 #if defined(WIN32) && defined(TCPCONN)
0430 int
0431 TRANS(WSAStartup) (void)
0432 {
0433     static WSADATA wsadata;
0434 
0435     prmsg (2,"WSAStartup()\n");
0436 
0437     if (!wsadata.wVersion && WSAStartup(MAKEWORD(2,2), &wsadata))
0438         return 1;
0439     return 0;
0440 }
0441 #endif
0442 
0443 #ifdef TRANS_SERVER
0444 #include <sys/types.h>
0445 #include <sys/stat.h>
0446 #include <errno.h>
0447 
0448 #if !defined(S_IFLNK) && !defined(S_ISLNK)
0449 #undef lstat
0450 #define lstat(a,b) stat(a,b)
0451 #endif
0452 
0453 #define FAIL_IF_NOMODE  1
0454 #define FAIL_IF_NOT_ROOT 2
0455 #define WARN_NO_ACCESS 4
0456 
0457 /*
0458  * We make the assumption that when the 'sticky' (t) bit is requested
0459  * it's not save if the directory has non-root ownership or the sticky
0460  * bit cannot be set and fail.
0461  */
0462 static int
0463 trans_mkdir(const char *path, int mode)
0464 {
0465     struct stat buf;
0466 
0467     if (lstat(path, &buf) != 0) {
0468     if (errno != ENOENT) {
0469         prmsg(1, "mkdir: ERROR: (l)stat failed for %s (%d)\n",
0470           path, errno);
0471         return -1;
0472     }
0473     /* Dir doesn't exist. Try to create it */
0474 
0475 #if !defined(WIN32) && !defined(__CYGWIN__)
0476     /*
0477      * 'sticky' bit requested: assume application makes
0478      * certain security implications. If effective user ID
0479      * is != 0: fail as we may not be able to meet them.
0480      */
0481     if (geteuid() != 0) {
0482         if (mode & 01000) {
0483         prmsg(1, "mkdir: ERROR: euid != 0,"
0484               "directory %s will not be created.\n",
0485               path);
0486 #ifdef FAIL_HARD
0487         return -1;
0488 #endif
0489         } else {
0490         prmsg(1, "mkdir: Cannot create %s with root ownership\n",
0491               path);
0492         }
0493     }
0494 #endif
0495 
0496 #ifndef WIN32
0497     if (mkdir(path, mode) == 0) {
0498         if (chmod(path, mode)) {
0499         prmsg(1, "mkdir: ERROR: Mode of %s should be set to %04o\n",
0500               path, mode);
0501 #ifdef FAIL_HARD
0502         return -1;
0503 #endif
0504         }
0505 #else
0506     if (mkdir(path) == 0) {
0507 #endif
0508     } else {
0509         prmsg(1, "mkdir: ERROR: Cannot create %s\n",
0510           path);
0511         return -1;
0512     }
0513 
0514     return 0;
0515 
0516     } else {
0517     if (S_ISDIR(buf.st_mode)) {
0518         int updateOwner = 0;
0519         int updateMode = 0;
0520         int updatedOwner = 0;
0521         int updatedMode = 0;
0522         int status = 0;
0523         /* Check if the directory's ownership is OK. */
0524         if (buf.st_uid != 0)
0525         updateOwner = 1;
0526 
0527         /*
0528          * Check if the directory's mode is OK.  An exact match isn't
0529          * required, just a mode that isn't more permissive than the
0530          * one requested.
0531          */
0532         if ((~mode) & 0077 & buf.st_mode)
0533         updateMode = 1;
0534 
0535         /*
0536          * If the directory is not writeable not everybody may
0537          * be able to create sockets. Therefore warn if mode
0538          * cannot be fixed.
0539          */
0540         if ((~buf.st_mode) & 0022 & mode) {
0541         updateMode = 1;
0542         status |= WARN_NO_ACCESS;
0543         }
0544 
0545         /*
0546          * If 'sticky' bit is requested fail if owner isn't root
0547          * as we assume the caller makes certain security implications
0548          */
0549         if (mode & 01000) {
0550         status |= FAIL_IF_NOT_ROOT;
0551         if (!(buf.st_mode & 01000)) {
0552             status |= FAIL_IF_NOMODE;
0553             updateMode = 1;
0554         }
0555         }
0556 
0557 #ifdef HAS_FCHOWN
0558         /*
0559          * If fchown(2) and fchmod(2) are available, try to correct the
0560          * directory's owner and mode.  Otherwise it isn't safe to attempt
0561          * to do this.
0562          */
0563         if (updateMode || updateOwner) {
0564         int fd = -1;
0565         struct stat fbuf;
0566         if ((fd = open(path, O_RDONLY)) != -1) {
0567             if (fstat(fd, &fbuf) == -1) {
0568             prmsg(1, "mkdir: ERROR: fstat failed for %s (%d)\n",
0569                   path, errno);
0570             close(fd);
0571             return -1;
0572             }
0573             /*
0574              * Verify that we've opened the same directory as was
0575              * checked above.
0576              */
0577             if (!S_ISDIR(fbuf.st_mode) ||
0578             buf.st_dev != fbuf.st_dev ||
0579             buf.st_ino != fbuf.st_ino) {
0580             prmsg(1, "mkdir: ERROR: inode for %s changed\n",
0581                   path);
0582             close(fd);
0583             return -1;
0584             }
0585             if (updateOwner && fchown(fd, 0, 0) == 0)
0586             updatedOwner = 1;
0587             if (updateMode && fchmod(fd, mode) == 0)
0588             updatedMode = 1;
0589             close(fd);
0590         }
0591         }
0592 #endif
0593 
0594         if (updateOwner && !updatedOwner) {
0595 #ifdef FAIL_HARD
0596         if (status & FAIL_IF_NOT_ROOT) {
0597             prmsg(1, "mkdir: ERROR: Owner of %s must be set to root\n",
0598               path);
0599             return -1;
0600         }
0601 #endif
0602 #if !defined(__APPLE_CC__) && !defined(__CYGWIN__)
0603         prmsg(1, "mkdir: Owner of %s should be set to root\n",
0604               path);
0605 #endif
0606         }
0607 
0608         if (updateMode && !updatedMode) {
0609 #ifdef FAIL_HARD
0610         if (status & FAIL_IF_NOMODE) {
0611             prmsg(1, "mkdir: ERROR: Mode of %s must be set to %04o\n",
0612               path, mode);
0613             return -1;
0614         }
0615 #endif
0616         prmsg(1, "mkdir: Mode of %s should be set to %04o\n",
0617               path, mode);
0618         if (status & WARN_NO_ACCESS) {
0619             prmsg(1, "mkdir: this may cause subsequent errors\n");
0620         }
0621         }
0622         return 0;
0623     }
0624     return -1;
0625     }
0626 
0627     /* In all other cases, fail */
0628     return -1;
0629 }
0630 
0631 #endif /* TRANS_SERVER */