Please mail bugs and suggestions to the author at the above address.
*/
-/* HISTORY
- * 11-Nov-1990 bristor@simba
+/* HISTORY
+ * 11-Nov-1990 bristor@simba
* Added EOT stuff.
*/
* ../etc/gnuserv.README relative to the directory containing this file)
*/
-#if 0
-static char rcsid [] = "!Header: gnuserv.c,v 2.1 95/02/16 11:58:27 arup alpha !";
-#endif
-
#include "gnuserv.h"
+char gnuserv_version[] = "gnuserv version" GNUSERV_VERSION;
+
+
#ifdef USE_LITOUT
#ifdef linux
#include <bsd/sgtty.h>
#ifdef SYSV_IPC
int ipc_qid = 0; /* ipc message queue id */
-int ipc_wpid = 0; /* watchdog task pid */
+pid_t ipc_wpid = 0; /* watchdog task pid */
/*
ipc_exit (int stat)
{
msgctl (ipc_qid,IPC_RMID,0);
-
+
if (ipc_wpid != 0)
kill (ipc_wpid, SIGKILL);
} /* ipc_handle_signal */
-/*
+/*
ipc_spawn_watchdog -- spawn a watchdog task to clean up the message queue should the
server process die.
*/
{
if ((ipc_wpid = fork ()) == 0)
{ /* child process */
- int ppid = getppid (); /* parent's process id */
+ pid_t ppid = getppid (); /* parent's process id */
setpgrp(); /* gnu kills process group on exit */
msgctl (ipc_qid, IPC_STAT, &msg_st);
strncpy (buf, msgp->mtext, len);
buf[len] = '\0'; /* terminate */
-
+
printf ("%d %s", ipc_qid, buf);
fflush (stdout);
/* read in "n/m:" (n=client fd, m=message length) */
- while (offset < (GSERV_BUFSZ-1) &&
+ while (offset < (GSERV_BUFSZ-1) &&
((len = read (0, buf + offset, 1)) > 0) &&
buf[offset] != ':')
{
exit (1);
}
- /* Send this string off, but only if we have enough space */
+ /* Send this string off, but only if we have enough space */
if (GSERV_BUFSZ > total)
{
int len;
printf("%d ",s);
-
+
/* read until we get a newline or no characters */
while ((len = recv(s,buf,GSERV_BUFSZ-1,0)) > 0) {
buf[len] = '\0';
fprintf(stderr,"%s: unable to recv\n",progname);
exit(1);
} /* if */
-
+
} /* echo_request */
char buf[GSERV_BUFSZ+1];
int offset=0;
int s;
- int len;
+ int len = 0;
int result_len;
/* read in "n/m:" (n=client fd, m=message length) */
- while (offset < GSERV_BUFSZ &&
+ while (offset < GSERV_BUFSZ &&
((len = read(0,buf+offset,1)) > 0) &&
buf[offset] != ':') {
offset += len;
fprintf(stderr,"%s: unable to read\n",progname);
exit(1);
}
-
+
/* parse the response from emacs, getting client fd & result length */
buf[offset] = '\0';
sscanf(buf,"%d/%d", &s, &result_len);
/* send the newline */
buf[1] = '\0';
send_string(s,buf);
- close(s);
+ close(s);
} /* handle_response */
#endif /* INTERNET_DOMAIN_SOCKETS || UNIX_DOMAIN_SOCKETS */
#ifdef INTERNET_DOMAIN_SOCKETS
struct entry {
- u_long host_addr;
+ unsigned long host_addr;
struct entry *next;
};
# include <X11/Xauth.h>
static Xauth *server_xauth = NULL;
-#endif
+#endif
-static int
+static int
timed_read (int fd, char *buf, int max, int timeout, int one_line)
{
fd_set rmask;
char c = 0;
int nbytes = 0;
int r;
-
+
tv.tv_sec = timeout;
tv.tv_usec = 0;
FD_ZERO(&rmask);
FD_SET(fd, &rmask);
-
+
do
{
r = select(fd + 1, &rmask, NULL, NULL, &tv);
return nbytes;
}
-
-
+
+
/*
permitted -- return whether a given host is allowed to connect to the server.
*/
static int
-permitted (u_long host_addr, int fd)
+permitted (unsigned long host_addr, int fd)
{
int key;
struct entry *entry;
- char auth_protocol[128];
+ char auth_protocol[128];
char buf[1024];
int auth_data_len;
+ int auth_data_pos;
+ int auth_mismatches;
if (fd > 0)
{
/* we are checking permission on a real connection */
/* Read auth protocol name */
-
+
if (timed_read(fd, auth_protocol, AUTH_NAMESZ, AUTH_TIMEOUT, 1) <= 0)
return FALSE;
if (strcmp (auth_protocol, DEFAUTH_NAME) &&
strcmp (auth_protocol, MCOOKIE_NAME))
{
- printf ("authentication protocol (%s) from client is invalid...\n",
+ printf ("authentication protocol (%s) from client is invalid...\n",
auth_protocol);
printf ("... Was the client an old version of gnuclient/gnudoit?\004\n");
-
+
return FALSE;
}
auth_data_len = atoi(buf);
+ if (auth_data_len <= 0 || auth_data_len > sizeof(buf))
+ {
+ return FALSE;
+ }
+
if (timed_read(fd, buf, auth_data_len, AUTH_TIMEOUT, 0) != auth_data_len)
return FALSE;
-
+
#ifdef AUTH_MAGIC_COOKIE
- if (server_xauth && server_xauth->data &&
- !memcmp(buf, server_xauth->data, auth_data_len))
- {
+ if (server_xauth && server_xauth->data)
+ {
+ /* Do a compare without comprising info about
+ the size of the cookie */
+ auth_mismatches =
+ ( auth_data_len ^
+ server_xauth->data_length );
+
+ for(auth_data_pos=0; auth_data_pos < auth_data_len; ++auth_data_pos)
+ auth_mismatches |=
+ ( buf[auth_data_pos] ^
+ server_xauth->data[auth_data_pos % server_xauth->data_length]);
+
+ if (auth_mismatches == 0)
return TRUE;
- }
-#else
+
+ for(;rand() % 1000;);
+ }
+
+#else
printf ("client tried Xauth, but server is not compiled with Xauth\n");
#endif
-
+
/*
* auth failed, but allow this to fall through to the GNU_SECURE
* protocol....
printf ("Xauth authentication failed, trying GNU_SECURE auth...\004\n");
}
-
+
/* Other auth protocols go here, and should execute only if the
* auth_protocol name matches.
*/
/* Now, try the old GNU_SECURE stuff... */
-
+
/* First find the hash key */
key = HASH(host_addr) % TABLE_SIZE;
-
+
/* Now check the chain for that hash key */
for(entry=permitted_hosts[key]; entry != NULL; entry=entry->next)
- if (host_addr == entry->host_addr)
+ if (host_addr == entry->host_addr)
return(TRUE);
-
+
return(FALSE);
} /* permitted */
-/*
+/*
add_host -- add the given host to the list of permitted hosts, provided it isn't
already there.
-*/
+*/
static void
-add_host (u_long host_addr)
+add_host (unsigned long host_addr)
{
int key;
struct entry *new_entry;
-
+
if (!permitted(host_addr, -1))
{
if ((new_entry = (struct entry *) malloc(sizeof(struct entry))) == NULL) {
FILE *host_file;
char *file_name;
char hostname[HOSTNAMSZ];
- u_int host_addr;
+ unsigned int host_addr;
int i, hosts=0;
-
+
/* Make sure every entry is null */
for (i=0; i<TABLE_SIZE; i++)
permitted_hosts[i] = NULL;
if ((host_addr = internet_addr(hostname)) == -1)
{
- fprintf(stderr,"%s: unable to find %s in /etc/hosts or from YP",
+ fprintf(stderr,"%s: unable to find %s in /etc/hosts or from YP",
progname,hostname);
exit(1);
} /* if */
#ifdef AUTH_MAGIC_COOKIE
-
- server_xauth = XauGetAuthByAddr (FamilyInternet,
+
+ server_xauth = XauGetAuthByAddr (FamilyInternet,
sizeof(host_addr), (char *)&host_addr,
- strlen(MCOOKIE_SCREEN), MCOOKIE_SCREEN,
+ strlen(MCOOKIE_SCREEN), MCOOKIE_SCREEN,
strlen(MCOOKIE_X_NAME), MCOOKIE_X_NAME);
hosts++;
#endif /* AUTH_MAGIC_COOKIE */
-
+
#if 0 /* Don't even want to allow access from the local host by default */
add_host(host_addr); /* add local host */
-#endif
+#endif
if (((file_name = getenv("GNU_SECURE")) != NULL && /* security file */
(host_file = fopen(file_name,"r")) != NULL)) /* opened ok */
struct sockaddr_in server; /* for local socket address */
char *ptr; /* ptr to return from getenv */
- if (setup_table() == 0)
+ if (setup_table() == 0)
return -1;
/* clear out address structure */
- memset((char *)&server,0,sizeof(struct sockaddr_in));
-
+ memset (&server, '\0', sizeof (server));
+
/* Set up address structure for the listen socket. */
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(DEFAULT_PORT+getuid());
else
server.sin_port = sp->s_port;
-
+
/* Create the listen socket. */
if ((ls = socket (AF_INET,SOCK_STREAM, 0)) == -1)
{
fprintf(stderr,"%s: unable to create socket\n",progname);
exit(1);
} /* if */
-
+
/* Bind the listen address to the socket. */
if (bind(ls,(struct sockaddr *) &server,sizeof(struct sockaddr_in)) == -1)
{
} /* if */
/* Initiate the listen on the socket so remote users
- * can connect.
+ * can connect.
*/
if (listen(ls,20) == -1)
{
handle_internet_request (int ls)
{
int s;
- size_t addrlen = sizeof(struct sockaddr_in);
+ socklen_t addrlen = sizeof (struct sockaddr_in);
struct sockaddr_in peer; /* for peer socket address */
- memset((char *)&peer,0,sizeof(struct sockaddr_in));
+ memset (&peer, '\0', sizeof (peer));
- if ((s = accept(ls,(struct sockaddr *)&peer, (void *) &addrlen)) == -1)
+ if ((s = accept(ls,(struct sockaddr *)&peer, &addrlen)) == -1)
{
perror(progname);
fprintf(stderr,"%s: unable to accept\n",progname);
exit(1);
} /* if */
-
+
/* Check that access is allowed - if not return crud to the client */
if (!permitted(peer.sin_addr.s_addr, s))
{
} /* if */
echo_request(s);
-
+
} /* handle_internet_request */
#endif /* INTERNET_DOMAIN_SOCKETS */
{
int ls; /* socket descriptor */
struct sockaddr_un server; /* unix socket address */
- int bindlen;
+ socklen_t bindlen;
if ((ls = socket(AF_UNIX,SOCK_STREAM, 0)) < 0)
{
#else
bindlen = strlen (server.sun_path) + sizeof (server.sun_family);
#endif
-
+
if (bind(ls,(struct sockaddr *)&server,bindlen) < 0)
{
perror(progname);
/* #### there are also better ways of dealing with this when
sigvec() is present. */
#if defined (HAVE_SIGPROCMASK)
- {
+ {
sigset_t _mask;
sigemptyset (&_mask);
sigaddset (&_mask, SIGPIPE);
handle_unix_request (int ls)
{
int s;
- size_t len = sizeof(struct sockaddr_un);
+ socklen_t len = sizeof (struct sockaddr_un);
struct sockaddr_un server; /* for unix socket address */
server.sun_family = AF_UNIX;
- if ((s = accept(ls,(struct sockaddr *)&server, (void *)&len)) < 0)
+ if ((s = accept(ls,(struct sockaddr *)&server, &len)) < 0)
{
perror(progname);
fprintf(stderr,"%s: unable to accept\n",progname);
} /* if */
echo_request(s);
-
+
} /* handle_unix_request */
#endif /* UNIX_DOMAIN_SOCKETS */
FD_SET(uls, &rmask);
if (ils >= 0)
FD_SET(ils, &rmask);
-
- if (select(max2(fileno(stdin),max2(uls,ils)) + 1, &rmask,
+
+ if (select(max2(fileno(stdin),max2(uls,ils)) + 1, &rmask,
(fd_set *)NULL, (fd_set *)NULL, (struct timeval *)NULL) < 0)
{
perror(progname);
fprintf(stderr,"%s: unable to select\n",progname);
- exit(1);
+ return 1;
} /* if */
#ifdef UNIX_DOMAIN_SOCKETS
if (FD_ISSET(fileno(stdin), &rmask)) /* from stdin (gnu process) */
handle_response();
#endif /* NOT SYSV_IPC */
- } /* while */
-
- return 0;
+ } /* while (1) */
} /* main */
#endif /* SYSV_IPC || UNIX_DOMAIN_SOCKETS || INTERNET_DOMAIN_SOCKETS */