/*
* $Id: vpgsql.c,v 1.39 2007/08/17 22:49:23 rwidmer Exp $
* Copyright (C) 1999-2004 Inter7 Internet Technologies, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include <ctype.h>
#include <pwd.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <libpq-fe.h> /* required pgsql front-end headers */
#include "config.h"
#include "vpopmail.h"
#include "vauth.h"
#include "vlimits.h"
#include "vpgsql.h"
// Variables to control debug output
#ifdef VPOPMAIL_DEBUG
int show_trace=0;
int show_query=0;
int dump_data=0;
#endif
/* pgsql has no built-in replication, yet.
#ifdef PGSQL_REPLICATION
static PGconn *pgc_read;
#else
#define pgc_read pgc_update
#endif
#ifdef PGSQL_REPLICATION
static int read_open = 0;
#else
#define read_open update_open
#endif
#ifdef PGSQL_REPLICATION
static PGresult *res_read = NULL;
#else
#define res_read res_update
#endif
*/
/*
read-only and read-write connections
to be implemented later...
static PGconn *pgc_update;
static PGconn *pgc_read;
static PGconn *pgc_read_getall;
*/
static PGconn *pgc; /* pointer to pgsql connection */
static int is_open = 0;
#define SQL_BUF_SIZE 2048
static char SqlBufRead[SQL_BUF_SIZE];
static char SqlBufUpdate[SQL_BUF_SIZE];
#define SMALL_BUFF 200
char IUser[SMALL_BUFF];
char IPass[SMALL_BUFF];
char IGecos[SMALL_BUFF];
char IDir[SMALL_BUFF];
char IShell[SMALL_BUFF];
char IClearPass[SMALL_BUFF];
void vcreate_dir_control(char *domain);
void vcreate_vlog_table();
#ifdef POP_AUTH_OPEN_RELAY
void vcreate_relay_table();
#endif
#ifdef VALIAS
void vcreate_valias_table();
#endif
#ifdef ENABLE_AUTH_LOGGING
void vcreate_lastauth_table();
#endif
/* pgsql BEGIN TRANSACTION ********/
int pg_begin(void)
{
PGresult *pgres;
pgres=PQexec(pgc, "BEGIN");
if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
fprintf(stderr, "pg_begin: %s\n", PQerrorMessage(pgc));
if (pgres) PQclear (pgres);
return -1;
}
PQclear(pgres);
return 0;
}
/* pgsql END TRANSACTION ********/
int pg_end(void)
{
PGresult *pgres;
pgres=PQexec(pgc, "END");
if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
fprintf(stderr, "pg_end: %s\n", PQerrorMessage(pgc));
if (pgres) PQclear (pgres);
return -1;
}
PQclear(pgres);
return 0;
}
/*** Open a connection to pgsql ***/
int vauth_open( int will_update )
{
#ifdef VPOPMAIL_DEBUG
show_trace = ( getenv("VPSHOW_TRACE") != NULL);
show_query = ( getenv("VPSHOW_QUERY") != NULL);
dump_data = ( getenv("VPDUMP_DATA") != NULL);
#endif
#ifdef VPOPMAIL_DEBUG
if( show_trace ) {
fprintf( stderr, "vauth_open(%d)\n",will_update);
}
#endif
/*
* If the connection to this authentication database can fail
* you should test access here. If it works, return 0, else
* return VA_NO_AUTH_CONNECTION. You can also set the string
* sqlerr to some short descriptive text about the problem,
* and allocate a much longer string, pointed to by last_query
* that can be displayed in an error message returned because
* of this problem.
*
*/
if ( is_open != 0 ) return(0);
is_open = 1;
verrori = 0;
/* Try to connect to the pgserver with the specified database. */
pgc = PQconnectdb(PG_CONNECT);
if( PQstatus(pgc) == CONNECTION_BAD) {
fprintf(stderr, "vauth_open: can't connect: %s\n", PQerrorMessage(pgc));
return VA_NO_AUTH_CONNECTION;
}
return(0);
}
int vauth_create_table (char *table, char *layout, int showerror)
{
int err;
PGresult *pgres;
char SqlBufCreate[SQL_BUF_SIZE];
if ((err = vauth_open(1))) return (err);
snprintf(SqlBufCreate, SQL_BUF_SIZE,
"CREATE TABLE %s ( %s )", table, layout);
pgres=PQexec(pgc, SqlBufCreate);
if (!pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK) {
err = -1;
if (showerror)
fprintf (stderr, "vpgsql: error creating table '%s': %s\n", table,
PQerrorMessage(pgc));
} else err = 0;
if (pgres) PQclear (pgres);
return err;
}
int vauth_adddomain( char *domain )
{
#ifndef MANY_DOMAINS
vset_default_domain( domain );
return (vauth_create_table (vauth_munch_domain( domain ), TABLE_LAYOUT, 1));
#else
/* if creation fails, don't show an error */
vauth_create_table (PGSQL_DEFAULT_TABLE, TABLE_LAYOUT, 0);
return (0);
#endif
}
int vauth_adduser(char *user, char *domain, char *pass, char *gecos,
char *dir, int apop )
{
char *domstr;
char dom_dir[156];
uid_t uid;
gid_t gid;
char dirbuf[200];
char quota[30];
char Crypted[100];
int err;
PGresult *pgres;
if ( (err=vauth_open(1)) != 0 ) return(err);
vset_default_domain( domain );
strncpy( quota, "NOQUOTA", 30 );
#ifndef MANY_DOMAINS
domstr = vauth_munch_domain( domain );
#else
domstr = PGSQL_DEFAULT_TABLE;
#endif
if ( domain == NULL || domain[0] == 0 ) {
domstr = PGSQL_LARGE_USERS_TABLE;
}
if ( strlen(domain) <= 0 ) {
if ( strlen(dir) > 0 ) {
snprintf(dirbuf, SQL_BUF_SIZE,
"%s/users/%s/%s", VPOPMAILDIR, dir, user);
} else {
snprintf(dirbuf, SQL_BUF_SIZE, "%s/users/%s", VPOPMAILDIR, user);
}
} else {
vget_assign(domain, dom_dir, 156, &uid, &gid );
if ( strlen(dir) > 0 ) {
snprintf(dirbuf,SQL_BUF_SIZE, "%s/%s/%s", dom_dir, dir, user);
} else {
snprintf(dirbuf,SQL_BUF_SIZE, "%s/%s", dom_dir, user);
}
}
if ( pass[0] != 0 ) {
mkpasswd3(pass,Crypted, 100);
} else {
Crypted[0] = 0;
}
qnprintf( SqlBufUpdate, SQL_BUF_SIZE, INSERT,
domstr, user,
#ifdef MANY_DOMAINS
domain,
#endif
Crypted, apop, gecos, dirbuf, quota
#ifdef CLEAR_PASS
,pass
#endif
);
if(! ( pgres=PQexec(pgc,SqlBufUpdate) )||
PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
fprintf(stderr, "vauth_adduser: %s\npgsql: %s\n",
SqlBufUpdate, PQerrorMessage(pgc));
}
if( pgres ) PQclear(pgres);
return(0);
}
struct vqpasswd *vauth_getpw(char *user, char *domain)
{
char in_domain[156];
char *domstr;
static struct vqpasswd vpw;
int err;
PGresult *pgres;
verrori = 0;
if ( (err=vauth_open(0)) != 0 ) {
verrori = err;
return(NULL);
}
lowerit(user);
lowerit(domain);
snprintf (in_domain, sizeof(in_domain), "%s", domain);
vset_default_domain( in_domain );
#ifndef MANY_DOMAINS
domstr = vauth_munch_domain( in_domain );
#else
domstr = PGSQL_DEFAULT_TABLE;
#endif
if ( domstr == NULL || domstr[0] == 0 ) {
domstr = PGSQL_LARGE_USERS_TABLE;
}
qnprintf(SqlBufRead, SQL_BUF_SIZE, USER_SELECT, domstr, user
#ifdef MANY_DOMAINS
,in_domain
#endif
);
pgres=PQexec(pgc, SqlBufRead);
if ( ! pgres || PQresultStatus(pgres)!=PGRES_TUPLES_OK) {
if( pgres ) PQclear(pgres);
#ifdef DEBUG
fprintf(stderr,
"vauth_getpw: failed select: %s : %s\n",
SqlBufRead, PQerrorMessage(pgc));
#endif
return NULL;
}
if ( PQntuples(pgres) <= 0 ) { /* rows count */
PQclear(pgres);
return NULL;
}
memset(IUser, 0, sizeof(IUser));
memset(IPass, 0, sizeof(IPass));
memset(IGecos, 0, sizeof(IGecos));
memset(IDir, 0, sizeof(IDir));
memset(IShell, 0, sizeof(IShell));
memset(IClearPass, 0, sizeof(IClearPass));
vpw.pw_name = IUser;
vpw.pw_passwd = IPass;
vpw.pw_gecos = IGecos;
vpw.pw_dir = IDir;
vpw.pw_shell = IShell;
vpw.pw_clear_passwd = IClearPass;
strncpy(vpw.pw_name,PQgetvalue( pgres, 0, 0 ),SMALL_BUFF);
strncpy(vpw.pw_passwd,PQgetvalue( pgres, 0, 1 ),SMALL_BUFF);
vpw.pw_uid = atoi(PQgetvalue( pgres, 0, 2 ));
vpw.pw_gid = atoi(PQgetvalue( pgres, 0, 3 ));
strncpy(vpw.pw_gecos,PQgetvalue( pgres, 0, 4 ),SMALL_BUFF);
strncpy(vpw.pw_dir,PQgetvalue( pgres, 0, 5 ),SMALL_BUFF);
strncpy(vpw.pw_shell, PQgetvalue( pgres, 0, 6 ),SMALL_BUFF);
#ifdef CLEAR_PASS
if ( PQgetvalue( pgres, 0, 7 ) != 0 )
strncpy(vpw.pw_clear_passwd, PQgetvalue( pgres, 0, 7 ),SMALL_BUFF);
#endif
vlimits_setflags (&vpw, in_domain);
return(&vpw);
}
int vauth_deldomain( char *domain )
{
PGresult *pgres;
char *tmpstr;
int err;
if ( (err=vauth_open(1)) != 0 ) return(err);
vset_default_domain( domain );
#ifndef MANY_DOMAINS
tmpstr = vauth_munch_domain( domain );
snprintf( SqlBufUpdate, SQL_BUF_SIZE, "drop table %s", tmpstr);
#else
tmpstr = PGSQL_DEFAULT_TABLE;
qnprintf(SqlBufUpdate,SQL_BUF_SIZE,
"delete from %s where pw_domain = '%s'",
tmpstr, domain );
#endif
pgres=PQexec(pgc, SqlBufUpdate);
if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK){
fprintf(stderr,"vauth_deldomain: pgsql query: %s",
PQerrorMessage(pgc));
if(pgres) PQclear(pgres);
return(-1);
}
if(pgres) PQclear(pgres);
#ifdef VALIAS
valias_delete_domain( domain);
#endif
#ifdef ENABLE_AUTH_LOGGING
qnprintf( SqlBufUpdate, SQL_BUF_SIZE,
"delete from lastauth where domain = '%s'", domain );
pgres=PQexec(pgc, SqlBufUpdate);
if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK) {
return(-1);
}
if(pgres) PQclear(pgres);
#endif
#ifdef ENABLE_SQL_LOGGING
#ifdef ENABLE_SQL_REMOVE_DELETED
qnprintf( SqlBufUpdate, SQL_BUF_SIZE,
"delete from vlog where domain = '%s'", domain );
pgres=PQexec(pgc, SqlBufUpdate);
if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK) {
return(-1);
}
#endif
#endif
return(0);
}
int vauth_deluser( char *user, char *domain )
{
PGresult *pgres;
char *tmpstr;
int err = 0;
if ( (err=vauth_open(1)) != 0 ) return(err);
vset_default_domain( domain );
#ifndef MANY_DOMAINS
if ( domain == NULL || domain[0] == 0 ) {
tmpstr = PGSQL_LARGE_USERS_TABLE;
} else {
tmpstr = vauth_munch_domain( domain );
}
#else
tmpstr = PGSQL_DEFAULT_TABLE;
#endif
qnprintf( SqlBufUpdate, SQL_BUF_SIZE, DELETE_USER, tmpstr, user
#ifdef MANY_DOMAINS
, domain
#endif
);
pgres=PQexec(pgc, SqlBufUpdate);
if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
err = -1;
}
if( pgres ) PQclear(pgres);
#ifdef ENABLE_AUTH_LOGGING
qnprintf( SqlBufUpdate, SQL_BUF_SIZE,
"delete from lastauth where user = '%s' and domain = '%s'",
user, domain );
pgres=PQexec(pgc, SqlBufUpdate);
if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
err = -1;
}
if( pgres ) PQclear(pgres);
#endif
#ifdef ENABLE_SQL_LOGGING
#ifdef ENABLE_SQL_REMOVE_DELETED
qnprintf( SqlBufUpdate, SQL_BUF_SIZE,
"delete from vlog where domain = '%s' and user='%s'",
domain, user );
pgres=PQexec(pgc, SqlBufUpdate);
if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK) {
err = -1;
}
#endif
#endif
return(err);
}
int vauth_setquota( char *username, char *domain, char *quota)
{
PGresult *pgres;
char *tmpstr;
int err;
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);
if ( (err=vauth_open(1)) != 0 ) return(err);
vset_default_domain( domain );
#ifndef MANY_DOMAINS
tmpstr = vauth_munch_domain( domain );
#else
tmpstr = PGSQL_DEFAULT_TABLE;
#endif
qnprintf( SqlBufUpdate, SQL_BUF_SIZE, SETQUOTA, tmpstr, quota, username
#ifdef MANY_DOMAINS
, domain
#endif
);
pgres = PQexec(pgc, SqlBufUpdate);
if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
fprintf(stderr,
"vauth_setquota: query failed: %s\n", PQerrorMessage(pgc));
if( pgres ) PQclear(pgres);
return(-1);
}
if( pgres ) PQclear(pgres);
return(0);
}
struct vqpasswd *vauth_getall(char *domain, int first, int sortit)
{
static PGresult *pgres=NULL;
/* ntuples - number of tuples ctuple - current tuple */
static unsigned ntuples=0, ctuple=0;
char *domstr = NULL;
static struct vqpasswd vpw;
int err;
vset_default_domain( domain );
#ifdef MANY_DOMAINS
domstr = PGSQL_DEFAULT_TABLE;
#else
domstr = vauth_munch_domain( domain );
#endif
if ( first == 1 ) {
if ( (err=vauth_open(0)) != 0 ) return(NULL);
qnprintf(SqlBufRead, SQL_BUF_SIZE, GETALL, domstr
#ifdef MANY_DOMAINS
,domain
#endif
);
if ( sortit == 1 ) {
strncat( SqlBufRead, " order by pw_name", SQL_BUF_SIZE);
}
if ( pgres ) { /* reset state if we had previous result */
PQclear(pgres); // clear previous result
pgres=NULL;
ntuples=ctuple=0;
}
pgres = PQexec(pgc, SqlBufRead);
if( !pgres || PQresultStatus(pgres) != PGRES_TUPLES_OK ) {
fprintf(stderr, "vauth_getall:query failed[5]: %s\n", PQerrorMessage(pgc));
if( pgres ) {
PQclear(pgres);
pgres=NULL;
}
return (NULL);
}
ntuples = PQntuples( pgres );
}
if ( ctuple == ntuples ) {
PQclear(pgres);
pgres=NULL;
ctuple=ntuples=0;
return NULL;
}
memset(IUser, 0, sizeof(IUser));
memset(IPass, 0, sizeof(IPass));
memset(IGecos, 0, sizeof(IGecos));
memset(IDir, 0, sizeof(IDir));
memset(IShell, 0, sizeof(IShell));
memset(IClearPass, 0, sizeof(IClearPass));
vpw.pw_name = IUser;
vpw.pw_passwd = IPass;
vpw.pw_gecos = IGecos;
vpw.pw_dir = IDir;
vpw.pw_shell = IShell;
vpw.pw_clear_passwd = IClearPass;
strncpy(vpw.pw_name, PQgetvalue( pgres, ctuple, 0 ),SMALL_BUFF );
strncpy(vpw.pw_passwd, PQgetvalue( pgres, ctuple, 1 ),SMALL_BUFF );
vpw.pw_uid = atoi(PQgetvalue( pgres, ctuple, 2 ));
vpw.pw_gid = atoi(PQgetvalue( pgres, ctuple, 3 ));
strncpy(vpw.pw_gecos, PQgetvalue( pgres, ctuple, 4 ),SMALL_BUFF);
strncpy(vpw.pw_dir, PQgetvalue( pgres, ctuple, 5 ),SMALL_BUFF);
strncpy(vpw.pw_shell, PQgetvalue( pgres, ctuple, 6 ),SMALL_BUFF);
#ifdef CLEAR_PASS
if (PQgetvalue( pgres, ctuple, 7)!= 0 ) {
strncpy(vpw.pw_clear_passwd, PQgetvalue( pgres, ctuple, 7 ),SMALL_BUFF);
}
#endif
ctuple++;
vlimits_setflags(&vpw,domain);
return(&vpw);
}
void vauth_end_getall()
{
/* not applicable in pgsql? */
}
char *vauth_munch_domain( char *domain )
{
int i;
static char tmpbuf[50];
if ( domain == NULL || domain[0] == 0 ) return(domain);
for(i=0;domain[i]!=0;++i){
tmpbuf[i] = tolower(domain[i]);
if ( domain[i] == '.' || domain[i] == '-' ) {
tmpbuf[i] = SQL_DOT_CHAR;
}
}
tmpbuf[i] = 0;
return(tmpbuf);
}
int vauth_setpw( struct vqpasswd *inpw, char *domain )
{
PGresult *pgres;
char *tmpstr;
uid_t myuid;
uid_t uid;
gid_t gid;
int err;
err = vcheck_vqpw(inpw, domain);
if ( err != 0 ) return(err);
vget_assign(domain,NULL,0,&uid,&gid);
myuid = geteuid();
if ( myuid != 0 && myuid != uid ) {
return(VA_BAD_UID);
}
if ( (err=vauth_open(1)) != 0 ) return(err);
vset_default_domain( domain );
#ifndef MANY_DOMAINS
tmpstr = vauth_munch_domain( domain );
#else
tmpstr = PGSQL_DEFAULT_TABLE;
#endif
qnprintf( SqlBufUpdate,SQL_BUF_SIZE,SETPW,
tmpstr,
inpw->pw_passwd,
inpw->pw_uid,
inpw->pw_gid,
inpw->pw_gecos,
inpw->pw_dir,
inpw->pw_shell,
#ifdef CLEAR_PASS
inpw->pw_clear_passwd,
#endif
inpw->pw_name
#ifdef MANY_DOMAINS
,domain
#endif
);
pgres=PQexec(pgc, SqlBufUpdate);
if ( !pgres || PQresultStatus(pgres)!= PGRES_COMMAND_OK ) {
fprintf(stderr, "vauth_setpw: pgsql query[6]: %s\n",
PQerrorMessage(pgc));
if( pgres ) PQclear(pgres);
return(-1);
}
if( pgres ) PQclear(pgres);
#ifdef SQWEBMAIL_PASS
vsqwebmail_pass( inpw->pw_dir, inpw->pw_passwd, uid, gid);
#endif
#ifdef ONCHANGE_SCRIPT
if( allow_onchange ) {
/* tell other programs that data has changed */
snprintf ( onchange_buf, MAX_BUFF, "%s@%s", inpw->pw_name, domain );
call_onchange ( "mod_user" );
}
#endif
return(0);
}
#ifdef POP_AUTH_OPEN_RELAY
int vopen_smtp_relay()
{
PGresult *pgres;
char *ipaddr;
time_t mytime;
int err;
mytime = time(NULL);
ipaddr = get_remote_ip();
if ( ipaddr == NULL ) {
return 0;
}
if ( (err=vauth_open(1)) != 0 ) return 0;
qnprintf(SqlBufUpdate, SQL_BUF_SIZE,
"UPDATE relay SET ip_addr='%s', timestamp=%d WHERE ip_addr='%s'",
ipaddr, (int)mytime, ipaddr);
pgres=PQexec(pgc, SqlBufUpdate);
if (PQresultStatus(pgres) == PGRES_COMMAND_OK && atoi(PQcmdTuples(pgres)) == 0) {
if( pgres ) PQclear(pgres);
qnprintf( SqlBufUpdate, SQL_BUF_SIZE,
"INSERT INTO relay (ip_addr, timestamp) VALUES ('%s', %lu)",
ipaddr, time(NULL));
pgres=PQexec(pgc, SqlBufUpdate);
}
/* UPDATE returned 0 rows and/or INSERT failed. Try creating the table */
if(!pgres || PQresultStatus(pgres) != PGRES_COMMAND_OK) {
if( pgres ) PQclear(pgres);
vcreate_relay_table();
/* and try INSERTing now... */
qnprintf( SqlBufUpdate, SQL_BUF_SIZE,
"INSERT INTO relay (ip_addr, timestamp) VALUES ('%s', %lu)",
ipaddr, time(NULL));
pgres=PQexec(pgc, SqlBufUpdate);
}
if(pgres && PQresultStatus(pgres) == PGRES_COMMAND_OK ) {
/* need to return non-zero value if value inserted */
if( pgres ) PQclear(pgres);
return 1;
}
if( pgres ) PQclear(pgres);
return 0;
}
void vupdate_rules(int fdm)
{
PGresult *pgres;
const char re[]=":allow,RELAYCLIENT=\"\",RBLSMTPD=\"\"\n";
register unsigned i=0, n, len=strlen(re)+1;
char *buf=NULL;
if (vauth_open(0) != 0) return;
snprintf(SqlBufRead, SQL_BUF_SIZE, "SELECT ip_addr FROM relay");
if ( !(pgres=PQexec(pgc, SqlBufRead)) || PQresultStatus(pgres)!=PGRES_TUPLES_OK) {
vcreate_relay_table();
if(pgres) PQclear(pgres);
if ( !(pgres=PQexec(pgc, SqlBufRead)) || PQresultStatus(pgres)!=PGRES_TUPLES_OK ) {
fprintf(stderr, "vupdate_rules: query : %s\n", PQerrorMessage(pgc));
if (pgres) PQclear (pgres);
return;
}
}
n=PQntuples(pgres);
for( ; i < n ; i++ ) {
buf=realloc(buf, len+PQgetlength(pgres, i, 0) );
if( buf==NULL || errno==ENOMEM ) {
PQclear(pgres);
free(buf);
fprintf(stderr, "vupdate_rules: no mem\n");
return;
}
sprintf( buf, "%s%s", PQgetvalue(pgres, i, 0), re );
if( write( fdm, buf, strlen(buf) ) != strlen(buf) ) {
fprintf(stderr, "vupdate_rules: short write: %s",
strerror(errno));
break;
}
}
if(pgres) PQclear(pgres);
free(buf);
return;
}
void vclear_open_smtp(time_t clear_minutes, time_t mytime)
{
PGresult *pgres;
time_t delete_time;
int err;
if ( (err=vauth_open(1)) != 0 ) return;
delete_time = mytime - clear_minutes;
snprintf( SqlBufUpdate, SQL_BUF_SIZE,
"DELETE FROM relay WHERE timestamp <= %d",
(int)delete_time);
pgres=PQexec(pgc, SqlBufUpdate);
if( !pgres || PQresultStatus(pgres) != PGRES_COMMAND_OK) {
vcreate_relay_table();
}
return;
}
void vcreate_relay_table()
{
vauth_create_table ("relay", RELAY_TABLE_LAYOUT, 1);
return;
}
#endif
int vmkpasswd( char *domain )
{
return(0);
}
void vclose()
{
/* disconnection from the database */
if ( is_open == 1 ) {
is_open = 0;
PQfinish(pgc);
}
}
#ifdef IP_ALIAS_DOMAINS
void vcreate_ip_map_table()
{
vauth_create_table ("ip_alias_map", IP_ALIAS_TABLE_LAYOUT, 1);
return;
}
int vget_ip_map( char *ip, char *domain, int domain_size)
{
PGresult *pgres;
char *ptr;
unsigned ntuples;
int ret = -1;
if ( ip == NULL || strlen(ip) <= 0 ) return(-1);
if ( domain == NULL ) return(-2);
if ( vauth_open(0) != 0 ) return(-3);
qnprintf(SqlBufRead, SQL_BUF_SIZE,
"select domain from ip_alias_map where ip_addr = '%s'",
ip);
pgres=PQexec(pgc, SqlBufRead);
if( !pgres || PQresultStatus(pgres) != PGRES_TUPLES_OK ) {
fprintf( stderr, "vget_ip_map: pgsql query: %s\n", PQerrorMessage(pgc));
if( pgres ) PQclear(pgres);
return -1;
}
ntuples = PQntuples(pgres);
if(!ntuples)
*domain='\0';
else {
ret = 0;
ptr = PQgetvalue(pgres, ntuples-1, 0);
strncpy(domain, ptr, strlen(ptr) );
}
PQclear(pgres);
return (ret);
}
int vadd_ip_map( char *ip, char *domain)
{
PGresult *pgres;
int err = 0;
if ( ip == NULL || strlen(ip) <= 0 ) return(-1);
if ( domain == NULL || strlen(domain) <= 0 ) return(-1);
if ( (err=vauth_open(1)) != 0 ) return(err);
if( ( err=pg_begin() )!= 0 ) { /* begin transaction */
return(err);
}
qnprintf(SqlBufUpdate,SQL_BUF_SIZE,
"delete from ip_alias_map where ip_addr='%s' and domain='%s'",
ip, domain);
/* step 1: delete previous entry */
pgres=PQexec(pgc, SqlBufUpdate);
if( pgres ) PQclear(pgres); /* don't check pgres status
table may not exist */
/* step 2: insert new data */
qnprintf(SqlBufUpdate,SQL_BUF_SIZE,
"insert into ip_alias_map (ip_addr,domain) values ('%s','%s')",
ip, domain);
pgres=PQexec(pgc, SqlBufUpdate);
if ( !pgres || PQresultStatus(pgres) != PGRES_COMMAND_OK ) {
if( pgres ) PQclear(pgres);
vcreate_ip_map_table();
qnprintf(SqlBufUpdate,SQL_BUF_SIZE,
"insert into ip_alias_map (ip_addr,domain) values ('%s','%s')",
ip, domain);
pgres=PQexec( pgc, SqlBufUpdate);
if ( !pgres || PQresultStatus(pgres) != PGRES_COMMAND_OK ) {
fprintf( stderr, "vadd_ip_map: insert: %s\n", PQerrorMessage(pgc));
if( pgres ) PQclear(pgres);
return -1;
}
}
if( pgres ) PQclear(pgres);
return ( pg_end() ); /* end transaction */
}
int vdel_ip_map( char *ip, char *domain)
{
PGresult *pgres;
int err=0;
if ( ip == NULL || strlen(ip) <= 0 ) return(-1);
if ( domain == NULL || strlen(domain) <= 0 ) return(-1);
if ( (err=vauth_open(1)) != 0 ) return(err);
qnprintf( SqlBufUpdate,SQL_BUF_SIZE,
"delete from ip_alias_map where ip_addr='%s' and domain='%s'",
ip, domain);
pgres=PQexec(pgc, SqlBufUpdate);
if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
fprintf(stderr, "vdel_ip_map: delete failed: %s\n",
PQerrorMessage(pgc));
if(pgres) PQclear(pgres);
/* #warning why are we returning 0 when we couldn't delete?*/
return(0);
}
if(pgres) PQclear(pgres);
return(0);
}
int vshow_ip_map( int first, char *ip, char *domain )
{
static PGresult *pgres=NULL;
static unsigned ntuples=0, ctuple=0;
int err= 0;
if ( ip == NULL ) return(-1);
if ( domain == NULL ) return(-1);
if ( ( err=vauth_open(0) ) != 0 ) return(err);
if ( first == 1 ) {
snprintf(SqlBufRead,SQL_BUF_SIZE,
"select ip_addr, domain from ip_alias_map");
if (pgres) {
PQclear(pgres);
ntuples=ctuple=0;
}
if ( ! (pgres=PQexec(pgc, SqlBufRead))
|| PQresultStatus(pgres) != PGRES_TUPLES_OK ) {
if(pgres) PQclear(pgres);
snprintf(SqlBufRead,SQL_BUF_SIZE,
"select ip_addr, domain from ip_alias_map");
vcreate_ip_map_table();
if ( ! (pgres=PQexec(pgc, SqlBufRead))
|| PQresultStatus(pgres) != PGRES_TUPLES_OK ) {
return(0);
}
}
ntuples=PQntuples(pgres);
}
if ( ctuple == ntuples ) {
PQclear(pgres);
ntuples=ctuple=0;
return (0);
}
strncpy( ip, PQgetvalue( pgres, ctuple, 0), 18);
strncpy( domain, PQgetvalue( pgres, ctuple, 1), 156);
strncpy( ip, PQgetvalue( pgres, ctuple, 0), 18);
strncpy( domain, PQgetvalue( pgres, ctuple, 1), 156);
ctuple++;
return 1;
}
#endif
int vread_dir_control(vdir_type *vdir, char *domain, uid_t uid, gid_t gid)
{
PGresult *pgres;
int found = 0;
if ( vauth_open(0) != 0 ) return(-1);
qnprintf(SqlBufUpdate, SQL_BUF_SIZE,
"select %s from dir_control where domain = '%s'",
DIR_CONTROL_SELECT, domain );
if (!(pgres=PQexec(pgc, SqlBufUpdate)) ||
PQresultStatus(pgres)!=PGRES_TUPLES_OK ) {
if( pgres ) PQclear(pgres);
vcreate_dir_control(domain);
qnprintf(SqlBufUpdate, SQL_BUF_SIZE,
"select %s from dir_control where domain = '%s'",
DIR_CONTROL_SELECT, domain );
if (! (pgres=PQexec(pgc, SqlBufUpdate)) ||
PQresultStatus(pgres)!=PGRES_TUPLES_OK ) {
fprintf(stderr, "vread_dir_control: q: %s\npgsql: %s",
SqlBufUpdate, PQerrorMessage(pgc));
if (pgres) PQclear (pgres);
return (-1);
}
}
if ( PQntuples(pgres) > 0 ) {
found = 1;
vdir->cur_users = atol( PQgetvalue( pgres, 0, 0 ) );
vdir->level_cur = atoi( PQgetvalue( pgres, 0, 1 ) );
vdir->level_max = atoi( PQgetvalue( pgres, 0, 2 ) );
vdir->level_start[0] = atoi( PQgetvalue( pgres, 0, 3 ) );
vdir->level_start[1] = atoi( PQgetvalue( pgres, 0, 4 ) );
vdir->level_start[2] = atoi( PQgetvalue( pgres, 0, 5 ) );
vdir->level_end[0] = atoi( PQgetvalue( pgres, 0, 6 ) );
vdir->level_end[1] = atoi( PQgetvalue( pgres, 0, 7 ) );
vdir->level_end[2] = atoi( PQgetvalue( pgres, 0, 8 ) );
vdir->level_mod[0] = atoi( PQgetvalue( pgres, 0, 9 ) );
vdir->level_mod[1] = atoi( PQgetvalue( pgres, 0, 10 ) );
vdir->level_mod[2] = atoi( PQgetvalue( pgres, 0, 11 ) );
vdir->level_index[0] = atoi( PQgetvalue( pgres, 0, 12 ) );
vdir->level_index[1] = atoi( PQgetvalue( pgres, 0, 13 ) );
vdir->level_index[2] = atoi( PQgetvalue( pgres, 0, 14 ) );
strncpy(vdir->the_dir, PQgetvalue( pgres, 0, 15 ), MAX_DIR_NAME);
}
PQclear(pgres);
if ( found == 0 ) {
int i;
vdir->cur_users = 0;
for(i=0;i<MAX_DIR_LEVELS;++i) {
vdir->level_start[i] = 0;
vdir->level_end[i] = MAX_DIR_LIST-1;
vdir->level_index[i] = 0;
}
vdir->level_mod[0] = 0;
vdir->level_mod[1] = 2;
vdir->level_mod[2] = 4;
vdir->level_cur = 0;
vdir->level_max = MAX_DIR_LEVELS;
vdir->the_dir[0] = 0;
}
return(0);
}
int vwrite_dir_control(vdir_type *vdir, char *domain, uid_t uid, gid_t gid)
{
PGresult *pgres;
if ( vauth_open(1) != 0 ) return(-1);
qnprintf(SqlBufUpdate, SQL_BUF_SIZE,
"delete from dir_control where domain='%s'", domain );
if( pg_begin() ) { /* begin transaction */
return -1;
}
pgres=PQexec(pgc, SqlBufUpdate);
if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
fprintf(stderr, "vwrite_dir_control: delete failed: %s",
PQerrorMessage(pgc));
if (pgres) PQclear (pgres);
return -1;
}
qnprintf(SqlBufUpdate, SQL_BUF_SIZE,
"insert into dir_control ( \
domain, cur_users, \
level_cur, level_max, \
level_start0, level_start1, level_start2, \
level_end0, level_end1, level_end2, \
level_mod0, level_mod1, level_mod2, \
level_index0, level_index1, level_index2, the_dir ) values ( \
'%s', %lu, %d, %d, \
%d, %d, %d, \
%d, %d, %d, \
%d, %d, %d, \
%d, %d, %d, \
'%s')\n",
domain, vdir->cur_users, vdir->level_cur, vdir->level_max,
vdir->level_start[0], vdir->level_start[1], vdir->level_start[2],
vdir->level_end[0], vdir->level_end[1], vdir->level_end[2],
vdir->level_mod[0], vdir->level_mod[1], vdir->level_mod[2],
vdir->level_index[0], vdir->level_index[1], vdir->level_index[2],
vdir->the_dir);
pgres=PQexec(pgc, SqlBufUpdate);
if ( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
PQclear(pgres);
vcreate_dir_control(domain);
if ( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
fprintf(stderr, "vwrite_dir_control: %s\n", PQerrorMessage(pgc));
if (pgres) PQclear (pgres);
return(-1);
}
}
PQclear(pgres);
return pg_end(); /* end transcation */
}
void vcreate_dir_control(char *domain)
{
PGresult *pgres;
vauth_create_table ("dir_control", DIR_CONTROL_TABLE_LAYOUT, 1);
qnprintf(SqlBufUpdate, SQL_BUF_SIZE, "insert into dir_control ( \
domain, cur_users, \
level_cur, level_max, \
level_start0, level_start1, level_start2, \
level_end0, level_end1, level_end2, \
level_mod0, level_mod1, level_mod2, \
level_index0, level_index1, level_index2, the_dir ) values ( \
\'%s\', 0, \
0, %d, \
0, 0, 0, \
%d, %d, %d, \
0, 2, 4, \
0, 0, 0, \
\'\')\n",
domain, MAX_DIR_LEVELS, MAX_DIR_LIST-1, MAX_DIR_LIST-1, MAX_DIR_LIST-1);
pgres = PQexec( pgc, SqlBufUpdate );
if ( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
fprintf(stderr, "vcreate_dir_control: insert failed: %s\n",
PQerrorMessage(pgc));
if (pgres) PQclear (pgres);
return;
}
PQclear(pgres);
}
int vdel_dir_control(char *domain)
{
PGresult *pgres;
int err;
if ( (err=vauth_open(1)) != 0 ) return(err);
qnprintf(SqlBufUpdate, SQL_BUF_SIZE,
"delete from dir_control where domain = '%s'",
domain);
pgres=PQexec(pgc, SqlBufUpdate);
if ( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
PQclear(pgres);
vcreate_dir_control(domain);
qnprintf(SqlBufUpdate, SQL_BUF_SIZE,
"delete from dir_control where domain = '%s'",
domain);
if ( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
fprintf(stderr, "vdel_dir_control: delete failed[e]: %s\n",
PQerrorMessage(pgc));
err=-1;
}
}
if( pgres ) PQclear(pgres);
return err;
}
#ifdef ENABLE_AUTH_LOGGING
int vset_lastauth(char *user, char *domain, char *remoteip )
{
PGresult *pgres;
int err=0;
if ( (err=vauth_open(1)) != 0 ) return(err);
qnprintf( SqlBufUpdate, SQL_BUF_SIZE,
"UPDATE lastauth SET remote_ip='%s', timestamp=%lu " \
"WHERE userid='%s' AND domain='%s'", remoteip, time(NULL), user, domain);
#ifdef DEBUG
fprintf(stderr,"UPDATE command to run is \n\n%s\n\n", SqlBufUpdate);
#endif
pgres=PQexec(pgc, SqlBufUpdate);
if (pgres && PQresultStatus(pgres) == PGRES_COMMAND_OK && atoi(PQcmdTuples(pgres)) == 0) {
#ifdef DEBUG
fprintf(stderr,"UPDATE returned OK but had 0 rows\n");
#endif
if( pgres ) PQclear(pgres);
qnprintf( SqlBufUpdate, SQL_BUF_SIZE,
"INSERT INTO lastauth (userid, domain, remote_ip, timestamp) " \
"VALUES ('%s', '%s', '%s', %lu)", user, domain, remoteip, time(NULL));
#ifdef DEBUG
fprintf(stderr,"INSERT command to run is \n\n%s\n\n", SqlBufUpdate);
#endif
pgres=PQexec(pgc, SqlBufUpdate);
}
/* UPDATE returned 0 rows and/or INSERT failed. Try creating the table */
if(!pgres || PQresultStatus(pgres) != PGRES_COMMAND_OK) {
#ifdef DEBUG
fprintf(stderr,"UPDATE and/or INSERT failed. error was %s\n", PQerrorMessage(pgc));
#endif
if( pgres ) PQclear(pgres);
#ifdef DEBUG
fprintf(stderr, "update returned 0 and/or insert failed in vset_lastauth()\n");
#endif
vcreate_lastauth_table();
/* and try INSERTing now... */
qnprintf( SqlBufUpdate, SQL_BUF_SIZE,
"INSERT INTO lastauth (userid, domain, remote_ip, timestamp) " \
"VALUES ('%s', '%s', '%s', %lu)", user, domain, remoteip, time(NULL));
pgres=PQexec(pgc, SqlBufUpdate);
}
if ( !pgres || PQresultStatus(pgres) != PGRES_COMMAND_OK ) {
fprintf( stderr, "vset_lastauth[f]: %s\n: %s\n", SqlBufUpdate,PQerrorMessage(pgc));
if( pgres ) PQclear(pgres);
return (-1);
}
if( pgres ) PQclear(pgres);
return(0);
}
time_t vget_lastauth(struct vqpasswd *pw, char *domain)
{
PGresult *pgres;
int err, ntuples;
time_t mytime;
if ( (err=vauth_open(0)) != 0 ) return(err);
qnprintf( SqlBufRead, SQL_BUF_SIZE, "SELECT timestamp FROM lastauth WHERE userid='%s' AND domain='%s'", pw->pw_name, domain);
pgres=PQexec(pgc, SqlBufRead);
if ( !pgres || PQresultStatus(pgres) != PGRES_TUPLES_OK ) {
if( pgres ) PQclear(pgres);
vcreate_lastauth_table();
qnprintf( SqlBufRead, SQL_BUF_SIZE, "SELECT timestamp FROM lastauth WHERE userid='%s' AND domain='%s'", pw->pw_name, domain);
pgres=PQexec(pgc, SqlBufRead);
if ( !pgres || PQresultStatus(pgres) != PGRES_TUPLES_OK ) {
fprintf(stderr,"vpgsql: sql error[g]: %s\n", PQerrorMessage(pgc));
return(0);
}
}
ntuples = PQntuples(pgres);
mytime = 0;
if( ntuples ) { /* got something */
mytime = atol( PQgetvalue(pgres, ntuples-1, 0));
}
if( pgres ) PQclear(pgres);
return(mytime);
}
char *vget_lastauthip(struct vqpasswd *pw, char *domain)
{
PGresult *pgres;
static char tmpbuf[100];
int ntuples=0;
if ( vauth_open(0) != 0 ) return(NULL);
qnprintf( SqlBufRead, SQL_BUF_SIZE, "select remote_ip from lastauth where userid='%s' and domain='%s'", pw->pw_name, domain);
pgres=PQexec(pgc, SqlBufRead);
if ( !pgres || PQresultStatus(pgres) != PGRES_TUPLES_OK ) {
if( pgres ) PQclear(pgres);
vcreate_lastauth_table();
qnprintf( SqlBufRead, SQL_BUF_SIZE, "select remote_ip from lastauth where userid='%s' and domain='%s'", pw->pw_name, domain);
pgres=PQexec(pgc, SqlBufRead);
if ( !pgres || PQresultStatus(pgres) != PGRES_TUPLES_OK ) {
fprintf( stderr,"vpgsql: sql error[h]: %s\n", PQerrorMessage(pgc));
return(NULL);
}
}
ntuples = PQntuples(pgres);
if( ntuples ) { /* got something */
strncpy(tmpbuf, PQgetvalue(pgres, ntuples-1, 0),100 );
}
if( pgres ) PQclear(pgres);
return(tmpbuf);
}
void vcreate_lastauth_table()
{
vauth_create_table ("lastauth", LASTAUTH_TABLE_LAYOUT, 1);
return;
}
#endif /* ENABLE_AUTH_LOGGING */
#ifdef VALIAS
struct linklist *valias_current = NULL;
char *valias_select( char *alias, char *domain )
{
PGresult *pgvalias;
int err, verrori;
unsigned ntuples, ctuple;
struct linklist *temp_entry = NULL;
/* remove old entries as necessary */
while (valias_current != NULL)
valias_current = linklist_del (valias_current);
if ( (err=vauth_open(0)) != 0 ) {
verrori = err;
return(NULL);
}
qnprintf( SqlBufRead, SQL_BUF_SIZE,
"select valias_line from valias where alias='%s' and domain='%s'",
alias, domain );
if ( ! (pgvalias=PQexec(pgc, SqlBufRead))
|| PQresultStatus(pgvalias) != PGRES_TUPLES_OK ) {
if(pgvalias) PQclear(pgvalias);
vcreate_valias_table();
if ( ! (pgvalias=PQexec(pgc, SqlBufRead))
|| PQresultStatus(pgvalias) != PGRES_TUPLES_OK ) {
fprintf(stderr,"vpgsql: sql error[j]: %s\n",
PQerrorMessage(pgc));
if (pgvalias) PQclear(pgvalias);
return(NULL);
}
}
ntuples = PQntuples (pgvalias);
for (ctuple = 0; ctuple < ntuples; ctuple++) {
temp_entry = linklist_add (temp_entry, PQgetvalue (pgvalias, ctuple, 0), "");
if (valias_current == NULL) valias_current = temp_entry;
}
PQclear (pgvalias);
pgvalias = NULL;
if (valias_current == NULL) return NULL; /* no results */
else return(valias_current->data);
}
char *valias_select_next()
{
if (valias_current == NULL) return NULL;
valias_current = linklist_del (valias_current);
if (valias_current == NULL) return NULL;
else return valias_current->data;
}
int valias_insert( char *alias, char *domain, char *alias_line)
{
PGresult *pgres;
int err;
if ( (err=vauth_open(1)) != 0 ) return(err);
while(*alias_line==' ') ++alias_line;
qnprintf( SqlBufUpdate, SQL_BUF_SIZE,
"insert into valias(alias,domain,valias_line) values ('%s','%s','%s')",
alias, domain, alias_line );
pgres=PQexec( pgc, SqlBufUpdate );
if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
if(pgres) PQclear(pgres);
vcreate_valias_table();
qnprintf( SqlBufUpdate, SQL_BUF_SIZE,
"insert into valias(alias,domain,valias_line) values ('%s','%s','%s')",
alias, domain, alias_line );
pgres=PQexec( pgc, SqlBufUpdate );
if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
fprintf(stderr,"vpgsql: sql error[k]: %s\n", PQerrorMessage(pgc));
if (pgres) PQclear (pgres);
return(-1);
}
if(pgres) PQclear(pgres);
#ifdef ONCHANGE_SCRIPT
if( allow_onchange ) {
/* tell other programs that data has changed */
snprintf ( onchange_buf, MAX_BUFF, "%s@%s - %s", alias, domain, alias_line );
call_onchange ( "valias_add" );
}
#endif
return(0);
}
return(-1);
}
int valias_delete( char *alias, char *domain)
{
PGresult *pgres;
int err;
if ( (err=vauth_open(1)) != 0 ) return(err);
#ifdef ONCHANGE_SCRIPT
if( allow_onchange ) {
/* tell other programs that data has changed */
snprintf ( onchange_buf, MAX_BUFF, "%s@%s", alias, domain );
call_onchange ( "valias_delete" );
}
#endif
qnprintf( SqlBufUpdate, SQL_BUF_SIZE,
"delete from valias where alias='%s' and domain='%s'",
alias, domain );
pgres=PQexec( pgc, SqlBufUpdate );
if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
if(pgres) PQclear(pgres);
vcreate_valias_table();
qnprintf( SqlBufUpdate, SQL_BUF_SIZE,
"delete from valias where alias='%s' and domain='%s'",
alias, domain );
pgres=PQexec( pgc, SqlBufUpdate );
if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
fprintf(stderr,"vpgsql: sql error: %s\n", PQerrorMessage(pgc));
if (pgres) PQclear (pgres);
return(-1);
}
}
if(pgres) PQclear(pgres);
return(0);
}
int valias_remove( char *alias, char *domain, char *alias_line)
{
PGresult *pgres;
int err;
if ( (err=vauth_open(1)) != 0 ) return(err);
#ifdef ONCHANGE_SCRIPT
if( allow_onchange ) {
/* tell other programs that data has changed */
snprintf ( onchange_buf, MAX_BUFF, "%s@%s - %s", alias, domain, alias_line);
call_onchange ( "valias_remove" );
}
#endif
qnprintf( SqlBufUpdate, SQL_BUF_SIZE,
"delete from valias where alias='%s' and valias_line='%s' and domain='%s'",
alias, alias_line, domain );
pgres=PQexec( pgc, SqlBufUpdate );
if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
if(pgres) PQclear(pgres);
vcreate_valias_table();
pgres=PQexec( pgc, SqlBufUpdate );
if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
fprintf(stderr,"vpgsql: sql error: %s\n", PQerrorMessage(pgc));
if (pgres) PQclear (pgres);
return(-1);
}
}
if(pgres) PQclear(pgres);
return(0);
}
int valias_delete_domain( char *domain)
{
PGresult *pgres;
int err;
if ( (err=vauth_open(1)) != 0 ) return(err);
#ifdef ONCHANGE_SCRIPT
if( allow_onchange ) {
/* tell other programs that data has changed */
snprintf ( onchange_buf, MAX_BUFF, "%s@%s - %s", alias, domain, alias_line);
call_onchange ( "valias_delete_domain" );
}
#endif
qnprintf( SqlBufUpdate, SQL_BUF_SIZE,
"delete from valias where domain='%s'", domain );
pgres=PQexec( pgc, SqlBufUpdate );
if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
if(pgres) PQclear(pgres);
vcreate_valias_table();
qnprintf( SqlBufUpdate, SQL_BUF_SIZE,
"delete from valias where domain='%s'", domain );
pgres=PQexec( pgc, SqlBufUpdate );
if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
fprintf(stderr,"vpgsql: sql error: %s\n", PQerrorMessage(pgc));
if (pgres) PQclear (pgres);
return(-1);
}
}
if(pgres) PQclear(pgres);
return(0);
}
void vcreate_valias_table()
{
PGresult *pgres;
char SqlBufCreate[SQL_BUF_SIZE];
vauth_create_table ("valias", VALIAS_TABLE_LAYOUT, 1);
snprintf( SqlBufCreate, SQL_BUF_SIZE,
"create index valias_idx on valias ( %s )", VALIAS_INDEX_LAYOUT );
pgres=PQexec( pgc, SqlBufCreate );
if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
fprintf(stderr,"vpgsql:sql error[n.i]:%s\n", PQerrorMessage(pgc));
if( pgres ) PQclear(pgres);
return;
}
if( pgres ) PQclear(pgres);
return;
}
char *valias_select_all( char *alias, char *domain )
{
PGresult *pgres;
int err;
unsigned ntuples, ctuple;
struct linklist *temp_entry = NULL;
/* remove old entries as necessary */
while (valias_current != NULL)
valias_current = linklist_del (valias_current);
if ( (err=vauth_open(0)) != 0 ) return(NULL);
qnprintf( SqlBufRead, SQL_BUF_SIZE,
"select alias, valias_line from valias where domain = '%s' order by alias",
domain );
if ( ! (pgres=PQexec(pgc, SqlBufRead))
|| PQresultStatus(pgres) != PGRES_TUPLES_OK ) {
if(pgres) PQclear(pgres);
vcreate_valias_table();
if ( ! (pgres=PQexec(pgc, SqlBufRead))
|| PQresultStatus(pgres) != PGRES_TUPLES_OK ) {
fprintf(stderr,"vpgsql: sql error[o]: %s\n",
PQerrorMessage(pgc));
if (pgres) PQclear (pgres);
return(NULL);
}
}
ntuples = PQntuples (pgres);
for (ctuple = 0; ctuple < ntuples; ctuple++) {
temp_entry = linklist_add (temp_entry, PQgetvalue (pgres, ctuple, 1), PQgetvalue (pgres, ctuple, 0));
if (valias_current == NULL) valias_current = temp_entry;
}
PQclear (pgres);
pgres = NULL;
if (valias_current == NULL) return NULL; /* no results */
else {
strcpy (alias, valias_current->d2);
return(valias_current->data);
}
}
char *valias_select_all_next(char *alias)
{
if (valias_current == NULL) return NULL;
valias_current = linklist_del (valias_current);
if (valias_current == NULL) return NULL;
else {
strcpy (alias, valias_current->d2);
return valias_current->data;
}
}
#endif
#ifdef ENABLE_SQL_LOGGING
int logsql( int verror, char *TheUser, char *TheDomain, char *ThePass,
char *TheName, char *IpAddr, char *LogLine)
{
PGresult *pgres;
int err;
time_t mytime;
mytime = time(NULL);
if ( (err=vauth_open(1)) != 0 ) return(err);
/*
qnprintf( SqlBufUpdate, SQL_BUF_SIZE,
"INSERT INTO vlog set userid='%s', passwd='%s', \
domain='%s', logon='%s', remoteip='%s', message='%s', \
error=%i, timestamp=%d", TheUser, ThePass, TheDomain,
TheName, IpAddr, LogLine, verror, (int)mytime);
*/
qnprintf( SqlBufUpdate, SQL_BUF_SIZE,
"INSERT INTO vlog (userid,passwd,domain,logon,remoteip,message,error,timestamp) values('%s','%s','%s','%s','%s','%s',%i,%d)",
TheUser, ThePass, TheDomain, TheName,
IpAddr, LogLine, verror, (int)mytime);
pgres=PQexec( pgc, SqlBufUpdate );
if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
if( pgres ) PQclear(pgres);
vcreate_vlog_table();
qnprintf( SqlBufUpdate, SQL_BUF_SIZE,
"INSERT INTO vlog (userid,passwd,domain,logon,remoteip,message,error,timestamp) values('%s','%s','%s','%s','%s','%s',%i,%d)",
TheUser, ThePass, TheDomain, TheName,
IpAddr, LogLine, verror, (int)mytime);
pgres=PQexec( pgc, SqlBufUpdate );
if( !pgres || PQresultStatus(pgres)!=PGRES_COMMAND_OK ) {
if( pgres ) PQclear(pgres);
fprintf(stderr,"error inserting into lastauth table\n");
}
}
if( pgres ) PQclear(pgres);
return(0);
}
void vcreate_vlog_table()
{
vauth_create_table ("vlog", VLOG_TABLE_LAYOUT, 1);
return;
}
#endif
int vauth_crypt(char *user,char *domain,char *clear_pass,struct vqpasswd *vpw)
{
if ( vpw == NULL ) return(-1);
return(strcmp(crypt(clear_pass,vpw->pw_passwd),vpw->pw_passwd));
}
syntax highlighted by Code2HTML, v. 0.9.1