/*
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 "auth.h"
#include "db.h"
#include "list.h"
#include "debug.h"
#include "dbmd5.h"
#include "dbmail.h"
#include "misc.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
/**
* 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);
static u64_t __auth_insert_result(const char *sequence_identifier);
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)
{
const char *query_result;
char *escaped_username;
assert(user_idnr != NULL);
*user_idnr = 0;
if (!username) {
trace(TRACE_ERROR, "%s,%s: got NULL as username",
__FILE__, __func__);
return 0;
}
if (db_escape_string(&escaped_username, username)) {
trace(TRACE_ERROR, "%s,%s: error escaping username.",
__FILE__, __func__);
return -1;
}
snprintf(__auth_query_data, AUTH_QUERY_SIZE,
"SELECT user_idnr FROM dbmail_users WHERE userid='%s'",
escaped_username);
free(escaped_username);
if (__auth_query(__auth_query_data) == -1) {
trace(TRACE_ERROR, "%s,%s: could not execute query",
__FILE__, __func__);
return -1;
}
if (db_num_rows() == 0) {
db_free_result();
return 0;
}
query_result = db_get_result(0, 0);
*user_idnr = (query_result) ? strtoull(query_result, 0, 10) : 0;
db_free_result();
return 1;
}
int auth_get_known_users(struct list *users)
{
u64_t i;
const char *query_result;
if (!users) {
trace(TRACE_ERROR, "%s,%s: got a NULL pointer as argument",
__FILE__, __func__);
return -2;
}
list_init(users);
/* do a inverted (DESC) query because adding the names to the
* final list inverts again */
snprintf(__auth_query_data, AUTH_QUERY_SIZE,
"SELECT userid FROM dbmail_users ORDER BY userid DESC");
if (__auth_query(__auth_query_data) == -1) {
trace(TRACE_ERROR, "%s,%s: could not retrieve user list",
__FILE__, __func__);
return -1;
}
if (db_num_rows() > 0) {
for (i = 0; i < (unsigned) db_num_rows(); i++) {
query_result = db_get_result(i, 0);
if (!list_nodeadd
(users, query_result,
strlen(query_result) + 1)) {
list_freelist(&users->start);
return -2;
}
}
}
db_free_result();
return 0;
}
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 dbmail_users WHERE user_idnr = '%llu'",
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 dbmail_users WHERE user_idnr = '%llu'",
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 dbmail_users WHERE user_idnr = '%llu'",
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(const char *username, struct list *userids, int checks)
{
int occurences = 0;
int r;
void *saveres;
u64_t counter;
unsigned num_rows;
char *escaped_username;
const char *query_result;
trace(TRACE_DEBUG, "%s,%s: checking user [%s] in alias table",
__FILE__, __func__, username);
saveres = db_get_result_set();
db_set_result_set(NULL);
if (checks > MAX_CHECKS_DEPTH) {
trace(TRACE_ERROR,
"%s,%s: maximum checking depth reached, "
"there probably is a loop in your alias table",
__FILE__, __func__);
return -1;
}
if (db_escape_string(&escaped_username, username)) {
trace(TRACE_ERROR, "%s,%s: error escaping username.",
__FILE__, __func__);
return -1;
}
snprintf(__auth_query_data, AUTH_QUERY_SIZE,
"SELECT deliver_to FROM dbmail_aliases WHERE "
"lower(alias) = lower('%s')", escaped_username);
free(escaped_username);
trace(TRACE_DEBUG, "%s,%s: checks [%d]", __FILE__, __func__,
checks);
if (__auth_query(__auth_query_data) == -1) {
/* copy the old result set */
db_set_result_set(saveres);
return 0;
}
num_rows = db_num_rows();
if (num_rows < 1) {
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 */
list_nodeadd(userids, 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);
r = auth_check_user(query_result, userids,
(checks < 0) ? 1 : checks + 1);
if (r < 0) {
/* loop detected */
db_free_result();
db_set_result_set(saveres);
if (checks > 0)
return -1; /* still in recursive call */
if (userids->start) {
list_freelist(&userids->start);
userids->total_nodes = 0;
}
return 0; /* report to calling routine: no results */
}
occurences += r;
}
}
db_free_result();
db_set_result_set(saveres);
return occurences;
}
int auth_check_user_ext(const char *username, struct list *userids,
struct list *fwds, int checks)
{
int occurences = 0;
void *saveres;
u64_t counter;
char *escaped_username;
const char *query_result;
char *endptr;
u64_t id;
unsigned num_rows;
if (checks > 20) {
trace(TRACE_ERROR,"%s,%s: too many checks. Possible loop in recursion.",
__FILE__, __func__);
return 0;
}
if (strlen(username) < 1)
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 (db_escape_string(&escaped_username, username)) {
trace(TRACE_ERROR, "%s,%s: error escaping username.",
__FILE__, __func__);
return -1;
}
snprintf(__auth_query_data, AUTH_QUERY_SIZE,
"SELECT deliver_to FROM dbmail_aliases "
"WHERE lower(alias) = lower('%s') "
"AND lower(alias) <> lower(deliver_to)",
escaped_username);
free(escaped_username);
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)
list_nodeadd(userids, &id, sizeof(id));
/* numeric deliver-to --> this is a userid */
else
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)
{
char *escaped_password;
char *escaped_username;
assert(user_idnr != NULL);
*user_idnr = 0;
if (db_escape_string(&escaped_username, username)) {
trace(TRACE_ERROR, "%s,%s: error escaping username.",
__FILE__, __func__);
return -1;
}
if (db_escape_string(&escaped_password, password)) {
trace(TRACE_ERROR, "%s,%s: error escaping password.",
__FILE__, __func__);
free(escaped_username);
return -1;
}
#ifdef _DBAUTH_STRICT_USER_CHECK
/* first check to see if this user already exists */
snprintf(__auth_query_data, AUTH_QUERY_SIZE,
"SELECT * FROM dbmail_users WHERE userid = '%s'", escaped_username);
if (__auth_query(__auth_query_data) == -1) {
/* query failed */
trace(TRACE_ERROR, "%s,%s: query failed",
__FILE__, __func__);
free(escaped_username);
free(escaped_password);
return -1;
}
if (db_num_rows() > 0) {
/* this username already exists */
trace(TRACE_ERROR, "%s,%s: user already exists",
__FILE__, __func__);
free(escaped_username);
free(escaped_password);
db_free_result();
return -1;
}
db_free_result();
#endif
if (strlen(password) >= AUTH_QUERY_SIZE) {
trace(TRACE_ERROR, "%s,%s: password length is insane",
__FILE__, __func__);
free(escaped_username);
free(escaped_password);
return -1;
}
snprintf(__auth_query_data, AUTH_QUERY_SIZE,
"INSERT INTO dbmail_users "
"(userid,passwd,client_idnr,maxmail_size,encryption_type, last_login) VALUES "
"('%s','%s',%llu,'%llu','%s', CURRENT_TIMESTAMP)",
escaped_username, escaped_password, clientid, maxmail,
enctype ? enctype : "");
free(escaped_username);
free(escaped_password);
if (__auth_query(__auth_query_data) == -1) {
/* query failed */
trace(TRACE_ERROR, "%s,%s: query for adding user failed",
__FILE__, __func__);
return -1;
}
*user_idnr = __auth_insert_result("user_idnr");
return 1;
}
int auth_delete_user(const char *username)
{
char *escaped_username;
if (db_escape_string(&escaped_username, username)) {
trace(TRACE_ERROR, "%s,%s: error escaping username.",
__FILE__, __func__);
return -1;
}
snprintf(__auth_query_data, AUTH_QUERY_SIZE,
"DELETE FROM dbmail_users WHERE userid = '%s'", escaped_username);
free(escaped_username);
if (__auth_query(__auth_query_data) == -1) {
/* query failed */
trace(TRACE_ERROR, "%s,%s: query for removing user failed",
__FILE__, __func__);
return -1;
}
return 0;
}
int auth_change_username(u64_t user_idnr, const char *new_name)
{
char *escaped_new_name;
if (db_escape_string(&escaped_new_name, new_name)) {
trace(TRACE_ERROR, "%s,%s: error escaping new_name.",
__FILE__, __func__);
return -1;
}
snprintf(__auth_query_data, AUTH_QUERY_SIZE,
"UPDATE dbmail_users SET userid = '%s' WHERE user_idnr='%llu'",
escaped_new_name, user_idnr);
free(escaped_new_name);
if (__auth_query(__auth_query_data) == -1) {
trace(TRACE_ERROR,
"%s,%s: could not change name for user [%llu]",
__FILE__, __func__, user_idnr);
return -1;
}
return 0;
}
int auth_change_password(u64_t user_idnr, const char *new_pass,
const char *enctype)
{
char *escaped_new_pass;
if (db_escape_string(&escaped_new_pass, new_pass)) {
trace(TRACE_ERROR, "%s,%s: error escaping new_pass.",
__FILE__, __func__);
return -1;
}
snprintf(__auth_query_data, AUTH_QUERY_SIZE,
"UPDATE dbmail_users SET passwd = '%s', encryption_type = '%s' "
" WHERE user_idnr='%llu'",
escaped_new_pass, enctype ? enctype : "", user_idnr);
free(escaped_new_pass);
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 dbmail_users SET client_idnr = '%llu' "
"WHERE user_idnr='%llu'", 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)
{
snprintf(__auth_query_data, AUTH_QUERY_SIZE,
"UPDATE dbmail_users SET maxmail_size = '%llu' "
"WHERE user_idnr = '%llu'", new_size, user_idnr);
if (__auth_query(__auth_query_data) == -1) {
trace(TRACE_ERROR,
"%s,%s: could not change maxmailsize for user [%llu]",
__FILE__, __func__, user_idnr);
return -1;
}
return 0;
}
int auth_validate(char *username, char *password, u64_t * user_idnr)
{
const char *query_result;
int is_validated = 0;
timestring_t timestring;
char salt[13];
char cryptres[35];
char *escaped_username;
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;
}
create_current_timestring(×tring);
/* the shared mailbox user should not log in! */
if (strcmp(username, SHARED_MAILBOX_USERNAME) == 0)
return 0;
if (db_escape_string(&escaped_username, username)) {
trace(TRACE_ERROR, "%s,%s: error escaping username.",
__FILE__, __func__);
return -1;
}
snprintf(__auth_query_data, AUTH_QUERY_SIZE,
"SELECT user_idnr, passwd, encryption_type FROM dbmail_users "
"WHERE userid = '%s'", escaped_username);
if (__auth_query(__auth_query_data) == -1) {
trace(TRACE_ERROR,
"%s,%s: could not select user information", __FILE__,
__func__);
dm_free(escaped_username);
return -1;
}
dm_free(escaped_username);
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); */
is_validated =
(strncmp(makemd5(password), query_result, 32)
== 0) ? 1 : 0;
} 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);
is_validated =
(strncmp(makemd5(password), query_result, 32) ==
0) ? 1 : 0;
}
if (is_validated) {
query_result = db_get_result(0, 0);
*user_idnr =
(query_result) ? strtoull(query_result, NULL, 10) : 0;
db_free_result();
/* log login in the dbase */
snprintf(__auth_query_data, AUTH_QUERY_SIZE,
"UPDATE dbmail_users SET last_login = '%s' "
"WHERE user_idnr = '%llu'", timestring,
*user_idnr);
if (__auth_query(__auth_query_data) == -1)
trace(TRACE_ERROR,
"%s,%s: could not update user login time",
__FILE__, __func__);
} else {
db_free_result();
}
return (is_validated ? 1 : 0);
}
u64_t auth_md5_validate(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;
timestring_t timestring;
char *escaped_username;
create_current_timestring(×tring);
if (db_escape_string(&escaped_username, username)) {
trace(TRACE_ERROR, "%s,%s: error escaping username.",
__FILE__, __func__);
return -1;
}
snprintf(__auth_query_data, AUTH_QUERY_SIZE,
"SELECT passwd,user_idnr FROM dbmail_users WHERE "
"userid = '%s'", escaped_username);
free(escaped_username);
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 = makemd5(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(md5_apop_he, makemd5(checkstring)) == 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(checkstring);
/* log login in the dbase */
snprintf(__auth_query_data, AUTH_QUERY_SIZE,
"UPDATE dbmail_users SET last_login = '%s' "
"WHERE user_idnr = '%llu'", timestring,
user_idnr);
if (__auth_query(__auth_query_data) == -1)
trace(TRACE_ERROR,
"%s,%s: could not update user login time",
__FILE__, __func__);
return user_idnr;
}
trace(TRACE_MESSAGE, "%s,%s: user [%s] could not be validated",
__FILE__, __func__, username);
db_free_result();
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 dbmail_users WHERE user_idnr = '%llu'",
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;
}
u64_t __auth_insert_result(const char *sequence_identifier)
{
u64_t insert_result;
insert_result = db_insert_result(sequence_identifier);
return insert_result;
}
syntax highlighted by Code2HTML, v. 0.9.1