PHP Classes

File: multiotp.cli.proxy.php

Recommend this page to a friend!
  Classes of André Liechti   multiOTP PHP class   multiotp.cli.proxy.php   Download  
File: multiotp.cli.proxy.php
Role: Auxiliary script
Content type: text/plain
Description: Auxiliary script
Class: multiOTP PHP class
Authenticate and manage OTP strong user tokens
Author: By
Last change: New release 5.9.7.1
FIX: Command line number of parameters detection corrected
ENH: It's now possible to define the number of digits for new created PIN
(multiotp -config default-pin-digits=n)
ENH: It's now possible to generate the HTML provisioning file by command line
(multiotp -htmlinfo username /full/path/to/username.html or
multiotp -htmlinfo /full/path/to/folder/ to generate files for all users)
ENH: Embedded Windows nginx edition updated to version 1.25.3
ENH: Embedded Windows internal tools updated (wget 1.21.4 and fart 1.99d)
ENH: Embedded Windows freeradius is now launched using NSSM (instead of SRVANY)
New release 5.9.7.0
FIX: Better Windows nginx configuration support (path backslashes replaced by slashes)
ENH: Embedded Windows nginx edition updated to version 1.24.0
ENH: Embedded Windows PHP edition updated to version 8.2.13
ENH: Better hardware/model detection
ENH: Documentation enhanced with instructions for RDWeb on Windows
ENH: Upgrade of some internal tools
ENH: Better internal configuration organization
New release 5.9.6.7
ENH: Documentation updated for "Configuring multiOTP with FreeRADIUS 3.x under Linux"
ENH: Without2FA tokens cannot be used for multi_account connection
ENH: Added documentation for SSH login with multiOTP
New release 5.9.6.5
FIX: Better Raspberry Pi support
FIX: ShowLog() method (used by -showlog option) was buggy
New release 5.9.6.1
FIX: Automated concurrent access for the same user with "Without2FA" token could corrupt the user file
FIX: Any files backend operation is now secured with explicit lock mechanism
ENH: Template updated to print bigger QRcode for "MOTP-XML" tokens
New release 5.9.5.7
FIX: Weekly anonymized stats date was not always updated
FIX: Adding -tokenslist command in CLI mode (mas missing)
FIX: Remove a debug line displaying sometimes "COMMDN:$command\n";
FIX: Some minor PHP notice corrections
ENH: Adding on-premises smsgateway (https://github.com/multiOTP/SMSGateway) as a new SMS provider
ENH: Better warning messages when CheckUserLdapPassword failed
ENH: Embedded documentation enhanced
ENH: Template updated to display correct information for WITHOUT2FA tokens
Date: 7 months ago
Size: 6,779 bytes
 

Contents

Class file image Download
<?php
/**
 * @file multiotp.cli.proxy.php
 * @brief Command line calling the proxy of the multiOTP PHP class.
 *
 * multiOTP PHP CLI proxy - Strong two-factor authentication PHP class
 * https://www.multiotp.net
 *
 * Visit http://forum.multiotp.net/ for additional support.
 *
 * Donation are always welcome! Please check https://www.multiotp.net
 * and you will find the magic button ;-)
 *
 *
 * PHP 5.4.0 or higher is supported.
 *
 * @author Andre Liechti, SysCo systemes de communication sa, <info@multiotp.net>
 * @version 5.9.7.1
 * @date 2023-12-03
 * @since 2010-06-08
 * @copyright (c) 2010-2023 SysCo systemes de communication sa
 * @copyright GNU Lesser General Public License
 *
 *//*
 *
 * LICENCE
 *
 * Copyright (c) 2014-2023 SysCo systemes de communication sa
 * SysCo (tm) is a trademark of SysCo systemes de communication sa
 * (http://www.sysco.ch)
 * All rights reserved.
 *
 * This file is part of the MultiOTP PHP class
 *
 * MultiOTP PHP class is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of the License,
 * or (at your option) any later version.
 *
 * MultiOTP PHP class is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with MultiOTP PHP class.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 *
 * Command line usage
 *
 * Same usage as multiotp.cli.header.php. It's just a proxy to call
 * the web version of multiotp.cli.header.php, which could be cached,
 * giving a massive speed improvement on "weak" machines like Raspberry Pi.
 *
 * If the web version is not responding, it will fallback nicely and
 * will do a require_once of the local proxy file.
 *
 *********************************************************************/

@set_time_limit(0); // It can take a lot of time...

global $argc;
global
$argv;

// Define the stream context
if (function_exists("stream_context_set_default")) {
 
$default_ssl_context = array(
   
'ssl' => array(
     
'verify_peer' => false,
     
'verify_peer_name' => false,
     
'disable_compression' => true,
     
'ciphers' => 'ALL!EXPORT!EXPORT40!EXPORT56!aNULL!LOW!RC4'
   
)
  );
 
$default_context = stream_context_set_default($default_ssl_context);
}

$proxy_full_url = isset($proxy_full_url) ? $proxy_full_url : "http://127.0.0.1:18081/";
$timeout = isset($timeout)?intval($timeout):15;
$local_proxy_file = isset($local_proxy_file) ? $local_proxy_file : "multiotp.proxy.php";

// Clean quotes of the parameters if any
if (!function_exists('clean_quotes')) {
  function
clean_quotes($value)
  {
   
$cleaned = false;
   
$var = $value;
    if (((
'"' == substr($var,0,1)) || ("'" == substr($var,0,1))) && (('"' == substr($var,-1)) || ("'" == substr($var,-1)))) {
     
$var = substr($var, 1, mb_strlen($var)-2);
     
$cleaned = true;
    }
    if (
$cleaned) {
     
$var = clean_quotes($var);
    }
    return
$var;
  }
}

$value_unencoded = '';
// $_SERVER["argv"][0] is useless, it's the name of the script

$argv = isset($_SERVER["argv"]) ? $_SERVER["argv"] : (isset($argv) ? $argv : "");
$argc = intval(isset($_SERVER["argc"]) ? $_SERVER["argc"] : (isset($argc) ? $argc : 0));

for (
$arg_loop=1; $arg_loop < $argc; $arg_loop++) {
 
$current_arg = clean_quotes($argv[$arg_loop]);
  if (
'' != $value_unencoded) {
   
$value_unencoded.= chr(0);
  }
 
$value_unencoded.= $current_arg;
}

$key = 'argv';
$value = base64_encode($value_unencoded);

$multiotp_error_level_received = FALSE;
$multiotp_error_level = 99; // Unknown error

$post_url = $proxy_full_url;

$result = '';
$content_to_post = $key.'='.$value;

$pos = mb_strpos($post_url, '://');
if (
FALSE === $pos) {
 
$protocol = '';
} else {
  switch (
mb_strtolower(substr($post_url,0,$pos),'UTF-8')) {
    case
'https':
    case
'ssl':
       
$protocol = 'ssl://';
        break;
    case
'tls':
       
$protocol = 'tls://';
        break;
    default:
       
$protocol = '';
        break;
  }
 
$post_url = substr($post_url,$pos+3);
}

$pos = mb_strpos($post_url, '/');
if (
FALSE === $pos) {
 
$host = $post_url;
 
$url = '/';
} else {
 
$host = substr($post_url,0,$pos);
 
$url = substr($post_url,$pos); // And not +1 as we want the / at the beginning
}

$pos = mb_strpos($host, ':');
if (
FALSE === $pos) {
 
$port = 80;
} else {
 
$port = substr($host,$pos+1);
 
$host = substr($host,0,$pos);
}

$errno = 0;
$errdesc = 0;
$fp = @fsockopen($protocol.$host, $port, $errno, $errdesc, $timeout);
if (
FALSE !== $fp) {
 
$info['timed_out'] = FALSE;
 
fputs($fp, "POST ".$url." HTTP/1.0\r\n");
 
fputs($fp, "Content-Type: application/x-www-form-urlencoded\r\n");
 
fputs($fp, "Content-Length: ".mb_strlen($content_to_post)."\r\n");
 
fputs($fp, "User-Agent: multiOTP proxy\r\n");
 
fputs($fp, "Host: ".$host."\r\n");
 
fputs($fp, "\r\n");
 
fputs($fp, $content_to_post);
 
fputs($fp, "\r\n");

 
stream_set_blocking($fp, TRUE);
 
stream_set_timeout($fp, 86400); // It can take a lot of time, if we are doing AD/LDAP sync for example
 
$info = stream_get_meta_data($fp);

 
$reply = '';
 
$last_length = 0;
  while ((!
feof($fp)) && ((!$info['timed_out']) || ($last_length != mb_strlen($reply)))) {
   
$last_length = mb_strlen($reply);
   
$reply.= fgets($fp, 1024);
   
$info = stream_get_meta_data($fp);
    @
ob_flush(); // Avoid notice if any (if the buffer is empty and therefore cannot be flushed)
   
flush();
  }
 
fclose($fp);

  if (
$info['timed_out']) {
   
// error_log("Warning: timeout after $timeout seconds for $protocol$host:$port$url with a result code of $errno ($errdesc)");
 
} else {
   
// error_log("CLI ok");
   
$pos = mb_strpos(mb_strtolower($reply,'UTF-8'), "\r\n\r\n");
   
$header = substr($reply, 0, $pos);
   
   
$header_array = explode("\r\n", $header);
    foreach (
$header_array as $one_header) {
     
$one_header_array = explode(":", $one_header, 2);
      if (isset(
$one_header_array[1])) {
        if (
'X-multiOTP-Error-Level' == trim($one_header_array[0])) {
         
$multiotp_error_level_received = TRUE;
         
$multiotp_error_level = intval(trim($one_header_array[1]));
          break;
        }
      }
    }
   
   
$answer = substr($reply, $pos + 4);
   
   
$result = $answer;
    if (
$errno > 0) {
     
// Error ?
   
}
  }
}

if (!
$multiotp_error_level_received) {
  require_once(
dirname(__FILE__)."/".$local_proxy_file);
} else {
  echo
$result;
  exit(
$multiotp_error_level);
}
?>