From: kkalev Date: Tue, 6 Apr 2004 19:37:47 +0000 (+0000) Subject: * Add a check_user_passwd() and a get_user_dn() functions in lib/ldap/functions.php3 X-Git-Url: https://git.entuzijast.net/?a=commitdiff_plain;h=29b914d722490895445f386682604feeffc62a75;p=freeradius-dialup-admin.git * Add a check_user_passwd() and a get_user_dn() functions in lib/ldap/functions.php3 * Add general_restrict_badusers_access directive. If set to yes we only allow each administrator access to their own entries in the badusers table * Add a username.mappings table. We are able to map each administrator username to additional queries on the accounting and user settings tables. * Add an sql_accounting_extra_query directive. If set this query is included in all queries to the accounting tables. Combined with admin username mappings we are able to easily restrict access on specific accounting data to each administrator. * Escape bad characters in the $login variable * Add a da_sql_escape_string function. We use that for every element we pass to sql queries in order to protect ourselves from sql injection. * Use the ldap_userdn directive where applicable in the functions.php3 file * Add an sql_xlat function TODO: Check out the sql queries in lin/sql for sql injection. --- diff --git a/Changelog b/Changelog index 1a7c3be..08a2d24 100644 --- a/Changelog +++ b/Changelog @@ -3,6 +3,22 @@ Ver 1.70: * Add ldap_userdn as a configuration directive. If set we use that for user DN's (variables supported) instead of performing and ldap search for each user. That can be somewhat faster. +* Add a check_user_passwd() and a get_user_dn() functions in lib/ldap/functions.php3 +* Add general_restrict_badusers_access directive. If set to yes we only allow each administrator + access to their own entries in the badusers table +* Add a username.mappings table. We are able to map each administrator username to additional queries + on te accounting and user settings tables. +* Add an sql_extra_query directive. If set this query is included in all queries to the accounting tables. + Combined with admin username mappings we are able to easily restrict access on specific accounting data + to each administrator. +* Escape bad characters in the $login variable +* Add a da_sql_escape_string function. We use that for every element we pass to sql queries in order to + protect ourselves from sql injection. +* Use the ldap_userdn directive where applicable in the functions.php3 file +* Add an sql_xlat function + +TODO: Check out the sql queries in lin/sql for sql injection. + Ver 1.68: * Huge PostgreSQL compatibility patch by Guy Fraser * Also support the Crypt-Password attribute in lib/sql/password_check.php3. Patch by Guy Fraser diff --git a/conf/admin.conf b/conf/admin.conf index 076274d..c443b21 100644 --- a/conf/admin.conf +++ b/conf/admin.conf @@ -59,7 +59,7 @@ general_realm_format: suffix # # -# Determines if the administrator will be able to change the user password through +# Determines if the administrator will be able to see and change the user password through # the user edit page general_show_user_password: yes @@ -137,6 +137,11 @@ general_accounting_info_order: desc # this to work :-) # general_stats_use_totacct: no +# +# If set to yes then we only allow each administrator to examine it's own entries +# in the badusers table +# +general_restrict_badusers_access: no INCLUDE: %{general_base_dir}/conf/naslist.conf @@ -189,6 +194,8 @@ ldap_regular_profile_attr: dialupregularprofile # Variables supported: # %u: username # %U: username provided though http authentication +# %mu: mappings for userdb +# %ma: mappings for accounting # # One use of this would be to restrict access to only the user's belonging to # a specific administrator like this: @@ -246,6 +253,10 @@ general_snmpget_command: /usr/local/bin/snmpget # and sql_password. That way multiple admins with different rights # on the sql database can connect through one dialup_admin interface. #sql_use_http_credentials: yes +# +# If set the query will be added to all of the queries on the accounting +# table +#sql_accounting_extra_query: %ma # diff --git a/conf/config.php3 b/conf/config.php3 index 42fc005..11823d9 100644 --- a/conf/config.php3 +++ b/conf/config.php3 @@ -54,6 +54,10 @@ if ($use_session == 0 && $config[general_use_session] == 'yes'){ // Start session @session_start(); } +//Make sure we are only passed allowed strings in username +if ($login != '') + $login = preg_replace("/[^\w\s\.\/\@\:]\-i\=/",'',$login); + if ($login != '' && $config[general_strip_realms] == 'yes'){ $realm_del = ($config[general_realm_delimiter] != '') ? $config[general_realm_delimiter] : '@'; $realm_for = ($config[general_realm_format] != '') ? $config[general_realm_format] : 'suffix'; @@ -61,4 +65,17 @@ if ($login != '' && $config[general_strip_realms] == 'yes'){ if (count($new) == 2) $login = ($realm_for == 'suffix') ? $new[0] : $new[1]; } +if (!isset($mappings) && $config[general_username_mappings_file] != ''){ + $ARR = file($config[general_username_mappings_file]); + foreach($ARR as $val){ + $val=chop($val); + if (ereg('^[[:space:]]*#',$val) || ereg('^[[:space:]]*$',$val)) + continue; + list($key,$realm,$v)=split(":[[:space:]]*",$val,2); + if ($realm == 'accounting' || $realm == 'userdb') + $mappings["$key"][$realm] = $v; + } + if ($config[general_use_session] == 'yes') + session_register('mappings'); +} ?> diff --git a/doc/TODO b/doc/TODO index 224ccfb..315d454 100644 --- a/doc/TODO +++ b/doc/TODO @@ -16,3 +16,4 @@ are welcome. * Parse the radius dictionary files so that we can show a pull down menu of possible values for various attributes. +* Check the sql user code for sql injections diff --git a/htdocs/accounting.php3 b/htdocs/accounting.php3 index 88646d5..df5f4a2 100644 --- a/htdocs/accounting.php3 +++ b/htdocs/accounting.php3 @@ -2,6 +2,7 @@ require('../conf/config.php3'); require('../lib/functions.php3'); +require('../lib/sql/functions.php3'); require('../lib/acctshow.php3'); if (is_file("../lib/sql/drivers/$config[sql_type]/functions.php3")) @@ -203,6 +204,17 @@ EOM; if ($queryflag == 1){ $i = 1; while (${"item_of_w$i"}){ + $op_found = 0; + foreach ($operators as $operator){ + if (${"operator_of_w$i"} == $operator){ + $op_found = 1; + break; + } + } + if (!$op_found) + die("Operator passed is not valid. Exiting abnormaly."); + ${"item_of_w$i"} = preg_replace('/\s/','',${"item_of_w$i}); + ${"value_of_w$i"} = da_sql_escape_string(${"value_of_w$i"}); $where .= ($i == 1) ? ' WHERE ' . ${"item_of_w$i"} . ' ' . ${"operator_of_w$i"} . " '" . ${"value_of_w$i"} . "'" : ' AND ' . ${"item_of_w$i"} . ' ' . ${"operator_of_w$i"} . " '" . ${"value_of_w$i"} . "'" ; $i++; @@ -213,7 +225,10 @@ $order = ($order_by != '') ? "$order_by" : 'username'; foreach ($accounting_show_attrs as $val) $query_view .= $val . ','; $query_view = ereg_replace(',$','',$query_view); -$query="SELECT $query_view FROM $config[sql_accounting_table] $where ORDER BY $order LIMIT $maxresults;"; +$sql_extra_query = ''; +if ($config[sql_accounting_extra_query] != '') + $sql_extra_query = sql_xlat($config[sql_accounting_extra_query],$login,$config); +$query="SELECT $query_view FROM $config[sql_accounting_table] $where $sql_extra_query ORDER BY $order LIMIT $maxresults;"; echo << diff --git a/htdocs/badusers.php3 b/htdocs/badusers.php3 index 7657d59..0aeac02 100644 --- a/htdocs/badusers.php3 +++ b/htdocs/badusers.php3 @@ -25,8 +25,14 @@ EOM; $now = time(); $now_str = ($now_str != '') ? "$now_str" : date($config[sql_date_format],$now + 86400); $prev_str = ($prev_str != '') ? "$prev_str" : "0001-01-01 00:00:00"; + +$now_str = da_sql_escape_string($now_str); +$prev_str = da_sql_escape_string($prev_str); + $num = 0; $pagesize = ($pagesize) ? $pagesize : 10; +if (!is_int($pagesize)) + $pagesize = 10; $limit = ($pagesize == 'all') ? '' : "LIMIT $pagesize"; $selected[$pagesize] = 'selected'; $login = ($login != '') ? $login : 'anyone'; @@ -132,11 +138,15 @@ EOM; = '$prev_str' ORDER BY Date $order $limit;"); if ($search){ while( $row = @da_sql_fetch_array($search,$config) ){ diff --git a/htdocs/clear_opensessions.php3 b/htdocs/clear_opensessions.php3 index b450418..10349dc 100644 --- a/htdocs/clear_opensessions.php3 +++ b/htdocs/clear_opensessions.php3 @@ -39,6 +39,10 @@ include("../html/user_toolbar.html.php3"); $open_sessions = 0; +$sql_extra_query = ''; +if ($config[sql_accounting_extra_query] != '') + $sql_extra_query = sql_xlat($config[sql_accounting_extra_query],$login,$config); + print << @@ -63,7 +67,7 @@ if ($clear_sessions == 1){ if ($link){ $res = @da_sql_query($link,$config, "DELETE FROM $config[sql_accounting_table] - WHERE username='$login' AND acctstoptime = 0;"); + WHERE username='$login' AND acctstoptime = 0 $sql_extra_query;"); if ($res) echo "Deleted open sessions from accounting table
\n"; else @@ -86,7 +90,7 @@ else{ if ($link){ $search = @da_sql_query($link,$config, "SELECT COUNT(*) AS counter FROM $config[sql_accounting_table] - WHERE username = '$login' AND acctstoptime IS NULL;"); + WHERE username = '$login' AND acctstoptime IS NULL $sql_extra_query;"); if ($search){ if ($row = @da_sql_fetch_array($search,$config)) $open_sessions = $row[counter]; diff --git a/htdocs/failed_logins.php3 b/htdocs/failed_logins.php3 index 2cf1ff6..2527e52 100644 --- a/htdocs/failed_logins.php3 +++ b/htdocs/failed_logins.php3 @@ -28,17 +28,27 @@ if ($last == 0) $start = $now - ($last*60); $now_str = date($config[sql_full_date_format],$now); $prev_str = date($config[sql_full_date_format],$start); + +$now_str = da_sql_escape_string($now_str); +$prev_str = da_sql_escape_string($prev_str); + $pagesize = ($pagesize) ? $pagesize : 10; +if (!is_int($pagesize)) + $pagesize = 10; $limit = ($pagesize == 'all') ? '' : "LIMIT $pagesize"; $selected[$pagesize] = 'selected'; $order = ($order != '') ? $order : $config[general_accounting_info_order]; if ($order != 'desc' && $order != 'asc') $order = 'desc'; $selected[$order] = 'selected'; -if ($callerid != '') +if ($callerid != ''){ + $callerid = da_sql_escape_string($callerid); $callerid_str = "AND callingstationid = '$callerid'"; -if ($server != '' && $server != 'all') +} +if ($server != '' && $server != 'all'){ + $server = da_sql_escape_string($server); $server_str = "AND nasipaddress = '$server'"; +} ?> @@ -85,6 +95,9 @@ if ($acct_attrs['fl'][2] != '') echo "" . $acct_attrs['fl'][2] . "\n"; if ($acct_attrs['fl'][7] != '') echo "" . $acct_attrs['fl'][7] . "\n"; if ($acct_attrs['fl'][8] != '') echo "" . $acct_attrs['fl'][8] . "\n"; if ($acct_attrs['fl'][9] != '') echo "" . $acct_attrs['fl'][9] . "\n"; +$sql_extra_query = ''; +if ($config[sql_accounting_extra_query] != '') + $sql_extra_query = sql_xlat($config[sql_accounting_extra_query],$login,$config); ?> @@ -97,7 +110,7 @@ if ($link){ WHERE acctstoptime <= '$now_str' AND acctstoptime >= '$prev_str' AND (acctterminatecause LIKE 'Login-Incorrect%' OR acctterminatecause LIKE 'Invalid-User%' OR - acctterminatecause LIKE 'Multiple-Logins%') $callerid_str $server_str + acctterminatecause LIKE 'Multiple-Logins%') $callerid_str $server_str $sql_extra_query ORDER BY acctstoptime $order $limit;"); if ($search){ while( $row = @da_sql_fetch_array($search,$config) ){ diff --git a/htdocs/stats.php3 b/htdocs/stats.php3 index f4f8994..e03da0e 100644 --- a/htdocs/stats.php3 +++ b/htdocs/stats.php3 @@ -90,8 +90,13 @@ while(1){ $i++; } ksort($servers); -if ($server != 'all' && $server != '') +if ($server != 'all' && $server != ''){ + $server = da_sql_escape_string($server); $s = "AND nasipaddress = '$server'"; +} +$sql_extra_query = ''; +if ($config[sql_accounting_extra_query] != '') + $sql_extra_query = sql_xlat($config[sql_accounting_extra_query],$login,$config); $link = @da_sql_pconnect($config); if ($link){ @@ -100,12 +105,12 @@ if ($link){ if ($config[general_stats_use_totacct] == 'yes') $search = @da_sql_query($link,$config, "SELECT $res[1],$res[2],$res[3] FROM $config[sql_total_accounting_table] - $sql_val[user] AND acctdate = '$day' $s;"); + $sql_val[user] AND acctdate = '$day' $s $sql_extra_query;"); else $search = @da_sql_query($link,$config, "SELECT $res[1],$res[2],$res[3] FROM $config[sql_accounting_table] $sql_val[user] AND acctstoptime >= '$day 00:00:00' - AND acctstoptime <= '$day 23:59:59' $s;"); + AND acctstoptime <= '$day 23:59:59' $s $sql_extra_query;"); if ($search){ $row = @da_sql_fetch_array($search,$config); $data[$day][1] = $row[res_1]; diff --git a/htdocs/user_accounting.php3 b/htdocs/user_accounting.php3 index 5188565..74399f5 100644 --- a/htdocs/user_accounting.php3 +++ b/htdocs/user_accounting.php3 @@ -4,6 +4,7 @@ require('../conf/config.php3'); " . $acct_attrs['ua']["$i"] . "\n"; } +$sql_extra_query = ''; +if ($config[sql_accounting_extra_query] != '') + $sql_extra_query = sql_xlat($config[sql_accounting_extra_query],$login,$config); ?> @@ -92,7 +100,7 @@ if ($link){ $search = @da_sql_query($link,$config, "SELECT * FROM $config[sql_accounting_table] WHERE username = '$login' AND acctstarttime <= '$now_str' - AND acctstarttime >= '$prev_str' ORDER BY acctstarttime $order $limit;"); + AND acctstarttime >= '$prev_str' $sql_extra_query ORDER BY acctstarttime $order $limit;"); if ($search){ while( $row = @da_sql_fetch_array($search,$config) ){ $tr_color='white'; diff --git a/htdocs/user_finger.php3 b/htdocs/user_finger.php3 index a9aae2d..c28476a 100644 --- a/htdocs/user_finger.php3 +++ b/htdocs/user_finger.php3 @@ -39,6 +39,10 @@ EOM; $date = strftime('%A, %e %B %Y, %T %Z'); +$sql_extra_query = ''; +if ($config[sql_accounting_extra_query] != '') + $sql_extra_query = sql_xlat($config[sql_accounting_extra_query],$login,$config); + $link = @da_sql_pconnect($config); $link2 = connect2db($config); $tot_in = $tot_rem = 0; @@ -92,7 +96,7 @@ if ($link){ $search = @da_sql_query($link,$config, "SELECT DISTINCT username,acctstarttime,framedipaddress,callingstationid FROM $config[sql_accounting_table] WHERE - acctstoptime IS NULL AND nasipaddress = '$name_data' $extra + acctstoptime IS NULL AND nasipaddress = '$name_data' $extra $sql_extra_query GROUP BY username ORDER BY acctstarttime;"); if ($search){ $now = time(); diff --git a/htdocs/user_stats.php3 b/htdocs/user_stats.php3 index 06112c3..2d6c4bb 100644 --- a/htdocs/user_stats.php3 +++ b/htdocs/user_stats.php3 @@ -28,7 +28,11 @@ if ($start == '' && $stop == ''){ $now -= 604800; $start = date($config[sql_date_format],$now); } +$start = da_sql_escape_string($start); +$stop = da_sql_escape_string($stop); $pagesize = ($pagesize) ? $pagesize : 10; +if (!is_int($pagesize)) + $pagezise = 10; $limit = ($pagesize == 'all') ? '' : "LIMIT $pagesize"; $selected[$pagesize] = 'selected'; $order = ($order) ? $order : $config[general_accounting_info_order]; @@ -38,13 +42,19 @@ if ($sortby != '') $order_attr = ($sortby == 'num') ? 'connnum' : 'conntotduration'; else $order_attr = 'connnum'; -if ($server != '' && $server != 'all') +if ($server != '' && $server != 'all'){ + $server = da_sql_escape_string($server); $server_str = "AND nasipaddress = '$server'"; +} $login_str = ($login) ? "AND username = '$login' " : ''; $selected[$order] = 'selected'; $selected[$sortby] = 'selected'; +$sql_extra_query = ''; +if ($config[sql_accounting_extra_query] != '') + $sql_extra_query = sql_xlat($config[sql_accounting_extra_query],$login,$config); + ?> @@ -91,7 +101,7 @@ $link = @da_sql_pconnect($config); if ($link){ $search = @da_sql_query($link,$config, "SELECT * FROM $config[sql_total_accounting_table] - WHERE acctdate >= '$start' AND acctdate <= '$stop' $server_str $login_str + WHERE acctdate >= '$start' AND acctdate <= '$stop' $server_str $login_str $sql_extra_query ORDER BY $order_attr $order $limit;"); if ($search){ diff --git a/htdocs/user_test.php3 b/htdocs/user_test.php3 index bcbdc3e..4e476ee 100644 --- a/htdocs/user_test.php3 +++ b/htdocs/user_test.php3 @@ -57,9 +57,9 @@ EOM; DEBUG(LDAP): Search Query: BASE='$config[ldap_base]',FILTER='$filter'
\n"; + else + print "DEBUG(LDAP): Search Query: BASE='$filter',FILTER='(objectclass=radiusprofile)'
\n"; + } + if ($config[ldap_userdn] == '') + $sr=@ldap_search($ds,"$config[ldap_base]", $filter,$attrs); + else + $sr=@ldap_read($ds,$filter, '(objectclass=radiusprofile)',$attrs); $info = @ldap_get_entries($ds, $sr); $cn = $info[0]["cn"][0]; if ($cn != '' && $decode_normal == 1) @@ -62,19 +92,54 @@ function get_user_info($ds,$user,$config,$decode_normal,$k) } } -function closedb($ds,$config) +function get_user_dn($ds,$user,$config) { - if ($ds) - @ldap_close($ds); + if ($ds){ + $attrs = array('dn'); + if ($config[ldap_userdn] == ''){ + if ($config[ldap_filter] != '') + $filter = ldap_xlat($config[ldap_filter],$login,$config); + else + $filter = 'uid=' . $login; + } + else + $filter = ldap_xlat($config[ldap_userdn],$login,$config); + if ($config[ldap_debug] == 'true'){ + if ($config[ldap_userdn] == '') + print "DEBUG(LDAP): Search Query: BASE='$config[ldap_base]',FILTER='$filter'
\n"; + else + print "DEBUG(LDAP): Search Query: BASE='$filter',FILTER='(objectclass=radiusprofile)'
\n"; + } + if ($config[ldap_userdn] == '') + $sr=@ldap_search($ds,"$config[ldap_base]", $filter,$attrs); + else + $sr=@ldap_read($ds,$filter, '(objectclass=radiusprofile)',$attrs); + $entry = ldap_first_entry($ds, $sr); + if ($entry) + $dn = ldap_get_dn($ds,$entry); + return $dn; + } } -function ldap_xlat($filter,$login,$config) + +function check_user_passwd($dn,$passwd,$config) { - $string = $filter; - if ($filter != ''){ - $string = preg_replace('/%u/',$login,$string); - $string = preg_replace('/%U/',$HTTP_SERVER_VARS["PHP_AUTH_USER"],$string); + $ds=@ldap_connect("$config[ldap_server]"); + if ($ds && $dn != '' && $passwd != ''){ + $r = @ldap_bind($ds,$dn,$passwd); + if ($r) + return TRUE; + else + return FALSE; } + else + return FALSE; - return $string; + return FALSE; +} + +function closedb($ds,$config) +{ + if ($ds) + @ldap_close($ds); } ?> diff --git a/lib/sql/drivers/mysql/functions.php3 b/lib/sql/drivers/mysql/functions.php3 index 3c393f9..8f313c6 100644 --- a/lib/sql/drivers/mysql/functions.php3 +++ b/lib/sql/drivers/mysql/functions.php3 @@ -53,9 +53,13 @@ function da_sql_close($link,$config) return @mysql_close($link); } +function da_sql_escape_string($string) +{ + return @mysql_escape_string($string); +} + function da_sql_query($link,$config,$query) { - @mysql_escape_string($query); if ($config[sql_debug] == 'true') print "DEBUG(SQL,MYSQL DRIVER): Query: $query
\n"; return @mysql_db_query($config[sql_database],$query,$link); diff --git a/lib/sql/drivers/pg/functions.php3 b/lib/sql/drivers/pg/functions.php3 index 243eb32..ec20319 100644 --- a/lib/sql/drivers/pg/functions.php3 +++ b/lib/sql/drivers/pg/functions.php3 @@ -52,6 +52,11 @@ function da_sql_close($link,$config) @pg_close($link); } +function da_sql_escape_string($string) +{ + return addslashes($string); +} + function da_sql_query($link,$config,$query) { if ($config[sql_debug] == 'true') diff --git a/lib/sql/functions.php3 b/lib/sql/functions.php3 index aea26cd..2691528 100644 --- a/lib/sql/functions.php3 +++ b/lib/sql/functions.php3 @@ -30,4 +30,16 @@ function closedb($link,$config) { return 1; } +function sql_xlat($filter,$login,$config) +{ + $string = $filter; + $http_user = $HTTP_SERVER_VARS["PHP_AUTH_USER"]; + if ($filter != ''){ + $string = preg_replace('/%u/',$login,$string); + $string = preg_replace('/%U/',$http_user,$string); + $string = preg_replace('/%m/',$mappings[$http_user],$string); + } + + return $string; +} ?>