This is authuser.c in view mode; [Download] [Up]
/* 2/9/92: authuser 4.0. Public domain. 2/9/92: added bunches of zeroing just in case. 2/9/92: added auth_tcpuser3. uses bsd 4.3 select interface. 2/9/92: added auth_tcpsock, auth_sockuser. 2/9/92: added auth_fd2, auth_tcpuser2, simplified some of the code. 12/27/91: fixed up usercmp to deal with restricted tolower XXX 5/6/91 DJB baseline authuser 3.1. Public domain. */ #include <stdio.h> #include <signal.h> #include <sys/types.h> #include <sys/time.h> #include <sys/file.h> #include <fcntl.h> /*XXX*/ #include <sys/socket.h> #include <netinet/in.h> #include <ctype.h> #include <errno.h> extern int errno; #include "authuser.h" #ifndef FNDELAY #define FNDELAY O_NDELAY #endif unsigned short auth_tcpport = 113; #define SIZ 500 /* various buffers */ static clearsa(sa) struct sockaddr_in *sa; { register char *x; for (x = (char *) sa;x < sizeof(*sa) + (char *) sa;++x) *x = 0; } static int usercmp(u,v) register char *u; register char *v; { register char uc; register char vc; register char ucvc; /* is it correct to consider Foo and fOo the same user? yes */ /* but the function of this routine may change later */ while ((uc = *u) && (vc = *v)) { ucvc = (isupper(uc) ? tolower(uc) : uc) - (isupper(vc) ? tolower(vc) : vc); if (ucvc) return ucvc; else ++u,++v; } return uc || vc; } static char authline[SIZ]; char *auth_xline(user,fd,in) register char *user; /* the supposed name of the user, NULL if unknown */ register int fd; /* the file descriptor of the connection */ register unsigned long *in; { 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 */ sprintf(authline, (usercmp(ruser,user) ? "X-Forgery-By: %s" : "X-Auth-User: %s"), ruser); return authline; } int auth_fd(fd,in,local,remote) register int fd; register unsigned long *in; register unsigned short *local; register unsigned short *remote; { unsigned long inlocal; return auth_fd2(fd,&inlocal,in,local,remote); } int auth_fd2(fd,inlocal,inremote,local,remote) register int fd; register unsigned long *inlocal; register unsigned long *inremote; register unsigned short *local; register unsigned short *remote; { struct sockaddr_in sa; int dummy; dummy = sizeof(sa); if (getsockname(fd,&sa,&dummy) == -1) return -1; if (sa.sin_family != AF_INET) { errno = EAFNOSUPPORT; return -1; } *local = ntohs(sa.sin_port); *inlocal = sa.sin_addr.s_addr; dummy = sizeof(sa); if (getpeername(fd,&sa,&dummy) == -1) return -1; *remote = ntohs(sa.sin_port); *inremote = sa.sin_addr.s_addr; return 0; } static char ruser[SIZ]; static char realbuf[SIZ]; static char *buf; char *auth_tcpuser(in,local,remote) register unsigned long in; register unsigned short local; register unsigned short remote; { return auth_tcpuser2(0,in,local,remote); } #define CLORETS(e) { saveerrno = errno; close(s); errno = saveerrno; return e; } int auth_tcpsock(inlocal,inremote) register unsigned long inlocal; register unsigned long inremote; { struct sockaddr_in sa; register int s; register int fl; register int saveerrno; if ((s = socket(AF_INET,SOCK_STREAM,0)) == -1) return -1; if (inlocal) { clearsa(&sa); sa.sin_family = AF_INET; sa.sin_port = 0; sa.sin_addr.s_addr = inlocal; if (bind(s,&sa,sizeof(sa)) == -1) CLORETS(-1) } if ((fl = fcntl(s,F_GETFL,0)) == -1) CLORETS(-1); if (fcntl(s,F_SETFL,FNDELAY | fl) == -1) CLORETS(-1); clearsa(&sa); sa.sin_family = AF_INET; sa.sin_port = htons(auth_tcpport); sa.sin_addr.s_addr = inremote; if (connect(s,&sa,sizeof(sa)) == -1) if (errno != EINPROGRESS) CLORETS(-1) return s; } char *auth_tcpuser2(inlocal,inremote,local,remote) register unsigned long inlocal; register unsigned long inremote; register unsigned short local; register unsigned short remote; { register int s; s = auth_tcpsock(inlocal,inremote); if (s == -1) return 0; return auth_sockuser(s,local,remote); } char *auth_tcpuser3(inlocal,inremote,local,remote,timeout) register unsigned long inlocal; register unsigned long inremote; register unsigned short local; register unsigned short remote; register int timeout; { register int s; struct timeval tv; fd_set wfds; register int r; register int saveerrno; s = auth_tcpsock(inlocal,inremote); if (s == -1) return 0; tv.tv_sec = timeout; tv.tv_usec = 0; FD_ZERO(&wfds); FD_SET(s,&wfds); r = select(s + 1,(fd_set *) 0,&wfds,(fd_set *) 0,&tv); /* XXX: how to handle EINTR? */ if (r == -1) CLORETS(0) if (!FD_ISSET(s,&wfds)) { close(s); errno = ETIMEDOUT; return 0; } return auth_sockuser(s,local,remote); } char *auth_sockuser(s,local,remote) register int s; register unsigned short local; register unsigned short remote; { register int buflen; register int w; register int saveerrno; char ch; unsigned short rlocal; unsigned short rremote; register int fl; fd_set wfds; void *old_sig; old_sig = signal(SIGPIPE, SIG_IGN); FD_ZERO(&wfds); FD_SET(s,&wfds); select(s + 1,(fd_set *) 0,&wfds,(fd_set *) 0,(struct timeval *) 0); /* now s is writable */ if ((fl = fcntl(s,F_GETFL,0)) == -1) { signal(SIGPIPE, old_sig); CLORETS(0); } if (fcntl(s,F_SETFL,~FNDELAY & fl) == -1) { signal(SIGPIPE, old_sig); CLORETS(0); } buf = realbuf; sprintf(buf,"%u , %u\r\n",(unsigned int) remote,(unsigned int) local); /* note the reversed order---the example in RFC 931 is misleading */ buflen = strlen(buf); while ((w = write(s,buf,buflen)) < buflen) if (w == -1) /* should we worry about 0 as well? */ { signal(SIGPIPE, old_sig); CLORETS(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; } signal(SIGPIPE, old_sig); if (w == -1) CLORETS(0) *buf = 0; if (sscanf(realbuf,"%hd,%hd: USERID :%*[^:]:%s",&rremote,&rlocal,ruser) < 3) { 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)) { close(s); errno = EIO; return 0; } /* we're not going to do any backslash processing */ close(s); return ruser; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.