Add the default_user_profile configuration directive and support
authorkkalev <kkalev>
Sat, 7 Sep 2002 13:23:01 +0000 (13:23 +0000)
committerkkalev <kkalev>
Sat, 7 Sep 2002 13:23:01 +0000 (13:23 +0000)
for the User-Profile attribute in the sql module.
The default_profile is found in SQL by group membership.
That means that this profile must be a member of at least one group
which will contain the corresponding check and reply items.
This profile will be queried in the authorize section for every user.
The point is to assign all users a default profile without having to
manually add each one to a group that will contain the profile.
The SQL module will also honor the User-Profile attribute. This
attribute can be set anywhere in the authorize section (ie the users
file). It is found exactly as the default profile is found.
If it is set then it will *overwrite* the default profile setting.
The idea is to select profiles based on checks on the incoming packets,
not on user group membership. For example:
-- users file --
DEFAULT       Service-Type == Outbound-User, User-Profile := "outbound"
DEFAULT       Service-Type == Framed-User, User-Profile := "framed"

By default the default_user_profile is not set. We also add the
query_on_not_found configuration directive which determines if we will
query the default_user_profile or the User-Profile if the user is not found.
If the profile is found then we consider the user found. That way we can still
maintain the old module behaviour to look for a DEFAULT entry if the user was
not found. But now that is configurable and we don't need to do extra queries
if the user is not found. By default this is set to 'no'.

Also change references to RFC 2138 to RFC 2865 in the dictionary man page.

man/man5/dictionary.5
raddb/sql.conf
src/modules/rlm_sql/conf.h
src/modules/rlm_sql/rlm_sql.c

index 7064f6a..3e30515 100644 (file)
@@ -15,7 +15,7 @@ Each line of the file can contain one of the following strings
 .B ATTRIBUTE name  number  type
 Define a name to RADIUS attribute number mapping.  The \fIname\fP
 field can be any non-space text.  The \fInumber\fP must contain
-an ASCII number for that name, as given in \fIRFC2138\fP. The
+an ASCII number for that name, as given in \fIRFC2865\fP. The
 \fItype\fP field can be one of \fIstring\fP, \fIipaddr\fP,
 \fIinteger\fP, or \fIdate\fP.
 
@@ -24,7 +24,7 @@ an ASCII number for that name, as given in \fIRFC2138\fP. The
 Define a value name to value number mapping.  The \fIattribute-name\fP
 field must be previously defined by an \fIATTRIBUTE\fP entry.  The
 \fIvalue-name\fP can be any non-space text.  The \fInumber\fP must
-contain an ASCII number for that name, as given in \fIRFC2138\fP.
+contain an ASCII number for that name, as given in \fIRFC2865\fP.
 
 .TP 0.5i
 .B VENDOR vendor-name number
@@ -44,5 +44,5 @@ Include dictionary entries from the file \fIfilename\fP.  The
 .SH "SEE ALSO"
 .BR radiusd (8),
 .BR naslist (5),
-.BR RFC2138 ,
-.BR RFC2139
+.BR RFC2865 ,
+.BR RFC2866
index 1837ee3..a44667d 100644 (file)
@@ -64,11 +64,40 @@ sql {
        #
        #    Use Stripped-User-Name, if it's there.
        #    Else use User-Name, if it's there,
-       #    Else use hard-coded string "none" as the user name.
-       #sql_user_name = "%{Stripped-User-Name:-%{User-Name:-none}}"
+       #    Else use hard-coded string "DEFAULT" as the user name.
+       #sql_user_name = "%{Stripped-User-Name:-%{User-Name:-DEFAULT}}"
        #
        sql_user_name = "%{User-Name}"
 
+       #######################################################################
+       #  Default profile
+       #######################################################################
+       # This is the default profile. It is found in SQL by group membership. 
+       # That means that this profile must be a member of at least one group
+       # which will contain the corresponding check and reply items.
+       # This profile will be queried in the authorize section for every user.
+       # The point is to assign all users a default profile without having to
+       # manually add each one to a group that will contain the profile.
+       # The SQL module will also honor the User-Profile attribute. This
+       # attribute can be set anywhere in the authorize section (ie the users
+       # file). It is found exactly as the default profile is found.
+       # If it is set then it will *overwrite* the default profile setting.
+       # The idea is to select profiles based on checks on the incoming packets,
+       # not on user group membership. For example:
+       # -- users file --
+       # DEFAULT       Service-Type == Outbound-User, User-Profile := "outbound"
+       # DEFAULT       Service-Type == Framed-User, User-Profile := "framed"
+       #
+       # By default the default_user_profile is not set
+       #
+       #default_user_profile = "DEFAULT"
+       #
+       # Determines if we will query the default_user_profile or the User-Profile
+       # if the user is not found. If the profile is found then we consider the user
+       # found. By default this is set to 'no'.
+       # 
+       #query_on_not_found = no
+
 
        #######################################################################
        #  Authorization Queries
index dff500e..0640d2b 100644 (file)
@@ -25,6 +25,7 @@ typedef struct sql_config {
        char   *sql_nas_table;
        char   *sql_dict_table;
        char   *query_user;
+       char   *default_profile;
        char   *authorize_check_query;
        char   *authorize_reply_query;
        char   *authorize_group_check_query;
@@ -44,6 +45,7 @@ typedef struct sql_config {
        int     deletestalesessions;
        int     num_sql_socks;
        int     connect_failure_retry_delay;
+       int     query_on_not_found;
 
        /* individual driver config */
        void    *localcfg;
index 4ce9684..54a7aab 100644 (file)
@@ -69,6 +69,8 @@ static CONF_PARSER module_config[] = {
        {"deletestalesessions", PW_TYPE_BOOLEAN, offsetof(SQL_CONFIG,deletestalesessions), NULL, "0"},
        {"num_sql_socks", PW_TYPE_INTEGER, offsetof(SQL_CONFIG,num_sql_socks), NULL, "5"},
        {"sql_user_name", PW_TYPE_STRING_PTR, offsetof(SQL_CONFIG,query_user), NULL, ""},
+       {"default_user_profile", PW_TYPE_STRING_PTR, offsetof(SQL_CONFIG,default_profile), NULL, ""},
+       {"query_on_not_found", PW_TYPE_BOOLEAN, offsetof(SQL_CONFIG,query_on_not_found), NULL, "no"},
        {"authorize_check_query", PW_TYPE_STRING_PTR, offsetof(SQL_CONFIG,authorize_check_query), NULL, ""},
        {"authorize_reply_query", PW_TYPE_STRING_PTR, offsetof(SQL_CONFIG,authorize_reply_query), NULL, ""},
        {"authorize_group_check_query", PW_TYPE_STRING_PTR, offsetof(SQL_CONFIG,authorize_group_check_query), NULL, ""},
@@ -414,6 +416,7 @@ static int rlm_sql_authorize(void *instance, REQUEST * request) {
 
        VALUE_PAIR *check_tmp = NULL;
        VALUE_PAIR *reply_tmp = NULL;
+       VALUE_PAIR *user_profile = NULL;
        int     found = 0;
        SQLSOCK *sqlsocket;
        SQL_INST *inst = instance;
@@ -440,6 +443,7 @@ static int rlm_sql_authorize(void *instance, REQUEST * request) {
         *  After this point, ALL 'return's MUST release the SQL socket!
         */
 
+
        /*
         * Set, escape, and check the user attr here
         */
@@ -473,39 +477,45 @@ static int rlm_sql_authorize(void *instance, REQUEST * request) {
                return RLM_MODULE_FAIL;
 
        } else {
-               int     gcheck;
-               
-               radlog(L_DBG, "rlm_sql: User %s not found", sqlusername);
+               radlog(L_DBG, "rlm_sql: User %s not found in radcheck", sqlusername);
 
                 /*
                 * We didn't find the user in radcheck, so we try looking
                 * for radgroupcheck entry
                 */
                 radius_xlat(querystr, MAX_QUERY_LEN, inst->config->authorize_group_check_query, request, sql_escape_func);
-                gcheck = sql_getvpdata(inst, sqlsocket, &check_tmp, querystr, PW_VP_GROUPDATA);
+                found = sql_getvpdata(inst, sqlsocket, &check_tmp, querystr, PW_VP_GROUPDATA);
                 radius_xlat(querystr, MAX_QUERY_LEN, inst->config->authorize_group_reply_query, request, sql_escape_func);
                 sql_getvpdata(inst, sqlsocket, &reply_tmp, querystr, PW_VP_GROUPDATA);
-                if (gcheck) {
-                        found = 1;
-                } else {
-                        /*
-                        * We didn't find the user, so we try looking
-                        * for a DEFAULT entry
-                        */
-                        if (sql_set_user(inst, request, sqlusername, "DEFAULT") < 0) {
-                                sql_release_socket(inst, sqlsocket);
-                                return RLM_MODULE_FAIL;
-                        }
-                        radius_xlat(querystr, MAX_QUERY_LEN, inst->config->authorize_group_check_query, request, sql_escape_func);
-                        gcheck = sql_getvpdata(inst, sqlsocket, &check_tmp, querystr, PW_VP_GROUPDATA);
-                        radius_xlat(querystr, MAX_QUERY_LEN, inst->config->authorize_group_reply_query, request, sql_escape_func);
-                        gcheck = sql_getvpdata(inst, sqlsocket, &reply_tmp, querystr, PW_VP_GROUPDATA);
-                        if (gcheck)
-                                found = 1;
-                }
         }
+       if (!found)
+               radlog(L_DBG, "rlm_sql: User %s not found in radgroupcheck",sqlusername);
+       if (found || (!found && inst->config->query_on_not_found)){
+               /*
+               * Check for a default_profile or for a User-Profile.
+               */
+               user_profile = pairfind(request->config_items, PW_USER_PROFILE);
+               if (inst->config->default_profile[0] != 0 || user_profile != NULL){
+                       char *profile = inst->config->default_profile;
+
+                       if (user_profile != NULL)
+                               profile = user_profile->strvalue;
+                       if (profile && strlen(profile)){
+                               radlog(L_DBG, "rlm_sql: Checking profile %s",profile);
+                               if (sql_set_user(inst, request, sqlusername, profile) < 0) {
+                                       return RLM_MODULE_FAIL;
+                               }
+                               radius_xlat(querystr, MAX_QUERY_LEN, inst->config->authorize_group_check_query,
+                                                                       request, sql_escape_func);
+                               found = sql_getvpdata(inst, sqlsocket, &check_tmp, querystr, PW_VP_GROUPDATA);
+                               radius_xlat(querystr, MAX_QUERY_LEN, inst->config->authorize_group_reply_query,
+                                                                       request, sql_escape_func);
+                               sql_getvpdata(inst, sqlsocket, &reply_tmp, querystr, PW_VP_GROUPDATA);
+                       }
+               }
+       }
        if (!found) {
-               radlog(L_DBG, "rlm_sql: DEFAULT not found");
+               radlog(L_DBG, "rlm_sql: User not found");
                sql_release_socket(inst, sqlsocket);
                /* Remove the username we (maybe) added above */
                pairdelete(&request->packet->vps, PW_SQL_USER_NAME);