aboutsummaryrefslogtreecommitdiff
path: root/X11/xtrans/Xtransutil.c
diff options
context:
space:
mode:
Diffstat (limited to 'X11/xtrans/Xtransutil.c')
-rw-r--r--X11/xtrans/Xtransutil.c642
1 files changed, 642 insertions, 0 deletions
diff --git a/X11/xtrans/Xtransutil.c b/X11/xtrans/Xtransutil.c
new file mode 100644
index 000000000..0f7c7b2a5
--- /dev/null
+++ b/X11/xtrans/Xtransutil.c
@@ -0,0 +1,642 @@
+/*
+
+Copyright 1993, 1994, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+ * Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA
+ *
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name NCR not be used in advertising
+ * or publicity pertaining to distribution of the software without specific,
+ * written prior permission. NCR makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * NCRS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NCR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * These are some utility functions created for convenience or to provide
+ * an interface that is similar to an existing interface. These are built
+ * only using the Transport Independant API, and have no knowledge of
+ * the internal implementation.
+ */
+
+#ifdef XTHREADS
+#include <X11/Xthreads.h>
+#endif
+#ifdef WIN32
+#include <X11/Xlibint.h>
+#include <X11/Xwinsock.h>
+#endif
+
+#ifdef X11_t
+
+/*
+ * These values come from X.h and Xauth.h, and MUST match them. Some
+ * of these values are also defined by the ChangeHost protocol message.
+ */
+
+#define FamilyInternet 0 /* IPv4 */
+#define FamilyDECnet 1
+#define FamilyChaos 2
+#define FamilyInternet6 6
+#define FamilyAmoeba 33
+#define FamilyLocalHost 252
+#define FamilyKrb5Principal 253
+#define FamilyNetname 254
+#define FamilyLocal 256
+#define FamilyWild 65535
+
+/*
+ * TRANS(ConvertAddress) converts a sockaddr based address to an
+ * X authorization based address. Some of this is defined as part of
+ * the ChangeHost protocol. The rest is just done in a consistent manner.
+ */
+
+int
+TRANS(ConvertAddress)(int *familyp, int *addrlenp, Xtransaddr **addrp)
+
+{
+
+ PRMSG(2,"ConvertAddress(%d,%d,%x)\n",*familyp,*addrlenp,*addrp);
+
+ switch( *familyp )
+ {
+#if defined(TCPCONN) || defined(STREAMSCONN)
+ case AF_INET:
+ {
+ /*
+ * Check for the BSD hack localhost address 127.0.0.1.
+ * In this case, we are really FamilyLocal.
+ */
+
+ struct sockaddr_in saddr;
+ int len = sizeof(saddr.sin_addr.s_addr);
+ char *cp = (char *) &saddr.sin_addr.s_addr;
+
+ memcpy (&saddr, *addrp, sizeof (struct sockaddr_in));
+
+ if ((len == 4) && (cp[0] == 127) && (cp[1] == 0) &&
+ (cp[2] == 0) && (cp[3] == 1))
+ {
+ *familyp=FamilyLocal;
+ }
+ else
+ {
+ *familyp=FamilyInternet;
+ *addrlenp=len;
+ memcpy(*addrp,&saddr.sin_addr,len);
+ }
+ break;
+ }
+
+#if defined(IPv6) && defined(AF_INET6)
+ case AF_INET6:
+ {
+ struct sockaddr_in6 saddr6;
+
+ memcpy (&saddr6, *addrp, sizeof (struct sockaddr_in6));
+
+ if (IN6_IS_ADDR_LOOPBACK(&saddr6.sin6_addr))
+ {
+ *familyp=FamilyLocal;
+ }
+ else if (IN6_IS_ADDR_V4MAPPED(&(saddr6.sin6_addr))) {
+ char *cp = (char *) &saddr6.sin6_addr.s6_addr[12];
+
+ if ((cp[0] == 127) && (cp[1] == 0) &&
+ (cp[2] == 0) && (cp[3] == 1))
+ {
+ *familyp=FamilyLocal;
+ }
+ else
+ {
+ *familyp=FamilyInternet;
+ *addrlenp = sizeof (struct in_addr);
+ memcpy(*addrp,cp,*addrlenp);
+ }
+ }
+ else
+ {
+ *familyp=FamilyInternet6;
+ *addrlenp=sizeof(saddr6.sin6_addr);
+ memcpy(*addrp,&saddr6.sin6_addr,sizeof(saddr6.sin6_addr));
+ }
+ break;
+ }
+#endif /* IPv6 */
+#endif /* defined(TCPCONN) || defined(STREAMSCONN) */
+
+
+#if defined(UNIXCONN) || defined(LOCALCONN)
+ case AF_UNIX:
+ {
+ *familyp=FamilyLocal;
+ break;
+ }
+#endif /* defined(UNIXCONN) || defined(LOCALCONN) */
+
+#if (defined(__SCO__) || defined(__UNIXWARE__)) && defined(LOCALCONN)
+ case 0:
+ {
+ *familyp=FamilyLocal;
+ break;
+ }
+#endif
+
+ default:
+ PRMSG(1,"ConvertAddress: Unknown family type %d\n",
+ *familyp, 0,0 );
+ return -1;
+ }
+
+
+ if (*familyp == FamilyLocal)
+ {
+ /*
+ * In the case of a local connection, we need to get the
+ * host name for authentication.
+ */
+
+ char hostnamebuf[256];
+ int len = TRANS(GetHostname) (hostnamebuf, sizeof hostnamebuf);
+
+ if (len > 0) {
+ if (*addrp && *addrlenp < (len + 1))
+ {
+ xfree ((char *) *addrp);
+ *addrp = NULL;
+ }
+ if (!*addrp)
+ *addrp = (Xtransaddr *) xalloc (len + 1);
+ if (*addrp) {
+ strcpy ((char *) *addrp, hostnamebuf);
+ *addrlenp = len;
+ } else {
+ *addrlenp = 0;
+ }
+ }
+ else
+ {
+ if (*addrp)
+ xfree ((char *) *addrp);
+ *addrp = NULL;
+ *addrlenp = 0;
+ }
+ }
+
+ return 0;
+}
+
+#endif /* X11_t */
+
+#ifdef ICE_t
+
+#include <signal.h>
+
+char *
+TRANS(GetMyNetworkId) (XtransConnInfo ciptr)
+
+{
+ int family = ciptr->family;
+ char *addr = ciptr->addr;
+ char hostnamebuf[256];
+ char *networkId = NULL;
+ char *transName = ciptr->transptr->TransName;
+
+ if (gethostname (hostnamebuf, sizeof (hostnamebuf)) < 0)
+ {
+ return (NULL);
+ }
+
+ switch (family)
+ {
+#if defined(UNIXCONN) || defined(STREAMSCONN) || defined(LOCALCONN)
+ case AF_UNIX:
+ {
+ struct sockaddr_un *saddr = (struct sockaddr_un *) addr;
+ networkId = (char *) xalloc (3 + strlen (transName) +
+ strlen (hostnamebuf) + strlen (saddr->sun_path));
+ sprintf (networkId, "%s/%s:%s", transName,
+ hostnamebuf, saddr->sun_path);
+ break;
+ }
+#endif /* defined(UNIXCONN) || defined(STREAMSCONN) || defined(LOCALCONN) */
+
+#if defined(TCPCONN) || defined(STREAMSCONN)
+ case AF_INET:
+#if defined(IPv6) && defined(AF_INET6)
+ case AF_INET6:
+#endif
+ {
+ struct sockaddr_in *saddr = (struct sockaddr_in *) addr;
+#if defined(IPv6) && defined(AF_INET6)
+ struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *) addr;
+#endif
+ int portnum;
+ char portnumbuf[10];
+
+
+#if defined(IPv6) && defined(AF_INET6)
+ if (family == AF_INET6)
+ portnum = ntohs (saddr6->sin6_port);
+ else
+#endif
+ portnum = ntohs (saddr->sin_port);
+
+ snprintf (portnumbuf, sizeof(portnumbuf), "%d", portnum);
+ networkId = (char *) xalloc (3 + strlen (transName) +
+ strlen (hostnamebuf) + strlen (portnumbuf));
+ sprintf (networkId, "%s/%s:%s", transName, hostnamebuf, portnumbuf);
+ break;
+ }
+#endif /* defined(TCPCONN) || defined(STREAMSCONN) */
+
+
+ default:
+ break;
+ }
+
+ return (networkId);
+}
+
+#include <setjmp.h>
+static jmp_buf env;
+
+#ifdef SIGALRM
+static volatile int nameserver_timedout = 0;
+
+static
+#ifdef RETSIGTYPE /* set by autoconf AC_TYPE_SIGNAL */
+RETSIGTYPE
+#else /* Imake */
+#ifdef SIGNALRETURNSINT
+int
+#else
+void
+#endif
+#endif
+nameserver_lost(int sig)
+{
+ nameserver_timedout = 1;
+ longjmp (env, -1);
+ /* NOTREACHED */
+#ifdef SIGNALRETURNSINT
+ return -1; /* for picky compilers */
+#endif
+}
+#endif /* SIGALARM */
+
+
+char *
+TRANS(GetPeerNetworkId) (XtransConnInfo ciptr)
+
+{
+ int family = ciptr->family;
+ char *peer_addr = ciptr->peeraddr;
+ char *hostname;
+ char addrbuf[256];
+ const char *addr = NULL;
+
+ switch (family)
+ {
+ case AF_UNSPEC:
+#if defined(UNIXCONN) || defined(STREAMSCONN) || defined(LOCALCONN)
+ case AF_UNIX:
+ {
+ if (gethostname (addrbuf, sizeof (addrbuf)) == 0)
+ addr = addrbuf;
+ break;
+ }
+#endif /* defined(UNIXCONN) || defined(STREAMSCONN) || defined(LOCALCONN) */
+
+#if defined(TCPCONN) || defined(STREAMSCONN)
+ case AF_INET:
+#if defined(IPv6) && defined(AF_INET6)
+ case AF_INET6:
+#endif
+ {
+ struct sockaddr_in *saddr = (struct sockaddr_in *) peer_addr;
+#if defined(IPv6) && defined(AF_INET6)
+ struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *) peer_addr;
+#endif
+ char *address;
+ int addresslen;
+#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
+ _Xgethostbynameparams hparams;
+#endif
+ struct hostent * volatile hostp = NULL;
+
+#if defined(IPv6) && defined(AF_INET6)
+ if (family == AF_INET6)
+ {
+ address = (char *) &saddr6->sin6_addr;
+ addresslen = sizeof (saddr6->sin6_addr);
+ }
+ else
+#endif
+ {
+ address = (char *) &saddr->sin_addr;
+ addresslen = sizeof (saddr->sin_addr);
+ }
+
+#ifdef SIGALRM
+ /*
+ * gethostbyaddr can take a LONG time if the host does not exist.
+ * Assume that if it does not respond in NAMESERVER_TIMEOUT seconds
+ * that something is wrong and do not make the user wait.
+ * gethostbyaddr will continue after a signal, so we have to
+ * jump out of it.
+ */
+
+ nameserver_timedout = 0;
+ signal (SIGALRM, nameserver_lost);
+ alarm (4);
+ if (setjmp(env) == 0) {
+#endif
+ hostp = _XGethostbyaddr (address, addresslen, family, hparams);
+#ifdef SIGALRM
+ }
+ alarm (0);
+#endif
+ if (hostp != NULL)
+ addr = hostp->h_name;
+ else
+#if defined(IPv6) && defined(AF_INET6)
+ addr = inet_ntop (family, address, addrbuf, sizeof (addrbuf));
+#else
+ addr = inet_ntoa (saddr->sin_addr);
+#endif
+ break;
+ }
+
+#endif /* defined(TCPCONN) || defined(STREAMSCONN) */
+
+
+ default:
+ return (NULL);
+ }
+
+
+ hostname = (char *) xalloc (
+ strlen (ciptr->transptr->TransName) + strlen (addr) + 2);
+ strcpy (hostname, ciptr->transptr->TransName);
+ strcat (hostname, "/");
+ if (addr)
+ strcat (hostname, addr);
+
+ return (hostname);
+}
+
+#endif /* ICE_t */
+
+
+#if defined(WIN32) && defined(TCPCONN)
+int
+TRANS(WSAStartup) (void)
+{
+ static WSADATA wsadata;
+
+ PRMSG (2,"WSAStartup()\n", 0, 0, 0);
+
+ if (!wsadata.wVersion && WSAStartup(MAKEWORD(2,2), &wsadata))
+ return 1;
+ return 0;
+}
+#endif
+
+
+static int
+is_numeric (char *str)
+
+{
+ int i;
+
+ for (i = 0; i < (int) strlen (str); i++)
+ if (!isdigit (str[i]))
+ return (0);
+
+ return (1);
+}
+
+#ifdef TRANS_SERVER
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#if !defined(S_IFLNK) && !defined(S_ISLNK)
+#undef lstat
+#define lstat(a,b) stat(a,b)
+#endif
+
+#define FAIL_IF_NOMODE 1
+#define FAIL_IF_NOT_ROOT 2
+#define WARN_NO_ACCESS 4
+
+/*
+ * We make the assumption that when the 'sticky' (t) bit is requested
+ * it's not save if the directory has non-root ownership or the sticky
+ * bit cannot be set and fail.
+ */
+static int
+trans_mkdir(char *path, int mode)
+{
+ struct stat buf;
+
+ if (lstat(path, &buf) != 0) {
+ if (errno != ENOENT) {
+ PRMSG(1, "mkdir: ERROR: (l)stat failed for %s (%d)\n",
+ path, errno, 0);
+ return -1;
+ }
+ /* Dir doesn't exist. Try to create it */
+
+#ifndef WIN32
+ /*
+ * 'sticky' bit requested: assume application makes
+ * certain security implications. If effective user ID
+ * is != 0: fail as we may not be able to meet them.
+ */
+ if (geteuid() != 0) {
+ if (mode & 01000) {
+ PRMSG(1, "mkdir: ERROR: euid != 0,"
+ "directory %s will not be created.\n",
+ path, 0, 0);
+#ifdef FAIL_HARD
+ return -1;
+#endif
+ } else {
+ PRMSG(1, "mkdir: Cannot create %s with root ownership\n",
+ path, 0, 0);
+ }
+ }
+#endif
+
+#ifndef WIN32
+ if (mkdir(path, mode) == 0) {
+ if (chmod(path, mode)) {
+ PRMSG(1, "mkdir: ERROR: Mode of %s should be set to %04o\n",
+ path, mode, 0);
+#ifdef FAIL_HARD
+ return -1;
+#endif
+ }
+#else
+ if (mkdir(path) == 0) {
+#endif
+ } else {
+ PRMSG(1, "mkdir: ERROR: Cannot create %s\n",
+ path, 0, 0);
+ return -1;
+ }
+
+ return 0;
+
+ } else {
+ if (S_ISDIR(buf.st_mode)) {
+ int updateOwner = 0;
+ int updateMode = 0;
+ int updatedOwner = 0;
+ int updatedMode = 0;
+ int status = 0;
+ /* Check if the directory's ownership is OK. */
+ if (buf.st_uid != 0)
+ updateOwner = 1;
+
+ /*
+ * Check if the directory's mode is OK. An exact match isn't
+ * required, just a mode that isn't more permissive than the
+ * one requested.
+ */
+ if ((~mode) & 0077 & buf.st_mode)
+ updateMode = 1;
+
+ /*
+ * If the directory is not writeable not everybody may
+ * be able to create sockets. Therefore warn if mode
+ * cannot be fixed.
+ */
+ if ((~buf.st_mode) & 0022 & mode) {
+ updateMode = 1;
+ status |= WARN_NO_ACCESS;
+ }
+
+ /*
+ * If 'sticky' bit is requested fail if owner isn't root
+ * as we assume the caller makes certain security implications
+ */
+ if (mode & 01000) {
+ status |= FAIL_IF_NOT_ROOT;
+ if (!(buf.st_mode & 01000)) {
+ status |= FAIL_IF_NOMODE;
+ updateMode = 1;
+ }
+ }
+
+#ifdef HAS_FCHOWN
+ /*
+ * If fchown(2) and fchmod(2) are available, try to correct the
+ * directory's owner and mode. Otherwise it isn't safe to attempt
+ * to do this.
+ */
+ if (updateMode || updateOwner) {
+ int fd = -1;
+ struct stat fbuf;
+ if ((fd = open(path, O_RDONLY)) != -1) {
+ if (fstat(fd, &fbuf) == -1) {
+ PRMSG(1, "mkdir: ERROR: fstat failed for %s (%d)\n",
+ path, errno, 0);
+ return -1;
+ }
+ /*
+ * Verify that we've opened the same directory as was
+ * checked above.
+ */
+ if (!S_ISDIR(fbuf.st_mode) ||
+ buf.st_dev != fbuf.st_dev ||
+ buf.st_ino != fbuf.st_ino) {
+ PRMSG(1, "mkdir: ERROR: inode for %s changed\n",
+ path, 0, 0);
+ return -1;
+ }
+ if (updateOwner && fchown(fd, 0, 0) == 0)
+ updatedOwner = 1;
+ if (updateMode && fchmod(fd, mode) == 0)
+ updatedMode = 1;
+ close(fd);
+ }
+ }
+#endif
+
+ if (updateOwner && !updatedOwner) {
+#ifdef FAIL_HARD
+ if (status & FAIL_IF_NOT_ROOT) {
+ PRMSG(1, "mkdir: ERROR: Owner of %s must be set to root\n",
+ path, 0, 0);
+ return -1;
+ }
+#endif
+#ifndef __APPLE_CC__
+ PRMSG(1, "mkdir: Owner of %s should be set to root\n",
+ path, 0, 0);
+#endif
+ }
+
+ if (updateMode && !updatedMode) {
+#ifdef FAIL_HARD
+ if (status & FAIL_IF_NOMODE) {
+ PRMSG(1, "mkdir: ERROR: Mode of %s must be set to %04o\n",
+ path, mode, 0);
+ return -1;
+ }
+#endif
+ PRMSG(1, "mkdir: Mode of %s should be set to %04o\n",
+ path, mode, 0);
+ if (status & WARN_NO_ACCESS) {
+ PRMSG(1, "mkdir: this may cause subsequent errors\n",
+ 0, 0, 0);
+ }
+ }
+ return 0;
+ }
+ return -1;
+ }
+
+ /* In all other cases, fail */
+ return -1;
+}
+
+#endif /* TRANS_SERVER */