1 /*
2 * $Id: vcdb.c 1014 2011-02-03 16:04:37Z volz0r $
3 * Copyright (C) 1999-2009 Inter7 Internet Technologies, Inc.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
18 */
19 /******************************************************************************
20 **
21 ** $Id: vcdb.c 1014 2011-02-03 16:04:37Z volz0r $
22 ** Change a domain's password file to a CDB database
23 **
24 ** Chris Johnson, July 1998
25 **
26 ******************************************************************************/
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <sys/stat.h>
30 #include <fcntl.h>
31 #include <unistd.h>
32 #include <string.h>
33 #include <pwd.h>
34 #include <sys/time.h>
35 #include <time.h>
36 #include <utime.h>
37 #include <sys/types.h>
38 #include <cdbmake.h>
39 #include "config.h"
40 #include "vpopmail.h"
41 #include "vauth.h"
42 #include "vcdb.h"
43 #include "file_lock.h"
44 #include "vlimits.h"
45
46 #define TOKENS " \n"
47
48 char *dc_filename(char *domain, uid_t uid, gid_t gid);
49 void vcdb_strip_char( char *instr );
50
51 char sqlerr[MAX_BUFF] = "";
52 char *last_query = NULL;
53
54 extern int cdb_seek();
55
56 static char vpasswd_file[MAX_BUFF];
57 static char vpasswd_bak_file[MAX_BUFF];
58 static char vpasswd_cdb_file[MAX_BUFF];
59 static char vpasswd_cdb_tmp_file[MAX_BUFF];
60 static char vpasswd_lock_file[MAX_BUFF];
61 static char vpasswd_dir[MAX_BUFF];
62 static char TmpBuf1[MAX_BUFF];
63
make_vpasswd_cdb(char * domain)64 int make_vpasswd_cdb(char *domain)
65 {
66 char pwline[256];
67 char packbuf[8];
68 char *key;
69 char *data;
70 char *ptr;
71 int i,j,h;
72 int len;
73 long unsigned keylen,datalen;
74 uint32 pos,op;
75 struct cdbmake cdbm;
76 FILE *pwfile, *tmfile;
77 char Dir[156];
78 uid_t uid;
79 gid_t gid;
80 char *tmpstr;
81 mode_t oldmask;
82
83 /* If we don't optimize the index this time, just return */
84 if ( NoMakeIndex == 1 ) return(0);
85
86 if ((pwfile = fopen(vpasswd_file,"r")) == NULL) {
87 return(-1);
88 }
89
90 cdbmake_init(&cdbm);
91
92 /* temporarily set umask (no group/other access) and open temp file */
93 oldmask = umask(VPOPMAIL_UMASK);
94 tmfile = fopen(vpasswd_cdb_tmp_file,"w");
95 umask(oldmask);
96
97 if (tmfile == NULL) {
98 fprintf(stderr,"Error: could not create/open temporary file\n");
99 return(-1);
100 }
101
102 for (i=0; i < (int)sizeof(cdbm.final); i++) {
103 if (putc(' ',tmfile) == EOF) {
104 fprintf(stderr,"Error:error writing temp file\n");
105 return(-1);
106 }
107 }
108 pos = sizeof(cdbm.final);
109
110 /* creation **/
111 fgets(pwline,sizeof(pwline),pwfile);
112 while (!feof(pwfile)) {
113 key = pwline; ptr = pwline;
114 while (*ptr != ':') { ptr++; }
115 *ptr = 0; data = ptr; data++;
116 while (*ptr != '\n') { ptr++; }
117 *ptr = 0;
118 keylen = strlen(key); datalen = strlen(data);
119 #ifdef VPOPMAIL_DEBUG
120 fprintf (stderr,"Got entry: keylen = %lu, key = %s\n datalen = %lu, data = %s\n",keylen,key,datalen,data);
121 #endif
122
123 cdbmake_pack(packbuf, (uint32)keylen);
124 cdbmake_pack(packbuf + 4, (uint32)datalen);
125 if (fwrite(packbuf,1,8,tmfile) < 8) {
126 fprintf(stderr,"Error: error writing temp file\n");
127 return(-1);
128 }
129
130 h = CDBMAKE_HASHSTART;
131 for (i=0; i < (int)keylen; i++) {
132 h = cdbmake_hashadd(h,key[i]);
133 if (putc(key[i],tmfile) == EOF) {
134 fprintf (stderr,"Error: error temp file\n");
135 return(-1);
136 }
137 }
138 for (i=0; i < (int)datalen; i++) {
139 if (putc(data[i],tmfile) == EOF) {
140 fprintf (stderr,"Error: write error temp file");
141 return(-1);
142 }
143 }
144 if (!cdbmake_add(&cdbm,h,pos,malloc)) {
145 fprintf(stderr, "Error: out of memory\n");
146 return(-1);
147 }
148
149 op = pos;
150 pos += (uint32)8;
151 pos += (uint32)keylen;
152 pos += (uint32)datalen;
153 if (pos < op) {
154 fprintf(stderr,"Error: too much data\n");
155 return(-1);
156 }
157 if (!cdbmake_split(&cdbm,malloc)) {
158 fprintf(stderr,"Error: out of memory\n");
159 return(-1);
160 }
161 fgets(pwline,sizeof(pwline),pwfile);
162 free(cdbm.split);
163 }
164 fclose(pwfile);
165
166 if (!cdbmake_split(&cdbm,malloc)) {
167 fprintf(stderr, "Error: out of memory\n");
168 return(-1);
169 }
170
171 for (i=0; i < 256; i++) {
172 len = cdbmake_throw(&cdbm,pos,i);
173 for (j=0; j < len; j++) {
174 cdbmake_pack(packbuf,cdbm.hash[j].h);
175 cdbmake_pack(packbuf + 4, cdbm.hash[j].p);
176 if (fwrite(packbuf,1,8,tmfile) < 8) {
177 fprintf(stderr,"Error 1: error temp file\n");
178 return(-1);
179 }
180 op = pos;
181 pos += (uint32)8;
182 if (pos < op) {
183 fprintf (stderr, "Error 12: too much data\n");
184 return(-1);
185 }
186 }
187 }
188 if (fflush(tmfile) == EOF) {
189 fprintf (stderr,"Error 20: write error temp file\n");
190 return(-1);
191 }
192 rewind(tmfile);
193 if (fwrite(cdbm.final,1,sizeof(cdbm.final),tmfile)<sizeof(cdbm.final)){
194 fprintf(stderr,"Error 21: write error temp file\n");
195 return(-1);
196 }
197 if (fflush(tmfile) == EOF) {
198 fprintf(stderr,"Error 22: write error temp file\n");
199 return(-1);
200 }
201
202 if (close(fileno(tmfile)) == -1) {
203 fprintf(stderr,"Error 24: error with close()\n");
204 return(-1);
205 }
206 if (rename(vpasswd_cdb_tmp_file,vpasswd_cdb_file)) {
207 fprintf(stderr,
208 "Error 25: could not rename cdb.tmp to vpasswd.cdb\n");
209 return(-1);
210 }
211 free(cdbm.head);
212 free(cdbm.split);
213
214 tmpstr = vget_assign(domain, Dir, 156, &uid, &gid );
215 chown(vpasswd_cdb_file, uid, gid);
216 chown(vpasswd_lock_file, uid, gid);
217 chown(vpasswd_file, uid, gid);
218
219 return 0;
220 }
221
vauth_getpw(char * user,char * domain)222 struct vqpasswd *vauth_getpw(char *user, char *domain)
223 {
224 char in_domain[156];
225 static struct vqpasswd pwent;
226 static char line[2048];
227 char *ptr = NULL, *uid = NULL, *gid = NULL;
228 uid_t myuid;
229 uid_t tuid;
230 gid_t tgid;
231 uint32 dlen;
232 int pwf;
233 #ifdef FILE_LOCKING
234 int lock_fd;
235 #endif
236
237 verrori = 0;
238 lowerit(user);
239 lowerit(domain);
240
241 if (vget_assign(domain,NULL,0,&tuid,&tgid) == NULL) {
242 /* domain does not exist */
243 return(NULL);
244 }
245
246 myuid = geteuid();
247 if ( myuid != 0 && myuid != tuid ) {
248 return(NULL);
249 }
250
251 strncpy( in_domain, domain, sizeof(in_domain));
252 in_domain[sizeof(in_domain)-1] = '\0'; /* ensure NULL termination */
253
254 set_vpasswd_files( in_domain );
255
256 if ((pwf = open(vpasswd_cdb_file,O_RDONLY)) < 0 ) {
257 #ifdef FILE_LOCKING
258 if ( (lock_fd=open(vpasswd_lock_file, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR)) < 0) {
259 return(NULL);
260 }
261 get_write_lock( lock_fd );
262 #endif
263 make_vpasswd_cdb(domain);
264 #ifdef FILE_LOCKING
265 unlock_lock(lock_fd, 0, SEEK_SET, 0);
266 close(lock_fd);
267 #endif
268 if ((pwf = open(vpasswd_cdb_file,O_RDONLY)) < 0 ) {
269 return(NULL);
270 }
271 }
272
273 strncpy(line,user,sizeof(line));
274 strncat(line,":",sizeof(line));
275 ptr = line;
276 while (*ptr != ':') { ptr++; }
277 ptr++;
278 switch (cdb_seek(pwf,user,strlen(user),&dlen)) {
279 case -1:
280 case 0:
281 close(pwf);
282 return NULL;
283 }
284 if (read(pwf, ptr,dlen) != (int)dlen) {
285 close(pwf);
286 return NULL;
287 }
288 close(pwf);
289 line[(dlen+strlen(user)+1)] = 0;
290
291 pwent.pw_name = "";
292 pwent.pw_passwd = "";
293 pwent.pw_gecos = "";
294 pwent.pw_dir = "";
295 pwent.pw_shell = "";
296 pwent.pw_clear_passwd = "";
297
298 ptr = line;
299 pwent.pw_name = line;
300 while (*ptr!=0&&*ptr != ':') { ptr++; }
301 if ( *ptr!=0 ){ *ptr = 0; ptr++; pwent.pw_passwd = ptr; }
302 while (*ptr!=0&&*ptr != ':') { ptr++; }
303 if ( *ptr!=0 ){ *ptr = 0; ptr++; uid = ptr; }
304 while (*ptr!=0&&*ptr != ':') { ptr++; }
305 if ( *ptr!=0 ){ *ptr = 0; ptr++; gid = ptr; }
306 while (*ptr!=0&&*ptr != ':') { ptr++; }
307 if ( *ptr!=0 ){ *ptr = 0; ptr++; pwent.pw_gecos = ptr; }
308 while (*ptr!=0&&*ptr != ':') { ptr++; }
309 if ( *ptr!=0 ){ *ptr = 0; ptr++; pwent.pw_dir = ptr; }
310 while (*ptr!=0&&*ptr != ':') { ptr++; }
311 if ( *ptr!=0 ){ *ptr = 0; ptr++; pwent.pw_shell = ptr; }
312 while (*ptr!=0&&*ptr != ':') { ptr++; }
313 if ( *ptr!=0 ){ *ptr = 0; ptr++; pwent.pw_clear_passwd = ptr; }
314
315 if (!*uid) { pwent.pw_uid = 0; } else { pwent.pw_uid = atoi(uid); }
316 if (!*gid) { pwent.pw_gid = 0; } else { pwent.pw_gid = atoi(gid); }
317
318 vlimits_setflags (&pwent, in_domain);
319
320 #ifdef VPOPMAIL_DEBUG
321 if( dump_data ) {
322 fprintf (stderr,"vgetpw: db: results: pw_name = %s\n",pwent.pw_name);
323 fprintf (stderr," pw_passwd = %s\n",pwent.pw_passwd);
324 fprintf (stderr," pw_uid = %d\n",pwent.pw_uid);
325 fprintf (stderr," pw_gid = %d\n",pwent.pw_gid);
326 fprintf (stderr," pw_flags = %d\n",pwent.pw_flags);
327 fprintf (stderr," pw_gecos = %s\n",pwent.pw_gecos);
328 fprintf (stderr," pw_dir = %s\n",pwent.pw_dir);
329 fprintf (stderr," pw_shell = %s\n",pwent.pw_shell);
330 }
331 #endif
332
333 return(&pwent);
334 }
335
336
vauth_getall(char * domain,int first,int sortit)337 struct vqpasswd *vauth_getall(char *domain, int first, int sortit)
338 {
339 static FILE *fsv = NULL;
340 struct vqpasswd *tmpwd;
341
342 set_vpasswd_files( domain );
343 if ( first == 1 ) {
344 if ( fsv != NULL ) fclose(fsv);
345 set_vpasswd_files( domain );
346 if ((fsv = fopen(vpasswd_file, "r")) == NULL) return(NULL);
347 } else if ( fsv == NULL ) {
348 return(NULL);
349 }
350 tmpwd = vgetent(fsv);
351 if ( tmpwd == NULL ) {
352 fclose(fsv);
353 fsv = NULL;
354 }
355 if(tmpwd) vlimits_setflags(tmpwd,domain) ;
356 return(tmpwd);
357 }
358
vauth_end_getall()359 void vauth_end_getall()
360 {
361 }
362
set_vpasswd_files(char * domain)363 void set_vpasswd_files( char *domain )
364 {
365 char *tmpstr;
366 uid_t uid;
367 gid_t gid;
368 char Dir[156];
369
370 vset_default_domain( domain );
371 tmpstr = vget_assign(domain, Dir, 156, &uid, &gid );
372 memset(vpasswd_dir, 0, MAX_BUFF);
373 memset(vpasswd_file, 0, MAX_BUFF);
374 memset(vpasswd_cdb_file, 0, MAX_BUFF);
375 memset(vpasswd_cdb_tmp_file, 0, MAX_BUFF);
376 memset(vpasswd_lock_file, 0, MAX_BUFF);
377
378 if ( domain == NULL || domain[0] == 0 ) {
379 snprintf(vpasswd_dir, MAX_BUFF, "%s/users", VPOPMAILDIR);
380 } else {
381 snprintf(vpasswd_dir, MAX_BUFF, "%s", Dir);
382 }
383 snprintf(vpasswd_file, MAX_BUFF, "%s/%s", vpasswd_dir,VPASSWD_FILE);
384 snprintf(vpasswd_bak_file, MAX_BUFF, "%s/%s.%d",
385 vpasswd_dir,VPASSWD_BAK_FILE, getpid());
386 snprintf(vpasswd_cdb_file, MAX_BUFF,
387 "%s/%s", vpasswd_dir,VPASSWD_CDB_FILE);
388 snprintf(vpasswd_cdb_tmp_file, MAX_BUFF,
389 "%s/%s",vpasswd_dir,VPASSWD_CDB_TMP_FILE);
390 snprintf(vpasswd_lock_file, MAX_BUFF,
391 "%s/%s", vpasswd_dir,VPASSWD_LOCK_FILE);
392 }
393
vauth_adduser(char * user,char * domain,char * pass,char * gecos,char * dir,int apop)394 int vauth_adduser(char *user, char *domain, char *pass, char *gecos, char *dir, int apop )
395 {
396 static char tmpbuf1[MAX_BUFF];
397 static char tmpbuf2[MAX_BUFF];
398 char *tmpstr;
399 int added = 0;
400 FILE *fs1;
401 FILE *fs2;
402 #ifdef FILE_LOCKING
403 int fd3;
404 #endif
405
406 /* do not trod on the vpasswd file */
407 if ( strcmp( "vpasswd", user ) == 0 ) {
408 return( VA_ILLEGAL_USERNAME );
409 }
410
411 set_vpasswd_files( domain );
412
413 /* if the gecos field is null, set it to user name */
414 if ( gecos==0 || gecos[0]==0) gecos=user;
415 vcdb_strip_char( gecos );
416
417 #ifdef FILE_LOCKING
418 fd3 = open(vpasswd_lock_file, O_WRONLY | O_CREAT, S_IRUSR|S_IWUSR);
419 if ( get_write_lock(fd3) < 0 ) return(-2);
420 #endif
421
422 fs1 = fopen(vpasswd_bak_file, "w+");
423 if ( (fs2 = fopen(vpasswd_file, "r+")) == NULL ) {
424 fs2 = fopen(vpasswd_file, "w+");
425 }
426
427 if ( fs1 == NULL || fs2 == NULL ) {
428 if ( fs1 != NULL ) fclose(fs1);
429 if ( fs2 != NULL ) fclose(fs2);
430 #ifdef FILE_LOCKING
431 unlock_lock(fd3, 0, SEEK_SET, 0);
432 close(fd3);
433 #endif
434 return(-1);
435 }
436
437 while (fgets(tmpbuf1,MAX_BUFF,fs2)!=NULL){
438 strncpy(tmpbuf2, tmpbuf1, MAX_BUFF);
439 tmpstr = strtok(tmpbuf2,":");
440 if ( added == 0 && strcmp(user, tmpstr) < 0 ) {
441 added = 1;
442 vauth_adduser_line( fs1, user, pass, domain,gecos,dir, apop);
443 }
444 fputs(tmpbuf1, fs1);
445 }
446 if ( added == 0 ) {
447 vauth_adduser_line( fs1, user, pass, domain,gecos,dir,apop);
448 }
449 fclose(fs1);
450 fclose(fs2);
451
452 rename(vpasswd_bak_file, vpasswd_file);
453 make_vpasswd_cdb(domain);
454
455 #ifdef FILE_LOCKING
456 unlock_lock(fd3, 0, SEEK_SET, 0);
457 close(fd3);
458 #endif
459
460 return(0);
461
462 }
463
vauth_adddomain(char * domain)464 int vauth_adddomain( char *domain )
465 {
466 return(0);
467 }
468
vauth_deldomain(char * domain)469 int vauth_deldomain( char *domain )
470 {
471 return(0);
472 }
473
vauth_deluser(char * user,char * domain)474 int vauth_deluser( char *user, char *domain )
475 {
476 static char tmpbuf1[MAX_BUFF];
477 static char tmpbuf2[MAX_BUFF];
478 char *tmpstr;
479 FILE *fs1;
480 FILE *fs2;
481 #ifdef FILE_LOCKING
482 int fd3;
483 #endif
484
485 set_vpasswd_files( domain );
486
487 #ifdef FILE_LOCKING
488 fd3 = open(vpasswd_lock_file, O_WRONLY | O_CREAT, S_IRUSR|S_IWUSR);
489 if ( get_write_lock(fd3) < 0 ) return(-2);
490 #endif
491
492 fs1 = fopen(vpasswd_bak_file, "w+");
493 if ( (fs2 = fopen(vpasswd_file, "r+")) == NULL ) {
494 fs2 = fopen(vpasswd_file, "w+");
495 }
496
497 if ( fs1 == NULL || fs2 == NULL ) {
498 if ( fs1 != NULL ) fclose(fs1);
499 if ( fs2 != NULL ) fclose(fs2);
500 #ifdef FILE_LOCKING
501 unlock_lock(fd3, 0, SEEK_SET, 0);
502 close(fd3);
503 #endif
504 return(-1);
505 }
506
507 while (fgets(tmpbuf1,MAX_BUFF,fs2)!=NULL){
508 strncpy(tmpbuf2, tmpbuf1, MAX_BUFF);
509 tmpstr = strtok(tmpbuf2,":");
510
511 if ( strcmp(user, tmpstr) != 0) {
512 fputs(tmpbuf1, fs1);
513 }
514 }
515 fclose(fs1);
516 fclose(fs2);
517
518 rename(vpasswd_bak_file, vpasswd_file);
519 make_vpasswd_cdb(domain);
520
521 #ifdef FILE_LOCKING
522 unlock_lock(fd3, 0, SEEK_SET, 0);
523 close(fd3);
524 #endif
525
526 return(0);
527 }
528
529 /* Utility function to set the users quota
530 *
531 * Calls underlying vauth_getpw and vauth_setpw
532 * to actually change the users information
533 */
vauth_setquota(char * username,char * domain,char * quota)534 int vauth_setquota( char *username, char *domain, char *quota)
535 {
536 struct vqpasswd *vpw;
537
538 if ( strlen(username) > MAX_PW_NAME ) return(VA_USER_NAME_TOO_LONG);
539 #ifdef USERS_BIG_DIR
540 if ( strlen(username) == 1 ) return(VA_ILLEGAL_USERNAME);
541 #endif
542 if ( strlen(domain) > MAX_PW_DOMAIN ) return(VA_DOMAIN_NAME_TOO_LONG);
543 if ( strlen(quota) > MAX_PW_QUOTA ) return(VA_QUOTA_TOO_LONG);
544
545 vpw = vauth_getpw( username, domain );
546 if ( vpw==NULL ) return(VA_USER_DOES_NOT_EXIST);
547 vpw->pw_shell = quota;
548 return(vauth_setpw(vpw,domain));
549
550 }
551
vauth_setpw(struct vqpasswd * inpw,char * domain)552 int vauth_setpw( struct vqpasswd *inpw, char *domain )
553 {
554 static char tmpbuf1[MAX_BUFF];
555 static char tmpbuf2[MAX_BUFF];
556 char *tmpstr;
557 FILE *fs1;
558 FILE *fs2;
559 #ifdef FILE_LOCKING
560 int fd3;
561 #endif
562 uid_t myuid;
563 uid_t uid;
564 gid_t gid;
565 int ret;
566
567 ret = vcheck_vqpw(inpw, domain);
568 if ( ret != 0 ) return(ret);
569
570 /* get the owner of the domain */
571 vget_assign(domain,NULL,0,&uid,&gid);
572
573 /* get the current effective user */
574 myuid = geteuid();
575
576 /*
577 * if it is not the owner, vpopmail or root
578 * then reject this operation
579 */
580 if ( myuid != 0 && myuid != uid ) {
581 return(VA_BAD_UID);
582 }
583
584 set_vpasswd_files( domain );
585 #ifdef FILE_LOCKING
586 fd3 = open(vpasswd_lock_file, O_WRONLY | O_CREAT, S_IRUSR|S_IWUSR);
587 if ( get_write_lock(fd3) < 0 ) return(-2);
588 #endif
589
590 fs1 = fopen(vpasswd_bak_file, "w+");
591 if ( (fs2 = fopen(vpasswd_file, "r+")) == NULL ) {
592 fs2 = fopen(vpasswd_file, "w+");
593 }
594
595 if ( fs1 == NULL || fs2 == NULL ) {
596 if ( fs1 != NULL ) fclose(fs1);
597 if ( fs2 != NULL ) fclose(fs2);
598
599 #ifdef FILE_LOCKING
600 unlock_lock(fd3, 0, SEEK_SET, 0);
601 close(fd3);
602 #endif
603 return(-1);
604 }
605 vcdb_strip_char( inpw->pw_gecos );
606 #ifndef CLEAR_PASS
607 vcdb_strip_char( inpw->pw_clear_passwd );
608 #endif
609
610 while (fgets(tmpbuf1,MAX_BUFF,fs2)!=NULL){
611 strncpy(tmpbuf2, tmpbuf1, MAX_BUFF);
612 tmpstr = strtok(tmpbuf2,":\n");
613
614 if ( strcmp(inpw->pw_name, tmpstr) != 0) {
615 fputs(tmpbuf1, fs1);
616 } else {
617 #ifndef CLEAR_PASS
618 fprintf(fs1, "%s:%s:%d:%d:%s:%s:%s\n",
619 inpw->pw_name,
620 inpw->pw_passwd,
621 inpw->pw_uid,
622 inpw->pw_gid,
623 inpw->pw_gecos,
624 inpw->pw_dir,
625 inpw->pw_shell);
626 #else
627 fprintf(fs1, "%s:%s:%d:%d:%s:%s:%s:%s\n",
628 inpw->pw_name,
629 inpw->pw_passwd,
630 inpw->pw_uid,
631 inpw->pw_gid,
632 inpw->pw_gecos,
633 inpw->pw_dir,
634 inpw->pw_shell, inpw->pw_clear_passwd);
635 #endif
636 }
637 }
638 fclose(fs1);
639 fclose(fs2);
640
641 rename(vpasswd_bak_file, vpasswd_file);
642 make_vpasswd_cdb(domain);
643
644 #ifdef FILE_LOCKING
645 unlock_lock(fd3, 0, SEEK_SET, 0);
646 close(fd3);
647 #endif
648
649 #ifdef SQWEBMAIL_PASS
650 tmpstr = vget_assign(domain, NULL, 0, &uid, &gid );
651 vsqwebmail_pass( inpw->pw_dir, inpw->pw_passwd, uid, gid);
652 #endif
653
654 #ifdef ONCHANGE_SCRIPT
655 if( allow_onchange ) {
656 /* tell other programs that data has changed */
657 snprintf ( onchange_buf, MAX_BUFF, "%s@%s", inpw->pw_name, domain ) ;
658 call_onchange ( "mod_user" ) ;
659 }
660 #endif
661
662 return(0);
663 }
664
vauth_adduser_line(FILE * fs1,char * user,char * pass,char * domain,char * gecos,char * dir,int apop)665 int vauth_adduser_line( FILE *fs1,
666 char *user,
667 char *pass,
668 char *domain,
669 char *gecos,
670 char *dir, int apop )
671 {
672 char Dir[156];
673 uid_t uid;
674 gid_t gid;
675 char crypted[100];
676
677 if ( vget_assign(domain, Dir, 156, &uid, &gid ) == NULL ) {
678 strcpy(Dir, VPOPMAILDIR);
679 }
680
681 if ( pass[0] != 0 ) {
682 mkpasswd3(pass,crypted, 100);
683 } else {
684 crypted[0] = 0;
685 }
686
687 fprintf(fs1,"%s:", user );
688
689 if ( apop == USE_POP ) fprintf(fs1, "%s:1:", crypted);
690 else fprintf(fs1, "%s:2:", crypted);
691
692 fprintf(fs1, "0:%s:%s", gecos, Dir);
693
694 if ( strlen(domain) <= 0 ) {
695 if ( strlen(dir) > 0 ) {
696 fprintf(fs1, "/users/%s/%s:", dir, user);
697 } else {
698 fprintf(fs1, "/users/%s:", user);
699 }
700 } else {
701 if ( strlen(dir) > 0 ) {
702 fprintf(fs1,"/%s/%s:", dir,user);
703 } else {
704 fprintf(fs1, "/%s:", user);
705 }
706 }
707
708 fprintf(fs1, "NOQUOTA");
709
710 #ifndef CLEAR_PASS
711 fprintf(fs1, "\n");
712 #else
713 fprintf(fs1, ":%s\n", pass);
714 #endif
715
716 return(0);
717 }
718
719
vmkpasswd(char * domain)720 int vmkpasswd( char *domain )
721 {
722 #ifdef FILE_LOCKING
723 int fd3;
724 #endif
725 char Dir[156];
726 uid_t uid;
727 gid_t gid;
728 char *tmpstr;
729
730 getcwd(TmpBuf1, MAX_BUFF);
731 tmpstr = vget_assign(domain, Dir, 156, &uid, &gid );
732
733 if ( chdir(Dir) != 0 ) return(VA_BAD_DIR);
734
735 lowerit(domain);
736 set_vpasswd_files( domain );
737 #ifdef FILE_LOCKING
738 fd3 = open(vpasswd_lock_file, O_WRONLY | O_CREAT, S_IRUSR|S_IWUSR);
739 if ( get_write_lock(fd3) < 0 ) return(-2);
740 #endif
741
742 make_vpasswd_cdb(domain);
743 #ifdef FILE_LOCKING
744 unlock_lock(fd3, 0, SEEK_SET, 0);
745 close(fd3);
746 #endif
747
748 return(0);
749 }
750
751 /* Verify the connection to the authentication database */
752
vauth_open(int will_update)753 int vauth_open( int will_update ) {
754
755 #ifdef VPOPMAIL_DEBUG
756 show_trace = ( getenv("VPSHOW_TRACE") != NULL);
757 show_query = ( getenv("VPSHOW_QUERY") != NULL);
758 dump_data = ( getenv("VPDUMP_DATA") != NULL);
759 #endif
760
761 #ifdef VPOPMAIL_DEBUG
762 if( show_trace ) {
763 fprintf( stderr, "vauth_open()\n");
764 }
765 #endif
766
767
768 /*
769 * If the connection to this authentication database can fail
770 * you should test access here. If it works, return 0, else
771 * return VA_NO_AUTH_CONNECTION. You can also set the string
772 * sqlerr to some short descriptive text about the problem,
773 * and allocate a much longer string, pointed to by last_query
774 * that can be displayed in an error message returned because
775 * of this problem.
776 *
777 */
778
779 return( 0 );
780 }
781
vclose()782 void vclose()
783 {
784
785 }
786
787 #ifdef IP_ALIAS_DOMAINS
vget_ip_map(char * ip,char * domain,int domain_size)788 int vget_ip_map( char *ip, char *domain, int domain_size)
789 {
790 FILE *fs;
791 char tmpbuf[156];
792 char *tmpstr;
793
794 if ( ip == NULL || strlen(ip) <= 0 ) return(-1);
795
796 /* open the ip_alias_map file */
797 snprintf(tmpbuf, 156, "%s/%s", VPOPMAILDIR, IP_ALIAS_MAP_FILE);
798 if ( (fs = fopen(tmpbuf,"r")) == NULL ) return(-1);
799
800 while( fgets(tmpbuf, 156, fs) != NULL ) {
801 tmpstr = strtok(tmpbuf, IP_ALIAS_TOKENS);
802 if ( tmpstr == NULL ) continue;
803 if ( strcmp(ip, tmpstr) != 0 ) continue;
804
805 tmpstr = strtok(NULL, IP_ALIAS_TOKENS);
806 if ( tmpstr == NULL ) continue;
807 strncpy(domain, tmpstr, domain_size);
808 fclose(fs);
809 return(0);
810
811 }
812 fclose(fs);
813 return(-1);
814 }
815
816 /*
817 * Add an ip to domain mapping
818 * It will remove any duplicate entry before adding it
819 *
820 */
vadd_ip_map(char * ip,char * domain)821 int vadd_ip_map( char *ip, char *domain)
822 {
823 FILE *fs;
824 char tmpbuf[156];
825
826 if ( ip == NULL || strlen(ip) <= 0 ) return(-1);
827 if ( domain == NULL || strlen(domain) <= 0 ) return(-10);
828
829 vdel_ip_map( ip, domain );
830
831 snprintf(tmpbuf, 156, "%s/%s", VPOPMAILDIR, IP_ALIAS_MAP_FILE);
832 if ( (fs = fopen(tmpbuf,"a+")) == NULL ) return(-1);
833 fprintf( fs, "%s %s\n", ip, domain);
834 fclose(fs);
835
836 return(0);
837 }
838
vdel_ip_map(char * ip,char * domain)839 int vdel_ip_map( char *ip, char *domain)
840 {
841 FILE *fs;
842 FILE *fs1;
843 char file1[156];
844 char file2[156];
845 char tmpbuf[156];
846 char tmpbuf1[156];
847 char *ip_f;
848 char *domain_f;
849
850 if ( ip == NULL || strlen(ip) <= 0 ) return(-1);
851 if ( domain == NULL || strlen(domain) <= 0 ) return(-1);
852
853 snprintf(file1, 156, "%s/%s", VPOPMAILDIR, IP_ALIAS_MAP_FILE);
854 if ( (fs = fopen(file1,"r")) == NULL ) return(-1);
855
856 snprintf(file2, 156,
857 "%s/%s.%d", VPOPMAILDIR, IP_ALIAS_MAP_FILE, getpid());
858 if ( (fs1 = fopen(file2,"w")) == NULL ) {
859 fclose(fs);
860 return(-1);
861 }
862
863 while( fgets(tmpbuf, 156, fs) != NULL ) {
864 strncpy(tmpbuf1,tmpbuf, 156);
865
866 ip_f = strtok(tmpbuf, IP_ALIAS_TOKENS);
867 if ( ip_f == NULL ) continue;
868
869 domain_f = strtok(NULL, IP_ALIAS_TOKENS);
870 if ( domain_f == NULL ) continue;
871
872 if ( strcmp(ip, ip_f) == 0 && strcmp(domain,domain_f) == 0)
873 continue;
874
875 fprintf(fs1, tmpbuf1);
876
877 }
878 fclose(fs);
879 fclose(fs1);
880
881 if ( rename( file2, file1) < 0 ) return(-1);
882
883 return(0);
884 }
885
vshow_ip_map(int first,char * ip,char * domain)886 int vshow_ip_map( int first, char *ip, char *domain)
887 {
888 static FILE *fs = NULL;
889 char tmpbuf[156];
890 char *tmpstr;
891
892 if ( ip == NULL ) return(-1);
893 if ( domain == NULL ) return(-1);
894
895 if ( first == 1 ) {
896 if ( fs != NULL ) {
897 fclose(fs);
898 fs = NULL;
899 }
900 snprintf(tmpbuf, 156, "%s/%s", VPOPMAILDIR, IP_ALIAS_MAP_FILE);
901 if ( (fs = fopen(tmpbuf,"r")) == NULL ) return(-1);
902 }
903 if ( fs == NULL ) return(-1);
904
905 while (1) {
906 if (fgets(tmpbuf, 156, fs) == NULL ) {
907 fclose(fs);
908 fs = NULL;
909 return(0);
910 }
911
912 tmpstr = strtok(tmpbuf, IP_ALIAS_TOKENS);
913 if ( tmpstr == NULL ) continue;
914 strcpy( ip, tmpstr);
915
916 tmpstr = strtok(NULL, IP_ALIAS_TOKENS);
917 if ( tmpstr == NULL ) continue;
918 strcpy( domain, tmpstr);
919
920 return(1);
921 }
922 return(-1);
923
924 }
925 #endif
926
vread_dir_control(vdir_type * vdir,char * domain,uid_t uid,gid_t gid)927 int vread_dir_control(vdir_type *vdir, char *domain, uid_t uid, gid_t gid)
928 {
929 FILE *fs;
930 char dir_control_file[MAX_DIR_NAME];
931 int i;
932
933 strncpy(dir_control_file,dc_filename(domain, uid, gid),MAX_DIR_NAME);
934
935
936 if ( (fs = fopen(dir_control_file, "r")) == NULL ) {
937 vdir->cur_users = 0;
938 for(i=0;i<MAX_DIR_LEVELS;++i){
939 vdir->level_start[i] = 0;
940 vdir->level_end[i] = MAX_DIR_LIST-1;
941 vdir->level_index[i] = 0;
942 }
943 vdir->level_mod[0] = 0;
944 vdir->level_mod[1] = 2;
945 vdir->level_mod[2] = 4;
946 vdir->level_cur = 0;
947 vdir->level_max = MAX_DIR_LEVELS;
948 vdir->the_dir[0] = 0;
949 return(-1);
950 }
951
952 fgets(dir_control_file, MAX_DIR_NAME, fs );
953 vdir->cur_users = atol(dir_control_file);
954
955 fgets(dir_control_file, MAX_DIR_NAME, fs );
956 vdir->level_cur = atoi(dir_control_file);
957
958 fgets(dir_control_file, MAX_DIR_NAME, fs );
959 vdir->level_max = atoi(dir_control_file);
960
961 fgets(dir_control_file, MAX_DIR_NAME, fs );
962 vdir->level_start[0] = atoi(dir_control_file);
963 for(i=0;dir_control_file[i]!=' ';++i); ++i;
964 vdir->level_start[1] = atoi(&dir_control_file[i]);
965 for(i=0;dir_control_file[i]!=' ';++i); ++i;
966 vdir->level_start[2] = atoi(&dir_control_file[i]);
967
968 fgets(dir_control_file, MAX_DIR_NAME, fs );
969 vdir->level_end[0] = atoi(dir_control_file);
970 for(i=0;dir_control_file[i]!=' ';++i); ++i;
971 vdir->level_end[1] = atoi(&dir_control_file[i]);
972 for(i=0;dir_control_file[i]!=' ';++i); ++i;
973 vdir->level_end[2] = atoi(&dir_control_file[i]);
974
975 fgets(dir_control_file, MAX_DIR_NAME, fs );
976 vdir->level_mod[0] = atoi(dir_control_file);
977 for(i=0;dir_control_file[i]!=' ';++i); ++i;
978 vdir->level_mod[1] = atoi(&dir_control_file[i]);
979 for(i=0;dir_control_file[i]!=' ';++i); ++i;
980 vdir->level_mod[2] = atoi(&dir_control_file[i]);
981
982 fgets(dir_control_file, MAX_DIR_NAME, fs );
983 vdir->level_index[0] = atoi(dir_control_file);
984 for(i=0;dir_control_file[i]!=' ';++i); ++i;
985 vdir->level_index[1] = atoi(&dir_control_file[i]);
986 for(i=0;dir_control_file[i]!=' ';++i); ++i;
987 vdir->level_index[2] = atoi(&dir_control_file[i]);
988
989 fgets(dir_control_file, MAX_DIR_NAME, fs );
990 for(i=0;dir_control_file[i]!=0;++i) {
991 if (dir_control_file[i] == '\n') {
992 dir_control_file[i] = 0;
993 }
994 }
995
996 fgets(dir_control_file, MAX_DIR_NAME, fs );
997 for(i=0;dir_control_file[i]!=0;++i) {
998 if (dir_control_file[i] == '\n') {
999 dir_control_file[i] = 0;
1000 }
1001 }
1002 strncpy(vdir->the_dir, dir_control_file, MAX_DIR_NAME);
1003
1004 fclose(fs);
1005
1006 return(0);
1007 }
1008
vwrite_dir_control(vdir_type * vdir,char * domain,uid_t uid,gid_t gid)1009 int vwrite_dir_control(vdir_type *vdir, char *domain, uid_t uid, gid_t gid)
1010 {
1011 FILE *fs;
1012 char dir_control_file[MAX_DIR_NAME];
1013 char dir_control_tmp_file[MAX_DIR_NAME];
1014
1015 strncpy(dir_control_file,dc_filename(domain, uid, gid),MAX_DIR_NAME);
1016 snprintf(dir_control_tmp_file, MAX_DIR_NAME,
1017 "%s.%d", dir_control_file, getpid());
1018
1019 if ( (fs = fopen(dir_control_tmp_file, "w+")) == NULL ) {
1020 return(-1);
1021 }
1022
1023 fprintf(fs, "%lu\n", vdir->cur_users);
1024 fprintf(fs, "%d\n", vdir->level_cur);
1025 fprintf(fs, "%d\n", vdir->level_max);
1026 fprintf(fs, "%d %d %d\n",
1027 vdir->level_start[0],
1028 vdir->level_start[1],
1029 vdir->level_start[2]);
1030 fprintf(fs, "%d %d %d\n",
1031 vdir->level_end[0],
1032 vdir->level_end[1],
1033 vdir->level_end[2]);
1034 fprintf(fs, "%d %d %d\n",
1035 vdir->level_mod[0],
1036 vdir->level_mod[1],
1037 vdir->level_mod[2]);
1038 fprintf(fs, "%d %d %d\n",
1039 vdir->level_index[0],
1040 vdir->level_index[1],
1041 vdir->level_index[2]);
1042 fprintf(fs, "%s\n", vdir->the_dir);
1043
1044 fclose(fs);
1045
1046 rename( dir_control_tmp_file, dir_control_file);
1047
1048 chown(dir_control_file,uid, gid);
1049
1050 return(0);
1051 }
1052
vdel_dir_control(char * domain)1053 int vdel_dir_control(char *domain)
1054 {
1055 char dir_control_file[MAX_DIR_NAME];
1056
1057 vget_assign(domain, dir_control_file, 156, NULL,NULL);
1058 strncat(dir_control_file,"/.dir-control", MAX_DIR_NAME);
1059 return(unlink(dir_control_file));
1060 }
1061
1062 #ifdef ENABLE_AUTH_LOGGING
vset_lastauth(char * user,char * domain,char * remoteip)1063 int vset_lastauth(char *user, char *domain, char *remoteip )
1064 {
1065 char *tmpbuf;
1066 FILE *fs;
1067 struct vqpasswd *vpw;
1068 uid_t uid;
1069 gid_t gid;
1070
1071 if( (vpw = vauth_getpw( user, domain )) == NULL) return(0);
1072
1073 tmpbuf = malloc(MAX_BUFF);
1074 snprintf(tmpbuf, MAX_BUFF, "%s/lastauth", vpw->pw_dir);
1075 if ( (fs = fopen(tmpbuf,"w+")) == NULL ) {
1076 free(tmpbuf);
1077 return(-1);
1078 }
1079 fprintf(fs, "%s", remoteip);
1080 fclose(fs);
1081
1082 vget_assign(domain,NULL,0,&uid,&gid);
1083 chown(tmpbuf,uid,gid);
1084 free(tmpbuf);
1085 return(0);
1086 }
1087
vget_lastauth(struct vqpasswd * pw,char * domain)1088 time_t vget_lastauth( struct vqpasswd *pw, char *domain)
1089 {
1090 char *tmpbuf;
1091 struct stat mystatbuf;
1092
1093 tmpbuf = malloc(MAX_BUFF);
1094 snprintf(tmpbuf, MAX_BUFF, "%s/lastauth", pw->pw_dir);
1095 if ( stat(tmpbuf,&mystatbuf) == -1 ) {
1096 free(tmpbuf);
1097 return(0);
1098 }
1099 free(tmpbuf);
1100 return(mystatbuf.st_mtime);
1101 }
1102
vget_lastauthip(struct vqpasswd * pw,char * domain)1103 char *vget_lastauthip( struct vqpasswd *pw, char *domain)
1104 {
1105 static char tmpbuf[MAX_BUFF];
1106 FILE *fs;
1107
1108 snprintf(tmpbuf, MAX_BUFF, "%s/lastauth", pw->pw_dir);
1109 if ( (fs=fopen(tmpbuf,"r"))==NULL) return(NULL);
1110 fgets(tmpbuf,MAX_BUFF,fs);
1111 fclose(fs);
1112 return(tmpbuf);
1113 }
1114 #endif /* ENABLE_AUTH_LOGGING */
1115
dc_filename(char * domain,uid_t uid,gid_t gid)1116 char *dc_filename(char *domain, uid_t uid, gid_t gid)
1117 {
1118 static char dir_control_file[MAX_DIR_NAME];
1119 struct passwd *pw;
1120
1121 /* if we are lucky the domain is in the assign file */
1122 if ( vget_assign(domain,dir_control_file,MAX_DIR_NAME,NULL,NULL)!=NULL ) {
1123 strncat(dir_control_file, "/.dir-control", MAX_DIR_NAME);
1124
1125 /* it isn't in the assign file so we have to get it from /etc/passwd */
1126 } else {
1127
1128 /* save some time if this is the vpopmail user */
1129 if ( uid == VPOPMAILUID ) {
1130 strncpy(dir_control_file, VPOPMAILDIR, MAX_DIR_NAME);
1131
1132 /* for other users, look them up in /etc/passwd */
1133 } else if ( (pw=getpwuid(uid))!=NULL ) {
1134 strncpy(dir_control_file, pw->pw_dir, MAX_DIR_NAME);
1135
1136 /* all else fails return a blank string */
1137 } else {
1138 return("");
1139 }
1140
1141 /* stick on the rest of the path */
1142 strncat(dir_control_file, "/" DOMAINS_DIR "/.dir-control", MAX_DIR_NAME);
1143 }
1144 return(dir_control_file);
1145 }
1146
vcdb_strip_char(char * instr)1147 void vcdb_strip_char( char *instr )
1148 {
1149 char *nextstr;
1150
1151 nextstr = instr;
1152 while (*instr != 0 ) {
1153 if ( *instr == ':' ) ++instr;
1154 if ( nextstr != instr ) *nextstr = *instr;
1155 ++nextstr;
1156 ++instr;
1157 }
1158
1159 }
1160
vauth_crypt(char * user,char * domain,char * clear_pass,struct vqpasswd * vpw)1161 int vauth_crypt(char *user,char *domain,char *clear_pass,struct vqpasswd *vpw)
1162 {
1163 if ( vpw == NULL ) return(-1);
1164
1165 return(strcmp(crypt(clear_pass,vpw->pw_passwd),vpw->pw_passwd));
1166 }
1167