Compiles with new ICRADIUS code, but BADLY BROKEN. DO NOT USE YET :)
authormmachado <mmachado>
Thu, 16 Mar 2000 23:32:37 +0000 (23:32 +0000)
committermmachado <mmachado>
Thu, 16 Mar 2000 23:32:37 +0000 (23:32 +0000)
src/modules/rlm_sql/conf.h [new file with mode: 0644]
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
src/modules/rlm_sql/sql_mysql.c
src/modules/rlm_sql/sql_mysql.h

diff --git a/src/modules/rlm_sql/conf.h b/src/modules/rlm_sql/conf.h
new file mode 100644 (file)
index 0000000..12cc8f4
--- /dev/null
@@ -0,0 +1,38 @@
+#define CHECKRAD1              "/usr/sbin/checkrad"
+#define CHECKRAD2              "/usr/local/sbin/checkrad"
+
+/* Hack for funky ascend ports on MAX 4048 (and probably others)
+   The "NAS-Port-Id" value is "xyyzz" where "x" = 1 for digital, 2 for analog;
+   "yy" = line number (1 for first PRI/T1/E1, 2 for second, so on);
+   "zz" = channel number (on the PRI or Channelized T1/E1).
+    This should work with normal terminal servers, unless you have a TS with
+        more than 9999 ports ;^).
+    The "ASCEND_CHANNELS_PER_LINE" is the number of channels for each line into
+        the unit.  For my US/PRI that's 23.  A US/T1 would be 24, and a
+        European E1 would be 30 (I think ... never had one ;^).
+    This will NOT change the "NAS-Port-Id" reported in the detail log.  This
+        is simply to fix the dynamic IP assignments a la Cistron.
+    WARNING: This hack works for me, but I only have one PRI!!!  I've not
+        tested it on 2 or more (or with models other than the Max 4048)
+    Use at your own risk!
+  -- dgreer@austintx.com
+*/
+
+#define ASCEND_PORT_HACK
+#define ASCEND_CHANNELS_PER_LINE        23
+
+#define CISCO_ACCOUNTING_HACK
+
+/* SQL defines */
+#define SQL_LOCK_LEN                   sizeof(SQLACCTREC)
+#define        SQLQUERYLOG                     "/var/log/radacct/radius.sql"
+#define        SQLCONFIGFILE                   "rlm_sql.conf"
+#define        SQLBACKUP                       "/var/log/radacct/sqlbackup.dat"
+#define SQLBIGREC                      32
+#define SQLLILREC                      15
+
+#define MAX_COMMUNITY_LEN              50
+#define MAX_SQL_SOCKS                  5
+#define MAX_TABLE_LEN                  20
+#define MAX_AUTH_QUERY_LEN             256
+#define AUTH_STRING_LEN                        128
index 2570345..860bc60 100644 (file)
 
 static int rlm_sql_init(int argc, char **argv) {
 
-       FILE    *sqlfd;
-        char    dummystr[64];
-        char    namestr[64];
-        int     line_no;
-        char    buffer[256];
-        char    sqlfile[256];
-
-       if ((sql = malloc(sizeof(SQL))) == NULL) {
-               log(L_ERR|L_CONS, "no memory");
-               exit(1);        
-       }
-       
-       strcpy(sql->config.sql_server,"localhost");
-       strcpy(sql->config.sql_login,"");
-       strcpy(sql->config.sql_password,"");
-       strcpy(sql->config.sql_db,"radius");
-       strcpy(sql->config.sql_authcheck_table,"radcheck");
-       strcpy(sql->config.sql_authreply_table,"radreply");
-       strcpy(sql->config.sql_groupcheck_table,"radgroupcheck");
-       strcpy(sql->config.sql_groupreply_table,"radgroupreply");
-       strcpy(sql->config.sql_usergroup_table,"usergroup");
-       strcpy(sql->config.sql_realmgroup_table,"realmgroup");
-       strcpy(sql->config.sql_acct_table,"radacct");
-       strcpy(sql->config.sql_nas_table,"nas");
-       strcpy(sql->config.sql_realm_table, "realms");
-       strcpy(sql->config.sql_dict_table,"dictionary");
-       sql->config.sqltrace = 0;
-       sql->config.sql_keepopen = 0;
-
-       sprintf(sqlfile, "%s/%s", radius_dir, SQLCONFIGFILE);
-
-        if((sqlfd = fopen(sqlfile, "r")) == (FILE *)NULL) {
-                log(L_ERR,"could not read sql configuration file %s",sqlfile);
-                return(-1);
-        }
-
-        line_no = 0;
-        while(fgets(buffer, sizeof(buffer), sqlfd) != (char *)NULL) {
-                line_no++;
-
-                /* Skip empty space */
-                if(*buffer == '#' || *buffer == '\0' || *buffer == '\n') {
-                        continue;
-                }
-
-                if(strncasecmp(buffer, "type", 4) == 0) {
-                        /* Read the SERVER line */
-                        if(sscanf(buffer, "%s%s", dummystr, namestr) != 2) {
-                               log(L_ERR,"invalid attribute on line %d of sqlserver file %s", line_no,sqlfile);
-                       } else {
-                         strcpy(sql->config.sql_type,namestr);
-                       }
-               }
-                if(strncasecmp(buffer, "server", 6) == 0) {
-                        /* Read the SERVER line */
-                        if(sscanf(buffer, "%s%s", dummystr, namestr) != 2) {
-                               log(L_ERR,"invalid attribute on line %d of sqlserver file %s", line_no,sqlfile);
-                       } else {
-                         strcpy(sql->config.sql_server,namestr);
-                       }
-               }
-                if(strncasecmp(buffer, "port", 4) == 0) {
-                        /* Read the SERVER line */
-                        if(sscanf(buffer, "%s%s", dummystr, namestr) != 2) {
-                               log(L_ERR,"invalid attribute on line %d of sqlserver file %s", line_no,sqlfile);
-                       } else {
-                         sql->config.sql_port = strtol(namestr, (char **)NULL, 10);
-                       }
-               }
-                if(strncasecmp(buffer, "login", 5) == 0) {
-                        /* Read the LOGIN line */
-                        if(sscanf(buffer, "%s%s", dummystr, namestr) != 2) {
-                               log(L_ERR,"invalid attribute on line %d of sqlserver file %s", line_no,sqlfile);
-                       } else {
-                         strcpy(sql->config.sql_login,namestr);
-                       }
-               }
-                if(strncasecmp(buffer, "password", 8) == 0) {
-                        /* Read the PASSWORD line */
-                        if(sscanf(buffer, "%s%s", dummystr, namestr) != 2) {
-                               log(L_ERR,"invalid attribute on line %d of sqlserver file %s", line_no,sqlfile);
-                       } else {
-                         strcpy(sql->config.sql_password,namestr);
-                       }
-               }
-                if(strncasecmp(buffer, "radius_db", 9) == 0) {
-                        /* Read the RADIUS_DB line */
-                        if(sscanf(buffer, "%s%s", dummystr, namestr) != 2) {
-                               log(L_ERR,"invalid attribute on line %d of sqlserver file %s", line_no,sqlfile);
-                       } else {
-                         strcpy(sql->config.sql_db,namestr);
-                       }
-               }
-                if(strncasecmp(buffer, "authcheck_table", 15) == 0) {
-                        /* Read the AUTHCHECK_TABLE line */
-                        if(sscanf(buffer, "%s%s", dummystr, namestr) != 2) {
-                               log(L_ERR,"invalid attribute on line %d of sqlserver file %s", line_no,sqlfile);
-                       } else {
-                         strncpy(sql->config.sql_authcheck_table,namestr, MAX_TABLE_LEN);
-                       }
-               }
-                if(strncasecmp(buffer, "authreply_table", 15) == 0) {
-                        /* Read the AUTHREPLY_TABLE line */
-                        if(sscanf(buffer, "%s%s", dummystr, namestr) != 2) {
-                               log(L_ERR,"invalid attribute on line %d of sqlserver file %s", line_no,sqlfile);
-                       } else {
-                         strncpy(sql->config.sql_authreply_table,namestr, MAX_TABLE_LEN);
-                       }
-               }
-                if(strncasecmp(buffer, "groupcheck_table", 16) == 0) {
-                        /* Read the GROUPCHECK_TABLE line */
-                        if(sscanf(buffer, "%s%s", dummystr, namestr) != 2) {
-                               log(L_ERR,"invalid attribute on line %d of sqlserver file %s", line_no,sqlfile);
-                       } else {
-                         strncpy(sql->config.sql_groupcheck_table,namestr, MAX_TABLE_LEN);
-                       }
-               }
-                if(strncasecmp(buffer, "groupreply_table", 16) == 0) {
-                        /* Read the GROUP_REPLY_TABLE line */
-                        if(sscanf(buffer, "%s%s", dummystr, namestr) != 2) {
-                               log(L_ERR,"invalid attribute on line %d of sqlserver file %s", line_no,sqlfile);
-                       } else {
-                         strncpy(sql->config.sql_groupreply_table,namestr, MAX_TABLE_LEN);
-                       }
-               }
-                if(strncasecmp(buffer, "usergroup_table", 15) == 0) {
-                        /* Read the USERGROUP_TABLE line */
-                        if(sscanf(buffer, "%s%s", dummystr, namestr) != 2) {
-                               log(L_ERR,"invalid attribute on line %d of sqlserver file %s", line_no,sqlfile);
-                       } else {
-                         strncpy(sql->config.sql_usergroup_table,namestr, MAX_TABLE_LEN);
-                       }
-               }
-                if(strncasecmp(buffer, "realmgroup_table", 16) == 0) {
-                        /* Read the REALMGROUP_TABLE line */
-                        if(sscanf(buffer, "%s%s", dummystr, namestr) != 2) {
-                               log(L_ERR,"invalid attribute on line %d of sqlserver file %s", line_no,sqlfile);
-                       } else {
-                         strncpy(sql->config.sql_realmgroup_table,namestr, MAX_TABLE_LEN);
-                       }
-               }
-                if(strncasecmp(buffer, "acct_table", 10) == 0) {
-                        /* Read the ACCT_TABLE line */
-                        if(sscanf(buffer, "%s%s", dummystr, namestr) != 2) {
-                               log(L_ERR,"invalid attribute on line %d of sqlserver file %s", line_no,sqlfile);
-                       } else {
-                         strncpy(sql->config.sql_acct_table,namestr, MAX_TABLE_LEN);
-                       }
-               }
-                if(strncasecmp(buffer, "nas_table", 9) == 0) {
-                        /* Read the NAS_TABLE line */
-                        if(sscanf(buffer, "%s%s", dummystr, namestr) != 2) {
-                               log(L_ERR,"invalid attribute on line %d of sqlserver file %s", line_no,sqlfile);
-                       } else {
-                         strncpy(sql->config.sql_nas_table,namestr, MAX_TABLE_LEN);
-                       }
-               }
-                if(strncasecmp(buffer, "realm_table", 9) == 0) {
-                       /* Read the REALM_TABLE line */
-                       if(sscanf(buffer, "%s%s", dummystr, namestr) != 2) {
-                               log(L_ERR,"invalid attribute on line %d of sqlserver file %s", line_no,sqlfile);
-                      } else {
-                         strncpy(sql->config.sql_realm_table,namestr, MAX_TABLE_LEN);
-                      }
-               }
-                if(strncasecmp(buffer, "dict_table", 9) == 0) {
-                        /* Read the DICT_TABLE line */
-                        if(sscanf(buffer, "%s%s", dummystr, namestr) != 2) {
-                               log(L_ERR,"invalid attribute on line %d of sqlserver file %s", line_no,sqlfile);
-                       } else {
-                         strncpy(sql->config.sql_dict_table,namestr, MAX_TABLE_LEN);
-                       }
-               }
-                if(strncasecmp(buffer, "sqltrace", 8) == 0) {
-                        /* Read the SQLTRACE line */
-                        if(sscanf(buffer, "%s%s", dummystr, namestr) != 2) {
-                               log(L_ERR,"invalid attribute on line %d of sqlserver file %s", line_no,sqlfile);
-                      } else {
-                         if(strncasecmp(namestr, "on", 2) == 0) {
-                           sql->config.sqltrace = 1;
-                         } else {
-                           sql->config.sqltrace = 0;
-                         }
-                       }
-               }
-               if(strncasecmp(buffer, "keepopen", 8) == 0) {
-                        /* Read the KEEPOPEN line */
-                        if(sscanf(buffer, "%s%s", dummystr, namestr) != 2) {
-                               log(L_ERR,"invalid attribute on line %d of sqlserver file %s", line_no,sqlfile);
-                       } else {
-                         if(strncasecmp(namestr, "yes", 3) == 0) {
-                           sql->config.sql_keepopen = 1;
-                        } else {
-                           sql->config.sql_keepopen = 0;
-                        }
-                       }
-               }
-
-       }
-       fclose(sqlfd);
-       
-       log(L_INFO,"SQL: Attempting to connect to %s@%s:%s",
-       sql->config.sql_login,
-       sql->config.sql_server,
-       sql->config.sql_db);
-
-       if (sql->config.sql_keepopen)
-          sql_connect();
+       sql_init(0);
            
        return 0;
 }
@@ -243,98 +36,121 @@ static int rlm_sql_detach(void) {
 }
 
 
-static int rlm_sql_authorize(REQUEST *request, char *name, VALUE_PAIR **check_pairs, VALUE_PAIR **reply_pairs) {
+static int rlm_sql_authorize(REQUEST *request, VALUE_PAIR **check_pairs, VALUE_PAIR **reply_pairs) {
 
        int             nas_port = 0;
        VALUE_PAIR      *check_tmp = NULL;
        VALUE_PAIR      *reply_tmp = NULL;
        VALUE_PAIR      *tmp;
        int             found = 0;
-#ifdef NT_DOMAIN_HACK
+       char            *name;
+       SQLSOCK         *socket;
+ #ifdef NT_DOMAIN_HACK
        char            *ptr;
        char            newname[AUTH_STRING_LEN];
-#endif
-
+ #endif
 
-       /* 
-        *      Check for valid input, zero length names not permitted 
-        */
-       if (name[0] == 0) {
-               log(L_ERR, "zero length username not permitted\n");
-               return -1;
-       }
+       name = request->username->strvalue;
 
-       /*
-        *      Find the NAS port ID.
-        */
-       if ((tmp = pairfind(request->packet->vps, PW_NAS_PORT_ID)) != NULL)
-               nas_port = tmp->lvalue;
-
-       /*
-        *      Find the entry for the user.
-        */
-
-#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(name, '\\')) != NULL) {
-               strncpy(newname, ptr + 1, sizeof(newname));
-               newname[sizeof(newname) - 1] = 0;
-               strcpy(name, newname);
-       }
-#endif /* NT_DOMAIN_HACK */
+       /*
+        *      Check for valid input, zero length names not permitted
+        */
+       if (name[0] == 0) {
+               log(L_ERR, "zero length username not permitted\n");
+               return -1;
+       }
 
+       socket = sql_get_socket();
+
+       /*
+        *      Find the NAS port ID.
+        */
+       if ((tmp = pairfind(request->packet->vps, PW_NAS_PORT_ID)) != NULL)
+               nas_port = tmp->lvalue;
+
+       /*
+        *      Find the entry for the user.
+        */
+
+ #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(name, '\\')) != NULL) {
+               strncpy(newname, ptr + 1, sizeof(newname));
+               newname[sizeof(newname) - 1] = 0;
+               strcpy(name, newname);
+       }
+ #endif /* NT_DOMAIN_HACK */
+
+
+        if ((found = sql_getvpdata(socket, sql->config->sql_authcheck_table, &check_tmp, name, PW_VP_USERDATA)) > 0) {
+                sql_getvpdata(socket, sql->config->sql_groupcheck_table, &check_tmp, name, PW_VP_GROUPDATA);
+                sql_getvpdata(socket, sql->config->sql_authreply_table, &reply_tmp, name, PW_VP_USERDATA);
+                sql_getvpdata(socket, sql->config->sql_groupreply_table, &reply_tmp, name, PW_VP_GROUPDATA);
+        } else {
+                int gcheck, greply;
+                gcheck = sql_getvpdata(socket, sql->config->sql_groupcheck_table, &check_tmp, "DEFAULT", PW_VP_GROUPDATA);
+                greply = sql_getvpdata(socket, sql->config->sql_groupreply_table, &reply_tmp, "DEFAULT", PW_VP_GROUPDATA);
+                if (gcheck && greply)
+                        found = 1;
+        }
+       sql_release_socket(socket);
+        if (!found) {
+                DEBUG2("User %s not found and DEFAULT not found", name);
+                return RLM_AUTZ_NOTFOUND;
+        }
 
-       if ((found = sql_getvpdata(sql->config.sql_authcheck_table, &check_tmp, name, PW_VP_USERDATA)) <= 0)
+        if (paircmp(request->packet->vps, check_tmp, reply_tmp) != 0) {
+               DEBUG2("Pairs do not match [%s]", name);
                return RLM_AUTZ_NOTFOUND;
-       sql_getvpdata(sql->config.sql_groupcheck_table, &check_tmp, name, PW_VP_GROUPDATA);
-       sql_getvpdata(sql->config.sql_authreply_table, &reply_tmp, name, PW_VP_USERDATA);
-       sql_getvpdata(sql->config.sql_groupreply_table, &reply_tmp, name, PW_VP_GROUPDATA);
-
-       pairmove(reply_pairs, &reply_tmp);
-       pairmove(check_pairs, &check_tmp);
-       pairfree(reply_tmp);
-       pairfree(check_tmp);
-
-       /*
-        *      Fix dynamic IP address if needed.
-        */
-       if ((tmp = pairfind(*reply_pairs, PW_ADD_PORT_TO_IP_ADDRESS)) != NULL){
-               if (tmp->lvalue != 0) {
-                       tmp = pairfind(*reply_pairs, PW_FRAMED_IP_ADDRESS);
-                       if (tmp) {
-                               /*
-                                *      FIXME: This only works because IP
-                                *      numbers are stored in host order
-                                *      everywhere in this program.
-                                */
-#ifdef ASCEND_PORT_HACK
-                               nas_port = ascend_port_number(nas_port);
-#endif
-                               tmp->lvalue += nas_port;
-                       }
-               }
-               pairdelete(reply_pairs, PW_ADD_PORT_TO_IP_ADDRESS);
        }
+        pairmove(reply_pairs, &reply_tmp);
+        pairmove(check_pairs, &check_tmp);
+        pairfree(reply_tmp);
+        pairfree(check_tmp);
+
+
+       /*
+        *      Fix dynamic IP address if needed.
+        */
+       if ((tmp = pairfind(*reply_pairs, PW_ADD_PORT_TO_IP_ADDRESS)) != NULL){
+               if (tmp->lvalue != 0) {
+                       tmp = pairfind(*reply_pairs, PW_FRAMED_IP_ADDRESS);
+                       if (tmp) {
+                               /*
+                                *      FIXME: This only works because IP
+                                *      numbers are stored in host order
+                                *      everywhere in this program.
+                                */
+                               tmp->lvalue += nas_port;
+                       }
+               }
+               pairdelete(reply_pairs, PW_ADD_PORT_TO_IP_ADDRESS);
+       }
 
-       /*
-        *      Remove server internal parameters.
-        */
        return RLM_AUTZ_OK;
 }
 
-static int rlm_sql_authenticate(REQUEST *request, char *user, char *password)
-{
+static int rlm_sql_authenticate(REQUEST *request) {
+
        VALUE_PAIR      *auth_pair;
        SQL_ROW         row;
+       SQLSOCK         *socket;
        char            *querystr;
        char            *escaped_user;
+       char            *user;
+       char            *password;
        char            query[] = "SELECT Value FROM %s WHERE UserName = '%s' AND Attribute = 'Password'";
 
+       user = request->username->strvalue;
+
        if ((auth_pair = pairfind(request->packet->vps, PW_AUTHTYPE)) == NULL)
           return RLM_AUTH_REJECT;
 
@@ -342,222 +158,34 @@ static int rlm_sql_authenticate(REQUEST *request, char *user, char *password)
                 log(L_ERR|L_CONS, "no memory");
                 exit(1);
         }
-       if((escaped_user = sql_escape_string(user)) == NULL) {
-                log(L_ERR|L_CONS, "no memory");
-                exit(1);
-        }
 
-       if((querystr = malloc(strlen(escaped_user)+strlen(sql->config.sql_authcheck_table)+sizeof(query)))
+       sql_escape_string(escaped_user, user, strlen(user));
+
+       if((querystr = malloc(strlen(escaped_user)+strlen(sql->config->sql_authcheck_table)+sizeof(query)))
                 == NULL) {
                 log(L_ERR|L_CONS, "no memory");
                 exit(1);
         }
 
-       sprintf(querystr, query, sql->config.sql_authcheck_table, escaped_user);
+       sprintf(querystr, query, sql->config->sql_authcheck_table, escaped_user);
 
         free(escaped_user);
         free(query);
 
-       sql_select_query(sql->AcctSock, querystr);
-       row = sql_fetch_row(sql->AcctSock);
-       sql_finish_select_query(sql->AcctSock);
+       socket = sql_get_socket();
+
+       sql_select_query(socket, querystr);
+       row = sql_fetch_row(socket);
+       sql_finish_select_query(socket);
 
        if (strncmp( password, row[0],strlen(password)) != 0)
                return RLM_AUTH_REJECT;
        else
                return RLM_AUTH_OK;
-
-
-
-
 }
 
 static int rlm_sql_accounting(REQUEST *request) {
 
-       time_t          nowtime;
-       struct tm       *tim;
-        char           datebuf[20];
-       int             *sqlpid;
-       int             sqlstatus;
-       FILE            *backupfile;
-       struct stat     backup;
-       char            *valbuf;
-       VALUE_PAIR      *pair;
-
-
-       if ((sql->sqlrecord = malloc(sizeof(SQLREC))) == NULL) {
-               log(L_ERR|L_CONS, "no memory");
-               exit(1);        
-       }
-       
-       pair = request->packet->vps;
-       strcpy(sql->sqlrecord->Realm, "");
-       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(sql->sqlrecord->AcctSessionId, pair->strvalue, SQLBIGREC);
-                       break;
-                       
-                case PW_USER_NAME:
-                       strncpy(sql->sqlrecord->UserName, pair->strvalue, SQLBIGREC);
-                       break;
-                       
-                case PW_NAS_IP_ADDRESS:
-                       ip_ntoa(sql->sqlrecord->NASIPAddress, pair->lvalue);
-                       //ipaddr2str(sql->sqlrecord->NASIPAddress, pair->lvalue);
-                       break;
-
-                case PW_NAS_PORT_ID:
-                       sql->sqlrecord->NASPortId = pair->lvalue;
-                       break;
-
-                case PW_NAS_PORT_TYPE:
-                                               valbuf = (char *)dict_valgetname(pair->lvalue, pair->name);
-                                               if(valbuf != (char *)NULL) {
-                               strncpy(sql->sqlrecord->NASPortType, valbuf, SQLBIGREC);
-                                               }
-                                               break;
-
-                case PW_ACCT_STATUS_TYPE:
-                                                       sql->sqlrecord->AcctStatusTypeId = pair->lvalue;
-                                               valbuf = (char *)dict_valgetname(pair->lvalue, pair->name);
-                                               if(valbuf != (char *)NULL) {
-                               strncpy(sql->sqlrecord->AcctStatusType, valbuf, SQLBIGREC);
-                                               }
-                                               break;
-
-                case PW_ACCT_SESSION_TIME:
-                       sql->sqlrecord->AcctSessionTime = pair->lvalue;
-                       break;
-
-                case PW_ACCT_AUTHENTIC:
-                                               valbuf = (char *)dict_valgetname(pair->lvalue, pair->name);
-                                               if(valbuf != (char *)NULL) {
-                               strncpy(sql->sqlrecord->AcctAuthentic, valbuf, SQLBIGREC);
-                                               }
-                                               break;
-
-                case PW_CONNECT_INFO:
-                       strncpy(sql->sqlrecord->ConnectInfo, pair->strvalue, SQLBIGREC);
-                       break;
-
-                case PW_ACCT_INPUT_OCTETS:
-                       sql->sqlrecord->AcctInputOctets = pair->lvalue;
-                       break;
-
-                case PW_ACCT_OUTPUT_OCTETS:
-                       sql->sqlrecord->AcctOutputOctets = pair->lvalue;
-                       break;
-
-                case PW_CALLED_STATION_ID:
-                       strncpy(sql->sqlrecord->CalledStationId, pair->strvalue, SQLLILREC);
-                       break;
-
-                case PW_CALLING_STATION_ID:
-                       strncpy(sql->sqlrecord->CallingStationId, pair->strvalue, SQLLILREC);
-                       break;
-
-/*                case PW_ACCT_TERMINATE_CAUSE:
-                                               valbuf = (char *)dict_valgetname(pair->lvalue, pair->name);
-                                               if(valbuf != (char *)NULL) {
-                               strncpy(sql->sqlrecord->AcctTerminateCause, valbuf, SQLBIGREC);
-                                               }
-                                               break;
-*/
-
-
-                case PW_SERVICE_TYPE:
-                                               valbuf = (char *)dict_valgetname(pair->lvalue, pair->name);
-                                               if(valbuf != (char *)NULL) {
-                               strncpy(sql->sqlrecord->ServiceType, valbuf, SQLBIGREC);
-                                               }
-                                               break;
-
-                case PW_FRAMED_PROTOCOL:
-                                               valbuf = (char *)dict_valgetname(pair->lvalue, pair->name);
-                                               if(valbuf != (char *)NULL) {
-                               strncpy(sql->sqlrecord->FramedProtocol, valbuf, SQLBIGREC);
-                                               }
-                                               break;
-
-                case PW_FRAMED_IP_ADDRESS:
-                       ip_ntoa(sql->sqlrecord->FramedIPAddress, pair->lvalue);
-                       //ipaddr2str(sql->sqlrecord->FramedIPAddress, pair->lvalue);
-                       break;
-
-                case PW_ACCT_DELAY_TIME:
-                       sql->sqlrecord->AcctDelayTime = pair->lvalue;
-                       break;
-
-                default:
-                       break;
-               }
-
-               pair = pair->next;
-       }
-
-
-        nowtime = time(0) - sql->sqlrecord->AcctDelayTime;
-        tim = localtime(&nowtime);
-        strftime(datebuf, sizeof(datebuf), "%Y%m%d%H%M%S", tim);
-
-        strncpy(sql->sqlrecord->AcctTimeStamp, datebuf, 20);
-       
-
-       /* If backup file exists we know the database was down */
-       if(stat(SQLBACKUP, &backup) == 0) {
-               if(backup.st_size > 0) {
-
-                       /* We'll fork a child to load records in the backup file */
-                       (pid_t)sqlpid = fork();
-                       if(sqlpid > 0) {
-
-                               /* suspend the parent while child reads records */
-                               while(waitpid((pid_t)sqlpid, &sqlstatus, 0) != (pid_t)sqlpid);
-                       }
-                       /* Child Process */
-                       if(sqlpid == 0) {
-                               if((backupfile = fopen(SQLBACKUP, "rwb")) == (FILE *)NULL) {
-                                       log(L_ERR, "Acct: (Child) Couldn't open file %s", SQLBACKUP);
-                                       exit(1);
-                               }
-
-                               /* Lock the mysql backup file, prefer lockf() over flock(). */
-#if defined(F_LOCK) && !defined( BSD)
-                               (void)lockf((int)backupfile, (int)F_LOCK, (off_t)SQL_LOCK_LEN);
-#else
-                               (void)flock(backupfile, SQL_LOCK_LEN);
-#endif  
-
-                               log(L_INFO, "Acct:  Clearing out sql backup file - %s", SQLBACKUP);
-
-                               while(!feof(backupfile)) {
-                                       if(fread(sql->backuprecord, sizeof(SQLREC), 1, backupfile) == 1) {
-
-                                               /* pass our filled structure to the
-                                                  function that will write to the database */
-                                               if (sql_save_acct(sql->backuprecord) == 0)
-                                                       return RLM_ACCT_FAIL_SOFT;
-
-                                       }
-
-                               }
-                               unlink((const char *)SQLBACKUP);
-                               exit(0);
-                       }
-               }
-       }
-       if (sql_save_acct(sql->sqlrecord) == 0)
-               return RLM_ACCT_FAIL_SOFT;
-       if (!sql->config.sql_keepopen) {
-               sql_close(sql->AcctSock);
-               sql->AcctSock = NULL;
-       }
-
        return RLM_ACCT_OK;
 }
 
index 33e33f9..84af7d5 100644 (file)
@@ -6,21 +6,10 @@
 
 #include "sql_module.h"
 
-#define QUERYLOG               "/var/log/radacct/radius.sql"
-#define SQLCONFIGFILE          "rlm_sql.conf"
-#define SQLBACKUP              "/var/log/radacct/sqlbackup.dat"
-#define CHECKRAD1              "/usr/sbin/checkrad"
-#define CHECKRAD2              "/usr/local/sbin/checkrad"
-
-#define        SQLBIGREC               32
-#define        SQLLILREC               16
 #define PW_VP_USERDATA         1
 #define PW_VP_GROUPDATA                2
 #define PW_VP_REALMDATA                3
 
-#define MAX_TABLE_LEN          20
-#define MAX_AUTH_QUERY_LEN     256
-
 typedef struct sqlrec {
        char            AcctSessionId[SQLBIGREC];
         char            UserName[SQLBIGREC];
@@ -43,46 +32,21 @@ typedef struct sqlrec {
         char            FramedProtocol[SQLBIGREC];
         char            FramedIPAddress[SQLLILREC];
         unsigned long  AcctDelayTime;
-} SQLREC; 
-
-typedef struct sqlconfig {
-       char            sql_type[40];
-       char            sql_server[40];
-       int             sql_port;
-       char            sql_login[20];
-       char            sql_password[20];
-       char            sql_db[20];
-       char            sql_acct_table[MAX_TABLE_LEN];
-       char            sql_authcheck_table[MAX_TABLE_LEN];
-       char            sql_authreply_table[MAX_TABLE_LEN];
-       char            sql_groupcheck_table[MAX_TABLE_LEN];
-       char            sql_groupreply_table[MAX_TABLE_LEN];
-       char            sql_usergroup_table[MAX_TABLE_LEN];
-       char            sql_realm_table[MAX_TABLE_LEN];
-       char            sql_realmgroup_table[MAX_TABLE_LEN];
-       char            sql_nas_table[MAX_TABLE_LEN];
-       char            sql_dict_table[MAX_TABLE_LEN];
-       int             sql_keepopen;
-       int             sqltrace;
-} SQLCONFIG;
-
-typedef struct sql {
-       SQLSOCK         *AuthSock;
-       SQLSOCK         *AcctSock;
-       SQLREC          *sqlrecord;
-       SQLREC          *backuprecord;
-       SQLCONFIG       config;
-} SQL;
-       
-#define SQL_LOCK_LEN sizeof(SQLREC)
-
-int            sql_start();
-int            sql_save_acct(SQLREC *sqlrecord);
-int            sql_userparse(VALUE_PAIR **first_pair, SQL_ROW row);
-int            sql_checksocket(const char *facility);
-int            sql_getvpdata(char *table, VALUE_PAIR **vp, char *user, int mode);
-int            sql_check_multi(char *name, VALUE_PAIR *request, int maxsimul);
-
+} SQLACCTREC; 
+
+int             sql_init(int reload);
+int             sql_init_socket(int reload);
+int             sql_close_socket(SQLSOCK *socket);
+SQLSOCK         *sql_get_socket(void);
+int             sql_release_socket(SQLSOCK *socket);
+int             sql_save_acct(SQLSOCK *socket, SQLACCTREC *sqlrecord);
+int             sql_userparse(VALUE_PAIR **first_pair, SQL_ROW row, int mode);
+int             sql_read_realms(SQLSOCK *socket);
+int             sql_getvpdata(SQLSOCK *socket, char *table, VALUE_PAIR **vp, char *user, int mode);
+int             sql_check_multi(SQLSOCK *socket, char *name, VALUE_PAIR *request, int maxsimul);
+int             sql_read_naslist(SQLSOCK *socket);
+int             sql_read_clients(SQLSOCK *socket);
+int             sql_dict_init(SQLSOCK *socket);
 
 SQL *sql;
 
index c9b2bee..96217e9 100644 (file)
@@ -1,11 +1,9 @@
-
 #include       <sys/types.h>
 #include       <sys/socket.h>
 #include       <sys/time.h>
 #include       <sys/file.h>
 #include       <sys/stat.h>
 #include       <netinet/in.h>
-#include        <arpa/inet.h>
 
 #include       <stdio.h>
 #include       <stdlib.h>
 #include       <errno.h>
 #include       <sys/wait.h>
 
-#include       <string.h>
-
 #include       "radiusd.h"
 #include       "rlm_sql.h"
 
+/*************************************************************************
+ *
+ *     Function: mysql_start
+ *
+ *     Purpose: Reads SQL Config File 
+ *
+ *************************************************************************/
+
+int sql_init(int reload) {
+       FILE    *sqlfd;
+        char    dummystr[64];
+        char    namestr[64];
+        int     line_no = 0;
+        char    buffer[256];
+        char    sqlfile[256];
+
+       if (reload)
+               free(sql->config);
+       if ((sql->config = malloc(sizeof(SQL_CONFIG))) == NULL) {
+               log(L_ERR|L_CONS, "no memory");
+               exit(1);
+       }
+       strcpy(sql->config->sql_server,"localhost");
+       strcpy(sql->config->sql_login,"");
+       strcpy(sql->config->sql_password,"");
+       strcpy(sql->config->sql_db,"radius");
+       strcpy(sql->config->sql_authcheck_table,"radcheck");
+       strcpy(sql->config->sql_authreply_table,"radreply");
+       strcpy(sql->config->sql_groupcheck_table,"radgroupcheck");
+       strcpy(sql->config->sql_groupreply_table,"radgroupreply");
+       strcpy(sql->config->sql_usergroup_table,"usergroup");
+       strcpy(sql->config->sql_realmgroup_table,"realmgroup");
+       strcpy(sql->config->sql_acct_table,"radacct");
+       sql->config->sqltrace = 0;
+       sql->config->sensitiveusername = 1;
+       sql->config->deletestalesessions = 0;
+
+       strcpy(sql->config->sql_nas_table,"nas");
+       strcpy(sql->config->sql_realm_table, "realms");
+       strcpy(sql->config->sql_dict_table,"dictionary");
+       sql->config->max_sql_socks = MAX_SQL_SOCKS;
+
+        sprintf(sqlfile, "%s/%s", radius_dir, SQLCONFIGFILE);
+        if((sqlfd = fopen(sqlfile, "r")) == (FILE *)NULL) {
+                log(L_ERR,"could not read MySQL configuration file %s",sqlfile);
+                return(-1);
+        }
 
+        line_no = 0;
+        while(fgets(buffer, sizeof(buffer), sqlfd) != (char *)NULL) {
+                line_no++;
+
+                /* Skip empty space */
+                if(*buffer == '#' || *buffer == '\0' || *buffer == '\n') {
+                        continue;
+                }
+
+                if(strncasecmp(buffer, "server", 6) == 0) {
+                        /* Read the SERVER line */
+                        if(sscanf(buffer, "%s%s", dummystr, namestr) != 2) {
+                               log(L_ERR,"invalid attribute on line %d of configuration file %s", line_no,sqlfile);
+                       } else {
+                         strcpy(sql->config->sql_server,namestr);
+                       }
+               }
+                if(strncasecmp(buffer, "login", 5) == 0) {
+                        /* Read the LOGIN line */
+                        if(sscanf(buffer, "%s%s", dummystr, namestr) != 2) {
+                               log(L_ERR,"invalid attribute on line %d of configuration file %s", line_no,sqlfile);
+                       } else {
+                         strcpy(sql->config->sql_login,namestr);
+                       }
+               }
+                if(strncasecmp(buffer, "password", 8) == 0) {
+                        /* Read the PASSWORD line */
+                        if(sscanf(buffer, "%s%s", dummystr, namestr) != 2) {
+                               log(L_ERR,"invalid attribute on line %d of configuration file %s", line_no,sqlfile);
+                       } else {
+                         strcpy(sql->config->sql_password,namestr);
+                       }
+               }
+                if(strncasecmp(buffer, "radius_db", 9) == 0) {
+                        /* Read the RADIUS_DB line */
+                        if(sscanf(buffer, "%s%s", dummystr, namestr) != 2) {
+                               log(L_ERR,"invalid attribute on line %d of configuration file %s", line_no,sqlfile);
+                       } else {
+                         strcpy(sql->config->sql_db,namestr);
+                       }
+               }
+                if(strncasecmp(buffer, "authcheck_table", 15) == 0) {
+                        /* Read the AUTHCHECK_TABLE line */
+                        if(sscanf(buffer, "%s%s", dummystr, namestr) != 2) {
+                               log(L_ERR,"invalid attribute on line %d of configuration file %s", line_no,sqlfile);
+                       } else {
+                         strncpy(sql->config->sql_authcheck_table,namestr, MAX_TABLE_LEN);
+                       }
+               }
+                if(strncasecmp(buffer, "authreply_table", 15) == 0) {
+                        /* Read the AUTHREPLY_TABLE line */
+                        if(sscanf(buffer, "%s%s", dummystr, namestr) != 2) {
+                               log(L_ERR,"invalid attribute on line %d of configuration file %s", line_no,sqlfile);
+                       } else {
+                         strncpy(sql->config->sql_authreply_table,namestr, MAX_TABLE_LEN);
+                       }
+               }
+                if(strncasecmp(buffer, "groupcheck_table", 16) == 0) {
+                        /* Read the GROUPCHECK_TABLE line */
+                        if(sscanf(buffer, "%s%s", dummystr, namestr) != 2) {
+                               log(L_ERR,"invalid attribute on line %d of configuration file %s", line_no,sqlfile);
+                       } else {
+                         strncpy(sql->config->sql_groupcheck_table,namestr, MAX_TABLE_LEN);
+                       }
+               }
+                if(strncasecmp(buffer, "groupreply_table", 16) == 0) {
+                        /* Read the GROUP_REPLY_TABLE line */
+                        if(sscanf(buffer, "%s%s", dummystr, namestr) != 2) {
+                               log(L_ERR,"invalid attribute on line %d of configuration file %s", line_no,sqlfile);
+                       } else {
+                         strncpy(sql->config->sql_groupreply_table,namestr, MAX_TABLE_LEN);
+                       }
+               }
+                if(strncasecmp(buffer, "usergroup_table", 15) == 0) {
+                        /* Read the USERGROUP_TABLE line */
+                        if(sscanf(buffer, "%s%s", dummystr, namestr) != 2) {
+                               log(L_ERR,"invalid attribute on line %d of configuration file %s", line_no,sqlfile);
+                       } else {
+                         strncpy(sql->config->sql_usergroup_table,namestr, MAX_TABLE_LEN);
+                       }
+               }
+                if(strncasecmp(buffer, "realmgroup_table", 16) == 0) {
+                        /* Read the REALMGROUP_TABLE line */
+                        if(sscanf(buffer, "%s%s", dummystr, namestr) != 2) {
+                               log(L_ERR,"invalid attribute on line %d of configuration file %s", line_no,sqlfile);
+                       } else {
+                         strncpy(sql->config->sql_realmgroup_table,namestr, MAX_TABLE_LEN);
+                       }
+               }
+                if(strncasecmp(buffer, "acct_table", 10) == 0) {
+                        /* Read the ACCT_TABLE line */
+                        if(sscanf(buffer, "%s%s", dummystr, namestr) != 2) {
+                               log(L_ERR,"invalid attribute on line %d of configuration file %s", line_no,sqlfile);
+                       } else {
+                         strncpy(sql->config->sql_acct_table,namestr, MAX_TABLE_LEN);
+                       }
+               }
+                if(strncasecmp(buffer, "nas_table", 9) == 0) {
+                        /* Read the NAS_TABLE line */
+                        if(sscanf(buffer, "%s%s", dummystr, namestr) != 2) {
+                               log(L_ERR,"invalid attribute on line %d of configuration file %s", line_no,sqlfile);
+                       } else {
+                         strncpy(sql->config->sql_nas_table,namestr, MAX_TABLE_LEN);
+                       }
+               }
+                if(strncasecmp(buffer, "realm_table", 9) == 0) {
+                       /* Read the REALM_TABLE line */
+                       if(sscanf(buffer, "%s%s", dummystr, namestr) != 2) {
+                               log(L_ERR,"invalid attribute on line %d of configuration file %s", line_no,sqlfile);
+                      } else {
+                         strncpy(sql->config->sql_realm_table,namestr, MAX_TABLE_LEN);
+                      }
+               }
+                if(strncasecmp(buffer, "dict_table", 9) == 0) {
+                        /* Read the DICT_TABLE line */
+                        if(sscanf(buffer, "%s%s", dummystr, namestr) != 2) {
+                               log(L_ERR,"invalid attribute on line %d of configuration file %s", line_no,sqlfile);
+                       } else {
+                         strncpy(sql->config->sql_dict_table,namestr, MAX_TABLE_LEN);
+                       }
+               }
+                if(strncasecmp(buffer, "sqltrace", 8) == 0) {
+                        /* Read the SQLTRACE line */
+                        if(sscanf(buffer, "%s%s", dummystr, namestr) != 2) {
+                               log(L_ERR,"invalid attribute on line %d of configuration file %s", line_no,sqlfile);
+                      } else {
+                         if(strncasecmp(namestr, "on", 2) == 0) {
+                           sql->config->sqltrace = 1;
+                         } else {
+                           sql->config->sqltrace = 0;
+                         }
+                       }
+               }
+               if(strncasecmp(buffer, "sensitiveusername", 17) == 0) {
+                        /* Read the SENSITIVEUSERNAME line */
+                        if(sscanf(buffer, "%s%s", dummystr, namestr) != 2) {
+                               log(L_ERR,"invalid attribute on line %d of configuration file %s", line_no,sqlfile);
+                       } else {
+                         if(strncasecmp(namestr, "on", 2) == 0) {
+                           sql->config->sensitiveusername = 1;
+                        } else {
+                           sql->config->sensitiveusername = 0;
+                        }
+                       }
+               }
+               if(strncasecmp(buffer, "deletestalesessions", 19) == 0) {
+                        /* Read the DELETESTALESESSIONS line */
+                        if(sscanf(buffer, "%s%s", dummystr, namestr) != 2) {
+                               log(L_ERR,"invalid attribute on line %d of configuration file %s", line_no,sqlfile);
+                       } else {
+                         if(strncasecmp(namestr, "on", 2) == 0) {
+                           sql->config->deletestalesessions = 1;
+                        } else {
+                           sql->config->deletestalesessions = 0;
+                        }
+                       }
+               }
+
+       }
+       fclose(sqlfd);
+       
+       log(L_INFO,"SQL: Attempting to connect to %s@%s:%s", sql->config->sql_login, sql->config->sql_server, sql->config->sql_db);
+
+       sql_init_socket(reload);
+           
+       return 0;
+}
 
 
 /*************************************************************************
  *
+ *     Function: sql_init_socket
+ *
+ *     Purpose: Connect to the sql server
+ *
+ *************************************************************************/
+int sql_init_socket(int reload) {
+
+       int i;
+
+       /* Clear up old connections if reload */
+       if (reload)
+               for (i = 0; i < sql->config->max_sql_socks; i++)
+                       if (!sql_close_socket(sql->socks[i]))
+                               log(L_CONS|L_ERR, "Could not release socket %d", i);
+       
+
+        /* Initalize our connection pool */
+        for (i = 0; i < sql->config->max_sql_socks; i++) {
+               if ((sql->socks[i] = sql_create_socket()) == NULL) {
+                       log(L_CONS|L_ERR, "SQL: Failed to connect socket %d", i);
+               } else {
+                       sql->socks[i]->id = i;
+                       sql->socks[i]->in_use = 0;
+                       DEBUG2("SQL: Connected socket %d", i);
+               }
+       }
+           
+       return 1;
+}
+
+
+/*************************************************************************
+ *
+ *     Function: sql_close_socket
+ *
+ *     Purpose: Close and free a sql socket
+ *
+ *************************************************************************/
+int sql_close_socket(SQLSOCK *socket) {
+
+       DEBUG2("SQL: Closing socket %d", socket->id);
+       sql_close(socket);
+       free(socket);
+       return 1;
+}
+
+/*************************************************************************
+ *
+ *     Function: sql_get_socket
+ *
+ *     Purpose: Return a SQL socket from the connection pool           
+ *
+ *************************************************************************/
+SQLSOCK *sql_get_socket(void) {
+
+       int     i = 0;
+       
+       DEBUG2("SQL: Attempting to reserve socket");
+       while (1) {
+               if (i == sql->config->max_sql_socks)
+                       i = 0;
+               if (sql->socks[i]->in_use == 0) {
+                       sql->socks[i]->in_use = 1;
+                       gettimeofday(&(sql->socks[i]->tv), NULL);
+                       DEBUG2("SQL: Reserved socket %d", i);
+                       return sql->socks[i];
+               }
+               i++;
+       }
+}
+
+/*************************************************************************
+ *
+ *     Function: sql_release_socket
+ *
+ *     Purpose: Frees a SQL socket back to the connection pool           
+ *
+ *************************************************************************/
+int sql_release_socket(SQLSOCK *socket) {
+
+       struct timeval  tv;
+       double          start, end;
+       char            buff[24];
+
+       gettimeofday(&tv, NULL);
+       sprintf(buff, "%ld.%2ld", tv.tv_sec, tv.tv_usec);
+       end = strtod(buff, NULL);
+       sprintf(buff, "%ld %2.0ld", socket->tv.tv_sec, socket->tv.tv_usec);
+       start = strtod(buff, NULL);
+       DEBUG2("SQL: Socket %d used for %.2f seconds", socket->id, end - start);
+
+       socket->tv.tv_sec = tv.tv_sec;
+       socket->tv.tv_usec = tv.tv_usec;
+       sql->socks[socket->id]->in_use = 0;
+       DEBUG2("SQL: Released socket %d", socket->id);
+       return 1;
+}
+
+/*************************************************************************
+ *
  *     Function: sql_save_acct
  *
  *     Purpose: Write data from the sqlrecord structure to the database
  *
  *************************************************************************/
 
-int sql_save_acct(SQLREC *sqlrecord) {
+int sql_save_acct(SQLSOCK *socket, SQLACCTREC *sqlrecord) {
 
        char            querystr[2048];
        FILE            *sqlfile;
-       FILE            *backupfile;
        int             num = 0;
 #ifdef NT_DOMAIN_HACK
        char            *ptr;
@@ -47,8 +358,8 @@ int sql_save_acct(SQLREC *sqlrecord) {
        
 
 
-     if((sqlfile = fopen(QUERYLOG, "a")) == (FILE *)NULL) {
-            log(L_ERR, "Acct: Couldn't open file %s", QUERYLOG);
+     if((sqlfile = fopen(SQLQUERYLOG, "a")) == (FILE *)NULL) {
+            log(L_ERR, "Acct: Couldn't open file %s", SQLQUERYLOG);
      } else { 
         #if defined(F_LOCK) && !defined(BSD)
               (void)lockf((int)sqlfile, (int)F_LOCK, (off_t)SQL_LOCK_LEN);
@@ -71,19 +382,17 @@ int sql_save_acct(SQLREC *sqlrecord) {
        }
 #endif /* NT_DOMAIN_HACK */
 
- if (sql_checksocket("Acct")) {
-
      if (sqlrecord->AcctStatusTypeId == PW_STATUS_ACCOUNTING_ON || sqlrecord->AcctStatusTypeId == PW_STATUS_ACCOUNTING_OFF) {
         log(L_INFO, "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' WHERE AcctSessionTime=0 AND AcctStopTime=0 AND NASIPAddress= '%s' AND AcctStartTime <= '%s'", sql->config.sql_acct_table, sqlrecord->AcctTimeStamp, sqlrecord->AcctTimeStamp, sqlrecord->AcctTerminateCause, sqlrecord->NASIPAddress, sqlrecord->AcctTimeStamp);
+         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'", sql->config->sql_acct_table, sqlrecord->AcctTimeStamp, sqlrecord->AcctTimeStamp, sqlrecord->AcctTerminateCause, sqlrecord->AcctDelayTime, sqlrecord->NASIPAddress, sqlrecord->AcctTimeStamp);
 
-                if (sql_query(sql->AcctSock, querystr) < 0)
-             log(L_ERR, "Acct: Couldn't update SQL accounting after NAS reboot - %s", sql_error(sql->AcctSock));
-        sql_finish_query(sql->AcctSock);
+                if (sql_query(socket, querystr) < 0)
+             log(L_ERR, "Acct: Couldn't update SQL accounting after NAS reboot - %s", sql_error(socket));
+        sql_finish_query(socket);
 
          if (sqlfile) {
               fputs(querystr, sqlfile);
@@ -94,10 +403,10 @@ int sql_save_acct(SQLREC *sqlrecord) {
       } 
 
        if (sqlrecord->AcctStatusTypeId == PW_STATUS_ALIVE) {
-               sprintf(querystr, "UPDATE %s SET Framed-IP-Address = '%s' WHERE AcctSessionId = '%s' AND UserName = '%s' AND NASIPAddress= '%s'", sql->config.sql_acct_table, sqlrecord->FramedIPAddress, sqlrecord->AcctSessionId, sqlrecord->UserName, sqlrecord->NASIPAddress);
-               if (sql_query(sql->AcctSock, querystr) < 0)
-                       log(L_ERR, "Acct: Couldn't update SQL accounting after NAS reboot - %s", sql_error(sql->AcctSock));
-               sql_finish_query(sql->AcctSock);
+               sprintf(querystr, "UPDATE %s SET FramedIPAddress = '%s' WHERE AcctSessionId = '%s' AND UserName = '%s' AND NASIPAddress= '%s'", sql->config->sql_acct_table, sqlrecord->FramedIPAddress, sqlrecord->AcctSessionId, sqlrecord->UserName, sqlrecord->NASIPAddress);
+               if (sql_query(socket, querystr) < 0)
+                       log(L_ERR, "Acct: Couldn't update SQL accounting for ALIVE packet - %s", sql_error(socket));
+               sql_finish_query(socket);
 
                if (sqlfile) {
                        fputs(querystr, sqlfile);
@@ -107,28 +416,28 @@ int sql_save_acct(SQLREC *sqlrecord) {
                return 0;
        }
 
-
           /* Got start record */
           if(sqlrecord->AcctStatusTypeId == PW_STATUS_START) {
              
              /* Set start time on record with only a stop record */
-            snprintf(querystr, 2048, "UPDATE %s SET AcctStartTime = '%s' WHERE AcctSessionId = '%s' AND UserName = '%s' AND NASIPAddress = '%s'", 
-            sql->config.sql_acct_table,
+            snprintf(querystr, 2048, "UPDATE %s SET AcctStartTime = '%s', AcctStartDelay = %ld WHERE AcctSessionId = '%s' AND UserName = '%s' AND NASIPAddress = '%s'", 
+            sql->config->sql_acct_table,
              sqlrecord->AcctTimeStamp,
+            sqlrecord->AcctDelayTime,
              sqlrecord->AcctSessionId,
              sqlrecord->UserName,
              sqlrecord->NASIPAddress
              );
-                    if (sql_query(sql->AcctSock, querystr) < 0)
-               log(L_ERR, "Acct: Couldn't update SQL accounting START record - %s", sql_error(sql->AcctSock));
-            sql_finish_query(sql->AcctSock);
+                    if (sql_query(socket, querystr) < 0)
+               log(L_ERR, "Acct: Couldn't update SQL accounting START record - %s", sql_error(socket));
+            sql_finish_query(socket);
 
-             num = sql_affected_rows(sql->AcctSock);
+             num = sql_affected_rows(socket);
              if (num == 0) {
 
                 /* Insert new record with blank stop time until stop record is got */
-                snprintf(querystr, 2048, "INSERT INTO %s VALUES (0, '%s', '%s', '%s', '%s', %ld, '%s', '%s', 0, 0, '%s', '%s', 0, 0, '%s', '%s', '', '%s', '%s', '%s', %ld)",
-                sql->config.sql_acct_table,
+                snprintf(querystr, 2048, "INSERT INTO %s VALUES (0, '%s', '%s', '%s', '%s', %ld, '%s', '%s', 0, 0, '%s', '%s', 0, 0, '%s', '%s', '', '%s', '%s', '%s', %ld, 0)",
+                sql->config->sql_acct_table,
                 sqlrecord->AcctSessionId,
                 sqlrecord->UserName,
                 sqlrecord->Realm,
@@ -146,68 +455,79 @@ int sql_save_acct(SQLREC *sqlrecord) {
                 sqlrecord->AcctDelayTime
                 );                  
 
-                       if (sql_query(sql->AcctSock, querystr) < 0)
-                 log(L_ERR, "Acct: Couldn't insert SQL accounting START record - %s", sql_error(sql->AcctSock));
-               sql_finish_query(sql->AcctSock);
+                       if (sql_query(socket, querystr) < 0)
+                 log(L_ERR, "Acct: Couldn't insert SQL accounting START record - %s", sql_error(socket));
+               sql_finish_query(socket);
              }
 
            /* Got stop record */
            } else {
 
-               sprintf(querystr, "SELECT RadAcctId FROM %s WHERE AcctSessionId='%s' AND NASIPAddress='%s' AND UserName='%s'", sql->config.sql_acct_table, sqlrecord->AcctSessionId, sqlrecord->NASIPAddress, sqlrecord->UserName);
-               sql_select_query(sql->AcctSock, querystr);
-               num = sql_num_rows(sql->AcctSock);
-               sql_finish_select_query(sql->AcctSock);
+             sprintf(querystr, "SELECT RadAcctId FROM %s WHERE AcctSessionId='%s' AND NASIPAddress='%s' AND UserName='%s'", sql->config->sql_acct_table, sqlrecord->AcctSessionId, sqlrecord->NASIPAddress, sqlrecord->UserName);
+              sql_select_query(socket, querystr);
+              num = sql_num_rows(socket);
+             sql_finish_select_query(socket);
 
-               if (num > 0) {
+             if (num > 0) {
 
-                       /* Set stop time on matching record with start time */
-                       snprintf(querystr, 2048, "UPDATE %s SET AcctStopTime = '%s', AcctSessionTime = '%lu', AcctInputOctets = '%u', AcctOutputOctets = '%u', AcctTerminateCause = '%s' WHERE AcctSessionId = '%s' AND UserName = '%s' AND NASIPAddress = '%s'", 
-                       sql->config.sql_acct_table,
-                       sqlrecord->AcctTimeStamp,
-                       sqlrecord->AcctSessionTime,
-                       sqlrecord->AcctInputOctets,
-                       sqlrecord->AcctOutputOctets,
-                       sqlrecord->AcctTerminateCause,
-                       sqlrecord->AcctSessionId,
-                       sqlrecord->UserName,
-                       sqlrecord->NASIPAddress);
+                /* Set stop time on matching record with start time */
+               snprintf(querystr, 2048, "UPDATE %s SET AcctStopTime = '%s', AcctSessionTime = '%lu', AcctInputOctets = '%lu', AcctOutputOctets = '%lu', AcctTerminateCause = '%s', AcctStopDelay = %ld WHERE AcctSessionId = '%s' AND UserName = '%s' AND NASIPAddress = '%s'", 
+               sql->config->sql_acct_table,
+                sqlrecord->AcctTimeStamp,
+                sqlrecord->AcctSessionTime,
+                sqlrecord->AcctInputOctets,
+                sqlrecord->AcctOutputOctets,
+                sqlrecord->AcctTerminateCause,
+               sqlrecord->AcctDelayTime,
+                sqlrecord->AcctSessionId,
+                sqlrecord->UserName,
+                sqlrecord->NASIPAddress
+                );
 
 
-                       if (sql_query(sql->AcctSock, querystr) < 0)
-                               log(L_ERR, "Acct: Couldn't update SQL accounting STOP record - %s", sql_error(sql->AcctSock));
-                       sql_finish_query(sql->AcctSock);
+                       if (sql_query(socket, querystr) < 0)
+                  log(L_ERR, "Acct: Couldn't update SQL accounting STOP record - %s", sql_error(socket));
+               sql_finish_query(socket);
 
-               } else if (num == 0) {
+             } else if (num == 0) {
 
-            
-                       /* Insert record with no start time until matching start record comes */
-                       snprintf(querystr, 2048, "INSERT INTO %s VALUES (0, '%s', '%s', '%s', '%s', %ld, '%s', 0, '%s', '%lu', '%s', '%s', '%u', '%u', '%s', '%s', '%s', '%s', '%s', '%s', %ld)",
-                       sql->config.sql_acct_table,
-                       sqlrecord->AcctSessionId,
-                       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(sql->AcctSock, querystr) < 0)
-                               log(L_ERR, "Acct: Couldn't insert SQL accounting STOP record - %s", sql_error(sql->AcctSock));
-                       sql_finish_query(sql->AcctSock);
+#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) {
+                       log(L_ERR, "Acct: 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 VALUES (0, '%s', '%s', '%s', '%s', %ld, '%s', 0, '%s', '%lu', '%s', '%s', '%lu', '%lu', '%s', '%s', '%s', '%s', '%s', '%s', 0, %ld)",
+                sql->config->sql_acct_table,
+                sqlrecord->AcctSessionId,
+                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(socket, querystr) < 0)
+                  log(L_ERR, "Acct: Couldn't insert SQL accounting STOP record - %s", sql_error(socket));
+               sql_finish_query(socket);
+             }
 
           }
           if (sqlfile) {
@@ -217,33 +537,6 @@ int sql_save_acct(SQLREC *sqlrecord) {
                 fclose(sqlfile);
           }
 
-
-       } else {
-
-           /*
-            *  The database is down for some reason
-             *  So open up the backup file to save records in
-            */
-
-             if((backupfile = fopen(SQLBACKUP, "a")) == (FILE *)NULL) {
-                 log(L_ERR, "Acct: Couldn't open file %s", SQLBACKUP);
-             } else {
-                  /*
-                   * Lock the sql backup file, prefer lockf() over flock().
-                   */
-                   #if defined(F_LOCK) && !defined(BSD)
-                       (void)lockf((int)backupfile, (int)F_LOCK, (off_t)SQL_LOCK_LEN);
-                   #else
-                       (void)flock(backupfile, SQL_LOCK_EX);
-                   #endif
-                   if(fwrite(sqlrecord, sizeof(SQLREC), 1, backupfile) < 1) {
-                       log(L_ERR, "Acct: Couldn't write to file %s", SQLBACKUP);
-                   }
-                   fclose(backupfile);
-              }
-
-       }
-        
      return 0;
 
 }
@@ -256,7 +549,7 @@ int sql_save_acct(SQLREC *sqlrecord) {
  *     Purpose: Read entries from the database and fill VALUE_PAIR structures
  *
  *************************************************************************/
-int sql_userparse(VALUE_PAIR **first_pair, SQL_ROW row) {
+int sql_userparse(VALUE_PAIR **first_pair, SQL_ROW row, int mode) {
 
        DICT_ATTR       *attr;
        VALUE_PAIR      *pair, *check;
@@ -271,17 +564,16 @@ int sql_userparse(VALUE_PAIR **first_pair, SQL_ROW row) {
 
        /* If attribute is already there, skip it because we checked usercheck first 
           and we want user settings to over ride group settings */
-       if ((check = pairfind(*first_pair, attr->attr)) != NULL)
+       if ((check = pairfind(*first_pair, attr->attr)) != NULL && mode == PW_VP_GROUPDATA)
                return 0;
 
-       pair = pairmake(row[2], row[3], T_OP_EQ);
-       pairadd(first_pair, pair);
-
-       return 0;
+        pair = pairmake(row[2], row[3], T_OP_EQ);
+        pairadd(first_pair, pair);
+        return 0;
 }
 
 
-
 /*************************************************************************
  *
  *     Function: sql_getvpdata
@@ -289,29 +581,48 @@ int sql_userparse(VALUE_PAIR **first_pair, SQL_ROW row) {
  *     Purpose: Get any group check or reply pairs
  *
  *************************************************************************/
-int sql_getvpdata(char *table, VALUE_PAIR **vp, char *user, int mode) {
+int sql_getvpdata(SQLSOCK *socket, char *table, VALUE_PAIR **vp, char *user, int mode) {
 
        char            querystr[256];
+       char            authstr[256];
+       char            username[AUTH_STRING_LEN*2+1];
        SQL_ROW         row;
        int             rows;
-
-       if (mode == PW_VP_USERDATA)
-               sprintf(querystr, "SELECT * FROM %s WHERE UserName = '%s'", table, user);
-       else if (mode == PW_VP_GROUPDATA)
-               sprintf(querystr, "SELECT %s.* FROM %s, %s WHERE %s.UserName = '%s' AND %s.GroupName = %s.GroupName ORDER BY %s.id", table, table, sql->config.sql_usergroup_table, sql->config.sql_usergroup_table, user, sql->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, sql->config.sql_realmgroup_table, sql->config.sql_realmgroup_table, user, sql->config.sql_realmgroup_table, table, table);
-        sql_checksocket("Auth");
-       sql_select_query(sql->AuthSock, querystr);
-       rows = sql_num_rows(sql->AuthSock);
-       while ((row = sql_fetch_row(sql->AuthSock))) {
-               if (sql_userparse(vp, row) != 0) {
-                       log(L_ERR|L_CONS, "Error getting data from SQL database");
-                       sql_finish_select_query(sql->AuthSock);
+       int             length;
+
+       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 (sql->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 (sql->config->sensitiveusername) 
+                       sprintf(authstr, "STRCMP(%s.Username, '%s') = 0", sql->config->sql_usergroup_table, username);
+               else
+                       sprintf(authstr, "%s.UserName = '%s'",sql->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, sql->config->sql_usergroup_table, authstr, sql->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, sql->config->sql_realmgroup_table, sql->config->sql_realmgroup_table, username, sql->config->sql_realmgroup_table, table, table);
+       sql_select_query(socket, querystr);
+       rows = sql_num_rows(socket);
+       while ((row = sql_fetch_row(socket))) {
+
+               if (sql_userparse(vp, row, mode) != 0) {
+                       log(L_ERR|L_CONS, "Error getting data from SQL");
+                       sql_finish_select_query(socket);
                        return -1;
                }
        }
-       sql_finish_select_query(sql->AuthSock);
+       sql_finish_select_query(socket);
 
        return rows;
 
@@ -319,7 +630,8 @@ int sql_getvpdata(char *table, VALUE_PAIR **vp, char *user, int mode) {
 
 
 static int got_alrm;
-static void alrm_handler() {
+static void alrm_handler()
+{
        got_alrm = 1;
 }
 
@@ -342,8 +654,8 @@ static int sql_check_ts(SQL_ROW row) {
        /*
         *      Find NAS type.
         */
-       if ((nas = nas_find(ip_addr(row[3]))) == NULL) {
-                log(L_ERR, "Accounting: unknown NAS [%s]", row[3]);
+       if ((nas = nas_find(ipstr2long(row[4]))) == NULL) {
+                log(L_ERR, "Accounting: unknown NAS [%s]", row[4]);
                 return -1;
         }
 
@@ -417,22 +729,25 @@ static int sql_check_ts(SQL_ROW row) {
  *     Purpose: Check radius accounting for duplicate logins
  *
  *************************************************************************/
-int sql_check_multi(char *name, VALUE_PAIR *request, int maxsimul) {
+int sql_check_multi(SQLSOCK *socket, char *name, VALUE_PAIR *request, int maxsimul) {
 
        char            querystr[256];
+       char            authstr[256];
        VALUE_PAIR      *fra;
        SQL_ROW         row;
        int             count = 0;
        uint32_t        ipno = 0;
        int             mpp = 1;
 
-       if (!sql_checksocket("Auth"))
-               return 0;
-       sprintf(querystr, "SELECT COUNT(*) FROM %s WHERE UserName = '%s' AND AcctStopTime = 0", sql->config.sql_acct_table, name);
-       sql_select_query(sql->AuthSock, querystr);
-       row = sql_fetch_row(sql->AuthSock);
+       if (sql->config->sensitiveusername)
+               sprintf(authstr, "STRCMP(UserName, '%s') = 0", name);
+       else
+               sprintf(authstr, "UserName = '%s'", name);
+       sprintf(querystr, "SELECT COUNT(*) FROM %s WHERE %s AND AcctStopTime = 0", sql->config->sql_acct_table, authstr);
+       sql_select_query(socket, querystr);
+       row = sql_fetch_row(socket);
        count = atoi(row[0]);
-       sql_finish_select_query(sql->AuthSock);
+       sql_finish_select_query(socket);
 
        if (count < maxsimul)
                return 0;
@@ -444,27 +759,36 @@ int sql_check_multi(char *name, VALUE_PAIR *request, int maxsimul) {
                ipno = htonl(fra->lvalue);
 
        count = 0;
-       sprintf(querystr, "SELECT * FROM %s WHERE UserName = '%s' AND AcctStopTime = 0", sql->config.sql_acct_table, name);
-       sql_select_query(sql->AuthSock, querystr);
-       while ((row = sql_fetch_row(sql->AuthSock))) {
-               if (sql_check_ts(row) == 1) {
+       sprintf(querystr, "SELECT * FROM %s WHERE %s AND AcctStopTime = 0", sql->config->sql_acct_table, authstr);
+       sql_select_query(socket, querystr);
+       while ((row = sql_fetch_row(socket))) {
+               int check = sql_check_ts(row);
+               if (check == 1) {
                        count++;
 
-                       if (ipno && atoi(row[18]) == ipno)
+                       if (ipno && atoi(row[19]) == ipno)
                                mpp = 2;   
 
-               } else {
+               } else if (check == 2)
+                       log(L_ERR,"Problem with checkrad [%s] (from nas %s)", name, row[4]);
+               else {
                        /*
                         *      False record - zap it
                         */
 
-                       sprintf(querystr, "DELETE FROM %s WHERE RadAcctId = '%s'", sql->config.sql_acct_table, row[0]);
-                       sql_query(sql->AuthSock, querystr);
-                       sql_finish_query(sql->AuthSock);
-                       
+                       if (sql->config->deletestalesessions) {
+                               SQLSOCK *socket;
+
+                               log(L_ERR,"Deleteing stale session [%s] (from nas %s/%s)", row[2], row[4], row[5]);
+                               socket = sql_get_socket();
+                               sprintf(querystr, "DELETE FROM %s WHERE RadAcctId = '%s'", sql->config->sql_acct_table, row[0]);
+                               sql_query(socket, querystr);
+                               sql_finish_query(socket);
+                               sql_close_socket(socket);
+                       }
                }
        }
-       sql_finish_select_query(sql->AuthSock);
+       sql_finish_select_query(socket);
 
        return (count < maxsimul) ? 0 : mpp; 
 
index cca14b8..3f1b820 100644 (file)
 
 /*************************************************************************
  *
- *     Function: sql_connect
- *
- *     Purpose: Connect to the sql server
- *
- *************************************************************************/
-int sql_connect(void) {
-
-       MYSQL MyAuthConn;
-       MYSQL MyAcctConn;
-
-        /* Connect to the database server */
-        mysql_init(&MyAuthConn);
-        if (!(sql->AuthSock->conn = mysql_real_connect(&MyAuthConn, sql->config.sql_server, sql->config.sql_login, sql->config.sql_password, sql->config.sql_db, 0, NULL, 0))) {
-             log(L_ERR, "Init: Couldn't connect authentication socket to MySQL server on %s as %s", sql->config.sql_server, sql->config.sql_login);
-             sql->AuthSock->conn = NULL;
-        }
-        mysql_init(&MyAcctConn);
-        if (!(sql->AcctSock->conn = mysql_real_connect(&MyAcctConn, sql->config.sql_server, sql->config.sql_login, sql->config.sql_password, sql->config.sql_db, 0, NULL, 0))) {
-             log(L_ERR, "Init: Couldn't connect accounting socket to MySQL server on %s as %s", sql->config.sql_server, sql->config.sql_login);
-             sql->AcctSock->conn = NULL;
-        }
-           
-       return 0;
-}
-
-
-/*************************************************************************
- *
- *     Function: sql_checksocket
+ *     Function: sql_query
  *
- *     Purpose: Make sure our database connection is up
+ *     Purpose: Issue a query to the database
  *
  *************************************************************************/
-int sql_checksocket(const char *facility) {
-
-       if ((strncmp(facility, "Auth", 4) == 0)) {
-               if (sql->AuthSock->conn == NULL) {
-
-                       MYSQL MyAuthConn;
-                       if (sql->config.sql_keepopen)
-                               log(L_ERR, "%s: Keepopen set but had to reconnect to MySQL", facility);
-                       /* Connect to the database server */
-                       mysql_init(&MyAuthConn);
-                       if (!(sql->AuthSock->conn = mysql_real_connect(&MyAuthConn, sql->config.sql_server, sql->config.sql_login, sql->config.sql_password, sql->config.sql_db, 0, NULL, 0))) {
-                               log(L_ERR, "Auth: Couldn't connect authentication socket to MySQL server on %s as %s", sql->config.sql_server, sql->config.sql_login);
-                               sql->AuthSock->conn = NULL;
-                               return 0;
-                       }
-               }
-
-       } else {
-               if (sql->AcctSock->conn == NULL) {
-                       MYSQL MyAcctConn;
-                       if (sql->config.sql_keepopen)
-                               log(L_ERR, "%s: Keepopen set but had to reconnect to MySQL", facility);
-                       /* Connect to the database server */
-                       mysql_init(&MyAcctConn);
-                       if (!(sql->AcctSock->conn = mysql_real_connect(&MyAcctConn, sql->config.sql_server, sql->config.sql_login, sql->config.sql_password, sql->config.sql_db, 0, NULL, 0))) {
-                               log(L_ERR, "Acct: Couldn't connect accounting socket to MySQL server on %s as %s", sql->config.sql_server, sql->config.sql_login);
-                               sql->AcctSock->conn = NULL;
-                               return 0;
-                       }
-               }
+SQLSOCK *sql_create_socket(void) {
+       SQLSOCK *socket;
 
+       if ((socket = malloc(sizeof(SQLSOCK))) == NULL) {
+               log(L_CONS|L_ERR, "sql_create_socket: no memory");
+               exit(1);
        }
 
-       return 1;
-
+       mysql_init(&(socket->conn));
+       if (!(socket->sock = mysql_real_connect(&(socket->conn), sql->config->sql_server, sql->config->sql_login, sql->config->sql_password, sql->config->sql_db, 0, NULL, 0))) {
+               log(L_ERR, "Init: Couldn't connect socket to MySQL server %s@%s:%s", sql->config->sql_login, sql->config->sql_server, sql->config->sql_db);
+               socket->sock = NULL;
+               return NULL;
+       }
+       return socket;
 }
 
-
 /*************************************************************************
  *
  *     Function: sql_query
@@ -96,10 +46,13 @@ int sql_checksocket(const char *facility) {
  *************************************************************************/
 int sql_query(SQLSOCK *socket, char *querystr) {
 
- if (sql->config.sqltrace)
-       DEBUG(querystr);
- return mysql_query(socket->conn, querystr);
-
+       if (sql->config->sqltrace)
+               DEBUG(querystr);
+        if (socket->sock == NULL) {
+               log(L_ERR, "Socket not connected");
+               return 0;
+       }
+       return mysql_query(socket->sock, querystr);
 }
 
 
@@ -112,14 +65,17 @@ int sql_query(SQLSOCK *socket, char *querystr) {
  *************************************************************************/
 int sql_select_query(SQLSOCK *socket, char *querystr) {
 
- if (sql->config.sqltrace)
-       DEBUG(querystr);
- mysql_query(socket->conn, querystr);
- if (sql_store_result(socket) && sql_num_fields(socket)) 
-       return 0;
- else
-       return 1;
-
+       if (sql->config->sqltrace)
+               DEBUG(querystr);
+       if (socket->sock == NULL) {
+               log(L_ERR, "Socket not connected");
+               return 0;
+       }
+       mysql_query(socket->sock, querystr);
+       if (sql_store_result(socket) && sql_num_fields(socket)) 
+               return 1;
+       else
+               return 0;
 }
 
 
@@ -133,10 +89,13 @@ int sql_select_query(SQLSOCK *socket, char *querystr) {
  *************************************************************************/
 int sql_store_result(SQLSOCK *socket) {
 
-       if (!(socket->result = mysql_store_result(socket->conn))) {
+       if (socket->sock == NULL) {
+               log(L_ERR, "Socket not connected");
+               return 0;
+       }
+       if (!(socket->result = mysql_store_result(socket->sock))) {
                log(L_ERR,"MYSQL Error: Cannot get result");
-               log(L_ERR,"MYSQL error: %s",mysql_error(socket->conn));
-               sql_close(socket);
+               log(L_ERR,"MYSQL Error: %s",mysql_error(socket->sock));
                return 0;
        }
        return 1;
@@ -155,10 +114,13 @@ int sql_store_result(SQLSOCK *socket) {
 int sql_num_fields(SQLSOCK *socket) {
 
        int     num = 0;
-       if (!(num = mysql_num_fields(socket->conn))) {
+#if MYSQL_VERSION_ID >= 32224
+       if (!(num = mysql_field_count(socket->sock))) {
+#else
+       if (!(num = mysql_num_fields(socket->sock))) {
+#endif
                log(L_ERR,"MYSQL Error: Cannot get result");
-               log(L_ERR,"MYSQL error: %s",mysql_error(socket->conn));
-               sql_close(socket);
+               log(L_ERR,"MYSQL error: %s",mysql_error(socket->sock));
        }
        return num;
 }
@@ -174,8 +136,7 @@ int sql_num_fields(SQLSOCK *socket) {
  *************************************************************************/
 int sql_num_rows(SQLSOCK *socket) {
 
-    return mysql_num_rows(socket->result);
-
+       return mysql_num_rows(socket->result);
 }
 
 
@@ -189,8 +150,7 @@ int sql_num_rows(SQLSOCK *socket) {
  *************************************************************************/
 SQL_ROW sql_fetch_row(SQLSOCK *socket) {
 
-   return mysql_fetch_row(socket->result);
-
+       return mysql_fetch_row(socket->result);
 }
 
 
@@ -205,8 +165,7 @@ SQL_ROW sql_fetch_row(SQLSOCK *socket) {
  *************************************************************************/
 void sql_free_result(SQLSOCK *socket) {
 
-   mysql_free_result(socket->result);
-
+       mysql_free_result(socket->result);
 }
 
 
@@ -221,8 +180,7 @@ void sql_free_result(SQLSOCK *socket) {
  *************************************************************************/
 char *sql_error(SQLSOCK *socket) {
 
-  return (mysql_error(socket->conn));
-
+       return mysql_error(socket->sock);
 }
 
 
@@ -236,8 +194,8 @@ char *sql_error(SQLSOCK *socket) {
  *************************************************************************/
 void sql_close(SQLSOCK *socket) {
 
-   mysql_close(socket->conn);
-
+       mysql_close(socket->sock);
+       socket->sock = NULL;
 }
 
 
@@ -263,7 +221,7 @@ void sql_finish_query(SQLSOCK *socket) {
  *************************************************************************/
 void sql_finish_select_query(SQLSOCK *socket) {
 
-   sql_free_result(socket);
+       sql_free_result(socket);
 }
 
 
@@ -271,14 +229,12 @@ void sql_finish_select_query(SQLSOCK *socket) {
  *
  *     Function: sql_affected_rows
  *
- *     Purpose: End the select quh as freeing memory or result
+ *     Purpose: End the select query, such as freeing memory or result
  *
  *************************************************************************/
 int sql_affected_rows(SQLSOCK *socket) {
-   int rows;
 
-   rows = mysql_affected_rows(socket->conn);
-   return rows;
+       return mysql_affected_rows(socket->sock);
 }
 
 
@@ -286,17 +242,11 @@ int sql_affected_rows(SQLSOCK *socket) {
  *
  *      Function: sql_escape_string
  *
- *      Purpose: strdup() with the added feature of escaping binary
- *              data in the string to safely fit into an SQL query
+ *      Purpose: Esacpe "'" and any other wierd charactors
  *
  *************************************************************************/
-char *sql_escape_string(const char *from) {
-       char *to;
-
-       if(from==NULL) 
-               return NULL;
-       if((to=malloc((strlen(from)*2) + 1)) == NULL)   
-               return NULL;
-       mysql_escape_string(to,from,strlen(from));
-       return to;
+int sql_escape_string(char *to, char *from, int length) {
+
+       mysql_escape_string(to, from, length);
+       return 1;
 }
index 8a1bc9e..580c53f 100644 (file)
@@ -5,17 +5,47 @@
  */
 
 #include       <mysql/mysql.h>
+#include       "conf.h"
 
 typedef MYSQL_ROW      SQL_ROW;
-typedef MYSQL_RES      SQL_RES;
 
-typedef struct {
-       MYSQL           *conn;
-       MYSQL_RES       *result;
+typedef struct sql_config {
+        char sql_server[40];
+        char sql_login[20];
+        char sql_password[20];
+        char sql_db[20];
+        char sql_acct_table[MAX_TABLE_LEN];
+        char sql_authcheck_table[MAX_TABLE_LEN];
+        char sql_authreply_table[MAX_TABLE_LEN];
+        char sql_groupcheck_table[MAX_TABLE_LEN];
+        char sql_groupreply_table[MAX_TABLE_LEN];
+        char sql_usergroup_table[MAX_TABLE_LEN];
+        char sql_realm_table[MAX_TABLE_LEN];
+        char sql_realmgroup_table[MAX_TABLE_LEN];
+        char sql_nas_table[MAX_TABLE_LEN];
+        char sql_dict_table[MAX_TABLE_LEN];
+        int  sensitiveusername;
+        int  sqltrace;
+       int  deletestalesessions;
+       int  max_sql_socks;
+} SQL_CONFIG;
+typedef struct sql_socket {
+       MYSQL           *sock;
+       MYSQL           conn;
+        MYSQL_RES      *result;
+        int             id;
+        int             in_use;
+       struct timeval  tv;
 } SQLSOCK;
+typedef struct sql {
+        SQL_CONFIG *config;
+        SQLSOCK *socks[MAX_SQL_SOCKS];
+} SQL;
 
 
-int sql_connect(void);
+SQLSOCK *sql_create_socket(void);
 int sql_checksocket(const char *facility);
 int sql_query(SQLSOCK *socket, char *querystr);
 int sql_select_query(SQLSOCK *socket, char *querystr);
@@ -29,4 +59,4 @@ void sql_close(SQLSOCK *socket);
 void sql_finish_query(SQLSOCK *socket);
 void sql_finish_select_query(SQLSOCK *socket);
 int sql_affected_rows(SQLSOCK *socket);
-char *sql_escape_string(const char *from);
+int sql_escape_string(char *to, char *from, int length);
index 55481ee..3f1b820 100644 (file)
 
 /*************************************************************************
  *
- *     Function: sql_connect
- *
- *     Purpose: Connect to the sql server
- *
- *************************************************************************/
-int sql_connect(void) {
-
-       MYSQL MyAuthConn;
-       MYSQL MyAcctConn;
-
-        /* Connect to the database server */
-        mysql_init(&MyAuthConn);
-        if (!(sql->AuthSock->conn = mysql_real_connect(&MyAuthConn, sql->config.sql_server, sql->config.sql_login, sql->config.sql_password, sql->config.sql_db, 0, NULL, 0))) {
-             log(L_ERR, "Init: Couldn't connect authentication socket to MySQL server on %s as %s", sql->config.sql_server, sql->config.sql_login);
-             sql->AuthSock->conn = NULL;
-        }
-        mysql_init(&MyAcctConn);
-        if (!(sql->AcctSock->conn = mysql_real_connect(&MyAcctConn, sql->config.sql_server, sql->config.sql_login, sql->config.sql_password, sql->config.sql_db, 0, NULL, 0))) {
-             log(L_ERR, "Init: Couldn't connect accounting socket to MySQL server on %s as %s", sql->config.sql_server, sql->config.sql_login);
-             sql->AcctSock->conn = NULL;
-        }
-           
-       return 0;
-}
-
-
-/*************************************************************************
- *
- *     Function: sql_checksocket
+ *     Function: sql_query
  *
- *     Purpose: Make sure our database connection is up
+ *     Purpose: Issue a query to the database
  *
  *************************************************************************/
-int sql_checksocket(const char *facility) {
-
-       if ((strncmp(facility, "Auth", 4) == 0)) {
-               if (sql->AuthSock->conn == NULL) {
-
-                       MYSQL MyAuthConn;
-                       if (sql->config.sql_keepopen)
-                               log(L_ERR, "%s: Keepopen set but had to reconnect to MySQL", facility);
-                       /* Connect to the database server */
-                       mysql_init(&MyAuthConn);
-                       if (!(sql->AuthSock->conn = mysql_real_connect(&MyAuthConn, sql->config.sql_server, sql->config.sql_login, sql->config.sql_password, sql->config.sql_db, 0, NULL, 0))) {
-                               log(L_ERR, "Auth: Couldn't connect authentication socket to MySQL server on %s as %s", sql->config.sql_server, sql->config.sql_login);
-                               sql->AuthSock->conn = NULL;
-                               return 0;
-                       }
-               }
-
-       } else {
-               if (sql->AcctSock->conn == NULL) {
-                       MYSQL MyAcctConn;
-                       if (sql->config.sql_keepopen)
-                               log(L_ERR, "%s: Keepopen set but had to reconnect to MySQL", facility);
-                       /* Connect to the database server */
-                       mysql_init(&MyAcctConn);
-                       if (!(sql->AcctSock->conn = mysql_real_connect(&MyAcctConn, sql->config.sql_server, sql->config.sql_login, sql->config.sql_password, sql->config.sql_db, 0, NULL, 0))) {
-                               log(L_ERR, "Acct: Couldn't connect accounting socket to MySQL server on %s as %s", sql->config.sql_server, sql->config.sql_login);
-                               sql->AcctSock->conn = NULL;
-                               return 0;
-                       }
-               }
+SQLSOCK *sql_create_socket(void) {
+       SQLSOCK *socket;
 
+       if ((socket = malloc(sizeof(SQLSOCK))) == NULL) {
+               log(L_CONS|L_ERR, "sql_create_socket: no memory");
+               exit(1);
        }
 
-       return 1;
-
+       mysql_init(&(socket->conn));
+       if (!(socket->sock = mysql_real_connect(&(socket->conn), sql->config->sql_server, sql->config->sql_login, sql->config->sql_password, sql->config->sql_db, 0, NULL, 0))) {
+               log(L_ERR, "Init: Couldn't connect socket to MySQL server %s@%s:%s", sql->config->sql_login, sql->config->sql_server, sql->config->sql_db);
+               socket->sock = NULL;
+               return NULL;
+       }
+       return socket;
 }
 
-
 /*************************************************************************
  *
  *     Function: sql_query
@@ -96,10 +46,13 @@ int sql_checksocket(const char *facility) {
  *************************************************************************/
 int sql_query(SQLSOCK *socket, char *querystr) {
 
- if (sql->config.sqltrace)
-       DEBUG(querystr);
- return mysql_query(socket->conn, querystr);
-
+       if (sql->config->sqltrace)
+               DEBUG(querystr);
+        if (socket->sock == NULL) {
+               log(L_ERR, "Socket not connected");
+               return 0;
+       }
+       return mysql_query(socket->sock, querystr);
 }
 
 
@@ -112,14 +65,17 @@ int sql_query(SQLSOCK *socket, char *querystr) {
  *************************************************************************/
 int sql_select_query(SQLSOCK *socket, char *querystr) {
 
- if (sql->config.sqltrace)
-       DEBUG(querystr);
- mysql_query(socket->conn, querystr);
- if (sql_store_result(socket) && sql_num_fields(socket)) 
-       return 0;
- else
-       return 1;
-
+       if (sql->config->sqltrace)
+               DEBUG(querystr);
+       if (socket->sock == NULL) {
+               log(L_ERR, "Socket not connected");
+               return 0;
+       }
+       mysql_query(socket->sock, querystr);
+       if (sql_store_result(socket) && sql_num_fields(socket)) 
+               return 1;
+       else
+               return 0;
 }
 
 
@@ -133,10 +89,13 @@ int sql_select_query(SQLSOCK *socket, char *querystr) {
  *************************************************************************/
 int sql_store_result(SQLSOCK *socket) {
 
-       if (!(socket->result = mysql_store_result(socket->conn))) {
+       if (socket->sock == NULL) {
+               log(L_ERR, "Socket not connected");
+               return 0;
+       }
+       if (!(socket->result = mysql_store_result(socket->sock))) {
                log(L_ERR,"MYSQL Error: Cannot get result");
-               log(L_ERR,"MYSQL error: %s",mysql_error(socket->conn));
-               sql_close(socket);
+               log(L_ERR,"MYSQL Error: %s",mysql_error(socket->sock));
                return 0;
        }
        return 1;
@@ -155,10 +114,13 @@ int sql_store_result(SQLSOCK *socket) {
 int sql_num_fields(SQLSOCK *socket) {
 
        int     num = 0;
-       if (!(num = mysql_num_fields(socket->conn))) {
+#if MYSQL_VERSION_ID >= 32224
+       if (!(num = mysql_field_count(socket->sock))) {
+#else
+       if (!(num = mysql_num_fields(socket->sock))) {
+#endif
                log(L_ERR,"MYSQL Error: Cannot get result");
-               log(L_ERR,"MYSQL error: %s",mysql_error(socket->conn));
-               sql_close(socket);
+               log(L_ERR,"MYSQL error: %s",mysql_error(socket->sock));
        }
        return num;
 }
@@ -174,8 +136,7 @@ int sql_num_fields(SQLSOCK *socket) {
  *************************************************************************/
 int sql_num_rows(SQLSOCK *socket) {
 
-    return mysql_num_rows(socket->result);
-
+       return mysql_num_rows(socket->result);
 }
 
 
@@ -189,8 +150,7 @@ int sql_num_rows(SQLSOCK *socket) {
  *************************************************************************/
 SQL_ROW sql_fetch_row(SQLSOCK *socket) {
 
-   return mysql_fetch_row(socket->result);
-
+       return mysql_fetch_row(socket->result);
 }
 
 
@@ -205,8 +165,7 @@ SQL_ROW sql_fetch_row(SQLSOCK *socket) {
  *************************************************************************/
 void sql_free_result(SQLSOCK *socket) {
 
-   mysql_free_result(socket->result);
-
+       mysql_free_result(socket->result);
 }
 
 
@@ -221,8 +180,7 @@ void sql_free_result(SQLSOCK *socket) {
  *************************************************************************/
 char *sql_error(SQLSOCK *socket) {
 
-  return (mysql_error(socket->conn));
-
+       return mysql_error(socket->sock);
 }
 
 
@@ -236,8 +194,8 @@ char *sql_error(SQLSOCK *socket) {
  *************************************************************************/
 void sql_close(SQLSOCK *socket) {
 
-   mysql_close(socket->conn);
-
+       mysql_close(socket->sock);
+       socket->sock = NULL;
 }
 
 
@@ -263,7 +221,7 @@ void sql_finish_query(SQLSOCK *socket) {
  *************************************************************************/
 void sql_finish_select_query(SQLSOCK *socket) {
 
-   sql_free_result(socket);
+       sql_free_result(socket);
 }
 
 
@@ -275,10 +233,8 @@ void sql_finish_select_query(SQLSOCK *socket) {
  *
  *************************************************************************/
 int sql_affected_rows(SQLSOCK *socket) {
-   int rows;
 
-   rows = mysql_affected_rows(socket->conn);
-   return rows;
+       return mysql_affected_rows(socket->sock);
 }
 
 
@@ -286,17 +242,11 @@ int sql_affected_rows(SQLSOCK *socket) {
  *
  *      Function: sql_escape_string
  *
- *      Purpose: strdup() with the added feature of escaping binary
- *              data in the string to safely fit into an SQL query
+ *      Purpose: Esacpe "'" and any other wierd charactors
  *
  *************************************************************************/
-char *sql_escape_string(const char *from) {
-       char *to;
-
-       if(from==NULL) 
-               return NULL;
-       if((to=malloc((strlen(from)*2) + 1)) == NULL)   
-               return NULL;
-       mysql_escape_string(to,from,strlen(from));
-       return to;
+int sql_escape_string(char *to, char *from, int length) {
+
+       mysql_escape_string(to, from, length);
+       return 1;
 }
index 8a1bc9e..580c53f 100644 (file)
@@ -5,17 +5,47 @@
  */
 
 #include       <mysql/mysql.h>
+#include       "conf.h"
 
 typedef MYSQL_ROW      SQL_ROW;
-typedef MYSQL_RES      SQL_RES;
 
-typedef struct {
-       MYSQL           *conn;
-       MYSQL_RES       *result;
+typedef struct sql_config {
+        char sql_server[40];
+        char sql_login[20];
+        char sql_password[20];
+        char sql_db[20];
+        char sql_acct_table[MAX_TABLE_LEN];
+        char sql_authcheck_table[MAX_TABLE_LEN];
+        char sql_authreply_table[MAX_TABLE_LEN];
+        char sql_groupcheck_table[MAX_TABLE_LEN];
+        char sql_groupreply_table[MAX_TABLE_LEN];
+        char sql_usergroup_table[MAX_TABLE_LEN];
+        char sql_realm_table[MAX_TABLE_LEN];
+        char sql_realmgroup_table[MAX_TABLE_LEN];
+        char sql_nas_table[MAX_TABLE_LEN];
+        char sql_dict_table[MAX_TABLE_LEN];
+        int  sensitiveusername;
+        int  sqltrace;
+       int  deletestalesessions;
+       int  max_sql_socks;
+} SQL_CONFIG;
+typedef struct sql_socket {
+       MYSQL           *sock;
+       MYSQL           conn;
+        MYSQL_RES      *result;
+        int             id;
+        int             in_use;
+       struct timeval  tv;
 } SQLSOCK;
+typedef struct sql {
+        SQL_CONFIG *config;
+        SQLSOCK *socks[MAX_SQL_SOCKS];
+} SQL;
 
 
-int sql_connect(void);
+SQLSOCK *sql_create_socket(void);
 int sql_checksocket(const char *facility);
 int sql_query(SQLSOCK *socket, char *querystr);
 int sql_select_query(SQLSOCK *socket, char *querystr);
@@ -29,4 +59,4 @@ void sql_close(SQLSOCK *socket);
 void sql_finish_query(SQLSOCK *socket);
 void sql_finish_select_query(SQLSOCK *socket);
 int sql_affected_rows(SQLSOCK *socket);
-char *sql_escape_string(const char *from);
+int sql_escape_string(char *to, char *from, int length);