Jeff Carneal <jeff@apex.net>
authorjcarneal <jcarneal>
Fri, 2 Feb 2001 21:31:46 +0000 (21:31 +0000)
committerjcarneal <jcarneal>
Fri, 2 Feb 2001 21:31:46 +0000 (21:31 +0000)
Finally.  The SQL config-based queries patch.  It's really alpha, and there
are probably bugs.  However, whatever bugs exist should be simple, as the
logic behind the patch is straight-forward.

src/modules/rlm_sql/conf.h
src/modules/rlm_sql/drivers/rlm_sql_iodbc/sql_iodbc.c
src/modules/rlm_sql/drivers/rlm_sql_iodbc/sql_iodbc.h
src/modules/rlm_sql/drivers/rlm_sql_oracle/sql_oracle.c
src/modules/rlm_sql/drivers/rlm_sql_oracle/sql_oracle.h
src/modules/rlm_sql/rlm_sql.c
src/modules/rlm_sql/rlm_sql.h
src/modules/rlm_sql/sql.c
src/modules/rlm_sql/sql_module.c
src/modules/rlm_sql/sql_module.h

index 2f366de..6dd05b6 100644 (file)
@@ -5,6 +5,36 @@
 *                                                                          *
 *                                     Mike Machado <mike@innercite.com>    *
 ***************************************************************************/
+
+typedef struct sql_config {
+       char   *sql_server;
+       char   *sql_login;
+       char   *sql_password;
+       char   *sql_db;
+       char   *sql_acct_table;
+       char   *sql_acct_table2;
+       char   *sql_authcheck_table;
+       char   *sql_authreply_table;
+       char   *sql_groupcheck_table;
+       char   *sql_groupreply_table;
+       char   *sql_usergroup_table;
+       char   *sql_nas_table;
+       char   *sql_dict_table;
+       char   *authorize_query;
+       char   *authorize_group_query;
+       char   *authenticate_query;
+       char   *accounting_onoff_query;
+       char   *accounting_update_query;
+       char   *accounting_start_query;
+       char   *accounting_start_query_alt;
+       char   *accounting_stop_query;
+       char   *accounting_stop_query_alt;
+       int     sqltrace;
+       char   *tracefile;
+       int     deletestalesessions;
+       int     num_sql_socks;
+} SQL_CONFIG;
+
 #define CHECKRAD1              "/usr/sbin/checkrad"
 #define CHECKRAD2              "/usr/local/sbin/checkrad"
 
 
 #define ASCEND_PORT_HACK
 #define ASCEND_CHANNELS_PER_LINE        23
-
 #define CISCO_ACCOUNTING_HACK
 
 /* SQL defines */
-#define SQL_LOCK_LEN                   sizeof(SQLACCTREC)
+#define MAX_QUERY_LEN                  4096
+#define SQL_LOCK_LEN                   MAX_QUERY_LEN
 #define        SQLTRACEFILE                    RADLOG_DIR "/sqltrace.sql"
-#define SQLBIGREC                      32
-#define SQLLILREC                      15
 
 #define MAX_COMMUNITY_LEN              50
 #define MAX_SQL_SOCKS                  256
index 259dc44..ac21aea 100644 (file)
@@ -274,6 +274,7 @@ void sql_close(SQLSOCK *socket)
  *
  *************************************************************************/
 void sql_finish_query(SQLSOCK *socket) {
+       sql_free_result(socket);
 }
 
 
index 5a4e834..4035e3c 100644 (file)
@@ -28,28 +28,6 @@ typedef struct sql_socket {
        struct sql_socket *next;
 } SQLSOCK;
 
-typedef struct sql_config {
-       char    *sql_server;
-       char    *sql_login;
-       char    *sql_password;
-       char    *sql_db;
-       char    *sql_acct_table;
-       char    *sql_authcheck_table;
-       char    *sql_authreply_table;
-       char    *sql_groupcheck_table;
-       char    *sql_groupreply_table;
-       char    *sql_usergroup_table;
-       char    *sql_realm_table;
-       char    *sql_realmgroup_table;
-       char    *sql_nas_table;
-       char    *sql_dict_table;
-       int     sensitiveusername;
-       int     sqltrace;
-       char    *tracefile;
-       int     deletestalesessions;
-       int     num_sql_socks;
-} SQL_CONFIG;
-
 typedef struct sql_inst {
        int used;
        SQLSOCK *sqlpool;
index 7c34ebf..53a4b8e 100644 (file)
@@ -366,7 +366,13 @@ SQL_ROW sql_fetch_row(SQLSOCK *socket)
  *
  *************************************************************************/
 void sql_free_result(SQLSOCK *socket) {
-       /* Nothing to do here for Oracle */
+       int i=0;
+
+       for(i=0; i<sql_num_fields(socket); i++) {
+               free(socket->results[i]);
+       }
+       free(socket->results);
+       socket->results=NULL;
 }
 
 
@@ -436,6 +442,7 @@ void sql_close(SQLSOCK *socket)
 void sql_finish_query(SQLSOCK *socket)
 {
        /* Nothing to do here for Oracle */
+       sql_free_result(socket);
 }
 
 
index f26d292..1d86992 100644 (file)
@@ -21,28 +21,6 @@ typedef struct {
        int             in_use;
        struct timeval  tv;
 } SQLSOCK;
-typedef struct sql_config {
-       char    *sql_server;
-       char    *sql_login;
-       char    *sql_password;
-       char    *sql_db;
-       char    *sql_acct_table;
-       char    *sql_authcheck_table;
-       char    *sql_authreply_table;
-       char    *sql_groupcheck_table;
-       char    *sql_groupreply_table;
-       char    *sql_usergroup_table;
-       char    *sql_realm_table;
-       char    *sql_realmgroup_table;
-       char    *sql_nas_table;
-       char    *sql_dict_table;
-       int     sensitiveusername;
-       int     sqltrace;
-       char    *tracefile;
-       int     deletestalesessions;
-       int     num_sql_socks;
-} SQL_CONFIG;
 
 typedef struct sql {
        SQL_CONFIG *config;
index c560f0e..f2b4534 100644 (file)
  * Copyright 2000  The FreeRADIUS server project
  * Copyright 2000  Mike Machado <mike@innercite.com>
  * Copyright 2000  Alan DeKok <aland@ox.org>
+ *
+ * If you want this code to look right, set your tabstop to 2 or 3 
+ * for vi users -  :set ts=3
+ *
  */
 
 static const char rcsid[] =
-"$Id$";
+
+       "$Id$";
 
 #include "autoconf.h"
 
@@ -55,20 +60,39 @@ static CONF_PARSER module_config[] = {
        {"password", PW_TYPE_STRING_PTR, &config.sql_password, ""},
        {"radius_db", PW_TYPE_STRING_PTR, &config.sql_db, "radius"},
        {"acct_table", PW_TYPE_STRING_PTR, &config.sql_acct_table, "radacct"},
-       {"authcheck_table", PW_TYPE_STRING_PTR, &config.sql_authcheck_table, "radcheck"},
-       {"authreply_table", PW_TYPE_STRING_PTR, &config.sql_authreply_table, "radreply"},
-       {"groupcheck_table", PW_TYPE_STRING_PTR, &config.sql_groupcheck_table, "radgroupcheck"},
-       {"groupreply_table", PW_TYPE_STRING_PTR, &config.sql_groupreply_table, "radgroupreply"},
-       {"usergroup_table", PW_TYPE_STRING_PTR, &config.sql_usergroup_table, "usergroup"},
-       {"realm_table", PW_TYPE_STRING_PTR, &config.sql_realm_table, "realms"},
-       {"realmgroup_table", PW_TYPE_STRING_PTR, &config.sql_realmgroup_table, "realmgroup"},
+       {"acct_table2", PW_TYPE_STRING_PTR, &config.sql_acct_table2, "radacct"},
+       {"authcheck_table", PW_TYPE_STRING_PTR, &config.sql_authcheck_table,
+        "radcheck"},
+       {"authreply_table", PW_TYPE_STRING_PTR, &config.sql_authreply_table,
+        "radreply"},
+       {"groupcheck_table", PW_TYPE_STRING_PTR, &config.sql_groupcheck_table,
+        "radgroupcheck"},
+       {"groupreply_table", PW_TYPE_STRING_PTR, &config.sql_groupreply_table,
+        "radgroupreply"},
+       {"usergroup_table", PW_TYPE_STRING_PTR, &config.sql_usergroup_table,
+        "usergroup"},
        {"nas_table", PW_TYPE_STRING_PTR, &config.sql_nas_table, "nas"},
        {"dict_table", PW_TYPE_STRING_PTR, &config.sql_dict_table, "dictionary"},
-       {"sensitiveusername", PW_TYPE_BOOLEAN, &config.sensitiveusername, "1"},
        {"sqltrace", PW_TYPE_BOOLEAN, &config.sqltrace, "0"},
        {"sqltracefile", PW_TYPE_STRING_PTR, &config.tracefile, SQLTRACEFILE},
        {"deletestalesessions", PW_TYPE_BOOLEAN, &config.deletestalesessions, "0"},
        {"num_sql_socks", PW_TYPE_INTEGER, &config.num_sql_socks, "5"},
+       {"authorize_query", PW_TYPE_STRING_PTR, &config.authorize_query, ""},
+       {"authorize_group_query", PW_TYPE_STRING_PTR,
+        &config.authorize_group_query, ""},
+       {"authenticate_query", PW_TYPE_STRING_PTR, &config.authenticate_query, ""},
+       {"accounting_onoff_query", PW_TYPE_STRING_PTR,
+        &config.accounting_onoff_query, ""},
+       {"accounting_update_query", PW_TYPE_STRING_PTR,
+        &config.accounting_update_query, ""},
+       {"accounting_start_query", PW_TYPE_STRING_PTR,
+        &config.accounting_start_query, ""},
+       {"accounting_start_query_alt", PW_TYPE_STRING_PTR,
+        &config.accounting_start_query_alt, ""},
+       {"accounting_stop_query", PW_TYPE_STRING_PTR, &config.accounting_stop_query,
+        ""},
+       {"accounting_stop_query_alt", PW_TYPE_STRING_PTR,
+        &config.accounting_stop_query_alt, ""},
 
        {NULL, -1, NULL, NULL}
 };
@@ -76,7 +100,9 @@ static CONF_PARSER module_config[] = {
 /***********************************************************************
  * start of main routines
  ***********************************************************************/
-static int rlm_sql_init(void) {
+static int
+rlm_sql_init(void)
+{
 
        /*
         * FIXME:
@@ -88,7 +114,9 @@ static int rlm_sql_init(void) {
        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;
 
@@ -105,73 +133,91 @@ static int rlm_sql_instantiate(CONF_SECTION *conf, void **instance) {
        memset(inst->config, 0, sizeof(SQL_CONFIG));
 
 #if HAVE_PTHREAD_H
-       inst->lock = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
+       inst->lock = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t));
        if (inst->lock == NULL)
                return -1;
        pthread_mutex_init(inst->lock, NULL);
 
-       inst->notfull = (pthread_cond_t *)malloc(sizeof(pthread_cond_t));
+       inst->notfull = (pthread_cond_t *) malloc(sizeof(pthread_cond_t));
        pthread_cond_init(inst->notfull, NULL);
 #endif
 
        /*
         * If the configuration parameters can't be parsed, then
         * fail.
-       */
+        */
        if (cf_section_parse(conf, module_config) < 0) {
                free(inst->config);
                free(inst);
                return -1;
        }
 
-       if(config.num_sql_socks > MAX_SQL_SOCKS) {
-               radlog(L_ERR | L_CONS, "sql_instantiate:  number of sqlsockets cannot exceed %d", MAX_SQL_SOCKS);
+       if (config.num_sql_socks > MAX_SQL_SOCKS) {
+               radlog(L_ERR | L_CONS,
+                                        "sql_instantiate:  number of sqlsockets cannot exceed %d",
+                                        MAX_SQL_SOCKS);
                free(inst->config);
                free(inst);
                return -1;
        }
 
-       inst->config->sql_server                = config.sql_server;
-       inst->config->sql_login                 = config.sql_login;
-       inst->config->sql_password              = config.sql_password;
-       inst->config->sql_db                    = config.sql_db;
-       inst->config->sql_acct_table            = config.sql_acct_table;        
-       inst->config->sql_authcheck_table       = config.sql_authcheck_table;
-       inst->config->sql_authreply_table       = config.sql_authreply_table;
-       inst->config->sql_groupcheck_table      = config.sql_groupcheck_table;
-       inst->config->sql_groupreply_table      = config.sql_groupreply_table;
-       inst->config->sql_usergroup_table       = config.sql_usergroup_table;
-       inst->config->sql_realm_table           = config.sql_realm_table;
-       inst->config->sql_realmgroup_table      = config.sql_realmgroup_table;
-       inst->config->sql_nas_table             = config.sql_nas_table;
-       inst->config->sql_dict_table            = config.sql_dict_table;
-       inst->config->sensitiveusername         = config.sensitiveusername;
-       inst->config->sqltrace                  = config.sqltrace;
-       inst->config->tracefile                 = config.tracefile;
-       inst->config->deletestalesessions       = config.deletestalesessions;
-       inst->config->num_sql_socks             = config.num_sql_socks;
-
-       config.sql_server               = NULL;
-       config.sql_login                = NULL;
-       config.sql_password             = NULL;
-       config.sql_db                   = NULL;
-       config.sql_acct_table           = NULL;
-       config.sql_authcheck_table      = NULL;
-       config.sql_authreply_table      = NULL;
-       config.sql_groupcheck_table     = NULL;
-       config.sql_groupreply_table     = NULL;
-       config.sql_usergroup_table      = NULL;
-       config.sql_realm_table          = NULL;
-       config.sql_realmgroup_table     = NULL;
-       config.sql_nas_table            = NULL;
-       config.sql_dict_table           = NULL;
-       config.tracefile                = NULL;
+       inst->config->sql_server = config.sql_server;
+       inst->config->sql_login = config.sql_login;
+       inst->config->sql_password = config.sql_password;
+       inst->config->sql_db = config.sql_db;
+       inst->config->sql_acct_table = config.sql_acct_table;
+       inst->config->sql_acct_table2 = config.sql_acct_table2;
+       inst->config->sql_authcheck_table = config.sql_authcheck_table;
+       inst->config->sql_authreply_table = config.sql_authreply_table;
+       inst->config->sql_groupcheck_table = config.sql_groupcheck_table;
+       inst->config->sql_groupreply_table = config.sql_groupreply_table;
+       inst->config->sql_usergroup_table = config.sql_usergroup_table;
+       inst->config->sql_nas_table = config.sql_nas_table;
+       inst->config->sql_dict_table = config.sql_dict_table;
+       inst->config->sqltrace = config.sqltrace;
+       inst->config->tracefile = config.tracefile;
+       inst->config->deletestalesessions = config.deletestalesessions;
+       inst->config->num_sql_socks = config.num_sql_socks;
+       inst->config->authorize_query = config.authorize_query;
+       inst->config->authorize_group_query = config.authorize_group_query;
+       inst->config->authenticate_query = config.authenticate_query;
+       inst->config->accounting_onoff_query = config.accounting_onoff_query;
+       inst->config->accounting_update_query = config.accounting_update_query;
+       inst->config->accounting_start_query = config.accounting_start_query;
+       inst->config->accounting_start_query_alt =
+               config.accounting_start_query_alt;
+       inst->config->accounting_stop_query = config.accounting_stop_query;
+       inst->config->accounting_stop_query_alt = config.accounting_stop_query_alt;
+
+       config.sql_server = NULL;
+       config.sql_login = NULL;
+       config.sql_password = NULL;
+       config.sql_db = NULL;
+       config.sql_acct_table = NULL;
+       config.sql_acct_table2 = NULL;
+       config.sql_authcheck_table = NULL;
+       config.sql_authreply_table = NULL;
+       config.sql_groupcheck_table = NULL;
+       config.sql_groupreply_table = NULL;
+       config.sql_usergroup_table = NULL;
+       config.sql_nas_table = NULL;
+       config.sql_dict_table = NULL;
+       config.tracefile = NULL;
+       config.authorize_query = NULL;
+       config.authorize_group_query = NULL;
+       config.authenticate_query = NULL;
+       config.accounting_onoff_query = NULL;
+       config.accounting_update_query = NULL;
+       config.accounting_start_query = NULL;
+       config.accounting_start_query_alt = NULL;
+       config.accounting_stop_query = NULL;
+       config.accounting_stop_query_alt = NULL;
 
        radlog(L_INFO, "rlm_sql: Attempting to connect to %s@%s:%s",
-               inst->config->sql_login, inst->config->sql_server,
-               inst->config->sql_db);
+                                inst->config->sql_login, inst->config->sql_server,
+                                inst->config->sql_db);
 
-       if(sql_init_socketpool(inst) < 0) {
+       if (sql_init_socketpool(inst) < 0) {
                free(inst->config);
                free(inst);
                return -1;
@@ -182,12 +228,16 @@ static int rlm_sql_instantiate(CONF_SECTION *conf, void **instance) {
        return RLM_MODULE_OK;
 }
 
-static int rlm_sql_destroy(void) {
+static int
+rlm_sql_destroy(void)
+{
 
        return 0;
 }
 
-static int rlm_sql_detach(void *instance) {
+static int
+rlm_sql_detach(void *instance)
+{
 
        SQL_INST *inst = instance;
 
@@ -199,66 +249,92 @@ static int rlm_sql_detach(void *instance) {
 }
 
 
-static int rlm_sql_authorize(void *instance, REQUEST * request) {
+static int
+rlm_sql_authorize(void *instance, REQUEST * request)
+{
 
-       int     nas_port = 0;
        VALUE_PAIR *check_tmp = NULL;
        VALUE_PAIR *reply_tmp = NULL;
-       VALUE_PAIR *tmp;
        int     found = 0;
        char   *name;
        SQLSOCK *sqlsocket;
        SQL_INST *inst = instance;
+       char    querystr[MAX_QUERY_LEN];
+       char    saveuser[MAX_STRING_LEN];
+       int     savelen = 0;
 
-       name = request->username->strvalue;
+       VALUE_PAIR *uservp = NULL;
+
+       sqlsocket = sql_get_socket(inst);
 
        /*
-        *      Check for valid input, zero length names not permitted
+        * Set, escape, and check the user attr here
         */
+       uservp = set_userattr(request->packet->vps, NULL, saveuser, &savelen);
+       name = uservp->strvalue;
        if (name[0] == 0) {
                radlog(L_ERR, "zero length username not permitted\n");
+               sql_release_socket(inst, sqlsocket);
+               restore_userattr(uservp, saveuser, savelen);
                return -1;
        }
 
-       sqlsocket = sql_get_socket(inst);
-
-       /*
-        *      Find the NAS port ID.
-        */
-       if ((tmp = pairfind(request->packet->vps, PW_NAS_PORT_ID)) != NULL)
-               nas_port = tmp->lvalue;
-
-
+       radius_xlat2(querystr, MAX_QUERY_LEN, inst->config->authorize_query,
+                                                        request);
+       found =
+               sql_getvpdata(inst, sqlsocket, &check_tmp, &reply_tmp, querystr,
+                                                                       PW_VP_USERDATA);
        /*
         *      Find the entry for the user.
         */
-       if ((found = sql_getvpdata(inst, sqlsocket, inst->config->sql_authcheck_table, &check_tmp, name, PW_VP_USERDATA)) > 0) {
-               sql_getvpdata(inst, sqlsocket, inst->config->sql_groupcheck_table, &check_tmp, name, PW_VP_GROUPDATA);
-               sql_getvpdata(inst, sqlsocket, inst->config->sql_authreply_table, &reply_tmp, name, PW_VP_USERDATA);
-               sql_getvpdata(inst, sqlsocket, inst->config->sql_groupreply_table, &reply_tmp, name, PW_VP_GROUPDATA);
-       } else if(found < 0) {
+       if (found > 0) {
+               radius_xlat2(querystr, MAX_QUERY_LEN,
+                                                                inst->config->authorize_group_query, request);
+               sql_getvpdata(inst, sqlsocket, &check_tmp, &reply_tmp,
+                                                                       querystr, PW_VP_GROUPDATA);
+       } else if (found < 0) {
                radlog(L_ERR, "rlm_sql:  SQL query error; rejecting user");
+               sql_release_socket(inst, sqlsocket);
+               restore_userattr(uservp, saveuser, savelen);
                return -1;
 
        } else {
 
-               int     gcheck, greply;
+               int     gcheck;
 
-               gcheck = sql_getvpdata(inst, sqlsocket, inst->config->sql_groupcheck_table, &check_tmp, "DEFAULT", PW_VP_GROUPDATA);
-               greply = sql_getvpdata(inst, sqlsocket, inst->config->sql_groupreply_table, &reply_tmp, "DEFAULT", PW_VP_GROUPDATA);
-               if (gcheck && greply)
+               /*
+                * We didn't find the user, so we try looking
+                * for a DEFAULT entry
+                */
+               set_userattr(uservp, "DEFAULT", NULL, NULL);
+               radius_xlat2(querystr, MAX_QUERY_LEN,
+                                                                inst->config->authorize_group_query, request);
+               gcheck = sql_getvpdata(inst, sqlsocket, &check_tmp, &reply_tmp,
+                                                                                                        querystr, PW_VP_GROUPDATA);
+               if (gcheck)
                        found = 1;
        }
+       restore_userattr(uservp, saveuser, savelen);
 
        sql_release_socket(inst, sqlsocket);
 
        if (!found) {
-               radlog(L_DBG,"rlm_sql: User %s not found and DEFAULT not found", name);
+               radlog(L_DBG, "rlm_sql: User %s not found and DEFAULT not found", name);
                return RLM_MODULE_NOTFOUND;
        }
 
+       /*
+        * Uncomment these lines for debugging
+        * Recompile, and run 'radiusd -X'
+        *
+        DEBUG2("rlm_sql:  check items");
+        vp_printlist(stderr, check_tmp);
+        DEBUG2("rlm_sql:  reply items");
+        vp_printlist(stderr, reply_tmp);
+        */
+
        if (paircmp(request->packet->vps, check_tmp, &reply_tmp) != 0) {
-               radlog(L_INFO,"rlm_sql: Pairs do not match [%s]", name);
+               radlog(L_INFO, "rlm_sql: Pairs do not match [%s]", name);
                return RLM_MODULE_FAIL;
        }
 
@@ -271,45 +347,41 @@ static int rlm_sql_authorize(void *instance, REQUEST * request) {
 }
 
 static int
-rlm_sql_authenticate(void *instance, REQUEST *request)
+rlm_sql_authenticate(void *instance, REQUEST * request)
 {
 
        SQL_ROW row;
        SQLSOCK *sqlsocket;
-       char   *querystr;
-       char    escaped_user[AUTH_STRING_LEN * 3];
-       char   *user;
-       const char query[] = "SELECT Value FROM %s WHERE UserName = '%s' AND Attribute = 'Password'";
+       char    querystr[MAX_QUERY_LEN];
+       VALUE_PAIR *uservp;
+       char    saveuser[MAX_STRING_LEN];
+       int     savelen = 0;
        SQL_INST *inst = instance;
 
-       user = request->username->strvalue;
-
        /*
         *      Ensure that a password attribute exists.
         */
        if ((request->password == NULL) ||
                        (request->password->length == 0) ||
                        (request->password->attribute != PW_PASSWORD)) {
-               radlog(L_AUTH, "rlm_sql: Attribute \"Password\" is required for authentication.");
+               radlog(L_AUTH,
+                                        "rlm_sql: Attribute \"Password\" is required for authentication.");
                return RLM_MODULE_INVALID;
        }
 
-       sql_escape_string(escaped_user, user, strlen(user));
-
        /*
-        *      This should really be replaced with a static buffer...
+        * 1. Set username to escaped value
+        * 2. Translate vars in the query
+        * 3. Replace User-Name attr with saved value
         */
-       if ((querystr = malloc(strlen(escaped_user) +
-                                                                                                strlen(inst->config->sql_authcheck_table) +
-                                                                                                sizeof(query))) == NULL) {
-               radlog(L_ERR | L_CONS, "no memory");
-               exit(1);
-       }
+       uservp = set_userattr(request->packet->vps, NULL, saveuser, &savelen);
+       radius_xlat2(querystr, MAX_QUERY_LEN, inst->config->authenticate_query,
+                                                        request);
+       restore_userattr(uservp, saveuser, savelen);
 
-       sprintf(querystr, query, inst->config->sql_authcheck_table, escaped_user);
        sqlsocket = sql_get_socket(inst);
        if (sql_select_query(inst, sqlsocket, querystr) < 0) {
-               radlog(L_ERR,"rlm_sql_authenticate: database query error");
+               radlog(L_ERR, "rlm_sql_authenticate: database query error");
                sql_release_socket(inst, sqlsocket);
                return RLM_MODULE_REJECT;
        }
@@ -317,19 +389,19 @@ rlm_sql_authenticate(void *instance, REQUEST *request)
        row = sql_fetch_row(sqlsocket);
        sql_finish_select_query(sqlsocket);
        sql_release_socket(inst, sqlsocket);
-       sql_free_result(sqlsocket);
-       free(querystr);
 
        if (row == NULL) {
-               radlog(L_ERR,"rlm_sql_authenticate: no rows returned from query (no such user)");
+               radlog(L_ERR,
+                                        "rlm_sql_authenticate: no rows returned from query (no such user)");
                return RLM_MODULE_REJECT;
        }
 
-       /* Just compare the two */
+       /*
+        * Just compare the two 
+        */
        if (strncmp(request->password->strvalue,
-               row[0],
-               request->password->length) != 0) {
-                       return RLM_MODULE_REJECT;
+                                                       row[0], request->password->length) != 0) {
+               return RLM_MODULE_REJECT;
        }
        return RLM_MODULE_OK;
 
@@ -338,173 +410,177 @@ rlm_sql_authenticate(void *instance, REQUEST *request)
 /*
  *     Accounting: save the account data to our sql table
  */
-static int rlm_sql_accounting(void *instance, REQUEST * request) {
+static int
+rlm_sql_accounting(void *instance, REQUEST * request)
+{
 
-       time_t  nowtime;
-       struct tm *tim;
-       char    datebuf[20];
-       VALUE_PAIR *pair;
-       SQLACCTREC *sqlrecord;
        SQLSOCK *sqlsocket;
-       DICT_VALUE *dval;
+       VALUE_PAIR *pair;
        SQL_INST *inst = instance;
-       int lentmp = 0;
+       int     numaffected = 0;
+       int     acctstatustype = 0;
+       char    querystr[MAX_QUERY_LEN];
+       char    logstr[MAX_QUERY_LEN];
+
+#ifdef CISCO_ACCOUNTING_HACK
+       int     acctsessiontime = 0;
+#endif
+
+       sqlsocket = sql_get_socket(inst);
+       memset(querystr, 0, MAX_QUERY_LEN);
 
        /*
-        * FIXME:  Should we really do this malloc?
-        * Why not a static structure, because this malloc is 
-        * relatively expensive considering we do it for every
-        * accounting packet
+        * Find the Acct Status Type
         */
-       if ((sqlrecord = malloc(sizeof(SQLACCTREC))) == NULL) {
-               radlog(L_ERR | L_CONS, "no memory");
-               exit(1);
+       if ((pair = pairfind(request->packet->vps, PW_ACCT_STATUS_TYPE)) != NULL) {
+               acctstatustype = pair->lvalue;
+       } else {
+               radius_xlat2(logstr, MAX_QUERY_LEN,
+                                                                "rlm_sql:  packet has no account status"
+                                                                "type.  (user '%{User-Name}', nas '%{NAS-IP-Address}')",
+                                                                request);
+               radlog(L_ERR, logstr);
+               return 0;
        }
-       memset(sqlrecord, 0, sizeof(SQLACCTREC));
-
-       pair = request->packet->vps;
-       while (pair != (VALUE_PAIR *) NULL) {
 
-               /*
-                * Check the pairs to see if they are anything we are interested in. 
-                */
-               switch (pair->attribute) {
-                       case PW_ACCT_SESSION_ID:
-                               strncpy(sqlrecord->AcctSessionId, pair->strvalue, SQLBIGREC);
-                               break;
-
-                       case PW_ACCT_UNIQUE_SESSION_ID:
-                               strncpy(sqlrecord->AcctUniqueId, pair->strvalue, SQLBIGREC);
-                               break;
-
-                       case PW_USER_NAME:
-                               strncpy(sqlrecord->UserName, pair->strvalue, SQLBIGREC);
-                               break;
-
-                       case PW_NAS_IP_ADDRESS:
-                               ip_ntoa(sqlrecord->NASIPAddress, pair->lvalue);
-                               //ipaddr2str(sqlrecord->NASIPAddress, pair->lvalue);
-                               break;
-
-                       case PW_NAS_PORT_ID:
-                               sqlrecord->NASPortId = pair->lvalue;
-                               break;
-
-                       case PW_NAS_PORT_TYPE:
-                               dval = dict_valbyattr(PW_NAS_PORT_TYPE, pair->lvalue);
-                               if (dval != NULL) {
-                                       strncpy(sqlrecord->NASPortType, dval->name, SQLBIGREC);
-                               }
-                               break;
-
-                       case PW_ACCT_STATUS_TYPE:
-                               sqlrecord->AcctStatusTypeId = pair->lvalue;
-                               dval = dict_valbyattr(PW_ACCT_STATUS_TYPE, pair->lvalue);
-                               if (dval != NULL) {
-                                       strncpy(sqlrecord->AcctStatusType, dval->name, SQLBIGREC);
-                               }
-                               break;
-
-                       case PW_ACCT_SESSION_TIME:
-                               sqlrecord->AcctSessionTime = pair->lvalue;
-                               break;
-
-                       case PW_ACCT_AUTHENTIC:
-                               dval = dict_valbyattr(PW_ACCT_AUTHENTIC, pair->lvalue);
-                               if (dval != NULL) {
-                                       strncpy(sqlrecord->AcctAuthentic, dval->name, SQLBIGREC);
-                               }
-                               break;
-
-                       case PW_CONNECT_INFO:
-                               strncpy(sqlrecord->ConnectInfo, pair->strvalue, SQLBIGREC);
-                               break;
-
-                       case PW_ACCT_INPUT_OCTETS:
-                               sqlrecord->AcctInputOctets = pair->lvalue;
-                               break;
-
-                       case PW_ACCT_OUTPUT_OCTETS:
-                               sqlrecord->AcctOutputOctets = pair->lvalue;
-                               break;
-
-                       case PW_CALLED_STATION_ID:
-                               strncpy(sqlrecord->CalledStationId, pair->strvalue, SQLLILREC);
-                               break;
-
-                       case PW_CALLING_STATION_ID:
-       /* USR 00 workaround */
-                               lentmp = strlen(pair->strvalue);
-                               if(lentmp > 10) {
-                                       strncpy(sqlrecord->CallingStationId, pair->strvalue+(lentmp-10), SQLLILREC);
-                               } else {
-                                       strncpy(sqlrecord->CallingStationId, pair->strvalue, SQLLILREC);
-                               }
-                               break;
+#ifdef CISCO_ACCOUNTING_HACK
+       /*
+        * If stop but zero session length AND no previous
+        * session found, drop it as in invalid packet 
+        * This is to fix CISCO's aaa from filling our  
+        * table with bogus crap
+        */
+       if ((pair = pairfind(request->packet->vps, PW_ACCT_SESSION_TIME)) != NULL)
+               acctsessiontime = pair->lvalue;
+
+       if ((acctsessiontime <= 0) && (acctstatustype == PW_STATUS_STOP)) {
+               radius_xlat2(logstr, MAX_QUERY_LEN,
+                                                                "rlm_sql:  Stop packet with zero session"
+                                                                "length.  (user '%{User-Name}', nas '%{NAS-IP-Address}')",
+                                                                request);
+               radlog(L_ERR, logstr);
+               return 0;
+       }
+#endif
 
-                       case PW_ACCT_TERMINATE_CAUSE:
-                               dval = dict_valbyattr(PW_ACCT_TERMINATE_CAUSE, pair->lvalue);
-                               if(dval != NULL) {
-                                       strncpy(sqlrecord->AcctTerminateCause, dval->name, SQLBIGREC);
-                               }
-                               break;
+       switch (acctstatustype) {
+                       /*
+                        * The Terminal server informed us that it was rebooted
+                        * STOP all records from this NAS 
+                        */
+               case PW_STATUS_ACCOUNTING_ON:
+               case PW_STATUS_ACCOUNTING_OFF:
+                       radlog(L_INFO, "rlm_sql:  received Acct On/Off packet");
+                       radius_xlat2(querystr, MAX_QUERY_LEN,
+                                                                        inst->config->accounting_onoff_query, request);
+                       query_log(inst, querystr);
+
+                       if (querystr) {
+                               if (sql_query(inst, sqlsocket, querystr) < 0)
+                                       radlog(L_ERR,
+                                                                "rlm_sql: Couldn't update SQL accounting for ALIVE packet - %s",
+                                                                sql_error(sqlsocket));
+                               sql_finish_query(sqlsocket);
+                       }
+
+                       break;
+
+                       /*
+                        * Got an update accounting packet
+                        */
+               case PW_STATUS_ALIVE:
 
-                       case PW_SERVICE_TYPE:
-                               dval = dict_valbyattr(PW_SERVICE_TYPE, pair->lvalue);
-                               if (dval != NULL) {
-                                       strncpy(sqlrecord->ServiceType, dval->name, SQLBIGREC);
-                               }
-                               break;
+                       radius_xlat2(querystr, MAX_QUERY_LEN,
+                                                                        inst->config->accounting_update_query, request);
+                       query_log(inst, querystr);
 
-                       case PW_FRAMED_PROTOCOL:
-                               dval = dict_valbyattr(PW_FRAMED_PROTOCOL, pair->lvalue);
-                               if (dval != NULL) {
-                                       strncpy(sqlrecord->FramedProtocol, dval->name, SQLBIGREC);
-                               }
-                               break;
+                       if (querystr) {
+                               if (sql_query(inst, sqlsocket, querystr) < 0)
+                                       radlog(L_ERR,
+                                                                "rlm_sql: Couldn't update SQL accounting for ALIVE packet - %s",
+                                                                sql_error(sqlsocket));
+                               sql_finish_query(sqlsocket);
+                       }
 
-                       case PW_FRAMED_IP_ADDRESS:
-                               ip_ntoa(sqlrecord->FramedIPAddress, pair->lvalue);
-                               //ipaddr2str(sqlrecord->FramedIPAddress, pair->lvalue);
-                               break;
+                       break;
 
-                       case PW_ACCT_DELAY_TIME:
-                               sqlrecord->AcctDelayTime = pair->lvalue;
-                               break;
-
-                       /* 
-                        * FIXME:  USR VSA for:  USR-Connect-Speed 
-                        * Ugly hack.  Will go away when conf-based
-                        * tables are implemented
+                       /*
+                        * Got accounting start packet
                         */
-      case 167971:
-                               dval = dict_valbyattr(167971, pair->lvalue);
-                               if(dval != NULL)  {
-                                       strncpy(sqlrecord->ConnectInfo, dval->name, SQLBIGREC);
+               case PW_STATUS_START:
+
+                       radius_xlat2(querystr, MAX_QUERY_LEN,
+                                                                        inst->config->accounting_start_query, request);
+                       query_log(inst, querystr);
+
+                       if (querystr) {
+                               if (sql_query(inst, sqlsocket, querystr) < 0) {
+                                       radlog(L_ERR, "rlm_sql: Couldn't update SQL accounting"
+                                                                "for ALIVE packet - %s", sql_error(sqlsocket));
+                                       sql_finish_query(sqlsocket);
+
+                                       /*
+                                        * We failed the insert above.  It's probably because 
+                                        * the stop record came before the start.  We try an
+                                        * our alternate query now (typically an UPDATE)
+                                        */
+                                       radius_xlat2(querystr, MAX_QUERY_LEN,
+                                                                                        inst->config->accounting_start_query_alt, request);
+                                       query_log(inst, querystr);
+
+                                       if (querystr) {
+                                               if (sql_query(inst, sqlsocket, querystr) < 0) {
+                                                       radlog(L_ERR, "rlm_sql: Couldn't update SQL"
+                                                                                "accounting START record - %s", sql_error(sqlsocket));
+                                               }
+                                               sql_finish_query(sqlsocket);
+                                       }
                                }
-                               break;
+                       }
+                       break;
 
-                       /* Appears to be LE-Terminate-Detail */
-                       case 65538:
-                               strncpy(sqlrecord->AcctTerminateCause, pair->strvalue, SQLBIGREC);
-                               break;
+                       /*
+                        * Got accounting stop packet
+                        */
+               case PW_STATUS_STOP:
 
-                       default:
-                               break;
-               }
+                       radius_xlat2(querystr, MAX_QUERY_LEN,
+                                                                        inst->config->accounting_stop_query, request);
+                       query_log(inst, querystr);
 
-               pair = pair->next;
+                       if (querystr) {
+                               if ((querystr) && sql_query(inst, sqlsocket, querystr) < 0) {
+                                       radlog(L_ERR,
+                                                                "rlm_sql: Couldn't insert SQL accounting START record - %s",
+                                                                sql_error(sqlsocket));
+                               }
+                               sql_finish_query(sqlsocket);
+                       }
+
+                       numaffected = sql_affected_rows(sqlsocket);
+                       if (numaffected < 1) {
+                               /*
+                                * If our update above didn't match anything
+                                * we assume it's because we haven't seen a 
+                                * matching Start record.  So we have to
+                                * insert this stop rather than do an update
+                                */
+                               radius_xlat2(querystr, MAX_QUERY_LEN,
+                                                                                inst->config->accounting_stop_query_alt, request);
+                               query_log(inst, querystr);
+
+                               if (querystr) {
+                                       if (sql_query(inst, sqlsocket, querystr) < 0) {
+                                               radlog(L_ERR,
+                                                                        "rlm_sql: Couldn't update SQL accounting START record - %s",
+                                                                        sql_error(sqlsocket));
+                                       }
+                                       sql_finish_query(sqlsocket);
+                               }
+                       }
+                       break;
        }
 
-
-       nowtime = request->timestamp - sqlrecord->AcctDelayTime;
-       tim = localtime(&nowtime);
-       strftime(datebuf, sizeof(datebuf), "%Y%m%d%H%M%S", tim);
-
-       strncpy(sqlrecord->AcctTimeStamp, datebuf, 20);
-
-       sqlsocket = sql_get_socket(inst);
-       sql_save_acct(inst, sqlsocket, sqlrecord);
        sql_release_socket(inst, sqlsocket);
 
        return RLM_MODULE_OK;
@@ -514,14 +590,14 @@ static int rlm_sql_accounting(void *instance, REQUEST * request) {
 /* globally exported name */
 module_t rlm_sql = {
        "SQL",
-       0,                      /* type: reserved */
-       rlm_sql_init,           /* initialization */
-       rlm_sql_instantiate,    /* instantiation */
-       rlm_sql_authorize,      /* authorization */
-       rlm_sql_authenticate,   /* authentication */
-       NULL,                   /* preaccounting */
-       rlm_sql_accounting,     /* accounting */
-       NULL,                   /* checksimul */
-       rlm_sql_detach,         /* detach */
-       rlm_sql_destroy,        /* destroy */
+       0,                                                                                                              /* type: reserved */
+       rlm_sql_init,                                                                   /* initialization */
+       rlm_sql_instantiate,                                    /* instantiation */
+       rlm_sql_authorize,                                              /* authorization */
+       rlm_sql_authenticate,                                   /* authentication */
+       NULL,                                                                                                   /* preaccounting */
+       rlm_sql_accounting,                                             /* accounting */
+       NULL,                                                                                                   /* checksimul */
+       rlm_sql_detach,                                                         /* detach */
+       rlm_sql_destroy,                                                        /* destroy */
 };
index d1ded0a..b9bec49 100644 (file)
@@ -1,4 +1,3 @@
-
 /***************************************************************************
 *  rlm_sql.h                          rlm_sql - FreeRADIUS SQL Module      *
 *                                                                          *
 #define PW_VP_GROUPDATA                2
 #define PW_VP_REALMDATA                3
 
-typedef struct sqlrec {
-       char    AcctSessionId[SQLBIGREC];
-       char    AcctUniqueId[SQLBIGREC];
-       char    UserName[SQLBIGREC];
-       char    Realm[SQLBIGREC];
-       char    NASIPAddress[SQLLILREC];
-       unsigned long NASPortId;
-       char    NASPortType[SQLBIGREC];
-       char    AcctStatusType[SQLBIGREC];
-       unsigned int AcctStatusTypeId;
-       char    AcctTimeStamp[20];
-       unsigned long AcctSessionTime;
-       char    AcctAuthentic[SQLBIGREC];
-       char    ConnectInfo[SQLBIGREC];
-       unsigned long AcctInputOctets;
-       unsigned long AcctOutputOctets;
-       char    CalledStationId[SQLLILREC];
-       char    CallingStationId[SQLLILREC];
-       char    AcctTerminateCause[SQLBIGREC];
-       char    ServiceType[SQLBIGREC];
-       char    FramedProtocol[SQLBIGREC];
-       char    FramedIPAddress[SQLLILREC];
-       unsigned long AcctDelayTime;
-} SQLACCTREC;
-
-int     sql_init_socketpool(SQL_INST *inst);
-void   sql_poolfree(SQL_INST *inst);
-int     sql_close_socket(SQLSOCK *sqlsocket);
-SQLSOCK *sql_get_socket(SQL_INST *inst);
-int     sql_release_socket(SQL_INST *inst, SQLSOCK *sqlsocket);
-int     sql_save_acct(SQL_INST *inst, SQLSOCK *sqlsocket, SQLACCTREC * sqlrecord);
-int     sql_userparse(VALUE_PAIR ** first_pair, SQL_ROW row, int mode);
-int     sql_read_realms(SQLSOCK *sqlsocket);
-int     sql_getvpdata(SQL_INST *inst, SQLSOCK *sqlsocket, char *table, VALUE_PAIR ** vp, char *user, int mode);
-int     sql_check_multi(SQL_INST *inst, SQLSOCK *sqlsocket, char *name, VALUE_PAIR * request, int maxsimul);
-int     sql_read_naslist(SQLSOCK *sqlsocket);
-int     sql_read_clients(SQLSOCK *sqlsocket);
-int     sql_dict_init(SQLSOCK *sqlsocket);
+#define PW_ITEM_CHECK                  0
+#define PW_ITEM_REPLY                  1
 
+int     sql_init_socketpool(SQL_INST * inst);
+void    sql_poolfree(SQL_INST * inst);
+int     sql_close_socket(SQLSOCK * sqlsocket);
+SQLSOCK *sql_get_socket(SQL_INST * inst);
+int     sql_release_socket(SQL_INST * inst, SQLSOCK * sqlsocket);
+int     sql_userparse(VALUE_PAIR ** first_pair, SQL_ROW row,
+                                                                                       int mode, int itemtype);
+int     sql_read_realms(SQLSOCK * sqlsocket);
+int     sql_getvpdata(SQL_INST * inst, SQLSOCK * sqlsocket,
+                                                                                       VALUE_PAIR ** check, VALUE_PAIR ** reply, char *query,
+                                                                                       int mode);
+int     sql_check_multi(SQL_INST * inst, SQLSOCK * sqlsocket, char *name,
+                                                                                               VALUE_PAIR * request, int maxsimul);
+int     sql_read_naslist(SQLSOCK * sqlsocket);
+int     sql_read_clients(SQLSOCK * sqlsocket);
+int     sql_dict_init(SQLSOCK * sqlsocket);
+void    query_log(SQL_INST * inst, char *querystr);
+VALUE_PAIR *set_userattr(VALUE_PAIR * first, char *username,
+                                                                                                char *saveuser, int *savelen);
+void    restore_userattr(VALUE_PAIR * uservp, char *saveuser, int savelen);
index 933fcb5..30d947b 100644 (file)
  *     Purpose: Connect to the sql server
  *
  *************************************************************************/
-int sql_init_socketpool(SQL_INST *inst) {
+int
+sql_init_socketpool(SQL_INST * inst)
+{
 
-       SQLSOCK *sqlsocket;
-       int     i;
+       SQLSOCK *sqlsocket;
+       int     i;
 
        inst->used = 0;
        inst->sqlpool = NULL;
@@ -73,7 +75,7 @@ int sql_init_socketpool(SQL_INST *inst) {
                } else {
                        sqlsocket->id = i;
 #if HAVE_PTHREAD_H
-                       sqlsocket->semaphore = (sem_t *)malloc(sizeof(sem_t));
+                       sqlsocket->semaphore = (sem_t *) malloc(sizeof(sem_t));
                        sem_init(sqlsocket->semaphore, 0, SQLSOCK_UNLOCKED);
 #else
                        sqlsocket->in_use = 0;
@@ -93,7 +95,9 @@ int sql_init_socketpool(SQL_INST *inst) {
  *     Purpose: Clean up and free sql pool
  *
  *************************************************************************/
-void sql_poolfree(SQL_INST *inst) {
+void
+sql_poolfree(SQL_INST * inst)
+{
 
        SQLSOCK *cur;
 
@@ -114,9 +118,11 @@ void sql_poolfree(SQL_INST *inst) {
  *     Purpose: Close and free a sql sqlsocket
  *
  *************************************************************************/
-int sql_close_socket(SQLSOCK *sqlsocket) {
+int
+sql_close_socket(SQLSOCK * sqlsocket)
+{
 
-       radlog(L_DBG,"rlm_sql: Closing sqlsocket %d", sqlsocket->id);
+       radlog(L_DBG, "rlm_sql: Closing sqlsocket %d", sqlsocket->id);
        sql_close(sqlsocket);
 #if HAVE_PTHREAD_H
        sem_destroy(sqlsocket->semaphore);
@@ -133,7 +139,9 @@ int sql_close_socket(SQLSOCK *sqlsocket) {
  *     Purpose: Return a SQL sqlsocket from the connection pool           
  *
  *************************************************************************/
-SQLSOCK *sql_get_socket(SQL_INST *inst) {
+SQLSOCK *
+sql_get_socket(SQL_INST * inst)
+{
 
 
        SQLSOCK *cur;
@@ -146,7 +154,9 @@ SQLSOCK *sql_get_socket(SQL_INST *inst) {
 #if HAVE_PTHREAD_H
                pthread_cond_wait(inst->notfull, inst->lock);
 #else
-               /* FIXME: Subsecond sleep needed here */
+               /*
+                * FIXME: Subsecond sleep needed here 
+                */
                sleep(1);
 #endif
        }
@@ -163,7 +173,7 @@ SQLSOCK *sql_get_socket(SQL_INST *inst) {
 #else
                        cur->in_use = SQLSOCK_LOCKED;
 #endif
-                       radlog(L_DBG,"rlm_sql: Reserved sql socket id: %d", cur->id);
+                       radlog(L_DBG, "rlm_sql: Reserved sql socket id: %d", cur->id);
                        return cur;
                }
        }
@@ -172,7 +182,9 @@ SQLSOCK *sql_get_socket(SQL_INST *inst) {
        pthread_mutex_unlock(inst->lock);
 #endif
 
-       /* Should never get here, but what the hey */
+       /*
+        * Should never get here, but what the hey 
+        */
        return NULL;
 }
 
@@ -183,7 +195,9 @@ SQLSOCK *sql_get_socket(SQL_INST *inst) {
  *     Purpose: Frees a SQL sqlsocket back to the connection pool           
  *
  *************************************************************************/
-int sql_release_socket(SQL_INST *inst, SQLSOCK *sqlsocket) {
+int
+sql_release_socket(SQL_INST * inst, SQLSOCK * sqlsocket)
+{
 
 #if HAVE_PTHREAD_H
        pthread_mutex_lock(inst->lock);
@@ -195,7 +209,7 @@ int sql_release_socket(SQL_INST *inst, SQLSOCK *sqlsocket) {
        sqlsocket->in_use = 0;
 #endif
 
-       radlog(L_DBG,"rlm_sql: Released sql socket id: %d", sqlsocket->id);
+       radlog(L_DBG, "rlm_sql: Released sql socket id: %d", sqlsocket->id);
 
 #if HAVE_PTHREAD_H
        pthread_mutex_unlock(inst->lock);
@@ -208,328 +222,25 @@ int sql_release_socket(SQL_INST *inst, SQLSOCK *sqlsocket) {
 
 /*************************************************************************
  *
- *     Function: sql_save_acct
- *
- *     Purpose: Write data from the sqlrecord structure to the database
- *
- *************************************************************************/
-
-int sql_save_acct(SQL_INST *inst, SQLSOCK *sqlsocket, SQLACCTREC *sqlrecord) {
-
-       char    querystr[2048];
-       FILE   *sqlfile=0;
-       int     num = 0;
-       int                     acctunique = 0;
-
-#ifdef NT_DOMAIN_HACK
-       char   *ptr;
-       char    newname[AUTH_STRING_LEN];
-#endif
-
-       acctunique = strlen(sqlrecord->AcctUniqueId);
-
-       if(inst->config->sqltrace) {
-               if ((sqlfile = fopen(inst->config->tracefile, "a")) == (FILE *) NULL) {
-                       radlog(L_ERR, "rlm_sql: Couldn't open file %s", inst->config->tracefile);
-               } else {
-#if defined(F_LOCK) && !defined(BSD)
-                       (void) lockf((int) sqlfile, (int) F_LOCK, (off_t) SQL_LOCK_LEN);
-#else
-                       (void) flock(sqlfile, SQL_LOCK_EX);
-#endif
-               }
-       }
-
-#ifdef NT_DOMAIN_HACK
-       /*
-        *      Windows NT machines often authenticate themselves as
-        *      NT_DOMAIN\username. Try to be smart about this.
-        *
-        *      FIXME: should we handle this as a REALM ?
-        */
-       if ((ptr = strchr(sqlrecord->UserName, '\\')) != NULL) {
-               strncpy(newname, ptr + 1, sizeof(newname));
-               newname[sizeof(newname) - 1] = 0;
-               strcpy(sqlrecord->UserName, newname);
-       }
-#endif /*
-                         * NT_DOMAIN_HACK 
-                         */
-
-       if (sqlrecord->AcctStatusTypeId == PW_STATUS_ACCOUNTING_ON ||
-                       sqlrecord->AcctStatusTypeId == PW_STATUS_ACCOUNTING_OFF) {
-               radlog(L_INFO, "rlm_sql:  Portmaster %s rebooted at %s", sqlrecord->NASIPAddress,
-                                        sqlrecord->AcctTimeStamp);
-
-               /*
-                * The Terminal server informed us that it was rebooted
-                * * STOP all records from this NAS 
-                */
-
-               sprintf(querystr,
-                                               "UPDATE %s SET AcctStopTime='%s', AcctSessionTime=unix_timestamp('%s') - unix_timestamp(AcctStartTime), AcctTerminateCause='%s', AcctStopDelay = %ld WHERE AcctSessionTime=0 AND AcctStopTime=0 AND NASIPAddress= '%s' AND AcctStartTime <= '%s'",
-                                               inst->config->sql_acct_table, sqlrecord->AcctTimeStamp,
-                                               sqlrecord->AcctTimeStamp, sqlrecord->AcctTerminateCause,
-                                               sqlrecord->AcctDelayTime, sqlrecord->NASIPAddress,
-                                               sqlrecord->AcctTimeStamp);
-
-               if (sql_query(inst, sqlsocket, querystr) < 0)
-                       radlog(L_ERR, "rlm_sql: Couldn't update SQL accounting after NAS reboot - %s",
-                                                sql_error(sqlsocket));
-               sql_finish_query(sqlsocket);
-
-               if (sqlfile) {
-                       fputs(querystr, sqlfile);
-                       fputs(";\n", sqlfile);
-                       fclose(sqlfile);
-               }
-               return 0;
-       }
-
-       if (sqlrecord->AcctStatusTypeId == PW_STATUS_ALIVE) {
-               /* 
-                * Use acct unique session identifier if present
-                */
-               if(acctunique) { 
-                       sprintf(querystr, "UPDATE %s SET FramedIPAddress = '%s' WHERE AcctUniqueId = '%s'",
-                                                       inst->config->sql_acct_table, sqlrecord->FramedIPAddress,
-                                                       sqlrecord->AcctUniqueId);
-
-               } else {
-                       sprintf(querystr, "UPDATE %s SET FramedIPAddress = '%s' WHERE AcctSessionId = '%s' AND UserName = '%s' AND NASIPAddress= '%s'",
-                                                       inst->config->sql_acct_table, sqlrecord->FramedIPAddress,
-                                                       sqlrecord->AcctSessionId, sqlrecord->UserName,
-                                                       sqlrecord->NASIPAddress);
-               }
-
-               if (sql_query(inst, sqlsocket, querystr) < 0)
-                       radlog(L_ERR, "rlm_sql: Couldn't update SQL accounting for ALIVE packet - %s",
-                                                sql_error(sqlsocket));
-               sql_finish_query(sqlsocket);
-
-               if (sqlfile) {
-                       fputs(querystr, sqlfile);
-                       fputs(";\n", sqlfile);
-                       fclose(sqlfile);
-               }
-               return 0;
-       }
-
-       /*
-        * Got start record 
-        */
-       if (sqlrecord->AcctStatusTypeId == PW_STATUS_START) {
-
-               /*
-                * Insert new record with blank stop time until stop record is got 
-                */
-               snprintf(querystr, 2048,
-            "INSERT INTO %s ("
-            "radacctid,"
-            "acctsessionid,"
-            "acctuniqueid,"
-            "username,"
-            "realm,"
-            "nasipaddress,"
-            "nasportid,"
-            "nasporttype,"
-            "acctstarttime,"
-            "acctstoptime,"
-            "acctsessiontime,"
-            "acctauthentic,"
-            "connectinfo_start,"
-            "connectinfo_stop,"
-            "acctinputoctets,"
-            "acctoutputoctets,"
-            "calledstationid,"
-            "callingstationid,"
-            "acctterminatecause,"
-            "servicetype,"
-            "framedprotocol,"
-            "framedipaddress,"
-            "acctstartdelay,"
-            "acctstopdelay) "
-            "VALUES (0,"
-            "'%s', '%s', '%s', '%s', '%s', %ld, '%s', '%s',0,"
-            "0, '%s', '%s', '', 0, 0,"
-            "'%s', '%s', '', '%s', '%s', '%s', %ld, 0)",
-            inst->config->sql_acct_table, sqlrecord->AcctSessionId, 
-            sqlrecord->AcctUniqueId, sqlrecord->UserName, 
-            sqlrecord->Realm, sqlrecord->NASIPAddress,
-            sqlrecord->NASPortId, sqlrecord->NASPortType,
-            sqlrecord->AcctTimeStamp, sqlrecord->AcctAuthentic,
-            sqlrecord->ConnectInfo, sqlrecord->CalledStationId,
-            sqlrecord->CallingStationId, sqlrecord->ServiceType,
-            sqlrecord->FramedProtocol, sqlrecord->FramedIPAddress,
-            sqlrecord->AcctDelayTime);
-
-
-               if (sql_query(inst, sqlsocket, querystr) < 0) {
-                       radlog(L_ERR, "rlm_sql: Couldn't insert SQL accounting START record - %s",
-                                                        sql_error(sqlsocket));
-
-                       /*
-                        * We failed the insert above.  It's probably because 
-                        * the stop record came before the start.  We try an
-                        * update here to be sure
-                        */
-                       if(acctunique) {
-                               snprintf(querystr, 2048, "UPDATE %s SET AcctStartTime = '%s', AcctStartDelay = %ld, ConnectInfo_start = '%s' WHERE AcctUniqueId = '%s'",
-                                                                inst->config->sql_acct_table, sqlrecord->AcctTimeStamp,
-                                                                sqlrecord->AcctDelayTime, sqlrecord->ConnectInfo,
-                                                                sqlrecord->AcctUniqueId);
-                       } else {
-                               snprintf(querystr, 2048, "UPDATE %s SET AcctStartTime = '%s', AcctStartDelay = %ld, ConnectInfo_start = '%s' WHERE AcctSessionId = '%s' AND UserName = '%s' AND NASIPAddress = '%s'",
-                                                                inst->config->sql_acct_table, sqlrecord->AcctTimeStamp,
-                                                                sqlrecord->AcctDelayTime, sqlrecord->ConnectInfo,
-                                                                sqlrecord->AcctSessionId, sqlrecord->UserName, 
-                                                                sqlrecord->NASIPAddress);
-                       }
-                       if (sql_query(inst, sqlsocket, querystr) < 0)
-                               radlog(L_ERR, "rlm_sql: Couldn't update SQL accounting START record - %s",
-                                                        sql_error(sqlsocket));
-
-               } 
-               sql_finish_query(sqlsocket);
-
-               /*
-                * Got stop record 
-                */
-       } else {
-
-               /*
-                * Set stop time on matching record with start time 
-                */
-               if(acctunique) {
-                       snprintf(querystr, 2048,
-                                                        "UPDATE %s SET AcctStopTime = '%s', AcctSessionTime = '%lu', AcctInputOctets = '%lu', AcctOutputOctets = '%lu', AcctTerminateCause = '%s', AcctStopDelay = %ld, ConnectInfo_stop = '%s' WHERE AcctUniqueId = '%s'",
-                                                        inst->config->sql_acct_table, sqlrecord->AcctTimeStamp,
-                                                        sqlrecord->AcctSessionTime, sqlrecord->AcctInputOctets,
-                                                        sqlrecord->AcctOutputOctets, sqlrecord->AcctTerminateCause,
-                                                        sqlrecord->AcctDelayTime, sqlrecord->ConnectInfo,
-                                                        sqlrecord->AcctUniqueId);
-
-               } else {
-                       snprintf(querystr, 2048,
-                                                        "UPDATE %s SET AcctStopTime = '%s', AcctSessionTime = '%lu', AcctInputOctets = '%lu', AcctOutputOctets = '%lu', AcctTerminateCause = '%s', AcctStopDelay = %ld, ConnectInfo_stop = '%s' WHERE AcctSessionId = '%s' AND UserName = '%s' AND NASIPAddress = '%s'",
-                                                        inst->config->sql_acct_table, sqlrecord->AcctTimeStamp,
-                                                        sqlrecord->AcctSessionTime, sqlrecord->AcctInputOctets,
-                                                        sqlrecord->AcctOutputOctets, sqlrecord->AcctTerminateCause,
-                                                        sqlrecord->AcctDelayTime, sqlrecord->ConnectInfo,
-                                                        sqlrecord->AcctSessionId, sqlrecord->UserName, 
-                                                        sqlrecord->NASIPAddress);
-               }
-
-
-               if (sql_query(inst, sqlsocket, querystr) < 0)
-                       radlog(L_ERR, "rlm_sql: Couldn't update SQL accounting STOP record - %s",
-                                                sql_error(sqlsocket));
-               sql_finish_query(sqlsocket);
-
-
-               /* 
-                * If our update above didn't match anything
-                * we assume it's because we haven't seen a 
-                * matching Start record.  So we have to
-                * insert this stop rather than do an update
-                */
-               num = sql_affected_rows(sqlsocket);
-               if(num < 1) {
-
-#ifdef CISCO_ACCOUNTING_HACK
-                       /*
-                        * If stop but zero session length AND no previous 
-                        * session found, drop it as in invalid packet 
-                        * This is to fix CISCO's aaa from filling our 
-                        * table with bogus crap 
-                        */
-                       if (sqlrecord->AcctSessionTime <= 0) {
-                               radlog(L_ERR, "rlm_sql: Invalid STOP record. [%s] STOP record but zero session length? (nas %s)",
-                                                        sqlrecord->UserName, sqlrecord->NASIPAddress);
-                               return 0;
-                       }
-#endif
-
-                       /*
-                        * Insert record with no start time until matching start record comes 
-                        */
-                       snprintf(querystr, 2048,
-              "INSERT INTO %s ("
-              "radacctid,"
-              "acctsessionid,"
-              "acctuniqueid,"
-              "username,"
-              "realm,"
-              "nasipaddress,"
-              "nasportid,"
-              "nasporttype,"
-              "acctstarttime,"
-              "acctstoptime,"
-              "acctsessiontime,"
-              "acctauthentic,"
-              "connectinfo_start,"
-              "connectinfo_stop,"
-              "acctinputoctets,"
-              "acctoutputoctets,"
-              "calledstationid,"
-              "callingstationid,"
-              "acctterminatecause,"
-              "servicetype,"
-              "framedprotocol,"
-              "framedipaddress,"
-              "acctstartdelay,"
-              "acctstopdelay) "
-              "VALUES ("
-              "0, '%s', '%s', '%s', '%s', '%s', %ld, '%s', 0,"
-              "'%s', '%lu', '%s', '', '%s', '%lu', '%lu', '%s',"
-              "'%s', '%s', '%s', '%s', '%s', 0, %ld)",
-              inst->config->sql_acct_table, sqlrecord->AcctSessionId,
-              sqlrecord->AcctUniqueId, sqlrecord->UserName, 
-              sqlrecord->Realm, sqlrecord->NASIPAddress,
-              sqlrecord->NASPortId, sqlrecord->NASPortType,
-              sqlrecord->AcctTimeStamp, sqlrecord->AcctSessionTime,
-              sqlrecord->AcctAuthentic, sqlrecord->ConnectInfo,
-              sqlrecord->AcctInputOctets, sqlrecord->AcctOutputOctets,
-              sqlrecord->CalledStationId, sqlrecord->CallingStationId,
-              sqlrecord->AcctTerminateCause, sqlrecord->ServiceType,
-              sqlrecord->FramedProtocol, sqlrecord->FramedIPAddress,
-              sqlrecord->AcctDelayTime);
-
-
-                       if (sql_query(inst, sqlsocket, querystr) < 0)
-                               radlog(L_ERR, "rlm_sql: Couldn't insert SQL accounting STOP record - %s",
-                                                        sql_error(sqlsocket));
-                       sql_finish_query(sqlsocket);
-               }
-
-       }
-       if (sqlfile) {
-               fputs(querystr, sqlfile);
-               fputs(";\n", sqlfile);
-               fflush(sqlfile);
-               fclose(sqlfile);
-       }
-
-       return 0;
-
-}
-
-
-/*************************************************************************
- *
  *     Function: sql_userparse
  *
  *     Purpose: Read entries from the database and fill VALUE_PAIR structures
  *
  *************************************************************************/
-int sql_userparse(VALUE_PAIR ** first_pair, SQL_ROW row, int mode) {
+int
+sql_userparse(VALUE_PAIR ** first_pair, SQL_ROW row, int mode, int itemtype)
+{
 
        DICT_ATTR *attr;
        VALUE_PAIR *pair, *check;
+       int     i = 0;
+
 
+       if (itemtype == PW_ITEM_REPLY)
+               i = 2;
 
-       if ((attr = dict_attrbyname(row[2])) == (DICT_ATTR *) NULL) {
-               radlog(L_ERR | L_CONS, "rlm_sql: unknown attribute %s", row[2]);
+       if ((attr = dict_attrbyname(row[i])) == (DICT_ATTR *) NULL) {
+               radlog(L_ERR | L_CONS, "rlm_sql: unknown attribute %s", row[i]);
                return (-1);
        }
 
@@ -541,11 +252,14 @@ int sql_userparse(VALUE_PAIR ** first_pair, SQL_ROW row, int mode) {
 #if defined( BINARY_FILTERS )
                        attr->type != PW_TYPE_ABINARY &&
 #endif
-                       mode == PW_VP_GROUPDATA) return 0;
+                       mode == PW_VP_GROUPDATA)
+               return 0;
 
-       pair = pairmake(row[2], row[3], T_OP_CMP_EQ);
+       pair = pairmake(row[i], row[i + 1], T_OP_CMP_EQ);
        pairadd(first_pair, pair);
 
+       vp_printlist(stderr, *first_pair);
+
        return 0;
 }
 
@@ -557,58 +271,25 @@ int sql_userparse(VALUE_PAIR ** first_pair, SQL_ROW row, int mode) {
  *     Purpose: Get any group check or reply pairs
  *
  *************************************************************************/
-int sql_getvpdata(SQL_INST *inst, SQLSOCK *sqlsocket, char *table, VALUE_PAIR ** vp, char *user, int mode)
+int
+sql_getvpdata(SQL_INST * inst, SQLSOCK * sqlsocket, VALUE_PAIR ** check,
+                                                       VALUE_PAIR ** reply, char *query, int mode)
 {
 
-       char    querystr[256];
-       char    authstr[256];
-       char    username[AUTH_STRING_LEN * 2 + 1];
        SQL_ROW row;
-       int     rows=0;
-       int     length;
+       int     rows = 0;
 
-       if (strlen(user) > AUTH_STRING_LEN)
-               length = AUTH_STRING_LEN;
-       else
-               length = strlen(user);
-
-       /*
-        * FIXME CHECK user for weird charactors!! 
-        */
-       sql_escape_string(username, user, length);
-
-       if (mode == PW_VP_USERDATA) {
-               if (inst->config->sensitiveusername)
-                       sprintf(authstr, "STRCMP(Username, '%s') = 0", username);
-               else
-                       sprintf(authstr, "UserName = '%s'", username);
-               sprintf(querystr, "SELECT * FROM %s WHERE %s ORDER BY id", table,
-                                               authstr);
-       } else if (mode == PW_VP_GROUPDATA) {
-               if (inst->config->sensitiveusername)
-                       sprintf(authstr, "STRCMP(%s.Username, '%s') = 0",
-                                                       inst->config->sql_usergroup_table, username);
-               else
-                       sprintf(authstr, "%s.UserName = '%s'", inst->config->sql_usergroup_table,
-                                                       username);
-               sprintf(querystr,
-                                               "SELECT %s.* FROM %s, %s WHERE %s AND %s.GroupName = %s.GroupName ORDER BY %s.id",
-                                               table, table, inst->config->sql_usergroup_table, authstr,
-                                               inst->config->sql_usergroup_table, table, table);
-       } else if (mode == PW_VP_REALMDATA)
-               sprintf(querystr,
-                                               "SELECT %s.* FROM %s, %s WHERE %s.RealmName = '%s' AND %s.GroupName = %s.GroupName ORDER BY %s.id",
-                                               table, table, inst->config->sql_realmgroup_table,
-                                               inst->config->sql_realmgroup_table, username,
-                                               inst->config->sql_realmgroup_table, table, table);
-       if (sql_select_query(inst, sqlsocket, querystr) < 0) {
-               radlog(L_ERR,"get_vpdata: database query error");
+       if (sql_select_query(inst, sqlsocket, query) < 0) {
+               radlog(L_ERR, "rlm_sql_getvpdata: database query error");
                return -1;
        }
-
-
        while ((row = sql_fetch_row(sqlsocket))) {
-               if (sql_userparse(vp, row, mode) != 0) {
+               if (sql_userparse(check, row, mode, PW_ITEM_CHECK) != 0) {
+                       radlog(L_ERR | L_CONS, "rlm_sql:  Error getting data from database");
+                       sql_finish_select_query(sqlsocket);
+                       return -1;
+               }
+               if (sql_userparse(reply, row, mode, PW_ITEM_REPLY) != 0) {
                        radlog(L_ERR | L_CONS, "rlm_sql:  Error getting data from database");
                        sql_finish_select_query(sqlsocket);
                        return -1;
@@ -616,10 +297,8 @@ int sql_getvpdata(SQL_INST *inst, SQLSOCK *sqlsocket, char *table, VALUE_PAIR **
                rows++;
        }
        sql_finish_select_query(sqlsocket);
-       sql_free_result(sqlsocket);
 
        return rows;
-
 }
 
 
@@ -637,7 +316,9 @@ alrm_handler()
  *     Purpose: Checks the terminal server for a spacific login entry
  *
  *************************************************************************/
-static int sql_check_ts(SQL_ROW row) {
+static int
+sql_check_ts(SQL_ROW row)
+{
 
        int     pid, st, e;
        int     n;
@@ -724,9 +405,12 @@ static int sql_check_ts(SQL_ROW row) {
  *     Purpose: Check radius accounting for duplicate logins
  *
  *************************************************************************/
-int sql_check_multi(SQL_INST *inst, SQLSOCK *sqlsocket, char *name, VALUE_PAIR * request, int maxsimul) {
+int
+sql_check_multi(SQL_INST * inst, SQLSOCK * sqlsocket, char *name,
+                                                               VALUE_PAIR * request, int maxsimul)
+{
 
-       char    querystr[256];
+       char    querystr[MAX_QUERY_LEN];
        char    authstr[256];
        VALUE_PAIR *fra;
        SQL_ROW row;
@@ -734,21 +418,17 @@ int sql_check_multi(SQL_INST *inst, SQLSOCK *sqlsocket, char *name, VALUE_PAIR *
        uint32_t ipno = 0;
        int     mpp = 1;
 
-       if (inst->config->sensitiveusername)
-               sprintf(authstr, "STRCMP(UserName, '%s') = 0", name);
-       else
-               sprintf(authstr, "UserName = '%s'", name);
+       sprintf(authstr, "UserName = '%s'", name);
        sprintf(querystr, "SELECT COUNT(*) FROM %s WHERE %s AND AcctStopTime = 0",
                                        inst->config->sql_acct_table, authstr);
        if (sql_select_query(inst, sqlsocket, querystr) < 0) {
-               radlog(L_ERR,"sql_check_multi: database query error");
+               radlog(L_ERR, "sql_check_multi: database query error");
                return -1;
        }
 
        row = sql_fetch_row(sqlsocket);
        count = atoi(row[0]);
        sql_finish_select_query(sqlsocket);
-       sql_free_result(sqlsocket);
 
        if (count < maxsimul)
                return 0;
@@ -763,7 +443,7 @@ int sql_check_multi(SQL_INST *inst, SQLSOCK *sqlsocket, char *name, VALUE_PAIR *
        sprintf(querystr, "SELECT * FROM %s WHERE %s AND AcctStopTime = 0",
                                        inst->config->sql_acct_table, authstr);
        if (sql_select_query(inst, sqlsocket, querystr) < 0) {
-               radlog(L_ERR,"sql_check_multi: database query error");
+               radlog(L_ERR, "sql_check_multi: database query error");
                return -1;
        }
        while ((row = sql_fetch_row(sqlsocket))) {
@@ -776,7 +456,8 @@ int sql_check_multi(SQL_INST *inst, SQLSOCK *sqlsocket, char *name, VALUE_PAIR *
                                mpp = 2;
 
                } else if (check == 2)
-                       radlog(L_ERR, "rlm_sql:  Problem with checkrad [%s] (from nas %s)", name, row[4]);
+                       radlog(L_ERR, "rlm_sql:  Problem with checkrad [%s] (from nas %s)",
+                                                name, row[4]);
                else {
                        /*
                         *      False record - zap it
@@ -785,8 +466,9 @@ int sql_check_multi(SQL_INST *inst, SQLSOCK *sqlsocket, char *name, VALUE_PAIR *
                        if (inst->config->deletestalesessions) {
                                SQLSOCK *sqlsocket1;
 
-                               radlog(L_ERR, "rlm_sql:  Deleteing stale session [%s] (from nas %s/%s)", row[2],
-                                                        row[4], row[5]);
+                               radlog(L_ERR,
+                                                        "rlm_sql:  Deleteing stale session [%s] (from nas %s/%s)",
+                                                        row[2], row[4], row[5]);
                                sqlsocket1 = sql_get_socket(inst);
                                sprintf(querystr, "DELETE FROM %s WHERE RadAcctId = '%s'",
                                                                inst->config->sql_acct_table, row[0]);
@@ -797,8 +479,60 @@ int sql_check_multi(SQL_INST *inst, SQLSOCK *sqlsocket, char *name, VALUE_PAIR *
                }
        }
        sql_finish_select_query(sqlsocket);
-       sql_free_result(sqlsocket);
 
        return (count < maxsimul) ? 0 : mpp;
+}
+
+void
+query_log(SQL_INST * inst, char *querystr)
+{
+       FILE   *sqlfile = 0;
+
+       if (inst->config->sqltrace) {
+               if ((sqlfile = fopen(inst->config->tracefile, "a")) == (FILE *) NULL) {
+                       radlog(L_ERR, "rlm_sql: Couldn't open file %s",
+                                                inst->config->tracefile);
+               } else {
+#if defined(F_LOCK) && !defined(BSD)
+                       (void) lockf((int) sqlfile, (int) F_LOCK, (off_t) MAX_QUERY_LEN);
+#else
+                       (void) flock(sqlfile, SQL_LOCK_EX);
+#endif
+                       fputs(querystr, sqlfile);
+                       fputs(";\n", sqlfile);
+                       fclose(sqlfile);
+               }
+       }
+}
+
+VALUE_PAIR *
+set_userattr(VALUE_PAIR * first, char *username, char *saveuser, int *savelen)
+{
+
+       VALUE_PAIR *uservp = NULL;
+       uint8_t escaped_user[MAX_STRING_LEN];
+
+       if ((uservp = pairfind(first, PW_USER_NAME)) != NULL) {
+               if (saveuser)
+                       strNcpy(saveuser, uservp->strvalue, MAX_STRING_LEN);
+               if (savelen)
+                       *savelen = uservp->length;
+               if (username) {
+                       sql_escape_string(escaped_user, username, strlen(username));
+               } else {
+                       sql_escape_string(escaped_user, uservp->strvalue, uservp->length);
+               }
+               strNcpy(uservp->strvalue, escaped_user, MAX_STRING_LEN);
+               uservp->length = strlen(escaped_user);
+       }
+
+       return uservp;
+}
+
+void
+restore_userattr(VALUE_PAIR * uservp, char *saveuser, int savelen)
+{
 
+       strNcpy(uservp->strvalue, saveuser, MAX_STRING_LEN);
+       uservp->length = savelen;
 }
index bc29695..8ae0936 100644 (file)
  *     Purpose: Establish connection to the db
  *
  *************************************************************************/
-SQLSOCK *sql_create_socket(SQL_INST *inst) {
+SQLSOCK *
+sql_create_socket(SQL_INST * inst)
+{
 
        SQLSOCK *sqlsocket;
 
        if ((sqlsocket = malloc(sizeof(SQLSOCK))) == NULL) {
-               radlog(L_CONS|L_ERR, "sql_create_socket: no memory");
+               radlog(L_CONS | L_ERR, "sql_create_socket: no memory");
                exit(1);
        }
 
        mysql_init(&(sqlsocket->conn));
-       if (!(sqlsocket->sock = mysql_real_connect(&(sqlsocket->conn), inst->config->sql_server, inst->config->sql_login, inst->config->sql_password, inst->config->sql_db, 0, NULL, CLIENT_FOUND_ROWS))) {
-               radlog(L_ERR, "rlm_sql: Couldn't connect socket to MySQL server %s@%s:%s", inst->config->sql_login, inst->config->sql_server, inst->config->sql_db);
-               radlog(L_ERR, "rlm_sql:  Mysql error '%s'", mysql_error(&sqlsocket->conn));
+       if (!
+                       (sqlsocket->sock =
+                        mysql_real_connect(&(sqlsocket->conn), inst->config->sql_server,
+                                                                                                       inst->config->sql_login, inst->config->sql_password,
+                                                                                                       inst->config->sql_db, 0, NULL, CLIENT_FOUND_ROWS))) {
+               radlog(L_ERR, "rlm_sql: Couldn't connect socket to MySQL server %s@%s:%s",
+                                        inst->config->sql_login, inst->config->sql_server,
+                                        inst->config->sql_db);
+               radlog(L_ERR, "rlm_sql:  Mysql error '%s'",
+                                        mysql_error(&sqlsocket->conn));
                sqlsocket->sock = NULL;
                return NULL;
        }
@@ -65,11 +74,13 @@ SQLSOCK *sql_create_socket(SQL_INST *inst) {
  *     Purpose: Issue a query to the database
  *
  *************************************************************************/
-int sql_query(SQL_INST *inst, SQLSOCK *sqlsocket, char *querystr) {
+int
+sql_query(SQL_INST * inst, SQLSOCK * sqlsocket, char *querystr)
+{
 
        if (inst->config->sqltrace)
-               DEBUG(querystr);
-        if (sqlsocket->sock == NULL) {
+               DEBUG("query:  %s", querystr);
+       if (sqlsocket->sock == NULL) {
                radlog(L_ERR, "Socket not connected");
                return 0;
        }
@@ -84,19 +95,21 @@ int sql_query(SQL_INST *inst, SQLSOCK *sqlsocket, char *querystr) {
  *     Purpose: Issue a select query to the database
  *
  *************************************************************************/
-int sql_select_query(SQL_INST *inst, SQLSOCK *sqlsocket, char *querystr) {
+int
+sql_select_query(SQL_INST * inst, SQLSOCK * sqlsocket, char *querystr)
+{
 
        if (inst->config->sqltrace)
                DEBUG(querystr);
        if (sqlsocket->sock == NULL) {
                radlog(L_ERR, "Socket not connected");
-               return 0;
+               return -1;
        }
        mysql_query(sqlsocket->sock, querystr);
-       if (sql_store_result(sqlsocket) && sql_num_fields(sqlsocket)) 
-               return 1;
-       else
+       if (sql_store_result(sqlsocket) && sql_num_fields(sqlsocket))
                return 0;
+       else
+               return -1;
 }
 
 
@@ -108,15 +121,17 @@ int sql_select_query(SQL_INST *inst, SQLSOCK *sqlsocket, char *querystr) {
  *               set for the query.
  *
  *************************************************************************/
-int sql_store_result(SQLSOCK *sqlsocket) {
+int
+sql_store_result(SQLSOCK * sqlsocket)
+{
 
        if (sqlsocket->sock == NULL) {
                radlog(L_ERR, "Socket not connected");
                return 0;
        }
        if (!(sqlsocket->result = mysql_store_result(sqlsocket->sock))) {
-               radlog(L_ERR,"MYSQL Error: Cannot get result");
-               radlog(L_ERR,"MYSQL Error: %s",mysql_error(sqlsocket->sock));
+               radlog(L_ERR, "MYSQL Error: Cannot get result");
+               radlog(L_ERR, "MYSQL Error: %s", mysql_error(sqlsocket->sock));
                return 0;
        }
        return 1;
@@ -132,16 +147,19 @@ int sql_store_result(SQLSOCK *sqlsocket) {
  *               of columns from query
  *
  *************************************************************************/
-int sql_num_fields(SQLSOCK *sqlsocket) {
+int
+sql_num_fields(SQLSOCK * sqlsocket)
+{
+
+       int     num = 0;
 
-       int     num = 0;
 #if MYSQL_VERSION_ID >= 32224
        if (!(num = mysql_field_count(sqlsocket->sock))) {
 #else
        if (!(num = mysql_num_fields(sqlsocket->sock))) {
 #endif
-               radlog(L_ERR,"MYSQL Error: Cannot get result");
-               radlog(L_ERR,"MYSQL error: %s",mysql_error(sqlsocket->sock));
+               radlog(L_ERR, "MYSQL Error: Cannot get result");
+               radlog(L_ERR, "MYSQL error: %s", mysql_error(sqlsocket->sock));
        }
        return num;
 }
@@ -155,7 +173,9 @@ int sql_num_fields(SQLSOCK *sqlsocket) {
  *               query
  *
  *************************************************************************/
-int sql_num_rows(SQLSOCK *sqlsocket) {
+int
+sql_num_rows(SQLSOCK * sqlsocket)
+{
 
        return mysql_num_rows(sqlsocket->result);
 }
@@ -169,7 +189,9 @@ int sql_num_rows(SQLSOCK *sqlsocket) {
  *               with all the data for the query
  *
  *************************************************************************/
-SQL_ROW sql_fetch_row(SQLSOCK *sqlsocket) {
+SQL_ROW
+sql_fetch_row(SQLSOCK * sqlsocket)
+{
 
        return mysql_fetch_row(sqlsocket->result);
 }
@@ -184,9 +206,13 @@ SQL_ROW sql_fetch_row(SQLSOCK *sqlsocket) {
  *               for a result set
  *
  *************************************************************************/
-void sql_free_result(SQLSOCK *sqlsocket) {
+void
+sql_free_result(SQLSOCK * sqlsocket)
+{
 
-       mysql_free_result(sqlsocket->result);
+       if (sqlsocket->result) {
+               mysql_free_result(sqlsocket->result);
+       }
 }
 
 
@@ -199,7 +225,9 @@ void sql_free_result(SQLSOCK *sqlsocket) {
  *               connection
  *
  *************************************************************************/
-char *sql_error(SQLSOCK *sqlsocket) {
+char   *
+sql_error(SQLSOCK * sqlsocket)
+{
 
        return mysql_error(sqlsocket->sock);
 }
@@ -213,7 +241,9 @@ char *sql_error(SQLSOCK *sqlsocket) {
  *               connection
  *
  *************************************************************************/
-void sql_close(SQLSOCK *sqlsocket) {
+void
+sql_close(SQLSOCK * sqlsocket)
+{
 
        mysql_close(sqlsocket->sock);
        sqlsocket->sock = NULL;
@@ -227,7 +257,9 @@ void sql_close(SQLSOCK *sqlsocket) {
  *     Purpose: End the query, such as freeing memory
  *
  *************************************************************************/
-void sql_finish_query(SQLSOCK *sqlsocket) {
+void
+sql_finish_query(SQLSOCK * sqlsocket)
+{
 
 }
 
@@ -240,7 +272,9 @@ void sql_finish_query(SQLSOCK *sqlsocket) {
  *     Purpose: End the select query, such as freeing memory or result
  *
  *************************************************************************/
-void sql_finish_select_query(SQLSOCK *sqlsocket) {
+void
+sql_finish_select_query(SQLSOCK * sqlsocket)
+{
 
        sql_free_result(sqlsocket);
 }
@@ -253,7 +287,9 @@ void sql_finish_select_query(SQLSOCK *sqlsocket) {
  *     Purpose: End the select query, such as freeing memory or result
  *
  *************************************************************************/
-int sql_affected_rows(SQLSOCK *sqlsocket) {
+int
+sql_affected_rows(SQLSOCK * sqlsocket)
+{
 
        return mysql_affected_rows(sqlsocket->sock);
 }
@@ -266,7 +302,9 @@ int sql_affected_rows(SQLSOCK *sqlsocket) {
  *      Purpose: Esacpe "'" and any other wierd charactors
  *
  *************************************************************************/
-int sql_escape_string(char *to, char *from, int length) {
+int
+sql_escape_string(char *to, char *from, int length)
+{
 
        mysql_escape_string(to, from, length);
        return 1;
index 82b6e19..1d69c8f 100644 (file)
 typedef MYSQL_ROW SQL_ROW;
 
 typedef struct sql_socket {
-       int             id;
+       int     id;
 #if HAVE_PTHREAD_H
-       sem_t           *semaphore;
+       sem_t  *semaphore;
 #else
-       int             in_use;
+       int     in_use;
 #endif
        struct sql_socket *next;
 
-       MYSQL           *sock;
-       MYSQL           conn;
-       MYSQL_RES       *result;
+       MYSQL  *sock;
+       MYSQL   conn;
+       MYSQL_RES *result;
 } SQLSOCK;
 
-typedef struct sql_config {
-       char    *sql_server;
-       char    *sql_login;
-       char    *sql_password;
-       char    *sql_db;
-       char    *sql_acct_table;
-       char    *sql_authcheck_table;
-       char    *sql_authreply_table;
-       char    *sql_groupcheck_table;
-       char    *sql_groupreply_table;
-       char    *sql_usergroup_table;
-       char    *sql_realm_table;
-       char    *sql_realmgroup_table;
-       char    *sql_nas_table;
-       char    *sql_dict_table;
-       int     sensitiveusername;
-       int     sqltrace;
-       char    *tracefile;
-       int     deletestalesessions;
-       int     num_sql_socks;
-} SQL_CONFIG;
-
 typedef struct sql_inst {
-       int used;
+       int     used;
        SQLSOCK *sqlpool;
        SQL_CONFIG *config;
 #if HAVE_PTHREAD_H
@@ -60,18 +38,19 @@ typedef struct sql_inst {
 #endif
 } SQL_INST;
 
-SQLSOCK *sql_create_socket(SQL_INST *inst);
+SQLSOCK *sql_create_socket(SQL_INST * inst);
 int     sql_checksocket(const char *facility);
-int     sql_query(SQL_INST *inst, SQLSOCK *sqlsocket, char *querystr);
-int     sql_select_query(SQL_INST *inst, SQLSOCK *sqlsocket, char *querystr);
-int     sql_store_result(SQLSOCK *sqlsocket);
-int     sql_num_fields(SQLSOCK *sqlsocket);
-int     sql_num_rows(SQLSOCK *sqlsocket);
-SQL_ROW sql_fetch_row(SQLSOCK *sqlsocket);
-void    sql_free_result(SQLSOCK *sqlsocket);
-char   *sql_error(SQLSOCK *sqlsocket);
-void    sql_close(SQLSOCK *sqlsocket);
-void    sql_finish_query(SQLSOCK *sqlsocket);
-void    sql_finish_select_query(SQLSOCK *sqlsocket);
-int     sql_affected_rows(SQLSOCK *sqlsocket);
+int     sql_query(SQL_INST * inst, SQLSOCK * sqlsocket, char *querystr);
+int     sql_select_query(SQL_INST * inst, SQLSOCK * sqlsocket,
+                                                                                                char *querystr);
+int     sql_store_result(SQLSOCK * sqlsocket);
+int     sql_num_fields(SQLSOCK * sqlsocket);
+int     sql_num_rows(SQLSOCK * sqlsocket);
+SQL_ROW sql_fetch_row(SQLSOCK * sqlsocket);
+void    sql_free_result(SQLSOCK * sqlsocket);
+char   *sql_error(SQLSOCK * sqlsocket);
+void    sql_close(SQLSOCK * sqlsocket);
+void    sql_finish_query(SQLSOCK * sqlsocket);
+void    sql_finish_select_query(SQLSOCK * sqlsocket);
+int     sql_affected_rows(SQLSOCK * sqlsocket);
 int     sql_escape_string(char *to, char *from, int length);