/* * pop3d - IP/TCP/POP3 server for UNIX 4.3BSD * Post Office Protocol - Version 3 (RFC1225) * * (C) Copyright 1991 Regents of the University of California * * Permission to use, copy, modify, and distribute this program * for any purpose and without fee is hereby granted, provided * that this copyright and permission notice appear on all copies * and supporting documentation, the name of University of California * not be used in advertising or publicity pertaining to distribution * of the program without specific prior permission, and notice be * given in supporting documentation that copying and distribution is * by permission of the University of California. * The University of California makes no representations about * the suitability of this software for any purpose. It is provided * "as is" without express or implied warranty. * * Katie Stevens * dkstevens@ucdavis.edu * Information Technology -- Campus Access Point * University of California, Davis * ************************************** * * util.c * * REVISIONS: * 02-27-90 [ks] original implementation * 1.000 03-04-90 [ks] */ #include #include #include #include #include #include #ifdef SHADOWPWD #include /*#include */ #endif #include "pop3.h" #include char flash_buf[SVR_BUFSIZ]; #ifdef DEBUG extern FILE *logfp; #endif /**************************************************************************/ /* Verify a usercode/password */ int verify_user( const char *user, const char *pass, const char *pwdfile, /* Alternate password file or NULL */ const char *shadow_file) { /* For virtual email domain, we are on our own. So we use the function vmail_getpwnam() to access user account info. This function is smart enough to use passwd only records or shadow records if available. This looks like a winner and it is tempting to use it also for the main domain. This would make the vpop3d utility magically shadow aware. The problem is that vmail_getpwnam() is not NIS aware (for one) so by using it on the main domain we may very well end up with more problems than we solve. The real solution is to pass as an argument to vpop3d the path of the native pop3 daemon which is aware of all that. The #ifdef SHADOWPWD below was left in place even if it is not useful. */ struct passwd *pwd; if (pwdfile != NULL){ pwd = vmail_getpwnam(pwdfile,shadow_file,user,false,false); }else{ pwd = getpwnam(user); } if (pwd == NULL) return -1; #ifdef SHADOWPWD if (pwdfile == NULL){ struct spwd *spwd; if (!(spwd = getspnam(user))) return -1; else pwd->pw_passwd = spwd->sp_pwdp; #if 0 if (pwd->pw_name && pwd->pw_passwd[0] == '@') { if (pw_auth(pwd->pw_passwd+1, user, PW_LOGIN)) return -1; return(setuid(pwd->pw_uid)); } if (!valid(pass, pwd)) return -1; return(setuid(pwd->pw_uid)); #endif } #endif char *cp = crypt(pass,pwd->pw_passwd); if (strcmp(cp,pwd->pw_passwd) == 0){ return setuid(pwd->pw_uid); } return -1; } /**************************************************************************/ /* Read a line of text from a stream. If more than n-1 */ /* characters are read without a line terminator (LF), */ /* discard characters until line terminator is located. */ char * fgetl( char *buf, /* Buffer for text */ int n, /* Size of buffer */ FILE *fp) /* Stream to read from */ { if (fgets(buf,n,fp) == NULL) return(NULL); if (((int)strlen(buf) == (n-1))&&(buf[n-1] != LF_CHAR)) { buf[n-1] = LF_CHAR; while (fgets(flash_buf,SVR_BUFSIZ,fp) != NULL) { if (strlen(flash_buf) != (SVR_BUFSIZ-1)) break; if (flash_buf[SVR_BUFSIZ-1] == LF_CHAR) break; } } return(buf); } /* Prepare client command for server */ void cmd_prepare(char *buf) { char *cp; if (buf == NULL) return; /* Convert command verb to lowercase */ while (*buf != NULL_CHAR) { if (isupper(*buf)) *buf = tolower(*buf); else if (isspace(*buf)) break; ++buf; } /* Strip trailing whitespace from client command */ if ((cp = strchr(buf,CR_CHAR)) != NULL) { while ((cp != buf)&&(isspace(*cp))) --cp; if (!isspace(*cp)) ++cp; *cp = NULL_CHAR; } if ((cp = strchr(buf,LF_CHAR)) != NULL) { while ((cp != buf)&&(isspace(*cp))) --cp; if (!isspace(*cp)) ++cp; *cp = NULL_CHAR; } } /**************************************************************************/ /* Send an error message and exit POP3 server */ void fail(int err) { char *cp; switch(err) { case FAIL_FILE_ERROR: /* File I/O error */ cp = "File I/O error"; break; case FAIL_HANGUP: /* Client hung up on us */ cp = "Lost connection to client"; break; case FAIL_LOST_CLIENT: /* Timeout waiting for client */ cp = "Timeout waiting for command from client"; break; case FAIL_OUT_OF_MEMORY: /* Failed malloc() */ cp = "Out of memory!"; break; case FAIL_PROGERR: /* Fatal program error */ cp = "Fatal program error!"; break; case FAIL_ACCESS: /* Session already active */ cp = "Already one POP session for this user!"; break; case FAIL_CONFUSION: /* Shouldnt happen */ default: cp = "Complete confusion!"; break; } fprintf(stdout,"-ERR POP3 Server Abnormal Shutdown: %s\r\n",cp); fflush(stdout); #ifdef DEBUG fprintf(logfp,"-ERR POP3 Server Abnormal Shutdown: %s\r\n",cp); fclose(logfp); #endif exit(err); /* Exit with error */ }