This is authuser.c in view mode; [Download] [Up]
/*
* 5/6/91 DJB baseline authuser 3.1. Public domain.
* $Id: authuser.c,v 1.6 1997/03/03 08:58:53 sob Exp $
*/
#include "../src/config.h"
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
extern int errno;
#include "authuser.h"
unsigned short auth_tcpport = 113;
#define SIZ 500 /* various buffers */
static int
#ifdef __STDC__
usercmp(register char *u, register char *v)
#else
usercmp(u,v)
register char *u;
register char *v;
#endif
{
/* is it correct to consider Foo and fOo the same user? yes */
/* but the function of this routine may change later */
while (*u && *v)
if (tolower(*u) != tolower(*v))
return tolower(*u) - tolower(*v);
else
++u, ++v;
return *u || *v;
}
static char authline[SIZ];
char *
#ifdef __STDC__
auth_xline(register char *user, register int fd, register long unsigned int *in)
#else
auth_xline(user, fd, in)
register char *user;
register int fd;
register long unsigned int *in;
#endif
/* the supposed name of the user, NULL if unknown */
/* the file descriptor of the connection */
{
unsigned short local;
unsigned short remote;
register char *ruser;
if (auth_fd(fd, in, &local, &remote) == -1)
return 0;
ruser = auth_tcpuser(*in, local, remote);
if (!ruser)
return 0;
if (!user)
user = ruser; /* forces X-Auth-User */
(void) sprintf(authline,
(usercmp(ruser, user) ? "X-Forgery-By: %s" : "X-Auth-User: %s"),
ruser);
return authline;
}
int
#ifdef __STDC__
auth_fd(register int fd, register long unsigned int *in, register short unsigned int *local, register short unsigned int *remote)
#else
auth_fd(fd,in,local,remote)
register int fd;
register long unsigned int *in;
register short unsigned int *local;
register short unsigned int *remote;
#endif
{
struct sockaddr_in sa;
int dummy;
dummy = sizeof(sa);
if (getsockname(fd, (struct sockaddr *)&sa, &dummy) == -1)
return -1;
if (sa.sin_family != AF_INET) {
errno = EAFNOSUPPORT;
return -1;
}
*local = ntohs(sa.sin_port);
dummy = sizeof(sa);
if (getpeername(fd, (struct sockaddr *)&sa, &dummy) == -1)
return -1;
*remote = ntohs(sa.sin_port);
*in = sa.sin_addr.s_addr;
return 0;
}
static char ruser[SIZ];
static char realbuf[SIZ];
static char *buf;
char *
#ifdef __STDC__
auth_tcpuser(register long unsigned int in, register short unsigned int local, register short unsigned int remote)
#else
auth_tcpuser(in,local,remote)
register long unsigned int in;
register short unsigned int local;
register short unsigned int remote;
#endif
{
struct sockaddr_in sa;
register int s;
register int buflen;
register int w;
register int saveerrno;
char ch;
unsigned short rlocal;
unsigned short rremote;
if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1)
return 0;
sa.sin_family = AF_INET;
sa.sin_port = htons(auth_tcpport);
sa.sin_addr.s_addr = in;
if (connect(s, (struct sockaddr *)&sa, sizeof(sa)) == -1) {
saveerrno = errno;
(void) close(s);
errno = saveerrno;
return 0;
}
buf = realbuf;
(void) sprintf(buf, "%u , %u\r\n", (unsigned int) remote, (unsigned int) local);
/* note the reversed order---the example in the RFC is misleading */
buflen = strlen(buf);
while ((w = write(s, buf, buflen)) < buflen)
if (w == -1) { /* should we worry about 0 as well? */
saveerrno = errno;
(void) close(s);
errno = saveerrno;
return 0;
} else {
buf += w;
buflen -= w;
}
buf = realbuf;
while ((w = read(s, &ch, 1)) == 1) {
*buf = ch;
if ((ch != ' ') && (ch != '\t') && (ch != '\r'))
++buf;
if ((buf - realbuf == sizeof(realbuf) - 1) || (ch == '\n'))
break;
}
if (w == -1) {
saveerrno = errno;
(void) close(s);
errno = saveerrno;
return 0;
}
*buf = '\0';
/* H* fix: limit scanf of returned identd string. */
if (sscanf(realbuf, "%hd,%hd: USERID :%*[^:]:%400s",
&rremote, &rlocal, ruser) < 3) {
(void) close(s);
errno = EIO;
/* makes sense, right? well, not when USERID failed to match
ERROR but there's no good error to return in that case */
return 0;
}
if ((remote != rremote) || (local != rlocal)) {
(void) close(s);
errno = EIO;
return 0;
}
/* XXX: we're not going to do any backslash processing */
(void) close(s);
return ruser;
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.