#include #include #include #include #include #include #include #include #include #include #include "utils.h" #include "ctype.h" #include "username.h" extern char **argvec; #define IDENTD_PORT 113 #if defined(USERNAMES) #if !defined(SYNC_USERNAMES) static #endif const char *run_identd(const struct sockaddr_in *lcl, const struct sockaddr_in *rem) { struct sockaddr_in sin; int s; static char buf[10240]; int r; char *bp; int l; fd_set fds; fd_set tfds; struct timeval end; struct timeval d; s = socket(AF_INET,SOCK_STREAM,0); if (s < 0) { sprintf(&buf[0],"(socket: %s)",strerror(errno)); return(&buf[0]); } bzero(&sin,sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr = lcl->sin_addr; sin.sin_port = 0; if (bind(s,(struct sockaddr *)&sin,sizeof(sin)) < 0) { sprintf(&buf[0],"(bind: %s)",strerror(errno)); close(s); return(&buf[0]); } bzero(&sin,sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr = rem->sin_addr; sin.sin_port = htons(IDENTD_PORT); if (connect(s,(struct sockaddr *)&sin,sizeof(sin)) < 0) { sprintf(&buf[0],"(connect: %s)",strerror(errno)); close(s); return(&buf[0]); } sprintf(&buf[0],"%hu,%hu\r\n",ntohs(rem->sin_port),ntohs(lcl->sin_port)); write(s,&buf[0],strlen(&buf[0])); shutdown(s,1); bp = &buf[0]; l = sizeof(buf) - 1; gettimeofday(&end,0); end.tv_sec += 60; FD_ZERO(&tfds); FD_SET(s,&tfds); while (l > 0) { gettimeofday(&d,0); if (d.tv_sec > end.tv_sec) { if (l < 16) bp -= 16; strcpy(bp,"(timeout)"); close(s); return(&buf[0]); } d.tv_sec = end.tv_sec - d.tv_sec; d.tv_usec = 999999 - d.tv_usec; fds = tfds; r = select(s+1,&fds,0,0,&d); if (r < 0) { if (errno == EINTR) continue; sprintf(&buf[0],"(select: %s)",strerror(errno)); close(s); return(&buf[0]); } if ((r > 0) && FD_ISSET(s,&fds)) { r = read(s,bp,l); if (r < 0) { sprintf(&buf[0],"(read: %s)",strerror(errno)); close(s); return(&buf[0]); } if (r == 0) break; bp += r; l -= r; } } close(s); r = bp - &buf[0]; if ((r > 0) && (bp[-1] == '\n')) { r --; bp --; } if ((r > 0) && (bp[-1] == '\r')) { r --; bp --; } l = bp - &buf[0]; *bp = '\0'; l = 0; for (bp=&buf[0];*bp;bp++) { if ( (*(unsigned char *)bp < 32) || ( (*(unsigned char *)bp >= 127) && (*(unsigned char *)bp < 160) ) ) { l --; } else if (l != 0) { bp[l] = *bp; } } if (l != 0) bp[l] = '\0'; l = (bp+l) - &buf[0]; bp = index(&buf[0],':'); if (! bp) { int i; fprintf(stderr,"no colon 1:"); for (i=0;i 32) { fprintf(stderr," ..."); break; } fprintf(stderr," %02x",((unsigned char *)&buf[0])[i]); } fprintf(stderr,"\n"); l = strlen(&buf[0]); if (l > 100) l = 100; bcopy(&buf[0],&buf[20],l); bcopy("(error: no colon 1: ",&buf[0],20); buf[l+20] = ')'; buf[l+21] = '\0'; return(&buf[0]); } do bp++; while (*bp && Cisspace(*bp)); if (!bcmp(bp,"USERID",6)) { bp = index(bp+6,':'); if (! bp) return("(error: no colon after USERID)"); bp = index(bp+1,':'); if (! bp) return("(error: no colon after OS)"); return(bp+1); } else if (!bcmp(bp,"ERROR",5)) { return(bp); } return("(error: neither USERID nor ERROR)"); } #endif #if defined(USERNAMES) && !defined(SYNC_USERNAMES) int username_fd; void fork_username_process(void) { int p[2]; int pid; int npend; int pend[1024]; int i; int j; fd_set rfds; socketpair(AF_UNIX,SOCK_STREAM,0,&p[0]); pid = fork(); if (pid) { username_fd = p[0]; close(p[1]); return; } signal(SIGINT,SIG_IGN); username_fd = p[1]; close(p[0]); for (i=getdtablesize()-1;i>=0;i--) { if ((i != username_fd) && (i != 2)) close(i); } npend = 0; while (1) { while (1) { pid = wait3(0,WNOHANG,0); if (pid <= 0) break; } FD_ZERO(&rfds); FD_SET(username_fd,&rfds); j = 0; for (i=0;i= 0) { FD_SET(pend[i],&rfds); if (j != i) pend[j] = pend[i]; j ++; } } npend = j; i = select(FD_SETSIZE,&rfds,0,0,0); if (i < 0) { if (errno == EINTR) continue; fprintf(stderr,"%s: select: %s\n",argvec[0],strerror(errno)); exit(0); } if (FD_ISSET(username_fd,&rfds)) { struct sockaddr_in sin[2]; if (Read(username_fd,&sin[0],sizeof(sin)) < 0) exit(0); socketpair(AF_UNIX,SOCK_STREAM,0,&p[0]); pend[npend++] = p[0]; pid = fork(); if (pid == 0) { const char *s; int n; unsigned char len; close(username_fd); for (i=npend-1;i>=0;i--) close(pend[i]); s = run_identd(&sin[0],&sin[1]); n = strlen(s); len = (n > 255) ? 255 : n; write(p[1],&sin[0],sizeof(sin)); write(p[1],&len,1); write(p[1],s,len); exit(0); } close(p[1]); continue; } for (i=npend-1;i>=0;i--) { if (FD_ISSET(pend[i],&rfds)) #define SINS sizeof(struct sockaddr_in [2]) { unsigned char buf[SINS+1+255]; if ( (Read(pend[i],&buf[0],SINS+1) == 0) && (Read(pend[i],&buf[SINS+1],buf[SINS]) == 0) ) { write(username_fd,&buf[0],SINS+1+buf[SINS]); } #undef SINS close(pend[i]); pend[i] = -1; } } } } #endif