Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 10:26:39

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 #ifdef X11_t
0066 
0067 /*
0068  * These values come from X.h and Xauth.h, and MUST match them. Some
0069  * of these values are also defined by the ChangeHost protocol message.
0070  */
0071 
0072 #define FamilyInternet      0   /* IPv4 */
0073 #define FamilyDECnet        1
0074 #define FamilyChaos     2
0075 #define FamilyInternet6     6
0076 #define FamilyAmoeba        33
0077 #define FamilyLocalHost     252
0078 #define FamilyKrb5Principal 253
0079 #define FamilyNetname       254
0080 #define FamilyLocal     256
0081 #define FamilyWild      65535
0082 
0083 /*
0084  * TRANS(ConvertAddress) converts a sockaddr based address to an
0085  * X authorization based address. Some of this is defined as part of
0086  * the ChangeHost protocol. The rest is just done in a consistent manner.
0087  */
0088 
0089 int
0090 TRANS(ConvertAddress)(int *familyp, int *addrlenp, Xtransaddr **addrp)
0091 
0092 {
0093 
0094     prmsg(2,"ConvertAddress(%d,%d,%p)\n",*familyp,*addrlenp,*addrp);
0095 
0096     switch( *familyp )
0097     {
0098 #if defined(TCPCONN)
0099     case AF_INET:
0100     {
0101     /*
0102      * Check for the BSD hack localhost address 127.0.0.1.
0103      * In this case, we are really FamilyLocal.
0104      */
0105 
0106     struct sockaddr_in saddr;
0107     int len = sizeof(saddr.sin_addr.s_addr);
0108     char *cp = (char *) &saddr.sin_addr.s_addr;
0109 
0110     memcpy (&saddr, *addrp, sizeof (struct sockaddr_in));
0111 
0112     if ((len == 4) && (cp[0] == 127) && (cp[1] == 0) &&
0113         (cp[2] == 0) && (cp[3] == 1))
0114     {
0115         *familyp=FamilyLocal;
0116     }
0117     else
0118     {
0119         *familyp=FamilyInternet;
0120         *addrlenp=len;
0121         memcpy(*addrp,&saddr.sin_addr,len);
0122     }
0123     break;
0124     }
0125 
0126 #if defined(IPv6) && defined(AF_INET6)
0127     case AF_INET6:
0128     {
0129     struct sockaddr_in6 saddr6;
0130 
0131     memcpy (&saddr6, *addrp, sizeof (struct sockaddr_in6));
0132 
0133     if (IN6_IS_ADDR_LOOPBACK(&saddr6.sin6_addr))
0134     {
0135         *familyp=FamilyLocal;
0136     }
0137     else if (IN6_IS_ADDR_V4MAPPED(&(saddr6.sin6_addr))) {
0138         char *cp = (char *) &saddr6.sin6_addr.s6_addr[12];
0139 
0140         if ((cp[0] == 127) && (cp[1] == 0) &&
0141           (cp[2] == 0) && (cp[3] == 1))
0142         {
0143         *familyp=FamilyLocal;
0144         }
0145         else
0146         {
0147         *familyp=FamilyInternet;
0148         *addrlenp = sizeof (struct in_addr);
0149         memcpy(*addrp,cp,*addrlenp);
0150         }
0151     }
0152     else
0153     {
0154         *familyp=FamilyInternet6;
0155         *addrlenp=sizeof(saddr6.sin6_addr);
0156         memcpy(*addrp,&saddr6.sin6_addr,sizeof(saddr6.sin6_addr));
0157     }
0158     break;
0159     }
0160 #endif /* IPv6 */
0161 #endif /* defined(TCPCONN) */
0162 
0163 
0164 #if defined(UNIXCONN) || defined(LOCALCONN)
0165     case AF_UNIX:
0166     {
0167     *familyp=FamilyLocal;
0168     break;
0169     }
0170 #endif /* defined(UNIXCONN) || defined(LOCALCONN) */
0171 
0172 
0173     default:
0174     prmsg(1,"ConvertAddress: Unknown family type %d\n",
0175           *familyp);
0176     return -1;
0177     }
0178 
0179 
0180     if (*familyp == FamilyLocal)
0181     {
0182     /*
0183      * In the case of a local connection, we need to get the
0184      * host name for authentication.
0185      */
0186 
0187     char hostnamebuf[256];
0188     int len = TRANS(GetHostname) (hostnamebuf, sizeof hostnamebuf);
0189 
0190     if (len > 0) {
0191         if (*addrp && *addrlenp < (len + 1))
0192         {
0193         free (*addrp);
0194         *addrp = NULL;
0195         }
0196         if (!*addrp)
0197         *addrp = malloc (len + 1);
0198         if (*addrp) {
0199         strcpy ((char *) *addrp, hostnamebuf);
0200         *addrlenp = len;
0201         } else {
0202         *addrlenp = 0;
0203         }
0204     }
0205     else
0206     {
0207         if (*addrp)
0208         free (*addrp);
0209         *addrp = NULL;
0210         *addrlenp = 0;
0211     }
0212     }
0213 
0214     return 0;
0215 }
0216 
0217 #endif /* X11_t */
0218 
0219 #ifdef ICE_t
0220 
0221 /* Needed for _XGethostbyaddr usage in TRANS(GetPeerNetworkId) */
0222 # if defined(TCPCONN) || defined(UNIXCONN)
0223 #  define X_INCLUDE_NETDB_H
0224 #  define XOS_USE_NO_LOCKING
0225 #  include <X11/Xos_r.h>
0226 # endif
0227 
0228 #include <signal.h>
0229 
0230 char *
0231 TRANS(GetMyNetworkId) (XtransConnInfo ciptr)
0232 
0233 {
0234     int     family = ciptr->family;
0235     char    *addr = ciptr->addr;
0236     char    hostnamebuf[256];
0237     char    *networkId = NULL;
0238     const char  *transName = ciptr->transptr->TransName;
0239 
0240     if (gethostname (hostnamebuf, sizeof (hostnamebuf)) < 0)
0241     {
0242     return (NULL);
0243     }
0244 
0245     switch (family)
0246     {
0247 #if defined(UNIXCONN) || defined(LOCALCONN)
0248     case AF_UNIX:
0249     {
0250     struct sockaddr_un *saddr = (struct sockaddr_un *) addr;
0251     networkId = malloc (3 + strlen (transName) +
0252         strlen (hostnamebuf) + strlen (saddr->sun_path));
0253     if (networkId != NULL)
0254         sprintf (networkId, "%s/%s:%s", transName,
0255              hostnamebuf, saddr->sun_path);
0256     break;
0257     }
0258 #endif /* defined(UNIXCONN) || defined(LOCALCONN) */
0259 
0260 #if defined(TCPCONN)
0261     case AF_INET:
0262 #if defined(IPv6) && defined(AF_INET6)
0263     case AF_INET6:
0264 #endif
0265     {
0266     struct sockaddr_in *saddr = (struct sockaddr_in *) addr;
0267 #if defined(IPv6) && defined(AF_INET6)
0268     struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *) addr;
0269 #endif
0270     int portnum;
0271     char portnumbuf[10];
0272 
0273 
0274 #if defined(IPv6) && defined(AF_INET6)
0275     if (family == AF_INET6)
0276         portnum = ntohs (saddr6->sin6_port);
0277     else
0278 #endif
0279         portnum = ntohs (saddr->sin_port);
0280 
0281     snprintf (portnumbuf, sizeof(portnumbuf), "%d", portnum);
0282     networkId = malloc (3 + strlen (transName) +
0283         strlen (hostnamebuf) + strlen (portnumbuf));
0284     if (networkId != NULL)
0285         sprintf (networkId, "%s/%s:%s", transName, hostnamebuf, portnumbuf);
0286     break;
0287     }
0288 #endif /* defined(TCPCONN) */
0289 
0290 
0291     default:
0292     break;
0293     }
0294 
0295     return (networkId);
0296 }
0297 
0298 #include <setjmp.h>
0299 static jmp_buf env;
0300 
0301 #ifdef SIGALRM
0302 static volatile int nameserver_timedout = 0;
0303 
0304 static void
0305 nameserver_lost(int sig _X_UNUSED)
0306 {
0307   nameserver_timedout = 1;
0308   longjmp (env, -1);
0309   /* NOTREACHED */
0310 }
0311 #endif /* SIGALARM */
0312 
0313 
0314 char *
0315 TRANS(GetPeerNetworkId) (XtransConnInfo ciptr)
0316 
0317 {
0318     int     family = ciptr->family;
0319     char    *peer_addr = ciptr->peeraddr;
0320     char    *hostname;
0321     char    addrbuf[256];
0322     const char  *addr = NULL;
0323 
0324     switch (family)
0325     {
0326     case AF_UNSPEC:
0327 #if defined(UNIXCONN) || defined(LOCALCONN)
0328     case AF_UNIX:
0329     {
0330     if (gethostname (addrbuf, sizeof (addrbuf)) == 0)
0331         addr = addrbuf;
0332     break;
0333     }
0334 #endif /* defined(UNIXCONN) || defined(LOCALCONN) */
0335 
0336 #if defined(TCPCONN)
0337     case AF_INET:
0338 #if defined(IPv6) && defined(AF_INET6)
0339     case AF_INET6:
0340 #endif
0341     {
0342     struct sockaddr_in *saddr = (struct sockaddr_in *) peer_addr;
0343 #if defined(IPv6) && defined(AF_INET6)
0344     struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *) peer_addr;
0345 #endif
0346     char *address;
0347     int addresslen;
0348 #ifdef XTHREADS_NEEDS_BYNAMEPARAMS
0349     _Xgethostbynameparams hparams;
0350 #endif
0351     struct hostent * volatile hostp = NULL;
0352 
0353 #if defined(IPv6) && defined(AF_INET6)
0354     if (family == AF_INET6)
0355     {
0356         address = (char *) &saddr6->sin6_addr;
0357         addresslen = sizeof (saddr6->sin6_addr);
0358     }
0359     else
0360 #endif
0361     {
0362         address = (char *) &saddr->sin_addr;
0363         addresslen = sizeof (saddr->sin_addr);
0364     }
0365 
0366 #ifdef SIGALRM
0367     /*
0368      * gethostbyaddr can take a LONG time if the host does not exist.
0369      * Assume that if it does not respond in NAMESERVER_TIMEOUT seconds
0370      * that something is wrong and do not make the user wait.
0371      * gethostbyaddr will continue after a signal, so we have to
0372      * jump out of it.
0373      */
0374 
0375     nameserver_timedout = 0;
0376     signal (SIGALRM, nameserver_lost);
0377     alarm (4);
0378     if (setjmp(env) == 0) {
0379 #endif
0380         hostp = _XGethostbyaddr (address, addresslen, family, hparams);
0381 #ifdef SIGALRM
0382     }
0383     alarm (0);
0384 #endif
0385     if (hostp != NULL)
0386       addr = hostp->h_name;
0387     else
0388 #if defined(IPv6) && defined(AF_INET6)
0389       addr = inet_ntop (family, address, addrbuf, sizeof (addrbuf));
0390 #else
0391       addr = inet_ntoa (saddr->sin_addr);
0392 #endif
0393     break;
0394     }
0395 
0396 #endif /* defined(TCPCONN) */
0397 
0398 
0399     default:
0400     return (NULL);
0401     }
0402 
0403 
0404     hostname = malloc (strlen (ciptr->transptr->TransName) +
0405                        (addr ? strlen (addr) : 0) + 2);
0406     if (hostname)
0407     {
0408     strcpy (hostname, ciptr->transptr->TransName);
0409     strcat (hostname, "/");
0410     if (addr)
0411         strcat (hostname, addr);
0412     }
0413     return (hostname);
0414 }
0415 
0416 #endif /* ICE_t */
0417 
0418 
0419 #if defined(WIN32) && defined(TCPCONN)
0420 int
0421 TRANS(WSAStartup) (void)
0422 {
0423     static WSADATA wsadata;
0424 
0425     prmsg (2,"WSAStartup()\n");
0426 
0427     if (!wsadata.wVersion && WSAStartup(MAKEWORD(2,2), &wsadata))
0428         return 1;
0429     return 0;
0430 }
0431 #endif
0432 
0433 #ifdef TRANS_SERVER
0434 #include <sys/types.h>
0435 #include <sys/stat.h>
0436 #include <errno.h>
0437 
0438 #if !defined(S_IFLNK) && !defined(S_ISLNK)
0439 #undef lstat
0440 #define lstat(a,b) stat(a,b)
0441 #endif
0442 
0443 #define FAIL_IF_NOMODE  1
0444 #define FAIL_IF_NOT_ROOT 2
0445 #define WARN_NO_ACCESS 4
0446 
0447 /*
0448  * We make the assumption that when the 'sticky' (t) bit is requested
0449  * it's not save if the directory has non-root ownership or the sticky
0450  * bit cannot be set and fail.
0451  */
0452 static int
0453 trans_mkdir(const char *path, int mode)
0454 {
0455     struct stat buf;
0456 
0457     if (lstat(path, &buf) != 0) {
0458     if (errno != ENOENT) {
0459         prmsg(1, "mkdir: ERROR: (l)stat failed for %s (%d)\n",
0460           path, errno);
0461         return -1;
0462     }
0463     /* Dir doesn't exist. Try to create it */
0464 
0465 #if !defined(WIN32) && !defined(__CYGWIN__)
0466     /*
0467      * 'sticky' bit requested: assume application makes
0468      * certain security implications. If effective user ID
0469      * is != 0: fail as we may not be able to meet them.
0470      */
0471     if (geteuid() != 0) {
0472         if (mode & 01000) {
0473         prmsg(1, "mkdir: ERROR: euid != 0,"
0474               "directory %s will not be created.\n",
0475               path);
0476 #ifdef FAIL_HARD
0477         return -1;
0478 #endif
0479         } else {
0480         prmsg(1, "mkdir: Cannot create %s with root ownership\n",
0481               path);
0482         }
0483     }
0484 #endif
0485 
0486 #ifndef WIN32
0487     if (mkdir(path, mode) == 0) {
0488         if (chmod(path, mode)) {
0489         prmsg(1, "mkdir: ERROR: Mode of %s should be set to %04o\n",
0490               path, mode);
0491 #ifdef FAIL_HARD
0492         return -1;
0493 #endif
0494         }
0495 #else
0496     if (mkdir(path) == 0) {
0497 #endif
0498     } else {
0499         prmsg(1, "mkdir: ERROR: Cannot create %s\n",
0500           path);
0501         return -1;
0502     }
0503 
0504     return 0;
0505 
0506     } else {
0507     if (S_ISDIR(buf.st_mode)) {
0508         int updateOwner = 0;
0509         int updateMode = 0;
0510         int updatedOwner = 0;
0511         int updatedMode = 0;
0512         int status = 0;
0513         /* Check if the directory's ownership is OK. */
0514         if (buf.st_uid != 0)
0515         updateOwner = 1;
0516 
0517         /*
0518          * Check if the directory's mode is OK.  An exact match isn't
0519          * required, just a mode that isn't more permissive than the
0520          * one requested.
0521          */
0522         if ((~mode) & 0077 & buf.st_mode)
0523         updateMode = 1;
0524 
0525         /*
0526          * If the directory is not writeable not everybody may
0527          * be able to create sockets. Therefore warn if mode
0528          * cannot be fixed.
0529          */
0530         if ((~buf.st_mode) & 0022 & mode) {
0531         updateMode = 1;
0532         status |= WARN_NO_ACCESS;
0533         }
0534 
0535         /*
0536          * If 'sticky' bit is requested fail if owner isn't root
0537          * as we assume the caller makes certain security implications
0538          */
0539         if (mode & 01000) {
0540         status |= FAIL_IF_NOT_ROOT;
0541         if (!(buf.st_mode & 01000)) {
0542             status |= FAIL_IF_NOMODE;
0543             updateMode = 1;
0544         }
0545         }
0546 
0547 #ifdef HAS_FCHOWN
0548         /*
0549          * If fchown(2) and fchmod(2) are available, try to correct the
0550          * directory's owner and mode.  Otherwise it isn't safe to attempt
0551          * to do this.
0552          */
0553         if (updateMode || updateOwner) {
0554         int fd = -1;
0555         struct stat fbuf;
0556         if ((fd = open(path, O_RDONLY)) != -1) {
0557             if (fstat(fd, &fbuf) == -1) {
0558             prmsg(1, "mkdir: ERROR: fstat failed for %s (%d)\n",
0559                   path, errno);
0560             close(fd);
0561             return -1;
0562             }
0563             /*
0564              * Verify that we've opened the same directory as was
0565              * checked above.
0566              */
0567             if (!S_ISDIR(fbuf.st_mode) ||
0568             buf.st_dev != fbuf.st_dev ||
0569             buf.st_ino != fbuf.st_ino) {
0570             prmsg(1, "mkdir: ERROR: inode for %s changed\n",
0571                   path);
0572             close(fd);
0573             return -1;
0574             }
0575             if (updateOwner && fchown(fd, 0, 0) == 0)
0576             updatedOwner = 1;
0577             if (updateMode && fchmod(fd, mode) == 0)
0578             updatedMode = 1;
0579             close(fd);
0580         }
0581         }
0582 #endif
0583 
0584         if (updateOwner && !updatedOwner) {
0585 #ifdef FAIL_HARD
0586         if (status & FAIL_IF_NOT_ROOT) {
0587             prmsg(1, "mkdir: ERROR: Owner of %s must be set to root\n",
0588               path);
0589             return -1;
0590         }
0591 #endif
0592 #if !defined(__APPLE_CC__) && !defined(__CYGWIN__)
0593         prmsg(1, "mkdir: Owner of %s should be set to root\n",
0594               path);
0595 #endif
0596         }
0597 
0598         if (updateMode && !updatedMode) {
0599 #ifdef FAIL_HARD
0600         if (status & FAIL_IF_NOMODE) {
0601             prmsg(1, "mkdir: ERROR: Mode of %s must be set to %04o\n",
0602               path, mode);
0603             return -1;
0604         }
0605 #endif
0606         prmsg(1, "mkdir: Mode of %s should be set to %04o\n",
0607               path, mode);
0608         if (status & WARN_NO_ACCESS) {
0609             prmsg(1, "mkdir: this may cause subsequent errors\n");
0610         }
0611         }
0612         return 0;
0613     }
0614     return -1;
0615     }
0616 
0617     /* In all other cases, fail */
0618     return -1;
0619 }
0620 
0621 #endif /* TRANS_SERVER */