#define CONFIG_FILE "/var/qmail/users/poppasswd" #ifndef LINE_MAX #define LINE_MAX 2048 #endif #include #include #include extern int errno; extern char *crypt(); extern char *malloc(); extern char **environ; int error_txtbsy = #ifdef ETXTBSY ETXTBSY; #else -4; #endif #include "prot.h" #include static struct passwd *pw; static char *stored; static char *userdir; #include "hasspnam.h" #ifdef HASGETSPNAM #include static struct spwd *spw; #endif #include "hasuserpw.h" #ifdef HASUSERPW #include static struct userpw *upw; #endif void doit(login) char *login; { static char line[LINE_MAX + 1]; FILE *fp; char *lineptr, *newlogin = NULL; pw = getpwnam(login); if (pw) { stored = pw->pw_passwd; userdir = pw->pw_dir; #ifdef HASUSERPW upw = getuserpw(login); if (upw) stored = upw->upw_passwd; else if (errno == error_txtbsy) _exit(111); #endif #ifdef HASGETSPNAM spw = getspnam(login); if (spw) stored = spw->sp_pwdp; else if (errno == error_txtbsy) _exit(111); #endif return; } if (errno == error_txtbsy) _exit(111); if (!(fp = fopen(CONFIG_FILE, "r"))) _exit(2); while (fgets(line, LINE_MAX, fp)) { if (!(lineptr = strtok(line, ":"))) _exit(2); if (strcmp(lineptr, login) == 0) { if (!(lineptr = strtok(NULL, ":"))) _exit(2); stored = lineptr; if (!(lineptr = strtok(NULL, ":"))) _exit(2); newlogin = lineptr; if (!(lineptr = strtok(NULL, ":"))) _exit(2); userdir = lineptr; if (lineptr = strchr(userdir, '\n')) *lineptr = '\0'; break; } } fclose(fp); if (!newlogin) _exit(1); pw = getpwnam(newlogin); if (!pw) { if (errno == error_txtbsy) _exit(111); _exit(1); } } char *str1e2(name,value) char *name; char *value; { char *nv; nv = malloc(strlen(name) + strlen(value) + 2); if (!nv) _exit(111); strcpy(nv,name); strcat(nv,"="); strcat(nv,value); return nv; } char up[513]; int uplen; void main(argc,argv) int argc; char **argv; { char *login; char *password; char *encrypted; int r; int i; char **newenv; int numenv; if (!argv[1]) _exit(2); uplen = 0; for (;;) { do r = read(3,up + uplen,sizeof(up) - uplen); while ((r == -1) && (errno == EINTR)); if (r == -1) _exit(111); if (r == 0) break; uplen += r; if (uplen >= sizeof(up)) _exit(1); } close(3); i = 0; login = up + i; while (up[i++]) if (i == uplen) _exit(2); password = up + i; if (i == uplen) _exit(2); while (up[i++]) if (i == uplen) _exit(2); doit(login); encrypted = crypt(password,stored); for (i = 0;i < sizeof(up);++i) up[i] = 0; if (!*stored || strcmp(encrypted,stored)) _exit(1); if (prot_gid((int) pw->pw_gid) == -1) _exit(1); if (prot_uid((int) pw->pw_uid) == -1) _exit(1); if (chdir(userdir) == -1) _exit(111); numenv = 0; while (environ[numenv]) ++numenv; newenv = (char **) malloc((numenv + 4) * sizeof(char *)); if (!newenv) _exit(111); for (i = 0;i < numenv;++i) newenv[i] = environ[i]; newenv[numenv++] = str1e2("USER",pw->pw_name); newenv[numenv++] = str1e2("HOME",userdir); newenv[numenv++] = str1e2("SHELL",pw->pw_shell); newenv[numenv] = 0; environ = newenv; execvp(argv[1],argv + 1); _exit(111); }