781 lines
18 KiB
C
781 lines
18 KiB
C
/*
|
|
* Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan
|
|
* (Royal Institute of Technology, Stockholm, Sweden).
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
*
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* 3. Neither the name of the Institute nor the names of its contributors
|
|
* may be used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
* SUCH DAMAGE.
|
|
*/
|
|
|
|
#include "kx.h"
|
|
|
|
RCSID("$Id: common.c,v 1.1.1.2 2000/12/29 01:42:50 assar Exp $");
|
|
|
|
char x_socket[MaxPathLen];
|
|
|
|
u_int32_t display_num;
|
|
char display[MaxPathLen];
|
|
int display_size = sizeof(display);
|
|
char xauthfile[MaxPathLen];
|
|
int xauthfile_size = sizeof(xauthfile);
|
|
u_char cookie[16];
|
|
size_t cookie_len = sizeof(cookie);
|
|
|
|
#ifndef X_UNIX_PATH
|
|
#define X_UNIX_PATH "/tmp/.X11-unix/X"
|
|
#endif
|
|
|
|
#ifndef X_PIPE_PATH
|
|
#define X_PIPE_PATH "/tmp/.X11-pipe/X"
|
|
#endif
|
|
|
|
#ifndef INADDR_LOOPBACK
|
|
#define INADDR_LOOPBACK 0x7f000001
|
|
#endif
|
|
|
|
/*
|
|
* Allocate a unix domain socket in `s' for display `dpy' and with
|
|
* filename `pattern'
|
|
*
|
|
* 0 if all is OK
|
|
* -1 if bind failed badly
|
|
* 1 if dpy is already used */
|
|
|
|
static int
|
|
try_socket (struct x_socket *s, int dpy, const char *pattern)
|
|
{
|
|
struct sockaddr_un addr;
|
|
int fd;
|
|
|
|
fd = socket (AF_UNIX, SOCK_STREAM, 0);
|
|
if (fd < 0)
|
|
err (1, "socket AF_UNIX");
|
|
memset (&addr, 0, sizeof(addr));
|
|
addr.sun_family = AF_UNIX;
|
|
snprintf (addr.sun_path, sizeof(addr.sun_path), pattern, dpy);
|
|
if(bind(fd,
|
|
(struct sockaddr *)&addr,
|
|
sizeof(addr)) < 0) {
|
|
close (fd);
|
|
if (errno == EADDRINUSE ||
|
|
errno == EACCES /* Cray return EACCESS */
|
|
#ifdef ENOTUNIQ
|
|
|| errno == ENOTUNIQ /* bug in Solaris 2.4 */
|
|
#endif
|
|
)
|
|
return 1;
|
|
else
|
|
return -1;
|
|
}
|
|
s->fd = fd;
|
|
s->pathname = strdup (addr.sun_path);
|
|
if (s->pathname == NULL)
|
|
errx (1, "strdup: out of memory");
|
|
s->flags = UNIX_SOCKET;
|
|
return 0;
|
|
}
|
|
|
|
#ifdef MAY_HAVE_X11_PIPES
|
|
/*
|
|
* Allocate a stream (masqueraded as a named pipe)
|
|
*
|
|
* 0 if all is OK
|
|
* -1 if bind failed badly
|
|
* 1 if dpy is already used
|
|
*/
|
|
|
|
static int
|
|
try_pipe (struct x_socket *s, int dpy, const char *pattern)
|
|
{
|
|
char path[MAXPATHLEN];
|
|
int ret;
|
|
int fd;
|
|
int pipefd[2];
|
|
|
|
snprintf (path, sizeof(path), pattern, dpy);
|
|
fd = open (path, O_WRONLY | O_CREAT | O_EXCL, 0600);
|
|
if (fd < 0) {
|
|
if (errno == EEXIST)
|
|
return 1;
|
|
else
|
|
return -1;
|
|
}
|
|
|
|
close (fd);
|
|
|
|
ret = pipe (pipefd);
|
|
if (ret < 0)
|
|
err (1, "pipe");
|
|
|
|
ret = ioctl (pipefd[1], I_PUSH, "connld");
|
|
if (ret < 0) {
|
|
if(errno == ENOSYS)
|
|
return -1;
|
|
err (1, "ioctl I_PUSH");
|
|
}
|
|
|
|
ret = fattach (pipefd[1], path);
|
|
if (ret < 0)
|
|
err (1, "fattach %s", path);
|
|
|
|
s->fd = pipefd[0];
|
|
close (pipefd[1]);
|
|
s->pathname = strdup (path);
|
|
if (s->pathname == NULL)
|
|
errx (1, "strdup: out of memory");
|
|
s->flags = STREAM_PIPE;
|
|
return 0;
|
|
}
|
|
#endif /* MAY_HAVE_X11_PIPES */
|
|
|
|
/*
|
|
* Try to create a TCP socket in `s' corresponding to display `dpy'.
|
|
*
|
|
* 0 if all is OK
|
|
* -1 if bind failed badly
|
|
* 1 if dpy is already used
|
|
*/
|
|
|
|
static int
|
|
try_tcp (struct x_socket *s, int dpy)
|
|
{
|
|
struct sockaddr_in tcpaddr;
|
|
struct in_addr local;
|
|
int one = 1;
|
|
int fd;
|
|
|
|
memset(&local, 0, sizeof(local));
|
|
local.s_addr = htonl(INADDR_LOOPBACK);
|
|
|
|
fd = socket (AF_INET, SOCK_STREAM, 0);
|
|
if (fd < 0)
|
|
err (1, "socket AF_INET");
|
|
#if defined(TCP_NODELAY) && defined(HAVE_SETSOCKOPT)
|
|
setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, (void *)&one,
|
|
sizeof(one));
|
|
#endif
|
|
memset (&tcpaddr, 0, sizeof(tcpaddr));
|
|
tcpaddr.sin_family = AF_INET;
|
|
tcpaddr.sin_addr = local;
|
|
tcpaddr.sin_port = htons(6000 + dpy);
|
|
if (bind (fd, (struct sockaddr *)&tcpaddr,
|
|
sizeof(tcpaddr)) < 0) {
|
|
close (fd);
|
|
if (errno == EADDRINUSE)
|
|
return 1;
|
|
else
|
|
return -1;
|
|
}
|
|
s->fd = fd;
|
|
s->pathname = NULL;
|
|
s->flags = TCP;
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* The potential places to create unix sockets.
|
|
*/
|
|
|
|
static char *x_sockets[] = {
|
|
X_UNIX_PATH "%u",
|
|
"/var/X/.X11-unix/X" "%u",
|
|
"/usr/spool/sockets/X11/" "%u",
|
|
NULL
|
|
};
|
|
|
|
/*
|
|
* Dito for stream pipes.
|
|
*/
|
|
|
|
#ifdef MAY_HAVE_X11_PIPES
|
|
static char *x_pipes[] = {
|
|
X_PIPE_PATH "%u",
|
|
"/var/X/.X11-pipe/X" "%u",
|
|
NULL
|
|
};
|
|
#endif
|
|
|
|
/*
|
|
* Create the directory corresponding to dirname of `path' or fail.
|
|
*/
|
|
|
|
static void
|
|
try_mkdir (const char *path)
|
|
{
|
|
char *dir;
|
|
char *p;
|
|
int oldmask;
|
|
|
|
if((dir = strdup (path)) == NULL)
|
|
errx (1, "strdup: out of memory");
|
|
p = strrchr (dir, '/');
|
|
if (p)
|
|
*p = '\0';
|
|
|
|
oldmask = umask(0);
|
|
mkdir (dir, 01777);
|
|
umask (oldmask);
|
|
free (dir);
|
|
}
|
|
|
|
/*
|
|
* Allocate a display, returning the number of sockets in `number' and
|
|
* all the corresponding sockets in `sockets'. If `tcp_socket' is
|
|
* true, also allcoaet a TCP socket.
|
|
*
|
|
* The return value is the display allocated or -1 if an error occurred.
|
|
*/
|
|
|
|
int
|
|
get_xsockets (int *number, struct x_socket **sockets, int tcp_socket)
|
|
{
|
|
int dpy;
|
|
struct x_socket *s;
|
|
int n;
|
|
int i;
|
|
|
|
s = malloc (sizeof(*s) * 5);
|
|
if (s == NULL)
|
|
errx (1, "malloc: out of memory");
|
|
|
|
try_mkdir (X_UNIX_PATH);
|
|
try_mkdir (X_PIPE_PATH);
|
|
|
|
for(dpy = 4; dpy < 256; ++dpy) {
|
|
char **path;
|
|
int tmp = 0;
|
|
|
|
n = 0;
|
|
for (path = x_sockets; *path; ++path) {
|
|
tmp = try_socket (&s[n], dpy, *path);
|
|
if (tmp == -1) {
|
|
if (errno != ENOTDIR && errno != ENOENT)
|
|
return -1;
|
|
} else if (tmp == 1) {
|
|
while(--n >= 0) {
|
|
close (s[n].fd);
|
|
free (s[n].pathname);
|
|
}
|
|
break;
|
|
} else if (tmp == 0)
|
|
++n;
|
|
}
|
|
if (tmp == 1)
|
|
continue;
|
|
|
|
#ifdef MAY_HAVE_X11_PIPES
|
|
for (path = x_pipes; *path; ++path) {
|
|
tmp = try_pipe (&s[n], dpy, *path);
|
|
if (tmp == -1) {
|
|
if (errno != ENOTDIR && errno != ENOENT && errno != ENOSYS)
|
|
return -1;
|
|
} else if (tmp == 1) {
|
|
while (--n >= 0) {
|
|
close (s[n].fd);
|
|
free (s[n].pathname);
|
|
}
|
|
break;
|
|
} else if (tmp == 0)
|
|
++n;
|
|
}
|
|
|
|
if (tmp == 1)
|
|
continue;
|
|
#endif
|
|
|
|
if (tcp_socket) {
|
|
tmp = try_tcp (&s[n], dpy);
|
|
if (tmp == -1)
|
|
return -1;
|
|
else if (tmp == 1) {
|
|
while (--n >= 0) {
|
|
close (s[n].fd);
|
|
free (s[n].pathname);
|
|
}
|
|
break;
|
|
} else if (tmp == 0)
|
|
++n;
|
|
}
|
|
break;
|
|
}
|
|
if (dpy == 256)
|
|
errx (1, "no free x-servers");
|
|
for (i = 0; i < n; ++i)
|
|
if (s[i].flags & LISTENP
|
|
&& listen (s[i].fd, SOMAXCONN) < 0)
|
|
err (1, "listen %s", s[i].pathname ? s[i].pathname : "tcp");
|
|
*number = n;
|
|
*sockets = s;
|
|
return dpy;
|
|
}
|
|
|
|
/*
|
|
* Change owner on the `n' sockets in `sockets' to `uid', `gid'.
|
|
* Return 0 is succesful or -1 if an error occurred.
|
|
*/
|
|
|
|
int
|
|
chown_xsockets (int n, struct x_socket *sockets, uid_t uid, gid_t gid)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < n; ++i)
|
|
if (sockets[i].pathname != NULL)
|
|
if (chown (sockets[i].pathname, uid, gid) < 0)
|
|
return -1;
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Connect to local display `dnr' with local transport.
|
|
* Return a file descriptor.
|
|
*/
|
|
|
|
int
|
|
connect_local_xsocket (unsigned dnr)
|
|
{
|
|
int fd;
|
|
struct sockaddr_un addr;
|
|
char **path;
|
|
|
|
for (path = x_sockets; *path; ++path) {
|
|
fd = socket (AF_UNIX, SOCK_STREAM, 0);
|
|
if (fd < 0)
|
|
err (1, "socket AF_UNIX");
|
|
memset (&addr, 0, sizeof(addr));
|
|
addr.sun_family = AF_UNIX;
|
|
snprintf (addr.sun_path, sizeof(addr.sun_path), *path, dnr);
|
|
if (connect (fd, (struct sockaddr *)&addr, sizeof(addr)) == 0)
|
|
return fd;
|
|
}
|
|
err (1, "connecting to local display %u", dnr);
|
|
}
|
|
|
|
/*
|
|
* Create a cookie file with a random cookie for the localhost. The
|
|
* file name will be stored in `xauthfile' (but not larger than
|
|
* `xauthfile_size'), and the cookie returned in `cookie', `cookie_sz'.
|
|
* Return 0 if succesful, or errno.
|
|
*/
|
|
|
|
int
|
|
create_and_write_cookie (char *xauthfile,
|
|
size_t xauthfile_size,
|
|
u_char *cookie,
|
|
size_t cookie_sz)
|
|
{
|
|
Xauth auth;
|
|
char tmp[64];
|
|
int fd;
|
|
FILE *f;
|
|
char hostname[MaxHostNameLen];
|
|
struct in_addr loopback;
|
|
int saved_errno;
|
|
|
|
gethostname (hostname, sizeof(hostname));
|
|
loopback.s_addr = htonl(INADDR_LOOPBACK);
|
|
|
|
auth.family = FamilyLocal;
|
|
auth.address = hostname;
|
|
auth.address_length = strlen(auth.address);
|
|
snprintf (tmp, sizeof(tmp), "%d", display_num);
|
|
auth.number_length = strlen(tmp);
|
|
auth.number = tmp;
|
|
auth.name = COOKIE_TYPE;
|
|
auth.name_length = strlen(auth.name);
|
|
auth.data_length = cookie_sz;
|
|
auth.data = (char*)cookie;
|
|
des_rand_data (cookie, cookie_sz);
|
|
|
|
strlcpy(xauthfile, "/tmp/AXXXXXX", xauthfile_size);
|
|
fd = mkstemp(xauthfile);
|
|
if(fd < 0) {
|
|
saved_errno = errno;
|
|
syslog(LOG_ERR, "create_and_write_cookie: mkstemp: %m");
|
|
return saved_errno;
|
|
}
|
|
f = fdopen(fd, "r+");
|
|
if(f == NULL){
|
|
saved_errno = errno;
|
|
close(fd);
|
|
return errno;
|
|
}
|
|
if(XauWriteAuth(f, &auth) == 0) {
|
|
saved_errno = errno;
|
|
fclose(f);
|
|
return saved_errno;
|
|
}
|
|
|
|
/*
|
|
* I would like to write a cookie for localhost:n here, but some
|
|
* stupid code in libX11 will not look for cookies of that type,
|
|
* so we are forced to use FamilyWild instead.
|
|
*/
|
|
|
|
auth.family = FamilyWild;
|
|
auth.address_length = 0;
|
|
|
|
#if 0 /* XXX */
|
|
auth.address = (char *)&loopback;
|
|
auth.address_length = sizeof(loopback);
|
|
#endif
|
|
|
|
if (XauWriteAuth(f, &auth) == 0) {
|
|
saved_errno = errno;
|
|
fclose (f);
|
|
return saved_errno;
|
|
}
|
|
|
|
if(fclose(f))
|
|
return errno;
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Verify and remove cookies. Read and parse a X-connection from
|
|
* `fd'. Check the cookie used is the same as in `cookie'. Remove the
|
|
* cookie and copy the rest of it to `sock'.
|
|
* Expect cookies iff cookiesp.
|
|
* Return 0 iff ok.
|
|
*
|
|
* The protocol is as follows:
|
|
*
|
|
* C->S: [Bl] 1
|
|
* unused 1
|
|
* protocol major version 2
|
|
* protocol minor version 2
|
|
* length of auth protocol name(n) 2
|
|
* length of auth protocol data 2
|
|
* unused 2
|
|
* authorization protocol name n
|
|
* pad pad(n)
|
|
* authorization protocol data d
|
|
* pad pad(d)
|
|
*
|
|
* S->C: Failed
|
|
* 0 1
|
|
* length of reason 1
|
|
* protocol major version 2
|
|
* protocol minor version 2
|
|
* length in 4 bytes unit of
|
|
* additional data (n+p)/4 2
|
|
* reason n
|
|
* unused p = pad(n)
|
|
*/
|
|
|
|
int
|
|
verify_and_remove_cookies (int fd, int sock, int cookiesp)
|
|
{
|
|
u_char beg[12];
|
|
int bigendianp;
|
|
unsigned n, d, npad, dpad;
|
|
char *protocol_name, *protocol_data;
|
|
u_char zeros[6] = {0, 0, 0, 0, 0, 0};
|
|
u_char refused[20] = {0, 10,
|
|
0, 0, /* protocol major version */
|
|
0, 0, /* protocol minor version */
|
|
0, 0, /* length of additional data / 4 */
|
|
'b', 'a', 'd', ' ', 'c', 'o', 'o', 'k', 'i', 'e',
|
|
0, 0};
|
|
|
|
if (net_read (fd, beg, sizeof(beg)) != sizeof(beg))
|
|
return 1;
|
|
if (net_write (sock, beg, 6) != 6)
|
|
return 1;
|
|
bigendianp = beg[0] == 'B';
|
|
if (bigendianp) {
|
|
n = (beg[6] << 8) | beg[7];
|
|
d = (beg[8] << 8) | beg[9];
|
|
} else {
|
|
n = (beg[7] << 8) | beg[6];
|
|
d = (beg[9] << 8) | beg[8];
|
|
}
|
|
npad = (4 - (n % 4)) % 4;
|
|
dpad = (4 - (d % 4)) % 4;
|
|
protocol_name = malloc(n + npad);
|
|
if (n + npad != 0 && protocol_name == NULL)
|
|
return 1;
|
|
protocol_data = malloc(d + dpad);
|
|
if (d + dpad != 0 && protocol_data == NULL) {
|
|
free (protocol_name);
|
|
return 1;
|
|
}
|
|
if (net_read (fd, protocol_name, n + npad) != n + npad)
|
|
goto fail;
|
|
if (net_read (fd, protocol_data, d + dpad) != d + dpad)
|
|
goto fail;
|
|
if (cookiesp) {
|
|
if (strncmp (protocol_name, COOKIE_TYPE, strlen(COOKIE_TYPE)) != 0)
|
|
goto refused;
|
|
if (d != cookie_len ||
|
|
memcmp (protocol_data, cookie, cookie_len) != 0)
|
|
goto refused;
|
|
}
|
|
free (protocol_name);
|
|
free (protocol_data);
|
|
if (net_write (sock, zeros, 6) != 6)
|
|
return 1;
|
|
return 0;
|
|
refused:
|
|
refused[2] = beg[2];
|
|
refused[3] = beg[3];
|
|
refused[4] = beg[4];
|
|
refused[5] = beg[5];
|
|
if (bigendianp)
|
|
refused[7] = 3;
|
|
else
|
|
refused[6] = 3;
|
|
|
|
net_write (fd, refused, sizeof(refused));
|
|
fail:
|
|
free (protocol_name);
|
|
free (protocol_data);
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* Return 0 iff `cookie' is compatible with the cookie for the
|
|
* localhost with name given in `disp_he' and display number in
|
|
* `disp_nr'.
|
|
*/
|
|
|
|
static int
|
|
match_local_auth (Xauth* auth, struct hostent *disp_he, int disp_nr)
|
|
{
|
|
int auth_disp;
|
|
char *tmp_disp;
|
|
|
|
tmp_disp = strndup (auth->number, auth->number_length);
|
|
if (tmp_disp == NULL)
|
|
return -1;
|
|
auth_disp = atoi(tmp_disp);
|
|
free (tmp_disp);
|
|
if (auth_disp != disp_nr)
|
|
return 1;
|
|
if (auth->family == FamilyLocal
|
|
|| auth->family == FamilyWild) {
|
|
int i;
|
|
|
|
if (strncmp (auth->address,
|
|
disp_he->h_name,
|
|
auth->address_length) == 0)
|
|
return 0;
|
|
|
|
for (i = 0; disp_he->h_aliases[i] != NULL; ++i)
|
|
if (strncmp (auth->address,
|
|
disp_he->h_aliases[i],
|
|
auth->address_length) == 0)
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* Find `our' cookie from the cookie file `f' and return it or NULL.
|
|
*/
|
|
|
|
static Xauth*
|
|
find_auth_cookie (FILE *f)
|
|
{
|
|
Xauth *ret = NULL;
|
|
char local_hostname[MaxHostNameLen];
|
|
char *display = getenv("DISPLAY");
|
|
char *colon;
|
|
struct hostent *display_he;
|
|
int disp;
|
|
|
|
if (display == NULL)
|
|
display = ":0";
|
|
colon = strchr (display, ':');
|
|
if (colon == NULL)
|
|
disp = 0;
|
|
else {
|
|
*colon = '\0';
|
|
disp = atoi (colon + 1);
|
|
}
|
|
if (strcmp (display, "") == 0
|
|
|| strncmp (display, "unix", 4) == 0
|
|
|| strncmp (display, "localhost", 9) == 0) {
|
|
gethostname (local_hostname, sizeof(local_hostname));
|
|
display = local_hostname;
|
|
}
|
|
display_he = gethostbyname (display);
|
|
if (display_he == NULL) {
|
|
warnx ("gethostbyname %s: %s", display, hstrerror(h_errno));
|
|
return NULL;
|
|
}
|
|
|
|
for (; (ret = XauReadAuth (f)) != NULL; XauDisposeAuth(ret)) {
|
|
if (match_local_auth (ret, display_he, disp) == 0)
|
|
return ret;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* Get rid of the cookie that we were sent and get the correct one
|
|
* from our own cookie file instead.
|
|
*/
|
|
|
|
int
|
|
replace_cookie(int xserver, int fd, char *filename, int cookiesp) /* XXX */
|
|
{
|
|
u_char beg[12];
|
|
int bigendianp;
|
|
unsigned n, d, npad, dpad;
|
|
FILE *f;
|
|
u_char zeros[6] = {0, 0, 0, 0, 0, 0};
|
|
|
|
if (net_read (fd, beg, sizeof(beg)) != sizeof(beg))
|
|
return 1;
|
|
if (net_write (xserver, beg, 6) != 6)
|
|
return 1;
|
|
bigendianp = beg[0] == 'B';
|
|
if (bigendianp) {
|
|
n = (beg[6] << 8) | beg[7];
|
|
d = (beg[8] << 8) | beg[9];
|
|
} else {
|
|
n = (beg[7] << 8) | beg[6];
|
|
d = (beg[9] << 8) | beg[8];
|
|
}
|
|
if (n != 0 || d != 0)
|
|
return 1;
|
|
f = fopen(filename, "r");
|
|
if (f != NULL) {
|
|
Xauth *auth = find_auth_cookie (f);
|
|
u_char len[6] = {0, 0, 0, 0, 0, 0};
|
|
|
|
fclose (f);
|
|
|
|
if (auth != NULL) {
|
|
n = auth->name_length;
|
|
d = auth->data_length;
|
|
} else {
|
|
n = 0;
|
|
d = 0;
|
|
}
|
|
if (bigendianp) {
|
|
len[0] = n >> 8;
|
|
len[1] = n & 0xFF;
|
|
len[2] = d >> 8;
|
|
len[3] = d & 0xFF;
|
|
} else {
|
|
len[0] = n & 0xFF;
|
|
len[1] = n >> 8;
|
|
len[2] = d & 0xFF;
|
|
len[3] = d >> 8;
|
|
}
|
|
if (net_write (xserver, len, 6) != 6) {
|
|
XauDisposeAuth(auth);
|
|
return 1;
|
|
}
|
|
if(n != 0 && net_write (xserver, auth->name, n) != n) {
|
|
XauDisposeAuth(auth);
|
|
return 1;
|
|
}
|
|
npad = (4 - (n % 4)) % 4;
|
|
if (npad && net_write (xserver, zeros, npad) != npad) {
|
|
XauDisposeAuth(auth);
|
|
return 1;
|
|
}
|
|
if (d != 0 && net_write (xserver, auth->data, d) != d) {
|
|
XauDisposeAuth(auth);
|
|
return 1;
|
|
}
|
|
XauDisposeAuth(auth);
|
|
dpad = (4 - (d % 4)) % 4;
|
|
if (dpad && net_write (xserver, zeros, dpad) != dpad)
|
|
return 1;
|
|
} else {
|
|
if(net_write(xserver, zeros, 6) != 6)
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Some simple controls on the address and corresponding socket
|
|
*/
|
|
|
|
int
|
|
suspicious_address (int sock, struct sockaddr_in addr)
|
|
{
|
|
char data[40];
|
|
int len = sizeof(data);
|
|
|
|
return addr.sin_addr.s_addr != htonl(INADDR_LOOPBACK)
|
|
#if defined(IP_OPTIONS) && defined(HAVE_GETSOCKOPT)
|
|
|| getsockopt (sock, IPPROTO_IP, IP_OPTIONS, data, &len) < 0
|
|
|| len != 0
|
|
#endif
|
|
;
|
|
}
|
|
|
|
/*
|
|
* This really sucks, but these functions are used and if we're not
|
|
* linking against libkrb they don't exist. Using the heimdal storage
|
|
* functions will not work either cause we do not always link with
|
|
* libkrb5 either.
|
|
*/
|
|
|
|
#ifndef KRB4
|
|
|
|
int
|
|
krb_get_int(void *f, u_int32_t *to, int size, int lsb)
|
|
{
|
|
int i;
|
|
unsigned char *from = (unsigned char *)f;
|
|
|
|
*to = 0;
|
|
if(lsb){
|
|
for(i = size-1; i >= 0; i--)
|
|
*to = (*to << 8) | from[i];
|
|
}else{
|
|
for(i = 0; i < size; i++)
|
|
*to = (*to << 8) | from[i];
|
|
}
|
|
return size;
|
|
}
|
|
|
|
int
|
|
krb_put_int(u_int32_t from, void *to, size_t rem, int size)
|
|
{
|
|
int i;
|
|
unsigned char *p = (unsigned char *)to;
|
|
|
|
if (rem < size)
|
|
return -1;
|
|
|
|
for(i = size - 1; i >= 0; i--){
|
|
p[i] = from & 0xff;
|
|
from >>= 8;
|
|
}
|
|
return size;
|
|
}
|
|
|
|
#endif /* !KRB4 */
|