merged in TCP-branch

git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@763 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
Assar Westerlund
1996-09-27 14:38:32 +00:00
parent 792a7cc84c
commit 4f06a53bad
4 changed files with 226 additions and 52 deletions

View File

@@ -85,56 +85,109 @@ childhandler (int sig)
SIGRETURN(0);
}
/*
* Allocate and listen on a local X server socket.
*/
#define TMPX11 "/tmp/.X11-unix"
#ifndef X_UNIX_PATH
#define X_UNIX_PATH "/tmp/.X11-unix/X"
#endif
char x_socket[MaxPathLen];
/*
* Allocate and listen on a local X server socket and a TCP socket.
* Return the display number.
*/
int
get_local_xsocket (int *num)
get_xsockets (int *unix_socket, int *tcp_socket)
{
int fd;
struct sockaddr_un addr;
int unixfd, tcpfd;
struct sockaddr_un unixaddr;
struct sockaddr_in tcpaddr;
int dpy;
int oldmask;
struct hostent *h;
struct in_addr local;
char *dir, *p;
dir = strdup (X_UNIX_PATH);
p = strchr (dir, '/');
if (p)
*p = '\0';
oldmask = umask(0);
mkdir (TMPX11, 01777);
mkdir (dir, 01777);
umask (oldmask);
free (dir);
h = gethostbyname ("localhost");
if (h)
memcpy (&local, h->h_addr, h->h_length);
else
local.s_addr = inet_addr ("127.0.0.1");
fd = socket (AF_UNIX, SOCK_STREAM, 0);
if (fd < 0) {
fprintf (stderr, "%s: socket: %s\n", prog, strerror(errno));
return fd;
}
addr.sun_family = AF_UNIX;
for(dpy = 4; dpy < 256; ++dpy) {
struct stat statbuf;
unixfd = socket (AF_UNIX, SOCK_STREAM, 0);
if (unixfd < 0) {
fprintf (stderr, "%s: socket: %s\n", prog, strerror(errno));
return -1;
}
memset (&unixaddr, 0, sizeof(unixaddr));
unixaddr.sun_family = AF_UNIX;
sprintf (unixaddr.sun_path, X_UNIX_PATH "%u", dpy);
if(bind(unixfd,
(struct sockaddr *)&unixaddr,
sizeof(unixaddr)) < 0) {
close (unixfd);
if (errno == EADDRINUSE ||
errno == EACCES) /* Cray return EACCESS */
continue;
else
return -1;
}
sprintf (addr.sun_path, TMPX11 "/X%u", dpy);
if(bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
if (errno == EADDRINUSE)
continue;
else
return -1;
else
break;
if (tcp_socket) {
tcpfd = socket (AF_INET, SOCK_STREAM, 0);
if (tcpfd < 0) {
fprintf (stderr, "%s: socket: %s\n", prog,
strerror(errno));
close (unixfd);
return -1;
}
memset (&tcpaddr, 0, sizeof(tcpaddr));
tcpaddr.sin_family = AF_INET;
tcpaddr.sin_addr = local;
tcpaddr.sin_port = htons(6000 + dpy);
if (bind (tcpfd, (struct sockaddr *)&tcpaddr,
sizeof(tcpaddr)) < 0) {
close (unixfd);
close (tcpfd);
if (errno == EADDRINUSE)
continue;
else
return -1;
}
}
break;
}
if (dpy == 256) {
fprintf (stderr, "%s: no free x-servers\n", prog);
return -1;
}
if (listen (fd, SOMAXCONN) < 0) {
if (listen (unixfd, SOMAXCONN) < 0) {
fprintf (stderr, "%s: listen: %s\n", prog,
strerror(errno));
return -1;
}
strcpy(x_socket, addr.sun_path);
*num = dpy;
return fd;
if (tcp_socket)
if (listen (tcpfd, SOMAXCONN) < 0) {
fprintf (stderr, "%s: listen: %s\n", prog,
strerror(errno));
return -1;
}
strcpy(x_socket, unixaddr.sun_path);
*unix_socket = unixfd;
if (tcp_socket)
*tcp_socket = tcpfd;
return dpy;
}
/*

View File

@@ -41,7 +41,7 @@ connect_host (char *host, des_cblock *key, des_key_schedule schedule,
memset (&thataddr, 0, sizeof(thataddr));
thataddr.sin_family = AF_INET;
thataddr.sin_port = k_getportbyname ("kx", "tcp", htons(2111));
thataddr.sin_port = k_getportbyname ("kx", "tcp", htons(KX_PORT));
memcpy (&thataddr.sin_addr, hostent->h_addr, sizeof(thataddr.sin_addr));
s = socket (AF_INET, SOCK_STREAM, 0);
@@ -261,11 +261,15 @@ doit (char *host, int passivep)
fprintf (stderr, "%s: listen: %s\n", prog, strerror(errno));
return 1;
}
if (krb_net_write (otherside, &newaddr.sin_port,
sizeof(newaddr.sin_port))
!= sizeof(newaddr.sin_port)) {
fprintf (stderr, "%s: write: %s\n", prog, strerror(errno));
return 1;
{
char tmp[6];
sprintf (tmp, "%d", ntohs(newaddr.sin_port));
if (krb_net_write (otherside, tmp, sizeof(tmp))
!= sizeof(tmp)) {
fprintf (stderr, "%s: write: %s\n", prog, strerror(errno));
return 1;
}
}
/* close (otherside); */
fn = passive;
@@ -280,8 +284,8 @@ doit (char *host, int passivep)
fclose(stdout);
}
} else {
rendez_vous = get_local_xsocket (&display_num); /* XXX */
if (rendez_vous < 0)
display_num = get_xsockets (&rendez_vous, NULL);
if (display_num < 0)
return 1;
fn = active;
}

View File

@@ -11,21 +11,44 @@
#include <errno.h>
#include <pwd.h>
#include <signal.h>
#ifdef HAVE_SYSLOG_H
#include <syslog.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef HAVE_SYS_UN_H
#include <sys/un.h>
#endif
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xauth.h>
#include <krb.h>
@@ -36,10 +59,6 @@
#define max(a,b) (((a)>(b))?(a):(b))
#endif
#ifndef SOMAXCONN
#define SOMAXCONN 5
#endif
#ifndef LOG_DAEMON
#define openlog(id,option,facility) openlog((id),(option))
#endif
@@ -53,5 +72,7 @@ RETSIGTYPE childhandler (int);
extern char x_socket[];
int get_local_xsocket (int *num);
int get_xsockets (int *unix_socket, int *tcp_socket);
int connect_local_xsocket (unsigned dnr);
#define KX_PORT 2111

View File

@@ -161,6 +161,10 @@ check_user_console ()
return 0;
}
#ifndef INADDR_LOOPBACK
#define INADDR_LOOPBACK 0x7f000001
#endif
static int
create_and_write_cookie (char *xauthfile,
u_char *cookie,
@@ -170,9 +174,13 @@ create_and_write_cookie (char *xauthfile,
char tmp[64];
FILE *f;
char hostname[MaxHostNameLen];
struct in_addr loopback;
struct hostent *h;
auth.family = FamilyLocal;
k_gethostname (hostname, sizeof(hostname));
loopback.s_addr = htonl(INADDR_LOOPBACK);
auth.family = FamilyLocal;
auth.address = hostname;
auth.address_length = strlen(auth.address);
sprintf (tmp, "%d", display_num);
@@ -190,19 +198,61 @@ create_and_write_cookie (char *xauthfile,
fclose(f);
return 1;
}
h = gethostbyname (hostname);
if (h == NULL) {
fclose (f);
return 1;
}
/*
* 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) {
fclose (f);
return 1;
}
if(fclose(f))
return 1;
return 0;
}
/*
* Some simple controls on the address and corresponding socket
*/
static int
doit(int sock)
suspicious_address (int sock, struct sockaddr_in addr)
{
char data[40];
int len = sizeof(data);
return addr.sin_addr.s_addr != htonl(INADDR_LOOPBACK)
|| getsockopt (sock, IPPROTO_IP, IP_OPTIONS, data, &len) < 0
|| len != 0;
}
static int
doit(int sock, int tcpp)
{
u_char passivep;
struct sockaddr_in thataddr;
des_key_schedule schedule;
des_cblock key;
int localx;
int localx, tcpx;
u_int32_t tmp;
if (recv_conn (sock, &key, schedule, &thataddr))
@@ -212,8 +262,8 @@ doit(int sock)
if (passivep) {
char tmp[16];
localx = get_local_xsocket (&display_num);
if (localx < 0)
display_num = get_xsockets (&localx, tcpp ? &tcpx : NULL);
if (display_num < 0)
return 1;
sprintf (tmp, "%u", display_num);
if (krb_net_write (sock, tmp, sizeof(tmp)) != sizeof(tmp))
@@ -225,9 +275,13 @@ doit(int sock)
if(create_and_write_cookie (xauthfile, cookie,
sizeof(cookie)))
return 1;
if (krb_net_read (sock, &thataddr.sin_port, sizeof(thataddr.sin_port))
!= sizeof(thataddr.sin_port))
return 1;
{
char tmp[6];
if(krb_net_read(sock, tmp, sizeof(tmp)) != sizeof(tmp))
return -1;
thataddr.sin_port = htons(atoi(tmp));
}
for (;;) {
pid_t child;
@@ -238,6 +292,8 @@ doit(int sock)
FD_ZERO(&fds);
FD_SET(localx, &fds);
FD_SET(sock, &fds);
if (tcpp)
FD_SET(tcpx, &fds);
if(select(FD_SETSIZE, &fds, NULL, NULL, NULL) <=0)
continue;
if(FD_ISSET(sock, &fds)){
@@ -245,9 +301,19 @@ doit(int sock)
*/
cleanup();
exit(0);
}else if(FD_ISSET(localx, &fds))
} else if(FD_ISSET(localx, &fds))
fd = accept (localx, NULL, &zero);
else
else if(tcpp && FD_ISSET(tcpx, &fds)) {
struct sockaddr_in peer;
int len = sizeof(peer);
fd = accept (tcpx, (struct sockaddr *)&peer, &len);
/* XXX */
if (fd >= 0 && suspicious_address (fd, peer)) {
close (fd);
continue;
}
} else
continue;
if (fd < 0)
if (errno == EINTR)
@@ -264,6 +330,8 @@ doit(int sock)
return fatal(sock, msg);
} else if (child == 0) {
close (localx);
if (tcpp)
close (tcpx);
return doit_conn (fd, &thataddr, &key, schedule);
} else {
close (fd);
@@ -280,6 +348,13 @@ doit(int sock)
}
}
static void
usage ()
{
fprintf (stderr, "Usage: %s [-i] [-t]\n", prog);
exit (1);
}
/*
* xkd - receive a forwarded X conncection
*/
@@ -287,9 +362,30 @@ doit(int sock)
int
main (int argc, char **argv)
{
int c;
int no_inetd = 0;
int tcpp = 0;
prog = argv[0];
while( (c = getopt (argc, argv, "it")) != EOF) {
switch (c) {
case 'i':
no_inetd = 1;
break;
case 't':
tcpp = 1;
break;
case '?':
default:
fprintf (stderr, "%s: unknown option '%c'\n", prog, c);
usage ();
}
}
if (no_inetd)
mini_inetd (k_getportbyname("kx", "tcp", htons(KX_PORT)));
openlog(prog, LOG_PID|LOG_CONS, LOG_DAEMON);
signal (SIGCHLD, childhandler);
return doit(0);
return doit(STDIN_FILENO, tcpp);
}