Import Debian changes 0.69.0-2
[hcoop/debian/courier-authlib.git] / authpgsqllib.c
diff --git a/authpgsqllib.c b/authpgsqllib.c
deleted file mode 100644 (file)
index a01ab5f..0000000
+++ /dev/null
@@ -1,1154 +0,0 @@
-/*
-** Copyright 2000-2004 Double Precision, Inc.  See COPYING for
-** distribution information.
-*/
-
-
-#include       <stdio.h>
-#include       <stdlib.h>
-#include       <string.h>
-#include       <unistd.h>
-#include       <ctype.h>
-#include       <sys/types.h>
-#include       <sys/stat.h>
-#include       <libpq-fe.h>
-#include       <time.h>
-
-#include       "authpgsql.h"
-#include       "authpgsqlrc.h"
-#include       "auth.h"
-#include       "courierauthdebug.h"
-
-#define err courier_auth_err
-
-/* tom@minnesota.com */
-#define                MAX_SUBSTITUTION_LEN    32
-#define                SV_BEGIN_MARK           "$("
-#define                SV_END_MARK             ")"
-#define                SV_BEGIN_LEN            ((sizeof(SV_BEGIN_MARK))-1)
-#define                SV_END_LEN              ((sizeof(SV_END_MARK))-1)
-
-static const char rcsid[]="$Id: authpgsqllib.c,v 1.18 2006/10/28 19:22:52 mrsam Exp $";
-
-/* tom@minnesota.com */
-struct var_data {                      
-       const char *name;
-       const char *value;
-       const size_t size;
-       size_t value_length;
-       } ;
-
-/* tom@minnesota.com */
-typedef int (*parsefunc)(const char *, size_t, void *);
-
-static const char *read_env(const char *env)
-{
-static char *pgsqlauth=0;
-static size_t pgsqlauth_size=0;
-size_t i;
-char   *p=0;
-int    l=strlen(env);
-
-       if (!pgsqlauth)
-       {
-       FILE    *f=fopen(AUTHPGSQLRC, "r");
-       struct  stat    buf;
-
-               if (!f) return (0);
-               if (fstat(fileno(f), &buf) ||
-                       (pgsqlauth=malloc(buf.st_size+2)) == 0)
-               {
-                       fclose(f);
-                       return (0);
-               }
-               if (fread(pgsqlauth, buf.st_size, 1, f) != 1)
-               {
-                       free(pgsqlauth);
-                       pgsqlauth=0;
-                       fclose(f);
-                       return (0);
-               }
-               pgsqlauth[pgsqlauth_size=buf.st_size]=0;
-
-               for (i=0; i<pgsqlauth_size; i++)
-                       if (pgsqlauth[i] == '\n')
-                       {       /* tom@minnesota.com */
-                               if (!i || pgsqlauth[i-1] != '\\')
-                               {
-                                       pgsqlauth[i]='\0';
-                               }
-                               else
-                               {
-                                       pgsqlauth[i]=pgsqlauth[i-1]= ' ';
-                               }
-                       }
-               fclose(f);
-       }
-
-       for (i=0; i<pgsqlauth_size; )
-       {
-               p=pgsqlauth+i;
-               if (memcmp(p, env, l) == 0 &&
-                       isspace((int)(unsigned char)p[l]))
-               {
-                       p += l;
-                       while (*p && *p != '\n' &&
-                               isspace((int)(unsigned char)*p))
-                               ++p;
-                       break;
-               }
-
-               while (i < pgsqlauth_size)
-                       if (pgsqlauth[i++] == 0)        break;
-       }
-
-       if (i < pgsqlauth_size)
-               return (p);
-       return (0);
-}
-
-static PGresult *pgresult=0;
-
-static PGconn *pgconn=0;
-
-/*
-static FILE *DEBUG=0;
-*/
-
-static int do_connect()
-{
-const  char *server;
-const  char *userid;
-const  char *password;
-const  char *database;
-const  char *server_port=0;
-const  char *server_opt=0;
-/*
-       if (!DEBUG) {
-               DEBUG=fopen("/tmp/courier.debug","a");
-       }
-       fprintf(DEBUG,"Apro il DB!\n");
-       fflush(DEBUG);
-*/
-
-/*
-** Periodically detect dead connections.
-*/
-       if (pgconn)
-       {
-               static time_t last_time=0;
-               time_t t_check;
-
-               time(&t_check);
-
-               if (t_check < last_time)
-                       last_time=t_check;      /* System clock changed */
-
-               if (t_check < last_time + 60)
-                       return (0);
-
-               last_time=t_check;
-                       
-               if (PQstatus(pgconn) == CONNECTION_OK) return (0);
-
-               DPRINTF("authpgsqllib: PQstatus failed, connection lost");
-               PQfinish(pgconn);
-               pgconn=0;
-       }
-
-       server=read_env("PGSQL_HOST");
-       server_port=read_env("PGSQL_PORT");
-       userid=read_env("PGSQL_USERNAME");
-       password=read_env("PGSQL_PASSWORD");
-       database=read_env("PGSQL_DATABASE");
-       server_opt=read_env("PGSQL_OPT");
-
-/*
-       fprintf(DEBUG,"Letti i parametri!\n");
-       fflush(DEBUG);
-*/
-
-       if (!userid)
-       {
-               err("authpgsql: PGSQL_USERNAME not set in "
-                       AUTHPGSQLRC ".");
-               return (-1);
-       }
-
-       if (!database)
-       {
-               err("authpgsql: PGSQL_DATABASE not set in "
-                       AUTHPGSQLRC ".");
-               return (-1);
-       }
-
-/*
-       fprintf(DEBUG,"Connecting to db:%s:%s\%s user=%s pass=%s\n",server,server_port,database,userid,password);
-       fflush(DEBUG);
-*/
-       pgconn = PQsetdbLogin(server, server_port, server_opt, NULL , database,userid,password);
-
-       if (PQstatus(pgconn) == CONNECTION_BAD)
-       {
-                       err("Connection to server '%s' userid '%s' database '%s' failed.",
-                               server ? server : "<null>",
-                               userid ? userid : "<null>",
-                               database);
-               err("%s", PQerrorMessage(pgconn));
-               pgconn=0;
-               return -1;
-       }
-/*
-       fprintf(DEBUG,"Connected!\n");
-       fflush(DEBUG);
-*/
-
-       return 0;
-
-}
-
-void auth_pgsql_cleanup()
-{
-       if (pgconn)
-       {
-               PQfinish(pgconn);
-               pgconn=0;
-       }
-}
-
-static struct authpgsqluserinfo ui={0, 0, 0, 0, 0, 0, 0, 0};
-
-static void append_username(char *p, const char *username,
-                           const char *defdomain)
-{
-       for (strcpy(p, username); *p; p++)
-               if (*p == '\'' || *p == '"' || *p == '\\' ||
-                   (int)(unsigned char)*p < ' ')
-                       *p=' '; /* No funny business */
-       if (strchr(username, '@') == 0 && defdomain && *defdomain)
-               strcat(strcpy(p, "@"), defdomain);
-}
-
-/* tom@minnesota.com */
-static struct var_data *get_variable (const char *begin, size_t len,
-                                          struct var_data *vdt)
-{
-struct var_data *vdp;
-
-       if (!begin || !vdt) /* should never happend */
-       {
-               err("authpgsql: critical error while "
-                                "parsing substitution variable");
-               return NULL;
-       }
-       if (len < 1)
-       {
-               err("authpgsql: unknown empty substitution "
-                                "variable - aborting");
-               return NULL;
-       }
-       if (len > MAX_SUBSTITUTION_LEN)
-       {
-               err("authpgsql: variable name too long "
-                                "while parsing substitution. "
-                                "name begins with "
-                                SV_BEGIN_MARK
-                                "%.*s...", MAX_SUBSTITUTION_LEN, begin);
-               return NULL;
-       }
-       
-       for (vdp=vdt; vdp->name; vdp++)
-               if (vdp->size == len+1 &&
-                   !strncmp(begin, vdp->name, len))
-               {
-                       if (!vdp->value)
-                               vdp->value = "";
-                       if (!vdp->value_length)         /* length cache */
-                               vdp->value_length = strlen (vdp->value);
-                       return vdp;
-               }
-       
-       err("authpgsql: unknown substitution variable "
-                        SV_BEGIN_MARK
-                        "%.*s"
-                        SV_END_MARK
-                        , (int)len, begin);
-       
-       return NULL;
-}
-
-/* tom@minnesota.com */
-static int ParsePlugin_counter (const char *p, size_t length, void *vp)
-{
-       if (!p || !vp || length < 0)
-       {
-               err("authpgsql: bad arguments while counting "
-                                "query string");
-               return -1;
-       }
-       
-       *((size_t *)vp) += length;
-   
-       return 0;
-}
-
-/* tom@minnesota.com */
-static int ParsePlugin_builder (const char *p, size_t length, void *vp)
-{
-char   **strptr = (char **) vp;
-
-       if (!p || !vp || length < 0)
-       {
-               err("authpgsql: bad arguments while building "
-                                "query string");
-               return -1;
-       }
-       
-       if (!length) return 0;
-       memcpy ((void *) *strptr, (void *) p, length);
-       *strptr += length;
-       
-       return 0;
-}
-
-/* tom@minnesota.com */
-static int parse_core  (const char *source, struct var_data *vdt,
-                       parsefunc outfn, void *result)
-{
-size_t v_size          = 0,
-       t_size          = 0;
-const char     *p, *q, *e,
-               *v_begin, *v_end,
-               *t_begin, *t_end;
-struct var_data        *v_ptr;
-
-       if (!source)
-               source = "";
-       if (!result)
-       {
-               err("authpgsql: no memory allocated for result "
-                                "while parser core was invoked");
-               return -1;
-       }
-       if (!vdt)
-       {
-               err("authpgsql: no substitution table found "
-                                "while parser core was invoked");
-               return -1;
-       }
-       
-       q = source;
-       while ( (p=strstr(q, SV_BEGIN_MARK)) )
-       {
-               e = strstr (p, SV_END_MARK);
-               if (!e)
-               {
-                       err("authpgsql: syntax error in "
-                                        "substitution "
-                                        "- no closing symbol found! "
-                                        "bad variable begins with:"
-                                        "%.*s...", MAX_SUBSTITUTION_LEN, p);
-                       return -1;
-               }
-               
-               /*
-                **
-                **          __________sometext$(variable_name)_________
-                **                    |      |  |           |  
-                **             t_begin' t_end'  `v_begin    `v_end
-                **
-                 */
-
-               v_begin = p+SV_BEGIN_LEN; /* variable field ptr             */
-               v_end   = e-SV_END_LEN;   /* variable field last character  */
-               v_size  = v_end-v_begin+1;/* variable field length          */
-               
-               t_begin = q;              /* text field ptr                 */
-               t_end   = p-1;            /* text field last character      */
-               t_size  = t_end-t_begin+1;/* text field length              */
-
-               /* work on text */
-               if ( (outfn (t_begin, t_size, result)) == -1 )
-                       return -1;
-               
-               /* work on variable */
-               v_ptr = get_variable (v_begin, v_size, vdt);
-               if (!v_ptr) return -1;
-               
-               if ( (outfn (v_ptr->value, v_ptr->value_length, result)) == -1 )
-                       return -1;
-               
-               q = e + 1;
-       }
-
-       /* work on last part of text if any */
-       if (*q != '\0')
-               if ( (outfn (q, strlen(q), result)) == -1 )
-                       return -1;
-
-       return 0;
-}
-
-/* tom@minnesota.com */
-static char *parse_string (const char *source, struct var_data *vdt)
-{
-struct var_data *vdp   = NULL;
-char   *output_buf     = NULL,
-       *pass_buf       = NULL;
-size_t buf_size        = 2;
-
-       if (source == NULL || *source == '\0' || 
-           vdt == NULL    || vdt[0].name == NULL)
-       {
-               err("authpgsql: source clause is empty "
-                                "- this is critical error");
-               return NULL;
-       }
-
-       /* zero var_data length cache - important! */
-       for (vdp=vdt; vdp->name; vdp++)
-               vdp->value_length = 0;
-
-
-       /* phase 1 - count and validate string */
-       if ( (parse_core (source, vdt, &ParsePlugin_counter, &buf_size)) != 0)
-               return NULL;
-
-       /* phase 2 - allocate memory */
-       output_buf = malloc (buf_size);
-       if (!output_buf)
-       {
-               perror ("malloc");
-               return NULL;
-       }
-       pass_buf = output_buf;
-
-       /* phase 3 - build the output string */
-       if ( (parse_core (source, vdt, &ParsePlugin_builder, &pass_buf)) != 0)
-       {
-               free (output_buf);
-               return NULL;
-       }       
-       *pass_buf = '\0';
-       
-       return output_buf;
-}
-
-/* tom@minnesota.com */
-static const char *get_localpart (const char *username)
-{
-size_t         lbuf    = 0;
-const char     *l_end, *p;
-char           *q;
-static char    localpart_buf[130];
-       
-       if (!username || *username == '\0')     return NULL;
-       
-       p = strchr(username,'@');
-       if (p)
-       {
-               if ((p-username) > 128)
-                       return NULL;
-               l_end = p;
-       }
-       else
-       {
-               if ((lbuf = strlen(username)) > 128)
-                       return NULL;
-               l_end = username + lbuf;
-       }
-
-       p=username;
-       q=localpart_buf;
-       
-       while (*p && p != l_end)
-               if (*p == '\"' || *p == '\\' ||
-                   *p == '\'' || (int)(unsigned char)*p < ' ')
-                       p++;
-               else
-                       *q++ = *p++;
-
-       *q = '\0';
-       return localpart_buf;
-}
-
-/* tom@minnesota.com */
-static const char *get_domain (const char *username, const char *defdomain)
-{
-static char    domain_buf[260];
-const char     *p;
-char           *q;
-       
-       if (!username || *username == '\0')     return NULL;
-       p = strchr(username,'@');
-       
-       if (!p || *(p+1) == '\0')
-       {
-               if (defdomain && *defdomain)
-                       return defdomain;
-               else
-                       return NULL;
-       }
-
-       p++;
-       if ((strlen(p)) > 256)
-               return NULL;
-       
-       q = domain_buf;
-       while (*p)
-               if (*p == '\"' || *p == '\\' ||
-                   *p == '\'' || (int)(unsigned char)*p < ' ')
-                       p++;
-               else
-                       *q++ = *p++;
-
-       *q = '\0';
-       return domain_buf;
-}
-
-/* tom@minnesota.com */
-
-static const char *validate_password (const char *password)
-{
-static char pass_buf[2][540]; /* Use two buffers, see parse_chpass_clause */
-static int next_pass=0;
-const char     *p;
-char           *q, *endq;
-       
-       if (!password || *password == '\0' || (strlen(password)) > 256)
-               return NULL;
-       
-       next_pass= 1-next_pass;
-
-       p = password;
-       q = pass_buf[next_pass];
-       endq = q + sizeof pass_buf[next_pass];
-       
-       while (*p && q < endq)
-       {
-               if (*p == '\"' || *p == '\\' || *p == '\'')
-                       *q++ = '\\';
-               *q++ = *p++;
-       }
-       
-       if (q >= endq)
-               return NULL;
-       
-       *q = '\0';
-       return pass_buf[next_pass];
-}
-
-/* tom@minnesota.com */
-static char *parse_select_clause (const char *clause, const char *username,
-                                 const char *defdomain,
-                                 const char *service)
-{
-static struct var_data vd[]={
-           {"local_part",      NULL,   sizeof("local_part"),   0},
-           {"domain",          NULL,   sizeof("domain"),       0},
-           {"service",         NULL,   sizeof("service"),      0},
-           {NULL,              NULL,   0,                      0}};
-
-       if (clause == NULL || *clause == '\0' ||
-           !username || *username == '\0')
-               return NULL;
-       
-       vd[0].value     = get_localpart (username);
-       vd[1].value     = get_domain (username, defdomain);
-       if (!vd[0].value || !vd[1].value)
-               return NULL;
-       vd[2].value     = service;
-
-       return (parse_string (clause, vd));
-}
-
-/* tom@minnesota.com */
-static char *parse_chpass_clause (const char *clause, const char *username,
-                                 const char *defdomain, const char *newpass,
-                                 const char *newpass_crypt)
-{
-static struct var_data vd[]={
-           {"local_part",      NULL,   sizeof("local_part"),           0},
-           {"domain",          NULL,   sizeof("domain"),               0},
-           {"newpass",         NULL,   sizeof("newpass"),              0},
-           {"newpass_crypt",   NULL,   sizeof("newpass_crypt"),        0},
-           {NULL,              NULL,   0,                              0}};
-
-       if (clause == NULL || *clause == '\0'           ||
-           !username || *username == '\0'              ||
-           !newpass || *newpass == '\0'                ||
-           !newpass_crypt || *newpass_crypt == '\0')   return NULL;
-
-       vd[0].value     = get_localpart (username);
-       vd[1].value     = get_domain (username, defdomain);
-       vd[2].value     = validate_password (newpass);
-       vd[3].value     = validate_password (newpass_crypt);
-       
-       if (!vd[0].value || !vd[1].value ||
-           !vd[2].value || !vd[3].value)       return NULL;
-
-       return (parse_string (clause, vd));
-}
-
-static void initui()
-{
-
-       if (ui.username)
-               free(ui.username);
-       if (ui.cryptpw)
-               free(ui.cryptpw);
-       if (ui.clearpw)
-               free(ui.clearpw);
-       if (ui.home)
-               free(ui.home);
-       if (ui.maildir)
-               free(ui.maildir);
-       if (ui.quota)
-               free(ui.quota);
-       if (ui.fullname)
-               free(ui.fullname);
-       if (ui.options)
-               free(ui.options);
-       memset(&ui, 0, sizeof(ui));
-}
-
-struct authpgsqluserinfo *auth_pgsql_getuserinfo(const char *username,
-                                                const char *service)
-{
-const char *defdomain, *select_clause;
-char   *querybuf, *p;
-
-static const char query[]=
-       "SELECT %s, %s, %s, %s, %s, %s, %s, %s, %s, %s FROM %s WHERE %s = '";
-
-       if (do_connect())       return (0);
-
-       initui();
-
-/*
-       fprintf(DEBUG,"1Leggo parametri\n");
-       fflush(DEBUG);
-*/
-       select_clause=read_env("PGSQL_SELECT_CLAUSE");
-       defdomain=read_env("DEFAULT_DOMAIN");
-       if (!defdomain) defdomain="";
-
-       if (!select_clause) /* tom@minnesota.com */
-       {
-               const char      *user_table,
-                               *crypt_field,
-                               *clear_field,
-                               *name_field,
-                               *uid_field,
-                               *gid_field,
-                               *login_field,
-                               *home_field,
-                               *maildir_field,
-                               *quota_field,
-                               *options_field,
-                               *where_clause;
-
-               user_table=read_env("PGSQL_USER_TABLE");
-
-               if (!user_table)
-               {
-                       err("authpgsql: PGSQL_USER_TABLE not set in "
-                               AUTHPGSQLRC ".");
-                       return (0);
-               }
-
-               crypt_field=read_env("PGSQL_CRYPT_PWFIELD");
-               clear_field=read_env("PGSQL_CLEAR_PWFIELD");
-               name_field=read_env("PGSQL_NAME_FIELD");
-
-               if (!crypt_field && !clear_field)
-               {
-                       err("authpgsql: PGSQL_CRYPT_PWFIELD and "
-                               "PGSQL_CLEAR_PWFIELD not set in " AUTHPGSQLRC ".");
-                       return (0);
-               }
-               if (!crypt_field) crypt_field="''";
-               if (!clear_field) clear_field="''";
-               if (!name_field) name_field="''";
-
-               uid_field = read_env("PGSQL_UID_FIELD");
-               if (!uid_field) uid_field = "uid";
-
-               gid_field = read_env("PGSQL_GID_FIELD");
-               if (!gid_field) gid_field = "gid";
-
-               login_field = read_env("PGSQL_LOGIN_FIELD");
-               if (!login_field) login_field = "id";
-
-               home_field = read_env("PGSQL_HOME_FIELD");
-               if (!home_field) home_field = "home";
-
-               maildir_field=read_env(service && strcmp(service, "courier")==0
-                                      ? "PGSQL_DEFAULTDELIVERY"
-                                      : "PGSQL_MAILDIR_FIELD");
-               if (!maildir_field) maildir_field="''";
-
-               quota_field=read_env("PGSQL_QUOTA_FIELD");
-               if (!quota_field) quota_field="''"; 
-
-               options_field=read_env("PGSQL_AUXOPTIONS_FIELD");
-               if (!options_field) options_field="''"; 
-
-               where_clause=read_env("PGSQL_WHERE_CLAUSE");
-               if (!where_clause) where_clause = "";
-
-               querybuf=malloc(sizeof(query) + 100
-                               + 2 * strlen(login_field)
-                               + strlen(crypt_field)
-                               + strlen(clear_field)
-                               + strlen(uid_field) + strlen(gid_field)
-                               + strlen(home_field)
-                               + strlen(maildir_field)
-                               + strlen(quota_field)
-                               + strlen(name_field)
-                               + strlen(options_field)
-                               + strlen(user_table)
-                               + strlen(username)
-                               + strlen(defdomain)
-                               + strlen(where_clause));
-
-               if (!querybuf)
-               {
-                       perror("malloc");
-                       return (0);
-               }
-
-               sprintf(querybuf, query, login_field, crypt_field, clear_field,
-                       uid_field, gid_field, home_field, maildir_field,
-                       quota_field,
-                       name_field,
-                       options_field,
-                       user_table, login_field);
-               p=querybuf+strlen(querybuf);
-
-               append_username(p, username, defdomain);
-               strcat(p, "'");
-               
-               if (strcmp(where_clause, "")) {
-                       strcat(p, " AND (");
-                       strcat(p, where_clause);
-                       strcat(p, ")");
-               }
-       }
-       else
-       {
-               /* tom@minnesota.com */
-               querybuf=parse_select_clause (select_clause, username,
-                                             defdomain, service);
-               if (!querybuf)
-               {
-                       DPRINTF("authpgsql: parse_select_clause failed (DEFAULT_DOMAIN not defined?)");
-                       return 0;
-               }
-       }
-
-       DPRINTF("SQL query: %s", querybuf);
-       pgresult = PQexec(pgconn, querybuf);
-       if (!pgresult || PQresultStatus(pgresult) != PGRES_TUPLES_OK)
-       {
-               DPRINTF("PQexec failed, reconnecting: %s", PQerrorMessage(pgconn));
-               if (pgresult) PQclear(pgresult);
-       
-               /* <o.blasnik@nextra.de> */
-
-               auth_pgsql_cleanup();
-
-               if (do_connect())
-               {
-                       free(querybuf);
-                       return (0);
-               }
-
-               pgresult = PQexec(pgconn, querybuf);
-               if (!pgresult || PQresultStatus(pgresult) != PGRES_TUPLES_OK)
-               {
-                       DPRINTF("PQexec failed second time, giving up: %s", PQerrorMessage(pgconn));
-                       if (pgresult) PQclear(pgresult);
-                       free(querybuf);
-                       auth_pgsql_cleanup();
-                       /* Server went down, that's OK,
-                       ** try again next time.
-                       */
-                       return (0);
-               }
-       }
-       free(querybuf);
-
-               if (PQntuples(pgresult)>0)
-               {
-               char *t, *endp;
-               int     num_fields = PQnfields(pgresult);
-
-                       if (num_fields < 6)
-                       {
-                               DPRINTF("incomplete row, only %d fields returned",
-                                       num_fields);
-                               PQclear(pgresult);
-                               return 0;
-                       }
-
-                       t=PQgetvalue(pgresult,0,0);
-                       if (t && t[0]) ui.username=strdup(t);
-                       t=PQgetvalue(pgresult,0,1);
-                       if (t && t[0]) ui.cryptpw=strdup(t);
-                       t=PQgetvalue(pgresult,0,2);
-                       if (t && t[0]) ui.clearpw=strdup(t);
-                       t=PQgetvalue(pgresult,0,3);
-                       if (!t || !t[0] ||
-                          (ui.uid=strtol(t, &endp, 10), endp[0] != '\0'))
-                       {
-                               DPRINTF("invalid value for uid: '%s'",
-                                       t ? t : "<null>");
-                               PQclear(pgresult);
-                               return 0;
-                       }
-                       t=PQgetvalue(pgresult,0,4);
-                       if (!t || !t[0] ||
-                          (ui.gid=strtol(t, &endp, 10), endp[0] != '\0'))
-                       {
-                               DPRINTF("invalid value for gid: '%s'",
-                                       t ? t : "<null>");
-                               PQclear(pgresult);
-                               return 0;
-                       }
-                       t=PQgetvalue(pgresult,0,5);
-                       if (t && t[0])
-                               ui.home=strdup(t);
-                       else
-                       {
-                               DPRINTF("required value for 'home' (column 6) is missing");
-                               PQclear(pgresult);
-                               return 0;
-                       }
-                       t=num_fields > 6 ? PQgetvalue(pgresult,0,6) : 0;
-                       if (t && t[0]) ui.maildir=strdup(t);
-                       t=num_fields > 7 ? PQgetvalue(pgresult,0,7) : 0;
-                       if (t && t[0]) ui.quota=strdup(t);
-                       t=num_fields > 8 ? PQgetvalue(pgresult,0,8) : 0;
-                       if (t && t[0]) ui.fullname=strdup(t);
-                       t=num_fields > 9 ? PQgetvalue(pgresult,0,9) : 0;
-                       if (t && t[0]) ui.options=strdup(t);
-               }
-               else
-               {
-                       DPRINTF("zero rows returned");
-                       PQclear(pgresult);
-                       return (&ui);
-               }
-               PQclear(pgresult);
-
-       return (&ui);
-}
-
-int auth_pgsql_setpass(const char *user, const char *pass,
-                      const char *oldpass)
-{
-       char *newpass_crypt;
-       const char *p;
-       int l;
-       char *sql_buf;
-       const char *comma;
-       int rc=0;
-
-       const char *clear_field=NULL;
-       const char *crypt_field=NULL;
-       const char *defdomain=NULL;
-       const char *where_clause=NULL;
-       const char *user_table=NULL;
-       const char *login_field=NULL;
-       const char *chpass_clause=NULL; /* tom@minnesota.com */
-
-       if (!pgconn)
-               return (-1);
-
-
-       if (!(newpass_crypt=authcryptpasswd(pass, oldpass)))
-               return (-1);
-
-       for (l=0, p=pass; *p; p++)
-       {
-               if ((int)(unsigned char)*p < ' ')
-               {
-                       free(newpass_crypt);
-                       return (-1);
-               }
-               if (*p == '"' || *p == '\\')
-                       ++l;
-               ++l;
-       }
-
-       /* tom@minnesota.com */
-       chpass_clause=read_env("PGSQL_CHPASS_CLAUSE");
-       defdomain=read_env("DEFAULT_DOMAIN");
-       user_table=read_env("PGSQL_USER_TABLE");
-       if (!chpass_clause)
-       {
-               login_field = read_env("PGSQL_LOGIN_FIELD");
-               if (!login_field) login_field = "id";
-               crypt_field=read_env("PGSQL_CRYPT_PWFIELD");
-               clear_field=read_env("PGSQL_CLEAR_PWFIELD");
-               where_clause=read_env("PGSQL_WHERE_CLAUSE");
-               sql_buf=malloc(strlen(crypt_field ? crypt_field:"")
-                              + strlen(clear_field ? clear_field:"")
-                              + strlen(defdomain ? defdomain:"")
-                              + strlen(login_field) + l + strlen(newpass_crypt)
-                              + strlen(user_table)
-                              + strlen(where_clause ? where_clause:"")
-                              + 200);
-       }
-       else
-       {
-               sql_buf=parse_chpass_clause(chpass_clause,
-                                           user,
-                                           defdomain,
-                                           pass,
-                                           newpass_crypt);
-       }
-
-       if (!sql_buf)
-       {
-               free(newpass_crypt);
-               return (-1);
-       }
-
-       if (!chpass_clause) /* tom@minnesota.com */
-       {
-               sprintf(sql_buf, "UPDATE %s SET", user_table);
-
-               comma="";
-
-               if (clear_field && *clear_field)
-               {
-                       char *q;
-
-                       strcat(strcat(strcat(sql_buf, " "), clear_field),
-                              "='");
-
-                       q=sql_buf+strlen(sql_buf);
-                       while (*pass)
-                       {
-                               if (*pass == '"' || *pass == '\\')
-                                       *q++= '\\';
-                               *q++ = *pass++;
-                       }
-                       strcpy(q, "'");
-                       comma=", ";
-               }
-
-               if (crypt_field && *crypt_field)
-               {
-                       strcat(strcat(strcat(strcat(strcat(strcat(sql_buf, comma),
-                                                          " "),
-                                                   crypt_field),
-                                            "='"),
-                                     newpass_crypt),
-                              "'");
-               }
-               free(newpass_crypt);
-
-               strcat(strcat(strcat(sql_buf, " WHERE "),
-                             login_field),
-                      "='");
-
-               append_username(sql_buf+strlen(sql_buf), user, defdomain);
-
-               strcat(sql_buf, "'");
-
-               if (where_clause && *where_clause)
-               {
-                       strcat(sql_buf, " AND (");
-                       strcat(sql_buf, where_clause);
-                       strcat(sql_buf, ")");
-               }
-
-       } /* end of: if (!chpass_clause) */
-
-       if (courier_authdebug_login_level >= 2)
-       {
-               DPRINTF("setpass SQL: %s", sql_buf);
-       }
-       pgresult=PQexec (pgconn, sql_buf);
-       if (!pgresult || PQresultStatus(pgresult) != PGRES_COMMAND_OK)
-       {
-               DPRINTF("setpass SQL failed");
-               rc= -1;
-               auth_pgsql_cleanup();
-       }
-       PQclear(pgresult);
-       free(sql_buf);
-       return (rc);
-}
-
-void auth_pgsql_enumerate( void(*cb_func)(const char *name,
-                                         uid_t uid,
-                                         gid_t gid,
-                                         const char *homedir,
-                                         const char *maildir,
-                                         const char *options,
-                                         void *void_arg),
-                          void *void_arg)
-{
-       const char *select_clause, *defdomain;
-       char    *querybuf, *p;
-
-static const char query[]=
-       "SELECT %s, %s, %s, %s, %s, %s FROM %s WHERE 1=1";
-int i,n;
-
-       if (do_connect())       return;
-
-       initui();
-
-       select_clause=read_env("PGSQL_ENUMERATE_CLAUSE");
-       defdomain=read_env("DEFAULT_DOMAIN");
-       if (!defdomain || !defdomain[0])
-               defdomain="*"; /* otherwise parse_select_clause fails */
-
-       if (!select_clause) /* tom@minnesota.com */
-       {
-               const char      *user_table,
-                               *uid_field,
-                               *gid_field,
-                               *login_field,
-                               *home_field,
-                               *maildir_field,
-                               *options_field,
-                               *where_clause;
-
-               user_table=read_env("PGSQL_USER_TABLE");
-
-               if (!user_table)
-               {
-                       err("authpgsql: PGSQL_USER_TABLE not set in "
-                              AUTHPGSQLRC ".");
-                       return;
-               }
-
-               uid_field = read_env("PGSQL_UID_FIELD");
-               if (!uid_field) uid_field = "uid";
-
-               gid_field = read_env("PGSQL_GID_FIELD");
-               if (!gid_field) gid_field = "gid";
-
-               login_field = read_env("PGSQL_LOGIN_FIELD");
-               if (!login_field) login_field = "id";
-
-               home_field = read_env("PGSQL_HOME_FIELD");
-               if (!home_field) home_field = "home";
-
-               maildir_field=read_env("PGSQL_MAILDIR_FIELD");
-               if (!maildir_field) maildir_field="''";
-
-               options_field=read_env("PGSQL_AUXOPTIONS_FIELD");
-               if (!options_field) options_field="''";
-
-               where_clause=read_env("PGSQL_WHERE_CLAUSE");
-               if (!where_clause) where_clause = "";
-
-               querybuf=malloc(sizeof(query) + 100
-                               + strlen(login_field)
-                               + strlen(uid_field) + strlen(gid_field)
-                               + strlen(home_field)
-                               + strlen(maildir_field)
-                               + strlen(options_field)
-                               + strlen(user_table)
-                               + strlen(where_clause));
-
-               if (!querybuf)
-               {
-                       perror("malloc");
-                       return;
-               }
-
-               sprintf(querybuf, query, login_field, 
-                       uid_field, gid_field, home_field, maildir_field,
-                       options_field, user_table);
-               p=querybuf+strlen(querybuf);
-               
-               if (strcmp(where_clause, "")) {
-                       strcat(p, " AND (");
-                       strcat(p, where_clause);
-                       strcat(p, ")");
-               }
-       }
-       else
-       {
-               /* tom@minnesota.com */
-               querybuf=parse_select_clause (select_clause, "*",
-                                             defdomain, "enumerate");
-               if (!querybuf)
-               {
-                       DPRINTF("authpgsql: parse_select_clause failed");
-                       return;
-               }
-       }
-       DPRINTF("authpgsql: enumerate query: %s", querybuf);
-
-       if (PQsendQuery(pgconn, querybuf) == 0)
-       {
-               DPRINTF("PQsendQuery failed, reconnecting: %s",PQerrorMessage(pgconn));
-
-               auth_pgsql_cleanup();
-
-               if (do_connect())
-               {
-                       free(querybuf);
-                       return;
-               }
-
-               if (PQsendQuery(pgconn, querybuf) == 0)
-               {
-                       DPRINTF("PQsendQuery failed second time, giving up: %s",PQerrorMessage(pgconn));
-                       free(querybuf);
-                       auth_pgsql_cleanup();
-                       return;
-               }
-       }
-       free(querybuf);
-
-       while ((pgresult = PQgetResult(pgconn)) != NULL)
-       {
-               if (PQresultStatus(pgresult) != PGRES_TUPLES_OK)
-               {
-                       DPRINTF("pgsql error during enumeration: %s",PQerrorMessage(pgconn));
-                       PQclear(pgresult);
-                       return;
-               }
-
-               for (n=PQntuples(pgresult), i=0; i<n; i++)
-               {
-                       const char *username;
-                       uid_t uid;
-                       gid_t gid;
-                       const char *homedir;
-                       const char *maildir;
-                       const char *options;
-
-                       username=PQgetvalue(pgresult,i,0);
-                       uid=atol(PQgetvalue(pgresult,i,1));
-                       gid=atol(PQgetvalue(pgresult,i,2));
-                       homedir=PQgetvalue(pgresult,i,3);
-                       maildir=PQgetvalue(pgresult,i,4);
-                       options=PQgetvalue(pgresult,i,5);
-
-                       if (!username || !*username || !homedir || !*homedir)
-                               continue;
-
-                       if (maildir && !*maildir)
-                               maildir=NULL;
-
-                       (*cb_func)(username, uid, gid, homedir,
-                                  maildir, options, void_arg);
-
-               }
-               PQclear(pgresult);
-       }
-       /* FIXME: is it possible that a NULL result from PQgetResult could
-          indicate an error rather than EOF? The documentation is not clear */
-       (*cb_func)(NULL, 0, 0, NULL, NULL, NULL, void_arg);
-}