📄 vcdb.c
字号:
/* * $Id: vcdb.c,v 1.12 2004/01/07 16:06:16 tomcollins Exp $ * Copyright (C) 1999-2003 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.12 2004/01/07 16:06:16 tomcollins 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 );extern int cdb_seek();#define MAX_BUFF 300static 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 < 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 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 < 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 < 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; FILE *pwf;#ifdef FILE_LOCKING FILE *lock_fs;#endif verrori = 0; lowerit(user); lowerit(domain); vget_assign(domain,NULL,0,&tuid,&tgid); 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 = fopen(vpasswd_cdb_file,"r")) == NULL) {#ifdef FILE_LOCKING if ( (lock_fs = fopen(vpasswd_lock_file, "w+")) == NULL) { return(NULL); } get_write_lock( lock_fs );#endif make_vpasswd_cdb(domain);#ifdef FILE_LOCKING unlock_lock(fileno(lock_fs), 0, SEEK_SET, 0); fclose(lock_fs);#endif if ((pwf = fopen(vpasswd_cdb_file,"r")) == NULL) { return(NULL); } } strncpy(line,user,sizeof(line)); strncat(line,":",sizeof(line)); ptr = line; while (*ptr != ':') { ptr++; } ptr++; switch (cdb_seek(fileno(pwf),user,strlen(user),&dlen)) { case -1: fclose(pwf); return NULL; case 0: fclose(pwf); return NULL; } if (fread(ptr,sizeof(char),dlen,pwf) != dlen) { return NULL; } fclose(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 DEBUG 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; } 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 FILE *fs3;#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 fs3 = fopen(vpasswd_lock_file, "w+"); if ( get_write_lock(fs3) < 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(fileno(fs3), 0, SEEK_SET, 0); fclose(fs3);#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(fileno(fs3), 0, SEEK_SET, 0); fclose(fs3);#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 FILE *fs3;#endif set_vpasswd_files( domain );#ifdef FILE_LOCKING fs3 = fopen(vpasswd_lock_file, "w+"); if ( get_write_lock(fs3) < 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(fileno(fs3), 0, SEEK_SET, 0); fclose(fs3);#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(fileno(fs3), 0, SEEK_SET, 0); fclose(fs3);#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 FILE *fs3;#endif uid_t myuid; uid_t uid; gid_t gid; int ret; ret = vcheck_vqpw(inpw, domain); if ( ret != 0 ) return(ret);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -