/*
Copyright (C) 1999-2004 IC & S dbmail@ic-s.nl
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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/**
* \file authsql.c
* \brief implements SQL authentication. Prototypes of these functions
* can be found in auth.h .
* \author IC&S (http://www.ic-s.nl)
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "dbmail.h"
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#ifdef HAVE_CRYPT_H
#include <crypt.h>
#endif
extern db_param_t _db_params;
#define DBPFX _db_params.pfx
/**
* used for query strings
*/
#define AUTH_QUERY_SIZE 1024
static char __auth_query_data[AUTH_QUERY_SIZE];
/* string to be returned by auth_getencryption() */
#define _DESCSTRLEN 50
static char __auth_encryption_desc_string[_DESCSTRLEN];
/**
* \brief perform a authentication query
* \param thequery the query
* \return
* - -1 on error
* - 0 otherwise
*/
static int __auth_query(const char *thequery);
int auth_connect()
{
/* this function is only called after a connection has been made
* if, in the future this is not the case, db.h should export a
* function that enables checking for the database connection
*/
return 0;
}
int auth_disconnect()
{
return 0;
}
int auth_user_exists(const char *username, u64_t * user_idnr)
{
return db_user_exists(username, user_idnr);
}
GList * auth_get_known_users(void)
{
u64_t i;
GList * users = NULL;
snprintf(__auth_query_data, AUTH_QUERY_SIZE,
"SELECT userid FROM %susers ORDER BY userid",DBPFX);
if (__auth_query(__auth_query_data) == -1) {
trace(TRACE_ERROR, "%s,%s: could not retrieve user list",
__FILE__, __func__);
return NULL;
}
for (i = 0; i < (unsigned) db_num_rows(); i++)
users = g_list_append(users, g_strdup(db_get_result(i, 0)));
db_free_result();
return users;
}
int auth_getclientid(u64_t user_idnr, u64_t * client_idnr)
{
const char *query_result;
assert(client_idnr != NULL);
*client_idnr = 0;
snprintf(__auth_query_data, AUTH_QUERY_SIZE,
"SELECT client_idnr FROM %susers WHERE user_idnr = '%llu'",DBPFX,
user_idnr);
if (__auth_query(__auth_query_data) == -1) {
trace(TRACE_ERROR,
"%s,%s: could not retrieve client id for user [%llu]\n",
__FILE__, __func__, user_idnr);
return -1;
}
if (db_num_rows() == 0) {
db_free_result();
return 1;
}
query_result = db_get_result(0, 0);
*client_idnr = (query_result) ? strtoull(query_result, 0, 10) : 0;
db_free_result();
return 1;
}
int auth_getmaxmailsize(u64_t user_idnr, u64_t * maxmail_size)
{
const char *query_result;
assert(maxmail_size != NULL);
*maxmail_size = 0;
snprintf(__auth_query_data, AUTH_QUERY_SIZE,
"SELECT maxmail_size FROM %susers WHERE user_idnr = '%llu'",DBPFX,
user_idnr);
if (__auth_query(__auth_query_data) == -1) {
trace(TRACE_ERROR,
"%s,%s: could not retrieve client id for user [%llu]",
__FILE__, __func__, user_idnr);
return -1;
}
if (db_num_rows() == 0) {
db_free_result();
return 0;
}
query_result = db_get_result(0, 0);
if (query_result)
*maxmail_size = strtoull(query_result, NULL, 10);
else
return -1;
db_free_result();
return 1;
}
char *auth_getencryption(u64_t user_idnr)
{
const char *query_result;
__auth_encryption_desc_string[0] = '\0';
if (user_idnr == 0) {
/* assume another function returned an error code (-1)
* or this user does not exist (0)
*/
trace(TRACE_ERROR, "%s,%s: got (%lld) as userid",
__FILE__, __func__, user_idnr);
return __auth_encryption_desc_string; /* return empty */
}
snprintf(__auth_query_data, AUTH_QUERY_SIZE,
"SELECT encryption_type FROM %susers WHERE user_idnr = '%llu'",DBPFX,
user_idnr);
if (__auth_query(__auth_query_data) == -1) {
trace(TRACE_ERROR,
"%s,%s: could not retrieve encryption type for user [%llu]",
__FILE__, __func__, user_idnr);
return __auth_encryption_desc_string; /* return empty */
}
if (db_num_rows() == 0) {
db_free_result();
return __auth_encryption_desc_string; /* return empty */
}
query_result = db_get_result(0, 0);
strncpy(__auth_encryption_desc_string, query_result, _DESCSTRLEN);
db_free_result();
return __auth_encryption_desc_string;
}
int auth_check_user_ext(const char *username, struct dm_list *userids, struct dm_list *fwds, int checks)
{
int occurences = 0;
void *saveres;
u64_t counter;
const char *query_result;
char *endptr;
u64_t id;
unsigned num_rows;
char *escaped_username;
if (checks > 20) {
trace(TRACE_ERROR,"%s,%s: too many checks. Possible loop detected.",
__FILE__, __func__);
return 0;
}
saveres = db_get_result_set();
db_set_result_set(NULL);
trace(TRACE_DEBUG, "%s,%s: checking user [%s] in alias table",
__FILE__, __func__, username);
if (!(escaped_username = (char *) dm_malloc(strlen(username) * 2 + 1))) {
trace(TRACE_ERROR, "%s,%s: out of memory allocating "
"escaped username", __FILE__, __func__);
return -1;
}
db_escape_string(escaped_username, username, strlen(username));
snprintf(__auth_query_data, AUTH_QUERY_SIZE,
"SELECT deliver_to FROM %saliases "
"WHERE lower(alias) = lower('%s') "
"AND lower(alias) <> lower(deliver_to)",
DBPFX, escaped_username);
dm_free(escaped_username);
trace(TRACE_DEBUG, "%s,%s: checks [%d]", __FILE__, __func__,
checks);
if (__auth_query(__auth_query_data) == -1) {
db_set_result_set(saveres);
return 0;
}
num_rows = db_num_rows();
if (num_rows == 0) {
if (checks > 0) {
/* found the last one, this is the deliver to
* but checks needs to be bigger then 0 because
* else it could be the first query failure */
id = strtoull(username, &endptr, 10);
if (*endptr == 0)
dm_list_nodeadd(userids, &id, sizeof(id));
/* numeric deliver-to --> this is a userid */
else
dm_list_nodeadd(fwds, username,
strlen(username) + 1);
trace(TRACE_DEBUG,
"%s,%s: adding [%s] to deliver_to address",
__FILE__, __func__, username);
db_free_result();
db_set_result_set(saveres);
return 1;
} else {
trace(TRACE_DEBUG,
"%s,%s: user %s not in aliases table",
__FILE__, __func__, username);
db_free_result();
db_set_result_set(saveres);
return 0;
}
}
trace(TRACE_DEBUG, "%s,%s: into checking loop", __FILE__,
__func__);
if (num_rows > 0) {
for (counter = 0; counter < num_rows; counter++) {
/* do a recursive search for deliver_to */
query_result = db_get_result(counter, 0);
trace(TRACE_DEBUG, "%s,%s: checking user %s to %s",
__FILE__, __func__, username, query_result);
occurences += auth_check_user_ext(query_result, userids, fwds, checks+1 );
}
}
db_free_result();
db_set_result_set(saveres);
return occurences;
}
int __auth_query(const char *thequery)
{
/* start using authentication result */
if (db_query(thequery) < 0) {
trace(TRACE_ERROR, "%s,%s: error executing query",
__FILE__, __func__);
return -1;
}
return 0;
}
int auth_adduser(const char *username, const char *password, const char *enctype,
u64_t clientid, u64_t maxmail, u64_t * user_idnr)
{
*user_idnr=0;
return db_user_create(username, password, enctype, clientid, maxmail, user_idnr);
}
int auth_delete_user(const char *username)
{
return db_user_delete(username);
}
int auth_change_username(u64_t user_idnr, const char *new_name)
{
return db_user_rename(user_idnr, new_name);
}
int auth_change_password(u64_t user_idnr, const char *new_pass,
const char *enctype)
{
char escapedpass[AUTH_QUERY_SIZE];
if (strlen(new_pass) >= AUTH_QUERY_SIZE) {
trace(TRACE_ERROR, "%s,%s: new password length is insane",
__FILE__, __func__);
return -1;
}
db_escape_string(escapedpass, new_pass, strlen(new_pass));
snprintf(__auth_query_data, AUTH_QUERY_SIZE,
"UPDATE %susers SET passwd = '%s', encryption_type = '%s' "
" WHERE user_idnr='%llu'", DBPFX,
escapedpass, enctype ? enctype : "", user_idnr);
if (__auth_query(__auth_query_data) == -1) {
trace(TRACE_ERROR,
"%s,%s: could not change passwd for user [%llu]",
__FILE__, __func__, user_idnr);
return -1;
}
return 0;
}
int auth_change_clientid(u64_t user_idnr, u64_t new_cid)
{
snprintf(__auth_query_data, AUTH_QUERY_SIZE,
"UPDATE %susers SET client_idnr = '%llu' "
"WHERE user_idnr='%llu'",
DBPFX, new_cid, user_idnr);
if (__auth_query(__auth_query_data) == -1) {
trace(TRACE_ERROR,
"%s,%s: could not change client id for user [%llu]",
__FILE__, __func__, user_idnr);
return -1;
}
return 0;
}
int auth_change_mailboxsize(u64_t user_idnr, u64_t new_size)
{
return db_change_mailboxsize(user_idnr, new_size);
}
int auth_validate(clientinfo_t *ci, char *username, char *password, u64_t * user_idnr)
{
const char *query_result;
int is_validated = 0;
char salt[13];
char cryptres[35];
char real_username[DM_USERNAME_LEN];
char *md5str;
int result;
assert(user_idnr != NULL);
*user_idnr = 0;
if (username == NULL || password == NULL) {
trace(TRACE_DEBUG, "%s,%s: username or password is NULL",
__FILE__, __func__);
return 0;
}
/* the shared mailbox user should not log in! */
if (strcmp(username, SHARED_MAILBOX_USERNAME) == 0)
return 0;
strncpy(real_username, username, DM_USERNAME_LEN);
if (db_use_usermap()) { /* use usermap */
result = db_usermap_resolve(ci, username, real_username);
if (result == DM_EGENERAL)
return 0;
if (result == DM_EQUERY)
return DM_EQUERY;
}
/* lookup the user_idnr */
if (auth_user_exists(real_username, user_idnr) == DM_EQUERY)
return DM_EQUERY;
snprintf(__auth_query_data, AUTH_QUERY_SIZE,
"SELECT user_idnr, passwd, encryption_type FROM %susers "
"WHERE user_idnr = '%llu'", DBPFX, *user_idnr);
if (__auth_query(__auth_query_data) == -1) {
trace(TRACE_ERROR,
"%s,%s: could not select user information", __FILE__,
__func__);
return -1;
}
if (db_num_rows() == 0) {
db_free_result();
return 0;
}
/* get encryption type */
query_result = db_get_result(0, 2);
if (!query_result || strcasecmp(query_result, "") == 0) {
trace(TRACE_DEBUG,
"%s,%s: validating using plaintext passwords",
__FILE__, __func__);
/* get password from database */
query_result = db_get_result(0, 1);
is_validated = (strcmp(query_result, password) == 0) ? 1 : 0;
} else if (strcasecmp(query_result, "crypt") == 0) {
trace(TRACE_DEBUG,
"%s,%s: validating using crypt() encryption",
__FILE__, __func__);
query_result = db_get_result(0, 1);
is_validated = (strcmp((const char *) crypt(password, query_result), /* Flawfinder: ignore */
query_result) == 0) ? 1 : 0;
} else if (strcasecmp(query_result, "md5") == 0) {
/* get password */
query_result = db_get_result(0, 1);
if (strncmp(query_result, "$1$", 3)) {
trace(TRACE_DEBUG,
"%s,%s: validating using MD5 digest comparison",
__FILE__, __func__);
/* redundant statement: query_result = db_get_result(0, 1); */
md5str = dm_md5((unsigned char *)password);
is_validated = (strncmp(md5str, query_result, 32) == 0) ? 1 : 0;
dm_free(md5str);
} else {
trace(TRACE_DEBUG,
"%s, %s: validating using MD5 hash comparison",
__FILE__, __func__);
strncpy(salt, query_result, 12);
strncpy(cryptres, (char *) crypt(password, query_result), 34); /* Flawfinder: ignore */
trace(TRACE_DEBUG, "%s,%s: salt : %s", __FILE__, __func__, salt);
trace(TRACE_DEBUG, "%s,%s: hash : %s", __FILE__, __func__, query_result);
trace(TRACE_DEBUG, "%s,%s: crypt(): %s", __FILE__, __func__, cryptres);
is_validated = (strncmp(query_result, cryptres, 34) == 0) ? 1 : 0;
}
} else if (strcasecmp(query_result, "md5sum") == 0) {
trace(TRACE_DEBUG,
"%s,%s: validating using MD5 digest comparison",
__FILE__, __func__);
query_result = db_get_result(0, 1);
md5str = dm_md5((unsigned char *)password);
is_validated = (strncmp(md5str, query_result, 32) == 0) ? 1 : 0;
dm_free(md5str);
} else if (strcasecmp(query_result, "md5base64") == 0) {
trace(TRACE_DEBUG,
"%s,%s: validating using MD5 digest base64 comparison",
__FILE__, __func__);
query_result = db_get_result(0, 1);
md5str = dm_md5_base64((unsigned char *)password);
is_validated = (strncmp(md5str, query_result, 32) == 0) ? 1 : 0;
dm_free(md5str);
}
if (is_validated) {
db_user_log_login(*user_idnr);
} else {
*user_idnr = 0;
}
db_free_result();
return (is_validated ? 1 : 0);
}
u64_t auth_md5_validate(clientinfo_t *ci UNUSED, char *username,
unsigned char *md5_apop_he, char *apop_stamp)
{
/* returns useridnr on OK, 0 on validation failed, -1 on error */
char *checkstring;
unsigned char *md5_apop_we;
u64_t user_idnr;
const char *query_result;
/* lookup the user_idnr */
if (auth_user_exists(username, &user_idnr) == DM_EQUERY)
return DM_EQUERY;
snprintf(__auth_query_data, AUTH_QUERY_SIZE,
"SELECT passwd,user_idnr FROM %susers WHERE "
"user_idnr = '%llu'", DBPFX, user_idnr);
if (__auth_query(__auth_query_data) == -1) {
trace(TRACE_ERROR, "%s,%s: error calling __auth_query()",
__FILE__, __func__);
return -1;
}
if (db_num_rows() < 1) {
/* no such user found */
db_free_result();
return 0;
}
/* now authenticate using MD5 hash comparisation */
query_result = db_get_result(0, 0); /* value holds the password */
trace(TRACE_DEBUG, "%s,%s: apop_stamp=[%s], userpw=[%s]",
__FILE__, __func__, apop_stamp, query_result);
memtst((checkstring = (char *) dm_malloc(strlen(apop_stamp) +
strlen(query_result) + 2)) == NULL);
snprintf(checkstring,
strlen(apop_stamp) + strlen(query_result) + 2, "%s%s",
apop_stamp, query_result);
md5_apop_we = dm_md5((unsigned char *)checkstring);
trace(TRACE_DEBUG,
"%s,%s: checkstring for md5 [%s] -> result [%s]", __FILE__,
__func__, checkstring, md5_apop_we);
trace(TRACE_DEBUG,
"%s,%s: validating md5_apop_we=[%s] md5_apop_he=[%s]",
__FILE__, __func__, md5_apop_we, md5_apop_he);
if (strcmp((const char *)md5_apop_he, (const char *)md5_apop_we) == 0) {
trace(TRACE_MESSAGE,
"%s,%s: user [%s] is validated using APOP", __FILE__,
__func__, username);
/* get user idnr */
query_result = db_get_result(0, 1);
user_idnr =
(query_result) ? strtoull(query_result, NULL, 10) : 0;
db_free_result();
dm_free(md5_apop_we);
dm_free(checkstring);
db_user_log_login(user_idnr);
return user_idnr;
}
trace(TRACE_MESSAGE, "%s,%s: user [%s] could not be validated",
__FILE__, __func__, username);
db_free_result();
dm_free(md5_apop_we);
dm_free(checkstring);
return 0;
}
char *auth_get_userid(u64_t user_idnr)
{
const char *query_result;
char *returnid = NULL;
snprintf(__auth_query_data, AUTH_QUERY_SIZE,
"SELECT userid FROM %susers WHERE user_idnr = '%llu'",
DBPFX, user_idnr);
if (__auth_query(__auth_query_data) == -1) {
trace(TRACE_ERROR, "%s,%s: query failed",
__FILE__, __func__);
return 0;
}
if (db_num_rows() < 1) {
trace(TRACE_DEBUG, "%s,%s: user has no username?",
__FILE__, __func__);
db_free_result();
return 0;
}
query_result = db_get_result(0, 0);
if (query_result) {
trace(TRACE_DEBUG, "%s,%s: query_result = %s",
__FILE__, __func__, query_result);
if (!(returnid =
(char *) dm_malloc(strlen(query_result) + 1))) {
trace(TRACE_ERROR, "%s,%s: out of memory",
__FILE__, __func__);
db_free_result();
return NULL;
}
strncpy(returnid, query_result, strlen(query_result) + 1);
}
db_free_result();
trace(TRACE_DEBUG, "%s,%s: returning %s as returnid", __FILE__,
__func__, returnid);
return returnid;
}
int auth_check_userid(u64_t user_idnr)
{
snprintf(__auth_query_data, AUTH_QUERY_SIZE,
"SELECT userid FROM %susers WHERE user_idnr = '%llu'",
DBPFX, user_idnr);
if (__auth_query(__auth_query_data) == -1) {
trace(TRACE_ERROR, "%s,%s: query failed",
__FILE__, __func__);
return -1;
}
if (db_num_rows() < 1) {
trace(TRACE_DEBUG, "%s,%s: didn't find user_idnr [%llu]",
__FILE__, __func__, user_idnr);
db_free_result();
return 1;
}
trace(TRACE_DEBUG, "%s,%s: found user_idnr [%llu]",
__FILE__, __func__, user_idnr);
db_free_result();
return 0;
}
int auth_get_users_from_clientid(u64_t client_id, u64_t ** user_ids,
unsigned *num_users)
{
unsigned i;
assert(user_ids != NULL);
assert(num_users != NULL);
*user_ids = NULL;
*num_users = 0;
snprintf(__auth_query_data, DEF_QUERYSIZE,
"SELECT user_idnr FROM %susers WHERE client_idnr = '%llu'",
DBPFX, client_id);
if (__auth_query(__auth_query_data) == -1) {
trace(TRACE_ERROR, "%s,%s: error gettings users for "
"client_id [%llu]", __FILE__, __func__, client_id);
return -1;
}
*num_users = db_num_rows();
*user_ids = (u64_t *) dm_malloc(*num_users * sizeof(u64_t));
if (*user_ids == NULL) {
trace(TRACE_ERROR,
"%s,%s: error allocating memory, probably "
"out of memory", __FILE__, __func__);
db_free_result();
return -2;
}
memset(*user_ids, 0, *num_users * sizeof(u64_t));
for (i = 0; i < *num_users; i++) {
(*user_ids)[i] = db_get_result_u64(i, 0);
}
db_free_result();
return 1;
}
int auth_addalias(u64_t user_idnr, const char *alias, u64_t clientid)
{
char *escaped_alias;
if (!(escaped_alias = (char *) dm_malloc(strlen(alias) * 2 + 1))) {
trace(TRACE_ERROR, "%s,%s: out of memory allocating "
"escaped alias", __FILE__, __func__);
return -1;
}
db_escape_string(escaped_alias, alias, strlen(alias));
/* check if this alias already exists */
snprintf(__auth_query_data, DEF_QUERYSIZE,
"SELECT alias_idnr FROM %saliases "
"WHERE lower(alias) = lower('%s') AND deliver_to = '%llu' "
"AND client_idnr = '%llu'",DBPFX, escaped_alias, user_idnr, clientid);
if (__auth_query(__auth_query_data) == -1) {
/* query failed */
trace(TRACE_ERROR,
"%s,%s: query for searching alias failed", __FILE__,
__func__);
dm_free(escaped_alias);
return -1;
}
if (db_num_rows() > 0) {
trace(TRACE_INFO,
"%s,%s: alias [%s] for user [%llu] already exists",
__FILE__, __func__, escaped_alias, user_idnr);
dm_free(escaped_alias);
db_free_result();
return 1;
}
db_free_result();
snprintf(__auth_query_data, DEF_QUERYSIZE,
"INSERT INTO %saliases (alias,deliver_to,client_idnr) "
"VALUES ('%s','%llu','%llu')",DBPFX, escaped_alias, user_idnr,
clientid);
dm_free(escaped_alias);
if (db_query(__auth_query_data) == -1) {
/* query failed */
trace(TRACE_ERROR, "%s,%s: query for adding alias failed",
__FILE__, __func__);
return -1;
}
return 0;
}
int auth_addalias_ext(const char *alias,
const char *deliver_to, u64_t clientid)
{
char *escaped_alias;
char *escaped_deliver_to;
if (!(escaped_alias = (char *) dm_malloc(strlen(alias) * 2 + 1))) {
trace(TRACE_ERROR, "%s,%s: out of memory allocating "
"escaped alias", __FILE__, __func__);
return -1;
}
if (!(escaped_deliver_to = (char *) dm_malloc(strlen(deliver_to) * 2 + 1))) {
trace(TRACE_ERROR, "%s,%s: out of memory allocating "
"escaped deliver_to", __FILE__, __func__);
return -1;
}
db_escape_string(escaped_alias, alias, strlen(alias));
db_escape_string(escaped_deliver_to, deliver_to, strlen(deliver_to));
/* check if this alias already exists */
if (clientid != 0) {
snprintf(__auth_query_data, DEF_QUERYSIZE,
"SELECT alias_idnr FROM %saliases "
"WHERE lower(alias) = lower('%s') AND "
"lower(deliver_to) = lower('%s') "
"AND client_idnr = '%llu'",DBPFX, escaped_alias, escaped_deliver_to,
clientid);
} else {
snprintf(__auth_query_data, DEF_QUERYSIZE,
"SELECT alias_idnr FROM %saliases "
"WHERE lower(alias) = lower('%s') "
"AND lower(deliver_to) = lower('%s') ",DBPFX,
escaped_alias, escaped_deliver_to);
}
if (__auth_query(__auth_query_data) == -1) {
/* query failed */
trace(TRACE_ERROR,
"%s,%s: query for searching alias failed", __FILE__,
__func__);
dm_free(escaped_alias);
dm_free(escaped_deliver_to);
return -1;
}
if (db_num_rows() > 0) {
trace(TRACE_INFO,
"%s,%s: alias [%s] --> [%s] already exists",
__FILE__, __func__, alias, deliver_to);
dm_free(escaped_alias);
dm_free(escaped_deliver_to);
db_free_result();
return 1;
}
db_free_result();
snprintf(__auth_query_data, DEF_QUERYSIZE,
"INSERT INTO %saliases (alias,deliver_to,client_idnr) "
"VALUES ('%s','%s','%llu')",DBPFX, escaped_alias, escaped_deliver_to, clientid);
dm_free(escaped_alias);
dm_free(escaped_deliver_to);
if (__auth_query(__auth_query_data) == -1) {
/* query failed */
trace(TRACE_ERROR, "%s,%s: query for adding alias failed",
__FILE__, __func__);
return -1;
}
return 0;
}
int auth_removealias(u64_t user_idnr, const char *alias)
{
char *escaped_alias;
if (!(escaped_alias = (char *) dm_malloc(strlen(alias) * 2 + 1))) {
trace(TRACE_ERROR, "%s,%s: out of memory allocating "
"escaped alias", __FILE__, __func__);
return -1;
}
db_escape_string(escaped_alias, alias, strlen(alias));
snprintf(__auth_query_data, DEF_QUERYSIZE,
"DELETE FROM %saliases WHERE deliver_to='%llu' "
"AND lower(alias) = lower('%s')",DBPFX, user_idnr, escaped_alias);
dm_free(escaped_alias);
if (__auth_query(__auth_query_data) == -1) {
/* query failed */
trace(TRACE_ERROR, "%s,%s: query failed", __FILE__,
__func__);
return -1;
}
return 0;
}
int auth_removealias_ext(const char *alias, const char *deliver_to)
{
char *escaped_alias;
char *escaped_deliver_to;
if (!(escaped_alias = (char *) dm_malloc(strlen(alias) * 2 + 1))) {
trace(TRACE_ERROR, "%s,%s: out of memory allocating "
"escaped alias", __FILE__, __func__);
return -1;
}
if (!(escaped_deliver_to = (char *) dm_malloc(strlen(deliver_to) * 2 + 1))) {
trace(TRACE_ERROR, "%s,%s: out of memory allocating "
"escaped deliver_to", __FILE__, __func__);
return -1;
}
db_escape_string(escaped_alias, alias, strlen(alias));
db_escape_string(escaped_deliver_to, deliver_to, strlen(deliver_to));
snprintf(__auth_query_data, DEF_QUERYSIZE,
"DELETE FROM %saliases WHERE lower(deliver_to) = lower('%s') "
"AND lower(alias) = lower('%s')",DBPFX, deliver_to, alias);
dm_free(escaped_alias);
dm_free(escaped_deliver_to);
if (db_query(__auth_query_data) == -1) {
/* query failed */
trace(TRACE_ERROR, "%s,%s: query failed", __FILE__,
__func__);
return -1;
}
return 0;
}
GList * auth_get_user_aliases(u64_t user_idnr)
{
int i, n;
const char *query_result;
GList *aliases = NULL;
/* do a inverted (DESC) query because adding the names to the
* final list inverts again */
snprintf(__auth_query_data, DEF_QUERYSIZE,
"SELECT alias FROM %saliases WHERE deliver_to = '%llu' "
"ORDER BY alias DESC",DBPFX, user_idnr);
if (__auth_query(__auth_query_data) == -1) {
trace(TRACE_ERROR, "%s,%s: could not retrieve list",
__FILE__, __func__);
return NULL;
}
n = db_num_rows();
for (i = 0; i < n; i++) {
query_result = db_get_result(i, 0);
if (!query_result || ! (aliases = g_list_append(aliases,g_strdup(query_result)))) {
g_list_foreach(aliases, (GFunc)g_free, NULL);
g_list_free(aliases);
db_free_result();
return NULL;
}
}
db_free_result();
return aliases;
}
GList * auth_get_aliases_ext(const char *alias)
{
int i, n;
const char *query_result;
GList *aliases = NULL;
/* do a inverted (DESC) query because adding the names to the
* final list inverts again */
snprintf(__auth_query_data, DEF_QUERYSIZE,
"SELECT deliver_to FROM %saliases WHERE alias = '%s' "
"ORDER BY alias DESC",DBPFX, alias);
if (__auth_query(__auth_query_data) == -1) {
trace(TRACE_ERROR, "%s,%s: could not retrieve list",
__FILE__, __func__);
return NULL;
}
n = db_num_rows();
for (i = 0; i < n; i++) {
query_result = db_get_result(i, 0);
if (!query_result || ! (aliases = g_list_append(aliases,g_strdup(query_result)))) {
g_list_foreach(aliases, (GFunc)g_free, NULL);
g_list_free(aliases);
db_free_result();
return NULL;
}
}
db_free_result();
return aliases;
}
gboolean auth_requires_shadow_user(void)
{
return FALSE;
}
syntax highlighted by Code2HTML, v. 0.9.1