Enable building WITHOUT_ACCOUNTING
[freeradius.git] / src / modules / rlm_sql / rlm_sql.c
index 4038ed1..9bc0d35 100644 (file)
@@ -29,7 +29,6 @@ RCSID("$Id$")
 #include <freeradius-devel/radiusd.h>
 #include <freeradius-devel/modules.h>
 #include <freeradius-devel/rad_assert.h>
-#include <ltdl.h>
 
 #include <sys/stat.h>
 
@@ -50,6 +49,8 @@ static const CONF_PARSER module_config[] = {
         offsetof(SQL_CONFIG,sql_password), NULL, ""},
        {"radius_db", PW_TYPE_STRING_PTR,
         offsetof(SQL_CONFIG,sql_db), NULL, "radius"},
+       {"filename", PW_TYPE_FILENAME, /* for sqlite */
+        offsetof(SQL_CONFIG,sql_file), NULL, NULL},
        {"read_groups", PW_TYPE_BOOLEAN,
         offsetof(SQL_CONFIG,read_groups), NULL, "yes"},
        {"sqltrace", PW_TYPE_BOOLEAN,
@@ -80,6 +81,7 @@ static const CONF_PARSER module_config[] = {
         offsetof(SQL_CONFIG,authorize_group_check_query), NULL, ""},
        {"authorize_group_reply_query", PW_TYPE_STRING_PTR,
         offsetof(SQL_CONFIG,authorize_group_reply_query), NULL, ""},
+#ifdef WITH_ACCOUNTING
        {"accounting_onoff_query", PW_TYPE_STRING_PTR,
         offsetof(SQL_CONFIG,accounting_onoff_query), NULL, ""},
        {"accounting_update_query", PW_TYPE_STRING_PTR,
@@ -94,20 +96,29 @@ static const CONF_PARSER module_config[] = {
         offsetof(SQL_CONFIG,accounting_stop_query), NULL, ""},
        {"accounting_stop_query_alt", PW_TYPE_STRING_PTR,
         offsetof(SQL_CONFIG,accounting_stop_query_alt), NULL, ""},
+#endif
        {"group_membership_query", PW_TYPE_STRING_PTR,
         offsetof(SQL_CONFIG,groupmemb_query), NULL, NULL},
        {"connect_failure_retry_delay", PW_TYPE_INTEGER,
         offsetof(SQL_CONFIG,connect_failure_retry_delay), NULL, "60"},
+#ifdef WITH_SESSION_MGMT
        {"simul_count_query", PW_TYPE_STRING_PTR,
         offsetof(SQL_CONFIG,simul_count_query), NULL, ""},
        {"simul_verify_query", PW_TYPE_STRING_PTR,
         offsetof(SQL_CONFIG,simul_verify_query), NULL, ""},
+#endif
        {"postauth_query", PW_TYPE_STRING_PTR,
         offsetof(SQL_CONFIG,postauth_query), NULL, ""},
        {"safe-characters", PW_TYPE_STRING_PTR,
         offsetof(SQL_CONFIG,allowed_chars), NULL,
        "@abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_: /"},
 
+       /*
+        *      This only works for a few drivers.
+        */
+       {"query_timeout", PW_TYPE_INTEGER,
+        offsetof(SQL_CONFIG,query_timeout), NULL, NULL},
+        
        {NULL, -1, 0, NULL, NULL}
 };
 
@@ -117,7 +128,7 @@ static const CONF_PARSER module_config[] = {
 static int fallthrough(VALUE_PAIR *vp)
 {
        VALUE_PAIR *tmp;
-       tmp = pairfind(vp, PW_FALL_THROUGH);
+       tmp = pairfind(vp, PW_FALL_THROUGH, 0);
 
        return tmp ? tmp->vp_integer : 0;
 }
@@ -393,12 +404,13 @@ static int generate_sql_clients(SQL_INST *inst)
                        c->nastype = strdup(row[3]);
 
                numf = (inst->module->sql_num_fields)(sqlsocket, inst->config);
-               if ((numf > 5) && (row[5] != NULL)) c->server = strdup(row[5]);
+               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);
                        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);
@@ -479,7 +491,7 @@ int sql_set_user(SQL_INST *inst, REQUEST *request, char *sqlusername, const char
        sqlusername[0]= '\0';
 
        /* Remove any user attr we added previously */
-       pairdelete(&request->packet->vps, PW_SQL_USER_NAME);
+       pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
 
        if (username != NULL) {
                strlcpy(tmpuser, username, sizeof(tmpuser));
@@ -614,7 +626,7 @@ static int sql_groupcmp(void *instance, REQUEST *request, VALUE_PAIR *request_vp
        sqlsocket = sql_get_socket(inst);
        if (sqlsocket == NULL) {
                /* Remove the username we (maybe) added above */
-               pairdelete(&request->packet->vps, PW_SQL_USER_NAME);
+               pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
                return 1;
        }
 
@@ -625,7 +637,7 @@ static int sql_groupcmp(void *instance, REQUEST *request, VALUE_PAIR *request_vp
                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);
+               pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
                sql_release_socket(inst, sqlsocket);
                return 1;
        }
@@ -637,7 +649,7 @@ static int sql_groupcmp(void *instance, REQUEST *request, VALUE_PAIR *request_vp
                        /* Free the grouplist */
                        sql_grouplist_free(&group_list);
                        /* Remove the username we (maybe) added above */
-                       pairdelete(&request->packet->vps, PW_SQL_USER_NAME);
+                       pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
                        sql_release_socket(inst, sqlsocket);
                        return 0;
                }
@@ -646,7 +658,7 @@ static int sql_groupcmp(void *instance, REQUEST *request, VALUE_PAIR *request_vp
        /* Free the grouplist */
        sql_grouplist_free(&group_list);
        /* Remove the username we (maybe) added above */
-       pairdelete(&request->packet->vps, PW_SQL_USER_NAME);
+       pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
        sql_release_socket(inst,sqlsocket);
 
        RDEBUG("sql_groupcmp finished: User is NOT a member of group %s",
@@ -691,7 +703,7 @@ static int rlm_sql_process_groups(SQL_INST *inst, REQUEST *request, SQLSOCK *sql
                        radlog_request(L_ERR, 0, request,
                                       "Error generating query; rejecting user");
                        /* Remove the grouup we added above */
-                       pairdelete(&request->packet->vps, PW_SQL_GROUP);
+                       pairdelete(&request->packet->vps, PW_SQL_GROUP, 0);
                        return -1;
                }
                rows = sql_getvpdata(inst, sqlsocket, &check_tmp, querystr);
@@ -699,7 +711,7 @@ static int rlm_sql_process_groups(SQL_INST *inst, REQUEST *request, SQLSOCK *sql
                        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);
+                       pairdelete(&request->packet->vps, PW_SQL_GROUP, 0);
                        pairfree(&check_tmp);
                        return -1;
                } else if (rows > 0) {
@@ -716,7 +728,7 @@ static int rlm_sql_process_groups(SQL_INST *inst, REQUEST *request, SQLSOCK *sql
                                if (!radius_xlat(querystr, sizeof(querystr), inst->config->authorize_group_reply_query, request, sql_escape_func)) {
                                        radlog_request(L_ERR, 0, request, "Error generating query; rejecting user");
                                        /* Remove the grouup we added above */
-                                       pairdelete(&request->packet->vps, PW_SQL_GROUP);
+                                       pairdelete(&request->packet->vps, PW_SQL_GROUP, 0);
                                        pairfree(&check_tmp);
                                        return -1;
                                }
@@ -724,7 +736,7 @@ static int rlm_sql_process_groups(SQL_INST *inst, REQUEST *request, SQLSOCK *sql
                                        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);
+                                       pairdelete(&request->packet->vps, PW_SQL_GROUP, 0);
                                        pairfree(&check_tmp);
                                        pairfree(&reply_tmp);
                                        return -1;
@@ -749,7 +761,7 @@ static int rlm_sql_process_groups(SQL_INST *inst, REQUEST *request, SQLSOCK *sql
                        if (!radius_xlat(querystr, sizeof(querystr), inst->config->authorize_group_reply_query, request, sql_escape_func)) {
                                radlog_request(L_ERR, 0, request, "Error generating query; rejecting user");
                                /* Remove the grouup we added above */
-                               pairdelete(&request->packet->vps, PW_SQL_GROUP);
+                               pairdelete(&request->packet->vps, PW_SQL_GROUP, 0);
                                pairfree(&check_tmp);
                                return -1;
                        }
@@ -757,7 +769,7 @@ static int rlm_sql_process_groups(SQL_INST *inst, REQUEST *request, SQLSOCK *sql
                                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);
+                               pairdelete(&request->packet->vps, PW_SQL_GROUP, 0);
                                pairfree(&check_tmp);
                                pairfree(&reply_tmp);
                                return -1;
@@ -771,7 +783,7 @@ static int rlm_sql_process_groups(SQL_INST *inst, REQUEST *request, SQLSOCK *sql
                 * Delete the Sql-Group we added above
                 * And clear out the pairlists
                 */
-               pairdelete(&request->packet->vps, PW_SQL_GROUP);
+               pairdelete(&request->packet->vps, PW_SQL_GROUP, 0);
                pairfree(&check_tmp);
                pairfree(&reply_tmp);
        }
@@ -821,7 +833,12 @@ static int rlm_sql_detach(void *instance)
                        free(*p);
                        *p = NULL;
                }
-               allowed_chars = NULL;
+               /*
+                *      Catch multiple instances of the module.
+                */
+               if (allowed_chars == inst->config->allowed_chars) {
+                       allowed_chars = NULL;
+               }
                free(inst->config);
                inst->config = NULL;
        }
@@ -870,8 +887,38 @@ static int rlm_sql_instantiate(CONF_SECTION * conf, void **instance)
        }
 
        xlat_name = cf_section_name2(conf);
-       if (xlat_name == NULL)
+       if (xlat_name == NULL) {
                xlat_name = cf_section_name1(conf);
+       } else {
+               char *group_name;
+               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);
+
+               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_ldap: Failed to create attribute %s",group_name);
+                       free(group_name);
+                       free(inst);     /* FIXME: detach */
+                       return -1;
+               }
+
+               if (inst->config->groupmemb_query && 
+                   inst->config->groupmemb_query[0]) {
+                       DEBUG("rlm_sql: Registering sql_groupcmp for %s",group_name);
+                       paircompare_register(dattr->attr, PW_USER_NAME, sql_groupcmp, inst);
+               }
+
+               free(group_name);
+       }
        if (xlat_name){
                inst->config->xlat_name = strdup(xlat_name);
                xlat_register(xlat_name, (RAD_XLAT_FUNC)sql_xlat, inst);
@@ -926,7 +973,10 @@ static int rlm_sql_instantiate(CONF_SECTION * conf, void **instance)
                return -1;
        }
 
-       paircompare_register(PW_SQL_GROUP, PW_USER_NAME, sql_groupcmp, inst);
+       if (inst->config->groupmemb_query && 
+           inst->config->groupmemb_query[0]) {
+               paircompare_register(PW_SQL_GROUP, PW_USER_NAME, sql_groupcmp, inst);
+       }
 
        if (inst->config->do_clients){
                if (generate_sql_clients(inst) == -1){
@@ -975,7 +1025,7 @@ static int rlm_sql_authorize(void *instance, REQUEST * request)
        sqlsocket = sql_get_socket(inst);
        if (sqlsocket == NULL) {
                /* Remove the username we (maybe) added above */
-               pairdelete(&request->packet->vps, PW_SQL_USER_NAME);
+               pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
                return RLM_MODULE_FAIL;
        }
 
@@ -991,7 +1041,7 @@ static int rlm_sql_authorize(void *instance, REQUEST * request)
                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);
+               pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
                return RLM_MODULE_FAIL;
        }
        rows = sql_getvpdata(inst, sqlsocket, &check_tmp, querystr);
@@ -999,7 +1049,7 @@ static int rlm_sql_authorize(void *instance, REQUEST * request)
                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);
+               pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
                pairfree(&check_tmp);
                return RLM_MODULE_FAIL;
        } else if (rows > 0) {
@@ -1020,7 +1070,7 @@ static int rlm_sql_authorize(void *instance, REQUEST * request)
                                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);
+                               pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
                                pairfree(&check_tmp);
                                return RLM_MODULE_FAIL;
                        }
@@ -1028,7 +1078,7 @@ static int rlm_sql_authorize(void *instance, REQUEST * request)
                                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);
+                               pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
                                pairfree(&check_tmp);
                                pairfree(&reply_tmp);
                                return RLM_MODULE_FAIL;
@@ -1060,7 +1110,7 @@ static int rlm_sql_authorize(void *instance, REQUEST * request)
                        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);
+                       pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
                        return RLM_MODULE_FAIL;
                } else if (rows > 0) {
                        found = 1;
@@ -1075,7 +1125,7 @@ static int rlm_sql_authorize(void *instance, REQUEST * request)
                /*
                * Check for a default_profile or for a User-Profile.
                */
-               user_profile = pairfind(request->config_items, PW_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;
 
@@ -1087,7 +1137,7 @@ static int rlm_sql_authorize(void *instance, REQUEST * request)
                                        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);
+                                       pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
                                        return RLM_MODULE_FAIL;
                                } else {
                                        profile_found = 1;
@@ -1101,7 +1151,7 @@ static int rlm_sql_authorize(void *instance, REQUEST * request)
                                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);
+                               pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
                                return RLM_MODULE_FAIL;
                        } else if (rows > 0) {
                                found = 1;
@@ -1110,7 +1160,7 @@ static int rlm_sql_authorize(void *instance, REQUEST * request)
        }
 
        /* Remove the username we (maybe) added above */
-       pairdelete(&request->packet->vps, PW_SQL_USER_NAME);
+       pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
        sql_release_socket(inst, sqlsocket);
 
        if (!found) {
@@ -1121,6 +1171,7 @@ static int rlm_sql_authorize(void *instance, REQUEST * request)
        }
 }
 
+#ifdef WITH_ACCOUNTING
 /*
  *     Accounting: save the account data to our sql table
  */
@@ -1145,7 +1196,7 @@ static int rlm_sql_accounting(void *instance, REQUEST * request) {
        /*
         * Find the Acct Status Type
         */
-       if ((pair = pairfind(request->packet->vps, PW_ACCT_STATUS_TYPE)) != NULL) {
+       if ((pair = pairfind(request->packet->vps, PW_ACCT_STATUS_TYPE, 0)) != NULL) {
                acctstatustype = pair->vp_integer;
        } else {
                radius_xlat(logstr, sizeof(logstr), "packet has no accounting status type. [user '%{User-Name}', nas '%{NAS-IP-Address}']", request, NULL);
@@ -1306,14 +1357,14 @@ static int rlm_sql_accounting(void *instance, REQUEST * request) {
                                                 * 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)
+                                               if ((pair = pairfind(request->packet->vps, PW_ACCT_SESSION_TIME, 0)) != NULL)
                                                        acctsessiontime = pair->vp_integer;
 
                                                if (acctsessiontime <= 0) {
                                                        radius_xlat(logstr, sizeof(logstr), "stop packet with zero session length. [user '%{User-Name}', nas '%{NAS-IP-Address}']", request, NULL);
-                                                       radlog_request(L_ERR, 0, request, "%s", logstr);
+                                                       radlog_request(L_DBG, 0, request, "%s", logstr);
                                                        sql_release_socket(inst, sqlsocket);
-                                                       ret = RLM_MODULE_NOOP;
+                                                       return RLM_MODULE_NOOP;
                                                }
 #endif
 
@@ -1350,8 +1401,10 @@ static int rlm_sql_accounting(void *instance, REQUEST * request) {
 
        return ret;
 }
+#endif
 
 
+#ifdef WITH_SESSION_MGMT
 /*
  *        See if a user is already logged in. Sets request->simul_count to the
  *        current session count for this user.
@@ -1448,9 +1501,9 @@ static int rlm_sql_checksimul(void *instance, REQUEST * request) {
          */
        request->simul_count = 0;
 
-        if ((vp = pairfind(request->packet->vps, PW_FRAMED_IP_ADDRESS)) != NULL)
+        if ((vp = pairfind(request->packet->vps, PW_FRAMED_IP_ADDRESS, 0)) != NULL)
                 ipno = vp->vp_ipaddr;
-        if ((vp = pairfind(request->packet->vps, PW_CALLING_STATION_ID)) != NULL)
+        if ((vp = pairfind(request->packet->vps, PW_CALLING_STATION_ID, 0)) != NULL)
                 call_num = vp->vp_strvalue;
 
 
@@ -1538,6 +1591,7 @@ static int rlm_sql_checksimul(void *instance, REQUEST * request) {
         */
        return RLM_MODULE_OK;
 }
+#endif
 
 /*
  *     Execute postauth_query after authentication
@@ -1594,8 +1648,16 @@ module_t rlm_sql = {
                NULL,                   /* authentication */
                rlm_sql_authorize,      /* authorization */
                NULL,                   /* preaccounting */
+#ifdef WITH_ACCOUNTING
                rlm_sql_accounting,     /* accounting */
+#else
+               NULL,
+#endif
+#ifdef WITH_SESSION_MGMT
                rlm_sql_checksimul,     /* checksimul */
+#else
+               NULL,
+#endif
                NULL,                   /* pre-proxy */
                NULL,                   /* post-proxy */
                rlm_sql_postauth        /* post-auth */