1 /*
2 * $Id: vpgsql.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 #include <ctype.h>
20 #include <pwd.h>
21 #include <unistd.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <sys/types.h>
25 #include <string.h>
26 #include <time.h>
27 #include <errno.h>
28 #include <libpq-fe.h> /* required pgsql front-end headers */
29
30 #include "config.h"
31 #include "vpopmail.h"
32 #include "vauth.h"
33 #include "vlimits.h"
34 #include "vpgsql.h"
35
36 // Variables to control debug output
37 #ifdef VPOPMAIL_DEBUG
38 int show_trace=0;
39 int show_query=0;
40 int dump_data=0;
41 #endif
42
43 /* pgsql has no built-in replication, yet.
44 #ifdef PGSQL_REPLICATION
45 static PGconn *pgc_read;
46 #else
47 #define pgc_read pgc_update
48 #endif
49
50 #ifdef PGSQL_REPLICATION
51 static int read_open = 0;
52 #else
53 #define read_open update_open
54 #endif
55 #ifdef PGSQL_REPLICATION
56 static PGresult *res_read = NULL;
57 #else
58 #define res_read res_update
59 #endif
60 */
61
62 /*
63 read-only and read-write connections
64 to be implemented later...
65 static PGconn *pgc_update;
66 static PGconn *pgc_read;
67 static PGconn *pgc_read_getall;
68 */
69
70 static PGconn *pgc; /* pointer to pgsql connection */
71 static int is_open = 0;
72
73 #define SQL_BUF_SIZE 2048
74 static char SqlBufRead[SQL_BUF_SIZE];
75 static char SqlBufUpdate[SQL_BUF_SIZE];
76
77 #define SMALL_BUFF 200
78 char IUser[SMALL_BUFF];
79 char IPass[SMALL_BUFF];
80 char IGecos[SMALL_BUFF];
81 char IDir[SMALL_BUFF];
82 char IShell[SMALL_BUFF];
83 char IClearPass[SMALL_BUFF];
84
85 void vcreate_dir_control(char *domain);
86 void vcreate_vlog_table();
87
88 #ifdef POP_AUTH_OPEN_RELAY
89 void vcreate_relay_table();
90 #endif
91
92 #ifdef VALIAS
93 void vcreate_valias_table();
94 #endif
95
96 #ifdef ENABLE_AUTH_LOGGING
97 void vcreate_lastauth_table();
98 #endif
99
100 /* pgsql BEGIN TRANSACTION ********/
pg_begin(void)101 int pg_begin(void)
102 {
103 PGresult *pgres;
104 pgres=PQexec(pgc, "BEGIN");
105 if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
106 fprintf(stderr, "pg_begin: %s\n", PQerrorMessage(pgc));
107 if (pgres) PQclear (pgres);
108 return -1;
109 }
110 PQclear(pgres);
111 return 0;
112 }
113
114 /* pgsql END TRANSACTION ********/
pg_end(void)115 int pg_end(void)
116 {
117 PGresult *pgres;
118 pgres=PQexec(pgc, "END");
119 if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
120 fprintf(stderr, "pg_end: %s\n", PQerrorMessage(pgc));
121 if (pgres) PQclear (pgres);
122 return -1;
123 }
124 PQclear(pgres);
125 return 0;
126 }
127
128 /*** Open a connection to pgsql ***/
vauth_open(int will_update)129 int vauth_open( int will_update )
130 {
131 #ifdef VPOPMAIL_DEBUG
132 show_trace = ( getenv("VPSHOW_TRACE") != NULL);
133 show_query = ( getenv("VPSHOW_QUERY") != NULL);
134 dump_data = ( getenv("VPDUMP_DATA") != NULL);
135 #endif
136
137 #ifdef VPOPMAIL_DEBUG
138 if( show_trace ) {
139 fprintf( stderr, "vauth_open(%d)\n",will_update);
140 }
141 #endif
142
143
144 /*
145 * If the connection to this authentication database can fail
146 * you should test access here. If it works, return 0, else
147 * return VA_NO_AUTH_CONNECTION. You can also set the string
148 * sqlerr to some short descriptive text about the problem,
149 * and allocate a much longer string, pointed to by last_query
150 * that can be displayed in an error message returned because
151 * of this problem.
152 *
153 */
154
155 if ( is_open != 0 ) return(0);
156 is_open = 1;
157 verrori = 0;
158
159 /* Try to connect to the pgserver with the specified database. */
160 pgc = PQconnectdb(PG_CONNECT);
161 if( PQstatus(pgc) == CONNECTION_BAD) {
162 fprintf(stderr, "vauth_open: can't connect: %s\n", PQerrorMessage(pgc));
163 return VA_NO_AUTH_CONNECTION;
164 }
165 return(0);
166 }
167
vauth_create_table(char * table,char * layout,int showerror)168 int vauth_create_table (char *table, char *layout, int showerror)
169 {
170 int err;
171 PGresult *pgres;
172 char SqlBufCreate[SQL_BUF_SIZE];
173
174 if ((err = vauth_open(1))) return (err);
175
176 snprintf(SqlBufCreate, SQL_BUF_SIZE,
177 "CREATE TABLE %s ( %s )", table, layout);
178 pgres=PQexec(pgc, SqlBufCreate);
179 if (!pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK) {
180 err = -1;
181 if (showerror)
182 fprintf (stderr, "vpgsql: error creating table '%s': %s\n", table,
183 PQerrorMessage(pgc));
184 } else err = 0;
185
186 if (pgres) PQclear (pgres);
187 return err;
188 }
189
vauth_adddomain(char * domain)190 int vauth_adddomain( char *domain )
191 {
192 #ifndef MANY_DOMAINS
193 vset_default_domain( domain );
194 return (vauth_create_table (vauth_munch_domain( domain ), TABLE_LAYOUT, 1));
195 #else
196 /* if creation fails, don't show an error */
197 vauth_create_table (PGSQL_DEFAULT_TABLE, TABLE_LAYOUT, 0);
198 return (0);
199 #endif
200 }
201
vauth_adduser(char * user,char * domain,char * pass,char * gecos,char * dir,int apop)202 int vauth_adduser(char *user, char *domain, char *pass, char *gecos,
203 char *dir, int apop )
204 {
205 char *domstr;
206 char dom_dir[156];
207 uid_t uid;
208 gid_t gid;
209 char dirbuf[200];
210 char quota[30];
211 char Crypted[100];
212 int err;
213 PGresult *pgres;
214
215 if ( (err=vauth_open(1)) != 0 ) return(err);
216 vset_default_domain( domain );
217
218 strncpy( quota, "NOQUOTA", 30 );
219
220 #ifndef MANY_DOMAINS
221 domstr = vauth_munch_domain( domain );
222 #else
223 domstr = PGSQL_DEFAULT_TABLE;
224 #endif
225 if ( domain == NULL || domain[0] == 0 ) {
226 domstr = PGSQL_LARGE_USERS_TABLE;
227 }
228
229 *dirbuf = '\0';
230
231 if ( strlen(domain) <= 0 ) {
232 if ( strlen(dir) > 0 ) {
233 snprintf(dirbuf, sizeof(dirbuf),
234 "%s/users/%s/%s", VPOPMAILDIR, dir, user);
235 } else {
236 snprintf(dirbuf, sizeof(dirbuf), "%s/users/%s", VPOPMAILDIR, user);
237 }
238 } else {
239 vget_assign(domain, dom_dir, 156, &uid, &gid );
240 if ( strlen(dir) > 0 ) {
241 snprintf(dirbuf,sizeof(dirbuf), "%s/%s/%s", dom_dir, dir, user);
242 } else {
243 snprintf(dirbuf,sizeof(dirbuf), "%s/%s", dom_dir, user);
244 }
245 }
246
247 if ( pass[0] != 0 ) {
248 mkpasswd3(pass,Crypted, 100);
249 } else {
250 Crypted[0] = 0;
251 }
252
253 qnprintf( SqlBufUpdate, sizeof(SqlBufUpdate), INSERT,
254 domstr, user,
255 #ifdef MANY_DOMAINS
256 domain,
257 #endif
258 Crypted, apop, gecos, dirbuf, quota
259 #ifdef CLEAR_PASS
260 ,pass
261 #endif
262 );
263 if(! ( pgres=PQexec(pgc,SqlBufUpdate) )||
264 PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
265 fprintf(stderr, "vauth_adduser: %s\npgsql: %s\n",
266 SqlBufUpdate, PQerrorMessage(pgc));
267 }
268 if( pgres ) PQclear(pgres);
269 return(0);
270
271 }
vauth_getpw(char * user,char * domain)272 struct vqpasswd *vauth_getpw(char *user, char *domain)
273 {
274 char in_domain[156];
275 char *domstr;
276 static struct vqpasswd vpw;
277 int err;
278 PGresult *pgres;
279
280 verrori = 0;
281 if ( (err=vauth_open(0)) != 0 ) {
282 verrori = err;
283 return(NULL);
284 }
285 lowerit(user);
286 lowerit(domain);
287
288 snprintf (in_domain, sizeof(in_domain), "%s", domain);
289
290 vset_default_domain( in_domain );
291
292 #ifndef MANY_DOMAINS
293 domstr = vauth_munch_domain( in_domain );
294 #else
295 domstr = PGSQL_DEFAULT_TABLE;
296 #endif
297
298 if ( domstr == NULL || domstr[0] == 0 ) {
299 domstr = PGSQL_LARGE_USERS_TABLE;
300 }
301
302 qnprintf(SqlBufRead, SQL_BUF_SIZE, USER_SELECT, domstr, user
303 #ifdef MANY_DOMAINS
304 ,in_domain
305 #endif
306 );
307 pgres=PQexec(pgc, SqlBufRead);
308 if ( ! pgres || PQresultStatus(pgres)!=PGRES_TUPLES_OK) {
309 if( pgres ) PQclear(pgres);
310 #ifdef DEBUG
311 fprintf(stderr,
312 "vauth_getpw: failed select: %s : %s\n",
313 SqlBufRead, PQerrorMessage(pgc));
314 #endif
315 return NULL;
316 }
317 if ( PQntuples(pgres) <= 0 ) { /* rows count */
318 PQclear(pgres);
319 return NULL;
320 }
321
322 memset(IUser, 0, sizeof(IUser));
323 memset(IPass, 0, sizeof(IPass));
324 memset(IGecos, 0, sizeof(IGecos));
325 memset(IDir, 0, sizeof(IDir));
326 memset(IShell, 0, sizeof(IShell));
327 memset(IClearPass, 0, sizeof(IClearPass));
328
329 vpw.pw_name = IUser;
330 vpw.pw_passwd = IPass;
331 vpw.pw_gecos = IGecos;
332 vpw.pw_dir = IDir;
333 vpw.pw_shell = IShell;
334 vpw.pw_clear_passwd = IClearPass;
335
336 strncpy(vpw.pw_name,PQgetvalue( pgres, 0, 0 ),SMALL_BUFF);
337 strncpy(vpw.pw_passwd,PQgetvalue( pgres, 0, 1 ),SMALL_BUFF);
338 vpw.pw_uid = atoi(PQgetvalue( pgres, 0, 2 ));
339 vpw.pw_gid = atoi(PQgetvalue( pgres, 0, 3 ));
340 strncpy(vpw.pw_gecos,PQgetvalue( pgres, 0, 4 ),SMALL_BUFF);
341 strncpy(vpw.pw_dir,PQgetvalue( pgres, 0, 5 ),SMALL_BUFF);
342 strncpy(vpw.pw_shell, PQgetvalue( pgres, 0, 6 ),SMALL_BUFF);
343 #ifdef CLEAR_PASS
344 if ( PQgetvalue( pgres, 0, 7 ) != 0 )
345 strncpy(vpw.pw_clear_passwd, PQgetvalue( pgres, 0, 7 ),SMALL_BUFF);
346 #endif
347
348 vlimits_setflags (&vpw, in_domain);
349
350 return(&vpw);
351 }
352
vauth_deldomain(char * domain)353 int vauth_deldomain( char *domain )
354 {
355 PGresult *pgres;
356 char *tmpstr;
357 int err;
358
359 if ( (err=vauth_open(1)) != 0 ) return(err);
360 vset_default_domain( domain );
361
362 #ifndef MANY_DOMAINS
363 tmpstr = vauth_munch_domain( domain );
364 snprintf( SqlBufUpdate, SQL_BUF_SIZE, "drop table %s", tmpstr);
365 #else
366 tmpstr = PGSQL_DEFAULT_TABLE;
367 qnprintf(SqlBufUpdate,SQL_BUF_SIZE,
368 "delete from %s where pw_domain = '%s'",
369 tmpstr, domain );
370 #endif
371 pgres=PQexec(pgc, SqlBufUpdate);
372 if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK){
373 fprintf(stderr,"vauth_deldomain: pgsql query: %s",
374 PQerrorMessage(pgc));
375 if(pgres) PQclear(pgres);
376 return(-1);
377 }
378 if(pgres) PQclear(pgres);
379
380 #ifdef VALIAS
381 valias_delete_domain( domain);
382 #endif
383
384 #ifdef ENABLE_AUTH_LOGGING
385 qnprintf( SqlBufUpdate, SQL_BUF_SIZE,
386 "delete from lastauth where domain = '%s'", domain );
387 pgres=PQexec(pgc, SqlBufUpdate);
388 if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK) {
389 return(-1);
390 }
391 if(pgres) PQclear(pgres);
392 #endif
393
394 #ifdef ENABLE_SQL_LOGGING
395 #ifdef ENABLE_SQL_REMOVE_DELETED
396 qnprintf( SqlBufUpdate, SQL_BUF_SIZE,
397 "delete from vlog where domain = '%s'", domain );
398 pgres=PQexec(pgc, SqlBufUpdate);
399 if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK) {
400 return(-1);
401 }
402 #endif
403 #endif
404 return(0);
405 }
406
vauth_deluser(char * user,char * domain)407 int vauth_deluser( char *user, char *domain )
408 {
409 PGresult *pgres;
410 char *tmpstr;
411 int err = 0;
412
413 if ( (err=vauth_open(1)) != 0 ) return(err);
414 vset_default_domain( domain );
415
416 #ifndef MANY_DOMAINS
417 if ( domain == NULL || domain[0] == 0 ) {
418 tmpstr = PGSQL_LARGE_USERS_TABLE;
419 } else {
420 tmpstr = vauth_munch_domain( domain );
421 }
422 #else
423 tmpstr = PGSQL_DEFAULT_TABLE;
424 #endif
425
426 qnprintf( SqlBufUpdate, SQL_BUF_SIZE, DELETE_USER, tmpstr, user
427 #ifdef MANY_DOMAINS
428 , domain
429 #endif
430 );
431
432 pgres=PQexec(pgc, SqlBufUpdate);
433 if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
434 err = -1;
435 }
436 if( pgres ) PQclear(pgres);
437
438 #ifdef ENABLE_AUTH_LOGGING
439 qnprintf( SqlBufUpdate, SQL_BUF_SIZE,
440 "delete from lastauth where user = '%s' and domain = '%s'",
441 user, domain );
442 pgres=PQexec(pgc, SqlBufUpdate);
443 if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
444 err = -1;
445 }
446 if( pgres ) PQclear(pgres);
447 #endif
448
449 #ifdef ENABLE_SQL_LOGGING
450 #ifdef ENABLE_SQL_REMOVE_DELETED
451 qnprintf( SqlBufUpdate, SQL_BUF_SIZE,
452 "delete from vlog where domain = '%s' and user='%s'",
453 domain, user );
454 pgres=PQexec(pgc, SqlBufUpdate);
455 if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK) {
456 err = -1;
457 }
458 #endif
459 #endif
460
461 return(err);
462 }
463
vauth_setquota(char * username,char * domain,char * quota)464 int vauth_setquota( char *username, char *domain, char *quota)
465 {
466 PGresult *pgres;
467 char *tmpstr;
468 int err;
469
470 if ( strlen(username) > MAX_PW_NAME ) return(VA_USER_NAME_TOO_LONG);
471 #ifdef USERS_BIG_DIR
472 if ( strlen(username) == 1 ) return(VA_ILLEGAL_USERNAME);
473 #endif
474 if ( strlen(domain) > MAX_PW_DOMAIN ) return(VA_DOMAIN_NAME_TOO_LONG);
475 if ( strlen(quota) > MAX_PW_QUOTA ) return(VA_QUOTA_TOO_LONG);
476
477 if ( (err=vauth_open(1)) != 0 ) return(err);
478 vset_default_domain( domain );
479
480 #ifndef MANY_DOMAINS
481 tmpstr = vauth_munch_domain( domain );
482 #else
483 tmpstr = PGSQL_DEFAULT_TABLE;
484 #endif
485
486 qnprintf( SqlBufUpdate, SQL_BUF_SIZE, SETQUOTA, tmpstr, quota, username
487 #ifdef MANY_DOMAINS
488 , domain
489 #endif
490 );
491
492 pgres = PQexec(pgc, SqlBufUpdate);
493 if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
494 fprintf(stderr,
495 "vauth_setquota: query failed: %s\n", PQerrorMessage(pgc));
496 if( pgres ) PQclear(pgres);
497 return(-1);
498 }
499 if( pgres ) PQclear(pgres);
500 return(0);
501 }
502
vauth_getall(char * domain,int first,int sortit)503 struct vqpasswd *vauth_getall(char *domain, int first, int sortit)
504 {
505 static PGresult *pgres=NULL;
506 /* ntuples - number of tuples ctuple - current tuple */
507 static unsigned ntuples=0, ctuple=0;
508
509 char *domstr = NULL;
510 static struct vqpasswd vpw;
511 int err;
512
513 vset_default_domain( domain );
514
515 #ifdef MANY_DOMAINS
516 domstr = PGSQL_DEFAULT_TABLE;
517 #else
518 domstr = vauth_munch_domain( domain );
519 #endif
520
521 if ( first == 1 ) {
522 if ( (err=vauth_open(0)) != 0 ) return(NULL);
523 qnprintf(SqlBufRead, SQL_BUF_SIZE, GETALL, domstr
524 #ifdef MANY_DOMAINS
525 ,domain
526 #endif
527 );
528 if ( sortit == 1 ) {
529 strncat( SqlBufRead, " order by pw_name", SQL_BUF_SIZE);
530 }
531 if ( pgres ) { /* reset state if we had previous result */
532 PQclear(pgres); // clear previous result
533 pgres=NULL;
534 ntuples=ctuple=0;
535 }
536 pgres = PQexec(pgc, SqlBufRead);
537 if( !pgres || PQresultStatus(pgres) != PGRES_TUPLES_OK ) {
538 fprintf(stderr, "vauth_getall:query failed[5]: %s\n", PQerrorMessage(pgc));
539 if( pgres ) {
540 PQclear(pgres);
541 pgres=NULL;
542 }
543 return (NULL);
544 }
545 ntuples = PQntuples( pgres );
546 }
547
548 if ( ctuple == ntuples ) {
549 PQclear(pgres);
550 pgres=NULL;
551 ctuple=ntuples=0;
552 return NULL;
553 }
554 memset(IUser, 0, sizeof(IUser));
555 memset(IPass, 0, sizeof(IPass));
556 memset(IGecos, 0, sizeof(IGecos));
557 memset(IDir, 0, sizeof(IDir));
558 memset(IShell, 0, sizeof(IShell));
559 memset(IClearPass, 0, sizeof(IClearPass));
560
561 vpw.pw_name = IUser;
562 vpw.pw_passwd = IPass;
563 vpw.pw_gecos = IGecos;
564 vpw.pw_dir = IDir;
565 vpw.pw_shell = IShell;
566 vpw.pw_clear_passwd = IClearPass;
567
568 strncpy(vpw.pw_name, PQgetvalue( pgres, ctuple, 0 ),SMALL_BUFF );
569 strncpy(vpw.pw_passwd, PQgetvalue( pgres, ctuple, 1 ),SMALL_BUFF );
570
571 vpw.pw_uid = atoi(PQgetvalue( pgres, ctuple, 2 ));
572 vpw.pw_gid = atoi(PQgetvalue( pgres, ctuple, 3 ));
573
574 strncpy(vpw.pw_gecos, PQgetvalue( pgres, ctuple, 4 ),SMALL_BUFF);
575 strncpy(vpw.pw_dir, PQgetvalue( pgres, ctuple, 5 ),SMALL_BUFF);
576 strncpy(vpw.pw_shell, PQgetvalue( pgres, ctuple, 6 ),SMALL_BUFF);
577
578 #ifdef CLEAR_PASS
579 if (PQgetvalue( pgres, ctuple, 7)!= 0 ) {
580 strncpy(vpw.pw_clear_passwd, PQgetvalue( pgres, ctuple, 7 ),SMALL_BUFF);
581 }
582 #endif
583 ctuple++;
584 vlimits_setflags(&vpw,domain);
585 return(&vpw);
586 }
587
vauth_end_getall()588 void vauth_end_getall()
589 {
590 /* not applicable in pgsql? */
591 }
592
vauth_munch_domain(char * domain)593 char *vauth_munch_domain( char *domain )
594 {
595 int i;
596 static char tmpbuf[512];
597
598 if ( domain == NULL || domain[0] == 0 ) return(domain);
599
600 for(i=0;domain[i]!=0 && i < (sizeof(tmpbuf) - 1);++i){
601 tmpbuf[i] = tolower(domain[i]);
602 if ( domain[i] == '.' || domain[i] == '-' ) {
603 tmpbuf[i] = SQL_DOT_CHAR;
604 }
605 }
606 tmpbuf[i] = 0;
607 return(tmpbuf);
608 }
609
vauth_setpw(struct vqpasswd * inpw,char * domain)610 int vauth_setpw( struct vqpasswd *inpw, char *domain )
611 {
612 PGresult *pgres;
613 char *tmpstr;
614 uid_t myuid;
615 uid_t uid;
616 gid_t gid;
617 int err;
618
619 err = vcheck_vqpw(inpw, domain);
620 if ( err != 0 ) return(err);
621
622 vget_assign(domain,NULL,0,&uid,&gid);
623 myuid = geteuid();
624 if ( myuid != 0 && myuid != uid ) {
625 return(VA_BAD_UID);
626 }
627
628 if ( (err=vauth_open(1)) != 0 ) return(err);
629 vset_default_domain( domain );
630
631 #ifndef MANY_DOMAINS
632 tmpstr = vauth_munch_domain( domain );
633 #else
634 tmpstr = PGSQL_DEFAULT_TABLE;
635 #endif
636
637 qnprintf( SqlBufUpdate,SQL_BUF_SIZE,SETPW,
638 tmpstr,
639 inpw->pw_passwd,
640 inpw->pw_uid,
641 inpw->pw_gid,
642 inpw->pw_gecos,
643 inpw->pw_dir,
644 inpw->pw_shell,
645 #ifdef CLEAR_PASS
646 inpw->pw_clear_passwd,
647 #endif
648 inpw->pw_name
649 #ifdef MANY_DOMAINS
650 ,domain
651 #endif
652 );
653 pgres=PQexec(pgc, SqlBufUpdate);
654 if ( !pgres || PQresultStatus(pgres)!= PGRES_COMMAND_OK ) {
655 fprintf(stderr, "vauth_setpw: pgsql query[6]: %s\n",
656 PQerrorMessage(pgc));
657 if( pgres ) PQclear(pgres);
658 return(-1);
659 }
660 if( pgres ) PQclear(pgres);
661 #ifdef SQWEBMAIL_PASS
662 vsqwebmail_pass( inpw->pw_dir, inpw->pw_passwd, uid, gid);
663 #endif
664
665 #ifdef ONCHANGE_SCRIPT
666 if( allow_onchange ) {
667 /* tell other programs that data has changed */
668 snprintf ( onchange_buf, MAX_BUFF, "%s@%s", inpw->pw_name, domain );
669 call_onchange ( "mod_user" );
670 }
671 #endif
672
673 return(0);
674 }
675
676 #ifdef POP_AUTH_OPEN_RELAY
vopen_smtp_relay()677 int vopen_smtp_relay()
678 {
679 PGresult *pgres;
680 char *ipaddr;
681 time_t mytime;
682 int err;
683
684 mytime = time(NULL);
685 ipaddr = get_remote_ip();
686 if ( ipaddr == NULL ) {
687 return 0;
688 }
689
690 if ( (err=vauth_open(1)) != 0 ) return 0;
691
692 qnprintf(SqlBufUpdate, SQL_BUF_SIZE,
693 "UPDATE relay SET ip_addr='%s', timestamp=%d WHERE ip_addr='%s'",
694 ipaddr, (int)mytime, ipaddr);
695
696 pgres=PQexec(pgc, SqlBufUpdate);
697 if (PQresultStatus(pgres) == PGRES_COMMAND_OK && atoi(PQcmdTuples(pgres)) == 0) {
698 if( pgres ) PQclear(pgres);
699
700 qnprintf( SqlBufUpdate, SQL_BUF_SIZE,
701 "INSERT INTO relay (ip_addr, timestamp) VALUES ('%s', %lu)",
702 ipaddr, time(NULL));
703
704 pgres=PQexec(pgc, SqlBufUpdate);
705 }
706
707 /* UPDATE returned 0 rows and/or INSERT failed. Try creating the table */
708 if(!pgres || PQresultStatus(pgres) != PGRES_COMMAND_OK) {
709 if( pgres ) PQclear(pgres);
710
711 vcreate_relay_table();
712
713 /* and try INSERTing now... */
714 qnprintf( SqlBufUpdate, SQL_BUF_SIZE,
715 "INSERT INTO relay (ip_addr, timestamp) VALUES ('%s', %lu)",
716 ipaddr, time(NULL));
717
718 pgres=PQexec(pgc, SqlBufUpdate);
719 }
720
721 if(pgres && PQresultStatus(pgres) == PGRES_COMMAND_OK ) {
722 /* need to return non-zero value if value inserted */
723 if( pgres ) PQclear(pgres);
724 return 1;
725 }
726
727 if( pgres ) PQclear(pgres);
728 return 0;
729 }
730
vupdate_rules(int fdm)731 void vupdate_rules(int fdm)
732 {
733 PGresult *pgres;
734 const char re[]=":allow,RELAYCLIENT=\"\",RBLSMTPD=\"\"\n";
735 register unsigned i=0, n, len=strlen(re)+1;
736 char *buf=NULL;
737
738 if (vauth_open(0) != 0) return;
739
740 snprintf(SqlBufRead, SQL_BUF_SIZE, "SELECT ip_addr FROM relay");
741 if ( !(pgres=PQexec(pgc, SqlBufRead)) || PQresultStatus(pgres)!=PGRES_TUPLES_OK) {
742 vcreate_relay_table();
743 if(pgres) PQclear(pgres);
744 if ( !(pgres=PQexec(pgc, SqlBufRead)) || PQresultStatus(pgres)!=PGRES_TUPLES_OK ) {
745 fprintf(stderr, "vupdate_rules: query : %s\n", PQerrorMessage(pgc));
746 if (pgres) PQclear (pgres);
747 return;
748 }
749 }
750
751 n=PQntuples(pgres);
752 for( ; i < n ; i++ ) {
753 buf=realloc(buf, len+PQgetlength(pgres, i, 0) );
754 if( buf==NULL || errno==ENOMEM ) {
755 PQclear(pgres);
756 free(buf);
757 fprintf(stderr, "vupdate_rules: no mem\n");
758 return;
759 }
760
761 sprintf( buf, "%s%s", PQgetvalue(pgres, i, 0), re );
762 if( write( fdm, buf, strlen(buf) ) != strlen(buf) ) {
763 fprintf(stderr, "vupdate_rules: short write: %s",
764 strerror(errno));
765 break;
766 }
767 }
768 if(pgres) PQclear(pgres);
769 free(buf);
770 return;
771 }
772
vclear_open_smtp(time_t clear_minutes,time_t mytime)773 void vclear_open_smtp(time_t clear_minutes, time_t mytime)
774 {
775 PGresult *pgres;
776 time_t delete_time;
777 int err;
778
779 if ( (err=vauth_open(1)) != 0 ) return;
780 delete_time = mytime - clear_minutes;
781
782 snprintf( SqlBufUpdate, SQL_BUF_SIZE,
783 "DELETE FROM relay WHERE timestamp <= %d",
784 (int)delete_time);
785 pgres=PQexec(pgc, SqlBufUpdate);
786 if( !pgres || PQresultStatus(pgres) != PGRES_COMMAND_OK) {
787 vcreate_relay_table();
788 }
789 return;
790 }
791
vcreate_relay_table()792 void vcreate_relay_table()
793 {
794 vauth_create_table ("relay", RELAY_TABLE_LAYOUT, 1);
795 return;
796 }
797 #endif
798
vmkpasswd(char * domain)799 int vmkpasswd( char *domain )
800 {
801 return(0);
802 }
803
vclose()804 void vclose()
805 {
806 /* disconnection from the database */
807 if ( is_open == 1 ) {
808 is_open = 0;
809 PQfinish(pgc);
810 }
811 }
812
813 #ifdef IP_ALIAS_DOMAINS
vcreate_ip_map_table()814 void vcreate_ip_map_table()
815 {
816 vauth_create_table ("ip_alias_map", IP_ALIAS_TABLE_LAYOUT, 1);
817 return;
818 }
819
vget_ip_map(char * ip,char * domain,int domain_size)820 int vget_ip_map( char *ip, char *domain, int domain_size)
821 {
822 PGresult *pgres;
823 char *ptr;
824 unsigned ntuples;
825 int ret = -1;
826
827 if ( ip == NULL || strlen(ip) <= 0 ) return(-1);
828 if ( domain == NULL ) return(-2);
829 if ( vauth_open(0) != 0 ) return(-3);
830
831 qnprintf(SqlBufRead, SQL_BUF_SIZE,
832 "select domain from ip_alias_map where ip_addr = '%s'",
833 ip);
834 pgres=PQexec(pgc, SqlBufRead);
835 if( !pgres || PQresultStatus(pgres) != PGRES_TUPLES_OK ) {
836 fprintf( stderr, "vget_ip_map: pgsql query: %s\n", PQerrorMessage(pgc));
837 if( pgres ) PQclear(pgres);
838 return -1;
839 }
840
841 ntuples = PQntuples(pgres);
842 if(!ntuples)
843 *domain='\0';
844 else {
845 ret = 0;
846 ptr = PQgetvalue(pgres, ntuples-1, 0);
847 strncpy(domain, ptr, strlen(ptr) );
848 }
849
850 PQclear(pgres);
851 return (ret);
852 }
853
vadd_ip_map(char * ip,char * domain)854 int vadd_ip_map( char *ip, char *domain)
855 {
856 PGresult *pgres;
857 int err = 0;
858
859 if ( ip == NULL || strlen(ip) <= 0 ) return(-1);
860 if ( domain == NULL || strlen(domain) <= 0 ) return(-1);
861
862 if ( (err=vauth_open(1)) != 0 ) return(err);
863
864 if( ( err=pg_begin() )!= 0 ) { /* begin transaction */
865 return(err);
866 }
867 qnprintf(SqlBufUpdate,SQL_BUF_SIZE,
868 "delete from ip_alias_map where ip_addr='%s' and domain='%s'",
869 ip, domain);
870
871 /* step 1: delete previous entry */
872 pgres=PQexec(pgc, SqlBufUpdate);
873 if( pgres ) PQclear(pgres); /* don't check pgres status
874 table may not exist */
875
876 /* step 2: insert new data */
877 qnprintf(SqlBufUpdate,SQL_BUF_SIZE,
878 "insert into ip_alias_map (ip_addr,domain) values ('%s','%s')",
879 ip, domain);
880 pgres=PQexec(pgc, SqlBufUpdate);
881 if ( !pgres || PQresultStatus(pgres) != PGRES_COMMAND_OK ) {
882 if( pgres ) PQclear(pgres);
883 vcreate_ip_map_table();
884 qnprintf(SqlBufUpdate,SQL_BUF_SIZE,
885 "insert into ip_alias_map (ip_addr,domain) values ('%s','%s')",
886 ip, domain);
887 pgres=PQexec( pgc, SqlBufUpdate);
888 if ( !pgres || PQresultStatus(pgres) != PGRES_COMMAND_OK ) {
889 fprintf( stderr, "vadd_ip_map: insert: %s\n", PQerrorMessage(pgc));
890 if( pgres ) PQclear(pgres);
891 return -1;
892 }
893 }
894 if( pgres ) PQclear(pgres);
895 return ( pg_end() ); /* end transaction */
896 }
897
vdel_ip_map(char * ip,char * domain)898 int vdel_ip_map( char *ip, char *domain)
899 {
900 PGresult *pgres;
901 int err=0;
902
903 if ( ip == NULL || strlen(ip) <= 0 ) return(-1);
904 if ( domain == NULL || strlen(domain) <= 0 ) return(-1);
905 if ( (err=vauth_open(1)) != 0 ) return(err);
906
907 qnprintf( SqlBufUpdate,SQL_BUF_SIZE,
908 "delete from ip_alias_map where ip_addr='%s' and domain='%s'",
909 ip, domain);
910
911 pgres=PQexec(pgc, SqlBufUpdate);
912 if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
913 fprintf(stderr, "vdel_ip_map: delete failed: %s\n",
914 PQerrorMessage(pgc));
915 if(pgres) PQclear(pgres);
916 /* #warning why are we returning 0 when we couldn't delete?*/
917 return(0);
918 }
919 if(pgres) PQclear(pgres);
920 return(0);
921 }
vshow_ip_map(int first,char * ip,char * domain)922 int vshow_ip_map( int first, char *ip, char *domain )
923 {
924 static PGresult *pgres=NULL;
925 static unsigned ntuples=0, ctuple=0;
926 int err= 0;
927
928 if ( ip == NULL ) return(-1);
929 if ( domain == NULL ) return(-1);
930 if ( ( err=vauth_open(0) ) != 0 ) return(err);
931
932 if ( first == 1 ) {
933 snprintf(SqlBufRead,SQL_BUF_SIZE,
934 "select ip_addr, domain from ip_alias_map");
935 if (pgres) {
936 PQclear(pgres);
937 ntuples=ctuple=0;
938 }
939 if ( ! (pgres=PQexec(pgc, SqlBufRead))
940 || PQresultStatus(pgres) != PGRES_TUPLES_OK ) {
941 if(pgres) PQclear(pgres);
942 snprintf(SqlBufRead,SQL_BUF_SIZE,
943 "select ip_addr, domain from ip_alias_map");
944 vcreate_ip_map_table();
945 if ( ! (pgres=PQexec(pgc, SqlBufRead))
946 || PQresultStatus(pgres) != PGRES_TUPLES_OK ) {
947 return(0);
948 }
949 }
950 ntuples=PQntuples(pgres);
951 }
952
953 if ( ctuple == ntuples ) {
954 PQclear(pgres);
955 ntuples=ctuple=0;
956 return (0);
957 }
958
959 strncpy( ip, PQgetvalue( pgres, ctuple, 0), 18);
960 strncpy( domain, PQgetvalue( pgres, ctuple, 1), 156);
961 strncpy( ip, PQgetvalue( pgres, ctuple, 0), 18);
962 strncpy( domain, PQgetvalue( pgres, ctuple, 1), 156);
963
964 ctuple++;
965 return 1;
966 }
967 #endif
968
vread_dir_control(vdir_type * vdir,char * domain,uid_t uid,gid_t gid)969 int vread_dir_control(vdir_type *vdir, char *domain, uid_t uid, gid_t gid)
970 {
971 PGresult *pgres;
972 int found = 0;
973
974 if ( vauth_open(0) != 0 ) return(-1);
975
976 qnprintf(SqlBufUpdate, SQL_BUF_SIZE,
977 "select %s from dir_control where domain = '%s'",
978 DIR_CONTROL_SELECT, domain );
979
980 if (!(pgres=PQexec(pgc, SqlBufUpdate)) ||
981 PQresultStatus(pgres)!=PGRES_TUPLES_OK ) {
982 if( pgres ) PQclear(pgres);
983 vcreate_dir_control(domain);
984 qnprintf(SqlBufUpdate, SQL_BUF_SIZE,
985 "select %s from dir_control where domain = '%s'",
986 DIR_CONTROL_SELECT, domain );
987 if (! (pgres=PQexec(pgc, SqlBufUpdate)) ||
988 PQresultStatus(pgres)!=PGRES_TUPLES_OK ) {
989 fprintf(stderr, "vread_dir_control: q: %s\npgsql: %s",
990 SqlBufUpdate, PQerrorMessage(pgc));
991 if (pgres) PQclear (pgres);
992 return (-1);
993 }
994 }
995 if ( PQntuples(pgres) > 0 ) {
996 found = 1;
997 vdir->cur_users = atol( PQgetvalue( pgres, 0, 0 ) );
998 vdir->level_cur = atoi( PQgetvalue( pgres, 0, 1 ) );
999 vdir->level_max = atoi( PQgetvalue( pgres, 0, 2 ) );
1000
1001 vdir->level_start[0] = atoi( PQgetvalue( pgres, 0, 3 ) );
1002 vdir->level_start[1] = atoi( PQgetvalue( pgres, 0, 4 ) );
1003 vdir->level_start[2] = atoi( PQgetvalue( pgres, 0, 5 ) );
1004
1005 vdir->level_end[0] = atoi( PQgetvalue( pgres, 0, 6 ) );
1006 vdir->level_end[1] = atoi( PQgetvalue( pgres, 0, 7 ) );
1007 vdir->level_end[2] = atoi( PQgetvalue( pgres, 0, 8 ) );
1008
1009 vdir->level_mod[0] = atoi( PQgetvalue( pgres, 0, 9 ) );
1010 vdir->level_mod[1] = atoi( PQgetvalue( pgres, 0, 10 ) );
1011 vdir->level_mod[2] = atoi( PQgetvalue( pgres, 0, 11 ) );
1012
1013 vdir->level_index[0] = atoi( PQgetvalue( pgres, 0, 12 ) );
1014 vdir->level_index[1] = atoi( PQgetvalue( pgres, 0, 13 ) );
1015 vdir->level_index[2] = atoi( PQgetvalue( pgres, 0, 14 ) );
1016
1017 strncpy(vdir->the_dir, PQgetvalue( pgres, 0, 15 ), MAX_DIR_NAME);
1018 }
1019 PQclear(pgres);
1020 if ( found == 0 ) {
1021 int i;
1022 vdir->cur_users = 0;
1023 for(i=0;i<MAX_DIR_LEVELS;++i) {
1024 vdir->level_start[i] = 0;
1025 vdir->level_end[i] = MAX_DIR_LIST-1;
1026 vdir->level_index[i] = 0;
1027 }
1028 vdir->level_mod[0] = 0;
1029 vdir->level_mod[1] = 2;
1030 vdir->level_mod[2] = 4;
1031 vdir->level_cur = 0;
1032 vdir->level_max = MAX_DIR_LEVELS;
1033 vdir->the_dir[0] = 0;
1034 }
1035 return(0);
1036 }
1037
vwrite_dir_control(vdir_type * vdir,char * domain,uid_t uid,gid_t gid)1038 int vwrite_dir_control(vdir_type *vdir, char *domain, uid_t uid, gid_t gid)
1039 {
1040 PGresult *pgres;
1041
1042 if ( vauth_open(1) != 0 ) return(-1);
1043
1044 qnprintf(SqlBufUpdate, SQL_BUF_SIZE,
1045 "delete from dir_control where domain='%s'", domain );
1046 if( pg_begin() ) { /* begin transaction */
1047 return -1;
1048 }
1049 pgres=PQexec(pgc, SqlBufUpdate);
1050 if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
1051 fprintf(stderr, "vwrite_dir_control: delete failed: %s",
1052 PQerrorMessage(pgc));
1053 if (pgres) PQclear (pgres);
1054 return -1;
1055 }
1056 qnprintf(SqlBufUpdate, SQL_BUF_SIZE,
1057 "insert into dir_control ( \
1058 domain, cur_users, \
1059 level_cur, level_max, \
1060 level_start0, level_start1, level_start2, \
1061 level_end0, level_end1, level_end2, \
1062 level_mod0, level_mod1, level_mod2, \
1063 level_index0, level_index1, level_index2, the_dir ) values ( \
1064 '%s', %lu, %d, %d, \
1065 %d, %d, %d, \
1066 %d, %d, %d, \
1067 %d, %d, %d, \
1068 %d, %d, %d, \
1069 '%s')\n",
1070 domain, vdir->cur_users, vdir->level_cur, vdir->level_max,
1071 vdir->level_start[0], vdir->level_start[1], vdir->level_start[2],
1072 vdir->level_end[0], vdir->level_end[1], vdir->level_end[2],
1073 vdir->level_mod[0], vdir->level_mod[1], vdir->level_mod[2],
1074 vdir->level_index[0], vdir->level_index[1], vdir->level_index[2],
1075 vdir->the_dir);
1076
1077 pgres=PQexec(pgc, SqlBufUpdate);
1078 if ( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
1079 PQclear(pgres);
1080 vcreate_dir_control(domain);
1081 if ( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
1082 fprintf(stderr, "vwrite_dir_control: %s\n", PQerrorMessage(pgc));
1083 if (pgres) PQclear (pgres);
1084 return(-1);
1085 }
1086 }
1087 PQclear(pgres);
1088 return pg_end(); /* end transcation */
1089
1090 }
1091
vcreate_dir_control(char * domain)1092 void vcreate_dir_control(char *domain)
1093 {
1094 PGresult *pgres;
1095 vauth_create_table ("dir_control", DIR_CONTROL_TABLE_LAYOUT, 1);
1096
1097 qnprintf(SqlBufUpdate, SQL_BUF_SIZE, "insert into dir_control ( \
1098 domain, cur_users, \
1099 level_cur, level_max, \
1100 level_start0, level_start1, level_start2, \
1101 level_end0, level_end1, level_end2, \
1102 level_mod0, level_mod1, level_mod2, \
1103 level_index0, level_index1, level_index2, the_dir ) values ( \
1104 \'%s\', 0, \
1105 0, %d, \
1106 0, 0, 0, \
1107 %d, %d, %d, \
1108 0, 2, 4, \
1109 0, 0, 0, \
1110 \'\')\n",
1111 domain, MAX_DIR_LEVELS, MAX_DIR_LIST-1, MAX_DIR_LIST-1, MAX_DIR_LIST-1);
1112
1113 pgres = PQexec( pgc, SqlBufUpdate );
1114 if ( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
1115 fprintf(stderr, "vcreate_dir_control: insert failed: %s\n",
1116 PQerrorMessage(pgc));
1117 if (pgres) PQclear (pgres);
1118 return;
1119 }
1120
1121 PQclear(pgres);
1122 }
1123
vdel_dir_control(char * domain)1124 int vdel_dir_control(char *domain)
1125 {
1126 PGresult *pgres;
1127 int err;
1128
1129 if ( (err=vauth_open(1)) != 0 ) return(err);
1130
1131 qnprintf(SqlBufUpdate, SQL_BUF_SIZE,
1132 "delete from dir_control where domain = '%s'",
1133 domain);
1134 pgres=PQexec(pgc, SqlBufUpdate);
1135
1136 if ( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
1137 PQclear(pgres);
1138 vcreate_dir_control(domain);
1139 qnprintf(SqlBufUpdate, SQL_BUF_SIZE,
1140 "delete from dir_control where domain = '%s'",
1141 domain);
1142 if ( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
1143 fprintf(stderr, "vdel_dir_control: delete failed[e]: %s\n",
1144 PQerrorMessage(pgc));
1145 err=-1;
1146 }
1147 }
1148 if( pgres ) PQclear(pgres);
1149 return err;
1150 }
1151
1152 #ifdef ENABLE_AUTH_LOGGING
vset_lastauth(char * user,char * domain,char * remoteip)1153 int vset_lastauth(char *user, char *domain, char *remoteip )
1154 {
1155 PGresult *pgres;
1156 int err=0;
1157
1158 if ( (err=vauth_open(1)) != 0 ) return(err);
1159
1160 qnprintf( SqlBufUpdate, SQL_BUF_SIZE,
1161 "UPDATE lastauth SET remote_ip='%s', timestamp=%lu " \
1162 "WHERE userid='%s' AND domain='%s'", remoteip, time(NULL), user, domain);
1163
1164 #ifdef DEBUG
1165 fprintf(stderr,"UPDATE command to run is \n\n%s\n\n", SqlBufUpdate);
1166 #endif
1167
1168 pgres=PQexec(pgc, SqlBufUpdate);
1169
1170 if (pgres && PQresultStatus(pgres) == PGRES_COMMAND_OK && atoi(PQcmdTuples(pgres)) == 0) {
1171
1172 #ifdef DEBUG
1173 fprintf(stderr,"UPDATE returned OK but had 0 rows\n");
1174 #endif
1175
1176 if( pgres ) PQclear(pgres);
1177
1178 qnprintf( SqlBufUpdate, SQL_BUF_SIZE,
1179 "INSERT INTO lastauth (userid, domain, remote_ip, timestamp) " \
1180 "VALUES ('%s', '%s', '%s', %lu)", user, domain, remoteip, time(NULL));
1181
1182 #ifdef DEBUG
1183 fprintf(stderr,"INSERT command to run is \n\n%s\n\n", SqlBufUpdate);
1184 #endif
1185 pgres=PQexec(pgc, SqlBufUpdate);
1186 }
1187
1188 /* UPDATE returned 0 rows and/or INSERT failed. Try creating the table */
1189 if(!pgres || PQresultStatus(pgres) != PGRES_COMMAND_OK) {
1190 #ifdef DEBUG
1191 fprintf(stderr,"UPDATE and/or INSERT failed. error was %s\n", PQerrorMessage(pgc));
1192 #endif
1193 if( pgres ) PQclear(pgres);
1194
1195 #ifdef DEBUG
1196 fprintf(stderr, "update returned 0 and/or insert failed in vset_lastauth()\n");
1197 #endif
1198 vcreate_lastauth_table();
1199
1200 /* and try INSERTing now... */
1201 qnprintf( SqlBufUpdate, SQL_BUF_SIZE,
1202 "INSERT INTO lastauth (userid, domain, remote_ip, timestamp) " \
1203 "VALUES ('%s', '%s', '%s', %lu)", user, domain, remoteip, time(NULL));
1204
1205 pgres=PQexec(pgc, SqlBufUpdate);
1206 }
1207
1208 if ( !pgres || PQresultStatus(pgres) != PGRES_COMMAND_OK ) {
1209 fprintf( stderr, "vset_lastauth[f]: %s\n: %s\n", SqlBufUpdate,PQerrorMessage(pgc));
1210 if( pgres ) PQclear(pgres);
1211 return (-1);
1212 }
1213
1214 if( pgres ) PQclear(pgres);
1215 return(0);
1216 }
vget_lastauth(struct vqpasswd * pw,char * domain)1217 time_t vget_lastauth(struct vqpasswd *pw, char *domain)
1218 {
1219 PGresult *pgres;
1220 int err, ntuples;
1221 time_t mytime;
1222
1223 if ( (err=vauth_open(0)) != 0 ) return(err);
1224
1225 qnprintf( SqlBufRead, SQL_BUF_SIZE, "SELECT timestamp FROM lastauth WHERE userid='%s' AND domain='%s'", pw->pw_name, domain);
1226
1227 pgres=PQexec(pgc, SqlBufRead);
1228
1229 if ( !pgres || PQresultStatus(pgres) != PGRES_TUPLES_OK ) {
1230 if( pgres ) PQclear(pgres);
1231 vcreate_lastauth_table();
1232 qnprintf( SqlBufRead, SQL_BUF_SIZE, "SELECT timestamp FROM lastauth WHERE userid='%s' AND domain='%s'", pw->pw_name, domain);
1233 pgres=PQexec(pgc, SqlBufRead);
1234 if ( !pgres || PQresultStatus(pgres) != PGRES_TUPLES_OK ) {
1235 fprintf(stderr,"vpgsql: sql error[g]: %s\n", PQerrorMessage(pgc));
1236 return(0);
1237 }
1238 }
1239
1240 ntuples = PQntuples(pgres);
1241 mytime = 0;
1242 if( ntuples ) { /* got something */
1243 mytime = atol( PQgetvalue(pgres, ntuples-1, 0));
1244 }
1245 if( pgres ) PQclear(pgres);
1246 return(mytime);
1247 }
1248
vget_lastauthip(struct vqpasswd * pw,char * domain)1249 char *vget_lastauthip(struct vqpasswd *pw, char *domain)
1250 {
1251 PGresult *pgres;
1252 static char tmpbuf[100];
1253 int ntuples=0;
1254
1255 if ( vauth_open(0) != 0 ) return(NULL);
1256
1257 qnprintf( SqlBufRead, SQL_BUF_SIZE, "select remote_ip from lastauth where userid='%s' and domain='%s'", pw->pw_name, domain);
1258
1259 pgres=PQexec(pgc, SqlBufRead);
1260 if ( !pgres || PQresultStatus(pgres) != PGRES_TUPLES_OK ) {
1261 if( pgres ) PQclear(pgres);
1262 vcreate_lastauth_table();
1263 qnprintf( SqlBufRead, SQL_BUF_SIZE, "select remote_ip from lastauth where userid='%s' and domain='%s'", pw->pw_name, domain);
1264
1265 pgres=PQexec(pgc, SqlBufRead);
1266 if ( !pgres || PQresultStatus(pgres) != PGRES_TUPLES_OK ) {
1267 fprintf( stderr,"vpgsql: sql error[h]: %s\n", PQerrorMessage(pgc));
1268 return(NULL);
1269 }
1270 }
1271 ntuples = PQntuples(pgres);
1272 if( ntuples ) { /* got something */
1273 strncpy(tmpbuf, PQgetvalue(pgres, ntuples-1, 0),100 );
1274 }
1275 if( pgres ) PQclear(pgres);
1276 return(tmpbuf);
1277 }
1278
vcreate_lastauth_table()1279 void vcreate_lastauth_table()
1280 {
1281 vauth_create_table ("lastauth", LASTAUTH_TABLE_LAYOUT, 1);
1282 return;
1283 }
1284 #endif /* ENABLE_AUTH_LOGGING */
1285
1286 #ifdef VALIAS
1287 struct linklist *valias_current = NULL;
1288
valias_select(char * alias,char * domain)1289 char *valias_select( char *alias, char *domain )
1290 {
1291 PGresult *pgvalias;
1292 int err, verrori;
1293 unsigned ntuples, ctuple;
1294 struct linklist *temp_entry = NULL;
1295
1296 /* remove old entries as necessary */
1297 while (valias_current != NULL)
1298 valias_current = linklist_del (valias_current);
1299
1300 if ( (err=vauth_open(0)) != 0 ) {
1301 verrori = err;
1302 return(NULL);
1303 }
1304
1305 qnprintf( SqlBufRead, SQL_BUF_SIZE,
1306 "select valias_line from valias where alias='%s' and domain='%s'",
1307 alias, domain );
1308 if ( ! (pgvalias=PQexec(pgc, SqlBufRead))
1309 || PQresultStatus(pgvalias) != PGRES_TUPLES_OK ) {
1310 if(pgvalias) PQclear(pgvalias);
1311 vcreate_valias_table();
1312 if ( ! (pgvalias=PQexec(pgc, SqlBufRead))
1313 || PQresultStatus(pgvalias) != PGRES_TUPLES_OK ) {
1314 fprintf(stderr,"vpgsql: sql error[j]: %s\n",
1315 PQerrorMessage(pgc));
1316 if (pgvalias) PQclear(pgvalias);
1317 return(NULL);
1318 }
1319 }
1320
1321 ntuples = PQntuples (pgvalias);
1322 for (ctuple = 0; ctuple < ntuples; ctuple++) {
1323 temp_entry = linklist_add (temp_entry, PQgetvalue (pgvalias, ctuple, 0), "");
1324 if (valias_current == NULL) valias_current = temp_entry;
1325 }
1326 PQclear (pgvalias);
1327 pgvalias = NULL;
1328
1329 if (valias_current == NULL) return NULL; /* no results */
1330 else return(valias_current->data);
1331 }
1332
valias_select_next()1333 char *valias_select_next()
1334 {
1335 if (valias_current == NULL) return NULL;
1336
1337 valias_current = linklist_del (valias_current);
1338
1339 if (valias_current == NULL) return NULL;
1340 else return valias_current->data;
1341 }
1342
valias_insert(char * alias,char * domain,char * alias_line)1343 int valias_insert( char *alias, char *domain, char *alias_line)
1344 {
1345 PGresult *pgres;
1346 int err;
1347
1348 if ( (err=vauth_open(1)) != 0 ) return(err);
1349
1350 while(*alias_line==' ') ++alias_line;
1351
1352 qnprintf( SqlBufUpdate, SQL_BUF_SIZE,
1353 "insert into valias(alias,domain,valias_line) values ('%s','%s','%s')",
1354 alias, domain, alias_line );
1355
1356 pgres=PQexec( pgc, SqlBufUpdate );
1357 if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
1358 if(pgres) PQclear(pgres);
1359 vcreate_valias_table();
1360 qnprintf( SqlBufUpdate, SQL_BUF_SIZE,
1361 "insert into valias(alias,domain,valias_line) values ('%s','%s','%s')",
1362 alias, domain, alias_line );
1363 pgres=PQexec( pgc, SqlBufUpdate );
1364 if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
1365 fprintf(stderr,"vpgsql: sql error[k]: %s\n", PQerrorMessage(pgc));
1366 if (pgres) PQclear (pgres);
1367 return(-1);
1368 }
1369 if(pgres) PQclear(pgres);
1370
1371 #ifdef ONCHANGE_SCRIPT
1372 if( allow_onchange ) {
1373 /* tell other programs that data has changed */
1374 snprintf ( onchange_buf, MAX_BUFF, "%s@%s - %s", alias, domain, alias_line );
1375 call_onchange ( "valias_add" );
1376 }
1377 #endif
1378
1379 return(0);
1380 }
1381 return(-1);
1382 }
1383
valias_delete(char * alias,char * domain)1384 int valias_delete( char *alias, char *domain)
1385 {
1386 PGresult *pgres;
1387 int err;
1388
1389 if ( (err=vauth_open(1)) != 0 ) return(err);
1390
1391 #ifdef ONCHANGE_SCRIPT
1392 if( allow_onchange ) {
1393 /* tell other programs that data has changed */
1394 snprintf ( onchange_buf, MAX_BUFF, "%s@%s", alias, domain );
1395 call_onchange ( "valias_delete" );
1396 }
1397 #endif
1398
1399 qnprintf( SqlBufUpdate, SQL_BUF_SIZE,
1400 "delete from valias where alias='%s' and domain='%s'",
1401 alias, domain );
1402 pgres=PQexec( pgc, SqlBufUpdate );
1403 if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
1404 if(pgres) PQclear(pgres);
1405 vcreate_valias_table();
1406 qnprintf( SqlBufUpdate, SQL_BUF_SIZE,
1407 "delete from valias where alias='%s' and domain='%s'",
1408 alias, domain );
1409 pgres=PQexec( pgc, SqlBufUpdate );
1410 if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
1411 fprintf(stderr,"vpgsql: sql error: %s\n", PQerrorMessage(pgc));
1412 if (pgres) PQclear (pgres);
1413 return(-1);
1414 }
1415 }
1416 if(pgres) PQclear(pgres);
1417 return(0);
1418 }
1419
valias_remove(char * alias,char * domain,char * alias_line)1420 int valias_remove( char *alias, char *domain, char *alias_line)
1421 {
1422 PGresult *pgres;
1423 int err;
1424
1425 if ( (err=vauth_open(1)) != 0 ) return(err);
1426
1427 #ifdef ONCHANGE_SCRIPT
1428 if( allow_onchange ) {
1429 /* tell other programs that data has changed */
1430 snprintf ( onchange_buf, MAX_BUFF, "%s@%s - %s", alias, domain, alias_line);
1431 call_onchange ( "valias_remove" );
1432 }
1433 #endif
1434
1435 qnprintf( SqlBufUpdate, SQL_BUF_SIZE,
1436 "delete from valias where alias='%s' and valias_line='%s' and domain='%s'",
1437 alias, alias_line, domain );
1438 pgres=PQexec( pgc, SqlBufUpdate );
1439 if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
1440 if(pgres) PQclear(pgres);
1441 vcreate_valias_table();
1442 pgres=PQexec( pgc, SqlBufUpdate );
1443 if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
1444 fprintf(stderr,"vpgsql: sql error: %s\n", PQerrorMessage(pgc));
1445 if (pgres) PQclear (pgres);
1446 return(-1);
1447 }
1448 }
1449 if(pgres) PQclear(pgres);
1450 return(0);
1451 }
1452
valias_delete_domain(char * domain)1453 int valias_delete_domain( char *domain)
1454 {
1455 PGresult *pgres;
1456 int err;
1457
1458 if ( (err=vauth_open(1)) != 0 ) return(err);
1459
1460 #ifdef ONCHANGE_SCRIPT
1461 if( allow_onchange ) {
1462 /* tell other programs that data has changed */
1463 snprintf ( onchange_buf, MAX_BUFF, "%s@%s - %s", alias, domain, alias_line);
1464 call_onchange ( "valias_delete_domain" );
1465 }
1466 #endif
1467
1468 qnprintf( SqlBufUpdate, SQL_BUF_SIZE,
1469 "delete from valias where domain='%s'", domain );
1470
1471 pgres=PQexec( pgc, SqlBufUpdate );
1472 if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
1473 if(pgres) PQclear(pgres);
1474 vcreate_valias_table();
1475 qnprintf( SqlBufUpdate, SQL_BUF_SIZE,
1476 "delete from valias where domain='%s'", domain );
1477 pgres=PQexec( pgc, SqlBufUpdate );
1478 if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
1479 fprintf(stderr,"vpgsql: sql error: %s\n", PQerrorMessage(pgc));
1480 if (pgres) PQclear (pgres);
1481 return(-1);
1482 }
1483 }
1484 if(pgres) PQclear(pgres);
1485 return(0);
1486 }
1487
vcreate_valias_table()1488 void vcreate_valias_table()
1489 {
1490 PGresult *pgres;
1491 char SqlBufCreate[SQL_BUF_SIZE];
1492
1493 vauth_create_table ("valias", VALIAS_TABLE_LAYOUT, 1);
1494 snprintf( SqlBufCreate, SQL_BUF_SIZE,
1495 "create index valias_idx on valias ( %s )", VALIAS_INDEX_LAYOUT );
1496
1497 pgres=PQexec( pgc, SqlBufCreate );
1498 if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
1499 fprintf(stderr,"vpgsql:sql error[n.i]:%s\n", PQerrorMessage(pgc));
1500 if( pgres ) PQclear(pgres);
1501 return;
1502 }
1503 if( pgres ) PQclear(pgres);
1504 return;
1505 }
1506
valias_select_all(char * alias,char * domain)1507 char *valias_select_all( char *alias, char *domain )
1508 {
1509 PGresult *pgres;
1510 int err;
1511 unsigned ntuples, ctuple;
1512 struct linklist *temp_entry = NULL;
1513
1514 /* remove old entries as necessary */
1515 while (valias_current != NULL)
1516 valias_current = linklist_del (valias_current);
1517
1518 if ( (err=vauth_open(0)) != 0 ) return(NULL);
1519
1520 qnprintf( SqlBufRead, SQL_BUF_SIZE,
1521 "select alias, valias_line from valias where domain = '%s' order by alias",
1522 domain );
1523 if ( ! (pgres=PQexec(pgc, SqlBufRead))
1524 || PQresultStatus(pgres) != PGRES_TUPLES_OK ) {
1525 if(pgres) PQclear(pgres);
1526 vcreate_valias_table();
1527 if ( ! (pgres=PQexec(pgc, SqlBufRead))
1528 || PQresultStatus(pgres) != PGRES_TUPLES_OK ) {
1529 fprintf(stderr,"vpgsql: sql error[o]: %s\n",
1530 PQerrorMessage(pgc));
1531 if (pgres) PQclear (pgres);
1532 return(NULL);
1533 }
1534 }
1535
1536 ntuples = PQntuples (pgres);
1537 for (ctuple = 0; ctuple < ntuples; ctuple++) {
1538 temp_entry = linklist_add (temp_entry, PQgetvalue (pgres, ctuple, 1), PQgetvalue (pgres, ctuple, 0));
1539 if (valias_current == NULL) valias_current = temp_entry;
1540 }
1541 PQclear (pgres);
1542 pgres = NULL;
1543
1544 if (valias_current == NULL) return NULL; /* no results */
1545 else {
1546 strcpy (alias, valias_current->d2);
1547 return(valias_current->data);
1548 }
1549 }
1550
valias_select_all_next(char * alias)1551 char *valias_select_all_next(char *alias)
1552 {
1553 if (valias_current == NULL) return NULL;
1554 valias_current = linklist_del (valias_current);
1555
1556 if (valias_current == NULL) return NULL;
1557 else {
1558 strcpy (alias, valias_current->d2);
1559 return valias_current->data;
1560 }
1561 }
1562
1563 /************************************************************************
1564 *
1565 * valias_select_names
1566 */
1567
valias_select_names(char * domain)1568 char *valias_select_names( char *domain )
1569 {
1570 PGresult *pgres;
1571 int err;
1572 unsigned ntuples, ctuple;
1573 struct linklist *temp_entry = NULL;
1574
1575
1576 /* remove old entries as necessary */
1577 while (valias_current != NULL)
1578 valias_current = linklist_del (valias_current);
1579
1580 if ( (err=vauth_open(0)) != 0 ) return(NULL);
1581
1582 qnprintf( SqlBufRead, SQL_BUF_SIZE,
1583 "select distinct alias from valias where domain = '%s' order by alias", domain );
1584
1585 if ( ! (pgres=PQexec(pgc, SqlBufRead))
1586 || PQresultStatus(pgres) != PGRES_TUPLES_OK ) {
1587 if(pgres) PQclear(pgres);
1588 vcreate_valias_table();
1589 if ( ! (pgres=PQexec(pgc, SqlBufRead))
1590 || PQresultStatus(pgres) != PGRES_TUPLES_OK ) {
1591 fprintf(stderr,"vpgsql: sql error[o]: %s\n",
1592 PQerrorMessage(pgc));
1593 if (pgres) PQclear (pgres);
1594 return(NULL);
1595 }
1596 }
1597
1598 ntuples = PQntuples (pgres);
1599 for (ctuple = 0; ctuple < ntuples; ctuple++) {
1600 temp_entry = linklist_add (temp_entry, PQgetvalue (pgres, ctuple, 0), "");
1601 if (valias_current == NULL) valias_current = temp_entry;
1602 }
1603 PQclear (pgres);
1604 pgres = NULL;
1605
1606 if (valias_current == NULL) return NULL; /* no results */
1607 else return(valias_current->data);
1608 }
1609
1610 /************************************************************************
1611 *
1612 * valias_select_names_next
1613 */
1614
valias_select_names_next()1615 char *valias_select_names_next()
1616 {
1617 if (valias_current == NULL) return NULL;
1618 valias_current = linklist_del (valias_current);
1619
1620 if (valias_current == NULL) return NULL; /* no results */
1621 else return(valias_current->data);
1622 }
1623
1624
1625 /************************************************************************
1626 *
1627 * valias_select_names_end
1628 */
1629
valias_select_names_end()1630 void valias_select_names_end() {
1631
1632 // not needed by pgsql
1633
1634 }
1635
1636 #endif
1637
1638 #ifdef ENABLE_SQL_LOGGING
logsql(int verror,char * TheUser,char * TheDomain,char * ThePass,char * TheName,char * IpAddr,char * LogLine)1639 int logsql( int verror, char *TheUser, char *TheDomain, char *ThePass,
1640 char *TheName, char *IpAddr, char *LogLine)
1641 {
1642 PGresult *pgres;
1643 int err;
1644 time_t mytime;
1645
1646 mytime = time(NULL);
1647 if ( (err=vauth_open(1)) != 0 ) return(err);
1648 /*
1649
1650 qnprintf( SqlBufUpdate, SQL_BUF_SIZE,
1651 "INSERT INTO vlog set userid='%s', passwd='%s', \
1652 domain='%s', logon='%s', remoteip='%s', message='%s', \
1653 error=%i, timestamp=%d", TheUser, ThePass, TheDomain,
1654 TheName, IpAddr, LogLine, verror, (int)mytime);
1655 */
1656
1657 qnprintf( SqlBufUpdate, SQL_BUF_SIZE,
1658 "INSERT INTO vlog (userid,passwd,domain,logon,remoteip,message,error,timestamp) values('%s','%s','%s','%s','%s','%s',%i,%d)",
1659 TheUser, ThePass, TheDomain, TheName,
1660 IpAddr, LogLine, verror, (int)mytime);
1661
1662 pgres=PQexec( pgc, SqlBufUpdate );
1663 if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
1664 if( pgres ) PQclear(pgres);
1665 vcreate_vlog_table();
1666 qnprintf( SqlBufUpdate, SQL_BUF_SIZE,
1667 "INSERT INTO vlog (userid,passwd,domain,logon,remoteip,message,error,timestamp) values('%s','%s','%s','%s','%s','%s',%i,%d)",
1668 TheUser, ThePass, TheDomain, TheName,
1669 IpAddr, LogLine, verror, (int)mytime);
1670
1671 pgres=PQexec( pgc, SqlBufUpdate );
1672 if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
1673 if( pgres ) PQclear(pgres);
1674 fprintf(stderr,"error inserting into lastauth table\n");
1675 }
1676 }
1677 if( pgres ) PQclear(pgres);
1678 return(0);
1679 }
1680
vcreate_vlog_table()1681 void vcreate_vlog_table()
1682 {
1683 vauth_create_table ("vlog", VLOG_TABLE_LAYOUT, 1);
1684 return;
1685 }
1686 #endif
1687
vauth_crypt(char * user,char * domain,char * clear_pass,struct vqpasswd * vpw)1688 int vauth_crypt(char *user,char *domain,char *clear_pass,struct vqpasswd *vpw)
1689 {
1690 if ( vpw == NULL ) return(-1);
1691
1692 return(strcmp(crypt(clear_pass,vpw->pw_passwd),vpw->pw_passwd));
1693 }
1694
1695