aboutsummaryrefslogtreecommitdiff
path: root/libX11/src/ConnDis.c
diff options
context:
space:
mode:
Diffstat (limited to 'libX11/src/ConnDis.c')
-rw-r--r--libX11/src/ConnDis.c1251
1 files changed, 0 insertions, 1251 deletions
diff --git a/libX11/src/ConnDis.c b/libX11/src/ConnDis.c
deleted file mode 100644
index 4eb94f34d..000000000
--- a/libX11/src/ConnDis.c
+++ /dev/null
@@ -1,1251 +0,0 @@
-/*
-
-Copyright 1989, 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.
-
-*/
-
-/*
- * This file contains operating system dependencies.
- */
-
-#define NEED_EVENTS
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <X11/Xlibint.h>
-#include <X11/Xtrans/Xtrans.h>
-#include <X11/Xauth.h>
-#ifdef HASXDMAUTH
-#include <X11/Xdmcp.h>
-#endif
-#include <stdio.h>
-#include <ctype.h>
-#include <unistd.h>
-
-#if !defined(WIN32)
-#ifndef Lynx
-#include <sys/socket.h>
-#else
-#include <socket.h>
-#endif
-#else
-#include <X11/Xwindows.h>
-#endif
-
-#ifndef X_CONNECTION_RETRIES /* number retries on ECONNREFUSED */
-#define X_CONNECTION_RETRIES 5
-#endif
-
-#include "Xintconn.h"
-
-/* prototypes */
-static void GetAuthorization(
- XtransConnInfo trans_conn,
- int family,
- char *saddr,
- int saddrlen,
- int idisplay,
- char **auth_namep,
- int *auth_namelenp,
- char **auth_datap,
- int *auth_datalenp);
-
-/* functions */
-static char *copystring (const char *src, int len)
-{
- char *dst = Xmalloc (len + 1);
-
- if (dst) {
- strncpy (dst, src, len);
- dst[len] = '\0';
- }
-
- return dst;
-}
-
-#define Xstrdup(s) copystring(s, strlen(s))
-
-#ifdef TCPCONN
-# define TCP_TRANS "tcp"
-#endif
-#ifdef UNIXCONN
-# define UNIX_TRANS "unix"
-#endif
-#if defined(LOCALCONN) || defined(OS2PIPECONN)
-# define LOCAL_TRANS "local"
-#endif
-
-/*
- * Attempts to connect to server, given display name. Returns file descriptor
- * (network socket) or -1 if connection fails. Display names may be of the
- * following format:
- *
- * [protocol/] [hostname] : [:] displaynumber [.screennumber]
- *
- * A string with exactly two colons seperating hostname from the display
- * indicates a DECnet style name. Colons in the hostname may occur if an
- * IPv6 numeric address is used as the hostname. An IPv6 numeric address
- * may also end in a double colon, so three colons in a row indicates an
- * IPv6 address ending in :: followed by :display. To make it easier for
- * people to read, an IPv6 numeric address hostname may be surrounded by
- * [ ] in a similar fashion to the IPv6 numeric address URL syntax defined
- * by IETF RFC 2732.
- *
- * If no hostname and no protocol is specified, the string is interpreted
- * as the most efficient local connection to a server on the same machine.
- * This is usually:
- *
- * o shared memory
- * o local stream
- * o UNIX domain socket
- * o TCP to local host
- *
- * This function will eventually call the X Transport Interface functions
- * which expects the hostname in the format:
- *
- * [protocol/] [hostname] : [:] displaynumber
- *
- */
-XtransConnInfo
-_X11TransConnectDisplay (
- char *display_name,
- char **fullnamep, /* RETURN */
- int *dpynump, /* RETURN */
- int *screenp, /* RETURN */
- char **auth_namep, /* RETURN */
- int *auth_namelenp, /* RETURN */
- char **auth_datap, /* RETURN */
- int *auth_datalenp) /* RETURN */
-{
- int family;
- int saddrlen;
- Xtransaddr *saddr;
- char *lastp, *lastc, *p; /* char pointers */
- char *pprotocol = NULL; /* start of protocol name */
- char *phostname = NULL; /* start of host of display */
- char *pdpynum = NULL; /* start of dpynum of display */
- char *pscrnum = NULL; /* start of screen of display */
- Bool dnet = False; /* if true, then DECnet format */
- int idisplay = 0; /* required display number */
- int iscreen = 0; /* optional screen number */
- /* int (*connfunc)(); */ /* method to create connection */
- int len, hostlen; /* length tmp variable */
- int retry; /* retry counter */
- char addrbuf[128]; /* final address passed to
- X Transport Interface */
- char* address = addrbuf;
- XtransConnInfo trans_conn = NULL; /* transport connection object */
- int connect_stat;
-#if defined(LOCALCONN) || defined(UNIXCONN) || defined(TCPCONN)
- Bool reset_hostname = False; /* Reset hostname? */
- char *original_hostname = NULL;
- int local_transport_index = -1;
- const char *local_transport[] = { LOCAL_TRANSPORT_LIST, NULL };
-#endif
-
- p = display_name;
-
- saddrlen = 0; /* set so that we can clear later */
- saddr = NULL;
-
- /*
- * Step 0, find the protocol. This is delimited by the optional
- * slash ('/').
- */
- for (lastp = p; *p && *p != ':' && *p != '/'; p++) ;
- if (!*p) return NULL; /* must have a colon */
-
- if (p != lastp && *p != ':') { /* protocol given? */
- pprotocol = copystring (lastp, p - lastp);
- if (!pprotocol) goto bad; /* no memory */
- p++; /* skip the '/' */
- } else
- p = display_name; /* reset the pointer in
- case no protocol was given */
-
- /*
- * Step 1, find the hostname. This is delimited by either one colon,
- * or two colons in the case of DECnet (DECnet Phase V allows a single
- * colon in the hostname). (See note above regarding IPv6 numeric
- * addresses with triple colons or [] brackets.)
- */
-
- lastp = p;
- lastc = NULL;
- for (; *p; p++)
- if (*p == ':')
- lastc = p;
-
- if (!lastc) return NULL; /* must have a colon */
-
- if ((lastp != lastc) && (*(lastc - 1) == ':')
-#if defined(IPv6) && defined(AF_INET6)
- && ( ((lastc - 1) == lastp) || (*(lastc - 2) != ':'))
-#endif
- ) {
- /* DECnet display specified */
-
-#ifndef DNETCONN
- goto bad;
-#else
- dnet = True;
- /* override the protocol specified */
- if (pprotocol)
- Xfree (pprotocol);
- pprotocol = copystring ("dnet", 4);
- hostlen = lastc - 1 - lastp;
-#endif
- }
- else
- hostlen = lastc - lastp;
-
- if (hostlen > 0) { /* hostname given? */
- phostname = copystring (lastp, hostlen);
- if (!phostname) goto bad; /* no memory */
- }
-
- p = lastc;
-
-#if defined(LOCALCONN) || defined(UNIXCONN) || defined(TCPCONN)
- /* check if phostname == localnodename AND protocol not specified */
- if (!pprotocol && phostname) {
- char localhostname[256];
-
- if ((_XGetHostname (localhostname, sizeof localhostname) > 0)
- && (strcmp(phostname, localhostname) == 0)) {
- original_hostname = phostname;
- phostname = NULL;
- reset_hostname = True;
- }
- }
-#endif
-
-
- /*
- * Step 2, find the display number. This field is required and is
- * delimited either by a nul or a period, depending on whether or not
- * a screen number is present.
- */
-
- for (lastp = ++p; *p && isascii(*p) && isdigit(*p); p++) ;
- if ((p == lastp) || /* required field */
- (*p != '\0' && *p != '.') || /* invalid non-digit terminator */
- !(pdpynum = copystring (lastp, p - lastp))) /* no memory */
- goto bad;
- idisplay = atoi (pdpynum);
-
-
- /*
- * Step 3, find the screen number. This field is optional. It is
- * present only if the display number was followed by a period (which
- * we've already verified is the only non-nul character).
- */
-
- if (*p) {
- for (lastp = ++p; *p && isascii(*p) && isdigit (*p); p++) ;
- if (p != lastp) {
- if (*p || /* non-digits */
- !(pscrnum = copystring (lastp, p - lastp))) /* no memory */
- goto bad;
- iscreen = atoi (lastp);
- }
- }
-
- /*
- * At this point, we know the following information:
- *
- * pprotocol protocol string or NULL
- * phostname hostname string or NULL
- * idisplay display number
- * iscreen screen number
- * dnet DECnet boolean
- *
- * We can now decide which transport to use based on the defined
- * connection types and the hostname string.
- * If phostname & pprotocol are NULL, then choose the best transport.
- * If phostname is "unix" & pprotocol is NULL, then choose UNIX domain
- * sockets (if configured).
- */
-
-#if defined(TCPCONN) || defined(UNIXCONN) || defined(LOCALCONN) || defined(MNX_TCPCONN) || defined(OS2PIPECONN)
- if (!pprotocol) {
-#if defined(UNIXCONN)
- if (phostname && (strcmp (phostname, "unix") == 0)) {
- Xfree(pprotocol);
- pprotocol = copystring ("unix", 4);
- } else
-#endif
-#ifdef HAVE_LAUNCHD
- if (phostname && phostname[0]=='/') {
- pprotocol = copystring ("local", 5);
- }
-#endif
- if (!phostname)
- {
- if (local_transport[0] != NULL) {
- pprotocol = Xstrdup(local_transport[0]);
- local_transport_index = 0;
- }
- }
-
- if (!pprotocol) { /* if still not found one, tcp is our last resort */
- pprotocol = copystring ("tcp", 3);
- }
- }
-#endif
-
-
- connect:
- /*
- * This seems kind of backwards, but we need to put the protocol,
- * host, and port back together to pass to _X11TransOpenCOTSClient().
- */
-
- {
- int olen = 3 + (pprotocol ? strlen(pprotocol) : 0) +
- (phostname ? strlen(phostname) : 0) +
- (pdpynum ? strlen(pdpynum) : 0);
- if (olen > sizeof addrbuf) address = Xmalloc (olen);
- }
- if (!address) goto bad;
-
- sprintf(address,"%s/%s:%d",
- pprotocol ? pprotocol : "",
- phostname ? phostname : "",
- idisplay );
-
- /*
- * Make the connection, also need to get the auth address info for
- * the connection. Do retries in case server host has hit its
- * backlog (which, unfortunately, isn't distinguishable from there not
- * being a server listening at all, which is why we have to not retry
- * too many times).
- */
- for(retry=X_CONNECTION_RETRIES; retry>=0; retry-- )
- {
- if ( (trans_conn = _X11TransOpenCOTSClient(address)) == NULL )
- {
- break;
- }
- if ((connect_stat = _X11TransConnect(trans_conn,address)) < 0 )
- {
- _X11TransClose(trans_conn);
- trans_conn = NULL;
-
- if (connect_stat == TRANS_TRY_CONNECT_AGAIN)
- continue;
- else
- break;
- }
-
- _X11TransGetPeerAddr(trans_conn, &family, &saddrlen, &saddr);
-
- /*
- * The family is given in a socket format (ie AF_INET). This
- * will convert it to the format used by the authorization and
- * X protocol (ie FamilyInternet).
- */
-
- if( _X11TransConvertAddress(&family, &saddrlen, &saddr) < 0 )
- {
- _X11TransClose(trans_conn);
- trans_conn = NULL;
- if (saddr)
- {
- free ((char *) saddr);
- saddr = NULL;
- }
- continue;
- }
-
- break;
- }
-
- if (address != addrbuf) Xfree (address);
- address = addrbuf;
-
- if( trans_conn == NULL )
- goto bad;
-
- /*
- * Set close-on-exec so that programs that fork() doesn't get confused.
- */
-
- _X11TransSetOption(trans_conn,TRANS_CLOSEONEXEC,1);
-
- /*
- * Build the expanded display name:
- *
- * [host] : [:] dpy . scr \0
- */
-#if defined(LOCALCONN) || defined(TCPCONN) || defined(UNIXCONN)
- /*
- * If we computed the host name, get rid of it so that
- * XDisplayString() and XDisplayName() agree.
- */
- if (reset_hostname && (phostname != original_hostname)) {
- Xfree (phostname);
- phostname = original_hostname;
- original_hostname = NULL;
- }
-#endif
- len = ((phostname ? strlen(phostname) : 0) + 1 + (dnet ? 1 : 0) +
- strlen(pdpynum) + 1 + (pscrnum ? strlen(pscrnum) : 1) + 1);
- *fullnamep = (char *) Xmalloc (len);
- if (!*fullnamep) goto bad;
-
-#ifdef HAVE_LAUNCHD
- if (phostname && strlen(phostname) > 11 && !strncmp(phostname, "/tmp/launch", 11))
- sprintf (*fullnamep, "%s%s%d",
- (phostname ? phostname : ""),
- (dnet ? "::" : ":"),
- idisplay);
- else
-#endif
- sprintf (*fullnamep, "%s%s%d.%d",
- (phostname ? phostname : ""),
- (dnet ? "::" : ":"),
- idisplay, iscreen);
-
- *dpynump = idisplay;
- *screenp = iscreen;
- if (pprotocol) Xfree (pprotocol);
- if (phostname) Xfree (phostname);
- if (pdpynum) Xfree (pdpynum);
- if (pscrnum) Xfree (pscrnum);
-#if defined(LOCALCONN) || defined(UNIXCONN) || defined(TCPCONN)
- if (original_hostname) Xfree (original_hostname);
-#endif
-
- GetAuthorization(trans_conn, family, (char *) saddr, saddrlen, idisplay,
- auth_namep, auth_namelenp, auth_datap, auth_datalenp);
- return trans_conn;
-
-
- /*
- * error return; make sure everything is cleaned up.
- */
- bad:
- if (trans_conn) (void)_X11TransClose(trans_conn);
- if (saddr) free ((char *) saddr);
- if (pprotocol) Xfree (pprotocol);
- if (phostname) Xfree (phostname);
- if (address && address != addrbuf) { Xfree(address); address = addrbuf; }
-
-#if defined(LOCALCONN) || defined(UNIXCONN) || defined(TCPCONN)
- /* If connecting to the local machine, and we failed, try again with
- * the next transport type available, if there is one.
- */
- if (local_transport_index >= 0) {
- if (local_transport[++local_transport_index] != NULL) {
- pprotocol = Xstrdup(local_transport[local_transport_index]);
-#ifdef TCPCONN
- if (strcmp(pprotocol, "tcp") == 0) {
- if (original_hostname != NULL) {
- phostname = original_hostname;
- original_hostname = NULL;
- } else {
- phostname = copystring("localhost", 9);
- }
- } else
-#endif /* TCPCONN */
- {
- if ((phostname != NULL) && (original_hostname == NULL)) {
- original_hostname = phostname;
- }
- phostname = NULL;
- }
- goto connect;
- }
- }
-
- /* No more to try, we've failed all available local transports */
- if (original_hostname) Xfree(original_hostname);
-#endif /* LOCALCONN || UNIXCONN || TCPCONN */
-
- if (pdpynum) Xfree (pdpynum);
- if (pscrnum) Xfree (pscrnum);
- return NULL;
-
-}
-
-/*
- * This is gross, but we need it for compatiblity.
- * The test suite relies on the following interface.
- *
- */
-
-int _XConnectDisplay (
- char *display_name,
- char **fullnamep, /* RETURN */
- int *dpynump, /* RETURN */
- int *screenp, /* RETURN */
- char **auth_namep, /* RETURN */
- int *auth_namelenp, /* RETURN */
- char **auth_datap, /* RETURN */
- int *auth_datalenp) /* RETURN */
-{
- XtransConnInfo trans_conn;
-
- trans_conn = _X11TransConnectDisplay (
- display_name, fullnamep, dpynump, screenp,
- auth_namep, auth_namelenp, auth_datap, auth_datalenp);
-
- if (trans_conn)
- {
- int fd = _X11TransGetConnectionNumber (trans_conn);
- _X11TransFreeConnInfo (trans_conn);
- return (fd);
- }
- else
- return (-1);
-}
-
-
-/*****************************************************************************
- * *
- * Connection Utility Routines *
- * *
- *****************************************************************************/
-
-/*
- * Disconnect from server.
- */
-
-int _XDisconnectDisplay (XtransConnInfo trans_conn)
-{
- _X11TransDisconnect(trans_conn);
- _X11TransClose(trans_conn);
- return 0;
-}
-
-
-
-Bool
-_XSendClientPrefix(
- Display *dpy,
- xConnClientPrefix *client, /* contains count for auth_* */
- char *auth_proto, char *auth_string, /* NOT null-terminated */
- xConnSetupPrefix *prefix) /* prefix information */
-{
- int auth_length = client->nbytesAuthProto;
- int auth_strlen = client->nbytesAuthString;
- static char padbuf[3]; /* for padding to 4x bytes */
- int pad;
- struct iovec iovarray[5], *iov = iovarray;
- int niov = 0;
- int len = 0;
-
-#define add_to_iov(b,l) \
- { iov->iov_base = (b); iov->iov_len = (l); iov++, niov++; len += (l); }
-
- add_to_iov ((caddr_t) client, SIZEOF(xConnClientPrefix));
-
- /*
- * write authorization protocol name and data
- */
- if (auth_length > 0) {
- add_to_iov (auth_proto, auth_length);
- pad = -auth_length & 3; /* pad auth_length to a multiple of 4 */
- if (pad) add_to_iov (padbuf, pad);
- }
- if (auth_strlen > 0) {
- add_to_iov (auth_string, auth_strlen);
- pad = -auth_strlen & 3; /* pad auth_strlen to a multiple of 4 */
- if (pad) add_to_iov (padbuf, pad);
- }
-
-#undef add_to_iov
-
- len -= _X11TransWritev (dpy->trans_conn, iovarray, niov);
-
- /*
- * Set the connection non-blocking since we use select() to block.
- */
-
- _X11TransSetOption(dpy->trans_conn, TRANS_NONBLOCKING, 1);
-
- if (len != 0)
- return -1;
-
-#ifdef K5AUTH
- if (auth_length == 14 &&
- !strncmp(auth_proto, "MIT-KERBEROS-5", 14))
- {
- return k5_clientauth(dpy, prefix);
- } else
-#endif
- return 0;
-}
-
-
-#ifdef STREAMSCONN
-#ifdef SVR4
-#include <tiuser.h>
-#else
-#undef HASXDMAUTH
-#endif
-#endif
-
-#ifdef SECURE_RPC
-#include <rpc/rpc.h>
-#ifdef ultrix
-#include <time.h>
-#include <rpc/auth_des.h>
-#endif
-#endif
-
-#ifdef HASXDMAUTH
-#include <time.h>
-#define Time_t time_t
-#endif
-
-/*
- * First, a routine for setting authorization data
- */
-static int xauth_namelen = 0;
-static char *xauth_name = NULL; /* NULL means use default mechanism */
-static int xauth_datalen = 0;
-static char *xauth_data = NULL; /* NULL means get default data */
-
-/*
- * This is a list of the authorization names which Xlib currently supports.
- * Xau will choose the file entry which matches the earliest entry in this
- * array, allowing us to prioritize these in terms of the most secure first
- */
-
-static char *default_xauth_names[] = {
-#ifdef K5AUTH
- "MIT-KERBEROS-5",
-#endif
-#ifdef SECURE_RPC
- "SUN-DES-1",
-#endif
-#ifdef HASXDMAUTH
- "XDM-AUTHORIZATION-1",
-#endif
- "MIT-MAGIC-COOKIE-1"
-};
-
-static _Xconst int default_xauth_lengths[] = {
-#ifdef K5AUTH
- 14, /* strlen ("MIT-KERBEROS-5") */
-#endif
-#ifdef SECURE_RPC
- 9, /* strlen ("SUN-DES-1") */
-#endif
-#ifdef HASXDMAUTH
- 19, /* strlen ("XDM-AUTHORIZATION-1") */
-#endif
- 18 /* strlen ("MIT-MAGIC-COOKIE-1") */
-};
-
-#define NUM_DEFAULT_AUTH (sizeof (default_xauth_names) / sizeof (default_xauth_names[0]))
-
-static char **xauth_names = default_xauth_names;
-static _Xconst int *xauth_lengths = default_xauth_lengths;
-
-static int xauth_names_length = NUM_DEFAULT_AUTH;
-
-void XSetAuthorization (
- char *name, int namelen, /* *len are lengths of name and data */
- char *data, int datalen) /* name/data are NULL or arbitrary array of bytes */
-{
- char *tmpname, *tmpdata;
-
- _XLockMutex(_Xglobal_lock);
- if (xauth_name) Xfree (xauth_name); /* free any existing data */
- if (xauth_data) Xfree (xauth_data);
-
- xauth_name = xauth_data = NULL; /* mark it no longer valid */
- xauth_namelen = xauth_datalen = 0;
- _XUnlockMutex(_Xglobal_lock);
-
- if (namelen < 0) namelen = 0; /* check for bogus inputs */
- if (datalen < 0) datalen = 0; /* maybe should return? */
-
- if (namelen > 0) { /* try to allocate space */
- tmpname = Xmalloc ((unsigned) namelen);
- if (!tmpname) return;
- memcpy (tmpname, name, namelen);
- } else {
- tmpname = NULL;
- }
-
- if (datalen > 0) {
- tmpdata = Xmalloc ((unsigned) datalen);
- if (!tmpdata) {
- if (tmpname) (void) Xfree (tmpname);
- return;
- }
- memcpy (tmpdata, data, datalen);
- } else {
- tmpdata = NULL;
- }
-
- _XLockMutex(_Xglobal_lock);
- xauth_name = tmpname; /* and store the suckers */
- xauth_namelen = namelen;
- if (tmpname)
- {
- xauth_names = &xauth_name;
- xauth_lengths = &xauth_namelen;
- xauth_names_length = 1;
- }
- else
- {
- xauth_names = default_xauth_names;
- xauth_lengths = default_xauth_lengths;
- xauth_names_length = NUM_DEFAULT_AUTH;
- }
- xauth_data = tmpdata;
- xauth_datalen = datalen;
- _XUnlockMutex(_Xglobal_lock);
- return;
-}
-
-#ifdef SECURE_RPC
-/*
- * Create a credential that we can send to the X server.
- */
-static int
-auth_ezencode(
- char *servername,
- int window,
- char *cred_out,
- int *len)
-{
- AUTH *a;
- XDR xdr;
-
-#if defined(SVR4) && defined(sun)
- a = authdes_seccreate(servername, window, NULL, NULL);
-#else
- a = (AUTH *)authdes_create(servername, window, NULL, NULL);
-#endif
- if (a == (AUTH *)NULL) {
- perror("auth_create");
- return 0;
- }
- xdrmem_create(&xdr, cred_out, *len, XDR_ENCODE);
- if (AUTH_MARSHALL(a, &xdr) == FALSE) {
- perror("auth_marshall");
- AUTH_DESTROY(a);
- return 0;
- }
- *len = xdr_getpos(&xdr);
- AUTH_DESTROY(a);
- return 1;
-}
-#endif
-
-#ifdef K5AUTH
-#include <com_err.h>
-
-extern krb5_flags krb5_kdc_default_options;
-
-/*
- * k5_clientauth
- *
- * Returns non-zero if the setup prefix has been read,
- * so we can tell XOpenDisplay to not bother looking for it by
- * itself.
- */
-static int k5_clientauth(dpy, sprefix)
- Display *dpy;
- xConnSetupPrefix *sprefix;
-{
- krb5_error_code retval;
- xReq prefix;
- char *buf;
- CARD16 plen, tlen;
- krb5_data kbuf;
- krb5_ccache cc;
- krb5_creds creds;
- krb5_principal cprinc, sprinc;
- krb5_ap_rep_enc_part *repl;
-
- krb5_init_ets();
- /*
- * stage 0: get encoded principal and tgt from server
- */
- _XRead(dpy, (char *)&prefix, sz_xReq);
- if (prefix.reqType != 2 && prefix.reqType != 3)
- /* not an auth packet... so deal */
- if (prefix.reqType == 0 || prefix.reqType == 1)
- {
- memcpy((char *)sprefix, (char *)&prefix, sz_xReq);
- _XRead(dpy, (char *)sprefix + sz_xReq,
- sz_xConnSetupPrefix - sz_xReq); /* ewww... gross */
- return 1;
- }
- else
- {
- fprintf(stderr,
- "Xlib: Krb5 stage 0: got illegal connection setup success code %d\n",
- prefix.reqType);
- return -1;
- }
- if (prefix.data != 0)
- {
- fprintf(stderr, "Xlib: got out of sequence (%d) packet in Krb5 auth\n",
- prefix.data);
- return -1;
- }
- buf = (char *)malloc((prefix.length << 2) - sz_xReq);
- if (buf == NULL) /* malloc failed. Run away! */
- {
- fprintf(stderr, "Xlib: malloc bombed in Krb5 auth\n");
- return -1;
- }
- tlen = (prefix.length << 2) - sz_xReq;
- _XRead(dpy, buf, tlen);
- if (prefix.reqType == 2 && tlen < 6)
- {
- fprintf(stderr, "Xlib: Krb5 stage 0 reply from server too short\n");
- free(buf);
- return -1;
- }
- if (prefix.reqType == 2)
- {
- plen = *(CARD16 *)buf;
- kbuf.data = buf + 2;
- kbuf.length = (plen > tlen) ? tlen : plen;
- }
- else
- {
- kbuf.data = buf;
- kbuf.length = tlen;
- }
- if (XauKrb5Decode(kbuf, &sprinc))
- {
- free(buf);
- fprintf(stderr, "Xlib: XauKrb5Decode bombed\n");
- return -1;
- }
- if (prefix.reqType == 3) /* do some special stuff here */
- {
- char *sname, *hostname = NULL;
-
- sname = (char *)malloc(krb5_princ_component(sprinc, 0)->length + 1);
- if (sname == NULL)
- {
- free(buf);
- krb5_free_principal(sprinc);
- fprintf(stderr, "Xlib: malloc bombed in Krb5 auth\n");
- return -1;
- }
- memcpy(sname, krb5_princ_component(sprinc, 0)->data,
- krb5_princ_component(sprinc, 0)->length);
- sname[krb5_princ_component(sprinc, 0)->length] = '\0';
- krb5_free_principal(sprinc);
- if (dpy->display_name[0] != ':') /* hunt for a hostname */
- {
- char *t;
-
- if ((hostname = (char *)malloc(strlen(dpy->display_name)))
- == NULL)
- {
- free(buf);
- free(sname);
- fprintf(stderr, "Xlib: malloc bombed in Krb5 auth\n");
- return -1;
- }
- strcpy(hostname, dpy->display_name);
- t = strchr(hostname, ':');
- if (t == NULL)
- {
- free(buf);
- free(sname);
- free(hostname);
- fprintf(stderr,
- "Xlib: shouldn't get here! malformed display name.");
- return -1;
- }
- if ((t - hostname + 1 < strlen(hostname)) && t[1] == ':')
- t++;
- *t = '\0'; /* truncate the dpy number out */
- }
- retval = krb5_sname_to_principal(hostname, sname,
- KRB5_NT_SRV_HST, &sprinc);
- free(sname);
- if (hostname)
- free(hostname);
- if (retval)
- {
- free(buf);
- fprintf(stderr, "Xlib: krb5_sname_to_principal failed: %s\n",
- error_message(retval));
- return -1;
- }
- }
- if (retval = krb5_cc_default(&cc))
- {
- free(buf);
- krb5_free_principal(sprinc);
- fprintf(stderr, "Xlib: krb5_cc_default failed: %s\n",
- error_message(retval));
- return -1;
- }
- if (retval = krb5_cc_get_principal(cc, &cprinc))
- {
- free(buf);
- krb5_free_principal(sprinc);
- fprintf(stderr, "Xlib: cannot get Kerberos principal from \"%s\": %s\n",
- krb5_cc_default_name(), error_message(retval));
- return -1;
- }
- bzero((char *)&creds, sizeof(creds));
- creds.server = sprinc;
- creds.client = cprinc;
- if (prefix.reqType == 2)
- {
- creds.second_ticket.length = tlen - plen - 2;
- creds.second_ticket.data = buf + 2 + plen;
- retval = krb5_get_credentials(KRB5_GC_USER_USER |
- krb5_kdc_default_options,
- cc, &creds);
- }
- else
- retval = krb5_get_credentials(krb5_kdc_default_options,
- cc, &creds);
- if (retval)
- {
- free(buf);
- krb5_free_cred_contents(&creds);
- fprintf(stderr, "Xlib: cannot get Kerberos credentials: %s\n",
- error_message(retval));
- return -1;
- }
- /*
- * now format the ap_req to send to the server
- */
- if (prefix.reqType == 2)
- retval = krb5_mk_req_extended(AP_OPTS_USE_SESSION_KEY |
- AP_OPTS_MUTUAL_REQUIRED, NULL,
- 0, 0, NULL, cc,
- &creds, NULL, &kbuf);
- else
- retval = krb5_mk_req_extended(AP_OPTS_MUTUAL_REQUIRED, NULL,
- 0, 0, NULL, cc, &creds, NULL,
- &kbuf);
- free(buf);
- if (retval) /* Some manner of Kerberos lossage */
- {
- krb5_free_cred_contents(&creds);
- fprintf(stderr, "Xlib: krb5_mk_req_extended failed: %s\n",
- error_message(retval));
- return -1;
- }
- prefix.reqType = 1;
- prefix.data = 0;
- prefix.length = (kbuf.length + sz_xReq + 3) >> 2;
- /*
- * stage 1: send ap_req to server
- */
- _XSend(dpy, (char *)&prefix, sz_xReq);
- _XSend(dpy, (char *)kbuf.data, kbuf.length);
- free(kbuf.data);
- /*
- * stage 2: get ap_rep from server to mutually authenticate
- */
- _XRead(dpy, (char *)&prefix, sz_xReq);
- if (prefix.reqType != 2)
- if (prefix.reqType == 0 || prefix.reqType == 1)
- {
- memcpy((char *)sprefix, (char *)&prefix, sz_xReq);
- _XRead(dpy, (char *)sprefix + sz_xReq,
- sz_xConnSetupPrefix - sz_xReq);
- return 1;
- }
- else
- {
- fprintf(stderr,
- "Xlib: Krb5 stage 2: got illegal connection setup success code %d\n",
- prefix.reqType);
- return -1;
- }
- if (prefix.data != 2)
- return -1;
- kbuf.length = (prefix.length << 2) - sz_xReq;
- kbuf.data = (char *)malloc(kbuf.length);
- if (kbuf.data == NULL)
- {
- fprintf(stderr, "Xlib: malloc bombed in Krb5 auth\n");
- return -1;
- }
- _XRead(dpy, (char *)kbuf.data, kbuf.length);
- retval = krb5_rd_rep(&kbuf, &creds.keyblock, &repl);
- if (retval)
- {
- free(kbuf.data);
- fprintf(stderr, "Xlib: krb5_rd_rep failed: %s\n",
- error_message(retval));
- return -1;
- }
- free(kbuf.data);
- /*
- * stage 3: send a short ack to the server and return
- */
- prefix.reqType = 3;
- prefix.data = 0;
- prefix.length = sz_xReq >> 2;
- _XSend(dpy, (char *)&prefix, sz_xReq);
- return 0;
-}
-#endif /* K5AUTH */
-
-static void
-GetAuthorization(
- XtransConnInfo trans_conn,
- int family,
- char *saddr,
- int saddrlen,
- int idisplay,
- char **auth_namep, /* RETURN */
- int *auth_namelenp, /* RETURN */
- char **auth_datap, /* RETURN */
- int *auth_datalenp) /* RETURN */
-{
-#ifdef SECURE_RPC
- char rpc_cred[MAX_AUTH_BYTES];
-#endif
-#ifdef HASXDMAUTH
- unsigned char xdmcp_data[192/8];
-#endif
- char *auth_name;
- int auth_namelen;
- unsigned char *auth_data;
- int auth_datalen;
- Xauth *authptr = NULL;
-
-/*
- * Look up the authorization protocol name and data if necessary.
- */
- if (xauth_name && xauth_data) {
- auth_namelen = xauth_namelen;
- auth_name = xauth_name;
- auth_datalen = xauth_datalen;
- auth_data = (unsigned char *) xauth_data;
- } else {
- char dpynumbuf[40]; /* big enough to hold 2^64 and more */
- (void) sprintf (dpynumbuf, "%d", idisplay);
-
- authptr = XauGetBestAuthByAddr ((unsigned short) family,
- (unsigned short) saddrlen,
- saddr,
- (unsigned short) strlen (dpynumbuf),
- dpynumbuf,
- xauth_names_length,
- xauth_names,
- xauth_lengths);
- if (authptr) {
- auth_namelen = authptr->name_length;
- auth_name = (char *)authptr->name;
- auth_datalen = authptr->data_length;
- auth_data = (unsigned char *) authptr->data;
- } else {
- auth_namelen = 0;
- auth_name = NULL;
- auth_datalen = 0;
- auth_data = NULL;
- }
- }
-#ifdef HASXDMAUTH
- /*
- * build XDM-AUTHORIZATION-1 data
- */
- if (auth_namelen == 19 && !strncmp (auth_name, "XDM-AUTHORIZATION-1", 19))
- {
- int i, j;
- Time_t now;
- int family, addrlen;
- Xtransaddr *addr = NULL;
-
- for (j = 0; j < 8; j++)
- xdmcp_data[j] = auth_data[j];
-
- _X11TransGetMyAddr(trans_conn, &family, &addrlen, &addr);
-
- switch( family )
- {
-#ifdef AF_INET
- case AF_INET:
- {
- /*
- * addr will contain a sockaddr_in with all
- * of the members already in network byte order.
- */
-
- for(i=4; i<8; i++) /* do sin_addr */
- xdmcp_data[j++] = ((char *)addr)[i];
- for(i=2; i<4; i++) /* do sin_port */
- xdmcp_data[j++] = ((char *)addr)[i];
- break;
- }
-#endif /* AF_INET */
-#if defined(IPv6) && defined(AF_INET6)
- case AF_INET6:
- /* XXX This should probably never happen */
- {
- unsigned char ipv4mappedprefix[] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
-
- /* In the case of v4 mapped addresses send the v4
- part of the address - addr is already in network byte order */
- if (memcmp((char*)addr+8, ipv4mappedprefix, 12) == 0) {
- for (i = 20 ; i < 24; i++)
- xdmcp_data[j++] = ((char *)addr)[i];
-
- /* Port number */
- for (i=2; i<4; i++)
- xdmcp_data[j++] = ((char *)addr)[i];
- } else {
- /* Fake data to keep the data aligned. Otherwise the
- the server will bail about incorrect timing data */
- for (i = 0; i < 6; i++) {
- xdmcp_data[j++] = 0;
- }
- }
- break;
- }
-#endif /* AF_INET6 */
-#ifdef AF_UNIX
- case AF_UNIX:
- {
- /*
- * We don't use the sockaddr_un for this encoding.
- * Instead, we create a sockaddr_in filled with
- * a decreasing counter for the address, and the
- * pid for the port.
- */
-
- static unsigned long unix_addr = 0xFFFFFFFF;
- unsigned long the_addr;
- unsigned short the_port;
- unsigned long the_utime;
- struct timeval tp;
-
- X_GETTIMEOFDAY(&tp);
- _XLockMutex(_Xglobal_lock);
- the_addr = unix_addr--;
- _XUnlockMutex(_Xglobal_lock);
- the_utime = (unsigned long) tp.tv_usec;
- the_port = getpid ();
-
- xdmcp_data[j++] = (the_utime >> 24) & 0xFF;
- xdmcp_data[j++] = (the_utime >> 16) & 0xFF;
- xdmcp_data[j++] = ((the_utime >> 8) & 0xF0)
- | ((the_addr >> 8) & 0x0F);
- xdmcp_data[j++] = (the_addr >> 0) & 0xFF;
- xdmcp_data[j++] = (the_port >> 8) & 0xFF;
- xdmcp_data[j++] = (the_port >> 0) & 0xFF;
- break;
- }
-#endif /* AF_UNIX */
-#ifdef AF_DECnet
- case AF_DECnet:
- /*
- * What is the defined encoding for this?
- */
- break;
-#endif /* AF_DECnet */
- default:
- /*
- * Need to return some kind of errro status here.
- * maybe a NULL auth??
- */
- break;
- } /* switch */
-
- if (addr)
- free ((char *) addr);
-
- time (&now);
- xdmcp_data[j++] = (now >> 24) & 0xFF;
- xdmcp_data[j++] = (now >> 16) & 0xFF;
- xdmcp_data[j++] = (now >> 8) & 0xFF;
- xdmcp_data[j++] = (now >> 0) & 0xFF;
- while (j < 192 / 8)
- xdmcp_data[j++] = 0;
- _XLockMutex(_Xglobal_lock);
- /* this function might use static data, hence the lock around it */
- XdmcpWrap (xdmcp_data, auth_data + 8,
- xdmcp_data, j);
- _XUnlockMutex(_Xglobal_lock);
- auth_data = xdmcp_data;
- auth_datalen = j;
- }
-#endif /* HASXDMAUTH */
-#ifdef SECURE_RPC
- /*
- * The SUN-DES-1 authorization protocol uses the
- * "secure RPC" mechanism in SunOS 4.0+.
- */
- if (auth_namelen == 9 && !strncmp(auth_name, "SUN-DES-1", 9)) {
- char servernetname[MAXNETNAMELEN + 1];
-
- /*
- * Copy over the server's netname from the authorization
- * data field filled in by XauGetAuthByAddr().
- */
- if (auth_datalen > MAXNETNAMELEN) {
- auth_datalen = 0;
- auth_data = NULL;
- } else {
- memcpy(servernetname, auth_data, auth_datalen);
- servernetname[auth_datalen] = '\0';
-
- auth_datalen = sizeof (rpc_cred);
- if (auth_ezencode(servernetname, 100, rpc_cred,
- &auth_datalen))
- auth_data = (unsigned char *) rpc_cred;
- else {
- auth_datalen = 0;
- auth_data = NULL;
- }
- }
- }
-#endif
- if (saddr) free ((char *) saddr);
- if ((*auth_namelenp = auth_namelen))
- {
- if ((*auth_namep = Xmalloc(auth_namelen)))
- memcpy(*auth_namep, auth_name, auth_namelen);
- else
- *auth_namelenp = 0;
- }
- else
- *auth_namep = NULL;
- if ((*auth_datalenp = auth_datalen))
- {
- if ((*auth_datap = Xmalloc(auth_datalen)))
- memcpy(*auth_datap, auth_data, auth_datalen);
- else
- *auth_datalenp = 0;
- }
- else
- *auth_datap = NULL;
- if (authptr) XauDisposeAuth (authptr);
-}