/*
* $Id: vcdb.c,v 1.26 2007/08/17 22:49:23 rwidmer Exp $
* Copyright (C) 1999-2004 Inter7 Internet Technologies, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
/******************************************************************************
**
** $Id: vcdb.c,v 1.26 2007/08/17 22:49:23 rwidmer Exp $
** Change a domain's password file to a CDB database
**
** Chris Johnson, July 1998
**
******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <pwd.h>
#include <sys/time.h>
#include <time.h>
#include <utime.h>
#include <sys/types.h>
#include <cdbmake.h>
#include "config.h"
#include "vpopmail.h"
#include "vauth.h"
#include "vcdb.h"
#include "file_lock.h"
#include "vlimits.h"
#define TOKENS " \n"
char *dc_filename(char *domain, uid_t uid, gid_t gid);
void vcdb_strip_char( char *instr );
char sqlerr[MAX_BUFF] = "";
char *last_query = NULL;
extern int cdb_seek();
static char vpasswd_file[MAX_BUFF];
static char vpasswd_bak_file[MAX_BUFF];
static char vpasswd_cdb_file[MAX_BUFF];
static char vpasswd_cdb_tmp_file[MAX_BUFF];
static char vpasswd_lock_file[MAX_BUFF];
static char vpasswd_dir[MAX_BUFF];
static char TmpBuf1[MAX_BUFF];
int make_vpasswd_cdb(char *domain)
{
char pwline[256];
char packbuf[8];
char *key;
char *data;
char *ptr;
int i,j,h;
int len;
long unsigned keylen,datalen;
uint32 pos,op;
struct cdbmake cdbm;
FILE *pwfile, *tmfile;
char Dir[156];
uid_t uid;
gid_t gid;
char *tmpstr;
mode_t oldmask;
/* If we don't optimize the index this time, just return */
if ( NoMakeIndex == 1 ) return(0);
if ((pwfile = fopen(vpasswd_file,"r")) == NULL) {
return(-1);
}
cdbmake_init(&cdbm);
/* temporarily set umask (no group/other access) and open temp file */
oldmask = umask(VPOPMAIL_UMASK);
tmfile = fopen(vpasswd_cdb_tmp_file,"w");
umask(oldmask);
if (tmfile == NULL) {
fprintf(stderr,"Error: could not create/open temporary file\n");
return(-1);
}
for (i=0; i < (int)sizeof(cdbm.final); i++) {
if (putc(' ',tmfile) == EOF) {
fprintf(stderr,"Error:error writing temp file\n");
return(-1);
}
}
pos = sizeof(cdbm.final);
/* creation **/
fgets(pwline,sizeof(pwline),pwfile);
while (!feof(pwfile)) {
key = pwline; ptr = pwline;
while (*ptr != ':') { ptr++; }
*ptr = 0; data = ptr; data++;
while (*ptr != '\n') { ptr++; }
*ptr = 0;
keylen = strlen(key); datalen = strlen(data);
#ifdef VPOPMAIL_DEBUG
fprintf (stderr,"Got entry: keylen = %lu, key = %s\n datalen = %lu, data = %s\n",keylen,key,datalen,data);
#endif
cdbmake_pack(packbuf, (uint32)keylen);
cdbmake_pack(packbuf + 4, (uint32)datalen);
if (fwrite(packbuf,1,8,tmfile) < 8) {
fprintf(stderr,"Error: error writing temp file\n");
return(-1);
}
h = CDBMAKE_HASHSTART;
for (i=0; i < (int)keylen; i++) {
h = cdbmake_hashadd(h,key[i]);
if (putc(key[i],tmfile) == EOF) {
fprintf (stderr,"Error: error temp file\n");
return(-1);
}
}
for (i=0; i < (int)datalen; i++) {
if (putc(data[i],tmfile) == EOF) {
fprintf (stderr,"Error: write error temp file");
return(-1);
}
}
if (!cdbmake_add(&cdbm,h,pos,malloc)) {
fprintf(stderr, "Error: out of memory\n");
return(-1);
}
op = pos;
pos += (uint32)8;
pos += (uint32)keylen;
pos += (uint32)datalen;
if (pos < op) {
fprintf(stderr,"Error: too much data\n");
return(-1);
}
if (!cdbmake_split(&cdbm,malloc)) {
fprintf(stderr,"Error: out of memory\n");
return(-1);
}
fgets(pwline,sizeof(pwline),pwfile);
free(cdbm.split);
}
fclose(pwfile);
if (!cdbmake_split(&cdbm,malloc)) {
fprintf(stderr, "Error: out of memory\n");
return(-1);
}
for (i=0; i < 256; i++) {
len = cdbmake_throw(&cdbm,pos,i);
for (j=0; j < len; j++) {
cdbmake_pack(packbuf,cdbm.hash[j].h);
cdbmake_pack(packbuf + 4, cdbm.hash[j].p);
if (fwrite(packbuf,1,8,tmfile) < 8) {
fprintf(stderr,"Error 1: error temp file\n");
return(-1);
}
op = pos;
pos += (uint32)8;
if (pos < op) {
fprintf (stderr, "Error 12: too much data\n");
return(-1);
}
}
}
if (fflush(tmfile) == EOF) {
fprintf (stderr,"Error 20: write error temp file\n");
return(-1);
}
rewind(tmfile);
if (fwrite(cdbm.final,1,sizeof(cdbm.final),tmfile)<sizeof(cdbm.final)){
fprintf(stderr,"Error 21: write error temp file\n");
return(-1);
}
if (fflush(tmfile) == EOF) {
fprintf(stderr,"Error 22: write error temp file\n");
return(-1);
}
if (close(fileno(tmfile)) == -1) {
fprintf(stderr,"Error 24: error with close()\n");
return(-1);
}
if (rename(vpasswd_cdb_tmp_file,vpasswd_cdb_file)) {
fprintf(stderr,
"Error 25: could not rename cdb.tmp to vpasswd.cdb\n");
return(-1);
}
free(cdbm.head);
free(cdbm.split);
tmpstr = vget_assign(domain, Dir, 156, &uid, &gid );
chown(vpasswd_cdb_file, uid, gid);
chown(vpasswd_lock_file, uid, gid);
chown(vpasswd_file, uid, gid);
return 0;
}
struct vqpasswd *vauth_getpw(char *user, char *domain)
{
char in_domain[156];
static struct vqpasswd pwent;
static char line[2048];
char *ptr = NULL, *uid = NULL, *gid = NULL;
uid_t myuid;
uid_t tuid;
gid_t tgid;
uint32 dlen;
int pwf;
#ifdef FILE_LOCKING
int lock_fd;
#endif
verrori = 0;
lowerit(user);
lowerit(domain);
if (vget_assign(domain,NULL,0,&tuid,&tgid) == NULL) {
/* domain does not exist */
return(NULL);
}
myuid = geteuid();
if ( myuid != 0 && myuid != tuid ) {
return(NULL);
}
strncpy( in_domain, domain, sizeof(in_domain));
in_domain[sizeof(in_domain)-1] = '\0'; /* ensure NULL termination */
set_vpasswd_files( in_domain );
if ((pwf = open(vpasswd_cdb_file,O_RDONLY)) < 0 ) {
#ifdef FILE_LOCKING
if ( (lock_fd=open(vpasswd_lock_file, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR)) < 0) {
return(NULL);
}
get_write_lock( lock_fd );
#endif
make_vpasswd_cdb(domain);
#ifdef FILE_LOCKING
unlock_lock(lock_fd, 0, SEEK_SET, 0);
close(lock_fd);
#endif
if ((pwf = open(vpasswd_cdb_file,O_RDONLY)) < 0 ) {
return(NULL);
}
}
strncpy(line,user,sizeof(line));
strncat(line,":",sizeof(line));
ptr = line;
while (*ptr != ':') { ptr++; }
ptr++;
switch (cdb_seek(pwf,user,strlen(user),&dlen)) {
case -1:
case 0:
close(pwf);
return NULL;
}
if (read(pwf, ptr,dlen) != (int)dlen) {
close(pwf);
return NULL;
}
close(pwf);
line[(dlen+strlen(user)+1)] = 0;
pwent.pw_name = "";
pwent.pw_passwd = "";
pwent.pw_gecos = "";
pwent.pw_dir = "";
pwent.pw_shell = "";
pwent.pw_clear_passwd = "";
ptr = line;
pwent.pw_name = line;
while (*ptr!=0&&*ptr != ':') { ptr++; }
if ( *ptr!=0 ){ *ptr = 0; ptr++; pwent.pw_passwd = ptr; }
while (*ptr!=0&&*ptr != ':') { ptr++; }
if ( *ptr!=0 ){ *ptr = 0; ptr++; uid = ptr; }
while (*ptr!=0&&*ptr != ':') { ptr++; }
if ( *ptr!=0 ){ *ptr = 0; ptr++; gid = ptr; }
while (*ptr!=0&&*ptr != ':') { ptr++; }
if ( *ptr!=0 ){ *ptr = 0; ptr++; pwent.pw_gecos = ptr; }
while (*ptr!=0&&*ptr != ':') { ptr++; }
if ( *ptr!=0 ){ *ptr = 0; ptr++; pwent.pw_dir = ptr; }
while (*ptr!=0&&*ptr != ':') { ptr++; }
if ( *ptr!=0 ){ *ptr = 0; ptr++; pwent.pw_shell = ptr; }
while (*ptr!=0&&*ptr != ':') { ptr++; }
if ( *ptr!=0 ){ *ptr = 0; ptr++; pwent.pw_clear_passwd = ptr; }
if (!*uid) { pwent.pw_uid = 0; } else { pwent.pw_uid = atoi(uid); }
if (!*gid) { pwent.pw_gid = 0; } else { pwent.pw_gid = atoi(gid); }
vlimits_setflags (&pwent, in_domain);
#ifdef VPOPMAIL_DEBUG
if( dump_data ) {
fprintf (stderr,"vgetpw: db: results: pw_name = %s\n",pwent.pw_name);
fprintf (stderr," pw_passwd = %s\n",pwent.pw_passwd);
fprintf (stderr," pw_uid = %d\n",pwent.pw_uid);
fprintf (stderr," pw_gid = %d\n",pwent.pw_gid);
fprintf (stderr," pw_flags = %d\n",pwent.pw_flags);
fprintf (stderr," pw_gecos = %s\n",pwent.pw_gecos);
fprintf (stderr," pw_dir = %s\n",pwent.pw_dir);
fprintf (stderr," pw_shell = %s\n",pwent.pw_shell);
}
#endif
return(&pwent);
}
struct vqpasswd *vauth_getall(char *domain, int first, int sortit)
{
static FILE *fsv = NULL;
struct vqpasswd *tmpwd;
set_vpasswd_files( domain );
if ( first == 1 ) {
if ( fsv != NULL ) fclose(fsv);
set_vpasswd_files( domain );
if ((fsv = fopen(vpasswd_file, "r")) == NULL) return(NULL);
} else if ( fsv == NULL ) {
return(NULL);
}
tmpwd = vgetent(fsv);
if ( tmpwd == NULL ) {
fclose(fsv);
fsv = NULL;
}
if(tmpwd) vlimits_setflags(tmpwd,domain) ;
return(tmpwd);
}
void vauth_end_getall()
{
}
void set_vpasswd_files( char *domain )
{
char *tmpstr;
uid_t uid;
gid_t gid;
char Dir[156];
vset_default_domain( domain );
tmpstr = vget_assign(domain, Dir, 156, &uid, &gid );
memset(vpasswd_dir, 0, MAX_BUFF);
memset(vpasswd_file, 0, MAX_BUFF);
memset(vpasswd_cdb_file, 0, MAX_BUFF);
memset(vpasswd_cdb_tmp_file, 0, MAX_BUFF);
memset(vpasswd_lock_file, 0, MAX_BUFF);
if ( domain == NULL || domain[0] == 0 ) {
snprintf(vpasswd_dir, MAX_BUFF, "%s/users", VPOPMAILDIR);
} else {
snprintf(vpasswd_dir, MAX_BUFF, "%s", Dir);
}
snprintf(vpasswd_file, MAX_BUFF, "%s/%s", vpasswd_dir,VPASSWD_FILE);
snprintf(vpasswd_bak_file, MAX_BUFF, "%s/%s.%d",
vpasswd_dir,VPASSWD_BAK_FILE, getpid());
snprintf(vpasswd_cdb_file, MAX_BUFF,
"%s/%s", vpasswd_dir,VPASSWD_CDB_FILE);
snprintf(vpasswd_cdb_tmp_file, MAX_BUFF,
"%s/%s",vpasswd_dir,VPASSWD_CDB_TMP_FILE);
snprintf(vpasswd_lock_file, MAX_BUFF,
"%s/%s", vpasswd_dir,VPASSWD_LOCK_FILE);
}
int vauth_adduser(char *user, char *domain, char *pass, char *gecos, char *dir, int apop )
{
static char tmpbuf1[MAX_BUFF];
static char tmpbuf2[MAX_BUFF];
char *tmpstr;
int added = 0;
FILE *fs1;
FILE *fs2;
#ifdef FILE_LOCKING
int fd3;
#endif
/* do not trod on the vpasswd file */
if ( strcmp( "vpasswd", user ) == 0 ) {
return( VA_ILLEGAL_USERNAME );
}
set_vpasswd_files( domain );
/* if the gecos field is null, set it to user name */
if ( gecos==0 || gecos[0]==0) gecos=user;
vcdb_strip_char( gecos );
#ifdef FILE_LOCKING
fd3 = open(vpasswd_lock_file, O_WRONLY | O_CREAT, S_IRUSR|S_IWUSR);
if ( get_write_lock(fd3) < 0 ) return(-2);
#endif
fs1 = fopen(vpasswd_bak_file, "w+");
if ( (fs2 = fopen(vpasswd_file, "r+")) == NULL ) {
fs2 = fopen(vpasswd_file, "w+");
}
if ( fs1 == NULL || fs2 == NULL ) {
if ( fs1 != NULL ) fclose(fs1);
if ( fs2 != NULL ) fclose(fs2);
#ifdef FILE_LOCKING
unlock_lock(fd3, 0, SEEK_SET, 0);
close(fd3);
#endif
return(-1);
}
while (fgets(tmpbuf1,MAX_BUFF,fs2)!=NULL){
strncpy(tmpbuf2, tmpbuf1, MAX_BUFF);
tmpstr = strtok(tmpbuf2,":");
if ( added == 0 && strcmp(user, tmpstr) < 0 ) {
added = 1;
vauth_adduser_line( fs1, user, pass, domain,gecos,dir, apop);
}
fputs(tmpbuf1, fs1);
}
if ( added == 0 ) {
vauth_adduser_line( fs1, user, pass, domain,gecos,dir,apop);
}
fclose(fs1);
fclose(fs2);
rename(vpasswd_bak_file, vpasswd_file);
make_vpasswd_cdb(domain);
#ifdef FILE_LOCKING
unlock_lock(fd3, 0, SEEK_SET, 0);
close(fd3);
#endif
return(0);
}
int vauth_adddomain( char *domain )
{
return(0);
}
int vauth_deldomain( char *domain )
{
return(0);
}
int vauth_deluser( char *user, char *domain )
{
static char tmpbuf1[MAX_BUFF];
static char tmpbuf2[MAX_BUFF];
char *tmpstr;
FILE *fs1;
FILE *fs2;
#ifdef FILE_LOCKING
int fd3;
#endif
set_vpasswd_files( domain );
#ifdef FILE_LOCKING
fd3 = open(vpasswd_lock_file, O_WRONLY | O_CREAT, S_IRUSR|S_IWUSR);
if ( get_write_lock(fd3) < 0 ) return(-2);
#endif
fs1 = fopen(vpasswd_bak_file, "w+");
if ( (fs2 = fopen(vpasswd_file, "r+")) == NULL ) {
fs2 = fopen(vpasswd_file, "w+");
}
if ( fs1 == NULL || fs2 == NULL ) {
if ( fs1 != NULL ) fclose(fs1);
if ( fs2 != NULL ) fclose(fs2);
#ifdef FILE_LOCKING
unlock_lock(fd3, 0, SEEK_SET, 0);
close(fd3);
#endif
return(-1);
}
while (fgets(tmpbuf1,MAX_BUFF,fs2)!=NULL){
strncpy(tmpbuf2, tmpbuf1, MAX_BUFF);
tmpstr = strtok(tmpbuf2,":");
if ( strcmp(user, tmpstr) != 0) {
fputs(tmpbuf1, fs1);
}
}
fclose(fs1);
fclose(fs2);
rename(vpasswd_bak_file, vpasswd_file);
make_vpasswd_cdb(domain);
#ifdef FILE_LOCKING
unlock_lock(fd3, 0, SEEK_SET, 0);
close(fd3);
#endif
return(0);
}
/* Utility function to set the users quota
*
* Calls underlying vauth_getpw and vauth_setpw
* to actually change the users information
*/
int vauth_setquota( char *username, char *domain, char *quota)
{
struct vqpasswd *vpw;
if ( strlen(username) > MAX_PW_NAME ) return(VA_USER_NAME_TOO_LONG);
#ifdef USERS_BIG_DIR
if ( strlen(username) == 1 ) return(VA_ILLEGAL_USERNAME);
#endif
if ( strlen(domain) > MAX_PW_DOMAIN ) return(VA_DOMAIN_NAME_TOO_LONG);
if ( strlen(quota) > MAX_PW_QUOTA ) return(VA_QUOTA_TOO_LONG);
vpw = vauth_getpw( username, domain );
if ( vpw==NULL ) return(VA_USER_DOES_NOT_EXIST);
vpw->pw_shell = quota;
return(vauth_setpw(vpw,domain));
}
int vauth_setpw( struct vqpasswd *inpw, char *domain )
{
static char tmpbuf1[MAX_BUFF];
static char tmpbuf2[MAX_BUFF];
char *tmpstr;
FILE *fs1;
FILE *fs2;
#ifdef FILE_LOCKING
int fd3;
#endif
uid_t myuid;
uid_t uid;
gid_t gid;
int ret;
ret = vcheck_vqpw(inpw, domain);
if ( ret != 0 ) return(ret);
/* get the owner of the domain */
vget_assign(domain,NULL,0,&uid,&gid);
/* get the current effective user */
myuid = geteuid();
/*
* if it is not the owner, vpopmail or root
* then reject this operation
*/
if ( myuid != 0 && myuid != uid ) {
return(VA_BAD_UID);
}
set_vpasswd_files( domain );
#ifdef FILE_LOCKING
fd3 = open(vpasswd_lock_file, O_WRONLY | O_CREAT, S_IRUSR|S_IWUSR);
if ( get_write_lock(fd3) < 0 ) return(-2);
#endif
fs1 = fopen(vpasswd_bak_file, "w+");
if ( (fs2 = fopen(vpasswd_file, "r+")) == NULL ) {
fs2 = fopen(vpasswd_file, "w+");
}
if ( fs1 == NULL || fs2 == NULL ) {
if ( fs1 != NULL ) fclose(fs1);
if ( fs2 != NULL ) fclose(fs2);
#ifdef FILE_LOCKING
unlock_lock(fd3, 0, SEEK_SET, 0);
close(fd3);
#endif
return(-1);
}
vcdb_strip_char( inpw->pw_gecos );
#ifndef CLEAR_PASS
vcdb_strip_char( inpw->pw_clear_passwd );
#endif
while (fgets(tmpbuf1,MAX_BUFF,fs2)!=NULL){
strncpy(tmpbuf2, tmpbuf1, MAX_BUFF);
tmpstr = strtok(tmpbuf2,":\n");
if ( strcmp(inpw->pw_name, tmpstr) != 0) {
fputs(tmpbuf1, fs1);
} else {
#ifndef CLEAR_PASS
fprintf(fs1, "%s:%s:%d:%d:%s:%s:%s\n",
inpw->pw_name,
inpw->pw_passwd,
inpw->pw_uid,
inpw->pw_gid,
inpw->pw_gecos,
inpw->pw_dir,
inpw->pw_shell);
#else
fprintf(fs1, "%s:%s:%d:%d:%s:%s:%s:%s\n",
inpw->pw_name,
inpw->pw_passwd,
inpw->pw_uid,
inpw->pw_gid,
inpw->pw_gecos,
inpw->pw_dir,
inpw->pw_shell, inpw->pw_clear_passwd);
#endif
}
}
fclose(fs1);
fclose(fs2);
rename(vpasswd_bak_file, vpasswd_file);
make_vpasswd_cdb(domain);
#ifdef FILE_LOCKING
unlock_lock(fd3, 0, SEEK_SET, 0);
close(fd3);
#endif
#ifdef SQWEBMAIL_PASS
tmpstr = vget_assign(domain, NULL, 0, &uid, &gid );
vsqwebmail_pass( inpw->pw_dir, inpw->pw_passwd, uid, gid);
#endif
#ifdef ONCHANGE_SCRIPT
if( allow_onchange ) {
/* tell other programs that data has changed */
snprintf ( onchange_buf, MAX_BUFF, "%s@%s", inpw->pw_name, domain ) ;
call_onchange ( "mod_user" ) ;
}
#endif
return(0);
}
int vauth_adduser_line( FILE *fs1,
char *user,
char *pass,
char *domain,
char *gecos,
char *dir, int apop )
{
char Dir[156];
uid_t uid;
gid_t gid;
char crypted[100];
if ( vget_assign(domain, Dir, 156, &uid, &gid ) == NULL ) {
strcpy(Dir, VPOPMAILDIR);
}
if ( pass[0] != 0 ) {
mkpasswd3(pass,crypted, 100);
} else {
crypted[0] = 0;
}
fprintf(fs1,"%s:", user );
if ( apop == USE_POP ) fprintf(fs1, "%s:1:", crypted);
else fprintf(fs1, "%s:2:", crypted);
fprintf(fs1, "0:%s:%s", gecos, Dir);
if ( strlen(domain) <= 0 ) {
if ( strlen(dir) > 0 ) {
fprintf(fs1, "/users/%s/%s:", dir, user);
} else {
fprintf(fs1, "/users/%s:", user);
}
} else {
if ( strlen(dir) > 0 ) {
fprintf(fs1,"/%s/%s:", dir,user);
} else {
fprintf(fs1, "/%s:", user);
}
}
fprintf(fs1, "NOQUOTA");
#ifndef CLEAR_PASS
fprintf(fs1, "\n");
#else
fprintf(fs1, ":%s\n", pass);
#endif
return(0);
}
int vmkpasswd( char *domain )
{
#ifdef FILE_LOCKING
int fd3;
#endif
char Dir[156];
uid_t uid;
gid_t gid;
char *tmpstr;
getcwd(TmpBuf1, MAX_BUFF);
tmpstr = vget_assign(domain, Dir, 156, &uid, &gid );
if ( chdir(Dir) != 0 ) return(VA_BAD_DIR);
lowerit(domain);
set_vpasswd_files( domain );
#ifdef FILE_LOCKING
fd3 = open(vpasswd_lock_file, O_WRONLY | O_CREAT, S_IRUSR|S_IWUSR);
if ( get_write_lock(fd3) < 0 ) return(-2);
#endif
make_vpasswd_cdb(domain);
#ifdef FILE_LOCKING
unlock_lock(fd3, 0, SEEK_SET, 0);
close(fd3);
#endif
return(0);
}
/* Verify the connection to the authentication database */
int vauth_open( int will_update ) {
#ifdef VPOPMAIL_DEBUG
show_trace = ( getenv("VPSHOW_TRACE") != NULL);
show_query = ( getenv("VPSHOW_QUERY") != NULL);
dump_data = ( getenv("VPDUMP_DATA") != NULL);
#endif
#ifdef VPOPMAIL_DEBUG
if( show_trace ) {
fprintf( stderr, "vauth_open()\n");
}
#endif
/*
* If the connection to this authentication database can fail
* you should test access here. If it works, return 0, else
* return VA_NO_AUTH_CONNECTION. You can also set the string
* sqlerr to some short descriptive text about the problem,
* and allocate a much longer string, pointed to by last_query
* that can be displayed in an error message returned because
* of this problem.
*
*/
return( 0 );
}
void vclose()
{
}
#ifdef IP_ALIAS_DOMAINS
int vget_ip_map( char *ip, char *domain, int domain_size)
{
FILE *fs;
char tmpbuf[156];
char *tmpstr;
if ( ip == NULL || strlen(ip) <= 0 ) return(-1);
/* open the ip_alias_map file */
snprintf(tmpbuf, 156, "%s/%s", VPOPMAILDIR, IP_ALIAS_MAP_FILE);
if ( (fs = fopen(tmpbuf,"r")) == NULL ) return(-1);
while( fgets(tmpbuf, 156, fs) != NULL ) {
tmpstr = strtok(tmpbuf, IP_ALIAS_TOKENS);
if ( tmpstr == NULL ) continue;
if ( strcmp(ip, tmpstr) != 0 ) continue;
tmpstr = strtok(NULL, IP_ALIAS_TOKENS);
if ( tmpstr == NULL ) continue;
strncpy(domain, tmpstr, domain_size);
fclose(fs);
return(0);
}
fclose(fs);
return(-1);
}
/*
* Add an ip to domain mapping
* It will remove any duplicate entry before adding it
*
*/
int vadd_ip_map( char *ip, char *domain)
{
FILE *fs;
char tmpbuf[156];
if ( ip == NULL || strlen(ip) <= 0 ) return(-1);
if ( domain == NULL || strlen(domain) <= 0 ) return(-10);
vdel_ip_map( ip, domain );
snprintf(tmpbuf, 156, "%s/%s", VPOPMAILDIR, IP_ALIAS_MAP_FILE);
if ( (fs = fopen(tmpbuf,"a+")) == NULL ) return(-1);
fprintf( fs, "%s %s\n", ip, domain);
fclose(fs);
return(0);
}
int vdel_ip_map( char *ip, char *domain)
{
FILE *fs;
FILE *fs1;
char file1[156];
char file2[156];
char tmpbuf[156];
char tmpbuf1[156];
char *ip_f;
char *domain_f;
if ( ip == NULL || strlen(ip) <= 0 ) return(-1);
if ( domain == NULL || strlen(domain) <= 0 ) return(-1);
snprintf(file1, 156, "%s/%s", VPOPMAILDIR, IP_ALIAS_MAP_FILE);
if ( (fs = fopen(file1,"r")) == NULL ) return(-1);
snprintf(file2, 156,
"%s/%s.%d", VPOPMAILDIR, IP_ALIAS_MAP_FILE, getpid());
if ( (fs1 = fopen(file2,"w")) == NULL ) {
fclose(fs);
return(-1);
}
while( fgets(tmpbuf, 156, fs) != NULL ) {
strncpy(tmpbuf1,tmpbuf, 156);
ip_f = strtok(tmpbuf, IP_ALIAS_TOKENS);
if ( ip_f == NULL ) continue;
domain_f = strtok(NULL, IP_ALIAS_TOKENS);
if ( domain_f == NULL ) continue;
if ( strcmp(ip, ip_f) == 0 && strcmp(domain,domain_f) == 0)
continue;
fprintf(fs1, tmpbuf1);
}
fclose(fs);
fclose(fs1);
if ( rename( file2, file1) < 0 ) return(-1);
return(0);
}
int vshow_ip_map( int first, char *ip, char *domain)
{
static FILE *fs = NULL;
char tmpbuf[156];
char *tmpstr;
if ( ip == NULL ) return(-1);
if ( domain == NULL ) return(-1);
if ( first == 1 ) {
if ( fs != NULL ) {
fclose(fs);
fs = NULL;
}
snprintf(tmpbuf, 156, "%s/%s", VPOPMAILDIR, IP_ALIAS_MAP_FILE);
if ( (fs = fopen(tmpbuf,"r")) == NULL ) return(-1);
}
if ( fs == NULL ) return(-1);
while (1) {
if (fgets(tmpbuf, 156, fs) == NULL ) {
fclose(fs);
fs = NULL;
return(0);
}
tmpstr = strtok(tmpbuf, IP_ALIAS_TOKENS);
if ( tmpstr == NULL ) continue;
strcpy( ip, tmpstr);
tmpstr = strtok(NULL, IP_ALIAS_TOKENS);
if ( tmpstr == NULL ) continue;
strcpy( domain, tmpstr);
return(1);
}
return(-1);
}
#endif
int vread_dir_control(vdir_type *vdir, char *domain, uid_t uid, gid_t gid)
{
FILE *fs;
char dir_control_file[MAX_DIR_NAME];
int i;
strncpy(dir_control_file,dc_filename(domain, uid, gid),MAX_DIR_NAME);
if ( (fs = fopen(dir_control_file, "r")) == NULL ) {
vdir->cur_users = 0;
for(i=0;i<MAX_DIR_LEVELS;++i){
vdir->level_start[i] = 0;
vdir->level_end[i] = MAX_DIR_LIST-1;
vdir->level_index[i] = 0;
}
vdir->level_mod[0] = 0;
vdir->level_mod[1] = 2;
vdir->level_mod[2] = 4;
vdir->level_cur = 0;
vdir->level_max = MAX_DIR_LEVELS;
vdir->the_dir[0] = 0;
return(-1);
}
fgets(dir_control_file, MAX_DIR_NAME, fs );
vdir->cur_users = atol(dir_control_file);
fgets(dir_control_file, MAX_DIR_NAME, fs );
vdir->level_cur = atoi(dir_control_file);
fgets(dir_control_file, MAX_DIR_NAME, fs );
vdir->level_max = atoi(dir_control_file);
fgets(dir_control_file, MAX_DIR_NAME, fs );
vdir->level_start[0] = atoi(dir_control_file);
for(i=0;dir_control_file[i]!=' ';++i); ++i;
vdir->level_start[1] = atoi(&dir_control_file[i]);
for(i=0;dir_control_file[i]!=' ';++i); ++i;
vdir->level_start[2] = atoi(&dir_control_file[i]);
fgets(dir_control_file, MAX_DIR_NAME, fs );
vdir->level_end[0] = atoi(dir_control_file);
for(i=0;dir_control_file[i]!=' ';++i); ++i;
vdir->level_end[1] = atoi(&dir_control_file[i]);
for(i=0;dir_control_file[i]!=' ';++i); ++i;
vdir->level_end[2] = atoi(&dir_control_file[i]);
fgets(dir_control_file, MAX_DIR_NAME, fs );
vdir->level_mod[0] = atoi(dir_control_file);
for(i=0;dir_control_file[i]!=' ';++i); ++i;
vdir->level_mod[1] = atoi(&dir_control_file[i]);
for(i=0;dir_control_file[i]!=' ';++i); ++i;
vdir->level_mod[2] = atoi(&dir_control_file[i]);
fgets(dir_control_file, MAX_DIR_NAME, fs );
vdir->level_index[0] = atoi(dir_control_file);
for(i=0;dir_control_file[i]!=' ';++i); ++i;
vdir->level_index[1] = atoi(&dir_control_file[i]);
for(i=0;dir_control_file[i]!=' ';++i); ++i;
vdir->level_index[2] = atoi(&dir_control_file[i]);
fgets(dir_control_file, MAX_DIR_NAME, fs );
for(i=0;dir_control_file[i]!=0;++i) {
if (dir_control_file[i] == '\n') {
dir_control_file[i] = 0;
}
}
fgets(dir_control_file, MAX_DIR_NAME, fs );
for(i=0;dir_control_file[i]!=0;++i) {
if (dir_control_file[i] == '\n') {
dir_control_file[i] = 0;
}
}
strncpy(vdir->the_dir, dir_control_file, MAX_DIR_NAME);
fclose(fs);
return(0);
}
int vwrite_dir_control(vdir_type *vdir, char *domain, uid_t uid, gid_t gid)
{
FILE *fs;
char dir_control_file[MAX_DIR_NAME];
char dir_control_tmp_file[MAX_DIR_NAME];
strncpy(dir_control_file,dc_filename(domain, uid, gid),MAX_DIR_NAME);
snprintf(dir_control_tmp_file, MAX_DIR_NAME,
"%s.%d", dir_control_file, getpid());
if ( (fs = fopen(dir_control_tmp_file, "w+")) == NULL ) {
return(-1);
}
fprintf(fs, "%lu\n", vdir->cur_users);
fprintf(fs, "%d\n", vdir->level_cur);
fprintf(fs, "%d\n", vdir->level_max);
fprintf(fs, "%d %d %d\n",
vdir->level_start[0],
vdir->level_start[1],
vdir->level_start[2]);
fprintf(fs, "%d %d %d\n",
vdir->level_end[0],
vdir->level_end[1],
vdir->level_end[2]);
fprintf(fs, "%d %d %d\n",
vdir->level_mod[0],
vdir->level_mod[1],
vdir->level_mod[2]);
fprintf(fs, "%d %d %d\n",
vdir->level_index[0],
vdir->level_index[1],
vdir->level_index[2]);
fprintf(fs, "%s\n", vdir->the_dir);
fclose(fs);
rename( dir_control_tmp_file, dir_control_file);
chown(dir_control_file,uid, gid);
return(0);
}
int vdel_dir_control(char *domain)
{
char dir_control_file[MAX_DIR_NAME];
vget_assign(domain, dir_control_file, 156, NULL,NULL);
strncat(dir_control_file,"/.dir-control", MAX_DIR_NAME);
return(unlink(dir_control_file));
}
#ifdef ENABLE_AUTH_LOGGING
int vset_lastauth(char *user, char *domain, char *remoteip )
{
char *tmpbuf;
FILE *fs;
struct vqpasswd *vpw;
uid_t uid;
gid_t gid;
if( (vpw = vauth_getpw( user, domain )) == NULL) return(0);
tmpbuf = malloc(MAX_BUFF);
snprintf(tmpbuf, MAX_BUFF, "%s/lastauth", vpw->pw_dir);
if ( (fs = fopen(tmpbuf,"w+")) == NULL ) {
free(tmpbuf);
return(-1);
}
fprintf(fs, "%s", remoteip);
fclose(fs);
vget_assign(domain,NULL,0,&uid,&gid);
chown(tmpbuf,uid,gid);
free(tmpbuf);
return(0);
}
time_t vget_lastauth( struct vqpasswd *pw, char *domain)
{
char *tmpbuf;
struct stat mystatbuf;
tmpbuf = malloc(MAX_BUFF);
snprintf(tmpbuf, MAX_BUFF, "%s/lastauth", pw->pw_dir);
if ( stat(tmpbuf,&mystatbuf) == -1 ) {
free(tmpbuf);
return(0);
}
free(tmpbuf);
return(mystatbuf.st_mtime);
}
char *vget_lastauthip( struct vqpasswd *pw, char *domain)
{
static char tmpbuf[MAX_BUFF];
FILE *fs;
snprintf(tmpbuf, MAX_BUFF, "%s/lastauth", pw->pw_dir);
if ( (fs=fopen(tmpbuf,"r"))==NULL) return(NULL);
fgets(tmpbuf,MAX_BUFF,fs);
fclose(fs);
return(tmpbuf);
}
#endif /* ENABLE_AUTH_LOGGING */
char *dc_filename(char *domain, uid_t uid, gid_t gid)
{
static char dir_control_file[MAX_DIR_NAME];
struct passwd *pw;
/* if we are lucky the domain is in the assign file */
if ( vget_assign(domain,dir_control_file,MAX_DIR_NAME,NULL,NULL)!=NULL ) {
strncat(dir_control_file, "/.dir-control", MAX_DIR_NAME);
/* it isn't in the assign file so we have to get it from /etc/passwd */
} else {
/* save some time if this is the vpopmail user */
if ( uid == VPOPMAILUID ) {
strncpy(dir_control_file, VPOPMAILDIR, MAX_DIR_NAME);
/* for other users, look them up in /etc/passwd */
} else if ( (pw=getpwuid(uid))!=NULL ) {
strncpy(dir_control_file, pw->pw_dir, MAX_DIR_NAME);
/* all else fails return a blank string */
} else {
return("");
}
/* stick on the rest of the path */
strncat(dir_control_file, "/" DOMAINS_DIR "/.dir-control", MAX_DIR_NAME);
}
return(dir_control_file);
}
void vcdb_strip_char( char *instr )
{
char *nextstr;
nextstr = instr;
while (*instr != 0 ) {
if ( *instr == ':' ) ++instr;
if ( nextstr != instr ) *nextstr = *instr;
++nextstr;
++instr;
}
}
int vauth_crypt(char *user,char *domain,char *clear_pass,struct vqpasswd *vpw)
{
if ( vpw == NULL ) return(-1);
return(strcmp(crypt(clear_pass,vpw->pw_passwd),vpw->pw_passwd));
}
syntax highlighted by Code2HTML, v. 0.9.1