-
/*
- * rlm_sql.c SQL Module
- * Main SQL module file. Most ICRADIUS code is located in sql.c
- *
- * Version: $Id$
- *
- * 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 is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2 if the
+ * License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/**
+ * $Id$
+ * @file rlm_sql.c
+ * @brief Implements SQL 'users' file, and SQL accounting.
*
- * Copyright 2012 Arran Cudbard-Bell <a.cudbardb@freeradius.org>
- * Copyright 2000,2006 The FreeRADIUS server project
- * Copyright 2000 Mike Machado <mike@innercite.com>
- * Copyright 2000 Alan DeKok <aland@ox.org>
+ * @copyright 2012 Arran Cudbard-Bell <a.cudbardb@freeradius.org>
+ * @copyright 2000,2006 The FreeRADIUS server project
+ * @copyright 2000 Mike Machado <mike@innercite.com>
+ * @copyright 2000 Alan DeKok <aland@ox.org>
*/
-
#include <freeradius-devel/ident.h>
RCSID("$Id$")
#include "rlm_sql.h"
-static char *allowed_chars = NULL;
-
-static const CONF_PARSER section_config[] = {
- { "reference", PW_TYPE_STRING_PTR,
- offsetof(rlm_sql_config_section_t, reference), NULL, ".query"},
+static const CONF_PARSER acct_section_config[] = {
+ {"reference", PW_TYPE_STRING_PTR,
+ offsetof(sql_acct_section_t, reference), NULL, ".query"},
{"logfile", PW_TYPE_STRING_PTR,
- offsetof(rlm_sql_config_section_t, logfile), NULL, NULL},
+ offsetof(sql_acct_section_t, logfile), NULL, NULL},
{NULL, -1, 0, NULL, NULL}
};
static const CONF_PARSER module_config[] = {
- {"driver",PW_TYPE_STRING_PTR,
- offsetof(SQL_CONFIG,sql_driver), NULL, "mysql"},
- {"server",PW_TYPE_STRING_PTR,
- offsetof(SQL_CONFIG,sql_server), NULL, "localhost"},
- {"port",PW_TYPE_STRING_PTR,
- offsetof(SQL_CONFIG,sql_port), NULL, ""},
+ {"driver", PW_TYPE_STRING_PTR,
+ offsetof(rlm_sql_config_t,sql_driver), NULL, "mysql"},
+ {"server", PW_TYPE_STRING_PTR,
+ offsetof(rlm_sql_config_t,sql_server), NULL, "localhost"},
+ {"port", PW_TYPE_STRING_PTR,
+ offsetof(rlm_sql_config_t,sql_port), NULL, ""},
{"login", PW_TYPE_STRING_PTR,
- offsetof(SQL_CONFIG,sql_login), NULL, ""},
+ offsetof(rlm_sql_config_t,sql_login), NULL, ""},
{"password", PW_TYPE_STRING_PTR,
- offsetof(SQL_CONFIG,sql_password), NULL, ""},
+ offsetof(rlm_sql_config_t,sql_password), NULL, ""},
{"radius_db", PW_TYPE_STRING_PTR,
- offsetof(SQL_CONFIG,sql_db), NULL, "radius"},
+ offsetof(rlm_sql_config_t,sql_db), NULL, "radius"},
{"filename", PW_TYPE_FILENAME, /* for sqlite */
- offsetof(SQL_CONFIG,sql_file), NULL, NULL},
+ offsetof(rlm_sql_config_t,sql_file), NULL, NULL},
{"read_groups", PW_TYPE_BOOLEAN,
- offsetof(SQL_CONFIG,read_groups), NULL, "yes"},
+ offsetof(rlm_sql_config_t,read_groups), NULL, "yes"},
{"readclients", PW_TYPE_BOOLEAN,
- offsetof(SQL_CONFIG,do_clients), NULL, "no"},
+ offsetof(rlm_sql_config_t,do_clients), NULL, "no"},
{"deletestalesessions", PW_TYPE_BOOLEAN,
- offsetof(SQL_CONFIG,deletestalesessions), NULL, "yes"},
+ offsetof(rlm_sql_config_t,deletestalesessions), NULL, "yes"},
{"sql_user_name", PW_TYPE_STRING_PTR,
- offsetof(SQL_CONFIG,query_user), NULL, ""},
+ offsetof(rlm_sql_config_t,query_user), NULL, ""},
+ {"logfile", PW_TYPE_STRING_PTR,
+ offsetof(rlm_sql_config_t,logfile), NULL, NULL},
{"default_user_profile", PW_TYPE_STRING_PTR,
- offsetof(SQL_CONFIG,default_profile), NULL, ""},
+ offsetof(rlm_sql_config_t,default_profile), NULL, ""},
{"nas_query", PW_TYPE_STRING_PTR,
- offsetof(SQL_CONFIG,nas_query), NULL, "SELECT id,nasname,shortname,type,secret FROM nas"},
+ offsetof(rlm_sql_config_t,nas_query), NULL,
+ "SELECT id,nasname,shortname,type,secret FROM nas"},
{"authorize_check_query", PW_TYPE_STRING_PTR,
- offsetof(SQL_CONFIG,authorize_check_query), NULL, ""},
+ offsetof(rlm_sql_config_t,authorize_check_query), NULL, ""},
{"authorize_reply_query", PW_TYPE_STRING_PTR,
- offsetof(SQL_CONFIG,authorize_reply_query), NULL, NULL},
+ offsetof(rlm_sql_config_t,authorize_reply_query), NULL, NULL},
{"authorize_group_check_query", PW_TYPE_STRING_PTR,
- offsetof(SQL_CONFIG,authorize_group_check_query), NULL, ""},
+ offsetof(rlm_sql_config_t,authorize_group_check_query), NULL, ""},
{"authorize_group_reply_query", PW_TYPE_STRING_PTR,
- offsetof(SQL_CONFIG,authorize_group_reply_query), NULL, ""},
+ offsetof(rlm_sql_config_t,authorize_group_reply_query), NULL, ""},
{"group_membership_query", PW_TYPE_STRING_PTR,
- offsetof(SQL_CONFIG,groupmemb_query), NULL, NULL},
+ offsetof(rlm_sql_config_t,groupmemb_query), NULL, NULL},
#ifdef WITH_SESSION_MGMT
{"simul_count_query", PW_TYPE_STRING_PTR,
- offsetof(SQL_CONFIG,simul_count_query), NULL, ""},
+ offsetof(rlm_sql_config_t,simul_count_query), NULL, ""},
{"simul_verify_query", PW_TYPE_STRING_PTR,
- offsetof(SQL_CONFIG,simul_verify_query), NULL, ""},
+ offsetof(rlm_sql_config_t,simul_verify_query), NULL, ""},
#endif
{"safe-characters", PW_TYPE_STRING_PTR,
- offsetof(SQL_CONFIG,allowed_chars), NULL,
+ offsetof(rlm_sql_config_t,allowed_chars), NULL,
"@abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_: /"},
/*
* This only works for a few drivers.
*/
{"query_timeout", PW_TYPE_INTEGER,
- offsetof(SQL_CONFIG,query_timeout), NULL, NULL},
+ offsetof(rlm_sql_config_t,query_timeout), NULL, NULL},
{NULL, -1, 0, NULL, NULL}
};
static int fallthrough(VALUE_PAIR *vp)
{
VALUE_PAIR *tmp;
- tmp = pairfind(vp, PW_FALL_THROUGH, 0);
+ tmp = pairfind(vp, PW_FALL_THROUGH, 0, TAG_ANY);
return tmp ? tmp->vp_integer : 0;
}
-
-
/*
* Yucky prototype.
*/
-static int generate_sql_clients(SQL_INST *inst);
-static size_t sql_escape_func(char *out, size_t outlen, const char *in);
+static int generate_sql_clients(rlm_sql_t *inst);
+static size_t sql_escape_func(REQUEST *, char *out, size_t outlen, const char *in, void *arg);
/*
* SQL xlat function
* for inserts, updates and deletes the number of rows afftected will be
* returned instead.
*/
-static int sql_xlat(void *instance, REQUEST *request,
- char *fmt, char *out, size_t freespace,
- UNUSED RADIUS_ESCAPE_STRING func)
+static size_t sql_xlat(void *instance, REQUEST *request,
+ const char *fmt, char *out, size_t freespace)
{
- SQLSOCK *sqlsocket;
- SQL_ROW row;
- SQL_INST *inst = instance;
+ rlm_sql_handle_t *handle;
+ rlm_sql_row_t row;
+ rlm_sql_t *inst = instance;
char querystr[MAX_QUERY_LEN];
- char sqlusername[MAX_STRING_LEN];
size_t ret = 0;
RDEBUG("sql_xlat");
* We could search the string fmt for SQL-User-Name to see if this is
* needed or not
*/
- sql_set_user(inst, request, sqlusername, NULL);
+ sql_set_user(inst, request, NULL);
/*
* Do an xlat on the provided string (nice recursive operation).
*/
- if (!radius_xlat(querystr, sizeof(querystr), fmt, request, sql_escape_func)) {
+ if (!radius_xlat(querystr, sizeof(querystr), fmt, request, sql_escape_func, inst)) {
radlog(L_ERR, "rlm_sql (%s): xlat failed.",
inst->config->xlat_name);
return 0;
}
- sqlsocket = sql_get_socket(inst);
- if (sqlsocket == NULL)
+ handle = sql_get_socket(inst);
+ if (handle == NULL)
return 0;
- query_log(inst, request, NULL, querystr);
+ rlm_sql_query_log(inst, request, NULL, querystr);
/*
* If the query starts with any of the following prefixes,
int numaffected;
char buffer[21]; /* 64bit max is 20 decimal chars + null byte */
- if (rlm_sql_query(&sqlsocket,inst,querystr)) {
- sql_release_socket(inst,sqlsocket);
+ if (rlm_sql_query(&handle,inst,querystr)) {
+ sql_release_socket(inst,handle);
return 0;
}
- numaffected = (inst->module->sql_affected_rows)(sqlsocket,
+ numaffected = (inst->module->sql_affected_rows)(handle,
inst->config);
if (numaffected < 1) {
RDEBUG("rlm_sql (%s): SQL query affected no rows",
if (ret >= freespace){
RDEBUG("rlm_sql (%s): Can't write result, insufficient string space",
inst->config->xlat_name);
- (inst->module->sql_finish_query)(sqlsocket,
+ (inst->module->sql_finish_query)(handle,
inst->config);
- sql_release_socket(inst,sqlsocket);
+ sql_release_socket(inst,handle);
return 0;
}
memcpy(out, buffer, ret + 1); /* we did bounds checking above */
- (inst->module->sql_finish_query)(sqlsocket, inst->config);
- sql_release_socket(inst,sqlsocket);
+ (inst->module->sql_finish_query)(handle, inst->config);
+ sql_release_socket(inst,handle);
return ret;
} /* else it's a SELECT statement */
- if (rlm_sql_select_query(&sqlsocket,inst,querystr)){
- sql_release_socket(inst,sqlsocket);
+ if (rlm_sql_select_query(&handle,inst,querystr)){
+ sql_release_socket(inst,handle);
return 0;
}
- ret = rlm_sql_fetch_row(&sqlsocket, inst);
+ ret = rlm_sql_fetch_row(&handle, inst);
if (ret) {
RDEBUG("SQL query did not succeed");
- (inst->module->sql_finish_select_query)(sqlsocket, inst->config);
- sql_release_socket(inst,sqlsocket);
+ (inst->module->sql_finish_select_query)(handle, inst->config);
+ sql_release_socket(inst,handle);
return 0;
}
- row = sqlsocket->row;
+ row = handle->row;
if (row == NULL) {
RDEBUG("SQL query did not return any results");
- (inst->module->sql_finish_select_query)(sqlsocket, inst->config);
- sql_release_socket(inst,sqlsocket);
+ (inst->module->sql_finish_select_query)(handle, inst->config);
+ sql_release_socket(inst,handle);
return 0;
}
if (row[0] == NULL){
RDEBUG("Null value in first column");
- (inst->module->sql_finish_select_query)(sqlsocket, inst->config);
- sql_release_socket(inst,sqlsocket);
+ (inst->module->sql_finish_select_query)(handle, inst->config);
+ sql_release_socket(inst,handle);
return 0;
}
ret = strlen(row[0]);
if (ret >= freespace){
RDEBUG("Insufficient string space");
- (inst->module->sql_finish_select_query)(sqlsocket, inst->config);
- sql_release_socket(inst,sqlsocket);
+ (inst->module->sql_finish_select_query)(handle, inst->config);
+ sql_release_socket(inst,handle);
return 0;
}
RDEBUG("sql_xlat finished");
- (inst->module->sql_finish_select_query)(sqlsocket, inst->config);
- sql_release_socket(inst,sqlsocket);
+ (inst->module->sql_finish_select_query)(handle, inst->config);
+ sql_release_socket(inst,handle);
return ret;
}
-static int generate_sql_clients(SQL_INST *inst)
+static int generate_sql_clients(rlm_sql_t *inst)
{
- SQLSOCK *sqlsocket;
- SQL_ROW row;
+ rlm_sql_handle_t *handle;
+ rlm_sql_row_t row;
char querystr[MAX_QUERY_LEN];
RADCLIENT *c;
char *prefix_ptr = NULL;
DEBUG("rlm_sql (%s) in generate_sql_clients: query is %s",
inst->config->xlat_name, querystr);
- sqlsocket = sql_get_socket(inst);
- if (sqlsocket == NULL)
+ handle = sql_get_socket(inst);
+ if (handle == NULL)
return -1;
- if (rlm_sql_select_query(&sqlsocket,inst,querystr)){
+ if (rlm_sql_select_query(&handle,inst,querystr)){
return -1;
}
- while(rlm_sql_fetch_row(&sqlsocket, inst) == 0) {
+ while(rlm_sql_fetch_row(&handle, inst) == 0) {
i++;
- row = sqlsocket->row;
+ row = handle->row;
if (row == NULL)
break;
/*
DEBUG("rlm_sql (%s): Read entry nasname=%s,shortname=%s,secret=%s",inst->config->xlat_name,
row[1],row[2],row[4]);
- c = rad_malloc(sizeof(*c));
- memset(c, 0, sizeof(*c));
+ c = talloc_zero(inst, RADCLIENT);
#ifdef WITH_DYNAMIC_CLIENTS
c->dynamic = 1;
if ((c->prefix < 0) || (c->prefix > 128)) {
radlog(L_ERR, "rlm_sql (%s): Invalid Prefix value '%s' for IP.",
inst->config->xlat_name, prefix_ptr + 1);
- free(c);
+ talloc_free(c);
continue;
}
/* Replace '/' with '\0' */
* Always get the numeric representation of IP
*/
if (ip_hton(row[1], AF_UNSPEC, &c->ipaddr) < 0) {
- radlog(L_CONS|L_ERR, "rlm_sql (%s): Failed to look up hostname %s: %s",
+ radlog(L_ERR, "rlm_sql (%s): Failed to look up hostname %s: %s",
inst->config->xlat_name,
row[1], fr_strerror());
- free(c);
+ talloc_free(c);
continue;
} else {
char buffer[256];
ip_ntoh(&c->ipaddr, buffer, sizeof(buffer));
- c->longname = strdup(buffer);
+ c->longname = talloc_strdup(c, buffer);
}
if (c->prefix < 0) switch (c->ipaddr.af) {
/*
* Other values (secret, shortname, nastype, virtual_server)
*/
- c->secret = strdup(row[4]);
- c->shortname = strdup(row[2]);
+ c->secret = talloc_strdup(c, row[4]);
+ c->shortname = talloc_strdup(c, row[2]);
if(row[3] != NULL)
c->nastype = strdup(row[3]);
- numf = (inst->module->sql_num_fields)(sqlsocket, inst->config);
+ numf = (inst->module->sql_num_fields)(handle, inst->config);
if ((numf > 5) && (row[5] != NULL) && *row[5]) c->server = strdup(row[5]);
DEBUG("rlm_sql (%s): Adding client %s (%s, server=%s) to clients list",
inst->config->xlat_name,
c->longname,c->shortname, c->server ? c->server : "<none>");
if (!client_add(NULL, c)) {
- sql_release_socket(inst, sqlsocket);
+ sql_release_socket(inst, handle);
DEBUG("rlm_sql (%s): Failed to add client %s (%s) to clients list. Maybe there's a duplicate?",
inst->config->xlat_name,
c->longname,c->shortname);
return -1;
}
}
- (inst->module->sql_finish_select_query)(sqlsocket, inst->config);
- sql_release_socket(inst, sqlsocket);
+ (inst->module->sql_finish_select_query)(handle, inst->config);
+ sql_release_socket(inst, handle);
return 0;
}
/*
* Translate the SQL queries.
*/
-static size_t sql_escape_func(char *out, size_t outlen, const char *in)
+static size_t sql_escape_func(UNUSED REQUEST *request, char *out, size_t outlen,
+ const char *in, void *arg)
{
+ rlm_sql_t *inst = arg;
size_t len = 0;
while (in[0]) {
* mime-encoded equivalents.
*/
if ((in[0] < 32) ||
- strchr(allowed_chars, *in) == NULL) {
+ strchr(inst->config->allowed_chars, *in) == NULL) {
/*
* Only 3 or less bytes available.
*/
* escape it twice. (it will make things wrong if we have an
* escape candidate character in the username)
*/
-int sql_set_user(SQL_INST *inst, REQUEST *request, char *sqlusername, const char *username)
+int sql_set_user(rlm_sql_t *inst, REQUEST *request, const char *username)
{
- VALUE_PAIR *vp=NULL;
- char tmpuser[MAX_STRING_LEN];
-
- tmpuser[0] = '\0';
- sqlusername[0]= '\0';
-
- /* Remove any user attr we added previously */
- pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
+ char buffer[254];
+ VALUE_PAIR *vp = NULL;
+ const char *sqluser;
+ size_t len;
if (username != NULL) {
- strlcpy(tmpuser, username, sizeof(tmpuser));
- } else if (strlen(inst->config->query_user)) {
- radius_xlat(tmpuser, sizeof(tmpuser), inst->config->query_user, request, NULL);
+ sqluser = username;
+ } else if (*inst->config->query_user) {
+ sqluser = inst->config->query_user;
} else {
return 0;
}
-
- strlcpy(sqlusername, tmpuser, MAX_STRING_LEN);
- RDEBUG2("sql_set_user escaped user --> '%s'", sqlusername);
- vp = radius_pairmake(request, &request->packet->vps,
- "SQL-User-Name", NULL, 0);
- if (!vp) {
- radlog(L_ERR, "%s", fr_strerror());
+
+ len = radius_xlat(buffer, sizeof(buffer), sqluser, request, NULL, NULL);
+ if (!len) {
return -1;
}
-
- strlcpy(vp->vp_strvalue, tmpuser, sizeof(vp->vp_strvalue));
+
+ vp = pairalloc(NULL, inst->sql_user);
+ vp->op = T_OP_SET;
+
+ strlcpy(vp->vp_strvalue, buffer, sizeof(vp->vp_strvalue));
vp->length = strlen(vp->vp_strvalue);
+ pairadd(&request->packet->vps, vp);
- return 0;
+ RDEBUG2("SQL-User-Name updated");
+ return 0;
}
-static void sql_grouplist_free (SQL_GROUPLIST **group_list)
+static void sql_grouplist_free (rlm_sql_grouplist_t **group_list)
{
- SQL_GROUPLIST *last;
+ rlm_sql_grouplist_t *last;
while(*group_list) {
last = *group_list;
}
-static int sql_get_grouplist (SQL_INST *inst, SQLSOCK *sqlsocket, REQUEST *request, SQL_GROUPLIST **group_list)
+static int sql_get_grouplist (rlm_sql_t *inst, rlm_sql_handle_t *handle, REQUEST *request, rlm_sql_grouplist_t **group_list)
{
char querystr[MAX_QUERY_LEN];
int num_groups = 0;
- SQL_ROW row;
- SQL_GROUPLIST *group_list_tmp;
+ rlm_sql_row_t row;
+ rlm_sql_grouplist_t *group_list_tmp;
/* NOTE: sql_set_user should have been run before calling this function */
(inst->config->groupmemb_query[0] == 0))
return 0;
- if (!radius_xlat(querystr, sizeof(querystr), inst->config->groupmemb_query, request, sql_escape_func)) {
+ if (!radius_xlat(querystr, sizeof(querystr), inst->config->groupmemb_query, request, sql_escape_func, inst)) {
radlog_request(L_ERR, 0, request, "xlat \"%s\" failed.",
inst->config->groupmemb_query);
return -1;
}
- if (rlm_sql_select_query(&sqlsocket, inst, querystr) < 0) {
+ if (rlm_sql_select_query(&handle, inst, querystr) < 0) {
return -1;
}
- while (rlm_sql_fetch_row(&sqlsocket, inst) == 0) {
- row = sqlsocket->row;
+ while (rlm_sql_fetch_row(&handle, inst) == 0) {
+ row = handle->row;
if (row == NULL)
break;
if (row[0] == NULL){
RDEBUG("row[0] returned NULL");
- (inst->module->sql_finish_select_query)(sqlsocket, inst->config);
+ (inst->module->sql_finish_select_query)(handle, inst->config);
sql_grouplist_free(group_list);
return -1;
}
if (*group_list == NULL) {
- *group_list = rad_malloc(sizeof(SQL_GROUPLIST));
+ *group_list = rad_malloc(sizeof(rlm_sql_grouplist_t));
group_list_tmp = *group_list;
} else {
rad_assert(group_list_tmp != NULL);
- group_list_tmp->next = rad_malloc(sizeof(SQL_GROUPLIST));
+ group_list_tmp->next = rad_malloc(sizeof(rlm_sql_grouplist_t));
group_list_tmp = group_list_tmp->next;
}
group_list_tmp->next = NULL;
strlcpy(group_list_tmp->groupname, row[0], MAX_STRING_LEN);
}
- (inst->module->sql_finish_select_query)(sqlsocket, inst->config);
+ (inst->module->sql_finish_select_query)(handle, inst->config);
return num_groups;
}
static int sql_groupcmp(void *instance, REQUEST *request, VALUE_PAIR *request_vp, VALUE_PAIR *check,
VALUE_PAIR *check_pairs, VALUE_PAIR **reply_pairs)
{
- SQLSOCK *sqlsocket;
- SQL_INST *inst = instance;
- char sqlusername[MAX_STRING_LEN];
- SQL_GROUPLIST *group_list, *group_list_tmp;
+ rlm_sql_handle_t *handle;
+ rlm_sql_t *inst = instance;
+ rlm_sql_grouplist_t *group_list, *group_list_tmp;
check_pairs = check_pairs;
reply_pairs = reply_pairs;
request_vp = request_vp;
RDEBUG("sql_groupcmp");
- if (!check || !check->vp_strvalue || !check->length){
+ if (!check || !check->length){
RDEBUG("sql_groupcmp: Illegal group name");
return 1;
}
return 1;
}
/*
- * Set, escape, and check the user attr here
+ * Set, escape, and check the user attr here
*/
- if (sql_set_user(inst, request, sqlusername, NULL) < 0)
+ if (sql_set_user(inst, request, NULL) < 0)
return 1;
/*
* Get a socket for this lookup
*/
- sqlsocket = sql_get_socket(inst);
- if (sqlsocket == NULL) {
- /* Remove the username we (maybe) added above */
- pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
+ handle = sql_get_socket(inst);
+ if (handle == NULL) {
return 1;
}
/*
* Get the list of groups this user is a member of
*/
- if (sql_get_grouplist(inst, sqlsocket, request, &group_list) < 0) {
+ if (sql_get_grouplist(inst, handle, request, &group_list) < 0) {
radlog_request(L_ERR, 0, request,
"Error getting group membership");
- /* Remove the username we (maybe) added above */
- pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
- sql_release_socket(inst, sqlsocket);
+ sql_release_socket(inst, handle);
return 1;
}
check->vp_strvalue);
/* Free the grouplist */
sql_grouplist_free(&group_list);
- /* Remove the username we (maybe) added above */
- pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
- sql_release_socket(inst, sqlsocket);
+ sql_release_socket(inst, handle);
return 0;
}
}
/* Free the grouplist */
sql_grouplist_free(&group_list);
- /* Remove the username we (maybe) added above */
- pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
- sql_release_socket(inst,sqlsocket);
+ sql_release_socket(inst,handle);
RDEBUG("sql_groupcmp finished: User is NOT a member of group %s",
check->vp_strvalue);
-static int rlm_sql_process_groups(SQL_INST *inst, REQUEST *request, SQLSOCK *sqlsocket, int *dofallthrough)
+static int rlm_sql_process_groups(rlm_sql_t *inst, REQUEST *request, rlm_sql_handle_t *handle, int *dofallthrough)
{
VALUE_PAIR *check_tmp = NULL;
VALUE_PAIR *reply_tmp = NULL;
- SQL_GROUPLIST *group_list, *group_list_tmp;
+ rlm_sql_grouplist_t *group_list, *group_list_tmp;
VALUE_PAIR *sql_group = NULL;
char querystr[MAX_QUERY_LEN];
int found = 0;
/*
* Get the list of groups this user is a member of
*/
- if (sql_get_grouplist(inst, sqlsocket, request, &group_list) < 0) {
+ if (sql_get_grouplist(inst, handle, request, &group_list) < 0) {
radlog_request(L_ERR, 0, request, "Error retrieving group list");
return -1;
}
return -1;
}
pairadd(&request->packet->vps, sql_group);
- if (!radius_xlat(querystr, sizeof(querystr), inst->config->authorize_group_check_query, request, sql_escape_func)) {
+ if (!radius_xlat(querystr, sizeof(querystr), inst->config->authorize_group_check_query, request, sql_escape_func, inst)) {
radlog_request(L_ERR, 0, request,
"Error generating query; rejecting user");
/* Remove the grouup we added above */
- pairdelete(&request->packet->vps, PW_SQL_GROUP, 0);
+ pairdelete(&request->packet->vps, PW_SQL_GROUP, 0, TAG_ANY);
sql_grouplist_free(&group_list);
return -1;
}
- rows = sql_getvpdata(inst, &sqlsocket, &check_tmp, querystr);
+ rows = sql_getvpdata(inst, &handle, &check_tmp, querystr);
if (rows < 0) {
radlog_request(L_ERR, 0, request, "Error retrieving check pairs for group %s",
group_list_tmp->groupname);
/* Remove the grouup we added above */
- pairdelete(&request->packet->vps, PW_SQL_GROUP, 0);
+ pairdelete(&request->packet->vps, PW_SQL_GROUP, 0, TAG_ANY);
pairfree(&check_tmp);
sql_grouplist_free(&group_list);
return -1;
/*
* Now get the reply pairs since the paircompare matched
*/
- if (!radius_xlat(querystr, sizeof(querystr), inst->config->authorize_group_reply_query, request, sql_escape_func)) {
+ if (!radius_xlat(querystr, sizeof(querystr), inst->config->authorize_group_reply_query, request, sql_escape_func, inst)) {
radlog_request(L_ERR, 0, request, "Error generating query; rejecting user");
/* Remove the grouup we added above */
- pairdelete(&request->packet->vps, PW_SQL_GROUP, 0);
+ pairdelete(&request->packet->vps, PW_SQL_GROUP, 0, TAG_ANY);
pairfree(&check_tmp);
sql_grouplist_free(&group_list);
return -1;
}
- if (sql_getvpdata(inst, &sqlsocket, &reply_tmp, querystr) < 0) {
+ if (sql_getvpdata(inst, &handle, &reply_tmp, querystr) < 0) {
radlog_request(L_ERR, 0, request, "Error retrieving reply pairs for group %s",
group_list_tmp->groupname);
/* Remove the grouup we added above */
- pairdelete(&request->packet->vps, PW_SQL_GROUP, 0);
+ pairdelete(&request->packet->vps, PW_SQL_GROUP, 0, TAG_ANY);
pairfree(&check_tmp);
pairfree(&reply_tmp);
sql_grouplist_free(&group_list);
return -1;
}
*dofallthrough = fallthrough(reply_tmp);
- pairxlatmove(request, &request->reply->vps, &reply_tmp);
- pairxlatmove(request, &request->config_items, &check_tmp);
+ radius_xlat_move(request, &request->reply->vps, &reply_tmp);
+ radius_xlat_move(request, &request->config_items, &check_tmp);
}
} else {
/*
/*
* Now get the reply pairs since the paircompare matched
*/
- if (!radius_xlat(querystr, sizeof(querystr), inst->config->authorize_group_reply_query, request, sql_escape_func)) {
+ if (!radius_xlat(querystr, sizeof(querystr), inst->config->authorize_group_reply_query, request, sql_escape_func, inst)) {
radlog_request(L_ERR, 0, request, "Error generating query; rejecting user");
/* Remove the grouup we added above */
- pairdelete(&request->packet->vps, PW_SQL_GROUP, 0);
+ pairdelete(&request->packet->vps, PW_SQL_GROUP, 0, TAG_ANY);
pairfree(&check_tmp);
sql_grouplist_free(&group_list);
return -1;
}
- if (sql_getvpdata(inst, &sqlsocket, &reply_tmp, querystr) < 0) {
+ if (sql_getvpdata(inst, &handle, &reply_tmp, querystr) < 0) {
radlog_request(L_ERR, 0, request, "Error retrieving reply pairs for group %s",
group_list_tmp->groupname);
/* Remove the grouup we added above */
- pairdelete(&request->packet->vps, PW_SQL_GROUP, 0);
+ pairdelete(&request->packet->vps, PW_SQL_GROUP, 0, TAG_ANY);
pairfree(&check_tmp);
pairfree(&reply_tmp);
sql_grouplist_free(&group_list);
return -1;
}
*dofallthrough = fallthrough(reply_tmp);
- pairxlatmove(request, &request->reply->vps, &reply_tmp);
- pairxlatmove(request, &request->config_items, &check_tmp);
+ radius_xlat_move(request, &request->reply->vps, &reply_tmp);
+ radius_xlat_move(request, &request->config_items, &check_tmp);
}
/*
* Delete the Sql-Group we added above
* And clear out the pairlists
*/
- pairdelete(&request->packet->vps, PW_SQL_GROUP, 0);
+ pairdelete(&request->packet->vps, PW_SQL_GROUP, 0, TAG_ANY);
pairfree(&check_tmp);
pairfree(&reply_tmp);
}
static int rlm_sql_detach(void *instance)
{
- SQL_INST *inst = instance;
+ rlm_sql_t *inst = instance;
paircompare_unregister(PW_SQL_GROUP, sql_groupcmp);
-
+
if (inst->config) {
- int i;
-
if (inst->pool) sql_poolfree(inst);
if (inst->config->xlat_name) {
- xlat_unregister(inst->config->xlat_name,(RAD_XLAT_FUNC)sql_xlat, instance);
- free(inst->config->xlat_name);
- }
-
- /*
- * Free up dynamically allocated string pointers.
- */
- for (i = 0; module_config[i].name != NULL; i++) {
- char **p;
- if (module_config[i].type != PW_TYPE_STRING_PTR) {
- continue;
- }
-
- /*
- * Treat 'config' as an opaque array of bytes,
- * and take the offset into it. There's a
- * (char*) pointer at that offset, and we want
- * to point to it.
- */
- p = (char **) (((char *)inst->config) + module_config[i].offset);
- if (!*p) { /* nothing allocated */
- continue;
- }
- free(*p);
- *p = NULL;
- }
- /*
- * Catch multiple instances of the module.
- */
- if (allowed_chars == inst->config->allowed_chars) {
- allowed_chars = NULL;
+ xlat_unregister(inst->config->xlat_name, sql_xlat, instance);
}
- free(inst->config);
- inst->config = NULL;
}
if (inst->handle) {
lt_dlclose(inst->handle); /* ignore any errors */
#endif
}
- free(inst);
return 0;
}
static int parse_sub_section(CONF_SECTION *parent,
- UNUSED SQL_INST *instance,
- rlm_sql_config_section_t *config,
+ rlm_sql_t *inst,
+ sql_acct_section_t **config,
rlm_components_t comp)
{
CONF_SECTION *cs;
cs = cf_section_sub_find(parent, name);
if (!cs) {
- /* TODO: Should really setup section with default values */
- goto error;
+ radlog(L_INFO, "rlm_sql (%s): Couldn't find configuration for "
+ "%s, will return NOOP for calls from this section",
+ inst->config->xlat_name, name);
+
+ return 0;
}
- if (cf_section_parse(cs, config, section_config) < 0)
- goto error;
+ *config = talloc_zero(parent, sql_acct_section_t);
+ if (cf_section_parse(cs, *config, acct_section_config) < 0) {
+ radlog(L_ERR, "rlm_sql (%s): Couldn't find configuration for "
+ "%s, will return NOOP for calls from this section",
+ inst->config->xlat_name, name);
+ return -1;
+ }
- config->cs = cs;
+ (*config)->cs = cs;
- return 1;
-
- error:
- radlog(L_ERR, "Failed parsing configuration for section %s",
- name);
-
- return -1;
-
+ return 0;
}
-static int rlm_sql_instantiate(CONF_SECTION * conf, void **instance)
+static int rlm_sql_instantiate(CONF_SECTION *conf, void **instance)
{
- SQL_INST *inst;
+ rlm_sql_t *inst;
const char *xlat_name;
- inst = rad_malloc(sizeof(SQL_INST));
- memset(inst, 0, sizeof(SQL_INST));
+ *instance = inst = talloc_zero(conf, rlm_sql_t);
+ if (!inst) return -1;
+
+ /*
+ * Cache the SQL-User-Name DICT_ATTR, so we can be slightly
+ * more efficient about creating SQL-User-Name attributes.
+ */
+ inst->sql_user = dict_attrbyname("SQL-User-Name");
+ if (!inst->sql_user) return -1;
/*
* Export these methods, too. This avoids RTDL_GLOBAL.
inst->sql_select_query = rlm_sql_select_query;
inst->sql_fetch_row = rlm_sql_fetch_row;
- inst->config = rad_malloc(sizeof(SQL_CONFIG));
- memset(inst->config, 0, sizeof(SQL_CONFIG));
+ inst->config = talloc_zero(inst, rlm_sql_config_t);
inst->cs = conf;
-
- /*
- * If the configuration parameters can't be parsed, then fail.
- */
- if (
- (cf_section_parse(conf, inst->config, module_config) < 0) ||
- (parse_sub_section(conf, inst,
- &inst->config->accounting,
- RLM_COMPONENT_ACCT) < 0) ||
- (parse_sub_section(conf, inst,
- &inst->config->postauth,
- RLM_COMPONENT_POST_AUTH) < 0)
- ) {
- radlog(L_ERR, "Failed parsing configuration");
-
- goto error;
- }
- /*
- * Sanity check for crazy people.
- */
- if (strncmp(inst->config->sql_driver, "rlm_sql_", 8) != 0) {
- radlog(L_ERR, "\"%s\" is NOT an SQL driver!",
- inst->config->sql_driver);
- goto error;
- }
xlat_name = cf_section_name2(conf);
if (xlat_name == NULL) {
xlat_name = cf_section_name1(conf);
} else {
char *group_name;
- DICT_ATTR *dattr;
+ const DICT_ATTR *dattr;
ATTR_FLAGS flags;
/*
* Allocate room for <instance>-SQL-Group
*/
- group_name = rad_malloc((strlen(xlat_name) + 1 + 11) * sizeof(char));
- sprintf(group_name,"%s-SQL-Group", xlat_name);
- DEBUG("rlm_sql Creating new attribute %s",group_name);
+ group_name = talloc_asprintf(inst, "%s-SQL-Group", xlat_name);
+ DEBUG("rlm_sql (%s): Creating new attribute %s",
+ xlat_name, group_name);
memset(&flags, 0, sizeof(flags));
- dict_addattr(group_name, 0, PW_TYPE_STRING, -1, flags);
- dattr = dict_attrbyname(group_name);
- if (dattr == NULL){
- radlog(L_ERR, "rlm_sql: Failed to create attribute %s",
- group_name);
-
- free(group_name);
+ if (dict_addattr(group_name, -1, 0, PW_TYPE_STRING, flags) < 0) {
+ radlog(L_ERR, "rlm_sql (%s): Failed to create "
+ "attribute %s: %s", xlat_name, group_name,
+ fr_strerror());
+ return -1;
+ }
- goto error;
+ dattr = dict_attrbyname(group_name);
+ if (!dattr) {
+ radlog(L_ERR, "rlm_sql (%s): Failed to create "
+ "attribute %s", xlat_name, group_name);
+ return -1;
}
if (inst->config->groupmemb_query &&
inst->config->groupmemb_query[0]) {
- DEBUG("rlm_sql: Registering sql_groupcmp for %s",
- group_name);
+ DEBUG("rlm_sql (%s): Registering sql_groupcmp for %s",
+ xlat_name, group_name);
paircompare_register(dattr->attr, PW_USER_NAME,
sql_groupcmp, inst);
}
-
- free(group_name);
}
rad_assert(xlat_name);
/*
* Register the SQL xlat function
*/
- inst->config->xlat_name = strdup(xlat_name);
- xlat_register(xlat_name, (RAD_XLAT_FUNC)sql_xlat, inst);
+ inst->config->xlat_name = talloc_strdup(inst->config, xlat_name);
+ xlat_register(xlat_name, sql_xlat, inst);
+
+ /*
+ * If the configuration parameters can't be parsed, then fail.
+ */
+ if ((cf_section_parse(conf, inst->config, module_config) < 0) ||
+ (parse_sub_section(conf, inst,
+ &inst->config->accounting,
+ RLM_COMPONENT_ACCT) < 0) ||
+ (parse_sub_section(conf, inst,
+ &inst->config->postauth,
+ RLM_COMPONENT_POST_AUTH) < 0)) {
+ radlog(L_ERR, "rlm_sql (%s): Failed parsing configuration",
+ inst->config->xlat_name);
+ return -1;
+ }
/*
+ * Sanity check for crazy people.
+ */
+ if (strncmp(inst->config->sql_driver, "rlm_sql_", 8) != 0) {
+ radlog(L_ERR, "rlm_sql (%s): \"%s\" is NOT an SQL driver!",
+ inst->config->xlat_name, inst->config->sql_driver);
+ return -1;
+ }
+
+ /*
* Load the appropriate driver for our database
*/
inst->handle = lt_dlopenext(inst->config->sql_driver);
lt_dlerror());
radlog(L_ERR, "Make sure it (and all its dependent libraries!)"
"are in the search path of your system's ld.");
-
- goto error;
+ return -1;
}
inst->module = (rlm_sql_module_t *) lt_dlsym(inst->handle,
radlog(L_ERR, "Could not link symbol %s: %s",
inst->config->sql_driver,
lt_dlerror());
-
- goto error;
+ return -1;
}
radlog(L_INFO, "rlm_sql (%s): Driver %s (module %s) loaded and linked",
inst->config->sql_server, inst->config->sql_port,
inst->config->sql_db);
- if (sql_init_socketpool(inst) < 0)
- goto error;
+ if (sql_init_socketpool(inst) < 0) return -1;
if (inst->config->groupmemb_query &&
inst->config->groupmemb_query[0]) {
if (inst->config->do_clients) {
if (generate_sql_clients(inst) == -1){
radlog(L_ERR, "Failed to load clients from SQL.");
-
- goto error;
+ return -1;
}
}
- allowed_chars = inst->config->allowed_chars;
-
- *instance = inst;
return RLM_MODULE_OK;
-
- error:
- rlm_sql_detach(inst);
-
- return -1;
}
-static int rlm_sql_authorize(void *instance, REQUEST * request)
+static rlm_rcode_t rlm_sql_authorize(void *instance, REQUEST * request)
{
+ int ret = RLM_MODULE_NOTFOUND;
+
+ rlm_sql_t *inst = instance;
+ rlm_sql_handle_t *handle;
+
VALUE_PAIR *check_tmp = NULL;
VALUE_PAIR *reply_tmp = NULL;
VALUE_PAIR *user_profile = NULL;
- int found = 0;
+
int dofallthrough = 1;
int rows;
- SQLSOCK *sqlsocket;
- SQL_INST *inst = instance;
- char querystr[MAX_QUERY_LEN];
- char sqlusername[MAX_STRING_LEN];
- /*
- * the profile username is used as the sqlusername during
- * profile checking so that we don't overwrite the orignal
- * sqlusername string
- */
- char profileusername[MAX_STRING_LEN];
-
- /*
- * Set, escape, and check the user attr here
- */
- if (sql_set_user(inst, request, sqlusername, NULL) < 0)
- return RLM_MODULE_FAIL;
+ char querystr[MAX_QUERY_LEN];
/*
- * Reserve a socket
+ * Set, escape, and check the user attr here
*/
- sqlsocket = sql_get_socket(inst);
- if (sqlsocket == NULL) {
- /* Remove the username we (maybe) added above */
- pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
+ if (sql_set_user(inst, request, NULL) < 0)
return RLM_MODULE_FAIL;
- }
-
/*
- * After this point, ALL 'return's MUST release the SQL socket!
+ * Reserve a socket
+ *
+ * After this point use goto error or goto release to cleanup sockets
+ * temporary pairlists and temporary attributes.
*/
+ handle = sql_get_socket(inst);
+ if (handle == NULL)
+ goto error;
/*
- * Alright, start by getting the specific entry for the user
+ * Query the check table to find any conditions associated with
+ * this user/realm/whatever...
*/
- if (!radius_xlat(querystr, sizeof(querystr), inst->config->authorize_check_query, request, sql_escape_func)) {
- radlog_request(L_ERR, 0, request, "Error generating query; rejecting user");
- sql_release_socket(inst, sqlsocket);
- /* Remove the username we (maybe) added above */
- pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
- return RLM_MODULE_FAIL;
- }
- rows = sql_getvpdata(inst, &sqlsocket, &check_tmp, querystr);
- if (rows < 0) {
- radlog_request(L_ERR, 0, request, "SQL query error; rejecting user");
- sql_release_socket(inst, sqlsocket);
- /* Remove the username we (maybe) added above */
- pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
- pairfree(&check_tmp);
- return RLM_MODULE_FAIL;
- } else if (rows > 0) {
+ if (inst->config->authorize_check_query &&
+ *inst->config->authorize_check_query) {
+ if (!radius_xlat(querystr, sizeof(querystr), inst->config->authorize_check_query, request, sql_escape_func, inst)) {
+ radlog_request(L_ERR, 0, request, "Error generating query; rejecting user");
+
+ goto error;
+ }
+
+ rows = sql_getvpdata(inst, &handle, &check_tmp, querystr);
+ if (rows < 0) {
+ radlog_request(L_ERR, 0, request, "SQL query error; rejecting user");
+
+ goto error;
+ }
+
/*
- * Only do this if *some* check pairs were returned
+ * Only do this if *some* check pairs were returned
*/
- if (paircompare(request, request->packet->vps, check_tmp, &request->reply->vps) == 0) {
- found = 1;
+ if ((rows > 0) &&
+ (paircompare(request, request->packet->vps, check_tmp, &request->reply->vps) == 0)) {
RDEBUG2("User found in radcheck table");
+
+ radius_xlat_move(request, &request->config_items, &check_tmp);
+
+ ret = RLM_MODULE_OK;
+ }
+
+ /*
+ * We only process reply table items if check conditions
+ * were verified
+ */
+ else
+ goto skipreply;
+ }
+
+ if (inst->config->authorize_reply_query &&
+ *inst->config->authorize_reply_query) {
+ /*
+ * Now get the reply pairs since the paircompare matched
+ */
+ if (!radius_xlat(querystr, sizeof(querystr), inst->config->authorize_reply_query, request, sql_escape_func, inst)) {
+ radlog_request(L_ERR, 0, request, "Error generating query; rejecting user");
+
+ goto error;
+ }
+
+ rows = sql_getvpdata(inst, &handle, &reply_tmp, querystr);
+ if (rows < 0) {
+ radlog_request(L_ERR, 0, request, "SQL query error; rejecting user");
- if (inst->config->authorize_reply_query &&
- *inst->config->authorize_reply_query) {
-
- /*
- * Now get the reply pairs since the paircompare matched
- */
- if (!radius_xlat(querystr, sizeof(querystr), inst->config->authorize_reply_query, request, sql_escape_func)) {
- radlog_request(L_ERR, 0, request, "Error generating query; rejecting user");
- sql_release_socket(inst, sqlsocket);
- /* Remove the username we (maybe) added above */
- pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
- pairfree(&check_tmp);
- return RLM_MODULE_FAIL;
- }
- if (sql_getvpdata(inst, &sqlsocket, &reply_tmp, querystr) < 0) {
- radlog_request(L_ERR, 0, request, "SQL query error; rejecting user");
- sql_release_socket(inst, sqlsocket);
- /* Remove the username we (maybe) added above */
- pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
- pairfree(&check_tmp);
- pairfree(&reply_tmp);
-
- return RLM_MODULE_FAIL;
- }
-
+ goto error;
+ }
+
+ if (rows > 0) {
if (!inst->config->read_groups)
dofallthrough = fallthrough(reply_tmp);
- pairxlatmove(request, &request->reply->vps, &reply_tmp);
- }
- pairxlatmove(request, &request->config_items, &check_tmp);
+
+ radius_xlat_move(request, &request->reply->vps, &reply_tmp);
+
+ ret = RLM_MODULE_OK;
}
}
+
+ skipreply:
/*
- * Clear out the pairlists
+ * Clear out the pairlists
*/
pairfree(&check_tmp);
pairfree(&reply_tmp);
/*
- * dofallthrough is set to 1 by default so that if the user information
- * is not found, we will still process groups. If the user information,
- * however, *is* found, Fall-Through must be set in order to process
- * the groups as well
+ * dofallthrough is set to 1 by default so that if the user information
+ * is not found, we will still process groups. If the user information,
+ * however, *is* found, Fall-Through must be set in order to process
+ * the groups as well.
*/
if (dofallthrough) {
- rows = rlm_sql_process_groups(inst, request, sqlsocket, &dofallthrough);
+ rows = rlm_sql_process_groups(inst, request, handle, &dofallthrough);
if (rows < 0) {
radlog_request(L_ERR, 0, request, "Error processing groups; rejecting user");
- sql_release_socket(inst, sqlsocket);
- /* Remove the username we (maybe) added above */
- pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
- return RLM_MODULE_FAIL;
- } else if (rows > 0) {
- found = 1;
+
+ goto error;
}
+
+ if (rows > 0)
+ ret = RLM_MODULE_OK;
}
/*
- * repeat the above process with the default profile or User-Profile
+ * Repeat the above process with the default profile or User-Profile
*/
if (dofallthrough) {
- int profile_found = 0;
/*
- * Check for a default_profile or for a User-Profile.
- */
- user_profile = pairfind(request->config_items, PW_USER_PROFILE, 0);
- if (inst->config->default_profile[0] != 0 || user_profile != NULL){
- char *profile = inst->config->default_profile;
-
- if (user_profile != NULL)
- profile = user_profile->vp_strvalue;
- if (profile && strlen(profile)){
- RDEBUG("Checking profile %s", profile);
- if (sql_set_user(inst, request, profileusername, profile) < 0) {
- radlog_request(L_ERR, 0, request, "Error setting profile; rejecting user");
- sql_release_socket(inst, sqlsocket);
- /* Remove the username we (maybe) added above */
- pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
- return RLM_MODULE_FAIL;
- } else {
- profile_found = 1;
- }
- }
- }
+ * Check for a default_profile or for a User-Profile.
+ */
+ user_profile = pairfind(request->config_items, PW_USER_PROFILE, 0, TAG_ANY);
+
+ const char *profile = user_profile ?
+ user_profile->vp_strvalue :
+ inst->config->default_profile;
+
+ if (!profile || !*profile)
+ goto release;
+
+ RDEBUG("Checking profile %s", profile);
+
+ if (sql_set_user(inst, request, profile) < 0) {
+ radlog_request(L_ERR, 0, request, "Error setting profile; rejecting user");
- if (profile_found) {
- rows = rlm_sql_process_groups(inst, request, sqlsocket, &dofallthrough);
- if (rows < 0) {
- radlog_request(L_ERR, 0, request, "Error processing profile groups; rejecting user");
- sql_release_socket(inst, sqlsocket);
- /* Remove the username we (maybe) added above */
- pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
- return RLM_MODULE_FAIL;
- } else if (rows > 0) {
- found = 1;
- }
+ goto error;
}
- }
-
- /* Remove the username we (maybe) added above */
- pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
- sql_release_socket(inst, sqlsocket);
+
+ rows = rlm_sql_process_groups(inst, request, handle, &dofallthrough);
+ if (rows < 0) {
+ radlog_request(L_ERR, 0, request, "Error processing profile groups; rejecting user");
- if (!found) {
- RDEBUG("User %s not found", sqlusername);
- return RLM_MODULE_NOTFOUND;
- } else {
- return RLM_MODULE_OK;
+ goto error;
+ }
+
+ if (rows > 0)
+ ret = RLM_MODULE_OK;
}
+
+ goto release;
+
+ error:
+ ret = RLM_MODULE_FAIL;
+
+ release:
+ sql_release_socket(inst, handle);
+
+ pairfree(&check_tmp);
+ pairfree(&reply_tmp);
+
+ return ret;
}
/*
* doesn't update any rows, the next matching config item is used.
*
*/
-static int rlm_sql_redundant(SQL_INST *inst, REQUEST *request,
- rlm_sql_config_section_t *section)
+static int acct_redundant(rlm_sql_t *inst, REQUEST *request,
+ sql_acct_section_t *section)
{
- int ret = RLM_MODULE_OK;
+ int ret = RLM_MODULE_OK;
- SQLSOCK *sqlsocket = NULL;
- int sql_ret;
- int numaffected = 0;
+ rlm_sql_handle_t *handle = NULL;
+ int sql_ret;
+ int numaffected = 0;
- CONF_ITEM *item;
- CONF_PAIR *pair;
- const char *attr = NULL;
- const char *value;
+ CONF_ITEM *item;
+ CONF_PAIR *pair;
+ const char *attr = NULL;
+ const char *value;
char path[MAX_STRING_LEN];
char querystr[MAX_QUERY_LEN];
- char sqlusername[MAX_STRING_LEN];
char *p = path;
- sql_set_user(inst, request, sqlusername, NULL);
+ rad_assert(section);
if (section->reference[0] != '.')
*p++ = '.';
- if (radius_xlat(p, (sizeof(path) - (p - path)) - 1,
- section->reference, request, NULL) < 0)
+ if (!radius_xlat(p, (sizeof(path) - (p - path)) - 1,
+ section->reference, request, NULL, NULL))
return RLM_MODULE_FAIL;
item = cf_reference_item(NULL, section->cs, path);
pair = cf_itemtopair(item);
attr = cf_pair_attr(pair);
- RDEBUG2("Failing between pairs with name '%s'", attr);
+ RDEBUG2("Using query template '%s'", attr);
- sqlsocket = sql_get_socket(inst);
- if (sqlsocket == NULL)
+ handle = sql_get_socket(inst);
+ if (handle == NULL)
return RLM_MODULE_FAIL;
+
+ sql_set_user(inst, request, NULL);
while (TRUE) {
value = cf_pair_value(pair);
- if (!value)
- goto null_query;
+ if (!value) {
+ RDEBUG("Ignoring null query");
+ ret = RLM_MODULE_NOOP;
+
+ goto release;
+ }
radius_xlat(querystr, sizeof(querystr), value, request,
- sql_escape_func);
- if (!*querystr)
- goto null_query;
+ sql_escape_func, inst);
+ if (!*querystr) {
+ RDEBUG("Ignoring null query");
+ ret = RLM_MODULE_NOOP;
+
+ goto release;
+ }
- query_log(inst, request, section, querystr);
+ rlm_sql_query_log(inst, request, section, querystr);
- sql_ret = rlm_sql_query(&sqlsocket, inst, querystr);
+ /*
+ * If rlm_sql_query cannot use the socket it'll try and
+ * reconnect. Reconnecting will automatically release
+ * the current socket, and try to select a new one.
+ *
+ * If we get SQL_DOWN it means all connections in the pool
+ * were exhausted, and we couldn't create a new connection,
+ * so we do not need to call sql_release_socket.
+ */
+ sql_ret = rlm_sql_query(&handle, inst, querystr);
if (sql_ret == SQL_DOWN)
return RLM_MODULE_FAIL;
-
- rad_assert(sqlsocket);
+
+ rad_assert(handle);
/*
* Assume all other errors are incidental, and just meant our
*/
if (sql_ret == 0) {
numaffected = (inst->module->sql_affected_rows)
- (sqlsocket, inst->config);
+ (handle, inst->config);
if (numaffected > 0)
break;
RDEBUG("No records updated");
}
- (inst->module->sql_finish_query)(sqlsocket, inst->config);
+ (inst->module->sql_finish_query)(handle, inst->config);
/*
* We assume all entries with the same name form a redundant
RDEBUG("Trying next query...");
}
- (inst->module->sql_finish_query)(sqlsocket, inst->config);
+ (inst->module->sql_finish_query)(handle, inst->config);
release:
-
- sql_release_socket(inst, sqlsocket);
+ sql_release_socket(inst, handle);
return ret;
-
- null_query:
-
- radlog_request(L_DBG, 0, request, "Ignoring null query");
-
- sql_release_socket(inst, sqlsocket);
-
- return RLM_MODULE_NOOP;
}
#ifdef WITH_ACCOUNTING
/*
* Accounting: Insert or update session data in our sql table
*/
-static int rlm_sql_accounting(void *instance, REQUEST * request) {
- SQL_INST *inst = instance;
+static rlm_rcode_t rlm_sql_accounting(void *instance, REQUEST * request) {
+ rlm_sql_t *inst = instance;
- return rlm_sql_redundant(inst, request, &inst->config->accounting);
+ if (inst->config->accounting) {
+ return acct_redundant(inst, request, inst->config->accounting);
+ }
+
+ return RLM_MODULE_NOOP;
}
#endif
* logins by querying the terminal server (using eg. SNMP).
*/
-static int rlm_sql_checksimul(void *instance, REQUEST * request) {
- SQLSOCK *sqlsocket;
- SQL_INST *inst = instance;
- SQL_ROW row;
+static rlm_rcode_t rlm_sql_checksimul(void *instance, REQUEST * request) {
+ rlm_sql_handle_t *handle;
+ rlm_sql_t *inst = instance;
+ rlm_sql_row_t row;
char querystr[MAX_QUERY_LEN];
- char sqlusername[MAX_STRING_LEN];
int check = 0;
uint32_t ipno = 0;
char *call_num = NULL;
}
- if(sql_set_user(inst, request, sqlusername, NULL) < 0)
+ if(sql_set_user(inst, request, NULL) < 0)
return RLM_MODULE_FAIL;
- radius_xlat(querystr, sizeof(querystr), inst->config->simul_count_query, request, sql_escape_func);
+ radius_xlat(querystr, sizeof(querystr), inst->config->simul_count_query, request, sql_escape_func, inst);
/* initialize the sql socket */
- sqlsocket = sql_get_socket(inst);
- if(sqlsocket == NULL)
+ handle = sql_get_socket(inst);
+ if(handle == NULL)
return RLM_MODULE_FAIL;
- if(rlm_sql_select_query(&sqlsocket, inst, querystr)) {
- sql_release_socket(inst, sqlsocket);
+ if(rlm_sql_select_query(&handle, inst, querystr)) {
+ sql_release_socket(inst, handle);
return RLM_MODULE_FAIL;
}
- ret = rlm_sql_fetch_row(&sqlsocket, inst);
+ ret = rlm_sql_fetch_row(&handle, inst);
if (ret != 0) {
- (inst->module->sql_finish_select_query)(sqlsocket, inst->config);
- sql_release_socket(inst, sqlsocket);
+ (inst->module->sql_finish_select_query)(handle, inst->config);
+ sql_release_socket(inst, handle);
return RLM_MODULE_FAIL;
}
- row = sqlsocket->row;
+ row = handle->row;
if (row == NULL) {
- (inst->module->sql_finish_select_query)(sqlsocket, inst->config);
- sql_release_socket(inst, sqlsocket);
+ (inst->module->sql_finish_select_query)(handle, inst->config);
+ sql_release_socket(inst, handle);
return RLM_MODULE_FAIL;
}
request->simul_count = atoi(row[0]);
- (inst->module->sql_finish_select_query)(sqlsocket, inst->config);
+ (inst->module->sql_finish_select_query)(handle, inst->config);
if(request->simul_count < request->simul_max) {
- sql_release_socket(inst, sqlsocket);
+ sql_release_socket(inst, handle);
return RLM_MODULE_OK;
}
*/
if (!inst->config->simul_verify_query ||
(inst->config->simul_verify_query[0] == '\0')) {
- sql_release_socket(inst, sqlsocket);
+ sql_release_socket(inst, handle);
return RLM_MODULE_OK;
}
- radius_xlat(querystr, sizeof(querystr), inst->config->simul_verify_query, request, sql_escape_func);
- if(rlm_sql_select_query(&sqlsocket, inst, querystr)) {
- sql_release_socket(inst, sqlsocket);
+ radius_xlat(querystr, sizeof(querystr), inst->config->simul_verify_query, request, sql_escape_func, inst);
+ if(rlm_sql_select_query(&handle, inst, querystr)) {
+ sql_release_socket(inst, handle);
return RLM_MODULE_FAIL;
}
*/
request->simul_count = 0;
- if ((vp = pairfind(request->packet->vps, PW_FRAMED_IP_ADDRESS, 0)) != NULL)
+ if ((vp = pairfind(request->packet->vps, PW_FRAMED_IP_ADDRESS, 0, TAG_ANY)) != NULL)
ipno = vp->vp_ipaddr;
- if ((vp = pairfind(request->packet->vps, PW_CALLING_STATION_ID, 0)) != NULL)
+ if ((vp = pairfind(request->packet->vps, PW_CALLING_STATION_ID, 0, TAG_ANY)) != NULL)
call_num = vp->vp_strvalue;
- while (rlm_sql_fetch_row(&sqlsocket, inst) == 0) {
- row = sqlsocket->row;
+ while (rlm_sql_fetch_row(&handle, inst) == 0) {
+ row = handle->row;
if (row == NULL)
break;
if (!row[2]){
- (inst->module->sql_finish_select_query)(sqlsocket, inst->config);
- sql_release_socket(inst, sqlsocket);
+ (inst->module->sql_finish_select_query)(handle, inst->config);
+ sql_release_socket(inst, handle);
RDEBUG("Cannot zap stale entry. No username present in entry.", inst->config->xlat_name);
return RLM_MODULE_FAIL;
}
if (!row[1]){
- (inst->module->sql_finish_select_query)(sqlsocket, inst->config);
- sql_release_socket(inst, sqlsocket);
+ (inst->module->sql_finish_select_query)(handle, inst->config);
+ sql_release_socket(inst, handle);
RDEBUG("Cannot zap stale entry. No session id in entry.", inst->config->xlat_name);
return RLM_MODULE_FAIL;
}
* Failed to check the terminal server for
* duplicate logins: return an error.
*/
- (inst->module->sql_finish_select_query)(sqlsocket, inst->config);
- sql_release_socket(inst, sqlsocket);
+ (inst->module->sql_finish_select_query)(handle, inst->config);
+ sql_release_socket(inst, handle);
radlog_request(L_ERR, 0, request, "Failed to check the terminal server for user '%s'.", row[2]);
return RLM_MODULE_FAIL;
}
}
- (inst->module->sql_finish_select_query)(sqlsocket, inst->config);
- sql_release_socket(inst, sqlsocket);
+ (inst->module->sql_finish_select_query)(handle, inst->config);
+ sql_release_socket(inst, handle);
/*
* The Auth module apparently looks at request->simul_count,
/*
* Postauth: Write a record of the authentication attempt
*/
-static int rlm_sql_postauth(void *instance, REQUEST * request) {
- SQL_INST *inst = instance;
+static rlm_rcode_t rlm_sql_postauth(void *instance, REQUEST * request) {
+ rlm_sql_t *inst = instance;
+
+ if (inst->config->postauth) {
+ return acct_redundant(inst, request, inst->config->postauth);
+ }
- return rlm_sql_redundant(inst, request, &inst->config->postauth);
+ return RLM_MODULE_NOOP;
}
/*