/****************************************************************************/
/* programma no sērijas - viens sistēmas useris | daudz virtuālo pop3 useru */
/* vpoppasswd formāts: */
/* ::vpop: */
/* */
/* kompilēt ar: gcc -o checkvirtpass checkvirtpass.c -lcrypt */
/* kompilējot nekādus citus failus nevajag! (c) Mr.Goblins*/
/* FreeBSD as always ROCK */
/****************************************************************************/
#define CONFIG_FILE "/var/qmail/users/vpoppasswd"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#ifndef LINE_MAX
# define LINE_MAX 2048
#endif
#ifndef LOGIN_MAX
# define LOGIN_MAX 16
#endif
extern int errno;
extern char *crypt();
extern char *malloc();
extern char **environ;
char up[513];
int uplen;
char remoteipz[25]="\0";
char *str1e2(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;
}
struct newpw {
char *pw_passwd;
char *pw_dir;
char *pw_name;
char *pw_shell;
uid_t pw_uid;
gid_t pw_gid;
char *pw_real;
} *newgetpwnam(char *newlogin)
{
static char line[LINE_MAX + 1];
static struct newpw npw;
struct passwd *pw;
char *tlogin = NULL;
FILE *fp;
if ((fp = fopen(CONFIG_FILE, "rt")) == NULL) _exit(2);
while (fgets(line, LINE_MAX, fp) != NULL) {
char *linepnt;
if ((linepnt = strchr(line, '\n')) != NULL) {
*linepnt = 0;
}
if ((linepnt = strtok(line, ":")) == NULL) _exit(2);
if (strcmp(linepnt, newlogin) == 0) {
npw.pw_real = linepnt;
if ((linepnt = strtok(NULL, ":")) == NULL) _exit(2);
npw.pw_passwd = linepnt;
if ((linepnt = strtok(NULL, ":")) == NULL) _exit(2);
*(linepnt - 1) = 0;
tlogin = linepnt;
if ((linepnt = strtok(NULL, ":")) == NULL) _exit(2);
npw.pw_dir = linepnt;
break;
}
}
fclose(fp);
if (tlogin == NULL) _exit(1);
pw = getpwnam(tlogin);
if (!pw) _exit(1);
npw.pw_name = tlogin;
npw.pw_shell = pw->pw_shell;
npw.pw_uid = pw->pw_uid;
npw.pw_gid = pw->pw_gid;
return &npw;
}
int main(int argc, char **argv, char *envp[])
{
struct newpw *pw;
char *login;
char *password;
char *stored;
char *encrypted;
int r;
int i;
char **newenv;
int numenv;
char **me;
char *constr;
char *cconv;
int z;
for(me=envp;*me;me++) {
long ptr;
ptr = (long) *(me);
if (strncmp(*me, "TCPREMOTEIP", 11) == 0) {
ptr += 12;
strcpy(remoteipz, (char*)(ptr));
}
}
if (argc < 2) _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);
cconv = login;
while (*cconv) {
if ((*cconv <= 90)&&(*cconv >= 65)) *cconv = *cconv + 32;
cconv++;
}
pw = newgetpwnam(login);
if (!pw) _exit(1);
stored = pw->pw_passwd;
encrypted = crypt(password,stored);
if (!*stored || strcmp(encrypted,stored)) {
syslog(LOG_LOCAL2 | LOG_INFO, "password incorrect for user [%s] with password [%s] from [%s]", pw->pw_real, password, remoteipz);
for (i = 0;i < sizeof(up);++i) up[i] = 0;
_exit(1);
}
for (i = 0;i < sizeof(up);++i) up[i] = 0;
if (!pw->pw_uid) _exit(1);
if (setgid(pw->pw_gid) == -1) {
syslog(LOG_LOCAL2 | LOG_INFO, "Unable to setgid() to user [%s] with group ID [%s]", pw->pw_real, pw->pw_gid);
_exit(1);
}
if (setuid(pw->pw_uid) == -1) {
syslog(LOG_LOCAL2 | LOG_INFO, "Unable to setuid() to user [%s] with user ID [%s]", pw->pw_real, pw->pw_gid);
_exit(1);
}
if (chdir(pw->pw_dir) == -1) {
syslog(LOG_LOCAL2 | LOG_INFO, "Unable to chdir() to user [%s] home directory [%s]", pw->pw_real, pw->pw_dir);
_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",pw->pw_dir);
newenv[numenv++] = str1e2("SHELL",pw->pw_shell);
newenv[numenv] = 0;
environ = newenv;
syslog(LOG_LOCAL2 | LOG_INFO, "user [%s] logged in from [%s]", pw->pw_real, remoteipz);
execvp(argv[1],argv + 1);
_exit(111);
return 0;
}