Nowwhat47

function portal_allow (in /etc/inc/captiveportal.inc)

Jan 21st, 2015
577
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 10.98 KB | None | 0 0
  1. function portal_allow($clientip,$clientmac,$username,$password = null, $attributes = null, $pipeno = null, $radiusctx = null)  {
  2.     global $redirurl, $g, $config, $type, $passthrumac, $_POST, $cpzone;
  3.  
  4.     // Ensure we create an array if we are missing attributes
  5.     if (!is_array($attributes))
  6.         $attributes = array();
  7.  
  8.     unset($sessionid);
  9.  
  10.     /* Do not allow concurrent login execution. */
  11.     $cpdblck = lock("captiveportaldb{$cpzone}", LOCK_EX);
  12.  
  13.     if ($attributes['voucher'])
  14.         $remaining_time = $attributes['session_timeout'];
  15.  
  16.     $writecfg = false;
  17.     /* Find an existing session */
  18.     if ((isset($config['captiveportal'][$cpzone]['noconcurrentlogins'])) && $passthrumac) {
  19.         if (isset($config['captiveportal'][$cpzone]['passthrumacadd'])) {
  20.             $mac = captiveportal_passthrumac_findbyname($username);
  21.             if (!empty($mac)) {
  22.                 if ($_POST['replacemacpassthru']) {
  23.                     foreach ($config['captiveportal'][$cpzone]['passthrumac'] as $idx => $macent) {
  24.                         if ($macent['mac'] == $mac['mac']) {
  25.                             $macrules = "";
  26.                             $ruleno = captiveportal_get_ipfw_passthru_ruleno($mac['mac']);
  27.                             $pipeno = captiveportal_get_dn_passthru_ruleno($mac['mac']);
  28.                             if ($ruleno) {
  29.                                 captiveportal_free_ipfw_ruleno($ruleno);
  30.                                 $macrules .= "delete {$ruleno}\n";
  31.                                 ++$ruleno;
  32.                                 $macrules .= "delete {$ruleno}\n";
  33.                             }
  34.                             if ($pipeno) {
  35.                                 captiveportal_free_dn_ruleno($pipeno);
  36.                                 $macrules .= "pipe delete {$pipeno}\n";
  37.                                 ++$pipeno;
  38.                                 $macrules .= "pipe delete {$pipeno}\n";
  39.                             }
  40.                             unset($config['captiveportal'][$cpzone]['passthrumac'][$idx]);
  41.                             $mac['mac'] = $clientmac;
  42.                             $config['captiveportal'][$cpzone]['passthrumac'][] = $mac;
  43.                             $macrules .= captiveportal_passthrumac_configure_entry($mac);
  44.                             file_put_contents("{$g['tmp_path']}/macentry_{$cpzone}.rules.tmp", $macrules);
  45.                             mwexec("/sbin/ipfw -x {$cpzone} -q {$g['tmp_path']}/macentry_{$cpzone}.rules.tmp");
  46.                             $writecfg = true;
  47.                             $sessionid = true;
  48.                             break;
  49.                         }
  50.                     }
  51.                 } else {
  52.                     portal_reply_page($redirurl, "error", "Username: {$username} is already authenticated using another MAC address.",
  53.                         $clientmac, $clientip, $username, $password);
  54.                     unlock($cpdblck);
  55.                     return;
  56.                 }
  57.             }
  58.         }
  59.     }
  60.  
  61.     /* read in client database */
  62.     $query = "WHERE ip = '{$clientip}'";
  63.     $tmpusername = strtolower($username);
  64.     if (isset($config['captiveportal'][$cpzone]['noconcurrentlogins']))
  65.         $query .= " OR (username != 'unauthenticated' AND lower(username) = '{$tmpusername}')";
  66.     $cpdb = captiveportal_read_db($query);
  67.  
  68.     /* Snapshot the timestamp */
  69.     $allow_time = time();
  70.     $radiusservers = captiveportal_get_radius_servers();
  71.     $unsetindexes = array();
  72.     if (is_null($radiusctx))
  73.         $radiusctx = 'first';
  74.  
  75.     foreach ($cpdb as $cpentry) {
  76.         if (empty($cpentry[11])) {
  77.             $cpentry[11] = 'first';
  78.         }
  79.         /* on the same ip */
  80.         if ($cpentry[2] == $clientip) {
  81.             if (isset($config['captiveportal'][$cpzone]['nomacfilter']) || $cpentry[3] == $clientmac)
  82.                 captiveportal_logportalauth($cpentry[4],$cpentry[3],$cpentry[2],"CONCURRENT LOGIN - REUSING OLD SESSION");
  83.             else
  84.                 captiveportal_logportalauth($cpentry[4],$cpentry[3],$cpentry[2],"CONCURRENT LOGIN - REUSING IP {$cpentry[2]} WITH DIFFERENT MAC ADDRESS {$cpentry[3]}");
  85.             $sessionid = $cpentry[5];
  86.             break;
  87.         }
  88.         elseif (($attributes['voucher']) && ($username != 'unauthenticated') && ($cpentry[4] == $username)) {
  89.             // user logged in with an active voucher. Check for how long and calculate
  90.             // how much time we can give him (voucher credit - used time)
  91.             $remaining_time = $cpentry[0] + $cpentry[7] - $allow_time;
  92.             if ($remaining_time < 0)    // just in case.
  93.                 $remaining_time = 0;
  94.  
  95.             /* This user was already logged in so we disconnect the old one */
  96.             captiveportal_disconnect($cpentry,$radiusservers[$cpentry[11]],13);
  97.             captiveportal_logportalauth($cpentry[4],$cpentry[3],$cpentry[2],"CONCURRENT LOGIN - TERMINATING OLD SESSION");
  98.             $unsetindexes[] = $cpentry[5];
  99.             break;
  100.         }
  101.         elseif ((isset($config['captiveportal'][$cpzone]['noconcurrentlogins'])) && ($username != 'unauthenticated')) {
  102.             /* on the same username */
  103.             if (strcasecmp($cpentry[4], $username) == 0) {
  104.                 /* This user was already logged in so we disconnect the old one */
  105.                 captiveportal_disconnect($cpentry,$radiusservers[$cpentry[11]],13);
  106.                 captiveportal_logportalauth($cpentry[4],$cpentry[3],$cpentry[2],"CONCURRENT LOGIN - TERMINATING OLD SESSION");
  107.                 $unsetindexes[] = $cpentry[5];
  108.                 break;
  109.             }
  110.         }
  111.     }
  112.     unset($cpdb);
  113.  
  114.     if (!empty($unsetindexes))
  115.         captiveportal_remove_entries($unsetindexes);
  116.  
  117.     if ($attributes['voucher'] && $remaining_time <= 0)
  118.         return 0;       // voucher already used and no time left
  119.  
  120.     if (!isset($sessionid)) {
  121.         /* generate unique session ID */
  122.         $tod = gettimeofday();
  123.         $sessionid = substr(md5(mt_rand() . $tod['sec'] . $tod['usec'] . $clientip . $clientmac), 0, 16);
  124.  
  125.         if ($passthrumac) {
  126.             $mac = array();
  127.             $mac['mac'] = $clientmac;
  128.             $mac['ip'] = $clientip; /* Used only for logging */
  129.             if (isset($config['captiveportal'][$cpzone]['passthrumacaddusername'])) {
  130.                 $mac['username'] = $username;
  131.                 if ($attributes['voucher'])
  132.                     $mac['logintype'] = "voucher";
  133.             }
  134.             $mac['descr'] =  "Auto added pass-through MAC for user {$username}";
  135.             if (!empty($bw_up))
  136.                 $mac['bw_up'] = $bw_up;
  137.             if (!empty($bw_down))
  138.                 $mac['bw_down'] = $bw_down;
  139.             if (!is_array($config['captiveportal'][$cpzone]['passthrumac']))
  140.                 $config['captiveportal'][$cpzone]['passthrumac'] = array();
  141.             $config['captiveportal'][$cpzone]['passthrumac'][] = $mac;
  142.             unlock($cpdblck);
  143.             $macrules = captiveportal_passthrumac_configure_entry($mac);
  144.             file_put_contents("{$g['tmp_path']}/macentry_{$cpzone}.rules.tmp", $macrules);
  145.             mwexec("/sbin/ipfw -x {$cpzone} -q {$g['tmp_path']}/macentry_{$cpzone}.rules.tmp");
  146.             $writecfg = true;
  147.         } else {
  148.             /* See if a pipeno is passed, if not start sessions because this means there isn't one atm */
  149.             if (is_null($pipeno))
  150.                 $pipeno = captiveportal_get_next_dn_ruleno();
  151.  
  152.             /* if the pool is empty, return appropriate message and exit */
  153.             if (is_null($pipeno)) {
  154.                 portal_reply_page($redirurl, "error", "System reached maximum login capacity");
  155.                 log_error("WARNING!  Captive portal has reached maximum login capacity");
  156.                 unlock($cpdblck);
  157.                 return;
  158.             }
  159.  
  160.             $dwfaultbw_up = isset($config['captiveportal'][$cpzone]['bwdefaultup']) ? $config['captiveportal'][$cpzone]['bwdefaultup'] : 0;
  161.             $dwfaultbw_down = isset($config['captiveportal'][$cpzone]['bwdefaultdn']) ? $config['captiveportal'][$cpzone]['bwdefaultdn'] : 0;
  162.             $bw_up = isset($attributes['bw_up']) ? round(intval($attributes['bw_up'])/1000, 2) : $dwfaultbw_up;
  163.             $bw_down = isset($attributes['bw_down']) ? round(intval($attributes['bw_down'])/1000, 2) : $dwfaultbw_down;
  164.  
  165.             $bw_up_pipeno = $pipeno;
  166.             $bw_down_pipeno = $pipeno + 1;
  167.             //$bw_up /= 1000; // Scale to Kbit/s
  168.             $_gb = @pfSense_pipe_action("pipe {$bw_up_pipeno} config bw {$bw_up}Kbit/s queue 100 buckets 16");
  169.             $_gb = @pfSense_pipe_action("pipe {$bw_down_pipeno} config bw {$bw_down}Kbit/s queue 100 buckets 16");
  170.  
  171.             $clientsn = (is_ipaddrv6($clientip)) ? 128 : 32;
  172.             if (!isset($config['captiveportal'][$cpzone]['nomacfilter']))
  173.                 $_gb = @pfSense_ipfw_Tableaction($cpzone, IP_FW_TABLE_ADD, 1, $clientip, $clientsn, $clientmac, $bw_up_pipeno);
  174.             else
  175.                 $_gb = @pfSense_ipfw_Tableaction($cpzone, IP_FW_TABLE_ADD, 1, $clientip, $clientsn, NULL, $bw_up_pipeno);
  176.  
  177.             if (!isset($config['captiveportal'][$cpzone]['nomacfilter']))
  178.                 $_gb = @pfSense_ipfw_Tableaction($cpzone, IP_FW_TABLE_ADD, 2, $clientip, $clientsn, $clientmac, $bw_down_pipeno);
  179.             else
  180.                 $_gb = @pfSense_ipfw_Tableaction($cpzone, IP_FW_TABLE_ADD, 2, $clientip, $clientsn, NULL, $bw_down_pipeno);
  181.  
  182.             if ($attributes['voucher'])
  183.                 $attributes['session_timeout'] = $remaining_time;
  184.            
  185.             /* handle empty attributes */
  186.             $session_timeout = (!empty($attributes['session_timeout'])) ? $attributes['session_timeout'] : 'NULL';
  187.             $idle_timeout = (!empty($attributes['idle_timeout'])) ? $attributes['idle_timeout'] : 'NULL';
  188.             $session_terminate_time = (!empty($attributes['session_terminate_time'])) ? $attributes['session_terminate_time'] : 'NULL';
  189.             $interim_interval = (!empty($attributes['interim_interval'])) ? $attributes['interim_interval'] : 'NULL';
  190.  
  191.             /* escape username */
  192.             $safe_username = sqlite_escape_string($username);
  193.  
  194.             /* encode password in Base64 just in case it contains commas */
  195.             $bpassword = base64_encode($password);
  196.             $insertquery  = "INSERT INTO captiveportal (allow_time, pipeno, ip, mac, username, sessionid, bpassword, session_timeout, idle_timeout, session_terminate_time, interim_interval, radiusctx) ";
  197.             $insertquery .= "VALUES ({$allow_time}, {$pipeno}, '{$clientip}', '{$clientmac}', '{$safe_username}', '{$sessionid}', '{$bpassword}', ";
  198.             $insertquery .= "{$session_timeout}, {$idle_timeout}, {$session_terminate_time}, {$interim_interval}, '{$radiusctx}')";
  199.  
  200.             /* store information to database */
  201.             captiveportal_write_db($insertquery);
  202.             unlock($cpdblck);
  203.             unset($insertquery, $bpassword);
  204.  
  205.             if (isset($config['captiveportal'][$cpzone]['radacct_enable']) && !empty($radiusservers[$radiusctx])) {
  206.                 $acct_val = RADIUS_ACCOUNTING_START($pipeno, $username, $sessionid, $radiusservers[$radiusctx], $clientip, $clientmac);
  207.                 if ($acct_val == 1)
  208.                     captiveportal_logportalauth($username,$clientmac,$clientip,$type,"RADIUS ACCOUNTING FAILED");
  209.             }
  210.         }
  211.     } else {
  212.         /* NOTE: #3062-11 If the pipeno has been allocated free it to not DoS the CP and maintain proper operation as in radius() case */
  213.         if (!is_null($pipeno))
  214.             captiveportal_free_dn_ruleno($pipeno);
  215.  
  216.         unlock($cpdblck);
  217.     }
  218.  
  219.     if ($writecfg == true)
  220.         write_config();
  221.  
  222.     $timeout = 0;
  223.     if (!empty($config['captiveportal'][$cpzone]['timeout']) && is_numeric($config['captiveportal'][$cpzone]['timeout'])) {
  224.         $timeout = time() + $config['captiveportal'][$cpzone]['timeout'] * 60;
  225.         setcookie("cookie_portal", $sessionid, $timeout);
  226.     } else
  227.         setcookie("cookie_portal", $sessionid, $timeout);  
  228.        
  229.     /* redirect user to desired destination */
  230.     if (!empty($attributes['url_redirection']))
  231.         $my_redirurl = $attributes['url_redirection'];
  232.     else if (!empty($redirurl))
  233.         $my_redirurl = $redirurl;
  234.     else if (!empty($config['captiveportal'][$cpzone]['redirurl']))
  235.         $my_redirurl = $config['captiveportal'][$cpzone]['redirurl'];
  236.  
  237.     if(isset($config['captiveportal'][$cpzone]['logoutwin_enable']) && !$passthrumac) {
  238.         $ourhostname = portal_hostname_from_client_ip($clientip);
  239.         $protocol = (isset($config['captiveportal'][$cpzone]['httpslogin'])) ? 'https://' : 'http://';
  240.         $logouturl = "{$protocol}{$ourhostname}/";
  241.  
  242.         if (isset($attributes['reply_message']))
  243.             $message = $attributes['reply_message'];
  244.         else
  245.             $message = 0;
  246.  
  247.         include("{$g['varetc_path']}/captiveportal-{$cpzone}-logout.html");
  248.  
  249.     } else {
  250.         portal_reply_page($my_redirurl, "redir", "Just redirect the user.");
  251.     }
  252.  
  253.     return $sessionid;
  254. }
Add Comment
Please, Sign In to add comment