PHP Classes
elePHPant
Icontem

File: multiotp.php

Recommend this page to a friend!
  Classes of Andr Liechti  >  multiOTP PHP class  >  multiotp.php  >  Download  
File: multiotp.php
Role: Application script
Content type: text/plain
Description: Command line tool (merged from the special header and the class)
Class: multiOTP PHP class
Authenticate and manage OTP strong user tokens
Author: By
Last change: Release 5.0.4.6
Date: 3 months ago
Size: 1,518,203 bytes
 

Contents

Class file image Download
#!/usr/bin/php
<?php
/* multiOTP stripped command line version (all-in-one) */
 global $argc; global $argv; if (!isset($multiotp)) { class Multiotp { var $_class; var $_version; var $_date; var $_copyright; var $_website; var $_base_dir; var $_valid_algorithms; var $_attributes_to_encrypt; var $_encryption_key; var $_source_tag; var $_source_ip; var $_source_mac; var $_calling_ip; var $_calling_mac; var $_chap_challenge; var $_chap_id; var $_chap_password; var $_ms_chap_challenge; var $_ms_chap_response; var $_ms_chap2_response; var $_ms_nt_key; var $_errors_text; var $_config_data; var $_config_folder; var $_device; var $_device_data; var $_group; var $_group_data; var $_user; var $_user_data; var $_user_data_read_flag; var $_users_folder; var $_qrcode_folder; var $_templates_folder; var $_devices_folder; var $_groups_folder; var $_token; var $_token_data; var $_token_data_read_flag; var $_tokens_folder; var $_log_folder; var $_log_file_name; var $_log_flag; var $_log_header_written; var $_log_verbose_flag; var $_log_display_flag; var $_last_imported_tokens; var $_reply_array_for_radius; var $_initialize_backend; var $_debug_via_html; var $_linux_file_mode; var $_server_challenge; var $_xml_dump_in_log; var $_servers_temp_bad_list; var $_test_server_secret; var $_last_clear_otp_value; var $_last_ldap_error; var $_parser_pointers; var $_cache_folder; var $_ldap_server_reachable; var $_default_ssl_context; var $_sql_tables; var $_anonymous_stat_interval; var $_no_display_log; var $_cli_mode; var $_cli_proxy_mode; var $_touch_folder; var $_touch_suffix_array; var $_lock_folder; var $_lock_time; var $_ldap_sync_lock_file_name; var $_ldap_sync_stop_file_name; var $_last_http_status; var $_bad_syslog_server; function __construct( $encryption_key = "", $initialize_backend = false, $base_dir = "", $config_dir = "" ) { if (!version_compare(phpversion(), '5', '>=')) { register_shutdown_function(array(&$this, '__destruct')); } putenv('RES_OPTIONS=retrans:1 retry:1 timeout:3 attempts:1'); putenv('LDAPTLS_REQCERT=never'); putenv('LDAPTLS_CIPHER_SUITE=NORMAL:!VERS-TLS1.2'); if (!isset($this->_class)) { $this->_class = base64_decode('bXVsdGlPVFA='); } if (!isset($this->_version)) { $temp_version = '@version   5.0.4.6'; $this->_version = trim(substr($temp_version, 8)); } if (!isset($this->_date)) { $temp_date = '@date      2017-06-02'; $this->_date = trim(substr($temp_date, 8)); } if (!isset($this->_copyright)) { $this->_copyright = base64_decode('KGMpIDIwMTAtMjAxNyBTeXNDbyBzeXN0ZW1lcyBkZSBjb21tdW5pY2F0aW9uIHNh'); } if (!isset($this->_website)) { $this->_website = base64_decode('aHR0cDovL3d3dy5tdWx0aU9UUC5uZXQ='); } $this->_anonymous_stat_interval = 604800; $this->_log_header_written = FALSE; $this->_valid_algorithms = '*mOTP*HOTP*TOTP*YubicoOTP*'; $this->_attributes_to_encrypt = '*admin_password_hash*challenge*device_secret*ldap_hash_cache*ldap_server_password*scratch_passwords*seed_password*server_secret*sms_api_id*sms_otp*sms_password*sms_userkey*smtp_password*sql_password*token_seed*user_pin*'; $this->_no_display_log = false; $this->_cli_mode = false; $this->_cli_proxy_mode = false; clearstatcache(); $this->_touch_folder = ''; $this->_touch_suffix_array = array(); $this->SetLockTime(300); $lock_folder = '/dev/shm/'; if (!file_exists($lock_folder)) { $lock_folder = sys_get_temp_dir()."/"; $actual_folder = $lock_folder; $actual_filter = "multiotp-*.lock"; if (($actual_dir = opendir($actual_folder)) !== FALSE) { while(($actual_file_name = readdir($actual_dir)) !== FALSE) { if (fnmatch($actual_filter, $actual_file_name)) { $actual_file = $actual_folder.$actual_file_name; if (filemtime($actual_file) <= (time() - $this->GetLockTime())) { unlink($actual_file); } } } } } $this->SetLockFolder($lock_folder); $this->SetLdapSyncLockFileName("multiotp-ldap.lock"); $this->SetLdapSyncStopFileName("multiotp-ldap.stop"); $this->_ldap_server_reachable = FALSE; $this->_default_ssl_context = array( 'ssl' => array( 'verify_peer' => false, 'verify_peer_name' => false, 'disable_compression' => true, 'ciphers' => 'ALL!EXPORT!EXPORT40!EXPORT56!aNULL!LOW!RC4' ) ); if (function_exists("stream_context_set_default")) { $default_context = stream_context_set_default($this->_default_ssl_context); } $this->_sql_tables = array('cache', 'config', 'devices', 'groups', 'log', 'tokens', 'users' ); $this->_sql_tables_schema['cache'] = array( 'active_users_count' => "int(10) DEFAULT -1", 'devices_count' => "int(10) DEFAULT -1", 'last_update' => "int(10) DEFAULT 0", 'locked_users_count' => "int(10) DEFAULT -1", 'locked_users_list' => "int(10) DEFAULT -1", 'delayed_users_count' => "int(10) DEFAULT -1", 'delayed_users_list' => "int(10) DEFAULT -1", 'tokens_count' => "int(10) DEFAULT -1", 'users_count' => "int(10) DEFAULT -1"); $this->_sql_tables_index['cache'] = '**'; $this->_sql_tables_ignore['cache'] = "**"; $this->_sql_tables_schema['config'] = array( 'actual_version' => "varchar(255) DEFAULT ''", 'admin_password_hash' => "varchar(255) DEFAULT ''", 'anonymous_stat' => "int(1) DEFAULT 1", 'anonymous_stat_last_update' => "int(10) DEFAULT 0", 'anonymous_stat_random_id' => "varchar(255) DEFAULT ''", 'attributes_to_encrypt' => "varchar(255) DEFAULT ''", 'auto_resync' => "int(1) DEFAULT 1", 'backend_encoding' => "varchar(255) DEFAULT 'UTF-8'", 'backend_type' => "varchar(255) DEFAULT 'files'", 'backend_type_validated' => "int(1) DEFAULT 0", 'cache_data' => "int(1) DEFAULT 0", 'cache_ldap_hash' => "int(1) DEFAULT 1", 'case_sensitive_users' => "int(1) DEFAULT 0", 'clear_otp_attribute' => "varchar(255) DEFAULT ''", 'console_authentication' => "int(1) DEFAULT 0", 'debug' => "int(1) DEFAULT 0", 'default_algorithm' => "varchar(255) DEFAULT 'totp'", 'default_dialin_ip_mask' => "varchar(255) DEFAULT ''", 'default_user_group' => "varchar(255) DEFAULT ''", 'default_request_ldap_pwd' => "int(1) DEFAULT 1", 'default_request_prefix_pin' => "int(1) DEFAULT 1", 'demo_mode' => "int(1) DEFAULT 0", 'display_log' => "int(1) DEFAULT 0", 'domain_name' => "varchar(255) DEFAULT ''", 'email_admin_address' => "varchar(255) DEFAULT ''", 'encode_file_id' => "int(1) DEFAULT 0", 'encryption_key_full_path' => "varchar(255) DEFAULT ''", 'failure_delayed_time' => "int(10) DEFAULT 300", 'group_attribute' => "varchar(255) DEFAULT 'Filter-Id'", 'hash_salt_full_path' => "varchar(255) DEFAULT ''", 'issuer' => "varchar(255) DEFAULT 'multiOTP'", 'language' => "varchar(255) DEFAULT 'en'", 'last_update' => "int(10) DEFAULT 0", 'ldap_account_suffix' => "varchar(255) DEFAULT ''", 'ldap_activated' => "int(1) DEFAULT 0", 'ldap_base_dn' => "varchar(255) DEFAULT ''", 'ldap_bind_dn' => "varchar(255) DEFAULT ''", 'ldap_cache_folder' => "varchar(255) DEFAULT 'tempdir'", 'ldap_cache_on' => "int(1) DEFAULT 1", 'ldap_cn_identifier' => "varchar(255) DEFAULT 'sAMAccountName'", 'ldap_default_algorithm' => "varchar(255) DEFAULT 'totp'", 'ldap_domain_controllers' => "varchar(255) DEFAULT ''", 'last_failed_white_delay' => "int(10) DEFAULT 60", 'ldap_group_attribute' => "varchar(255) DEFAULT 'memberOf'", 'ldap_group_cn_identifier' => "varchar(255) DEFAULT 'cn'", 'ldap_groups_dn' => "varchar(255) DEFAULT ''", 'ldap_hash_cache_time' => "int(10) DEFAULT 604800", 'ldap_in_group' => "varchar(255) DEFAULT ''", 'ldap_language_attribute' => "varchar(255) DEFAULT 'preferredLanguage'", 'ldap_network_timeout' => "int(10) DEFAULT 10", 'ldap_port' => "varchar(255) DEFAULT '389'", 'ldap_recursive_cache_only' => "int(1) DEFAULT 0", 'ldap_recursive_groups' => "int(1) DEFAULT 1", 'ldap_server_password' => "varchar(255) DEFAULT ''", 'ldap_server_type' => "int(10) DEFAULT 1", 'ldap_ssl' => "int(1) DEFAULT 0", 'ldap_synced_user_attribute' => "varchar(255) DEFAULT ''", 'ldap_time_limit' => "int(10) DEFAULT 30", 'log' => "int(1) DEFAULT 0", 'max_block_failures' => "int(10) DEFAULT 6", 'max_delayed_failures' => "int(10) DEFAULT 3", 'max_event_resync_window' => "int(10) DEFAULT 10000", 'max_event_window' => "int(10) DEFAULT 100", 'max_time_resync_window' => "int(10) DEFAULT 90000", 'max_time_window' => "int(10) DEFAULT 600", 'multiple_groups' => "int(1) DEFAULT 0", 'ntp_server' => "varchar(255) DEFAULT 'pool.ntp.org'", 'overwrite_request_ldap_pwd' => "int(1) DEFAULT 1", 'radius_error_reply_message' => "int(1) DEFAULT 1", 'radius_reply_attributor' => "varchar(255) DEFAULT ' += '", 'radius_reply_separator_hex' => "varchar(255) DEFAULT '".bin2hex(',')."'", 'scratch_passwords_digits' => "int(10) DEFAULT 6", 'scratch_passwords_amount' => "int(10) DEFAULT 10", 'self_registration' => "int(1) DEFAULT 1", 'server_cache_level' => "int(10) DEFAULT 1", 'server_cache_lifetime' => "int(10) DEFAULT 15552000", 'server_secret' => "varchar(255) DEFAULT 'ClientServerSecret'", 'server_timeout' => "int(10) DEFAULT 5", 'server_type' => "varchar(255) DEFAULT 'xml'", 'server_url' => "varchar(255) DEFAULT ''", 'sms_api_id' => "varchar(255) DEFAULT ''", 'sms_message_prefix' => "varchar(255) DEFAULT '%s is your SMS-Code'", 'sms_originator' => "varchar(255) DEFAULT 'multiOTP'", 'sms_password' => "varchar(255) DEFAULT ''", 'sms_provider' => "varchar(255) DEFAULT ''", 'sms_userkey' => "varchar(255) DEFAULT ''", 'sms_digits' => "int(10) DEFAULT 6", 'sms_timeout' => "int(10) DEFAULT 180", 'smtp_auth' => "int(1) DEFAULT 0", 'smtp_password' => "varchar(255) DEFAULT ''", 'smtp_port' => "int(10) DEFAULT 25", 'smtp_sender' => "varchar(255) DEFAULT ''", 'smtp_sender_name' => "varchar(255) DEFAULT ''", 'smtp_server' => "varchar(255) DEFAULT ''", 'smtp_ssl' => "int(1) DEFAULT 0", 'smtp_username' => "varchar(255) DEFAULT ''", 'sql_server' => "varchar(255) DEFAULT ''", 'sql_username' => "varchar(255) DEFAULT ''", 'sql_password' => "varchar(255) DEFAULT ''", 'sql_database' => "varchar(255) DEFAULT ''", 'sql_schema' => "varchar(255) DEFAULT ''", 'sql_config_table' => "varchar(255) DEFAULT 'multiotp_config'", 'sql_cache_table' => "varchar(255) DEFAULT 'multiotp_cache'", 'sql_devices_table' => "varchar(255) DEFAULT 'multiotp_devices'", 'sql_groups_table' => "varchar(255) DEFAULT 'multiotp_groups'", 'sql_log_table' => "varchar(255) DEFAULT 'multiotp_log'", 'sql_tokens_table' => "varchar(255) DEFAULT 'multiotp_tokens'", 'sql_users_table' => "varchar(255) DEFAULT 'multiotp_users'", 'syslog_facility' => "int(10) DEFAULT 7", 'syslog_level' => "int(10) DEFAULT 5", 'syslog_port' => "int(10) DEFAULT 514", 'syslog_server' => "varchar(255) DEFAULT ''", 'tel_default_country_code' => "varchar(255) DEFAULT ''", 'timezone' => "varchar(255) DEFAULT 'Europe/Zurich'", 'token_serial_number_length' => "varchar(255) DEFAULT '12'", 'token_otp_list_of_length' => "varchar(255) DEFAULT '6'", 'verbose_log_prefix' => "varchar(255) DEFAULT ''", 'encryption_hash' => "varchar(255) DEFAULT ''"); $this->_sql_tables_index['config'] = '**'; $this->_sql_tables_ignore['config'] = '*backend_type*backend_type_validated*sql_server*sql_username*sql_password*sql_database*sql_schema*sql_config_table*'; $this->_sql_tables_schema['devices'] = array( 'device_id' => "varchar(255) DEFAULT ''", 'cache_result_enabled' => "int(1) DEFAULT 0", 'cache_timeout' => "int(10) DEFAULT 3600", 'challenge_response_enabled' => "int(1) DEFAULT 0", 'description' => "varchar(255) DEFAULT ''", 'device_groups' => "varchar(255) DEFAULT ''", 'device_secret' => "varchar(255) DEFAULT ''", 'ip_or_fqdn' => "varchar(255) DEFAULT ''", 'last_update' => "int(10) DEFAULT 0", 'multiple_groups' => "int(1) DEFAULT 0", 'shortname' => "varchar(255) DEFAULT ''", 'sms_challenge_enabled' => "int(1) DEFAULT 0", 'subnet' => "varchar(255) DEFAULT ''", 'text_sms_challenge' => "varchar(255) DEFAULT 'Please enter the code received on your mobile phone'", 'text_token_challenge' => "varchar(255) DEFAULT 'Please enter the code displayed on the token'", 'encryption_hash' => "varchar(255) DEFAULT ''"); $this->_sql_tables_index['devices'] = '*device_id*ip_or_fqdn*shortname*'; $this->_sql_tables_ignore['devices'] = "**"; $this->_sql_tables_schema['groups'] = array( 'group_id' => "varchar(255) DEFAULT ''", 'description' => "varchar(255) DEFAULT ''", 'name' => "varchar(255) DEFAULT ''", 'last_update' => "int(10) DEFAULT 0", 'encryption_hash' => "varchar(255) DEFAULT ''"); $this->_sql_tables_index['groups'] = '*group_id*name*'; $this->_sql_tables_ignore['groups'] = "**"; $this->_sql_tables_schema['log'] = array( 'category' => "varchar(255) DEFAULT ''", 'datetime' => "datetime DEFAULT NULL", 'destination' => "varchar(255) DEFAULT ''", 'last_update' => "int(10) DEFAULT 0", 'logentry' => "text", 'note' => "varchar(255) DEFAULT ''", 'severity' => "varchar(255) DEFAULT ''", 'source' => "varchar(255) DEFAULT ''", 'user' => "varchar(255) DEFAULT ''"); $this->_sql_tables_index['log'] = '*datetime*'; $this->_sql_tables_ignore['log'] = "**"; $this->_sql_tables_schema['tokens'] = array( 'algorithm' => "varchar(255) DEFAULT ''", 'attributed_users' => "varchar(255) DEFAULT ''", 'delta_time' => "int(10) DEFAULT 0", 'description' => "varchar(255) DEFAULT ''", 'error_counter' => "int(10) DEFAULT 0", 'format' => "varchar(255) DEFAULT ''", 'key_id' => "varchar(255) DEFAULT ''", 'key_usage' => "varchar(255) DEFAULT ''", 'issue_no' => "varchar(255) DEFAULT ''", 'issuer' => "varchar(255) DEFAULT ''", 'key_algorithm' => "varchar(255) DEFAULT ''", 'last_error' => "int(10) DEFAULT 0", 'last_event' => "int(10) DEFAULT -1", 'last_login' => "int(10) DEFAULT 0", 'last_update' => "int(10) DEFAULT 0", 'locked' => "int(1) DEFAULT 0", 'manufacturer' => "varchar(255) DEFAULT 'multiOTP'", 'model' => "varchar(255) DEFAULT ''", 'number_of_digits' => "int(10) DEFAULT 6", 'otp' => "varchar(255) DEFAULT ''", 'private_id' => "varchar(255) DEFAULT ''", 'serial_no' => "varchar(255) DEFAULT ''", 'time_interval' => "int(10) DEFAULT 0", 'token_algo_suite' => "varchar(255) DEFAULT ''", 'token_id' => "varchar(255) DEFAULT ''", 'token_seed' => "varchar(255) DEFAULT '3132333435363738393031323334353637383930'", 'token_serial' => "varchar(255) DEFAULT ''", 'encryption_hash' => "varchar(255) DEFAULT ''"); $this->_sql_tables_index['tokens'] = '*attributed_users*token_id*token_serial*'; $this->_sql_tables_ignore['tokens'] = "**"; $this->_sql_tables_schema['users'] = array( 'algorithm' => "varchar(255) DEFAULT ''", 'attributed_tokens' => "varchar(255) DEFAULT ''", 'autolock_time' => "int(10) DEFAULT 0", 'challenge' => "varchar(255) DEFAULT ''", 'challenge_validity' => "int(10) DEFAULT 0", 'delta_time' => "int(10) DEFAULT 0", 'desactivated' => "int(1) DEFAULT 0", 'description' => "varchar(255) DEFAULT ''", 'dialin_ip_address' => "varchar(255) DEFAULT ''", 'dialin_ip_mask' => "varchar(255) DEFAULT ''", 'email' => "varchar(255) DEFAULT ''", 'error_counter' => "int(10) DEFAULT 0", 'group' => "varchar(255) DEFAULT ''", 'key_id' => "varchar(255) DEFAULT ''", 'language' => "varchar(255) DEFAULT ''", 'last_cached_credential' => "varchar(255) DEFAULT ''", 'last_error' => "int(10) DEFAULT 0", 'last_event' => "int(10) DEFAULT -1", 'last_failed_credential' => "varchar(255) DEFAULT ''", 'last_failed_time' => "int(10) DEFAULT 0", 'last_login' => "int(10) DEFAULT 0", 'last_login_for_cache' => "int(10) DEFAULT 0", 'last_success_credential' => "varchar(255) DEFAULT ''", 'last_update' => "int(10) DEFAULT 0", 'ldap_hash_cache' => "varchar(255) DEFAULT ''", 'ldap_hash_validity' => "int(10) DEFAULT 0", 'locked' => "int(1) DEFAULT 0", 'multi_account' => "int(1) DEFAULT 0", 'number_of_digits' => "int(10) DEFAULT 6", 'private_id' => "varchar(255) DEFAULT ''", 'request_ldap_pwd' => "int(1) DEFAULT 0", 'request_prefix_pin' => "int(1) DEFAULT 0", 'scratch_passwords' => "text", 'seed_password' => "varchar(255) DEFAULT ''", 'sms' => "varchar(255) DEFAULT ''", 'sms_otp' => "varchar(255) DEFAULT ''", 'sms_validity' => "int(10) DEFAULT 0", 'synchronized' => "int(1) DEFAULT 0", 'synchronized_channel' => "varchar(255) DEFAULT ''", 'synchronized_dn' => "varchar(255) DEFAULT ''", 'synchronized_server' => "varchar(255) DEFAULT ''", 'synchronized_time' => "int(10) DEFAULT 0", 'time_interval' => "int(10) DEFAULT 0", 'token_algo_suite' => "varchar(255) DEFAULT ''", 'token_seed' => "varchar(255) DEFAULT '3132333435363738393031323334353637383930'", 'token_serial' => "varchar(255) DEFAULT ''", 'user' => "varchar(255) DEFAULT ''", 'user_last_login' => "int(10) DEFAULT 0", 'user_pin' => "varchar(255) DEFAULT ''", 'encryption_hash' => "varchar(255) DEFAULT ''"); $this->_sql_tables_index['users'] = '*attributed_tokens*desactivated*locked*user*'; $this->_sql_tables_ignore['users'] = "**"; $this->_sql_tables_not_in_schema['users'] = array( 'delayed_account', 'delayed_time', 'delayed_finished'); if ("" == $encryption_key) { $this->_encryption_key = 'MuLtIoTpEnCrYpTiOn'; } else { $this->_encryption_key = $encryption_key; } $current_dir = $base_dir; if ("" == $current_dir) { $env_folder_path = getenv('MULTIOTP_PATH'); if (false !== $env_folder_path) { $current_dir = $env_folder_path; } } $this->SetBaseDir($current_dir); if ("" != trim($config_dir)) { $this->SetConfigFolder($config_dir, true, false); } $this->_parser_pointers = array(); $this->_hash_salt = 'MySalt'; $this->_random_salt = "Random"; $this->_source_tag = ""; $this->_source_ip = ""; $this->_source_mac = ""; $this->_calling_ip = ""; $this->_calling_mac = ""; $this->_chap_challenge = ""; $this->_chap_id = ""; $this->_chap_password = ""; $this->_ms_nt_key = ""; $this->_encryption_check = true; $this->_user = ""; $this->_user_data_read_flag = false; $this->_users_folder = ""; $this->_last_ldap_error = false; $this->_log_file_name = 'multiotp.log'; $this->_log_flag = false; $this->_log_folder = ""; $this->_log_verbose_flag = false; $this->_log_display_flag = false; $this->_mysql_database_link = NULL; $this->_mysqli = NULL; $this->_pgsql_database_link = NULL; $this->_migration_from_file = false; $this->_reply_array_for_radius = array(); $this->_servers_temp_bad_list = array(); $this->_initialize_backend = $initialize_backend; $this->_debug_via_html = false; $this->_linux_file_mode = ""; $this->_last_http_status = 0; $this->_bad_syslog_server = false; $this->ReadConfigData(true); if (("" == $encryption_key) || ('MuLtIoTpEnCrYpTiOn' == $encryption_key) || ('DefaultCliEncryptionKey' == $encryption_key)) { if (("" != $this->GetEncryptionKeyFullPath()) && file_exists($this->GetEncryptionKeyFullPath())) { if ($encryption_key_file_handler = @fopen($this->GetEncryptionKeyFullPath(), "rt")) { $temp_encryption_key = trim(fgets($encryption_key_file_handler)); if ("" != $temp_encryption_key) { $this->SetEncryptionKey($temp_encryption_key, false); } fclose($encryption_key_file_handler); } } } $this->_server_challenge = $this->GetEncryptionKey(); $this->_keep_local = false; $this->_xml_dump_in_log = false; $this->_sms_providers_array = array(array("aspsms", "aspsms", "http://www.aspsms.com/"), array("clickatell", "Clickatell", "http://www.clickatell.com/"), array("intellisms", "IntelliSMS", "http://www.intellisms.co.uk/") ); $this->SetLinuxFileMode('0666'); $this->SetLinuxFolderMode('0777'); $this->ResetErrorsArray(); $this->ResetConfigArray(); $this->ResetDeviceArray(); $this->ResetGroupArray(); $this->ResetUserArray(); $this->ResetTokenArray(); $this->ReadConfigData(); $this->ResetCacheArray(); if ($this->IsCacheData()) { $this->ReadCacheData(); } } function __destruct() { } function SetLastFailedWhiteDelay( $delay ) { $this->_config_data['last_failed_white_delay'] = $delay; } function GetLastFailedWhiteDelay() { return $this->_config_data['last_failed_white_delay']; } function SetLdapRecursiveGroups($value) { $this->_config_data['ldap_recursive_groups'] = ((intval($value) > 0)?1:0); } function SetLdapCacheOn($value) { $this->_config_data['ldap_cache_on'] = ((intval($value) > 0)?1:0); } function SetLdapRecursiveCacheOnly($value) { $this->_config_data['ldap_recursive_cache_only'] = ((intval($value) > 0)?1:0); } function SetLdapCacheFolder($value) { $folder = $value; if ($this->ConvertToWindowsPathIfNeeded(sys_get_temp_dir()."/") == $value) { $folder = "tempdir"; } $this->_config_data['ldap_cache_folder'] = trim($folder); } function IsLdapRecursiveGroups() { return (1 == $this->_config_data['ldap_recursive_groups']); } function IsLdapCacheOn() { return (1 == $this->_config_data['ldap_cache_on']); } function IsLdapRecursiveCacheOnly() { return (1 == $this->_config_data['ldap_recursive_cache_only']); } function GetLdapCacheFolder() { $folder = trim($this->_config_data['ldap_cache_folder']); if ("tempdir" == $folder) { $folder = $this->ConvertToWindowsPathIfNeeded(sys_get_temp_dir()."/"); } if (file_exists($folder) && touch($folder."test.cache")) { unlink($folder."test.cache"); if (!file_exists($folder.".ldap_cache/")) { if (@mkdir( $folder.".ldap_cache/", ('' != $this->GetLinuxFolderMode()) ? octdec($this->GetLinuxFolderMode()) : 0777, true )) { if ($this->GetVerboseFlag()) { $this->WriteLog("Debug: *LDAP cache folder created (".$folder.".ldap_cache/".")", FALSE, FALSE, 8888, 'System', ''); } } } if (file_exists($folder.".ldap_cache/") && touch($folder.".ldap_cache/test.cache")) { unlink($folder.".ldap_cache/test.cache"); $folder = $folder.".ldap_cache/"; } } else { $folder = ""; } if ($this->GetVerboseFlag()) { $this->WriteLog("Debug: *LDAP cache folder value: $folder", FALSE, FALSE, 8888, 'System', ''); } return $folder; } function EncodeForBackend($value) { $encoding = strtolower($this->GetBackendEncoding()); if (("utf-8" == $encoding) || ("utf8" == $encoding)) { $result = encode_utf8_if_needed($value); } else { $result = decode_utf8_if_needed($value); } return $result; } function SetBackendEncoding( $encoding ) { $this->_config_data['backend_encoding'] = $encoding; } function GetBackendEncoding() { return $this->_config_data['backend_encoding']; } function SetDeviceGroups( $first_param, $second_param = "*-*" ) { $result = ""; if ($second_param == "*-*") { $result = $first_param; } else { $this->SetDevice($first_param); $result = $second_param; } $this->_device_data['device_groups'] = $result; return $result; } function GetDeviceGroups( $device = '' ) { if($device != '') { $this->SetDevice($device); } return $this->_device_data['device_groups']; } function SetDeviceMultipleGroups( $first_param, $second_param = "*-*" ) { $value = ""; if ($second_param == "*-*") { $value = $first_param; } else { $this->SetDevice($first_param); $value = $second_param; } $this->_device_data['multiple_groups'] = intval($value); return $value; } function GetDeviceMultipleGroups( $device = '' ) { if($device != '') { $this->SetDevice($device); } return intval($this->_device_data['multiple_groups']); } function EnableDeviceMultipleGroups( $device = '' ) { if($device != '') { $this->SetDevice($device); } $this->_device_data['multiple_groups'] = 1; } function DisableDeviceMultipleGroups( $device = '' ) { if($device != '') { $this->SetDevice($device); } $this->_device_data['multiple_groups'] = 0; } function IsDeviceMultipleGroupsEnabled( $device = '' ) { if($device != '') { $this->SetDevice($device); } return (1 == ($this->_device_data['multiple_groups'])); } function SetMultipleGroups( $value ) { $this->_config_data['multiple_groups'] = ((intval($value) > 0)?1:0); } function EnableMultipleGroups() { $this->_config_data['multiple_groups'] = 1; } function DisableMultipleGroups() { $this->_config_data['multiple_groups'] = 0; } function IsMultipleGroupsEnabled() { return (1 == ($this->_config_data['multiple_groups'])); } function SetUserDialinIpAddress( $first_param, $second_param = "*-*" ) { $result = TRUE; $value = ""; if ($second_param == "*-*") { $value = $first_param; } else { $result = $this->SetUser($first_param); $value = $second_param; } $this->_user_data['dialin_ip_address'] = $value; return $result; } function GetUserDialinIpAddress( $user = '' ) { if($user != '') { $this->SetUser($user); } return $this->_user_data['dialin_ip_address']; } function SetUserDialinIpMask( $first_param, $second_param = "*-*" ) { $result = TRUE; $value = ""; if ($second_param == "*-*") { $value = $first_param; } else { $result = $this->SetUser($first_param); $value = $second_param; } $this->_user_data['dialin_ip_mask'] = $value; return $result; } function GetUserDialinIpMask( $user = '' ) { if($user != '') { $this->SetUser($user); } return $this->_user_data['dialin_ip_mask']; } function SetDefaultDialinIpMask($ip_mask) { $this->_config_data['default_dialin_ip_mask'] = $ip_mask; return TRUE; } function GetDefaultDialinIpMask() { return $this->_config_data['default_dialin_ip_mask']; } function SetLastHttpStatus($status = 200) { $this->_last_http_status = intval($status); } function GetLastHttpStatus() { return intval($this->_last_http_status); } function SetLockTime($value) { $this->_lock_time = trim($value); } function GetLockTime() { return trim($this->_lock_time); } function SetLdapSyncStopFileName($value) { $this->_ldap_sync_stop_file_name = trim($value); } function GetLdapSyncStopFileName() { return trim($this->_ldap_sync_stop_file_name); } function SetLdapSyncLockFileName($value) { $this->_ldap_sync_lock_file_name = trim($value); } function GetLdapSyncLockFileName() { return trim($this->_ldap_sync_lock_file_name); } function SetLockFolder($value) { $this->_lock_folder = trim($value); } function GetLockFolder() { return trim($this->_lock_folder); } function PurgeLockFolder() { $actual_folder = $this->GetLockFolder(); $actual_filter = "multiotp-*.lock"; if (($actual_dir = opendir($actual_folder)) !== FALSE) { while(($actual_file_name = readdir($actual_dir)) !== FALSE) { if (fnmatch($actual_filter, $actual_file_name)) { $actual_file = $actual_folder.$actual_file_name; unlink($actual_file); } } } return TRUE; } function PurgeLdapCacheFolder() { $actual_filter = "ldap_*.cache"; $actual_folder = $this->GetLdapCacheFolder(); if (($actual_dir = opendir($actual_folder)) !== FALSE) { while(($actual_file_name = readdir($actual_dir)) !== FALSE) { if (fnmatch($actual_filter, $actual_file_name)) { $actual_file = $actual_folder.$actual_file_name; unlink($actual_file); } } } $actual_folder = $this->ConvertToWindowsPathIfNeeded(sys_get_temp_dir()."/"); if (($actual_dir = opendir($actual_folder)) !== FALSE) { while(($actual_file_name = readdir($actual_dir)) !== FALSE) { if (fnmatch($actual_filter, $actual_file_name)) { $actual_file = $actual_folder.$actual_file_name; unlink($actual_file); } } } return TRUE; } function SetTouchSuffixArray($touch_suffix_array) { $this->_touch_suffix_array = $touch_suffix_array; return TRUE; } function GetTouchSuffixArray() { return ($this->_touch_suffix_array); } function SetTouchFolder($value) { $this->_touch_folder = trim($value); } function GetTouchFolder() { return trim($this->_touch_folder); } function PurgeTouchFolder() { $actual_folder = $this->GetTouchFolder(); if ("" != $actual_folder) { $actual_filter = "*.sync"; if (($actual_dir = opendir($actual_folder)) !== FALSE) { while(($actual_file_name = readdir($actual_dir)) !== FALSE) { if (fnmatch($actual_filter, $actual_file_name)) { $actual_file = $actual_folder.$actual_file_name; unlink($actual_file); } } } } return TRUE; } function TouchFolder( $type_fn = "", $item_fn = "", $id_fn = "", $folder_touched = TRUE, $touch_info = "" ) { $touch_suffix_array = $this->GetTouchSuffixArray(); if (('' != $this->GetTouchFolder()) && (0 < count($touch_suffix_array))) { if ($this->GetVerboseFlag()) { $this->WriteLog("Debug: *Touch element $type_fn $item_fn $id_fn", FALSE, FALSE, 8888, 'System', ''); } foreach ($touch_suffix_array as $one_touch_suffix) { $filename_path = $this->GetTouchFolder().bin2hex($type_fn."\t".$item_fn."\t".$id_fn.(("" != $one_touch_suffix) ? ("\t".$one_touch_suffix) : "")).".sync"; $result = touch($filename_path); if ($result && ('' != $this->GetLinuxFileMode())) { @chmod($filename_path, octdec($this->GetLinuxFileMode())); } } if ($folder_touched) { $this->FolderTouched($type_fn, $item_fn, $id_fn, $touch_info); } } } function FolderTouched( $type_fn = "", $item_fn = "", $id_fn = "", $touch_info = "") { } function UserRestoreBeforeWrite() { } function SetUserLanguage($value) { $this->_user_data['language'] = trim($value); } function GetUserLanguage($ignore_main_language = FALSE) { $language = trim($this->_user_data['language']); if (('' == $language) && (TRUE != $ignore_main_language)) { $language = $this->GetLanguage(); } return strtolower($language); } function SetLanguage($value) { $this->_config_data['language'] = trim($value); } function GetLanguage() { return strtolower(trim($this->_config_data['language'])); } function GetCustomInfo() { return ""; } function GetLibraryHash( $param1 = "", $param2 = "", $param3 = "" ) { if (file_exists(__FILE__)) { if ($me_handler = @fopen(__FILE__, "rt")) { $content = ""; while (!feof($me_handler)) { $content.= fgets($me_handler); } fclose($me_handler); $hash = md5($content); } } else { $hash = '00000000000000000000000000000000'; } $this->SendWeeklyAnonymousStat(); return ($hash); } function UpgradeSchemaIfNeeded() { if ($this->GetActualVersion() != $this->GetVersion()) { if ($this->InitializeBackend() < 20) { $this->SetActualVersion($this->GetVersion()); $this->WriteConfigData(); } } } function ResetErrorsArray() { $this->_errors_text[0] = "OK: Token accepted"; $this->_errors_text[10] = "INFO: Access Challenge returned back to the client"; $this->_errors_text[11] = "INFO: User successfully created or updated"; $this->_errors_text[12] = "INFO: User successfully deleted"; $this->_errors_text[13] = "INFO: User PIN code successfully changed"; $this->_errors_text[14] = "INFO: Token has been resynchronized successfully"; $this->_errors_text[15] = "INFO: Tokens definition file successfully imported"; $this->_errors_text[16] = "INFO: QRcode successfully created"; $this->_errors_text[17] = "INFO: UrlLink successfully created"; $this->_errors_text[18] = "INFO: SMS code request received"; $this->_errors_text[19] = "INFO: Requested operation successfully done"; $this->_errors_text[20] = "ERROR: User blacklisted"; $this->_errors_text[21] = "ERROR: User doesn't exist"; $this->_errors_text[22] = "ERROR: User already exists"; $this->_errors_text[23] = "ERROR: Invalid algorithm"; $this->_errors_text[24] = "ERROR: User locked (too many tries)"; $this->_errors_text[25] = "ERROR: User delayed (too many tries, but still a hope in a few minutes)"; $this->_errors_text[26] = "ERROR: This token has already been used"; $this->_errors_text[27] = "ERROR: Resynchronization of the token has failed"; $this->_errors_text[28] = "ERROR: Unable to write the changes in the file"; $this->_errors_text[29] = "ERROR: Token doesn't exist"; $this->_errors_text[30] = "ERROR: At least one parameter is missing"; $this->_errors_text[31] = "ERROR: Tokens definition file doesn't exist"; $this->_errors_text[32] = "ERROR: Tokens definition file not successfully imported"; $this->_errors_text[33] = "ERROR: Encryption hash error, encryption key is not matching"; $this->_errors_text[34] = "ERROR: Linked user doesn't exist"; $this->_errors_text[35] = "ERROR: User not created"; $this->_errors_text[36] = "ERROR: Token doesn't exist"; $this->_errors_text[37] = "ERROR: Token already attributed"; $this->_errors_text[38] = "ERROR: User is desactivated"; $this->_errors_text[39] = "ERROR: Requested operation aborted"; $this->_errors_text[40] = "ERROR: SQL query error"; $this->_errors_text[41] = "ERROR: SQL error"; $this->_errors_text[42] = "ERROR: They key is not in the table schema"; $this->_errors_text[43] = "ERROR: SQL entry cannot be updated"; $this->_errors_text[50] = "ERROR: QRcode not created"; $this->_errors_text[51] = "ERROR: UrlLink not created (no provisionable client for this protocol)"; $this->_errors_text[59] = "ERROR: Bad restore configuration password"; $this->_errors_text[60] = "ERROR: No information on where to send SMS code"; $this->_errors_text[61] = "ERROR: SMS code request received, but an error occurred during transmission"; $this->_errors_text[62] = "ERROR: SMS provider not supported"; $this->_errors_text[63] = "ERROR: This SMS code has expired"; $this->_errors_text[64] = "ERROR: Cannot resent an SMS code right now"; $this->_errors_text[69] = "ERROR: Failed to send email"; $this->_errors_text[70] = "ERROR: Server authentication error"; $this->_errors_text[71] = "ERROR: Server request is not correctly formatted"; $this->_errors_text[72] = "ERROR: Server answer is not correctly formatted"; $this->_errors_text[79] = "ERROR: AD/LDAP connection error"; $this->_errors_text[80] = "ERROR: Server cache error"; $this->_errors_text[81] = "ERROR: Cache too old for this user, account autolocked"; $this->_errors_text[88] = "ERROR: Device is not defined as a HA slave"; $this->_errors_text[89] = "ERROR: Device is not defined as a HA master"; $this->_errors_text[94] = "ERROR: API request error"; $this->_errors_text[95] = "ERROR: API authentication failed"; $this->_errors_text[96] = "ERROR: Authentication failed (CRC error)"; $this->_errors_text[97] = "ERROR: Authentication failed (wrong private id)"; $this->_errors_text[98] = "ERROR: Authentication failed (wrong token length)"; $this->_errors_text[99] = "ERROR: Authentication failed (and other possible unknown errors)"; } function GetErrorText( $error_number = 99 ) { $text = ""; if (isset($this->_errors_text[$error_number])) { $text = $this->_errors_text[$error_number]; } elseif (intval($error_number) > 0) { $text = $this->_errors_text[99]; } return $text; } function ResetCacheArray() { reset($this->_sql_tables_schema['cache']); while(list($valid_key, $valid_format) = @each($this->_sql_tables_schema['cache'])) { $pos = strpos(strtoupper($valid_format), 'DEFAULT'); $value = ""; if ($pos !== FALSE) { $value = trim(substr($valid_format, $pos + strlen("DEFAULT"))); if (("'" == substr($value,0,1)) && ("'" == substr($value,-1))) { $value = substr($value,1,-1); } } $this->_cache_data[$valid_key] = $value; } } function WriteData( $write_data_array = '', $table_param = '', $folder_param = '', $data_array_param = array(), $force_file_param = false, $id_field_param = '', $id_value_param = '', $id_case_sensitive_param = false, $automatically_param = false, $update_last_change_param = true, $no_encryption_hash_param = false ) { if (is_array($write_data_array)) { $item = isset($write_data_array['item'])?$write_data_array['item']:''; $table = isset($write_data_array['table'])?$write_data_array['table']:''; $folder = isset($write_data_array['folder'])?$write_data_array['folder']:''; $data_array = isset($write_data_array['data_array'])?$write_data_array['data_array']:array(); $force_file = isset($write_data_array['force_file'])?$write_data_array['force_file']:false; $id_field = isset($write_data_array['id_field'])?$write_data_array['id_field']:''; $id_value = isset($write_data_array['id_value'])?$write_data_array['id_value']:''; $id_case_sensitive = isset($write_data_array['id_case_sensitive'])?$write_data_array['id_case_sensitive']:false; $automatically = isset($write_data_array['automatically'])?$write_data_array['automatically']:false; $update_last_change = isset($write_data_array['update_last_change'])?$write_data_array['update_last_change']:true; $no_encryption_hash = isset($write_data_array['no_encryption_hash'])?$write_data_array['no_encryption_hash']:false; $encrypt_all = isset($write_data_array['encrypt_all'])?$write_data_array['encrypt_all']:false; $encryption_key = isset($write_data_array['encryption_key'])?$write_data_array['encryption_key']:''; $backup_file = isset($write_data_array['backup_file'])?$write_data_array['backup_file']:''; $raw_folder = isset($write_data_array['raw_folder'])?$write_data_array['raw_folder']:''; $raw_file = isset($write_data_array['raw_file'])?$write_data_array['raw_file']:''; $return_content = isset($write_data_array['return_content'])?$write_data_array['return_content']:false; $flush_attributes = isset($write_data_array['flush_attributes'])?$write_data_array['flush_attributes']:array(); $encode_file_id = isset($write_data_array['encode_file_id'])?$write_data_array['encode_file_id']:false; } else { $item = $write_data_array; $table = $table_param; $folder = $folder_param; $data_array = $data_array_param; $force_file = $force_file_param; $id_field = $id_field_param; $id_value = $id_value_param; $id_case_sensitive = $id_case_sensitive_param; $automatically = $automatically_param; $update_last_change = $update_last_change_param; $no_encryption_hash = $no_encryption_hash_param; $encrypt_all = false; $encryption_key = ''; $backup_file = ''; $raw_folder = ''; $raw_file = ''; $return_content = false; $flush_attributes = array(); } $backup_format = ('' != $backup_file); if ($backup_format) { $force_file = true; $folder = ''; } foreach($flush_attributes as $one_flush_attribute) { if (isset($data_array[$one_flush_attribute])) { $data_array[$one_flush_attribute] = ''; } } if ('' != $raw_file) { if (!file_exists($raw_folder.$raw_file)) { if ('' == $raw_folder) { $raw_folder = $folder; } } if (!file_exists($raw_folder.$raw_file)) { return false; } } $clean_raw_folder = str_replace($this->GetConfigFolder(), "--config-@-folder--", $raw_folder); if ('*CLEAR*' == $encryption_key) { $encryption_key = ''; } elseif ('' == $encryption_key) { $encryption_key = $this->GetEncryptionKey(); } $item_info = trim($item." ".$id_value); if ('group' == strtolower($item)) { $item_info = trim($item." ".(isset($data_array['name'])?$data_array['name']:$id_value)); } elseif ('device' == strtolower($item)) { $item_info = trim($item." ".(isset($data_array['description'])?$data_array['description']:(isset($data_array['ip_or_fqdn'])?$data_array['ip_or_fqdn']:$id_value))); } if ('configuration' == strtolower($item)) { $filename = 'multiotp.ini'; $force_file = true; } elseif ('cache' == strtolower($item)) { $filename = 'cache.ini'; } else { if ($encode_file_id) { $filename = $this->EncodeFileId($id_value, $this->IsCaseSensitiveUsers()).'.db'; } else { $filename = $id_value.'.db'; if (!$this->IsCaseSensitiveUsers()) { $filename = strtolower($filename); } } } if ($backup_format) { $filename = $backup_file; $item_info = "backup process"; } $now_epoch = time(); if ($update_last_change) { $data_array['last_update'] = $now_epoch; } $result = false; $item_created = FALSE; $data_array['encryption_hash'] = $this->CalculateControlHash($encryption_key); if($no_encryption_hash) { unset($data_array['encryption_hash']); } if ((($this->GetBackendTypeValidated()) && ((isset($this->_config_data['sql_'.$table.'_table'])) && ('' != $this->_config_data['sql_'.$table.'_table'])) ) || ('files' == $this->GetBackendType()) || $force_file || $backup_format ) { if (('files' == $this->GetBackendType()) || $force_file || $backup_format) { $file_time = $now_epoch; if (!$id_case_sensitive) { $filename = strtolower($filename); } $file_created = false; if ('@' != strtolower($filename)) { if (!file_exists($folder.$filename)) { $item_created = true; $file_created = true; } elseif ((!$update_last_change) && (!$file_created)) { $file_time = filemtime($folder.$filename); } if ($backup_format) { $file_handler = @fopen($folder.$filename,"ab+"); if (FALSE === $file_handler) { usleep(500000); $file_handler = @fopen($folder.$filename,"ab+"); } } else { $file_handler = @fopen($folder.$filename, "wt"); if (FALSE === $file_handler) { usleep(500000); $file_handler = @fopen($folder.$filename, "wt"); } } } else { $file_handler = TRUE; $return_content = TRUE; } $line = ""; if (FALSE === $file_handler) { $this->WriteLog("Error: database file for ".$item_info." cannot be written", FALSE, FALSE, 28, 'System', '', 3); } else { if ($backup_format) { if ($file_created) { $config_time = date("YmdHis"); $line.= "# CONFIGURATION /".$config_time."/".substr(md5($config_time.$encryption_key.$config_time),0,14)."/\n"; $line.= "; #!#multiotp-database-format-v3\n"; $line.= "; #!#timestamp=".time()."\n"; $line.= "; #!#encryption_hash=".$this->CalculateControlHash($encryption_key)."\n"; } $line.= "; #!#element-start#!#\n"; $line.= "; #!#element-timestamp=".time()."\n"; if (($backup_format) && ('' != $raw_file)) { $line.= "; #!#type=file\n"; $line.= "; #!#item=$clean_raw_folder\n"; $line.= "; #!#id_value=$raw_file\n"; } else { $line.= "; #!#type=data\n"; $line.= "; #!#item=$item\n"; $line.= "; #!#id_value=$id_value\n"; } } else { $line.= "multiotp-database-format-v3\n"; if ('configuration' == strtolower($item)) { $line.= "; If backend is set to something different than files,\n"; $line.= "; and backend_type_validated is set to 1,\n"; $line.= "; only the specific information needed for the backend\n"; $line.= "; is used from this config file.\n"; $line.= "\n"; } } if (($backup_format) && ('' != $raw_file)) { $key = "raw_data"; if ($raw_fn = @fopen($raw_folder.$raw_file, "rb")) { while(!feof($raw_fn)) { $line.= strtolower($key); $value = bin2hex(fread($raw_fn, 40)); if ($encrypt_all || ((!$no_encryption_hash) && ((FALSE !== strpos(strtolower($this->GetAttributesToEncrypt()), strtolower('*'.$key.'*'))) || ("*all*" == strtolower($this->GetAttributesToEncrypt()))) ) ) { $value = $this->Encrypt($key,$value,$encryption_key); $line.= ":"; } $line.= "=".$value."\n"; } fclose($raw_fn); } } else { reset($data_array); while(list($key, $value) = each($data_array)) { if ('' != trim($key)) { $line.= strtolower($key); if ($encrypt_all || ((!$no_encryption_hash) && ((FALSE !== strpos(strtolower($this->GetAttributesToEncrypt()), strtolower('*'.$key.'*'))) || ("*all*" == strtolower($this->GetAttributesToEncrypt()))) ) ) { $value = $this->Encrypt($key,$value,$encryption_key); $line.= ":"; } $line.= "=".$value."\n"; } } } if ($backup_format) { $line.= "; #!#element-stop#!#\n"; $line.= "; ##############################\n"; } if ('@' != strtolower($filename)) { fwrite($file_handler, $line); fclose($file_handler); } $result = $return_content ? $line : true; if ((!$update_last_change) && (!$file_created) && (!$backup_format)) { touch($folder.$filename, $file_time); } if ($file_created && ('' != $this->GetLinuxFileMode())) { @chmod($folder.$filename, octdec($this->GetLinuxFileMode())); } } if ($this->GetVerboseFlag()) { if ($file_created) { $this->WriteLog("Info: *File created: ".$folder.$filename, FALSE, FALSE, 8888, 'System', ''); } } } if ((!$backup_format) && ('mysql' == $this->GetBackendType())) { $esc_id_value = escape_mysql_string($id_value); if ($this->OpenMysqlDatabase()) { $result = TRUE; $sQi_Columns = ''; $sQi_Values = ''; $sQu_Data = ''; reset($data_array); while(list($key, $value) = each($data_array)) { $in_the_schema = FALSE; reset($this->_sql_tables_schema[$table]); $row_type = ""; while(list($valid_key, $valid_format) = each($this->_sql_tables_schema[$table])) { $row_type = ""; if ((strtolower(substr($valid_format, 0, 4)) == "int(") || (strtolower(substr($valid_format, 0, 8)) == "numeric(")) { $row_type = "int"; } elseif ((strtolower(substr($valid_format, 0, 8)) == "datetime") || (strtolower(substr($valid_format, 0, 9)) == "timestamp")) { $row_type = "datetime"; } if ($valid_key == $key) { $in_the_schema = TRUE; break; } } $not_in_the_schema = FALSE; if (isset($this->_sql_tables_not_in_schema[$table])) { reset($this->_sql_tables_not_in_schema[$table]); while(list($ignore_key, $ignore_format) = each($this->_sql_tables_not_in_schema[$table])) { if ($ignore_key == $key) { $not_in_the_schema = TRUE; break; } } } if (($in_the_schema) && ($key != $id_field)) { if (('' == trim($value)) && ("int" == $row_type)) { $value = 0; } if (($encrypt_all || ((!$no_encryption_hash) && ((FALSE !== strpos(strtolower($this->GetAttributesToEncrypt()), strtolower('*'.$key.'*'))) || ("*all*" == strtolower($this->GetAttributesToEncrypt()))) ) ) && ('' != $value) ) { $value = 'ENC:'.$this->Encrypt($key,$value,$encryption_key).':ENC'; } $value = escape_mysql_string($value); $sQu_Data .= "`{$key}`='{$value}',"; $sQi_Columns .= "`{$key}`,"; $sQi_Values .= "'{$value}',"; } elseif ((!$in_the_schema) && (!$not_in_the_schema) && ('unique_id' != $key) && $this->GetVerboseFlag()) { $this->WriteLog("Warning: *The key ".$key." is not in the $table table schema", FALSE, FALSE, 8888, 'System', ''); } } $num_rows = 0; $sQuery = "SELECT * FROM `".$this->_config_data['sql_'.$table.'_table']."`"; if ('' != $id_field) { $sQuery.= " WHERE `$id_field`='".$esc_id_value."'"; } if (is_object($this->_mysqli)) { if (!($result = @$this->_mysqli->query($sQuery))) { $this->WriteLog("Error: SQL query error ".trim($this->_mysqli->error)." ".$sQuery, TRUE, FALSE, 40, 'System', '', 3); } else { $num_rows = $result->num_rows; } } elseif (!($result = @mysql_query($sQuery, $this->_mysql_database_link))) { $this->WriteLog("Error: SQL query error ($sQuery) : ".mysql_error(), TRUE, FALSE, 40, 'System', '', 3); } else { $num_rows = mysql_num_rows($result); } if ($num_rows > 0) { $sQuery = "UPDATE `".$this->_config_data['sql_'.$table.'_table']."` SET ".substr($sQu_Data,0,-1); if ('' != $id_field) { $sQuery.= " WHERE `$id_field`='".$esc_id_value."'"; } if (is_object($this->_mysqli)) { if (!($rResult = @$this->_mysqli->query($sQuery))) { $this->WriteLog("Error: SQL query error ".trim($this->_mysqli->error)." ".$sQuery, TRUE, FALSE, 40, 'System', '', 3); $result = FALSE; } } elseif (!($rResult = @mysql_query($sQuery, $this->_mysql_database_link))) { $this->WriteLog("Error: SQL query error ($sQuery) : ".mysql_error(), TRUE, FALSE, 40, 'System', '', 3); $result = FALSE; } } else { if ('' != $id_field) { $sQuery = "INSERT INTO `".$this->_config_data['sql_'.$table.'_table']."` (`$id_field`,".substr($sQi_Columns,0,-1).") VALUES ('".$esc_id_value."',".substr($sQi_Values,0,-1).")"; } else { $sQuery = "INSERT INTO `".$this->_config_data['sql_'.$table.'_table']."` (".substr($sQi_Columns,0,-1).") VALUES (".substr($sQi_Values,0,-1).")"; } if (is_object($this->_mysqli)) { if (!($rResult = @$this->_mysqli->query($sQuery))) { $this->WriteLog("Error: SQL query error ".trim($this->_mysqli->error)." ".$sQuery, TRUE, FALSE, 40, 'System', '', 3); } elseif (0 == $this->_mysqli->affected_rows) { $this->WriteLog("Error: SQL entry for ".$item_info." cannot be created or changed", FALSE, FALSE, 43, 'System', '', 3); $result = FALSE; } else { $item_created = TRUE; } } elseif (!($rResult = @mysql_query($sQuery, $this->_mysql_database_link))) { $this->WriteLog("Error: SQL query error ($sQuery) : ".mysql_error(), TRUE, FALSE, 40, 'System', '', 3); $result = FALSE; } elseif (0 == mysql_affected_rows($this->_mysql_database_link)) { $this->WriteLog("Error: SQL entry for ".$item_info." cannot be created or changed", FALSE, FALSE, 43, 'System', '', 3); $result = FALSE; } else { $item_created = TRUE; } } } } elseif ((!$backup_format) && ('pgsql' == $this->GetBackendType())) { $esc_id_value = pg_escape_string($id_value); if ($this->OpenPGSQLDatabase()) { $result = TRUE; $sQi_Columns = ''; $sQi_Values = ''; $sQu_Data = ''; reset($data_array); while(list($key, $value) = each($data_array)) { $in_the_schema = FALSE; reset($this->_sql_tables_schema[$table]); $row_type = ""; while(list($valid_key, $valid_format) = each($this->_sql_tables_schema[$table])) { $row_type = ""; if ((strtolower(substr($valid_format, 0, 4)) == "int(") || (strtolower(substr($valid_format, 0, 8)) == "numeric(")) { $row_type = "int"; } elseif ((strtolower(substr($valid_format, 0, 8)) == "datetime") || (strtolower(substr($valid_format, 0, 9)) == "timestamp")) { $row_type = "datetime"; } if ($valid_key == $key) { $in_the_schema = TRUE; break; } } $not_in_the_schema = FALSE; if (isset($this->_sql_tables_not_in_schema[$table])) { reset($this->_sql_tables_not_in_schema[$table]); while(list($ignore_key, $ignore_format) = each($this->_sql_tables_not_in_schema[$table])) { if ($ignore_key == $key) { $not_in_the_schema = TRUE; break; } } } if (($in_the_schema) && ($key != $id_field)) { if (('' == trim($value)) && ("int" == $row_type)) { $value = 0; } if (($encrypt_all || ((!$no_encryption_hash) && ((FALSE !== strpos(strtolower($this->GetAttributesToEncrypt()), strtolower('*'.$key.'*'))) || ("*all*" == strtolower($this->GetAttributesToEncrypt()))) ) ) && ('' != $value) ) { $value = 'ENC:'.$this->Encrypt($key,$value,$encryption_key).':ENC'; } $value = pg_escape_string($value); $sQu_Data .= "\"{$key}\" = '{$value}',"; $sQi_Columns .= "\"{$key}\","; $sQi_Values .= "'{$value}',"; } elseif ((!$in_the_schema) && (!$not_in_the_schema) && ('unique_id' != $key) && $this->GetVerboseFlag()) { $this->WriteLog("Warning: *The key ".$key." is not in the $table table schema", FALSE, FALSE, 8888, 'System', ''); } } $num_rows = 0; $sQuery = "SELECT * FROM \"".$this->_config_data['sql_schema']."\".\"".$this->_config_data['sql_'.$table.'_table']."\""; if ('' != $id_field) { $sQuery.= " WHERE \"".$id_field."\" = '".$esc_id_value."'"; } if (!($result = @pg_query($this->_pgsql_database_link, $sQuery))) { $this->WriteLog("Error: SQL query error ($sQuery) : ".pg_last_error(), TRUE, FALSE, 40, 'System', '', 3); } else { $num_rows = pg_num_rows($result); } if ($num_rows > 0) { $sQuery = "UPDATE \"".$this->_config_data['sql_schema']."\".\"".$this->_config_data['sql_'.$table.'_table']."\" SET ".substr($sQu_Data,0,-1); if ('' != $id_field) { $sQuery.= " WHERE \"".$id_field."\" = '".$esc_id_value."'"; } if (!($rResult = @pg_query($this->_pgsql_database_link, $sQuery))) { $this->WriteLog("Error: SQL query error ($sQuery) : ".pg_last_error(), TRUE, FALSE, 40, 'System', '', 3); $result = FALSE; } } else { if ('' != $id_field) { $sQuery = "INSERT INTO \"".$this->_config_data['sql_schema']."\".\"".$this->_config_data['sql_'.$table.'_table']."\" (\"".$id_field."\",".substr($sQi_Columns,0,-1).") VALUES ('".$esc_id_value."',".substr($sQi_Values,0,-1).")"; } else { $sQuery = "INSERT INTO \"".$this->_config_data['sql_schema']."\".\"".$this->_config_data['sql_'.$table.'_table']."\" (".substr($sQi_Columns,0,-1).") VALUES (".substr($sQi_Values,0,-1).")"; } if (!($rResult = @pg_query($this->_pgsql_database_link, $sQuery))) { $this->WriteLog("Error: SQL query error ($sQuery) : ".pg_last_error(), TRUE, FALSE, 40, 'System', '', 3); $result = FALSE; } elseif (0 == pg_affected_rows($rResult)) { $this->WriteLog("Error: SQL entry for ".$item_info." cannot be created or changed", FALSE, FALSE, 43, 'System', '', 3); $result = FALSE; } else { $item_created = TRUE; } } } } } if (!$backup_format) { if ($item_created && $result) { if ($automatically) { $this->WriteLog("Info: ".$item_info." automatically created", FALSE, FALSE, 19, 'System', ''); } else { $this->WriteLog("Info: ".$item_info." manually created", FALSE, FALSE, 19, 'System', ''); } } } if ((!$backup_format) && ($update_last_change) && ('cache' != strtolower($item))) { $this->TouchFolder(('' != $raw_file) ? 'file' : 'data', ('' != $raw_file) ? $clean_raw_folder : $item, ('' != $raw_file) ? $raw_file : $id_value, TRUE, "WriteData"); } return $result; } function ReadCacheValue( $key ) { return ((isset($this->_cache_data[$key]))?$this->_cache_data[$key]:""); } function WriteCacheValue( $key, $value ) { $this->_cache_data[$key] = $value; } function ReadCacheData() { $this->ResetCacheArray(); $result = false; if (('files' == $this->GetBackendType()) || ($this->GetMigrationFromFile())) { $cache_filename = 'cache.ini'; if (file_exists($this->GetCacheFolder().$cache_filename)) { if ($file_handler = @fopen($this->GetCacheFolder().$cache_filename, "rt")) { $first_line = trim(fgets($file_handler)); while (!feof($file_handler)) { $line = str_replace(chr(10), "", str_replace(chr(13), "", fgets($file_handler))); $line_array = explode("=",$line,2); if (('#' != substr($line, 0, 1)) && (';' != substr($line, 0, 1)) && ("" != trim($line)) && (isset($line_array[1]))) { if ("" != $line_array[0]) { $this->_cache_data[strtolower($line_array[0])] = $line_array[1]; } } } fclose($file_handler); $result = TRUE; } } } if ($this->GetBackendTypeValidated()) { switch ($this->GetBackendType()) { case 'mysql': if ($this->OpenMysqlDatabase()) { if ("" != $this->_config_data['sql_cache_table']) { $sQuery = "SELECT * FROM `".$this->_config_data['sql_cache_table']."` "; $aRow = NULL; if (is_object($this->_mysqli)) { if (!($result = $this->_mysqli->query($sQuery))) { $this->WriteLog("Error: ".trim($this->_mysqli->error)." ".$sQuery, TRUE, FALSE, 41, 'System', '', 3); $result = FALSE; } else { $aRow = $result->fetch_assoc(); } } else { if (!($rResult = mysql_query($sQuery, $this->_mysql_database_link))) { $this->WriteLog("Error: ".mysql_error()." ".$sQuery, TRUE, FALSE, 41, 'System', '', 3); $result = FALSE; } else { $aRow = mysql_fetch_assoc($rResult); } } if (NULL != $aRow) { $result = TRUE; while(list($key, $value) = @each($aRow)) { $in_the_schema = FALSE; reset($this->_sql_tables_schema['cache']); while(list($valid_key, $valid_format) = @each($this->_sql_tables_schema['cache'])) { if ($valid_key == $key) { $in_the_schema = TRUE; break; } } if ($in_the_schema) { $this->_cache_data[$key] = $value; } elseif (('unique_id' != $key) && $this->GetVerboseFlag()) { $this->WriteLog("Warning: *the key ".$key." is not in the cache database schema", FALSE, FALSE, 8888, 'System', ''); } } } } } break; case 'pgsql': if ($this->OpenPGSQLDatabase()) { if ("" != $this->_config_data['sql_cache_table']) { $sQuery = "SELECT * FROM \"".$this->_config_data['sql_schema']."\".\"".$this->_config_data['sql_cache_table']."\" "; $aRow = NULL; if (!($rResult = pg_query($this->_pgsql_database_link, $sQuery))) { $this->WriteLog("Error: ".pg_last_error()." ".$sQuery, TRUE, FALSE, 41, 'System', '', 3); $result = FALSE; } else { $aRow = pg_fetch_assoc($rResult); } if (NULL != $aRow) { $result = TRUE; while(list($key, $value) = @each($aRow)) { $in_the_schema = FALSE; reset($this->_sql_tables_schema['cache']); while(list($valid_key, $valid_format) = @each($this->_sql_tables_schema['cache'])) { if ($valid_key == $key) { $in_the_schema = TRUE; break; } } if ($in_the_schema) { $this->_cache_data[$key] = $value; } elseif (('unique_id' != $key) && $this->GetVerboseFlag()) { $this->WriteLog("Warning: *the key ".$key." is not in the cache database schema", FALSE, FALSE, 8888, 'System', ''); } } } } } break; default: break; } } if (((24*60*60) + intval($this->_cache_data['last_update'])) < time()) { $this->ResetCacheArray(); $this->WriteCacheData(); } return $result; } function WriteCacheData( $write_cache_data_array = array() ) { $result = $this->WriteData(array_merge(array('item' => 'Cache', 'table' => 'cache', 'folder' => $this->GetCacheFolder(), 'data_array' => $this->_cache_data ), $write_cache_data_array)); return $result; } function ResetConfigArray($array_to_reset = '') { if (!is_array($array_to_reset)) { $array_to_reset = $this->_sql_tables_schema['config']; } reset($array_to_reset); while(list($valid_key, $valid_format) = @each($array_to_reset)) { $pos = strpos(strtoupper($valid_format), 'DEFAULT'); $value = ""; if ($pos !== FALSE) { $value = trim(substr($valid_format, $pos + strlen("DEFAULT"))); if (("'" == substr($value,0,1)) && ("'" == substr($value,-1))) { $value = substr($value,1,-1); } } $this->_config_data[$valid_key] = $value; } } function SetAnonymousStat( $value ) { $this->_config_data['anonymous_stat'] = ((intval($value) > 0)?1:0); } function EnableAnonymousStat() { $this->_config_data['anonymous_stat'] = 1; } function DisableAnonymousStat() { $this->_config_data['anonymous_stat'] = 0; } function IsAnonymousStat() { return (1 == ($this->_config_data['anonymous_stat'])); } function IsAnonymousStatTime() { return ($this->IsAnonymousStat() && (0 != $this->GetAnonymousStatInterval()) && (time() > ($this->GetAnonymousStatLastUpdate() + $this->GetAnonymousStatInterval()))); } function GetAnonymousStatRandomId() { $result = trim($this->_config_data['anonymous_stat_random_id']); if ('' == $result) { $result = substr(md5(date("YmdHis").mt_rand(100000,999999)),0,20).substr(sha1(mt_rand(100000,999999).date("YmdHis")),0,20); $this->_config_data['anonymous_stat_random_id'] = $result; } return ($result); } function GetAnonymousStatLastUpdate() { return intval($this->_config_data['anonymous_stat_last_update']); } function UpdateAnonymousStatLastUpdate() { $this->_config_data['anonymous_stat_last_update'] = time(); } function GetAnonymousStatInterval() { return ($this->_anonymous_stat_interval); } function SendWeeklyAnonymousStat() { if ($this->IsAnonymousStatTime()) { $result_stats = FALSE; $stats_array = array(); $stats_array['id'] = sha1($this->GetAnonymousStatRandomId().$this->GetClassName()); $stats_array['backend_type'] = $this->GetBackendType(); $stats_array['class_name'] = $this->GetClassName(); $stats_array['ldap_cn_identifier'] = $this->GetLdapCnIdentifier(); $stats_array['ldap_enabled'] = ('' != $this->GetLdapDomainControllers()); $stats_array['ldap_sync_user_attribute'] = $this->GetLdapSyncedUserAttribute(); $stats_array['os'] = php_uname(); if ($this->GetCliProxyMode()) { $stats_array['os'].= " [CLI PROXY]"; } elseif ($this->GetCliMode()) { $stats_array['os'].= " [CLI]"; } $stats_array['php'] = phpversion(); $stats_array['tokens'] = intval($this->GetTokensCount()); $stats_array['users'] = intval($this->GetUsersCount()); $stats_array['version_date'] = $this->GetVersionDate(); $stats_public_key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtfZPCfqhemvRagng961LMbBHKVb2B3uSUsWlkcOqu5EuXfRIyIqurJR7vigJ0GMu4zMvrBilQQYegCjXtceo03mGSthAJ+6rTZ9Qvlu7GY0CUgUCranZ8Ckw8EXdEiUNTdgK1pKm6kef+wK4wc3V/sU+XYo8gbMbH9C5YsG/XUon4hPx+FSuNNU1IX/GhTcHo7Tmc5+kZZw4ImCGAsrXO/N4qYcn9Y11HceKiRyglAdRoBhM/pbhzl1rgSVxnfUu6R0NBDWRVW8l3NMkp1He8ugzP5dca2cdBYdIgslNKQwzGccWsxDEAkK1Q6htjmQ85g+qv2hiShEpOI/EiWw3uwIDAQAB"; $rsa = new Crypt_RSA(); $rsa->loadKey($stats_public_key); $rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_OAEP); $encoded_stats_value = urlencode(base64_encode($rsa->encrypt(json_encode($stats_array)))); $result_stats = $this->PostHttpDataXmlRequest($encoded_stats_value, "http://stats.multiotp.net/", 5); $this->UpdateAnonymousStatLastUpdate(); $this->WriteConfigData(); } } function BackupConfiguration( $bc_array = array() ) { @set_time_limit(0); clearstatcache(); $bc_array['backup_file'] = isset($bc_array['backup_file']) ? $bc_array['backup_file']:"@"; $bc_array['encryption_key'] = isset($bc_array['encryption_key']) ? $bc_array['encryption_key']:''; $bc_array['return_content'] = isset($bc_array['return_content']) ? $bc_array['return_content']:FALSE; $bc_array['encrypt_all'] = isset($bc_array['encrypt_all']) ? $bc_array['encrypt_all']:TRUE; $bc_array['config_only'] = isset($bc_array['config_only']) ? $bc_array['config_only']:FALSE; $bc_array['no_encryption_hash'] = TRUE; $bc_array['update_last_change'] = FALSE; if (('' == $bc_array['backup_file']) || ('@' == $bc_array['backup_file'])) { $bc_array['backup_file'] = "@"; $bc_array['return_content'] = TRUE; } else { if (file_exists($bc_array['backup_file'])) { unlink($bc_array['backup_file']); } } $backup_time = time(); $backup_content = ''; $result = TRUE; $content = $this->WriteConfigData($bc_array); $result = $result && ($content !== FALSE); $backup_content.= (is_bool($content)?"":$content); if (!$bc_array['config_only']) { foreach (explode("\t", $this->GetDevicesList()) as $one_device) { if ('' != trim($one_device)) { if ($this->ReadDeviceData($one_device)) { $content = $this->WriteDeviceData(array_merge($bc_array, array("with_radius_update" => FALSE))); $result = $result && ($content !== FALSE); $backup_content.= (is_bool($content)?"":$content); } } } foreach (explode("\t", $this->GetGroupsList()) as $one_group) { if ('' != trim($one_group)) { if ($this->ReadGroupData($one_group)) { $content = $this->WriteGroupData($bc_array); $result = $result && ($content !== FALSE); $backup_content.= (is_bool($content)?"":$content); } } } foreach (explode("\t", $this->GetTokensList()) as $one_token) { if ('' != trim($one_token)) { if ($this->ReadTokenData($one_token)) { $content = $this->WriteTokenData($bc_array); $result = $result && ($content !== FALSE); $backup_content.= (is_bool($content)?"":$content); } } } $user_array = $this->GetNextUserArray(TRUE); while (FALSE !== $user_array) { if (isset($user_array['user'])) { if ($this->ReadUserData($user_array['user'], FALSE, TRUE)) { $content = $this->WriteUserData($bc_array); $result = $result && ($content !== FALSE); $backup_content.= (is_bool($content)?"":$content); } } $user_array = $this->GetNextUserArray(); } } return ($bc_array['return_content']?($result?$backup_content:FALSE):$result); } function RestoreConfiguration( $rc_array = array() ) { $backup_file = isset($rc_array['backup_file']) ? $rc_array['backup_file'] : ''; $restore_key = isset($rc_array['restore_key']) ? $rc_array['restore_key'] : ''; $ignore_attributes = isset($rc_array['ignore_attributes']) ? $rc_array['ignore_attributes'] : array(); $ignore_files = isset($rc_array['ignore_files']) ? $rc_array['ignore_files'] : array(); $rename_files = isset($rc_array['rename_files']) ? $rc_array['rename_files'] : array(); $update_config = isset($rc_array['update_config']) ? (TRUE === $rc_array['update_config']) : FALSE; $ignore_config = isset($rc_array['ignore_config']) ? (TRUE === $rc_array['ignore_config']) : FALSE; $automatically = isset($rc_array['automatically']) ? (TRUE === $rc_array['automatically']) : FALSE; if (!is_array($ignore_attributes)) { $ignore_attributes = array('multiotp-database-format', 'actual_version', 'anonymous_'); } else { $ignore_attributes = array_merge($ignore_attributes, array('multiotp-database-format', 'actual_version', 'anonymous_')); } if (!is_array($rename_files)) { $rename_files = array(); } if ('*CLEAR*' == $restore_key) { $restore_key = ''; } elseif ('' == $restore_key) { $restore_key = $this->GetEncryptionKey(); } $type = ''; $item = ''; $id_value = ''; $deleted = FALSE; $file_handler = FALSE; $data_array = array(); $validity = TRUE; $result = TRUE; if (file_exists($backup_file)) { if ($backup_handler = @fopen($backup_file, "rt")) { $first_line = TRUE; $line = str_replace(chr(10), "", str_replace(chr(13), "", fgets($backup_handler))); if (0 === strpos($line, '# CONFIGURATION')) { $first_line = FALSE; $validity_array = explode("/", $line."///"); $check_validity = substr(md5($validity_array[1].$restore_key.$validity_array[1]),0,14); if ($validity_array[2] != $check_validity) { $this->WriteLog("Error: Bad restore configuration password", FALSE, FALSE, 59, 'System', '', 3); $result = FALSE; } } while ((!feof($backup_handler)) && $result) { if ($first_line) { $first_line = FALSE; } else { $line = str_replace(chr(10), "", str_replace(chr(13), "", fgets($backup_handler))); } if (0 === strpos($line, '; #!#')) { $config_line = substr($line, 5); $config_line_array = explode("=",$config_line,2); $config_command = isset($config_line_array[0]) ? $config_line_array[0] : ''; $config_parameter = isset($config_line_array[1]) ? $config_line_array[1] : ''; if (0 === strpos ($config_command, 'element-start')) { $type = ''; $item = ''; $id_value = ''; $deleted = FALSE; $file_handler = FALSE; $data_array = array(); } elseif (0 === strpos ($config_command, 'type')) { $type = $config_parameter; } elseif (0 === strpos ($config_command, 'item')) { $item = $config_parameter; $item = str_replace("--config-@-folder--", $this->GetConfigFolder(), $item); } elseif (0 === strpos ($config_command, 'id_value')) { $id_value = $config_parameter; switch ($type) { case 'data': switch ($item) { case 'Configuration': if ($ignore_config) { if ($this->GetVerboseFlag()) { $this->WriteLog("Info: *System configuration data ignored", FALSE, FALSE, 8888, 'System', ''); } } else { if ($update_config) { if ($this->GetVerboseFlag()) { $this->WriteLog("Info: *Configuration update_config", FALSE, FALSE, 8888, 'System', ''); } $this->ReadConfigData(); } else { if ($this->GetVerboseFlag()) { $this->WriteLog("Info: *Reset (update) the configuration array", FALSE, FALSE, 8888, 'System', ''); } $this->ReadConfigData(); } } break; case 'Device': $this->ResetDeviceArray(); $this->_device = strtolower($id_value); break; case 'Group': $this->ResetGroupArray(); $this->_group = strtolower($id_value); break; case 'Token': $this->ResetTokenArray(); $this->_token = strtolower($id_value); break; case 'User': $this->ResetUserArray(); $this->_user = ($this->IsCaseSensitiveUsers()) ? $id_value : strtolower($id_value); break; } break; case 'file': $ignore = FALSE; foreach ($ignore_files as $one_ignore_file) { if ($one_ignore_file == $id_value) { $ignore = TRUE; break; } } if ((!$ignore) && ($id_value != '')) { if ($this->GetVerboseFlag()) { $this->WriteLog("Info: *File $id_value to restore", FALSE, FALSE, 8888, 'System', ''); } foreach($rename_files as $one_file) { if ($id_value == isset($one_file['original'])?$one_file['original']:'') { if ('' != (isset($one_file['original'])?$one_file['original']:'')) { $id_value = $one_file['renamed']; break; } } } if (file_exists($item)) { if (!($file_handler = @fopen($item.$id_value, "wb"))) { if ($this->GetVerboseFlag()) { $this->WriteLog("Info: *File ".$id_value." cannot be created", FALSE, FALSE, 8888, 'System', ''); } } } elseif ($this->GetVerboseFlag()) { $this->WriteLog("Info: *File ".$id_value." not created, $item doesn't exist", FALSE, FALSE, 8888, 'System', ''); } } elseif ($this->GetVerboseFlag()) { $this->WriteLog("Info: *File ".$id_value." ignored", FALSE, FALSE, 8888, 'System', ''); } break; } } elseif (0 === strpos ($config_command, 'deleted')) { $deleted = (1 == $config_parameter); } elseif (0 === strpos ($config_command, 'element-stop')) { switch ($type) { case 'data': switch ($item) { case 'Configuration': if ($ignore_config) { if ($this->GetVerboseFlag()) { $this->WriteLog("Info: *System configuration data ignored and not updated", FALSE, FALSE, 8888, 'System', ''); } } else { $this->WriteConfigData(); if ($this->GetVerboseFlag()) { $this->WriteLog("Info: *Configuration updated", FALSE, FALSE, 8888, 'System', ''); } } break; case 'Device': if (!$deleted) { $this->WriteDeviceData(array("automatically" => $automatically)); if ($this->GetVerboseFlag()) { $this->WriteLog("Info: *Device ".$id_value." updated", FALSE, FALSE, 8888, 'System', ''); } } else { $this->DeleteDevice($id_value, TRUE); if ($this->GetVerboseFlag()) { $this->WriteLog("Info: *Device ".$id_value." deleted", FALSE, FALSE, 8888, 'System', ''); } } break; case 'Group': if (!$deleted) { $this->WriteGroupData(array("automatically" => $automatically)); if ($this->GetVerboseFlag()) { $this->WriteLog("Info: *Group ".$id_value." updated", FALSE, FALSE, 8888, 'System', ''); } } else { $this->DeleteGroup($id_value, TRUE); if ($this->GetVerboseFlag()) { $this->WriteLog("Info: *Group ".$id_value." deleted", FALSE, FALSE, 8888, 'System', ''); } } break; case 'Token': if (!$deleted) { $this->WriteTokenData(array("automatically" => $automatically)); if ($this->GetVerboseFlag()) { $this->WriteLog("Info: *Token ".$id_value." updated", FALSE, FALSE, 8888, 'System', ''); } } else { $this->DeleteToken($id_value, TRUE); if ($this->GetVerboseFlag()) { $this->WriteLog("Info: *Token ".$id_value." deleted", FALSE, FALSE, 8888, 'System', ''); } } break; case 'User': if (!$deleted) { $this->UserRestoreBeforeWrite(); $this->WriteUserData(array("automatically" => $automatically)); if ($this->GetVerboseFlag()) { $this->WriteLog("Info: *User ".$id_value." updated", FALSE, FALSE, 8888, 'System', ''); } } else { $this->DeleteUser($id_value, TRUE); if ($this->GetVerboseFlag()) { $this->WriteLog("Info: *User ".$id_value." deleted", FALSE, FALSE, 8888, 'System', ''); } } break; } break; case 'file': if (FALSE !== $file_handler) { fclose($file_handler); if ('' != $this->GetLinuxFileMode()) { @chmod($item.$id_value, octdec($this->GetLinuxFileMode())); } if ($this->GetVerboseFlag()) { $this->WriteLog("Info: *File ".$id_value." closed", FALSE, FALSE, 8888, 'System', ''); } } if ($deleted) { unlink($item.$id_value); if ($this->GetVerboseFlag()) { $this->WriteLog("Info: *File ".$id_value." deleted", FALSE, FALSE, 8888, 'System', ''); } } elseif ($this->GetVerboseFlag()) { $this->WriteLog("Info: *File ".$id_value." updated", FALSE, FALSE, 8888, 'System', ''); } break; } $type = ''; $item = ''; $id_value = ''; $deleted = FALSE; $file_handler = FALSE; $data_array = array(); } } else { $line_array = explode("=",$line,2); $key = isset($line_array[0]) ? $line_array[0] : ''; $value = isset($line_array[1]) ? $line_array[1] : ''; if (('#' != substr($line, 0, 1)) && (';' != substr($line, 0, 1)) && ("" != trim($line)) && (isset($line_array[1]))) { if (":" == substr($key, -1)) { $key = substr($key, 0, strlen($key) -1); $value = $this->Decrypt($key,$value,$restore_key); } if ('raw_data' == $key) { $value = hex2bin($value); } foreach ($ignore_attributes as $one_ignore_attribute) { if ((0 === strpos($key, $one_ignore_attribute)) || (substr($key, -strlen($one_ignore_attribute)) == $one_ignore_attribute)) { $key = ""; break; } } if ("" != $key) { if ('file' == $type) { if ($file_handler && (!$deleted)) { fwrite($file_handler, $value); } } elseif ('data' == $type) { switch ($item) { case 'Configuration': if (!$ignore_config) { $this->_config_data[$key] = $value; } break; case 'Device': $this->_device_data[$key] = $value; break; case 'Group': $this->_group_data[$key] = $value; break; case 'Token': $this->_token_data[$key] = $value; break; case 'User': $this->_user_data[$key] = $value; break; } } } } } } fclose($backup_handler); } } else { $result = false; } return $result; } function SetConsoleAuthentication( $value ) { $this->_config_data['console_authentication'] = ((intval($value) > 0) ? 1 : 0); } function EnableConsoleAuthentication() { $this->_config_data['console_authentication'] = 1; } function DisableConsoleAuthentication() { $this->_config_data['console_authentication'] = 0; } function IsConsoleAuthentication() { return (1 == ($this->_config_data['console_authentication'])); } function SetLogFileName( $filename ) { $this->_log_file_name = trim($filename); } function GetLogFileName() { return $this->_log_file_name; } function SetLogHeaderWritten( $log_header_written ) { $this->_log_header_written = $log_header_written; } function GetLogHeaderWritten() { return $this->_log_header_written; } function SetLogFolder( $folder, $create = true ) { $new_folder = $this->ConvertToUnixPath($folder); if (substr($new_folder,-1) != "/") { $new_folder.="/"; } if ("/" == $new_folder) { $new_folder = "./"; } $new_folder = $this->ConvertToWindowsPathIfNeeded($new_folder); $this->_log_folder = $new_folder; if ($create && (!file_exists($new_folder))) { if (!@mkdir( $new_folder, ('' != $this->GetLinuxFolderMode()) ? octdec($this->GetLinuxFolderMode()) : 0777, true )) { $this->WriteLog("Error: Unable to create the missing config folder ".$new_folder, true, false, 28, 'System', '', 3); } } } function GetLogFolder() { if ("" == $this->_log_folder) { $this->SetLogFolder($this->GetScriptFolder()."log/"); } return $this->ConvertToWindowsPathIfNeeded($this->_log_folder); } function WriteLog( $info, $file_only = FALSE, $hide_on_display = FALSE, $error_code = 9999, $category = '*DEFAULT*', $user = '*DEFAULT*', $overwrite_severity = -1, $no_syslog = FALSE ) { if ('*DEFAULT*' != $user) { $user_log = $user; } else { $user_log = $this->GetUser(); } if ('*DEFAULT*' != $category) { $category_log = $category; } else { $category_log = "Authentication"; } if (0 == intval($error_code)) { $severity = 5; } elseif (8888 <= intval($error_code)) { $severity = 7; } elseif (20 > intval($error_code)) { $severity = 6; } elseif (100 > intval($error_code)) { $severity = 4; } elseif (200 > intval($error_code)) { $severity = 3; } elseif (300 > intval($error_code)) { $severity = 2; } elseif (400 > intval($error_code)) { $severity = 1; } elseif (500 > intval($error_code)) { $severity = 0; } else { $severity = 3; } if ((intval($overwrite_severity) >= 0) && (intval($overwrite_severity) <= 7)) { $severity = intval($overwrite_severity); } switch ($severity) { case 0: $severity_txt = 'emergency'; break; case 1: $severity_txt = 'alert'; break; case 2: $severity_txt = 'critical'; break; case 3: $severity_txt = 'error'; break; case 4: $severity_txt = 'warning'; break; case 5: $severity_txt = 'notice'; break; case 6: $severity_txt = 'info'; break; case 7: $severity_txt = 'debug'; break; default: $severity_txt = 'error'; } $post_info = ""; $pre_info = ""; if ("" != ($this->GetSourceIp().$this->GetSourceMac())) { $post_info.= "from "; if ("" != $this->GetSourceIp()) { $post_info.= $this->GetSourceIp().' '; } if ("" != $this->GetSourceMac()) { $post_info.= '['.$this->GetSourceMac().'] '; } } if ("" != ($this->GetCallingIp().$this->GetCallingMac())) { $post_info.= "for "; if ("" != $this->GetCallingIp()) { $post_info.= $this->GetCallingIp().' '; } if ("" != $this->GetCallingMac()) { $post_info.= '['.$this->GetCallingMac().'] '; } } $log_info = trim(trim($pre_info).' '.$info.' '.trim($post_info)); $log_info = str_replace(chr(13).chr(10), "<<CRLF>>", $log_info); $log_info = str_replace(chr(13), "<<CRLF>>", $log_info); $log_info = str_replace(chr(10), "<<CRLF>>", $log_info); $log_info = str_replace("<<CRLF>>", "\n", $log_info); $log_info = str_replace("\t", " ", $log_info); $log_time = time(); $log_datetime = date("Y-m-d H:i:s", $log_time); $logfile_content = $log_datetime."\t".$severity_txt."\t".$user_log."\t".$category_log."\t".str_replace("\n", $this->IsDebugViaHtml()?"<br />":"; ", $log_info); if (($this->GetDisplayLogFlag()) && (!$hide_on_display) && (!$this->GetNoDisplayLogFlag())) { $display_text = "\nLOG ".$log_datetime.' '.$severity_txt.' '.(("" == $user_log)?"":'(user '.$user_log.') ').$category_log.' '.$log_info."\n"; if ($this->IsDebugViaHtml()) { $display_text = str_replace("\n","<br />\n", $display_text); } echo $display_text; } if (("" != trim($this->GetSysLogServer())) && (!$this->IsSysLogServerBad()) && (!$no_syslog)) { if ($severity <= $this->GetSyslogLevel()) { $syslog_server = $this->GetSysLogServer(); if (!is_valid_ipv4($syslog_server)) { $syslog_server = gethostbyname($syslog_server); } if (is_valid_ipv4($syslog_server)) { $syslog_month = date("M", $log_time); $syslog_day = substr("  ".date("j", $log_time), -2); $syslog_hhmmss = date("H:i:s", $log_time); $syslog_timestamp = $syslog_month." ".$syslog_day." ".$syslog_hhmmss; $syslog_port = $this->GetSysLogPort(); $syslog_timeout = 3; $syslog_severity_facility = $severity + 8 * $this->GetSyslogFacility(); $syslog_hostname = $this->GetSystemName(); $syslog_process = 'multiOTP'; $syslog_ip_from = $this->GetLocalIpAddress(); $syslog_content = str_replace("\n", "; ", $log_info); $syslog_fqdn = $this->GetSystemName().(("" != $this->GetDomainName())?'.'.$this->GetDomainName():""); $cli_command = ""; if (file_exists('/bin/nc')) { $cli_command = "echo \"<$syslog_severity_facility>$syslog_timestamp $syslog_hostname $syslog_process: $syslog_fqdn $syslog_ip_from $syslog_content\" | /bin/nc $syslog_server -u $syslog_port -w $syslog_timeout > /dev/null 2>&1"; exec("nohup $cli_command &", $output); } if (("" == $cli_command) || ($this->GetVerboseFlag())) { $duplicated = (("" == $cli_command) ? "" : "(duplicated using native syslog library for debug) "); $syslog = new MultiotpSyslog(); $syslog->SetTimeout($syslog_timeout); $syslog->SetFacility($this->GetSyslogFacility()); $syslog->SetSeverity($severity); $syslog->SetHostname($syslog_hostname); $syslog->SetFqdn($syslog_fqdn); $syslog->SetIpFrom($syslog_ip_from); $syslog->SetProcess($syslog_process); $syslog->SetContent($duplicated.$syslog_content); $syslog->SetServer($syslog_server); $syslog->SetPort($syslog_port); $syslog_result = $syslog->Send(); if ('ERROR' == substr($syslog_result, 0, 5)) { $this->EnableBadSysLogServer(); if ($this->GetVerboseFlag()) { $this->WriteLog("Warning: *Error with the Syslog server ".$this->GetSysLogServer().": $syslog_result", FALSE, FALSE, 99, 'System', '', -1, TRUE); } else { $this->WriteLog("Warning: Error with the Syslog server ".$this->GetSysLogServer(), FALSE, FALSE, 99, 'System', '', -1, TRUE); } } } } else { $this->EnableBadSysLogServer(); $this->WriteLog("Warning: resolution name error for the Syslog server ".$this->GetSysLogServer(), FALSE, FALSE, 99, 'System', '', -1, TRUE); } } } $log_link = NULL; if ($this->IsLogEnabled()) { if ((!$file_only) && (('mysql' == $this->GetBackendType()) || ('pgsql' == $this->GetBackendType())) && $this->GetBackendTypeValidated() && ("" != $this->_config_data['sql_log_table']) ) { if ('mysql' == $this->GetBackendType()) { if ($this->OpenMysqlDatabase()) { $log_severity_escaped = escape_mysql_string($severity_txt); $log_user_escaped = escape_mysql_string($user_log); $log_category_escaped = escape_mysql_string($category_log); $log_info_escaped = escape_mysql_string(substr($log_info,0,255)); $sQuery = "INSERT INTO `".$this->_config_data['sql_log_table']."` (`datetime`,`severity`,`user`,`category`,`logentry`) VALUES ('".$log_datetime."','".$log_severity_escaped."','".$log_user_escaped."','".$log_category_escaped."','".$log_info_escaped."')"; if (is_object($this->_mysqli)) { if (!($rResult = $this->_mysqli->query($sQuery))) { $this->WriteLog("Error: SQL query error ($sQuery) : ".trim($this->_mysqli->error), TRUE, FALSE, 40, 'System', '', 3); } } elseif (!($rResult = mysql_query($sQuery, $this->_mysql_database_link))) { $this->WriteLog("Error: SQL query error ($sQuery) : ".mysql_error(), TRUE, FALSE, 40, 'System', '', 3); } } } elseif ('pgsql' == $this->GetBackendType()) { if ($this->OpenPGSQLDatabase()) { $log_severity_escaped = pg_escape_string($severity_txt); $log_user_escaped = pg_escape_string($user_log); $log_category_escaped = pg_escape_string($category_log); $log_info_escaped = pg_escape_string(substr($log_info,0,255)); $sQuery = "INSERT INTO \"".$this->_config_data['sql_schema']."\".\"".$this->_config_data['sql_log_table']."\" (\"datetime\",\"severity\",\"user\",\"category\",\"logentry\") VALUES ('".$log_datetime."','".$log_severity_escaped."','".$log_user_escaped."','".$log_category_escaped."','".$log_info_escaped."')"; if (!($rResult = pg_query($this->_pgsql_database_link, $sQuery))) { $this->WriteLog("Error: SQL query error ($sQuery) : ".pg_last_error(), TRUE, FALSE, 40, 'System', '', 3); } } } } else { if (!file_exists($this->GetLogFolder())) { @mkdir( $this->GetLogFolder(), ('' != $this->GetLinuxFolderMode()) ? octdec($this->GetLinuxFolderMode()) : 0777, true ); } $file_created = (!file_exists($this->GetLogFolder().$this->GetLogFileName())); if ($log_file_handle = @fopen($this->GetLogFolder().$this->GetLogFileName(),"ab+")) { if ($this->GetVerboseFlag()) { if (!$this->GetLogHeaderWritten()) { fwrite($log_file_handle,str_repeat("=",40)."\n"); fwrite($log_file_handle,'multiotp '.$this->GetVersion()."\n"); if ($this->GetVerboseFlag()) { fwrite($log_file_handle,'Your script is running from '.$this->GetScriptFolder()."\n"); } } $this->SetLogHeaderWritten(TRUE); } fwrite($log_file_handle,$logfile_content."\n"); fclose($log_file_handle); if ($file_created && ("" != $this->GetLinuxFileMode())) { @chmod($this->GetLogFolder().$this->GetLogFileName(), octdec($this->GetLinuxFileMode())); } } } } } function ShowLog( $as_result = FALSE ) { $result = ""; if ('mysql' == $this->GetBackendType()) { if ($this->OpenMysqlDatabase()) { $sQuery = "SELECT * FROM `".$this->_config_data['sql_log_table']."`"; if (is_object($this->_mysqli)) { if (!($rResult = $this->_mysqli->query($sQuery))) { $this->WriteLog("Error: Unable to access the database: ".trim($this->_mysqli->error), FALSE, FALSE, 41, 'System', '', 3); $result = FALSE; } else { while ($aRow = $rResult->fetch_assoc()) { if ($as_result) { $result.= trim($aRow['datetime'].' '.$aRow['user']).' '.$aRow['logentry']."\n"; } else { echo trim($aRow['datetime'].' '.$aRow['user']).' '.$aRow['logentry']."\n"; } } } } elseif (!($rResult = mysql_query($sQuery, $this->_mysql_database_link))) { $this->WriteLog("Error: Unable to access the database: ".mysql_error(), FALSE, FALSE, 41, 'System', '', 3); $result = FALSE; } else { while ($aRow = mysql_fetch_assoc($rResult)) { if ($as_result) { $result.= trim($aRow['datetime'].' '.$aRow['user']).' '.$aRow['logentry']."\n"; } else { echo trim($aRow['datetime'].' '.$aRow['user']).' '.$aRow['logentry']."\n"; } } } } } elseif ('pgsql' == $this->GetBackendType()) { if ($this->OpenPGSQLDatabase()) { $sQuery = "SELECT * FROM \"".$this->_config_data['sql_schema']."\".\"".$this->_config_data['sql_log_table']."\""; if (!($rResult = pg_query($this->_pgsql_database_link, $sQuery))) { $this->WriteLog("Error: Unable to access the database: ".pg_last_error(), FALSE, FALSE, 41, 'System', '', 3); $result = FALSE; } else { while ($aRow = pg_fetch_assoc($rResult)) { if ($as_result) { $result.= trim($aRow['datetime'].' '.$aRow['user']).' '.$aRow['logentry']."\n"; } else { echo trim($aRow['datetime'].' '.$aRow['user']).' '.$aRow['logentry']."\n"; } } } } } elseif (file_exists($this->GetLogFolder().$this->GetLogFileName())) { if ($log_file_handle = @fopen($this->GetLogFolder().$this->GetLogFileName(),"r")) { while (!feof($log_file_handle)) { if ($as_result) { $result.= trim(fgets($log_file_handle))."\n"; } else { echo trim(fgets($log_file_handle))."\n"; } } fclose($log_file_handle); } } return $result; } function ClearLog() { $result = TRUE; if ('mysql' == $this->GetBackendType()) { if ($this->OpenMysqlDatabase()) { $sQuery = "TRUNCATE `".$this->_config_data['sql_log_table']."`"; if (is_object($this->_mysqli)) { if (!($rResult = $this->_mysqli->query($sQuery))) { $this->WriteLog("Error: Unable to access the database: ".trim($this->_mysqli->error), FALSE, FALSE, 41, 'System', '', 3); $result = FALSE; } } elseif (!($rResult = mysql_query($sQuery, $this->_mysql_database_link))) { $this->WriteLog("Error: Unable to access the database: ".mysql_error(), FALSE, FALSE, 41, 'System', '', 3); $result = FALSE; } } else { $result = FALSE; } } elseif ('pgsql' == $this->GetBackendType()) { if ($this->OpenPGSQLDatabase()) { $sQuery = "TRUNCATE \"".$this->_config_data['sql_schema']."\".\"".$this->_config_data['sql_log_table']."\""; if (!($rResult = pg_query($this->_pgsql_database_link, $sQuery))) { $this->WriteLog("Error: Unable to access the database: ".pg_last_error(), FALSE, FALSE, 41, 'System', '', 3); $result = FALSE; } } else { $result = FALSE; } } if (file_exists($this->GetLogFolder().$this->GetLogFileName())) { unlink($this->GetLogFolder().$this->GetLogFileName()); } return $result; } function EnableLog() { $this->_log_flag = TRUE; if ("" == $this->_log_folder) { $this->SetLogFolder($this->GetScriptFolder()."log/"); } } function IsLogEnabled() { return (TRUE === $this->_log_flag); } function DisableLog() { $this->_log_flag = FALSE; } function EnableVerboseLog() { $this->EnableLog(); $this->_log_verbose_flag = TRUE; } function DisableVerboseLog() { $this->_log_verbose_flag = FALSE; } function GetVerboseFlag() { return $this->_log_verbose_flag; } function ForceNoDisplayLog() { $this->_no_display_log = true; } function DisableNoDisplayLog() { $this->_no_display_log = false; } function GetNoDisplayLogFlag() { return $this->_no_display_log; } function EnableDisplayLog() { $this->_log_display_flag = TRUE; } function DisableDisplayLog() { $this->_log_display_flag = FALSE; } function GetDisplayLogFlag() { return $this->_log_display_flag; } function SetCliMode($value) { $this->_cli_mode = (true == $value); } function GetCliMode() { return (true == $this->_cli_mode); } function SetCliProxyMode($value) { $this->_cli_proxy_mode = (true == $value); } function GetCliProxyMode() { return (true == $this->_cli_proxy_mode); } function SetDemoMode($value) { $this->_config_data['demo_mode'] = ((intval($value) > 0)?1:0); } function EnableDemoMode() { $this->_config_data['demo_mode'] = 1; } function DisableDemoMode() { $this->_config_data['demo_mode'] = 0; } function IsDemoMode() { return (1 == ($this->_config_data['demo_mode'])); } function SetCacheLdapHash( $value ) { $this->_config_data['cache_ldap_hash'] = ((intval($value) > 0)?1:0); } function EnableCacheLdapHash() { $this->_config_data['cache_ldap_hash'] = 1; } function DisableCacheLdapHash() { $this->_config_data['cache_ldap_hash'] = 0; } function IsCacheLdapHash() { return (1 == ($this->_config_data['cache_ldap_hash'])); } function IsLdapServerReachable() { return (TRUE === $this->_ldap_server_reachable); } function SetLdapServerReachable( $value ) { $this->_ldap_server_reachable = (TRUE === $value); } function SetEncryptionKeyFullPath( $full_path ) { $this->_config_data['encryption_key_full_path'] = $full_path; } function GetEncryptionKeyFullPath() { return trim(isset($this->_config_data['encryption_key_full_path'])?$this->_config_data['encryption_key_full_path']:""); } function SetHashSaltFullPath( $full_path ) { $this->_config_data['hash_salt_full_path'] = $full_path; } function GetHashSaltFullPath() { return trim($this->_config_data['hash_salt_full_path']); } function SetConfigFolder( $folder, $create = true, $read_config = true ) { $new_folder = $this->ConvertToUnixPath($folder); if (substr($new_folder,-1) != "/") { $new_folder.="/"; } if ("/" == $new_folder) { $new_folder = "./"; } $new_folder = $this->ConvertToWindowsPathIfNeeded($new_folder); $this->_config_folder = $new_folder; if ($create && (!file_exists($new_folder))) { if (!@mkdir( $new_folder, ('' != $this->GetLinuxFolderMode()) ? octdec($this->GetLinuxFolderMode()) : 0777, true )) { $this->WriteLog("Error: Unable to create the missing config folder ".$new_folder, true, false, 28, 'System', '', 3); } } if ($read_config) { $this->ReadConfigData(); } } function GetConfigFolder( $create_if_not_exist = false ) { $config_folder = $this->ConvertToWindowsPathIfNeeded($this->_config_folder); if ("" == $config_folder) { $this->SetConfigFolder($this->GetScriptFolder()."config/", $create_if_not_exist); } elseif (!file_exists($config_folder)) { if ($create_if_not_exist) { if (!@mkdir( $config_folder, ('' != $this->GetLinuxFolderMode()) ? octdec($this->GetLinuxFolderMode()) : 0777, true )) { $this->WriteLog("Error: Unable to create the missing config folder ".$config_folder, FALSE, FALSE, 28, 'System', '', 3); } } } return $this->ConvertToWindowsPathIfNeeded($this->_config_folder); } function SetCacheFolder( $folder, $create = true, $read_cache = true ) { $new_folder = $this->ConvertToUnixPath($folder); if (substr($new_folder,-1) != "/") { $new_folder.="/"; } if ("/" == $new_folder) { $new_folder = "./"; } $new_folder = $this->ConvertToWindowsPathIfNeeded($new_folder); $this->_cache_folder = $new_folder; if ($create && (!file_exists($new_folder))) { if (!@mkdir( $new_folder, ('' != $this->GetLinuxFolderMode()) ? octdec($this->GetLinuxFolderMode()) : 0777, true )) { $this->WriteLog("Error: Unable to create the missing cache folder ".$new_folder, TRUE, FALSE, 28, 'System', '', 3); } } if ($read_cache) { $this->ReadCacheData(); } } function GetCacheFolder( $create_if_not_exist = false ) { $cache_folder = $this->ConvertToWindowsPathIfNeeded($this->_cache_folder); if ("" == $cache_folder) { $this->SetCacheFolder($this->GetScriptFolder()."cache/", $create_if_not_exist); } elseif (!file_exists($cache_folder)) { if ($create_if_not_exist) { if (!@mkdir( $cache_folder, ('' != $this->GetLinuxFolderMode()) ? octdec($this->GetLinuxFolderMode()) : 0777, true )) { $this->WriteLog("Error: Unable to create the missing cache folder ".$cache_folder, FALSE, FALSE, 28, 'System', '', 3); } } } return $this->ConvertToWindowsPathIfNeeded($this->_cache_folder); } function GetLocalIpAddress() { $ip = ""; if (strtolower(substr(PHP_OS, 0, 3)) === 'win') { $output = array(); exec("ipconfig /all", $output); foreach($output as $line) { $line.= "  "; if (preg_match("/.*IPv4.*[^\.]+([[:xdigit:]]{1,3}[\.][[:xdigit:]]{1,3}[\.][[:xdigit:]]{1,3}[\.][[:xdigit:]]{1,3})[^\.]+/", $line)) { preg_match_all("/[^\.[:xdigit:]]+([[:xdigit:]]{1,3}[\.][[:xdigit:]]{1,3}[\.][[:xdigit:]]{1,3}[\.][[:xdigit:]]{1,3})/", $line, $result_array, PREG_SET_ORDER); if (isset($result_array[0][1])) { $temp = trim($result_array[0][1]); if ('0.0.0.0' != $temp) { $ip = $temp; break; } } } } } else { $output = array(); exec("ifconfig eth0 | grep \"inet addr\" | grep -o -E '([[:xdigit:]]{1,3}\.){3}[[:xdigit:]]{1,3}'", $output); $ip = (isset($output[0])?$output[0]:''); } return $ip; } function GetNetworkInfo() { $mode = ""; $ip = ""; $mask = ""; $gateway = ""; $dns = array(); $dns[0] = ""; $dns[1] = ""; $interface_name = ""; $fixed_gateway = false; if (strtolower(substr(PHP_OS, 0, 3)) === 'win') { $output = array(); exec("route print | find \"0.0.0.0\"", $output); foreach($output as $line) { $line.= "  "; if (preg_match("/.*0.0.0.0.*[^\.]+0.0.0.0.*[^\.]+([[:xdigit:]]{1,3}[\.][[:xdigit:]]{1,3}[\.][[:xdigit:]]{1,3}[\.][[:xdigit:]]{1,3})[^\.]+/", $line)) { $result_array = array(); preg_match_all("/[^\.[:xdigit:]]+([[:xdigit:]]{1,3}[\.][[:xdigit:]]{1,3}[\.][[:xdigit:]]{1,3}[\.][[:xdigit:]]{1,3})/", $line, $result_array, PREG_SET_ORDER); if ((!$fixed_gateway) && (isset($result_array[2][1]))) { $temp = trim($result_array[2][1]); if ('0.0.0.0' != $temp) { $gateway = $temp; if (!isset($result_array[3][1])) { $fixed_gateway = true; } } } } } $output = array(); exec("ipconfig /all", $output); $next_is_mask = false; foreach($output as $line) { $line.= "  "; if ($next_is_mask || preg_match("/.*IPv4.*[^\.]+([[:xdigit:]]{1,3}[\.][[:xdigit:]]{1,3}[\.][[:xdigit:]]{1,3}[\.][[:xdigit:]]{1,3})[^\.]+/", $line)) { $result_array = array(); preg_match_all("/[^\.[:xdigit:]]+([[:xdigit:]]{1,3}[\.][[:xdigit:]]{1,3}[\.][[:xdigit:]]{1,3}[\.][[:xdigit:]]{1,3})/", $line, $result_array, PREG_SET_ORDER); if (isset($result_array[0][1])) { $temp = trim($result_array[0][1]); if ($next_is_mask) { $mask = $temp; $cidr_mask = 32-log((ip2long($mask) ^ ip2long('255.255.255.255'))+1,2); $gw_long_subnet = (ip2long($gateway) >> (32-$cidr_mask)); $ip_long_subnet = (ip2long($ip) >> (32-$cidr_mask)); if ($ip_long_subnet != $gw_long_subnet) { $next_is_mask = false; } else { break; } } elseif ('0.0.0.0' != $temp) { $ip = $temp; $next_is_mask = true; } } } } $output = array(); exec("netsh interface dump | find \"".$ip."\"", $output); foreach($output as $line) { $line.= "  "; $result_array = array(); preg_match_all("/[^\"]+\"([^\"]*)\".*/", $line, $result_array, PREG_SET_ORDER); if (isset($result_array[0][1])) { $interface_name = mb_convert_encoding (trim($result_array[0][1]),"UTF-8","CP850"); $mode = "static"; break; } } if ("" == $interface_name) { $mode = "dhcp"; $output = array(); exec("netsh interface dump", $output); $ip4config = false; foreach($output as $line) { $line.= "  "; if (0 === strpos(trim($line),"pushd interface ipv4")) { $ip4config = true; } elseif ($ip4config && (0 === strpos(trim($line),"popd"))) { $ip4config = false; } if ($ip4config) { $result_array = array(); preg_match_all("/^set interface[^\"]+\"([^\"]*)\".*metric=1.*/", $line, $result_array, PREG_SET_ORDER); if (isset($result_array[0][1])) { $interface_name = mb_convert_encoding (trim($result_array[0][1]),"UTF-8","CP850"); break; } } } } $dns_count = 0; $output = array(); exec("netsh interface ip show dnsservers \"".mb_convert_encoding ($interface_name,"ISO-8859-15","UTF-8")."\"", $output); foreach($output as $line) { $line.= "  "; if (preg_match("/[^\.[:xdigit:]]+([[:xdigit:]]{1,3}[\.][[:xdigit:]]{1,3}[\.][[:xdigit:]]{1,3}[\.][[:xdigit:]]{1,3})[^\.]+/", $line)) { $result_array = array(); preg_match_all("/[^\.[:xdigit:]]+([[:xdigit:]]{1,3}[\.][[:xdigit:]]{1,3}[\.][[:xdigit:]]{1,3}[\.][[:xdigit:]]{1,3})/", $line, $result_array, PREG_SET_ORDER); if (($dns_count < 2) && isset($result_array[0][1])) { $dns[$dns_count] = trim($result_array[0][1]); $dns_count++; } } } } else { $output = array(); exec("grep -e \"^iface\seth0.*inet\s.*dhcp\" /etc/network/interfaces", $output); $mode = (false !== strpos(strtolower(isset($output[0])?$output[0]:''), "dhcp"))?"dhcp":"static"; $output = array(); exec("ifconfig eth0 | grep eth0 | grep -o -E '([[:xdigit:]]{1,2}:){5}[[:xdigit:]]{1,2}'", $output); $mac = strtoupper(isset($output[0])?$output[0]:''); $output = array(); exec("ifconfig eth0 | grep \"inet addr\" | grep -o -E '([[:xdigit:]]{1,3}\.){3}[[:xdigit:]]{1,3}'", $output); $ip = (isset($output[0])?$output[0]:''); $mask = (isset($output[2])?$output[2]:''); $output = array(); exec("ip route show default | awk '/default/ {print $3}'", $output); $gateway = strtoupper(isset($output[0])?$output[0]:''); $output = array(); exec("cat /etc/resolv.conf | grep -o -E '([[:xdigit:]]{1,3}\.){3}[[:xdigit:]]{1,3}'", $output); $dns[0] = (isset($output[0])?$output[0]:''); $dns[1] = (isset($output[1])?$output[1]:''); } $network_info = $mode."\t".$ip."\t".$mask."\t".$gateway."\t".$dns[0]."\t".$dns[1]."\t"; $network_array = explode("\t",$network_info); for ($i=count($network_array); $i <= 5; $i++) { $network_array[$i] = ''; } return $network_array; } function SetNetworkInfo( $ip = '', $mask = '', $gateway = '', $dns1 = '', $dns2 = '', $write_config = true, $if_down_up = true ) { $result = false; if ('' != $ip) { $resolv_file = "/etc/resolv.conf"; $resolv_tmp = sys_get_temp_dir()."/multiotp_resolv_tmp"; if (!($write = @fopen($resolv_tmp, "wt"))) { if ($this->GetVerboseFlag()) { $this->WriteLog("Error: *Temporary DNS information cannot be created", FALSE, FALSE, 8888, 'System', ''); } } else { $domain_name = $this->GetDomainName(); if ('' != $domain_name) { fwrite($write, "domain ".$domain_name."\n"); fwrite($write, "search ".$domain_name."\n"); } if ('' != $dns1) { fwrite($write, "nameserver ".$dns1."\n"); } if ('' != $dns2) { fwrite($write, "nameserver ".$dns2."\n"); } fclose($write); if ('' != $this->GetLinuxFileMode()) { @chmod($resolv_tmp, octdec($this->GetLinuxFileMode())); } if (!$this->IsDemoMode()) { if (strtolower(substr(PHP_OS, 0, 3)) !== 'win') { exec("sudo cp -f ".$resolv_tmp." ".$resolv_file, $output); } } } } $interfaces_file = "/etc/network/interfaces"; $interfaces_tmp = sys_get_temp_dir()."/multiotp_interfaces_tmp"; if (file_exists($interfaces_file)) { if (!($read = @fopen($interfaces_file, "rt"))) { if ($this->GetVerboseFlag()) { $this->WriteLog("Error: *Interface configuration cannot be accessed", FALSE, FALSE, 8888, 'System', ''); } } else { if (!($write = @fopen($interfaces_tmp, "wt"))) { if ($this->GetVerboseFlag()) { $this->WriteLog("Error: *Temporary interface configuration cannot be created", FALSE, FALSE, 8888, 'System', ''); } } else { $direct_write = true; $inet_eth0 = false; while(!feof($read)) { $one_line = fgets($read); if (preg_match("/^iface\seth0(.*)/", $one_line)) { $direct_write = false; $inet_eth0 = true; if ('' != $ip) { fwrite($write, "iface eth0 inet static\n"); fwrite($write, "\taddress ".$ip."\n"); fwrite($write, "\tnetmask ".$mask."\n"); fwrite($write, "\tgateway ".$gateway."\n"); fwrite($write, "\n"); } else { fwrite($write, "iface eth0 inet dhcp\n"); fwrite($write, "\n"); } } elseif ((0 === strpos(trim($one_line),"allow-")) || (0 === strpos(trim($one_line),"auto")) || (0 === strpos(trim($one_line),"iface")) || (0 === strpos(trim($one_line),"mapping")) || (0 === strpos(trim($one_line),"source"))) { $direct_write = true; } if ($direct_write) { fwrite($write, $one_line); } } fclose($read); fclose($write); if ('' != $this->GetLinuxFileMode()) { @chmod($interfaces_tmp, octdec($this->GetLinuxFileMode())); } if (!$this->IsDemoMode()) { exec("sudo cp -f ".$interfaces_tmp." ".$interfaces_file, $output); $result = true; if ($if_down_up) { exec("sudo /sbin/ifdown eth0 > /dev/null 2>&1", $output); sleep(1); exec("sudo /sbin/ifup eth0 > /dev/null 2>&1", $output); } } } } } else { if ($this->GetVerboseFlag()) { $this->WriteLog("Error: *Interface configuration file cannot be found", FALSE, FALSE, 8888, 'System', ''); } } return $result; } function GetSystemName() { $system_name = trim(php_uname('n')); return $system_name; } function SetDomainName( $value ) { if (!$this->IsDemoMode()) { $this->_config_data['domain_name'] = ($value); } } function GetDomainName() { return $this->_config_data['domain_name']; } function SetEmailAdminAddress( $value ) { $this->_config_data['email_admin_address'] = ($value); } function GetEmailAdminAddress() { return $this->_config_data['email_admin_address']; } function SetHashSalt( $salt ) { $this->_hash_salt = trim($salt); } function GetHashSalt() { $salt = $this->_hash_salt; if ((("" == $salt) || ("MySalt" == $salt) || ("AjaxH@shS@lt" == $salt) ) && ("" != $this->GetHashSaltFullPath()) && file_exists($this->GetHashSaltFullPath())) { if ($hash_salt_file_handler = @fopen($this->GetHashSaltFullPath(), "rt")) { $temp = trim(fgets($hash_salt_file_handler)); if ("" != $temp) { $salt = $temp; } fclose($hash_salt_file_handler); } } return trim($salt); } function SetRandomSalt( $salt ) { $this->_random_salt = trim($salt); } function GetRandomSalt() { return trim($this->_random_salt); } function SetAdminPassword( $password ) { if (!$this->IsDemoMode()) { return $this->SetConfigAttribute('admin_password_hash',md5($this->GetHashSalt().$password.$this->GetHashSalt())); } else { return false; } } function SetAdminPasswordHash( $password_hash ) { if (!$this->IsDemoMode()) { return $this->SetConfigAttribute('admin_password_hash',$password_hash); } else { return false; } } function CheckAdminPassword( $password ) { return ($this->GetConfigAttribute('admin_password_hash') == md5($this->GetHashSalt().$password.$this->GetHashSalt())); } function CheckAdminPasswordHash( $password_hash_with_salt ) { if (32 == strlen($password_hash_with_salt)) { return ($this->GetConfigAttribute('admin_password_hash') == $password_hash_with_salt); } else { return false; } } function CheckAdminPasswordHashWithRandomSalt( $password_hash_with_salt ) { if (32 == strlen($password_hash_with_salt)) { return (md5($this->GetRandomSalt().$this->GetConfigAttribute('admin_password_hash').$this->GetRandomSalt()) == $password_hash_with_salt); } else { return false; } } function EnableDebugViaHtml() { $this->_debug_via_html = TRUE; } function IsDebugViaHtml() { return ($this->_debug_via_html); } function EnableKeepLocal() { $this->_keep_local = TRUE; } function IsKeepLocal() { return ($this->_keep_local); } function SetLinuxFileMode( $mode ) { $this->_linux_file_mode = $mode; } function GetLinuxFileMode() { return ($this->_linux_file_mode); } function SetLinuxFolderMode( $mode ) { $this->_linux_folder_mode = $mode; } function GetLinuxFolderMode() { return ($this->_linux_folder_mode); } function SetConfigData( $key, $value ) { if (isset($this->_config_data[$key])) { $this->_config_data[$key] = $value; } } function SetLogOption( $value ) { $this->_config_data['log'] = $value; if (1 == $this->_config_data['log']) { $this->EnableLog(); } } function GetLogOption() { return intval($this->_config_data['log']); } function SetDebugOption( $value ) { $this->_config_data['debug'] = intval($value); if (1 == $this->_config_data['debug']) { $this->EnableVerboseLog(); } } function GetDebugOption() { return $this->_config_data['debug']; } function SetDisplayLogOption( $value ) { $this->_config_data['display_log'] = $value; if (1 == $this->_config_data['display_log']) { $this->EnableDisplayLog(); } } function SetMigrationFromFile( $value ) { $this->_migration_from_file = ($value?TRUE:FALSE); } function GetMigrationFromFile() { return $this->_migration_from_file; } function SetBackendType( $type ) { $this->_config_data['backend_type'] = $type; $this->_config_data['backend_type_validated'] = 0; } function GetBackendType() { return $this->_config_data['backend_type']; } function SetBackendTypeValidated( $backend_type_validated, $value ) { if ("" != $backend_type_validated) { $this->_config_data['backend_type'] = $backend_type_validated; } $this->_config_data['backend_type_validated'] = ($value ? 1 : 0); } function GetBackendTypeValidated() { return (1 == (isset($this->_config_data['backend_type_validated'])?$this->_config_data['backend_type_validated']:0)); } function SetScratchPasswordsDigits( $value ) { $this->_config_data['scratch_passwords_digits'] = $value; } function GetScratchPasswordsDigits() { return $this->_config_data['scratch_passwords_digits']; } function SetDefaultUserGroup( $value ) { $this->_config_data['default_user_group'] = $value; } function GetDefaultUserGroup() { return $this->_config_data['default_user_group']; } function SetGroupAttribute( $value ) { $this->_config_data['group_attribute'] = $value; } function GetGroupAttribute() { return $this->_config_data['group_attribute']; } function SetIssuer( $value ) { $this->_config_data['issuer'] = $value; } function GetIssuer() { if (isset($this->_config_data['issuer'])) { return $this->_config_data['issuer']; } else { return ""; } } function SetClearOtpAttribute( $value ) { $this->_config_data['clear_otp_attribute'] = $value; } function GetClearOtpAttribute() { return $this->_config_data['clear_otp_attribute']; } function SetSqlServer( $server ) { $this->_config_data['sql_server'] = $server; } function GetSqlServer() { return trim($this->_config_data['sql_server']); } function SetSqlUsername( $username ) { $this->_config_data['sql_username'] = $username; } function SetSqlPassword( $password ) { $this->_config_data['sql_password'] = $password; } function SetSqlSchema( $schema ) { $this->_config_data['sql_schema'] = $schema; } function SetSqlDatabase( $database ) { $this->_config_data['sql_database'] = $database; } function SetSqlTableName( $table_to_define, $table_name ) { if (isset($this->_config_data['sql_'.$table_to_define.'_table'])) { $this->_config_data['sql_'.$table_to_define.'_table'] = $table_name; } } function MySqlAddRowIfNeeded( $table, $row, $row_type, $is_an_index = FALSE ) { $result = FALSE; if (is_object($this->_mysqli)) { $sql_query = "SELECT `".$row."` FROM ".$table; if ($result = $this->_mysqli->query($sql_query)) { $result = TRUE; $sql_query = "ALTER TABLE ".$table." CHANGE `".$row."` `".$row."` ".$row_type; if (!$this->_mysqli->query($sql_query)) { $this->WriteLog("Error: ".trim($this->_mysqli->error)." ".$sql_query, TRUE, FALSE, 40, 'System', '', 3); $result = FALSE; } } else { $sql_query = "ALTER TABLE ".$table." ADD `".$row."` ".$row_type; if ($is_an_index) { $sql_query.= " , ADD INDEX ( `".$row."` )"; } if (!$this->_mysqli->query($sql_query)) { $this->WriteLog("Error: ".trim($this->_mysqli->error)." ".$sql_query, TRUE, FALSE, 40, 'System', '', 3); $result = FALSE; } } } elseif (NULL != $this->_mysql_database_link) { $sql_query = "SELECT `".$row."` FROM ".$table; if (($select_row = mysql_query($sql_query, $this->_mysql_database_link))) { $result = TRUE; $sql_query = "ALTER TABLE ".$table." CHANGE `".$row."` `".$row."` ".$row_type; if (!mysql_query($sql_query, $this->_mysql_database_link)) { $this->WriteLog("Error: ".mysql_error()." ".$sql_query, TRUE, FALSE, 40, 'System', '', 3); $result = FALSE; } } elseif (!$select_row) { $sql_query = "ALTER TABLE ".$table." ADD `".$row."` ".$row_type; if ($is_an_index) { $sql_query.= " , ADD INDEX ( `".$row."` )"; } if (!mysql_query($sql_query, $this->_mysql_database_link)) { $this->WriteLog("Error: ".mysql_error()." ".$sql_query, TRUE, FALSE, 40, 'System', '', 3); $result = FALSE; } } } elseif ($this->GetVerboseFlag()) { $this->WriteLog("Error: *The database link is down!", TRUE, FALSE, 41, 'System', '', 3); } return $result; } function OpenMysqlDatabase() { if ((is_object($this->_mysqli)) || (NULL != $this->_mysql_database_link)) { $result = TRUE; } else { $result = FALSE; if (("" != $this->_config_data['sql_server']) && ("" != $this->_config_data['sql_username']) && ("" != $this->_config_data['sql_password']) && ("" != $this->_config_data['sql_database'])) { if (class_exists('mysqli')) { $this->_mysqli = @new mysqli($this->_config_data['sql_server'], $this->_config_data['sql_username'], $this->_config_data['sql_password'], $this->_config_data['sql_database']); if (0 != $this->_mysqli->connect_errno) { $this->WriteLog("Error: Bad SQL authentication parameters, ".$this->_mysqli->connect_errno.', '.trim($this->_mysqli->connect_error), TRUE, FALSE, 41, 'System', '', 3); unset($this->_mysqli); $this->_mysqli = NULL; } else { $result = TRUE; } } elseif (!($this->_mysql_database_link = mysql_connect($this->_config_data['sql_server'], $this->_config_data['sql_username'], $this->_config_data['sql_password']))) { $this->WriteLog("Error: Bad SQL authentication parameters, ".mysql_error(), TRUE, FALSE, 41, 'System', '', 3); } else { if (!mysql_select_db($this->_config_data['sql_database'])) { $this->WriteLog("Error: Bad SQL database", TRUE, FALSE, 41, 'System', '', 3); mysql_close($this->_mysql_database_link); $this->_mysql_database_link = NULL; } else { $result = TRUE; } } } } return $result; } function PGSQLAddRowIfNeeded( $table, $column, $column_type, $column_default, $is_an_index = FALSE ) { $result = FALSE; if (NULL != $this->_pgsql_database_link) { $sql_query = "SELECT \"".$column."\" FROM \"".$this->_config_data['sql_schema']."\".\"".$table."\""; if (($select_row = @pg_query($this->_pgsql_database_link, $sql_query))) { $result = TRUE; $sql_query = "ALTER TABLE \"".$this->_config_data['sql_schema']."\".\"".$table."\" ALTER COLUMN \"".$column."\" TYPE ".$column_type; if (!@pg_query($this->_pgsql_database_link, $sql_query)) { $this->WriteLog("Error: ".pg_last_error()." ".$sql_query, TRUE, FALSE, 40, 'System', '', 3); $result = FALSE; } else { if ($column_default != NULL) { $sql_query = "ALTER TABLE \"".$this->_config_data['sql_schema']."\".\"".$table."\" ALTER COLUMN \"".$column."\" SET DEFAULT ".$column_default; } else { $sql_query = "ALTER TABLE \"".$this->_config_data['sql_schema']."\".\"".$table."\" ALTER COLUMN \"".$column."\" DROP DEFAULT"; } if (!@pg_query($this->_pgsql_database_link, $sql_query)) { $this->WriteLog("Error: ".pg_last_error()." ".$sql_query, TRUE, FALSE, 40, 'System', '', 3); $result = FALSE; } } } elseif (!$select_row) { $sql_query = "ALTER TABLE \"".$this->_config_data['sql_schema']."\".\"".$table."\" ADD COLUMN \"".$column."\" ".$column_type.($column_default != NULL ? " DEFAULT ".$column_default : ""); if (!@pg_query($this->_pgsql_database_link, $sql_query)) { $this->WriteLog("Error: ".pg_last_error()." ".$sql_query, TRUE, FALSE, 40, 'System', '', 3); $result = FALSE; } if ($is_an_index) { $sql_query = "CREATE INDEX \"".$table."_".$column."_idx\" ON \"".$this->_config_data['sql_schema']."\".\"".$table."\" ( \"".$column."\" )"; if(!@pg_query($this->_pgsql_database_link, $sql_query)) { $this->WriteLog("Error: ".pg_last_error()." ".$sql_query, TRUE, FALSE, 40, 'System', '', 3); $result = FALSE; } } } } elseif ($this->GetVerboseFlag()) { $this->WriteLog("Error: *The database link is down!", TRUE, FALSE, 41, 'System', '', 3); } return $result; } function OpenPGSQLDatabase() { if (NULL != $this->_pgsql_database_link) { $result = TRUE; } else { $result = FALSE; if (("" != $this->_config_data['sql_server']) && ("" != $this->_config_data['sql_username']) && ("" != $this->_config_data['sql_password']) && ("" != $this->_config_data['sql_database']) && ("" != $this->_config_data['sql_schema'])) { $sql_server = $this->_config_data['sql_server']; if (FALSE !== ($pos = strpos($this->_config_data['sql_server'], ":"))) { $sql_server_array = explode(":", $sql_server, 2); $sql_server = $sql_server_array[0]; $sql_port = $sql_server_array[1]; } else { $sql_port = "5432"; } $pgsql_connect_string = "host=$sql_server "; $pgsql_connect_string.= "port=$sql_port "; $pgsql_connect_string.= "dbname=".$this->_config_data['sql_database']." "; $pgsql_connect_string.= "user=".$this->_config_data['sql_username']." "; $pgsql_connect_string.= "password=".$this->_config_data['sql_password']; if (!($this->_pgsql_database_link = pg_connect($pgsql_connect_string))) { $this->WriteLog("Error: Bad SQL authentication parameters, ".pg_last_error(), TRUE, FALSE, 41, 'System', '', 3); } else { $result = TRUE; } } } return $result; } function InitializeBackend() { $write_config_data = false; $backend_type = $this->GetBackendType(); if ('mysql' == $backend_type) { if ($this->OpenMysqlDatabase()) { foreach ($this->_sql_tables as $sql_table) { if ("" != $this->_config_data['sql_'.$sql_table.'_table']) { $sql_query = "CREATE TABLE IF NOT EXISTS `".$this->_config_data['sql_'.$sql_table.'_table']."` (unique_id bigint(20) NOT NULL AUTO_INCREMENT, PRIMARY KEY (unique_id));"; if (is_object($this->_mysqli)) { if (!($result = $this->_mysqli->query($sql_query))) { $this->WriteLog("Error: Bad SQL request ($sql_query), ".trim($this->_mysqli->error), TRUE, FALSE, 40, 'System', '', 3); return 41; } } elseif (!mysql_query($sql_query, $this->_mysql_database_link)) { $this->WriteLog("Error: Bad SQL request (CREATE TABLE ".$this->_config_data['sql_'.$sql_table.'_table']."), ".mysql_error(), TRUE, FALSE, 40, 'System', '', 3); return 41; } reset($this->_sql_tables_schema[$sql_table]); while(list($valid_key, $valid_format) = @each($this->_sql_tables_schema[$sql_table])) { $this->MySqlAddRowIfNeeded($this->_config_data['sql_'.$sql_table.'_table'], $valid_key, $valid_format, (FALSE !== strpos($this->_sql_tables_index[$sql_table], "*".$valid_key."*"))); } } } $this->SetBackendTypeValidated($backend_type, TRUE); $write_config_data = true; } } elseif ('pgsql' == $backend_type) { if ($this->OpenPGSQLDatabase()) { foreach ($this->_sql_tables as $sql_table) { if ("" != $this->_config_data['sql_'.$sql_table.'_table']) { $sql_query = "CREATE TABLE IF NOT EXISTS \"".$this->_config_data['sql_schema']."\".\"".$this->_config_data['sql_'.$sql_table.'_table']."\" (\"unique_id\" BIGSERIAL PRIMARY KEY);"; if (!pg_query($this->_pgsql_database_link, $sql_query)) { $this->WriteLog("Error: Bad SQL request (CREATE TABLE ".$_config_data['sql_schema'].".".$this->_config_data['sql_'.$sql_table.'_table']."), ".pg_last_error(), TRUE, FALSE, 40, 'System', '', 3); return 41; } reset($this->_sql_tables_schema[$sql_table]); while(list($valid_key, $valid_format) = @each($this->_sql_tables_schema[$sql_table])) { $row_format = $valid_format; $row_default = NULL; if (strtolower(substr($row_format, 0, 4)) == "int(") { $row_format = str_ireplace("int(", "numeric(", $row_format); } elseif (strtolower(substr($row_format, 0, 8)) == "datetime") { $row_format = str_ireplace("datetime", "timestamp", $row_format); } $pos = strpos(strtoupper($row_format), 'DEFAULT'); if ($pos !== FALSE) { $row_default = trim(substr($valid_format, $pos + strlen("DEFAULT"))); $row_format = trim(substr($row_format, 0, $pos)); } $this->PGSQLAddRowIfNeeded($this->_config_data['sql_'.$sql_table.'_table'], $valid_key, $row_format, $row_default, (FALSE !== strpos($this->_sql_tables_index[$sql_table], "*".$valid_key."*"))); } } } $this->SetBackendTypeValidated($backend_type, TRUE); $write_config_data = true; } } if ($write_config_data) { $this->WriteConfigData(); } return 19; } function IsOptionInSchema( $schema, $option ) { $in_the_schema = FALSE; if (isset($this->_sql_tables_schema[$schema])) { reset($this->_sql_tables_schema[$schema]); while(list($valid_key, $valid_format) = @each($this->_sql_tables_schema[$schema])) { if ($valid_key == $option) { $in_the_schema = TRUE; break; } } } return $in_the_schema; } function ReadConfigData( $encryption_only = false, $encryption_key_param = '' ) { $result = FALSE; $encryption_key = $encryption_key_param ; if ('' == $encryption_key) { $encryption_key = $this->GetEncryptionKey(); } $this->_config_data['encryption_hash'] = ""; $config_filename = 'multiotp.ini'; if (file_exists($this->GetConfigFolder().$config_filename)) { if ($file_handler = @fopen($this->GetConfigFolder().$config_filename, "rt")) { $first_line = trim(fgets($file_handler)); while (!feof($file_handler)) { $line = str_replace(chr(10), "", str_replace(chr(13), "", fgets($file_handler))); $line_array = explode("=",$line,2); if (('#' != substr($line, 0, 1)) && (';' != substr($line, 0, 1)) && ("" != trim($line)) && (isset($line_array[1]))) { if (":" == substr($line_array[0], -1)) { $line_array[0] = substr($line_array[0], 0, strlen($line_array[0]) -1); $line_array[1] = $this->Decrypt($line_array[0],$line_array[1],$encryption_key); } if ("" != $line_array[0]) { $this->_config_data[strtolower($line_array[0])] = $line_array[1]; } } } fclose($file_handler); $result = TRUE; if (("" != $this->_config_data['encryption_hash']) && (!$encryption_only)) { if ($this->_config_data['encryption_hash'] != $this->CalculateControlHash($encryption_key)) { $this->_config_data['encryption_hash'] = "ERROR"; $this->WriteLog("Error: the configuration encryption key is not matching", FALSE, FALSE, 33, 'System', '', 3); $result = FALSE; } } } } if (!$encryption_only) { if ($this->_initialize_backend) { $this->SetBackendTypeValidated("", FALSE); $this->WriteConfigData(); } if ($this->GetBackendTypeValidated()) { switch ($this->GetBackendType()) { case 'mysql': if ($this->OpenMysqlDatabase()) { if ("" != $this->_config_data['sql_config_table']) { $sQuery = "SELECT * FROM `".$this->_config_data['sql_config_table']."` "; $aRow = NULL; if (is_object($this->_mysqli)) { if (!($result = @$this->_mysqli->query($sQuery))) { $this->WriteLog("Error: ".trim($this->_mysqli->error)." ".$sQuery, TRUE, FALSE, 41, 'System', '', 3); $result = FALSE; } else { $aRow = $result->fetch_assoc(); } } else { if (!($rResult = @mysql_query($sQuery, $this->_mysql_database_link))) { $this->WriteLog("Error: ".mysql_error()." ".$sQuery, TRUE, FALSE, 41, 'System', '', 3); $result = FALSE; } else { $aRow = mysql_fetch_assoc($rResult); } } if (NULL != $aRow) { $result = TRUE; while(list($key, $value) = @each($aRow)) { $in_the_schema = FALSE; reset($this->_sql_tables_schema['config']); while(list($valid_key, $valid_format) = @each($this->_sql_tables_schema['config'])) { if ($valid_key == $key) { $in_the_schema = TRUE; break; } } if ($in_the_schema) { if (FALSE === strpos($this->_sql_tables_ignore['config'], "*".$valid_key."*")) { if (('ENC:' == substr($value,0,4)) && (':ENC' == substr($value,-4))) { $value = substr($value,4); $value = substr($value,0,strlen($value)-4); $this->_config_data[$key] = $this->Decrypt($key,$value,$encryption_key); } else { $this->_config_data[$key] = $value; } } } elseif (('unique_id' != $key) && $this->GetVerboseFlag()) { $this->WriteLog("Warning: *the key ".$key." is not in the config database schema", FALSE, FALSE, 8888, 'System', '', 3); } } } } if (("" != $this->_config_data['encryption_hash']) && ($this->_encryption_check)) { if ($this->_config_data['encryption_hash'] != $this->CalculateControlHash($encryption_key)) { $this->_config_data['encryption_hash'] = "ERROR"; $this->WriteLog("Error: the configuration mysql encryption key is not matching", FALSE, FALSE, 33, 'System', '', 3); $result = FALSE; } } } break; case 'pgsql': if ($this->OpenPGSQLDatabase()) { if ("" != $this->_config_data['sql_config_table']) { $sQuery = "SELECT * FROM \"".$this->_config_data['sql_schema']."\".\"".$this->_config_data['sql_config_table']."\" "; $aRow = NULL; if (!($rResult = @pg_query($this->_pgsql_database_link, $sQuery))) { $this->WriteLog("Error: ".pg_last_error()." ".$sQuery, TRUE, FALSE, 41, 'System', '', 3); $result = FALSE; } else { $aRow = pg_fetch_assoc($rResult); } if (NULL != $aRow) { $result = TRUE; while(list($key, $value) = @each($aRow)) { $in_the_schema = FALSE; reset($this->_sql_tables_schema['config']); while(list($valid_key, $valid_format) = @each($this->_sql_tables_schema['config'])) { if ($valid_key == $key) { $in_the_schema = TRUE; break; } } if ($in_the_schema) { if (FALSE === strpos($this->_sql_tables_ignore['config'], "*".$valid_key."*")) { if (('ENC:' == substr($value,0,4)) && (':ENC' == substr($value,-4))) { $value = substr($value,4); $value = substr($value,0,strlen($value)-4); $this->_config_data[$key] = $this->Decrypt($key,$value,$encryption_key); } else { $this->_config_data[$key] = $value; } } } elseif (('unique_id' != $key) && $this->GetVerboseFlag()) { $this->WriteLog("Warning: *the key ".$key." is not in the config database schema", FALSE, FALSE, 8888, 'System', '', 3); } } } } if (("" != $this->_config_data['encryption_hash']) && ($this->_encryption_check)) { if ($this->_config_data['encryption_hash'] != $this->CalculateControlHash($encryption_key)) { $this->_config_data['encryption_hash'] = "ERROR"; $this->WriteLog("Error: the configuration pgsql encryption key is not matching", FALSE, FALSE, 33, 'System', '', 3); $result = FALSE; } } } break; default: break; } } if (isset($this->_config_data['log']) && (1 == $this->_config_data['log'])) { $this->EnableLog(); } if (isset($this->_config_data['debug']) && (1 == $this->_config_data['debug'])) { $this->EnableVerboseLog(); } if (isset($this->_config_data['display_log']) && (1 == $this->_config_data['display_log'])) { $this->EnableDisplayLog(); } $this->SetAttributesToEncrypt(trim(isset($this->_config_data['attributes_to_encrypt'])?$this->_config_data['attributes_to_encrypt']:"")); $timezone = $this->GetTimezone(); } if ((!isset($this->_config_data['server_secret'])) || ('' == $this->_config_data['server_secret'])) { $this->_config_data['server_secret'] = 'ClientServerSecret'; } return $result; } function WriteConfigData( $write_config_data_array = array() ) { if ($this->GetVerboseFlag()) { $backtrace = version_compare(PHP_VERSION, '5.3.6', '>=') ? debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS) : debug_backtrace(); foreach ($backtrace as $one_backtrace) { $file = isset($one_backtrace['file'])?$one_backtrace['file']:""; $line = isset($one_backtrace['line'])?$one_backtrace['line']:""; $class = isset($one_backtrace['class'])?$one_backtrace['class']."::":""; $function = isset($one_backtrace['function'])?$one_backtrace['function']:""; $this->WriteLog("Debug: *WriteConfigData $file:$line $class$function()", FALSE, FALSE, 8888, 'Debug', ''); } } $result = $this->WriteData(array_merge(array('item' => 'Configuration', 'table' => 'config', 'folder' => $this->GetConfigFolder(true), 'data_array' => $this->_config_data, 'force_file' => true ), $write_config_data_array)); return $result; } function ResetTempUserArray() { $temp_user_array = array(); reset($this->_sql_tables_schema['users']); while(list($valid_key, $valid_format) = @each($this->_sql_tables_schema['users'])) { $pos = strpos(strtoupper($valid_format), 'DEFAULT'); $value = ""; if ($pos !== FALSE) { $value = trim(substr($valid_format, $pos + strlen("DEFAULT"))); if (("'" == substr($value,0,1)) && ("'" == substr($value,-1))) { $value = substr($value,1,-1); } } $temp_user_array[$valid_key] = $value; } $temp_user_array['request_prefix_pin'] = $this->GetDefaultRequestPrefixPin(); return $temp_user_array; } function ResetUserArray() { $this->_user_data = array(); $this->_user_data = $this->ResetTempUserArray(); $this->SetUserDataReadFlag(false); } function ResetTokenArray() { reset($this->_sql_tables_schema['tokens']); while(list($valid_key, $valid_format) = @each($this->_sql_tables_schema['tokens'])) { $pos = strpos(strtoupper($valid_format), 'DEFAULT'); $value = ""; if ($pos !== FALSE) { $value = trim(substr($valid_format, $pos + strlen("DEFAULT"))); if (("'" == substr($value,0,1)) && ("'" == substr($value,-1))) { $value = substr($value,1,-1); } } $this->_token_data[$valid_key] = $value; } $this->_token_data['issuer'] = $this->GetIssuer(); $this->SetTokenDataReadFlag(FALSE); } function ResetDeviceArray() { reset($this->_sql_tables_schema['devices']); while(list($valid_key, $valid_format) = @each($this->_sql_tables_schema['devices'])) { $pos = strpos(strtoupper($valid_format), 'DEFAULT'); $value = ""; if ($pos !== FALSE) { $value = trim(substr($valid_format, $pos + strlen("DEFAULT"))); if (("'" == substr($value,0,1)) && ("'" == substr($value,-1))) { $value = substr($value,1,-1); } } $this->_device_data[$valid_key] = $value; } } function ResetGroupArray() { reset($this->_sql_tables_schema['groups']); while(list($valid_key, $valid_format) = @each($this->_sql_tables_schema['groups'])) { $pos = strpos(strtoupper($valid_format), 'DEFAULT'); $value = ""; if ($pos !== FALSE) { $value = trim(substr($valid_format, $pos + strlen("DEFAULT"))); if (("'" == substr($value,0,1)) && ("'" == substr($value,-1))) { $value = substr($value,1,-1); } } $this->_group_data[$valid_key] = $value; } } function CleanPhoneNumber( $phone_number ) { $pn = trim(preg_replace('[\D]', "", $phone_number)); if ('00' == substr($pn,0, 2)) { $pn = substr($pn, 2); } elseif ('0' == substr($pn,0, 1)) { $pn = $this->GetTelDefaultCountryCode() . substr($pn, 1); } return $pn; } function GetClassName() { return $this->_class; } function GetVersion() { return $this->_version; } function GetDate() { return $this->_date; } function GetVersionDate() { return $this->_version." (".$this->_date.")"; } function GetUptime( $text_output = true ) { $uptime = ''; if (file_exists('/proc/uptime')) { $file = @fopen('/proc/uptime', 'r'); if ($file) { $data = @fread($file, 128); if ($data !== false) { $upsecs = (int)substr($data, 0, strpos($data, ' ')); $days = floor($upsecs/60/60/24); $hours = $upsecs/60/60%24; $minutes = $upsecs/60%60; $seconds = $upsecs%60; $uptime = $days." day".(($days>1)?'s':'').", ".substr('00'.$hours, -2).':'.substr('00'.$minutes, -2).':'.substr('00'.$seconds, -2); } fclose($file); } } else { $pagefile = 'C:\pagefile.sys'; if (!is_file($pagefile)) { $pagefile = 'D:\pagefile.sys'; if (!is_file($pagefile)) { $pagefile = ''; } } if ('' != $pagefile) { $gettime = (time() - filemtime($pagefile)); $upsecs = $gettime; $days = floor($gettime / (24 * 3600)); $gettime = $gettime - ($days * (24 * 3600)); $hours = floor($gettime / (3600)); $gettime = $gettime - ($hours * (3600)); $minutes = floor($gettime / (60)); $gettime = $gettime - ($minutes * 60); $seconds = $gettime; - ($seconds * 1); $uptime = $days." day".(($days>1)?'s':'').", ".substr('00'.$hours, -2).':'.substr('00'.$minutes, -2).':'.substr('00'.$seconds, -2); } } return ($text_output?$uptime:$upsecs); } function GetFullVersionInfo() { return $this->_class." ".$this->_version." (".$this->_date.")"; } function GetCopyright() { return $this->_copyright; } function GetWebsite() { return $this->_website; } function SetSourceTag( $value = "" ) { $this->_source_tag = trim($value); } function GetSourceTag() { return trim($this->_source_tag); } function SetSourceIp( $value = "" ) { $this->_source_ip = $value; } function GetSourceIp() { return $this->_source_ip; } function SetSourceMac( $value ) { $this->_source_mac = $value; } function GetSourceMac() { return $this->_source_mac; } function SetCallingIp( $value ) { $this->_calling_ip = $value; } function GetCallingIp() { return $this->_calling_ip; } function SetCallingMac( $value ) { $this->_calling_mac = $value; } function GetCallingMac() { return $this->_calling_mac; } function SetChapChallenge( $hex_value ) { $pos = strpos(strtolower($hex_value), 'x'); if (FALSE === $pos) { $temp = $hex_value; } else { $temp = substr($hex_value, $pos+1); } $this->_chap_challenge = strtolower($temp); } function GetChapChallenge() { return strtolower($this->_chap_challenge); } function SetChapPassword( $hex_value ) { $pos = strpos(strtolower($hex_value), 'x'); if (FALSE === $pos) { $temp = $hex_value; } else { $temp = substr($hex_value, $pos+1); } if (32 < strlen($temp)) { $this->SetChapId(substr($temp, 0, 2)); $temp = substr($temp, 2); } $this->_chap_password = strtolower($temp); } function GetChapPassword() { return strtolower($this->_chap_password); } function SetMsChapChallenge( $hex_value ) { $pos = strpos(strtolower($hex_value), 'x'); if (FALSE === $pos) { $temp = $hex_value; } else { $temp = substr($hex_value, $pos+1); } $this->_ms_chap_challenge = strtolower($temp); } function GetMsChapChallenge() { return strtolower($this->_ms_chap_challenge); } function SetMsChapResponse( $hex_value ) { $pos = strpos(strtolower($hex_value), 'x'); if (FALSE === $pos) { $temp = $hex_value; } else { $temp = substr($hex_value, $pos+1); } $this->_ms_chap_response = strtolower($temp); } function GetMsChapResponse() { return strtolower($this->_ms_chap_response); } function SetMsChap2Response( $hex_value ) { $pos = strpos(strtolower($hex_value), 'x'); if (FALSE === $pos) { $temp = $hex_value; } else { $temp = substr($hex_value, $pos+1); } $this->_ms_chap2_response = strtolower($temp); } function GetMsChap2Response() { return strtolower($this->_ms_chap2_response); } function SetChapId( $hex_value ) { $pos = strpos(strtolower($hex_value), 'x'); if (FALSE === $pos) { $temp = $hex_value; } else { $temp = substr($hex_value, $pos+1); } $this->_chap_id = strtolower($temp); } function GetChapId() { return strtolower($this->_chap_id); } function SetNtKey( $hex_value ) { $temp = $hex_value; if (16 == strlen($temp)) { $temp = bin2hex($temp); } $pos = strpos(strtolower($temp), 'x'); if (FALSE !== $pos) { $temp = substr($temp, $pos+1); } if (32 != strlen($temp)) { $temp = ''; } $this->_ms_nt_key = strtoupper($temp); } function GetNtKey() { $temp = $this->_ms_nt_key; if (16 == strlen($temp)) { $temp = bin2hex($temp); } elseif (32 != strlen($temp)) { $temp = ''; } return strtoupper($temp); } function GetSmsProvidersArray() { return $this->_sms_providers_array; } function GetSmsProvidersList() { $providers_list = ''; foreach($this->GetSmsProvidersArray() as $one_provider) { $providers_list.= (('' != $providers_list)?"\t":''); $providers_list.= $one_provider[1]; $providers_list.= ('' != $one_provider[0])?' ('.$one_provider[0].')':''; $providers_list.= ('' != $one_provider[2])?', '.$one_provider[2]:''; } return $providers_list; } function SetSmsProvider( $value ) { $this->_config_data['sms_provider'] = $value; } function GetSmsProvider() { return $this->_config_data['sms_provider']; } function SetSmsOriginator( $value ) { $this->_config_data['sms_originator'] = $value; } function GetSmsOriginator() { return $this->_config_data['sms_originator']; } function SetTelDefaultCountryCode( $value ) { $this->_config_data['tel_default_country_code'] = $value; } function GetTelDefaultCountryCode() { return $this->_config_data['tel_default_country_code']; } function SetSmsUserkey( $value ) { $this->_config_data['sms_userkey'] = $value; } function GetSmsUserkey() { return $this->_config_data['sms_userkey']; } function SetSmsPassword( $value ) { $this->_config_data['sms_password'] = $value; } function GetSmsPassword() { return $this->_config_data['sms_password']; } function SetSmsApiId( $value ) { $this->_config_data['sms_api_id'] = $value; } function GetSmsApiId() { return $this->_config_data['sms_api_id']; } function SetDefaultAlgorithm( $value ) { $this->_config_data['default_algorithm'] = ((intval($value) > 0)?1:0); } function GetDefaultAlgorithm() { return $this->_config_data['default_algorithm']; } function SetDefaultRequestLdapPwd( $value ) { $this->_config_data['default_request_ldap_pwd'] = ((intval($value) > 0)?1:0); } function GetDefaultRequestLdapPwd() { return $this->_config_data['default_request_ldap_pwd']; } function IsDefaultRequestLdapPwd() { return (1 == ($this->_config_data['default_request_ldap_pwd'])); } function SetOverwriteRequestLdapPwd( $value ) { $this->_config_data['overwrite_request_ldap_pwd'] = ((intval($value) > 0)?1:0); } function GetOverwriteRequestLdapPwd() { return $this->_config_data['overwrite_request_ldap_pwd']; } function IsOverwriteRequestLdapPwd() { return (1 == ($this->_config_data['overwrite_request_ldap_pwd'])); } function SetDefaultRequestPrefixPin( $value ) { $this->_config_data['default_request_prefix_pin'] = ((intval($value) > 0)?1:0); } function GetDefaultRequestPrefixPin() { return $this->_config_data['default_request_prefix_pin']; } function IsDefaultRequestPrefixPin() { return (1 == ($this->_config_data['default_request_prefix_pin'])); } function EnableLdapError() { $this->_last_ldap_error = TRUE; } function DisableLdapError() { $this->_last_ldap_error = FALSE; } function IsLdapError() { return $this->_last_ldap_error; } function SetLdapActivated( $value ) { $this->_config_data['ldap_activated'] = ((intval($value) > 0) ? 1 : 0); if (1 > intval($value)) { $this->PurgeLdapCacheFolder(); } } function EnableLdapActivated() { $this->SetLdapActivated(1); } function DisableLdapActivated() { $this->SetLdapActivated(0); } function IsLdapActivated() { return (1 == ($this->_config_data['ldap_activated'])); } function SetLdapSsl( $value ) { $this->_config_data['ldap_ssl'] = ((intval($value) > 0)?1:0); } function EnableLdapSsl() { $this->_config_data['ldap_ssl'] = 1; } function DisableLdapSsl() { $this->_config_data['ldap_ssl'] = 0; } function IsLdapSsl() { return (1 == ($this->_config_data['ldap_ssl'])); } function SetLdapLanguageAttribute( $value ) { if ('' != trim($value)) { $this->_config_data['ldap_language_attribute'] = trim($value); } } function GetLdapLanguageAttribute() { return ($this->_config_data['ldap_language_attribute']); } function SetLdapAccountSuffix( $value ) { $this->_config_data['ldap_account_suffix'] = $value; } function GetLdapAccountSuffix() { return $this->_config_data['ldap_account_suffix']; } function SetLdapCnIdentifier( $value ) { if ('' != trim($value)) { $this->_config_data['ldap_cn_identifier'] = trim($value); } } function GetLdapCnIdentifier() { return ($this->_config_data['ldap_cn_identifier']); } function SetLdapSyncedUserAttribute( $value ) { $this->_config_data['ldap_synced_user_attribute'] = trim($value); } function GetLdapSyncedUserAttribute() { $result = ($this->_config_data['ldap_synced_user_attribute']); if ("" == trim($result)) { $result = $this->GetLdapCnIdentifier(); } return $result; } function SetLdapDefaultAlgorithm( $value ) { $this->_config_data['ldap_default_algorithm'] = $value; } function GetLdapDefaultAlgorithm() { return $this->_config_data['ldap_default_algorithm']; } function SetLdapGroupCnIdentifier( $value ) { if ('' != trim($value)) { $this->_config_data['ldap_group_cn_identifier'] = trim($value); } } function GetLdapGroupCnIdentifier() { return ($this->_config_data['ldap_group_cn_identifier']); } function GetLdapFieldsArray() { if (1 == $this->GetLdapServerType()) { $ldap_fields = array($this->GetLdapCnIdentifier(), "mail", $this->GetLdapGroupAttribute(), "displayName", "description", "telephoneNumber", "primaryGroupID", "mobile", "msNPAllowDialin", "userAccountControl", "ms-DS-User-Account-Control-Computed", "accountExpires", "distinguishedName", "msRADIUSFramedIPAddress", $this->GetLdapLanguageAttribute(), $this->GetLdapSyncedUserAttribute() ); } else { $ldap_fields = array($this->GetLdapCnIdentifier(), "mail", $this->GetLdapGroupAttribute(), "displayName", "description", "gecos", "telephoneNumber", "gidNumber", "mobile", "sambaAcctFlags", "shadowExpire", "distinguishedName", "radiusFramedIPAddress", "radiusFramedIPNetmask", $this->GetLdapLanguageAttribute(), $this->GetLdapSyncedUserAttribute() ); } return ($ldap_fields); } function SetLdapBaseDn( $value ) { $this->_config_data['ldap_base_dn'] = $value; } function GetLdapBaseDn() { return $this->_config_data['ldap_base_dn']; } function SetLdapGroupsDn( $value ) { $this->_config_data['ldap_groups_dn'] = $value; } function GetLdapGroupsDn() { return $this->_config_data['ldap_groups_dn']; } function SetLdapBindDn( $value ) { $this->_config_data['ldap_bind_dn'] = $value; } function GetLdapBindDn() { return encode_utf8_if_needed($this->_config_data['ldap_bind_dn']); } function SetLdapDomainControllers( $value ) { $this->_config_data['ldap_domain_controllers'] = trim($value); } function GetLdapDomainControllers() { return $this->_config_data['ldap_domain_controllers']; } function GetLdapPrimaryController() { $domain_controllers = str_replace(","," ",str_replace(";"," ",$this->GetLdapDomainControllers())); $controllers_array = explode(" ",$this->GetLdapDomainControllers()); return trim(isset($controllers_array[0])?$controllers_array[0]:''); } function GetLdapSecondaryController() { $domain_controllers = str_replace(","," ",str_replace(";"," ",$this->GetLdapDomainControllers())); $controllers_array = explode(" ",$this->GetLdapDomainControllers()); return trim(isset($controllers_array[1])?$controllers_array[1]:''); } function SetLdapInGroup( $value ) { $this->_config_data['ldap_in_group'] = $value; $ldap_in_group_array = explode("§",trim(str_replace(",","§",str_replace(";","§",$value)))); $groups_array = array(); $list = explode("\t", $this->GetGroupsList()); $n = count($list); for($i = 0; $i < $n; $i++) { if($list[$i] != '') { $this->SetGroup($list[$i]); $groups_array[] = $this->GetGroupName(); } } foreach($ldap_in_group_array as $one_group) { if (!in_array(trim($one_group), $groups_array)) { if ('' != trim($one_group)) { $this->CreateGroup('', trim($one_group), trim($one_group)); } } } } function GetLdapInGroup() { return $this->_config_data['ldap_in_group']; } function SetLdapGroupAttribute( $value ) { if ('' != trim($value)) { $this->_config_data['ldap_group_attribute'] = trim($value); } } function GetLdapGroupAttribute() { return ($this->_config_data['ldap_group_attribute']); } function SetLdapServerPassword( $value ) { $this->_config_data['ldap_server_password'] = $value; } function GetLdapServerPassword() { return encode_utf8_if_needed($this->_config_data['ldap_server_password']); } function SetLdapPort( $value ) { $this->_config_data['ldap_port'] = intval($value); } function GetLdapPort() { return $this->_config_data['ldap_port']; } function SetLdapServerType( $value, $default_parameters = false ) { $this->_config_data['ldap_server_type'] = intval($value); if (1 == $value) { $this->SetLdapGroupCnIdentifier('cn'); } else { $this->SetLdapGroupCnIdentifier('cn'); } if ($default_parameters) { if (1 == $value) { $this->SetLdapCnIdentifier('sAMAccountName'); } else { $this->SetLdapCnIdentifier('uid'); } } } function GetLdapServerType() { return $this->_config_data['ldap_server_type']; } function SetLdapTimeLimit( $value ) { $this->_config_data['ldap_time_limit'] = intval($value); } function GetLdapTimeLimit() { return $this->_config_data['ldap_time_limit']; } function SetLdapNetworkTimeout( $value ) { $this->_config_data['ldap_network_timeout'] = intval($value); } function GetLdapNetworkTimeout() { return $this->_config_data['ldap_network_timeout']; } function SetLdapHashCacheTime( $value ) { $this->_config_data['ldap_hash_cache_time'] = intval($value); } function GetLdapHashCacheTime() { return $this->_config_data['ldap_hash_cache_time']; } function SetSmsMessage( $value ) { $this->_config_data['sms_message_prefix'] = $value; } function GetSmsMessage() { return $this->_config_data['sms_message_prefix']; } function SetSmsDigits( $value ) { $this->_config_data['sms_digits'] = intval($value); } function GetSmsDigits() { return $this->_config_data['sms_digits']; } function SetSmsTimeout( $value ) { $this->_config_data['sms_timeout'] = intval($value); } function GetSmsTimeout() { return $this->_config_data['sms_timeout']; } function SetConfigAttribute( $attribute, $value ) { $result = FALSE; if ($this->IsOptionInSchema('config',$attribute)) { $this->_config_data[$attribute] = $value; $result = TRUE; } return $result; } function GetConfigAttribute( $attribute ) { return isset($this->_config_data[$attribute])?$this->_config_data[$attribute]:''; } function SetMaxTimeWindow( $time_window ) { $this->_config_data['max_time_window'] = intval($time_window); } function GetMaxTimeWindow() { return $this->_config_data['max_time_window']; } function SetMaxTimeResyncWindow( $time_resync_window ) { $this->_config_data['max_time_resync_window'] = intval($time_resync_window); } function GetMaxTimeResyncWindow() { return $this->_config_data['max_time_resync_window']; } function SetMaxEventWindow( $event_window ) { $this->_config_data['max_event_window'] = intval($event_window); } function GetMaxEventWindow() { return $this->_config_data['max_event_window']; } function SetMaxEventResyncWindow( $event_resync_window ) { $this->_config_data['max_event_resync_window'] = intval($event_resync_window); } function GetMaxEventResyncWindow() { return $this->_config_data['max_event_resync_window']; } function SetMaxBlockFailures( $max_failures ) { $this->_config_data['max_block_failures'] = $max_failures; } function GetMaxBlockFailures() { return $this->_config_data['max_block_failures']; } function SetServerCacheLevel( $value ) { $this->_config_data['server_cache_level'] = intval($value); } function GetServerCacheLevel() { return intval($this->_config_data['server_cache_level']); } function SetServerCacheLifetime( $value ) { $this->_config_data['server_cache_lifetime'] = intval($value); } function GetServerCacheLifetime() { return intval($this->_config_data['server_cache_lifetime']); } function SetServerChallenge( $value ) { $this->_server_challenge = $value; } function GetServerChallenge() { return $this->_server_challenge; } function SetServerSecret( $value ) { $this->_config_data['server_secret'] = $value; } function GetServerSecret($specific_ip = "") { return $this->_config_data['server_secret']; } function SetServerType( $value ) { $this->_config_data['server_type'] = $value; } function GetServerType() { return $this->_config_data['server_type']; } function SetServerTimeout( $value ) { $this->_config_data['server_timeout'] = intval($value); } function GetServerTimeout() { return intval($this->_config_data['server_timeout']); } function SetServerUrl( $value ) { $this->_config_data['server_url'] = trim($value); } function GetServerUrl() { return trim($this->_config_data['server_url']); } function SetSelfRegistration( $value ) { $this->_config_data['self_registration'] = ((intval($value) > 0)?1:0); } function EnableSelfRegistration() { $this->_config_data['self_registration'] = 1; } function DisableSelfRegistration() { $this->_config_data['self_registration'] = 0; } function IsSelfRegistrationEnabled() { return (1 == ($this->_config_data['self_registration'])); } function SetAutoResync( $value ) { $this->_config_data['auto_resync'] = ((intval($value) > 0)?1:0); } function EnableAutoResync() { $this->_config_data['auto_resync'] = 1; } function DisableAutoResync() { $this->_config_data['auto_resync'] = 0; } function IsAutoResync() { return (1 == ($this->_config_data['auto_resync'])); } function SetCacheData( $value ) { $this->_config_data['cache_data'] = ((intval($value) > 0)?1:0); } function EnableCacheData() { $this->_config_data['cache_data'] = 1; } function DisableCacheData() { $this->_config_data['cache_data'] = 0; } function IsCacheData() { return (1 == ($this->_config_data['cache_data'])); } function SetCaseSensitiveUsers() { $this->_config_data['case_sensitive_users'] = ((intval($value) > 0)?1:0); } function EnableCaseSensitiveUsers() { $this->_config_data['case_sensitive_users'] = 1; } function DisableCaseSensitiveUsers() { $this->_config_data['case_sensitive_users'] = 0; } function IsCaseSensitiveUsers() { return (1 == ($this->_config_data['case_sensitive_users'])); } function SetEncodeFileId() { $this->_config_data['encode_file_id'] = ((intval($value) > 0)?1:0); } function EnableEncodeFileId() { $this->_config_data['encode_file_id'] = 1; } function DisableEncodeFileId() { $this->_config_data['encode_file_id'] = 0; } function IsEncodeFileId() { return (1 == ($this->_config_data['encode_file_id'])); } function EncodeFileId($id, $case_sensitive = FALSE, $force_regular = FALSE) { if ($this->IsEncodeFileId() && (!$force_regular)) { if ($case_sensitive) { return "id0x".bin2hex($id); } else { return "id0x".bin2hex(strtolower($id)); } } else { if ($case_sensitive) { return str_replace('/','',$id); } else { return strtolower(str_replace('/','',$id)); } } } function DecodeFileId($id) { if ("id0x" == substr($id."  ", 0, 4)) { return hex2bin(substr($id, 4)); } else { return $id; } } function SetNtpServer( $ntp_server ) { $this->_config_data['ntp_server'] = $ntp_server; } function GetNtpServer() { return trim($this->_config_data['ntp_server']); } function SetRadiusReplyAttributor( $radius_reply_attributor ) { $this->_config_data['radius_reply_attributor'] = $radius_reply_attributor; } function GetRadiusReplyAttributor() { return ($this->_config_data['radius_reply_attributor']); } function SetRadiusReplySeparator( $radius_reply_separator ) { switch (strtolower($radius_reply_separator)) { case 'colon': $radius_reply_separator = ':'; break; case 'comma': $radius_reply_separator = ','; break; case 'cr': $radius_reply_separator = chr(13); break; case 'crlf': $radius_reply_separator = chr(13).chr(10); break; case 'lf': $radius_reply_separator = chr(10); break; case 'semicolon': $radius_reply_separator = ';'; break; } $this->_config_data['radius_reply_separator_hex'] = bin2hex($radius_reply_separator); } function GetRadiusReplySeparator() { return hex2bin($this->_config_data['radius_reply_separator_hex']); } function SetRadiusErrorReplyMessage( $radius_error_reply_message ) { $this->_config_data['radius_error_reply_message'] = intval($radius_error_reply_message); } function GetRadiusErrorReplyMessage() { return intval($this->_config_data['radius_error_reply_message']); } function IsRadiusErrorReplyMessage() { return (1 == $this->_config_data['radius_error_reply_message']); } function SetTimezone( $timezone ) { $this->_config_data['timezone'] = $timezone; if (function_exists('date_default_timezone_set')) { date_default_timezone_set($timezone); } } function GetTimezone() { $timezone = trim(isset($this->_config_data['timezone'])?$this->_config_data['timezone']:''); if (('' != $timezone) && (function_exists('date_default_timezone_set'))) { date_default_timezone_set($timezone); } return $timezone; } function SetSmtpAuth( $value ) { $this->_config_data['smtp_auth'] = ((intval($value) > 0)?1:0); } function GetSmtpAuth() { return (($this->_config_data['smtp_auth'] > 0)?1:0); } function IsSmtpAuth() { return (1 == ($this->_config_data['smtp_auth'])); } function SetSmtpPassword( $value ) { $this->_config_data['smtp_password'] = $value; } function GetSmtpPassword() { return $this->_config_data['smtp_password']; } function SetSmtpPort( $value ) { $this->_config_data['smtp_port'] = intval($value); } function GetSmtpPort() { return intval($this->_config_data['smtp_port']); } function SetSmtpSender( $value ) { $this->_config_data['smtp_sender'] = $value; } function GetSmtpSenderName() { return $this->_config_data['smtp_sender_name']; } function SetSmtpSenderName( $value ) { $this->_config_data['smtp_sender_name'] = $value; } function GetSmtpSender() { return $this->_config_data['smtp_sender']; } function SetSmtpServer( $value ) { if (!$this->IsDemoMode()) { $this->_config_data['smtp_server'] = $value; } } function GetSmtpServer() { return $this->_config_data['smtp_server']; } function SetSmtpSsl( $value ) { $this->_config_data['smtp_ssl'] = ((intval($value) > 0)?1:0); } function GetSmtpSsl() { return (($this->_config_data['smtp_ssl'] > 0)?1:0); } function SetSmtpUsername( $value ) { $this->_config_data['smtp_username'] = $value; } function GetSmtpUsername() { return $this->_config_data['smtp_username']; } function SetSyslogFacility( $value ) { $this->_config_data['syslog_facility'] = $value; } function GetSyslogFacility() { return $this->_config_data['syslog_facility']; } function SetSyslogLevel( $value ) { $this->_config_data['syslog_level'] = intval($value); } function GetSyslogLevel() { return intval($this->_config_data['syslog_level']); } function SetSysLogPort( $value ) { $this->_config_data['syslog_port'] = intval($value); } function GetSysLogPort() { return intval($this->_config_data['syslog_port']); } function SetSysLogServer( $value ) { $this->_config_data['syslog_server'] = $value; } function GetSysLogServer() { return $this->_config_data['syslog_server']; } function IsSysLogServerBad() { return $this->_bad_syslog_server; } function EnableBadSysLogServer() { $this->_bad_syslog_server = TRUE; } function DefineMySqlConnection( $sql_server, $sql_user, $sql_passwd, $sql_db, $sql_log_table = NULL, $sql_users_table = NULL, $sql_tokens_table = NULL ) { $this->SetBackendType('mysql'); $this->SetSqlServer($sql_server); $this->SetSqlUsername($sql_user); $this->SetSqlPassword($sql_passwd); $this->SetSqlDatabase($sql_db); if (NULL !== $sql_log_table) { $this->SetSqlTableName('log', $sql_log_table); } if (NULL !== $sql_users_table) { $this->SetSqlTableName('users', $sql_users_table); } if (NULL !== $sql_tokens_table) { $this->SetSqlTableName('tokens', $sql_tokens_table); } } function ComputeMotp( $seed_and_pin, $timestep, $token_size ) { return strtolower(substr(md5($timestep.$seed_and_pin),0,$token_size)); } function GenerateOathHotp( $key, $counter, $length = 6, $hash_algo = 'HMAC-SHA1' ) { return $this->ComputeOathTruncate($this->ComputeOathHotp($key, $counter, $hash_algo),$length); } function ComputeOathHotp( $key, $counter, $hash_algo = 'HMAC-SHA1' ) { $cur_counter = array(0,0,0,0,0,0,0,0); for($i=7;$i>=0;$i--) { $cur_counter[$i] = pack ('C*', $counter); $counter = $counter >> 8; } $bin_counter = implode($cur_counter); if (strlen ($bin_counter) < 8) { $bin_counter = str_repeat(chr(0), 8 - strlen($bin_counter)) . $bin_counter; } if ('HMAC-SHA512' == strtoupper($hash_algo)) { $hash = hash_hmac('sha512', $bin_counter, $key); } elseif ('HMAC-SHA256' == strtoupper($hash_algo)) { $hash = hash_hmac('sha256', $bin_counter, $key); } elseif ('HMAC-MD5' == strtoupper($hash_algo)) { $hash = hash_hmac('md5', $bin_counter, $key); } else { $hash = hash_hmac('sha1', $bin_counter, $key); } return $hash; } function ComputeOathTruncate( $hash, $length = 6 ) { foreach(str_split($hash,2) as $hex) { $hmac_result[]=hexdec($hex); } $offset = $hmac_result[(strlen($hash)/2)-1] & 0xf; $result = substr(str_repeat('0',$length). sprintf('%u', (($hmac_result[$offset+0] & 0x7f) << 24 ) | (($hmac_result[$offset+1] & 0xff) << 16 ) | (($hmac_result[$offset+2] & 0xff) << 8 ) | ($hmac_result[$offset+3] & 0xff) ), -$length); return $result; } function CalculateChapPassword( $secret, $hex_chap_id = '', $hex_chap_challenge = '' ) { if ($hex_chap_id != '') { $id = hex2bin($hex_chap_id); } elseif (32 < strlen($this->GetChapPassword())) { $id = hex2bin(substr($this->GetChapPassword(),0,2)); } else { $id = hex2bin($this->GetChapId()); } if ($hex_chap_challenge != '') { $challenge = hex2bin($hex_chap_challenge); } else { $challenge = hex2bin($this->GetChapChallenge()); } return md5($id.$secret.$challenge); } function Convert2Unicode( $value ) { $unicode = ''; $string = (string) $value; for ($i = 0; $i < strlen($string); $i++) { $asc = ord($string{$i}) << 8; $unicode .= sprintf("%X", $asc); } return pack('H*', $unicode); } function Padding7to8( $value ) { static $odd_parity = array( 1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, 14, 16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31, 32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47, 49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62, 64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79, 81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94, 97, 97, 98, 98,100,100,103,103,104,104,107,107,109,109,110,110, 112,112,115,115,117,117,118,118,121,121,122,122,124,124,127,127, 128,128,131,131,133,133,134,134,137,137,138,138,140,140,143,143, 145,145,146,146,148,148,151,151,152,152,155,155,157,157,158,158, 161,161,162,162,164,164,167,167,168,168,171,171,173,173,174,174, 176,176,179,179,181,181,182,182,185,185,186,186,188,188,191,191, 193,193,194,194,196,196,199,199,200,200,203,203,205,205,206,206, 208,208,211,211,213,213,214,214,217,217,218,218,220,220,223,223, 224,224,227,227,229,229,230,230,233,233,234,234,236,236,239,239, 241,241,242,242,244,244,247,247,248,248,251,251,253,253,254,254); $raw = ''; for ($i = 0; $i < strlen($value); $i++) { $raw .= sprintf('%08s', decbin(ord($value{$i}))); } $str1 = explode('-', substr(chunk_split($raw, 7, '-'), 0, -1)); $x = ''; foreach($str1 as $char) { $x .= sprintf('%02s', dechex($odd_parity[bindec($char. '0')])); } return pack('H*', $x); } function DesHashEcb( $clear ) { $cipher = new Crypt_DES(CRYPT_DES_MODE_ECB); $cipher->setKey($this->Padding7to8($clear)); return $cipher->encrypt('KGS!@#$%'); } function LmPasswordHash( $clear ) { $clear = substr(strtoupper($clear.str_repeat("\0",14)), 0, 14); return substr($this->DesHashEcb(substr($clear, 0, 7)),0,8).substr($this->DesHashEcb(substr($clear, 7, 7)),0,8); } function NtPasswordHash( $clear ) { return pack('H*',hash('md4', $this->Convert2Unicode($clear))); } function NtPasswordHashHash( $hash ) { return pack('H*',hash('md4', $hash)); } function CalculateMsChapResponse( $secret, $hex_mschap_challenge = '', $hex_mschap_response = '' ) { $temp_challenge = ('' != $hex_mschap_challenge)?$hex_mschap_challenge:$this->GetMsChapChallenge(); $pos = strpos(strtolower($temp_challenge), 'x'); if (FALSE !== $pos) { $temp_challenge = substr($temp_challenge, $pos+1); } $temp_response = ('' != $hex_mschap_response)?$hex_mschap_response:$this->GetMsChapResponse(); $this->SetMsChapResponse($temp_response); $pos = strpos(strtolower($temp_response), 'x'); if (FALSE !== $pos) { $temp_response = substr($temp_response, $pos+1); } $mschap_challenge = hex2bin($temp_challenge); $mschap_response = hex2bin($temp_response); if (24 == strlen($mschap_response)) { $mschap_response = str_repeat("\0",2+24).$mschap_response; } $id = substr($mschap_response,0,1); $flag = ord(substr($mschap_response,1,1)); $lm_response = substr($mschap_response,2,24); $nt_response = substr($mschap_response,26,24); if (1 == $flag) { $hash = $this->NtPasswordHash($secret); $response = $nt_response; $hash_for_nt_key = $hash; } else { $hash = $this->LmPasswordHash($secret); $response = $lm_response; $hash_for_nt_key = $this->NtPasswordHash($secret); } $this->SetNtKey(bin2hex($this->NtPasswordHashHash($hash))); $challenge = $mschap_challenge; $hash = substr($hash.str_repeat("\0",21), 0, 21); $cipher = new Crypt_DES(CRYPT_DES_MODE_ECB); $cipher->setKey($this->Padding7to8(substr($hash, 0, 7))); $part1 = substr($cipher->encrypt(substr($challenge,0,8)),0,8); $cipher->setKey($this->Padding7to8(substr($hash, 7, 7))); $part2 = substr($cipher->encrypt(substr($challenge,0,8)),0,8); $cipher->setKey($this->Padding7to8(substr($hash, 14, 7))); $part3 = substr($cipher->encrypt(substr($challenge,0,8)),0,8); $calculated_response = $part1.$part2.$part3; if ($calculated_response == $response) { $result = strtolower(bin2hex($mschap_response)); } else { $result = 'Error: '.bin2hex($calculated_response).' instead of '.bin2hex($nt_response); } return $result; } function CheckMsChapResponse( $secret, $hex_mschap_challenge = '', $hex_mschap_response = '' ) { $result = $this->CalculateMsChapResponse($secret, $hex_mschap_challenge, $hex_mschap_response); return ($this->GetMsChapResponse() == strtolower($result)); } function CalculateMsChap2Response( $user, $secret, $domain = "", $hex_mschap_challenge = '', $hex_mschap2_response = '' ) { $temp_challenge = ('' != $hex_mschap_challenge)?$hex_mschap_challenge:$this->GetMsChapChallenge(); $pos = strpos(strtolower($temp_challenge), 'x'); if (FALSE !== $pos) { $temp_challenge = substr($temp_challenge, $pos+1); } $temp_response = ('' != $hex_mschap2_response)?$hex_mschap2_response:$this->GetMsChap2Response(); $this->SetMsChap2Response($temp_response); $pos = strpos(strtolower($temp_response), 'x'); if (FALSE !== $pos) { $temp_response = substr($temp_response, $pos+1); } $mschap_challenge = hex2bin($temp_challenge); $mschap2_response = hex2bin($temp_response); if (24 == strlen($mschap2_response)) { $mschap2_response = str_repeat("\0",2+24).$mschap2_response; } $id = substr($mschap2_response,0,1); $flag = ord(substr($mschap2_response,1,1)); $peer_challenge = substr($mschap2_response,2,16); $empty = substr($mschap2_response,18,8); $nt_response = substr($mschap2_response,26,24); $hash = $this->NtPasswordHash($secret); $this->SetNtKey(bin2hex($this->NtPasswordHashHash($hash))); if (8 == strlen($mschap_challenge)) { $challenge = $mschap_challenge; } else { $challenge = substr(pack('H*',hash('sha1', $peer_challenge.$mschap_challenge.$user)), 0, 8); } $hash = substr($hash.str_repeat("\0",21), 0, 21); $cipher = new Crypt_DES(CRYPT_DES_MODE_ECB); $cipher->setKey($this->Padding7to8(substr($hash, 0, 7))); $part1 = substr($cipher->encrypt(substr($challenge,0,8)),0,8); $cipher->setKey($this->Padding7to8(substr($hash, 7, 7))); $part2 = substr($cipher->encrypt(substr($challenge,0,8)),0,8); $cipher->setKey($this->Padding7to8(substr($hash, 14, 7))); $part3 = substr($cipher->encrypt(substr($challenge,0,8)),0,8); $calculated_response = $part1.$part2.$part3; if ($calculated_response == $nt_response) { $result = strtolower(bin2hex($mschap2_response)); } else { $result = 'Error: '.bin2hex($calculated_response).' instead of '.bin2hex($nt_response); } return $result; } function CheckMsChap2Response( $user, $secret, $domain = '', $hex_mschap_challenge = '', $hex_mschap2_response = '' ) { $result = $this->CalculateMsChap2Response($user, $secret, $domain, $hex_mschap_challenge, $hex_mschap2_response); return ($this->GetMsChap2Response() == strtolower($result)); } function SetEncryptionKey( $key, $read_config = TRUE ) { $this->_encryption_key = $key; if ($read_config) { $this->ReadConfigData(); } } function GetEncryptionKey() { return $this->_encryption_key; } function CalculateControlHash( $value_to_hash ) { return strtoupper(md5("CaLcUlAtE".$value_to_hash."cOnTrOlHaSh")); } function Encrypt( $key, $value, $encryption_key ) { $result = ''; if (strlen($encryption_key) > 0) { if (0 < strlen($value)) { for ($i=0; $i < strlen($value); $i++) { $encrypt_char = ord(substr($encryption_key,$i % strlen($encryption_key),1)); $key_char = ord(substr($key,$i % strlen($key),1)); $result .= chr($encrypt_char^$key_char^ord(substr($value,$i,1))); } $result = base64_encode($result); } } else { $result = $value; } return $result; } function Decrypt( $key, $value, $encryption_key ) { $result = ''; if (strlen($encryption_key) > 0) { if (0 < strlen($value)) { $value_to_decrypt = base64_decode($value); for ($i=0; $i < strlen($value_to_decrypt); $i++) { $encrypt_char = ord(substr($encryption_key,$i % strlen($encryption_key),1)); $key_char = ord(substr($key,$i % strlen($key),1)); $result .= chr($encrypt_char^$key_char^ord(substr($value_to_decrypt,$i,1))); } } } else { $result = $value; } return $result; } function SetMaxDelayedFailures( $failures ) { $this->_config_data['max_delayed_failures'] = $failures; } function GetMaxDelayedFailures() { return $this->_config_data['max_delayed_failures']; } function SetMaxDelayedTime( $seconds ) { $this->_config_data['failure_delayed_time'] = $seconds; } function GetMaxDelayedTime() { return $this->_config_data['failure_delayed_time']; } function SetActualVersion( $value ) { $this->_config_data['actual_version'] = $value; } function GetActualVersion() { return $this->_config_data['actual_version']; } function CreateUser($user_raw, $prefix_pin_needed = -1, $algorithm = 'totp', $seed = '', $pin = '', $number_of_digits = 6, $time_interval_or_next_event = -1, $email = '', $sms = '', $description = '', $group = '', $token_algo_suite = '', $activated = 1, $synchronized = 0, $ldap_pwd_needed = -1, $automatically = FALSE ) { $user = str_replace("\\", "", $user_raw); $result = FALSE; if ('' != trim($user)) { if ((intval($ldap_pwd_needed) < 0) && (1 == $synchronized)) { $request_ldap_pwd = $this->GetDefaultRequestLdapPwd(); } else { $request_ldap_pwd = intval($ldap_pwd_needed); } if (intval($prefix_pin_needed) < 0) { $request_prefix_pin = $this->GetDefaultRequestPrefixPin(); } else { $request_prefix_pin = intval($prefix_pin_needed); } if ($this->ReadUserData($user, TRUE, TRUE) || ('' == $user)) { $result = FALSE; if ('' == $user) { $this->WriteLog("Error: User is not set", FALSE, FALSE, 21, 'User', ''); } else { $this->WriteLog("Error: User ".$user." already exists", FALSE, FALSE, 22, 'User', $user); } } else { $this->SetUser($user); $this->SetUserPrefixPin($request_prefix_pin); $this->SetUserRequestLdapPassword($request_ldap_pwd); $this->SetUserAlgorithm($algorithm); $this->SetUserTokenAlgoSuite($token_algo_suite); $the_pin = $pin; if ('' == $the_pin) { $the_pin = mt_rand(1000,9999); } $this->SetUserTokenNumberOfDigits($number_of_digits); $the_seed = (('' == $seed)?substr(md5(date("YmdHis").mt_rand(100000,999999)),0,20).substr(md5(mt_rand(100000,999999).date("YmdHis")),0,20):$seed); if (('hotp' == strtolower($algorithm)) || ('yubicootp' == strtolower($algorithm))) { $next_event = ((-1 == $time_interval_or_next_event)?0:$time_interval_or_next_event); $time_interval = 0; } else { $next_event = 0; $time_interval = ((-1 == $time_interval_or_next_event)?30:$time_interval_or_next_event); if ("motp" == strtolower($algorithm)) { $time_interval = 10; if ((strlen($the_pin) < 4) || (0 == intval($the_pin))) { $the_pin = mt_rand(1000,9999); } $the_pin = substr($the_pin, 0, 4); } } $this->SetUserPin($the_pin); $this->SetUserTokenSeed($the_seed); $this->SetUserTokenLastEvent($next_event - 1); $this->SetUserTokenTimeInterval($time_interval); $this_email = trim($email); if (('' == $this_email) && (FALSE !== strpos($user, '@'))) { $this_email = $user; } $this->SetUserEmail($this_email); $this->SetUserGroup(trim($group)); $this->SetUserSms($sms); $this->SetUserDescription($description); $this->SetUserActivated($activated); $this->SetUserSynchronized($synchronized); $result = $this->WriteUserData($automatically); } } return $result; } function CreateUserFromToken($user, $token, $email = '', $sms = '', $pin = '', $prefix_pin_needed = -1, $description = '', $group = '' ) { if (intval($prefix_pin_needed) < 0) { $request_prefix_pin = $this->GetDefaultRequestPrefixPin(); } else { $request_prefix_pin = intval($prefix_pin_needed); } if ($this->ReadUserData($user, TRUE, TRUE) || ('' == $user)) { $result = FALSE; if ('' == $user) { $this->WriteLog("Error: User is not set", FALSE, FALSE, 21, 'User', ''); } else { $this->WriteLog("Error: User ".$user." already exists", FALSE, FALSE, 22, 'User', $user); } } elseif (!$this->ReadTokenData($token)) { $result = FALSE; $this->WriteLog("Error: information about token ".$token." for user $user cannot be accessed", FALSE, FALSE, 29, 'Token', $token); } else { $this->AddTokenAttributedUsers($user); if (!$this->WriteTokenData()) { $result = 28; $this->WriteLog("Error: Unable to write the changes in the file for the token ".$this->GetToken(), FALSE, FALSE, $result, 'Token', $user); } else { $this->SetUser($user); $this->SetUserPrefixPin($request_prefix_pin); $this->SetUserKeyId($token); $this->SetUserTokenSerialNumber($token); $this->SetUserAlgorithm($this->GetTokenAlgorithm()); $this->SetUserTokenAlgoSuite($this->GetTokenAlgoSuite()); $this->SetUserTokenSeed($this->GetTokenSeed()); $this->SetUserTokenPrivateId($this->GetTokenPrivateId()); $this->SetUserTokenNumberOfDigits($this->GetTokenNumberOfDigits()); $this->SetUserTokenTimeInterval($this->GetTokenTimeInterval()); $this->SetUserTokenLastEvent($this->GetTokenLastEvent()); $the_pin = $pin; if ('' == $the_pin) { $the_pin = mt_rand(1000,9999); } $this_email = trim($email); if (('' == $this_email) && (FALSE !== strpos($user, '@'))) { $this_email = $user; } $this->SetUserPin($the_pin); $this->SetUserEmail($this_email); $this->SetUserGroup(trim($group)); $this->SetUserSms($sms); $this->SetUserDescription($description); $result = $this->WriteUserData(); } } return $result; } function GetUserTokenQrCode( $user = '', $display_name = '', $file_name = 'binary' ) { $result = FALSE; if (!function_exists('ImageCreate')) { $this->WriteLog("Error: PHP GD library is not installed", FALSE, FALSE, 39, 'System', '', 3); return $result; } else { $data = $this->GetUserTokenUrlLink($user,$display_name); if($data) { $result = $this->qrcode($data, $file_name); } return $result; } } function GetTokenQrCode( $token = '', $display_name = '', $file_name = 'binary' ) { $result = FALSE; if (!function_exists('ImageCreate')) { $this->WriteLog("Error: PHP GD library is not installed", FALSE, FALSE, 39, 'System', '', 3); return $result; } else { $data = $this->GetTokenUrlLink($token, $display_name); if($data) { $result = $this->qrcode($data, $file_name); } return $result; } } function GenerateHtmlQrCode( $select_user = '', $alternate_html_template = '', $keep_qrcode_tags = FALSE ) { $code_width=200; $code_height=200; if ('' != $select_user) { $user = $this->SetUser($select_user); } else { $user = $this->GetUser(); } $user = encode_utf8_if_needed($user); $descr = encode_utf8_if_needed($this->GetUserDescription()); $descr = encode_utf8_if_needed(empty($descr) ? $user : $descr); if ('' != trim($alternate_html_template)) { $html = $alternate_html_template; } else { $file_name = "template"; $file_to_show = $this->GetTemplatesFolder().$file_name.'.html'; if(file_exists($file_to_show)) { $html = (file_get_contents($file_to_show)); } else { $html = ''; } } $html = encode_utf8_if_needed($html); if ($this->IsUserRequestLdapPasswordEnabled()) { $request_ldap_pwd = TRUE; $html = preg_replace('/<!--\s*\{\/IfMultiotpUserLdapPwd\}\s*-->/i', '', $html); $html = preg_replace('/<!--\s*\{IfMultiotpUserLdapPwd\}\s*-->/i', '', $html); } else { $request_ldap_pwd = FALSE; $html = preg_replace('/<!--\s*\{\/IfMultiotpUserLdapPwd\}\s*-->/i', ' -- {/IfMultiotpUserLdapPwd} -->', $html); $html = preg_replace('/<!--\s*\{IfMultiotpUserLdapPwd\}\s*-->/i', '<!-- {/IfMultiotpUserLdapPwd} -- ', $html); } if ($this->IsUserPrefixPin() && (!$request_ldap_pwd)) { $html = preg_replace('/<!--\s*\{\/IfMultiotpUserPin\}\s*-->/i', '', $html); $html = preg_replace('/<!--\s*\{IfMultiotpUserPin\}\s*-->/i', '', $html); } else { $html = preg_replace('/<!--\s*\{\/IfMultiotpUserPin\}\s*-->/i', ' -- {/IfMultiotpUserPin} -->', $html); $html = preg_replace('/<!--\s*\{IfMultiotpUserPin\}\s*-->/i', '<!-- {/IfMultiotpUserPin} -- ', $html); } $token_serial = trim($this->GetUserTokenSerialNumber()); if (('' == $token_serial) || (1 > strlen($token_serial))) { $html = preg_replace('/<!--\s*\{\/IfMultiotpUserTokenSerial\}\s*-->/i', ' -- {/IfMultiotpUserTokenSerial} -->', $html); $html = preg_replace('/<!--\s*\{IfMultiotpUserTokenSerial\}\s*-->/i', '<!-- {/IfMultiotpUserTokenSerial} -- ', $html); } else { $html = preg_replace('/<!--\s*\{\/IfMultiotpUserTokenSerial\}\s*-->/i', '', $html); $html = preg_replace('/<!--\s*\{IfMultiotpUserTokenSerial\}\s*-->/i', '', $html); } $html = preg_replace('/IfMultiotpUserAlgorithm="[BCHIMOPTUY,]*'.strtoupper($this->GetUserAlgorithm()).'[BCHIMOPTUY,]*"}/i', 'IfMultiotpUserAlgorithm="'.strtoupper($this->GetUserAlgorithm()).'"}', $html); foreach (explode("\t",$this->GetAlgorithmsList()) as $algorithm_one) { if (strtoupper($algorithm_one) != strtoupper($this->GetUserAlgorithm())) { $html = preg_replace('/<!--\s*\{\/IfMultiotpUserAlgorithm="[BCHIMOPTUY,]*'.strtoupper($algorithm_one).'[BCHIMOPTUY,]*"\}\s*-->/i', ' -- {/IfMultiotpUserAlgorithm="DELETE"} -->', $html); $html = preg_replace('/<!--\s*\{IfMultiotpUserAlgorithm="[BCHIMOPTUY,]*'.strtoupper($algorithm_one).'[BCHIMOPTUY,]*"\}\s*-->/i', '<!-- {IfMultiotpUserAlgorithm="DELETE"} -- ', $html); } } $specific_language = $this->GetUserLanguage(); if (false === mb_stripos($html, '{IfMultiotpLanguage="'.$specific_language.'"')) { $specific_language = $this->GetLanguage(); if (false === mb_stripos($html, '{IfMultiotpLanguage="'.$specific_language.'"')) { $specific_language = 'en'; } } $html = preg_replace('/<!--\s*\{\/IfMultiotpLanguage="'.$specific_language.'"\}\s*-->/i', '', $html); $html = preg_replace('/<!--\s*\{IfMultiotpLanguage="'.$specific_language.'"\}\s*-->/i', '', $html); $html = preg_replace('/<!--\s*\{\/IfMultiotpLanguage="[a-z]*"\}\s*-->/i', ' -- {/IfMultiotpLanguage="other"} {ML} -->', $html); $html = preg_replace('/<!--\s*\{IfMultiotpLanguage="[a-z]*"\}\s*-->/i', '<!-- {ML} {IfMultiotpLanguage="other"} -- ', $html); $html_cleaned = ""; $html_slice = explode("{ML} -->",$html); foreach($html_slice as $one_slice) { $comment_pos = strpos($one_slice,'<!-- {ML}'); if(FALSE !== $comment_pos) { $html_cleaned.=substr($one_slice,0,$comment_pos); } } $html_cleaned .= end($html_slice); $html = $html_cleaned."\n"; $html_cleaned = ""; $html_slice = explode("-->",$html); foreach($html_slice as $one_slice) { $comment_pos = strpos($one_slice,'<!--'); if(FALSE !== $comment_pos) { $html_cleaned.=substr($one_slice,0,$comment_pos); } } $html_cleaned .= end($html_slice); $html = $html_cleaned."\n"; $html = str_replace('{MultiotpUserDescriptionUC}', mb_strtoupper($descr, 'UTF-8'), $html); $html = str_replace('{MultiotpUserDescription}', $descr, $html); $html = str_replace('{MultiotpUserAccount}', $user, $html); $html = str_replace('{MultiotpUserPin}', $this->GetUserPin(), $html); $html = str_replace('{MultiotpUserAlgorithm}', strtoupper($this->GetUserAlgorithm()), $html); $html = str_replace('{MultiotpUserTokenSeed}', $this->GetUserTokenSeed(), $html); $html = str_replace('{MultiotpUserTokenSeedBase32}', base32_encode(hex2bin($this->GetUserTokenSeed())), $html); $html = str_replace('{MultiotpUserTokenNumberOfDigits}', $this->GetUserTokenNumberOfDigits(), $html); $html = str_replace('{MultiotpUserTokenTimeInterval}', $this->GetUserTokenTimeInterval(), $html); $html = str_replace('{MultiotpUserTokenNextEvent}', 1+$this->GetUserTokenLastEvent(), $html); $html = str_replace('{MultiotpUserTokenSerial}', $token_serial, $html); $regex_url='/\surl=(.*?)[\}\s}]/'; $regex_format='/\sformat=\"?([^\"\}]*)\"?.*\}/'; $regex_w='/\swidth=(.*?)[\}\s]/'; $regex_h='/\sheight=(.*?)[\}\s]/'; $regex_tag='/\{MultiotpDateTime(.*)\}/'; $format = "Y-m-d H:i:s"; if(preg_match_all($regex_tag, $html, $matches)) { foreach ($matches[0] as $item) { if(!empty($item)) { if(preg_match($regex_format, $item, $values)) { $format = $values[1]; } $html = str_replace($item, date($format), $html); } } } if (!$keep_qrcode_tags) { $regex_tag='/\{MultiotpQrCodeUrl\s(.*?)\}/'; if(preg_match_all($regex_tag, $html, $matches)) { foreach ($matches[0] as $item) { $url = ''; $w = $code_width; $h = $code_height; if(!empty($item)) { if(preg_match($regex_url, $item, $values)) { $url= str_replace('"', '', explode('=', $values[0],2)); $url = $url[1]; } if(preg_match($regex_w, $item, $values)) { $w = str_replace('"', '', explode('=', $values[0],2)); $w = trim(str_replace('}', '', $w[1])); } if(preg_match($regex_h, $item, $values)) { $h = str_replace('"', '', explode('=', $values[0],2)); $h = trim(str_replace('}', '', $h[1])); } $html = str_replace($item, "<a id=\"QrCodeUrl\" href=\"".$url."\" target=\"blank\"><img border=\"0\" width=\"".$w."\" height=\"".$h."\" src=\"data:image/png;base64,".base64_encode($this->qrcode($url, 'binary'))."\" /></a>", $html); } } } $regex_tag='/\{MultiotpQrCodeUserToken\s(.*?)\}/'; if(preg_match_all($regex_tag, $html, $matches)) { foreach ($matches[0] as $item) { $url = $this->GetUserTokenUrlLink($user, $descr); $w = $code_width; $h = $code_height; if(!empty($item)) { if(preg_match($regex_w, $item, $values)) { $w = str_replace('"', '', explode('=', $values[0],2)); $w = trim(str_replace('}', '', $w[1])); } if(preg_match($regex_h, $item, $values)) { $h = str_replace('"', '', explode('=', $values[0],2)); $h = trim(str_replace('}', '', $h[1])); } $html = str_replace($item, "<a id=\"QrCodeUserToken\" href=\"".$url."\" target=\"blank\"><img border=\"0\" width=\"".$w."\" height=\"".$h."\" src=\"data:image/png;base64,".base64_encode($this->qrcode($url, 'binary'))."\"></a>", $html); } } } } return $html; } function GetUserTokenUrlLink( $user = '', $display_name = '' ) { $result = false; $user_array = $this->ReadUserDataArray(('' != $user)?$user:$this->GetUser()); if (false !== $user_array) { $the_user = $user; $description = $user_array['description']; $q_algorithm = $user_array['algorithm']; $q_algo_suite = $user_array['token_algo_suite']; $q_period = $user_array['time_interval']; $q_digits = $user_array['number_of_digits']; $q_seed = $user_array['token_seed']; $q_counter = $user_array['last_event'] + 1; $q_display_name = (('' != $display_name)?$display_name:(('' != $description)?$description:$the_user)); $q_issuer = $this->GetIssuer(); switch (strtolower($q_algorithm)) { case 'totp': $result = 'otpauth://'.$q_algorithm.'/'.rawurlencode($q_display_name).'?secret='.base32_encode(hex2bin($q_seed)).'&digits='.$q_digits.'&period='.$q_period.'&issuer='.rawurlencode($q_issuer); break; case 'hotp': $result = 'otpauth://'.$q_algorithm.'/'.rawurlencode($q_display_name).'?secret='.base32_encode(hex2bin($q_seed)).'&digits='.$q_digits.'&counter='.$q_counter.'&issuer='.rawurlencode($q_issuer); break; case 'motp': $result = 'motp://'.rawurlencode($q_issuer).':'.rawurlencode($q_display_name).'?secret='.$q_seed; break; default: $result = 'http://motp.sourceforge.net/no_qrcode_compatible_client_for_this_algorithm'; $this->WriteLog("Error: No known URL compatible client for this algorithm", FALSE, FALSE, 23, 'System', ''); } } else { } return $result; } function GetTokenUrlLink( $token = '', $display_name = '' ) { $the_token = strtolower($token); $result = FALSE; if ('' != $the_token) { $this->SetToken($the_token); } if ($this->ReadTokenData()) { $the_token = $this->GetToken(); $q_algorithm = $this->GetTokenAlgorithm(); $q_algo_suite = $this->GetTokenAlgoSuite(); $q_period = $this->GetTokenTimeInterval(); $q_digits = $this->GetTokenNumberOfDigits(); $q_seed = $this->GetTokenSeed(); $q_counter = $this->GetTokenLastEvent() + 1; $q_display_name = (('' != $display_name)?$display_name:$the_token); $q_issuer = $this->GetTokenIssuer(); switch (strtolower($q_algorithm)) { case 'totp': $result = 'otpauth://'.$q_algorithm.'/'.rawurlencode($q_display_name).'?secret='.base32_encode(hex2bin($q_seed)).'&digits='.$q_digits.'&period='.$q_period.'&issuer='.rawurlencode($q_issuer); break; case 'hotp': $result = 'otpauth://'.$q_algorithm.'/'.rawurlencode($q_display_name).'?secret='.base32_encode(hex2bin($q_seed)).'&digits='.$q_digits.'&counter='.$q_counter.'&issuer='.rawurlencode($q_issuer); break; case 'motp': $result = 'motp://'.rawurlencode($q_issuer).':'.rawurlencode($q_display_name).'?secret='.$q_seed; break; default: $result = 'http://http://motp.sourceforge.net/no_qrcode_compatible_client_for_this_algorithm'; $this->WriteLog("Error: No known URL compatible client for this algorithm", FALSE, FALSE, 23, 'System', ''); } } else { } return $result; } function FastCreateUser($user, $email = '', $sms = '', $prefix_pin_needed = -1, $algorithm = "totp", $activated=1, $description = "", $group = "*DEFAULT*", $synchronized = 0, $pin = '', $automatically = false, $synchronized_channel = '', $synchronized_server = '', $synchronized_dn = '', $ldap_pwd_needed = -1, $language = '', $dialin_ip_address = '' ) { $result = FALSE; if ('' != trim($user)) { if ($this->ReadUserData($user, TRUE, TRUE) || ('' == $user)) { $this->WriteLog("Error: Unable to create the user ".$user." because it already exists", FALSE, FALSE, 22, 'User', $user); } else { if ((intval($ldap_pwd_needed) < 0) && (1 == $synchronized)) { $request_ldap_pwd = $this->GetDefaultRequestLdapPwd(); } else { $request_ldap_pwd = intval($ldap_pwd_needed); } if (intval($prefix_pin_needed) < 0) { $prefix_required = $this->GetDefaultRequestPrefixPin(); } else { $prefix_required = intval($prefix_pin_needed); } $this->SetUser($user, false); $this->SetUserEmail($email); $this->SetUserDescription($description); $this->SetUserLanguage($language); $this->SetUserGroup(('*DEFAULT*' == $group) ? $this->GetDefaultUserGroup() : $group); $this->SetUserSms($sms); $this->SetUserAlgorithm($algorithm); $this->SetUserTokenAlgoSuite(''); $the_pin = $pin; if ('' == $the_pin) { $the_pin = mt_rand(1000,9999); } $this->SetUserPrefixPin($prefix_required); $this->SetUserTokenNumberOfDigits(6); $next_event = 0; $seed = substr(md5(date("YmdHis").mt_rand(100000,999999)),0,20).substr(md5(mt_rand(100000,999999).date("YmdHis")),0,20); if ("totp" == strtolower($algorithm)) { $time_interval = 30; } elseif ("motp" == strtolower($algorithm)) { $seed = substr($seed,0,16); $time_interval = 10; if ((strlen($the_pin) < 4) || (0 == intval($the_pin))) { $the_pin = mt_rand(1000,9999); } } else { $time_interval = 0; } $this->SetUserPin($the_pin); $this->SetUserTokenSeed($seed); $this->SetUserTokenLastEvent($next_event-1); $this->SetUserTokenTimeInterval($time_interval); $this->SetUserActivated($activated); $this->SetUserSynchronized($synchronized); if (($automatically) && (1 == $synchronized)) { $this->SetUserSynchronizedTime(); $this->SetUserSynchronizedChannel($synchronized_channel); $this->SetUserSynchronizedServer($synchronized_server); $this->SetUserSynchronizedDn($synchronized_dn); } $this->SetUserRequestLdapPassword($request_ldap_pwd); $this->SetUserDialinIpAddress($dialin_ip_address); $result = $this->WriteUserData($automatically); } } return $result; } function SetUser( $user, $auto_read_data = true ) { $result = TRUE; $user_encoded = $user; if ('' != $user_encoded) { if ($user_encoded != $this->GetUser()) { $this->ResetUserArray(); $this->_user = $user_encoded; if (!$this->IsCaseSensitiveUsers()) { $this->_user = strtolower($this->_user); } if ($auto_read_data) { $result = $this->ReadUserData('', false); } } } else { $this->ResetUserArray(); } return ($result ? $user_encoded : FALSE); } function RenameCurrentUser( $new_user, $no_error_info = FALSE ) { if ($this->IsCaseSensitiveUsers()) { $the_new_user = $new_user; } else { $the_new_user = strtolower($new_user); } $result = FALSE; if ($this->CheckUserExists($the_new_user)) { $this->WriteLog("Error: Unable to rename the current user ".$this->GetUser()." to $the_new_user because $the_new_user already exists", FALSE, FALSE, 22, 'User'); } else { if ($this->CheckUserExists()) { if ((($this->GetBackendTypeValidated()) && ('' != $this->_config_data['sql_users_table'])) || ('files' == $this->GetBackendType())) { switch ($this->GetBackendType()) { case 'mysql': $esc_actual = escape_mysql_string($this->GetUser()); $esc_new = escape_mysql_string($the_new_user); if ($this->OpenMysqlDatabase()) { if ('' != $this->_config_data['sql_users_table']) { $sQuery = "UPDATE `".$this->_config_data['sql_users_table']."` SET user='".strtolower($esc_new)."' WHERE `user`='".$esc_actual."'"; if (is_object($this->_mysqli)) { if (!($rResult = $this->_mysqli->query($sQuery))) { if (!$no_error_info) { $this->WriteLog("Error: Could not rename the user ".$this->GetUser().": ".trim($this->_mysqli->error), FALSE, FALSE, 28, 'User'); } } else { $num_rows = $this->_mysqli->affected_rows; } } elseif (!($rResult = mysql_query($sQuery, $this->_mysql_database_link))) { if (!$no_error_info) { $this->WriteLog("Error: Could not rename the user ".$this->GetUser().": ".mysql_error(), FALSE, FALSE, 28, 'User'); } } else { $num_rows = mysql_affected_rows($this->_mysql_database_link); } if (0 == $num_rows) { $this->WriteLog("Error: Could not rename the user ".$this->GetUser().". User does not exist", FALSE, FALSE, 21, 'User'); } else { $this->WriteLog("Info: User ".$this->GetUser()." successfully renamed to $the_new_user", FALSE, FALSE, 11, 'User'); $result = TRUE; } } } break; case 'pgsql': $esc_actual = pg_escape_string($this->GetUser()); $esc_new = pg_escape_string($the_new_user); if ($this->OpenPGSQLDatabase()) { if ('' != $this->_config_data['sql_users_table']) { $sQuery = "UPDATE \"".$this->_config_data['sql_schema']."\".\"".$this->_config_data['sql_users_table']."\" SET \"user\" = '".strtolower($esc_new)."' WHERE \"user\" = '".$esc_actual."'"; if (!($rResult = pg_query($this->_pgsql_database_link, $sQuery))) { if (!$no_error_info) { $this->WriteLog("Error: Could not rename the user ".$this->GetUser().": ".pg_last_error(), FALSE, FALSE, 28, 'User'); } } else { $num_rows = pg_affected_rows($rResult); } if (0 == $num_rows) { $this->WriteLog("Error: Could not rename the user ".$this->GetUser().". User does not exist", FALSE, FALSE, 21, 'User'); } else { $this->WriteLog("Info: User ".$this->GetUser()." successfully renamed to $the_new_user", FALSE, FALSE, 11, 'User'); $result = TRUE; } } } break; case 'files': default: $old_user_filename = $this->EncodeFileId($this->GetUser(), $this->IsCaseSensitiveUsers()).'.db'; if (!file_exists($this->GetUsersFolder().$old_user_filename)) { $old_user_filename = $this->EncodeFileId($this->GetUser(), $this->IsCaseSensitiveUsers(), TRUE).'.db'; } if (file_exists($this->GetUsersFolder().$old_user_filename)) { $new_user_filename = $this->EncodeFileId($the_new_user, $this->IsCaseSensitiveUsers()).'.db'; rename($this->GetUsersFolder().$old_user_filename, $this->GetUsersFolder().$new_user_filename); $result = TRUE; } break; } } } if ($result) { $this->_user = strtolower($the_new_user); } } return $result; } function GetUser() { return $this->_user; } function CheckUserExists( $user = '', $no_server_check = FALSE, $no_error = FALSE ) { $check_user = ('' != $user)?$user:$this->GetUser(); $result = FALSE; if ('' != trim($check_user)) { $server_result = -1; if ((!$no_server_check) && ('' != $this->GetServerUrl())) { $server_result = $this->CheckUserExistsOnServer($check_user); if (22 == $server_result) { $result = TRUE; return $result; } } if ((($this->GetBackendTypeValidated()) && ('' != $this->_config_data['sql_users_table'])) || ('files' == $this->GetBackendType())) { switch ($this->GetBackendType()) { case 'mysql': if ($this->OpenMysqlDatabase()) { $sQuery = "SELECT * FROM `".$this->_config_data['sql_users_table']."` WHERE `user` = '{$check_user}'"; if (is_object($this->_mysqli)) { if (!($rResult = $this->_mysqli->query($sQuery))) { $this->WriteLog("Error: Unable to access the database: ".trim($this->_mysqli->error), FALSE, FALSE, 41, 'System', '', 3); } else { $num_rows = $rResult->num_rows; } } elseif (!($rResult = mysql_query($sQuery, $this->_mysql_database_link))) { $this->WriteLog("Error: Unable to access the database: ".mysql_error(), FALSE, FALSE, 41, 'System', '', 3); } else { $num_rows = mysql_num_rows($this->_mysql_database_link); } if (0 == $num_rows) { if (!$no_error) { $this->WriteLog("Error: User ".$check_user." does not exist", FALSE, FALSE, 21, 'System', ''); } $result = FALSE; } else { $result = TRUE; } } break; case 'pgsql': if ($this->OpenPGSQLDatabase()) { $sQuery = "SELECT * FROM \"".$this->_config_data['sql_schema']."\".\"".$this->_config_data['sql_users_table']."\" WHERE \"user\" = '{$check_user}';"; if (!($rResult = pg_query($this->_pgsql_database_link, $sQuery))) { $this->WriteLog("Error: Unable to access the database: ".pg_last_error(), FALSE, FALSE, 41, 'System', '', 3); } else { $num_rows = pg_num_rows($rResult); } if (0 == $num_rows) { if (!$no_error) { $this->WriteLog("Error: User ".$check_user." does not exist", FALSE, FALSE, 21, 'System', ''); } $result = FALSE; } else { $result = TRUE; } } break; case 'files': default: $user_filename = $this->EncodeFileId($check_user, $this->IsCaseSensitiveUsers()).'.db'; if (!file_exists($this->GetUsersFolder().$user_filename)) { $user_filename = $this->EncodeFileId($check_user, $this->IsCaseSensitiveUsers(), TRUE).'.db'; } $result = file_exists($this->GetUsersFolder().$user_filename); break; } } } return $result; } function LockUser( $user = '' ) { $result = FALSE; if ('' != $user) { $this->SetUser($user, false); } if ($this->ReadUserData('', FALSE, TRUE)) { $this->SetUserLocked(1); if ($this->GetVerboseFlag()) { $this->WriteLog("Info: *User ".$this->GetUser()." successfully locked", FALSE, FALSE, 19, 'User'); } $this->WriteUserData(); $result = TRUE; } return $result; } function UnlockUser( $user = '' ) { $result = FALSE; if ('' != $user) { $this->SetUser($user, false); } if ($this->ReadUserData('', FALSE, TRUE)) { $this->SetUserErrorCounter(0); $this->SetUserLocked(0); if ($this->GetVerboseFlag()) { $this->WriteLog("Info: *User ".$this->GetUser()." successfully unlocked", FALSE, FALSE, 19, 'User'); } $this->WriteUserData(); $result = TRUE; } return $result; } function DeleteUser( $user = '', $no_error_info = FALSE ) { if ('' != $user) { $this->SetUser($user, false); } $result = FALSE; if (('files' == $this->GetBackendType()) || ($this->GetMigrationFromFile())) { $user_filename = $this->EncodeFileId($this->GetUser(), $this->IsCaseSensitiveUsers()).'.db'; if (!file_exists($this->GetUsersFolder().$user_filename)) { $user_filename = $this->EncodeFileId($this->GetUser(), $this->IsCaseSensitiveUsers(), TRUE).'.db'; } if (!file_exists($this->GetUsersFolder().$user_filename)) { if (!$no_error_info) { if ($this->GetVerboseFlag()) { $this->WriteLog("Error: *Unable to delete user ".$this->GetUser().", the users database file ".$this->GetUsersFolder().$user_filename." does not exist", FALSE, FALSE, 21, 'User'); } else { $this->WriteLog("Error: Unable to delete user ".$this->GetUser(), FALSE, FALSE, 29, 'User'); } } } else { $result = unlink($this->GetUsersFolder().$user_filename); if ($result) { if ($this->GetVerboseFlag()) { $this->WriteLog("Info: *User ".$this->GetUser()." successfully deleted", FALSE, FALSE, 12, 'User'); } } elseif (!$this->GetMigrationFromFile()) { if (!$no_error_info) { $this->WriteLog("Error: Unable to delete user ".$this->GetUser(), FALSE, FALSE, 28, 'User'); } } } } if ($this->GetBackendTypeValidated()) { switch ($this->_config_data['backend_type']) { case 'mysql': if ($this->OpenMysqlDatabase()) { if ('' != $this->_config_data['sql_users_table']) { $sQuery = "DELETE FROM `".$this->_config_data['sql_users_table']."` WHERE `user` = '".$this->_user."'"; if (is_object($this->_mysqli)) { if (!($rResult = $this->_mysqli->query($sQuery))) { if (!$no_error_info) { $this->WriteLog("Error: Could not delete user ".$this->GetUser().": ".trim($this->_mysqli->error), FALSE, FALSE, 28, 'User'); } } else { $num_rows = $this->_mysqli->affected_rows; } } elseif (!($rResult = mysql_query($sQuery, $this->_mysql_database_link))) { if (!$no_error_info) { $this->WriteLog("Error: Could not delete user ".$this->GetUser().": ".mysql_error(), FALSE, FALSE, 28, 'User'); } } else { $num_rows = mysql_affected_rows($this->_mysql_database_link); } if (0 == $num_rows) { if (!$no_error_info) { $this->WriteLog("Error: Could not delete user ".$this->GetUser().". User does not exist", FALSE, FALSE, 21, 'User'); } } else { if ($this->GetVerboseFlag()) { $this->WriteLog("Info: *User ".$this->GetUser()." successfully deleted", FALSE, FALSE, 12, 'User'); } $result = TRUE; } } } break; case 'pgsql': if ($this->OpenPGSQLDatabase()) { if ('' != $this->_config_data['sql_users_table']) { $sQuery = "DELETE FROM \"".$this->_config_data['sql_schema']."\".\"".$this->_config_data['sql_users_table']."\" WHERE \"user\" = '".$this->_user."'"; if (!($rResult = pg_query($this->_pgsql_database_link, $sQuery))) { if (!$no_error_info) { $this->WriteLog("Error: Could not delete user ".$this->GetUser().": ".pg_last_error(), FALSE, FALSE, 28, 'User'); } } else { $num_rows = pg_affected_rows($rResult); } if (0 == $num_rows) { if (!$no_error_info) { $this->WriteLog("Error: Could not delete user ".$this->GetUser().". User does not exist", FALSE, FALSE, 21, 'User'); } } else { if ($this->GetVerboseFlag()) { $this->WriteLog("Info: *User ".$this->GetUser()." successfully deleted", FALSE, FALSE, 12, 'User'); } $result = TRUE; } } } break; default: break; } } if ($result) { foreach(explode("\t", $this->GetTokensList()) as $one_token) { if ($this->RemoveTokenAttributedUsers($one_token, $this->GetUser())) { $this->WriteTokenData(); } } $this->TouchFolder('data', 'User', $this->GetUser(), TRUE, "DeleteUser"); } return $result; } function GetUsersCount($no_cache = FALSE) { if (($this->IsCacheData()) && (intval($this->ReadCacheValue('users_count')) >= 0) && (!$no_cache)) { $users_count = intval($this->ReadCacheValue('users_count')); } else { $users_count = 0; switch ($this->GetBackendType()) { case 'mysql': if ($this->OpenMysqlDatabase()) { $sQuery = "SELECT COUNT(user) AS counter FROM `".$this->_config_data['sql_users_table']."` "; if (is_object($this->_mysqli)) { if (!($result = $this->_mysqli->query($sQuery))) { $this->WriteLog("Error: Unable to access the database: ".trim($this->_mysqli->error), FALSE, FALSE, 41, 'System', '', 3); $result = FALSE; } else { if ($aRow = $result->fetch_assoc()) { $users_count = $aRow['counter']; } } } else { if (!($rResult = mysql_query($sQuery, $this->_mysql_database_link))) { $this->WriteLog("Error: Unable to access the database: ".mysql_error(), FALSE, FALSE, 41, 'System', '', 3); } else { if ($aRow = mysql_fetch_assoc($rResult)) { $users_count = $aRow['counter']; } } } } break; case 'pgsql': if ($this->OpenPGSQLDatabase()) { $sQuery = "SELECT COUNT(\"user\") AS \"counter\" FROM \"".$this->_config_data['sql_schema']."\".\"".$this->_config_data['sql_users_table']."\" "; if (!($rResult = pg_query($this->_pgsql_database_link, $sQuery))) { $this->WriteLog("Error: Unable to access the database: ".pg_last_error(), FALSE, FALSE, 41, 'System', '', 3); } else { if ($aRow = pg_fetch_assoc($rResult)) { $users_count = $aRow['counter']; } } } break; case 'files': default: if ($users_handle = @opendir($this->GetUsersFolder())) { while ($file = readdir($users_handle)) { if ((substr($file, -3) == ".db") && ($file != '.db')) { $users_count++; } } closedir($users_handle); } } if (($this->IsCacheData()) && ($users_count >= 0)) { $this->WriteCacheValue('users_count', $users_count); $this->WriteCacheData(); } } return $users_count; } function ReadUserDataArray( $user = '', $create = false, $no_server_check = false ) { $array_user = ('' != $user)?$user:$this->GetUser(); $result = false; $temp_user_array = $this->ResetTempUserArray(); if (('files' == $this->GetBackendType()) || ($this->GetMigrationFromFile())) { $user_filename = $this->EncodeFileId($array_user, $this->IsCaseSensitiveUsers()).'.db'; if (!file_exists($this->GetUsersFolder().$user_filename)) { $user_filename = $this->EncodeFileId($array_user, $this->IsCaseSensitiveUsers(), TRUE).'.db'; } if (!file_exists($this->GetUsersFolder().$user_filename)) { if (!$create) { $this->WriteLog("Error: database file ".$this->GetUsersFolder().$user_filename." for user ".$array_user." does not exist", FALSE, FALSE, 21, 'System', ''); } } else { $temp_user_array['multi_account'] = 0; $temp_user_array['time_interval'] = 0; if ($file_handler = @fopen($this->GetUsersFolder().$user_filename, "rt")) { $first_line = trim(fgets($file_handler)); $v3 = (false !== strpos(strtolower($first_line),"multiotp-database-format-v3")); if (false === strpos(strtolower($first_line),"multiotp-database-format")) { $temp_user_array['algorithm'] = $first_line; $temp_user_array['token_seed'] = trim(fgets($file_handler)); $temp_user_array['user_pin'] = trim(fgets($file_handler)); $temp_user_array['number_of_digits'] = trim(fgets($file_handler)); $temp_user_array['last_event'] = intval(trim(fgets($file_handler)) - 1); $temp_user_array['request_prefix_pin'] = intval(trim(fgets($file_handler))); $temp_user_array['last_login'] = intval(trim(fgets($file_handler))); $temp_user_array['error_counter'] = intval(trim(fgets($file_handler))); $temp_user_array['locked'] = intval(trim(fgets($file_handler))); } else { while (!feof($file_handler)) { $line = trim(fgets($file_handler)); $line_array = explode("=",$line,2); if ($v3) { if (":" == substr($line_array[0], -1)) { $line_array[0] = substr($line_array[0], 0, strlen($line_array[0]) -1); $line_array[1] = $this->Decrypt($line_array[0],$line_array[1],$this->GetEncryptionKey()); } } else { if ((FALSE !== strpos(strtolower($this->GetAttributesToEncrypt()), strtolower('*'.$line_array[0].'*'))) || ("*all*" == strtolower($this->GetAttributesToEncrypt()))) { $line_array[1] = $this->Decrypt($line_array[0],$line_array[1],$this->GetEncryptionKey()); } } if ('' != trim($line_array[0])) { $temp_user_array[strtolower($line_array[0])] = $line_array[1]; } } } fclose($file_handler); $result = true; } if ('' != $temp_user_array['encryption_hash']) { if ($temp_user_array['encryption_hash'] != $this->CalculateControlHash($this->GetEncryptionKey())) { $temp_user_array['encryption_hash'] = "ERROR"; $this->WriteLog("Error: the user information encryption key is not matching", FALSE, FALSE, 33, 'System', ''); $result = false; } } } } if ($this->GetBackendTypeValidated()) { switch ($this->_config_data['backend_type']) { case 'mysql': if ($this->OpenMysqlDatabase()) { if ('' != $this->_config_data['sql_users_table']) { $sQuery = "SELECT * FROM `".$this->_config_data['sql_users_table']."` WHERE `user` = '".$array_user."'"; $aRow = NULL; if (is_object($this->_mysqli)) { if (!($rResult = $this->_mysqli->query($sQuery))) { $this->WriteLog("Error: SQL query error ($sQuery) : ".trim($this->_mysqli->error).' ', TRUE, FALSE, 40, 'System', '', 3); $result = false; } else { $aRow = $rResult->fetch_assoc(); } } else { if (!($rResult = mysql_query($sQuery, $this->_mysql_database_link))) { $this->WriteLog("Error: SQL query error ($sQuery) : ".mysql_error(), TRUE, FALSE, 40, 'System', '', 3); $result = false; } else { $aRow = mysql_fetch_assoc($rResult); } } if (NULL != $aRow) { $result = false; while(list($key, $value) = @each($aRow)) { $in_the_schema = FALSE; reset($this->_sql_tables_schema['users']); while(list($valid_key, $valid_format) = @each($this->_sql_tables_schema['users'])) { if ($valid_key == $key) { $in_the_schema = TRUE; break; } } if (($in_the_schema) && ($key != 'user')) { if (('ENC:' == substr($value,0,4)) && (':ENC' == substr($value,-4))) { $value = substr($value,4); $value = substr($value,0,strlen($value)-4); $temp_user_array[$key] = $this->Decrypt($key,$value,$this->GetEncryptionKey()); } else { $temp_user_array[$key] = $value; } } elseif ((!$in_the_schema) && ('unique_id' != $key) && $this->GetVerboseFlag()) { $this->WriteLog("Warning: *The key ".$key." is not in the users table schema", FALSE, FALSE, 42, 'System', '', 3); } $result = true; } if(0 == count($aRow) && !$create) { $this->WriteLog("Error: SQL database entry for user ".$array_user." does not exist", FALSE, FALSE, 21, 'System', ''); } } } if ('' != $temp_user_array['encryption_hash']) { if ($temp_user_array['encryption_hash'] != $this->CalculateControlHash($this->GetEncryptionKey())) { $temp_user_array['encryption_hash'] = "ERROR"; $this->WriteLog("Error: the users mysql encryption key is not matching", FALSE, FALSE, 33, 'System', ''); $result = false; } } } break; case 'pgsql': if ($this->OpenPGSQLDatabase()) { if ('' != $this->_config_data['sql_users_table']) { $sQuery = "SELECT * FROM \"".$this->_config_data['sql_schema']."\".\"".$this->_config_data['sql_users_table']."\" WHERE \"user\" = '".$array_user."'"; $aRow = NULL; if (!($rResult = pg_query($this->_pgsql_database_link, $sQuery))) { $this->WriteLog("Error: SQL query error ($sQuery) : ".pg_last_error(), TRUE, FALSE, 40, 'System', '', 3); $result = false; } else { $aRow = pg_fetch_assoc($rResult); } if (NULL != $aRow) { $result = false; while(list($key, $value) = @each($aRow)) { $in_the_schema = FALSE; reset($this->_sql_tables_schema['users']); while(list($valid_key, $valid_format) = @each($this->_sql_tables_schema['users'])) { if ($valid_key == $key) { $in_the_schema = TRUE; break; } } if (($in_the_schema) && ($key != 'user')) { if (('ENC:' == substr($value,0,4)) && (':ENC' == substr($value,-4))) { $value = substr($value,4); $value = substr($value,0,strlen($value)-4); $temp_user_array[$key] = $this->Decrypt($key,$value,$this->GetEncryptionKey()); } else { $temp_user_array[$key] = $value; } } elseif ((!$in_the_schema) && ('unique_id' != $key) && $this->GetVerboseFlag()) { $this->WriteLog("Warning: *The key ".$key." is not in the users table schema", FALSE, FALSE, 42, 'System', '', 3); } $result = true; } if(0 == count($aRow) && !$create) { $this->WriteLog("Error: SQL database entry for user ".$array_user." does not exist", FALSE, FALSE, 21, 'System', ''); } } } if ('' != $temp_user_array['encryption_hash']) { if ($temp_user_array['encryption_hash'] != $this->CalculateControlHash($this->GetEncryptionKey())) { $temp_user_array['encryption_hash'] = "ERROR"; $this->WriteLog("Error: the users pgsql encryption key is not matching", FALSE, FALSE, 33, 'System', ''); $result = false; } } } break; default: break; } } $server_result = -1; if ((!$no_server_check) && ('' != $this->GetServerUrl())) { $server_result = $this->ReadUserDataOnServer($array_user); if (20 < strlen($server_result)) { $temp_user_array['encryption_hash'] = $this->CalculateControlHash($this->GetEncryptionKey()); $server_array = explode("\n",$server_result); $server_result = 19; foreach ($server_array as $one_line) { $line = trim($one_line); $line_array = explode("=",$line,2); if (":" == substr($line_array[0], -1)) { $line_array[0] = substr($line_array[0], 0, strlen($line_array[0]) -1); $line_array[1] = $this->Decrypt($line_array[0], $line_array[1], $this->GetServerSecret()); } if ('' != trim($line_array[0])) { if ('encryption_hash' != strtolower($line_array[0])) { $temp_user_array[strtolower($line_array[0])] = $line_array[1]; } } } $result = true; } } $now_epoch = time(); $temp_user_array['delayed_account'] = (($temp_user_array['error_counter'] >= $this->GetMaxDelayedFailures()) && ($now_epoch < ($temp_user_array['last_error'] + $this->GetMaxDelayedTime()))); $temp_user_array['delayed_time'] = 0; $temp_user_array['delayed_finished'] = 0; if ($temp_user_array['delayed_account']) { $temp_user_array['delayed_time'] = ($temp_user_array['last_error'] + $this->GetMaxDelayedTime()) - $now_epoch; $temp_user_array['delayed_finished'] = ($temp_user_array['last_error'] + $this->GetMaxDelayedTime()); } if (false !== $result) { return $temp_user_array; } else { return false; } } function ReadUserData( $user = '', $create = FALSE, $no_server_check = FALSE ) { if ('' != $user) { $this->SetUser($user, false); } $result = false; $temp_user_array = $this->ReadUserDataArray($user, $create, $no_server_check); if (false !== $temp_user_array) { $this->_user_data = $temp_user_array; $result = true; } else { $this->_user_data = $this->ResetUserArray(); } $this->SetUserDataReadFlag($result); return $result; } function WriteUserData( $write_user_data_array = false, $update_last_change_param = true ) { if (is_array($write_user_data_array)) { if (!isset($write_user_data_array['automatically'])) { $write_user_data_array['automatically'] = false; } if (!isset($write_user_data_array['update_last_change'])) { $write_user_data_array['update_last_change'] = true; } } else { $temp_array = array(); $temp_array['automatically'] = $write_user_data_array; $temp_array['update_last_change'] = $update_last_change_param; $write_user_data_array = $temp_array; } if ('' == trim($this->GetUser())) { $result = false; } else { $result = $this->WriteData(array_merge(array('item' => 'User', 'table' => 'users', 'folder' => $this->GetUsersFolder(), 'data_array' => $this->_user_data, 'force_file' => false, 'id_field' => 'user', 'id_value' => $this->GetUser(), 'encode_file_id' => $this->IsEncodeFileId(), 'id_case_sensitive' => $this->IsCaseSensitiveUsers() ), $write_user_data_array)); } return $result; } function GetUsersList() { return $this->GetList('user', 'sql_users_table', $this->GetUsersFolder()); } function GetDelayedUsersList( $limit = 0 ) { $delayed_users_list = ''; $delayed_users_count = 0; if ((($this->GetBackendTypeValidated()) && ('' != $this->_config_data['sql_users_table'])) || ('files' == $this->GetBackendType())) { switch ($this->GetBackendType()) { case 'mysql': if ($this->OpenMysqlDatabase()) { $sQuery = "SELECT user, error_counter, last_error FROM `".$this->_config_data['sql_users_table']."` WHERE (`locked` = 0) ORDER BY user ASC"; if ($limit > 0) { $sQuery.= " LIMIT 0,".$limit; } if (is_object($this->_mysqli)) { if (!($result = $this->_mysqli->query($sQuery))) { $this->WriteLog("Error: Unable to access the database: ".trim($this->_mysqli->error), FALSE, FALSE, 41, 'System', '', 3); $result = FALSE; } else { while ($aRow = $result->fetch_assoc()) { if ('' != $aRow['user']) { $now_epoch = time(); if (($aRow['error_counter'] >= $this->GetMaxDelayedFailures()) && ($now_epoch < ($aRow['last_error'] + $this->GetMaxDelayedTime()))) { $delayed_time = ($aRow['last_error'] + $this->GetMaxDelayedTime()) - $now_epoch; $delayed_finished = $aRow['last_error'] + $this->GetMaxDelayedTime(); $delayed_users_list.= (('' != $delayed_users_list)?"\t":'').$aRow['user'].'|'.$delayed_finished; $delayed_users_count++; } } } } } else { if (!($rResult = mysql_query($sQuery, $this->_mysql_database_link))) { $this->WriteLog("Error: Unable to access the database: ".mysql_error(), FALSE, FALSE, 41, 'System', '', 3); } else { while ($aRow = mysql_fetch_assoc($rResult)) { if ('' != $aRow['user']) { $now_epoch = time(); if (($aRow['error_counter'] >= $this->GetMaxDelayedFailures()) && ($now_epoch < ($aRow['last_error'] + $this->GetMaxDelayedTime()))) { $delayed_time = ($aRow['last_error'] + $this->GetMaxDelayedTime()) - $now_epoch; $delayed_finished = $aRow['last_error'] + $this->GetMaxDelayedTime(); $delayed_users_list.= (('' != $delayed_users_list)?"\t":'').$aRow['user'].'|'.$delayed_finished; $delayed_users_count++; } } } } } } break; case 'pgsql': if ($this->OpenPGSQLDatabase()) { $sQuery = "SELECT \"user\", \"error_counter\", \"last_error\" FROM \"".$this->_config_data['sql_schema']."\".\"".$this->_config_data['sql_users_table']."\" WHERE (\"locked\" = 0) ORDER BY \"user\" ASC"; if ($limit > 0) { $sQuery.= " LIMIT 0,".$limit; } if (!($rResult = pg_query($this->_pgsql_database_link, $sQuery))) { $this->WriteLog("Error: Unable to access the database: ".pg_last_error(), FALSE, FALSE, 41, 'System', '', 3); } else { while ($aRow = pg_fetch_assoc($rResult)) { if ('' != $aRow['user']) { $now_epoch = time(); if (($aRow['error_counter'] >= $this->GetMaxDelayedFailures()) && ($now_epoch < ($aRow['last_error'] + $this->GetMaxDelayedTime()))) { $delayed_time = ($aRow['last_error'] + $this->GetMaxDelayedTime()) - $now_epoch; $delayed_finished = $aRow['last_error'] + $this->GetMaxDelayedTime(); $delayed_users_list.= (('' != $delayed_users_list)?"\t":'').$aRow['user'].'|'.$delayed_finished; $delayed_users_count++; } } } } } break; case 'files': default: $users_count = 0; if ($users_handle = @opendir($this->GetUsersFolder())) { while ($file = readdir($users_handle)) { $error_counter = 0; $last_error = 0; $desactivated = FALSE; $locked = FALSE; if ((substr($file, -3) == ".db") && ($file != '.db')) { $current_user = $this->DecodeFileId(substr($file,0,-3)); if ($file_handler = @fopen($this->GetUsersFolder().$file, "rt")) { $first_line = trim(fgets($file_handler)); $v3 = (FALSE !== strpos(strtolower($first_line),"multiotp-database-format-v3")); if (FALSE !== strpos(strtolower($first_line),"multiotp-database-format")) { while (!feof($file_handler)) { $line = trim(fgets($file_handler)); $line_array = explode("=",$line,2); if ($v3) { if (":" == substr($line_array[0], -1)) { $line_array[0] = substr($line_array[0], 0, strlen($line_array[0]) -1); $line_array[1] = $this->Decrypt($line_array[0],$line_array[1],$this->GetEncryptionKey()); } } else { if ((FALSE !== strpos(strtolower($this->GetAttributesToEncrypt()), strtolower('*'.$line_array[0].'*'))) || ("*all*" == strtolower($this->GetAttributesToEncrypt()))) { $line_array[1] = $this->Decrypt($line_array[0],$line_array[1],$this->GetEncryptionKey()); } } if ('error_counter' == trim($line_array[0])) { $error_counter = $line_array[1]; } if ('last_error' == trim($line_array[0])) { $last_error = $line_array[1]; } if ('desactivated' == trim($line_array[0])) { if (1 == (isset($line_array[1])?$line_array[1]:0)) { $desactivated = TRUE; } } if ('locked' == trim($line_array[0])) { if (1 == (isset($line_array[1])?$line_array[1]:0)) { $locked = TRUE; } } } } fclose($file_handler); $users_count++; $now_epoch = time(); if (($error_counter >= $this->GetMaxDelayedFailures()) && ($now_epoch < ($last_error + $this->GetMaxDelayedTime()))) { $delayed_time = ($last_error + $this->GetMaxDelayedTime()) - $now_epoch; $delayed_finished = $last_error + $this->GetMaxDelayedTime(); if (!$locked) { $delayed_users_list.= (('' != $delayed_users_list)?"\t":'').$current_user.'|'.$delayed_finished; $delayed_users_count++; } } } } if (($limit > 0) && ($delayed_users_count >= $limit)) { break; } } closedir($users_handle); } } } return $delayed_users_list; } function GetLockedUsersList( $limit = 0 ) { if (($this->IsCacheData()) && (($this->ReadCacheValue('locked_users_list')) != '-1')) { $locked_users_list = ($this->ReadCacheValue('locked_users_list')); } else { $locked_users_list = ''; if ((($this->GetBackendTypeValidated()) && ('' != $this->_config_data['sql_users_table'])) || ('files' == $this->GetBackendType())) { switch ($this->GetBackendType()) { case 'mysql': if ($this->OpenMysqlDatabase()) { $sQuery = "SELECT user FROM `".$this->_config_data['sql_users_table']."` WHERE (`locked` = 1) ORDER BY user ASC"; if ($limit > 0) { $sQuery.= " LIMIT 0,".$limit; } if (is_object($this->_mysqli)) { if (!($result = $this->_mysqli->query($sQuery))) { $this->WriteLog("Error: Unable to access the database: ".trim($this->_mysqli->error), FALSE, FALSE, 41, 'System', '', 3); $result = FALSE; } else { while ($aRow = $result->fetch_assoc()) { if ('' != $aRow['user']) { $locked_users_list.= (('' != $locked_users_list)?"\t":'').$aRow['user']; } } } } else { if (!($rResult = mysql_query($sQuery, $this->_mysql_database_link))) { $this->WriteLog("Error: Unable to access the database: ".mysql_error(), FALSE, FALSE, 41, 'System', '', 3); } else { while ($aRow = mysql_fetch_assoc($rResult)) { if ('' != $aRow['user']) { $locked_users_list.= (('' != $locked_users_list)?"\t":'').$aRow['user']; } } } } } break; case 'pgsql': if ($this->OpenPGSQLDatabase()) { $sQuery = "SELECT \"user\" FROM \"".$this->_config_data['sql_schema']."\".\"".$this->_config_data['sql_users_table']."\" WHERE (\"locked\" = 1) ORDER BY \"user\" ASC"; if ($limit > 0) { $sQuery.= " LIMIT 0,".$limit; } if (!($rResult = pg_query($this->_pgsql_database_link, $sQuery))) { $this->WriteLog("Error: Unable to access the database: ".pg_last_error(), FALSE, FALSE, 41, 'System', '', 3); } else { while ($aRow = pg_fetch_assoc($rResult)) { if ('' != $aRow['user']) { $locked_users_list.= (('' != $locked_users_list)?"\t":'').$aRow['user']; } } } } break; case 'files': default: $locked_users_count = 0; $active_users_count = 0; $users_count = 0; if ($users_handle = @opendir($this->GetUsersFolder())) { while ($file = readdir($users_handle)) { $locked = FALSE; $desactivated = FALSE; if ((substr($file, -3) == ".db") && ($file != '.db')) { $current_user = $this->DecodeFileId(substr($file,0,-3)); if ($file_handler = @fopen($this->GetUsersFolder().$file, "rt")) { $first_line = trim(fgets($file_handler)); $v3 = (FALSE !== strpos(strtolower($first_line),"multiotp-database-format-v3")); if (FALSE !== strpos(strtolower($first_line),"multiotp-database-format")) { while (!feof($file_handler)) { $line = trim(fgets($file_handler)); $line_array = explode("=",$line,2); if ($v3) { if (":" == substr($line_array[0], -1)) { $line_array[0] = substr($line_array[0], 0, strlen($line_array[0]) -1); $line_array[1] = $this->Decrypt($line_array[0],$line_array[1],$this->GetEncryptionKey()); } } else { if ((FALSE !== strpos(strtolower($this->GetAttributesToEncrypt()), strtolower('*'.$line_array[0].'*'))) || ("*all*" == strtolower($this->GetAttributesToEncrypt()))) { $line_array[1] = $this->Decrypt($line_array[0],$line_array[1],$this->GetEncryptionKey()); } } if ('locked' == trim($line_array[0])) { if (1 == (isset($line_array[1])?$line_array[1]:0)) { $locked = TRUE; } } if ('desactivated' == trim($line_array[0])) { if (1 == (isset($line_array[1])?$line_array[1]:0)) { $desactivated = TRUE; } } } } fclose($file_handler); $users_count++; if ($locked) { $locked_users_list.= (('' != $locked_users_list)?"\t":'').$current_user; $locked_users_count++; } if (!$desactivated) { $active_users_count++; } } } if (($limit > 0) && ($locked_users_count >= $limit)) { break; } } closedir($users_handle); if (($limit <= 0) && ($this->IsCacheData())) { $this->WriteCacheValue('locked_users_list', $locked_users_list); if ($locked_users_count >= 0) { $this->WriteCacheValue('locked_users_count', $locked_users_count); } if ($active_users_count >= 0) { $this->WriteCacheValue('active_users_count', $active_users_count); } if ($users_count >= 0) { $this->WriteCacheValue('users_count', $users_count); } $this->WriteCacheData(); } } } } } return $locked_users_list; } function GetLockedUsersCount() { if (($this->IsCacheData()) && (intval($this->ReadCacheValue('locked_users_count')) >= 0)) { $locked_users_count = intval($this->ReadCacheValue('locked_users_count')); } else { $locked_users_count = 0; $active_users_count = -1; if ((($this->GetBackendTypeValidated()) && ('' != $this->_config_data['sql_users_table'])) || ('files' == $this->GetBackendType())) { switch ($this->GetBackendType()) { case 'mysql': if ($this->OpenMysqlDatabase()) { $sQuery = "SELECT COUNT(user) AS counter FROM `".$this->_config_data['sql_users_table']."` WHERE (`locked` = 1)"; if (is_object($this->_mysqli)) { if (!($result = $this->_mysqli->query($sQuery))) { $this->WriteLog("Error: Unable to access the database: ".trim($this->_mysqli->error), FALSE, FALSE, 41, 'System', '', 3); $result = FALSE; } else { if ($aRow = $result->fetch_assoc()) { $locked_users_count = $aRow['counter']; } } } else { if (!($rResult = mysql_query($sQuery, $this->_mysql_database_link))) { $this->WriteLog("Error: Unable to access the database: ".mysql_error(), FALSE, FALSE, 41, 'System', '', 3); } else { if ($aRow = mysql_fetch_assoc($rResult)) { $locked_users_count = $aRow['counter']; } } } } break; case 'pgsql': if ($this->OpenPGSQLDatabase()) { $sQuery = "SELECT COUNT(\"user\") AS \"counter\" FROM \"".$this->_config_data['sql_schema']."\".\"".$this->_config_data['sql_users_table']."\" WHERE (\"locked\" = 1)"; if (!($rResult = pg_query($this->_pgsql_database_link, $sQuery))) { $this->WriteLog("Error: Unable to access the database: ".pg_last_error(), FALSE, FALSE, 41, 'System', '', 3); } else { if ($aRow = pg_fetch_assoc($rResult)) { $locked_users_count = $aRow['counter']; } } } break; case 'files': default: $active_users_count = 0; $users_count = 0; if ($users_handle = @opendir($this->GetUsersFolder())) { while ($file = readdir($users_handle)) { $locked = FALSE; $desactivated = FALSE; if ((substr($file, -3) == ".db") && ($file != '.db')) { $current_user = $this->DecodeFileId(substr($file,0,-3)); if ($file_handler = @fopen($this->GetUsersFolder().$file, "rt")) { $first_line = trim(fgets($file_handler)); $v3 = (FALSE !== strpos(strtolower($first_line),"multiotp-database-format-v3")); if (FALSE !== strpos(strtolower($first_line),"multiotp-database-format")) { while (!feof($file_handler)) { $line = trim(fgets($file_handler)); $line_array = explode("=",$line,2); if ($v3) { if (":" == substr($line_array[0], -1)) { $line_array[0] = substr($line_array[0], 0, strlen($line_array[0]) -1); $line_array[1] = $this->Decrypt($line_array[0],$line_array[1],$this->GetEncryptionKey()); } } else { if ((FALSE !== strpos(strtolower($this->GetAttributesToEncrypt()), strtolower('*'.$line_array[0].'*'))) || ("*all*" == strtolower($this->GetAttributesToEncrypt()))) { $line_array[1] = $this->Decrypt($line_array[0],$line_array[1],$this->GetEncryptionKey()); } } if ('locked' == trim($line_array[0])) { if (1 == (isset($line_array[1])?$line_array[1]:0)) { $locked = TRUE; } } if ('desactivated' == trim($line_array[0])) { if (1 == (isset($line_array[1])?$line_array[1]:0)) { $desactivated = TRUE; } } } } fclose($file_handler); $users_count++; if ($locked) { $locked_users_count++; } if (!$desactivated) { $active_users_count++; } } } } closedir($users_handle); } } } if ($this->IsCacheData()) { if ($locked_users_count >= 0) { $this->WriteCacheValue('locked_users_count', $locked_users_count); } if ($active_users_count >= 0) { $this->WriteCacheValue('active_users_count', $active_users_count); } if ($users_count >= 0) { $this->WriteCacheValue('users_count', $users_count); } $this->WriteCacheData(); } } return $locked_users_count; } function GetActiveUsersList( $limit = 0 ) { $list = ''; if ((($this->GetBackendTypeValidated()) && ('' != $this->_config_data['sql_users_table'])) || ('files' == $this->GetBackendType())) { switch ($this->GetBackendType()) { case 'mysql': if ($this->OpenMysqlDatabase()) { $sQuery = "SELECT user FROM `".$this->_config_data['sql_users_table']."` WHERE (`desactivated` = 0) ORDER BY user ASC"; if ($limit > 0) { $sQuery.= " LIMIT 0,".$limit; } if (is_object($this->_mysqli)) { if (!($result = $this->_mysqli->query($sQuery))) { $this->WriteLog("Error: Unable to access the database: ".trim($this->_mysqli->error), FALSE, FALSE, 41, 'System', '', 3); $result = FALSE; } else { while ($aRow = $result->fetch_assoc()) { if ('' != $aRow['user']) { $list.= (('' != $list)?"\t":'').$aRow['user']; } } } } else { if (!($rResult = mysql_query($sQuery, $this->_mysql_database_link))) { $this->WriteLog("Error: Unable to access the database: ".mysql_error(), FALSE, FALSE, 41, 'System', '', 3); } else { while ($aRow = mysql_fetch_assoc($rResult)) { if ('' != $aRow['user']) { $list.= (('' != $list)?"\t":'').$aRow['user']; } } } } } break; case 'pgsql': if ($this->OpenPGSQLDatabase()) { $sQuery = "SELECT \"user\" FROM \"".$this->_config_data['sql_schema']."\".\"".$this->_config_data['sql_users_table']."\" WHERE (\"desactivated\" = 0) ORDER BY \"user\" ASC"; if ($limit > 0) { $sQuery.= " LIMIT 0,".$limit; } if (!($rResult = pg_query($this->_pgsql_database_link, $sQuery))) { $this->WriteLog("Error: Unable to access the database: ".pg_last_error(), FALSE, FALSE, 41, 'System', '', 3); } else { while ($aRow = pg_fetch_assoc($rResult)) { if ('' != $aRow['user']) { $list.= (('' != $list)?"\t":'').$aRow['user']; } } } } break; case 'files': default: $active_users_count = 0; $locked_users_count = 0; $users_count = 0; if ($users_handle = @opendir($this->GetUsersFolder())) { while ($file = readdir($users_handle)) { $desactivated = FALSE; $locked = FALSE; if ((substr($file, -3) == ".db") && ($file != '.db')) { $current_user = $this->DecodeFileId(substr($file,0,-3)); if ($file_handler = @fopen($this->GetUsersFolder().$file, "rt")) { $first_line = trim(fgets($file_handler)); $v3 = (FALSE !== strpos(strtolower($first_line),"multiotp-database-format-v3")); if (FALSE !== strpos(strtolower($first_line),"multiotp-database-format")) { while (!feof($file_handler)) { $line = trim(fgets($file_handler)); $line_array = explode("=",$line,2); if ($v3) { if (":" == substr($line_array[0], -1)) { $line_array[0] = substr($line_array[0], 0, strlen($line_array[0]) -1); $line_array[1] = $this->Decrypt($line_array[0],$line_array[1],$this->GetEncryptionKey()); } } else { if ((FALSE !== strpos(strtolower($this->GetAttributesToEncrypt()), strtolower('*'.$line_array[0].'*'))) || ("*all*" == strtolower($this->GetAttributesToEncrypt()))) { $line_array[1] = $this->Decrypt($line_array[0],$line_array[1],$this->GetEncryptionKey()); } } if ('desactivated' == trim($line_array[0])) { if (1 == (isset($line_array[1])?$line_array[1]:0)) { $desactivated = TRUE; } } if ('locked' == trim($line_array[0])) { if (1 == (isset($line_array[1])?$line_array[1]:0)) { $locked = TRUE; } } } } fclose($file_handler); $users_count++; if (!$desactivated) { $list.= (('' != $list)?"\t":'').$current_user; $active_users_count++; } if ($locked) { $locked_users_count++; } } } if (($limit > 0) && (active_users_count >= $limit)) { break; } } closedir($users_handle); if (($limit <= 0) && ($this->IsCacheData())) { if ($locked_users_count >= 0) { $this->WriteCacheValue('locked_users_count', $locked_users_count); } if ($active_users_count >= 0) { $this->WriteCacheValue('active_users_count', $active_users_count); } if ($users_count >= 0) { $this->WriteCacheValue('users_count', $users_count); } $this->WriteCacheData(); } } } } return $list; } function GetActiveUsersCount() { if (($this->IsCacheData()) && (intval($this->ReadCacheValue('active_users_count')) >= 0)) { $active_users_count = intval($this->ReadCacheValue('active_users_count')); } else { $active_users_count = 0; $locked_users_count = -1; if ((($this->GetBackendTypeValidated()) && ('' != $this->_config_data['sql_users_table'])) || ('files' == $this->GetBackendType())) { switch ($this->GetBackendType()) { case 'mysql': if ($this->OpenMysqlDatabase()) { $sQuery = "SELECT COUNT(user) AS counter FROM `".$this->_config_data['sql_users_table']."` WHERE (`desactivated` = 0)"; if (is_object($this->_mysqli)) { if (!($result = $this->_mysqli->query($sQuery))) { $this->WriteLog("Error: Unable to access the database: ".trim($this->_mysqli->error), FALSE, FALSE, 41, 'System', '', 3); $result = FALSE; } else { if ($aRow = $result->fetch_assoc()) { $active_users_count = $aRow['counter']; } } } else { if (!($rResult = mysql_query($sQuery, $this->_mysql_database_link))) { $this->WriteLog("Error: Unable to access the database: ".mysql_error(), FALSE, FALSE, 41, 'System', '', 3); } else { if ($aRow = mysql_fetch_assoc($rResult)) { $active_users_count = $aRow['counter']; } } } } break; case 'pgsql': if ($this->OpenPGSQLDatabase()) { $sQuery = "SELECT COUNT(\"user\") AS \"counter\" FROM \"".$this->_config_data['sql_schema']."\".\"".$this->_config_data['sql_users_table']."\" WHERE (\"desactivated\" = 0)"; if (!($rResult = pg_query($this->_pgsql_database_link, $sQuery))) { $this->WriteLog("Error: Unable to access the database: ".pg_last_error(), FALSE, FALSE, 41, 'System', '', 3); } else { if ($aRow = pg_fetch_assoc($rResult)) { $active_users_count = $aRow['counter']; } } } break; case 'files': default: $locked_users_count = 0; $users_count = 0; if ($users_handle = @opendir($this->GetUsersFolder())) { while ($file = readdir($users_handle)) { $desactivated = FALSE; $locked = FALSE; if ((substr($file, -3) == ".db") && ($file != '.db')) { $current_user = $this->DecodeFileId(substr($file,0,-3)); if ($file_handler = @fopen($this->GetUsersFolder().$file, "rt")) { $first_line = trim(fgets($file_handler)); $v3 = (FALSE !== strpos(strtolower($first_line),"multiotp-database-format-v3")); if (FALSE !== strpos(strtolower($first_line),"multiotp-database-format")) { while (!feof($file_handler)) { $line = trim(fgets($file_handler)); $line_array = explode("=",$line,2); if ($v3) { if (":" == substr($line_array[0], -1)) { $line_array[0] = substr($line_array[0], 0, strlen($line_array[0]) -1); $line_array[1] = $this->Decrypt($line_array[0],$line_array[1],$this->GetEncryptionKey()); } } else { if ((FALSE !== strpos(strtolower($this->GetAttributesToEncrypt()), strtolower('*'.$line_array[0].'*'))) || ("*all*" == strtolower($this->GetAttributesToEncrypt()))) { $line_array[1] = $this->Decrypt($line_array[0],$line_array[1],$this->GetEncryptionKey()); } } if ('desactivated' == trim($line_array[0])) { if (1 == (isset($line_array[1])?$line_array[1]:0)) { $desactivated = TRUE; } } if ('locked' == trim($line_array[0])) { if (1 == (isset($line_array[1])?$line_array[1]:0)) { $locked = TRUE; } } } } fclose($file_handler); $users_count++; if (!$desactivated) { $active_users_count++; } if ($locked) { $locked_users_count++; } } } } closedir($users_handle); } } } if ($this->IsCacheData()) { if ($active_users_count >= 0) { $this->WriteCacheValue('active_users_count', $active_users_count); } if ($locked_users_count >= 0) { $this->WriteCacheValue('locked_users_count', $locked_users_count); } if ($users_count >= 0) { $this->WriteCacheValue('users_count', $users_count); } $this->WriteCacheData(); } } return $active_users_count; } function GetDetailedUsersArray() { $users_array = array(); $result = $this->GetNextUserArray(TRUE); if (isset($result['user'])) { $users_array[$result['user']] = $result; } do { if ($result = $this->GetNextUserArray()) { if (isset($result['user'])) { $users_array[$result['user']] = $result; } } } while (FALSE !== $result); return $users_array; } function GetNextUserArray( $first = FALSE, $fields = NULL ) { if (NULL != $fields) { $fields_array = $fields; } else { $fields_array = array('user', 'description', 'email', 'group', 'desactivated', 'locked', 'sms', 'synchronized', 'synchronized_channel', 'synchronized_server', 'synchronized_time', 'token_serial', 'synchronized_dn', 'error_counter', 'last_error' ); } $now_epoch = time(); $raw_id = $fields_array[0]; $fields_text = ''; $fields_separator = ''; $table_name = 'sql_users_table'; $folder = $this->GetUsersFolder(); $parser_id = 'GET_NEXT_USER_ARRAY'; $user_array = false; if ((($this->GetBackendTypeValidated()) && ('' != $this->_config_data[$table_name])) || ('files' == $this->GetBackendType())) { if ($first) { switch ($this->GetBackendType()) { case 'mysql': foreach($fields_array as $one_field) { $fields_text.= $fields_separator.'`'.$one_field.'`'; $fields_separator = ','; } if ($this->OpenMysqlDatabase()) { $sQuery = "SELECT ".$fields_text." FROM `".$this->_config_data[$table_name]."` ORDER BY user ASC"; if (is_object($this->_mysqli)) { if (!($this->_parser_pointers[$parser_id] = $this->_mysqli->query($sQuery))) { $this->WriteLog("Error: Unable to access the database: ".trim($this->_mysqli->error), FALSE, FALSE, 41, 'System', '', 3); $this->_parser_pointers[$parser_id] = FALSE; $result = FALSE; return $result; } } else { if (!($this->_parser_pointers[$parser_id] = mysql_query($sQuery, $this->_mysql_database_link))) { $this->WriteLog("Error: Unable to access the database: ".mysql_error(), FALSE, FALSE, 41, 'System', '', 3); $this->_parser_pointers[$parser_id] = FALSE; $result = FALSE; return $result; } } } break; case 'pgsql': foreach($fields_array as $one_field) { $fields_text.= $fields_separator.'"'.$one_field.'"'; $fields_separator = ','; } if ($this->OpenPGSQLDatabase()) { $sQuery = "SELECT ".$fields_text." FROM \"".$this->_config_data['sql_schema']."\".\"".$this->_config_data[$table_name]."\" ORDER BY \"user\" ASC"; if (!($this->_parser_pointers[$parser_id] = pg_query($this->_pgsql_database_link, $sQuery))) { $this->WriteLog("Error: Unable to access the database: ".pg_last_error(), FALSE, FALSE, 41, 'System', '', 3); $this->_parser_pointers[$parser_id] = FALSE; $result = FALSE; return $result; } } break; case 'files': default: if (!($this->_parser_pointers[$parser_id] = @opendir($folder))) { $result = FALSE; return $result; } } } if (isset($this->_parser_pointers[$parser_id]) && (FALSE !== $this->_parser_pointers[$parser_id])) { switch ($this->GetBackendType()) { case 'mysql': if ($this->OpenMysqlDatabase()) { if (is_object($this->_mysqli)) { do { $aRow = $this->_parser_pointers[$parser_id]->fetch_assoc(); } while ((FALSE !== $aRow) && (NULL !== $aRow) && ('' == $aRow['user'])); } else { do { $aRow = mysql_fetch_assoc($this->_parser_pointers[$parser_id]); } while ((FALSE !== $aRow) && (NULL !== $aRow) && ('' == $aRow['user'])); } if (isset($aRow['user'])) { $user_array = array('user' => $aRow['user'], 'description' => $aRow['description'], 'email' => $aRow['email'], 'enabled' => (0 == $aRow['desactivated']), 'group' => $aRow['group'], 'locked' => (1 == $aRow['locked']), 'sms' => $aRow['sms'], 'synchronized' => (1 == $aRow['synchronized']), 'synchronized_channel' => $aRow['synchronized_channel'], 'synchronized_server' => $aRow['synchronized_server'], 'synchronized_time' => $aRow['synchronized_time'], 'token' => $aRow['token_serial'], 'synchronized_dn' => $aRow['synchronized_dn'], 'error_counter' => $aRow['error_counter'], 'last_error' => $aRow['last_error'] ); } } break; case 'pgsql': if ($this->OpenPGSQLDatabase()) { do { $aRow = pg_fetch_assoc($this->_parser_pointers[$parser_id]); } while ((FALSE !== $aRow) && (NULL !== $aRow) && ('' == $aRow['user'])); if (isset($aRow['user'])) { $user_array = array('user' => $aRow['user'], 'description' => $aRow['description'], 'email' => $aRow['email'], 'enabled' => (0 == $aRow['desactivated']), 'group' => $aRow['group'], 'locked' => (1 == $aRow['locked']), 'sms' => $aRow['sms'], 'synchronized' => (1 == $aRow['synchronized']), 'synchronized_channel' => $aRow['synchronized_channel'], 'synchronized_server' => $aRow['synchronized_server'], 'synchronized_time' => $aRow['synchronized_time'], 'token' => $aRow['token_serial'], 'synchronized_dn' => $aRow['synchronized_dn'], 'error_counter' => $aRow['error_counter'], 'last_error' => $aRow['last_error'] ); } } break; case 'files': default: do { $file = readdir($this->_parser_pointers[$parser_id]); } while ((FALSE !== $file) && ((substr($file, -3) != ".db") || ($file == '.db'))); if (FALSE !== $file) { $user = $this->DecodeFileId(substr($file,0,-3)); $this->SetUser($user); $user_array = array('user' => $user, 'description' => $this->GetUserDescription(), 'email' => $this->GetUserEmail(), 'enabled' => (1 == $this->GetUserActivated()), 'group' => $this->GetUserGroup(), 'locked' => (1 == $this->GetUserLocked()), 'sms' => $this->GetUserSms(), 'synchronized' => (1 == $this->GetUserSynchronized()), 'synchronized_channel' => $this->GetUserSynchronizedChannel(), 'synchronized_server' => $this->GetUserSynchronizedServer(), 'synchronized_time' => $this->GetUserSynchronizedTime(), 'token' => $this->GetUserTokenSerialNumber(), 'synchronized_dn' => $this->GetUserSynchronizedDn(), 'error_counter' => $this->GetUserErrorCounter(), 'last_error' => $this->GetUserTokenLastError() ); } else { $user_array = FALSE; closedir($this->_parser_pointers[$parser_id]); } } } } if (FALSE === $user_array) { unset($this->_parser_pointers[$parser_id]); } else { $user_array['delayed_account'] = (($user_array['error_counter'] >= $this->GetMaxDelayedFailures()) && ($now_epoch < ($user_array['last_error'] + $this->GetMaxDelayedTime()))); $user_array['delayed_time'] = 0; $user_array['delayed_finished'] = 0; if ($user_array['delayed_account']) { $user_array['delayed_time'] = ($user_array['last_error'] + $this->GetMaxDelayedTime()) - $now_epoch; $user_array['delayed_finished'] = ($user_array['last_error'] + $this->GetMaxDelayedTime()); $user_array['locked'] = TRUE; } } return $user_array; } function GetAlgorithmsList() { $algorithms_list = ''; $algorithms_array = explode("*",$this->_valid_algorithms); foreach ($algorithms_array as $algorithm_one) { if ('' != trim($algorithm_one)) { $algorithms_list.= (('' != $algorithms_list)?"\t":'').trim($algorithm_one); } } return $algorithms_list; } function IsValidAlgorithm( $algo_to_check ) { return (FALSE !== strpos(strtolower($this->_valid_algorithms), strtolower('*'.$algo_to_check.'*'))); } function GetUserScratchPasswordsArray( $user = '' ) { if ('' != $user) { $this->SetUser($user); } if ($this->_user_data['scratch_passwords'] != '') { return (explode(",",$this->_user_data['scratch_passwords'])); } else { return array(); } return (explode(",",$this->_user_data['scratch_passwords'])); } function RemoveUserUsedScratchPassword( $to_remove ) { $scratch_passwords = trim($this->_user_data['scratch_passwords']); if (FALSE !== ($pos = strpos($scratch_passwords, $to_remove))) { $scratch_passwords = trim(substr($scratch_passwords.' ', $pos+strlen($to_remove)+1)); $this->_user_data['scratch_passwords'] = $scratch_passwords; $result = $this->WriteUserData(); } return TRUE; } function GetScratchPasswordsAmount() { return $this->_config_data['scratch_passwords_amount']; } function SetScratchPasswordsAmount( $value ) { $amount = intval($value); $amount = ($amount < 3)?3:$amount; $amount = ($amount > 400)?400:$amount; $this->_config_data['scratch_passwords_amount'] = $amount; return TRUE; } function GetUserScratchPasswordsList( $user = '' ) { if ('' != $user) { $this->SetUser($user); } $digits = $this->GetScratchPasswordsDigits(); $seed = hex2bin(md5('sCratchP@sswordS'.$this->GetUser().bigdec2hex((time()-mktime(1,1,1,1,1,2000)).mt_rand(10000,99999)))); $scratch_loop = $this->GetScratchPasswordsAmount(); if (($scratch_loop * (1+$digits) * 2.5) > 65535) { $scratch_loop = inval(65535 / ((1+$digits) * 2.5)); $this->SetScratchPasswordsAmount($scratch_loop); } $scratch_passwords = trim($this->_user_data['scratch_passwords']); if (strlen($scratch_passwords) > ((1.5 * $scratch_loop) * (1 + $digits))) { $scratch_passwords = ''; } $passwords_list = ''; for ($i=0; $i<$scratch_loop; $i++) { $one_password = $this->GenerateOathHotp($seed,$i,$digits); $scratch_passwords.= (('' != $scratch_passwords)?",":'').$one_password; $passwords_list.= (('' != $passwords_list)?"\t":'').$one_password; } $this->_user_data['scratch_passwords'] = $scratch_passwords; $result = $this->WriteUserData(); if (!$result) { $passwords_list = ''; } return ($passwords_list); } function SetUserDataReadFlag( $flag ) { $this->_user_data_read_flag = $flag; return TRUE; } function GetUserDataReadFlag() { return $this->_user_data_read_flag; } function SetUserMultiAccount( $value ) { $this->_user_data['multi_account'] = $value; return TRUE; } function GetUserMultiAccount() { return $this->_user_data['multi_account']; } function SetUserAttribute( $first_param, $second_param, $third_param = "*-*" ) { $result = FALSE; if ($third_param == "*-*") { if ($this->IsOptionInSchema('users', $first_param)) { $this->_user_data[$first_param] = $second_param; $result = TRUE; } } else { if ($this->IsOptionInSchema('users', $second_param)) { $this->SetUser($first_param); $this->_user_data[$second_param] = $third_param; $result = TRUE; } } return $result; } function SetUserEmail( $first_param, $second_param = "*-*" ) { $valid = FALSE; $result = ""; if ($second_param == "*-*") { if (('' == $first_param) || (FALSE !== strpos($first_param, '@'))) { $result = $first_param; $valid = TRUE; } } else { $this->SetUser($first_param); if (('' == $second_param) || (FALSE !== strpos($second_param, '@'))) { $result = $second_param; $valid = TRUE; } } $this->_user_data['email'] = $result; return $valid; } function GetUserEmail( $user = '' ) { if($user != '') { $this->SetUser($user); } return $this->_user_data['email']; } function SetUserLastCachedCredential( $first_param, $second_param = "*-*" ) { $input = ""; if ($second_param == "*-*") { $input = $first_param; } else { $this->SetUser($first_param); $input = $second_param; } if ($this->GetVerboseFlag()) { $this->WriteLog("Debug: *SetUserLastCachedCredential cached credential: ".str_repeat('x', (strlen($input) >= 6)?strlen($input)-6:0).substr($input, -6), FALSE, FALSE, 8888, 'Debug', ''); } $this->_user_data['last_cached_credential'] = sha1('$+Cred'.$input.'!@#S'); return true; } function CompareUserLastCachedCredential( $first_param, $second_param = "*-*" ) { $input = ""; if ($second_param == "*-*") { $input = $first_param; } else { $this->SetUser($first_param); $input = $second_param; } if ($this->GetVerboseFlag()) { $this->WriteLog("Debug: *CompareUserLastCachedCredential cached credential: ".str_repeat('x', (strlen($input) >= 6)?strlen($input)-6:0).substr($input, -6), FALSE, FALSE, 8888, 'Debug', ''); } return (sha1('$+Cred'.$input.'!@#S') == $this->_user_data['last_cached_credential']); } function SetUserLastFailedCredential( $first_param, $second_param = "*-*" ) { $input = ""; if ($second_param == "*-*") { $input = $first_param; } else { $this->SetUser($first_param); $input = $second_param; } if (!$this->CompareUserLastFailedCredential($input)) { $this->_user_data['last_failed_time'] = time(); } $this->_user_data['last_failed_credential'] = sha1('$+Cred'.$input.'!@#S'); return true; } function CompareUserLastFailedCredential( $first_param, $second_param = "*-*" ) { $input = ""; if ($second_param == "*-*") { $input = $first_param; } else { $this->SetUser($first_param); $input = $second_param; } if (($this->_user_data['last_failed_time'] + $this->GetLastFailedWhiteDelay()) > time()) { return (sha1('$+Cred'.$input.'!@#S') == $this->_user_data['last_failed_credential']); } else { return false; } } function SetUserLastSuccessCredential( $first_param, $second_param = "*-*" ) { $input = ""; if ($second_param == "*-*") { $input = $first_param; } else { $this->SetUser($first_param); $input = $second_param; } $this->_user_data['last_success_credential'] = sha1('$+Cred'.$input.'!@#S'); return true; } function CompareUserLastSuccessCredential( $first_param, $second_param = "*-*" ) { $input = ""; if ($second_param == "*-*") { $input = $first_param; } else { $this->SetUser($first_param); $input = $second_param; } return (sha1('$+Cred'.$input.'!@#S') == $this->_user_data['last_success_credential']); } function SetUserLastLoginForCache( $first_param, $second_param = "*-*" ) { $input = ""; if ($second_param == "*-*") { $input = $first_param; } else { $this->SetUser($first_param); $input = $second_param; } $this->_user_data['last_login_for_cache'] = $input; return true; } function GetUserLastLoginForCache( $user = '' ) { if($user != '') { $this->SetUser($user); } return $this->_user_data['last_login_for_cache']; } function SetUserGroup( $first_param, $second_param = "*-*" ) { $result = ""; if ($second_param == "*-*") { $result = $first_param; } else { $this->SetUser($first_param); $result = $second_param; } $this->_user_data['group'] = $result; return $result; } function GetUserGroup( $user = '' ) { if($user != '') { $this->SetUser($user); } return $this->_user_data['group']; } function SetUserDescription( $first_param, $second_param = "*-*" ) { $result = ""; if ($second_param == "*-*") { $result = $first_param; } else { $this->SetUser($first_param); $result = $second_param; } $result = $this->EncodeForBackend($result); $this->_user_data['description'] = $result; $this->SetUserMultiAccount((FALSE !== strpos($result,'multi_account')) ? 1 : 0); return $result; } function GetUserDescription( $user = '' ) { if($user != '') { $this->SetUser($user); } return $this->_user_data['description']; } function SetUserSeedPassword( $value ) { $this->_user_data['seed_password'] = $value; } function GetUserSeedPassword() { return $this->_user_data['seed_password']; } function SetUserSms( $first_param, $second_param = "*-*" ) { $result = ""; if ($second_param == "*-*") { $result = $first_param; } else { $this->SetUser($first_param); $result = $second_param; } $this->_user_data['sms'] = $result; return TRUE; } function GetUserSms( $user = '' ) { if($user != '') { $this->SetUser($user); } return $this->_user_data['sms']; } function SetUserPrefixPin( $value ) { $this->_user_data['request_prefix_pin'] = ((intval($value) > 0)?1:0); return TRUE; } function GetUserPrefixPin() { return $this->_user_data['request_prefix_pin']; } function EnableUserPrefixPin() { $this->_user_data['request_prefix_pin'] = 1; return TRUE; } function DisableUserPrefixPin() { $this->_user_data['request_prefix_pin'] = 0; return TRUE; } function IsUserPrefixPin() { return (1 == ($this->_user_data['request_prefix_pin'])); } function SetUserRequestLdapPassword( $value ) { $this->_user_data['request_ldap_pwd'] = ((intval($value) > 0)?1:0); return TRUE; } function GetUserRequestLdapPassword() { return ((intval($this->_user_data['request_ldap_pwd']) > 0) ? 1 : 0); } function EnableUserRequestLdapPassword() { $this->_user_data['request_ldap_pwd'] = 1; return TRUE; } function DisableUserRequestLdapPassword() { $this->_user_data['request_ldap_pwd'] = 0; return TRUE; } function IsUserRequestLdapPasswordEnabled() { return (1 == ($this->_user_data['request_ldap_pwd'])); } function SetUserLdapHashCache( $first_param, $second_param = "*-*" ) { $value = ""; if ($second_param == "*-*") { $value = $first_param; } else { $this->SetUser($first_param); $value = $second_param; } $this->_user_data['ldap_hash_cache'] = $value; $this->_user_data['ldap_hash_validity'] = time() + $this->GetLdapHashCacheTime(); return TRUE; } function ResetUserLdapHashCache( $user = '' ) { if ('' != $user) { $this->SetUser($user); } $this->_user_data['ldap_hash_cache'] = ''; $this->_user_data['ldap_hash_validity'] = 0; return TRUE; } function GetUserLdapHashCache( $user = '' ) { if($user != '') { $this->SetUser($user); } if ($this->_user_data['ldap_hash_validity'] >= time()) { $value = $this->_user_data['ldap_hash_cache']; } else { $this->_user_data['ldap_hash_cache'] = ''; $value = ''; } return $value; } function SetUserAlgorithm( $algorithm ) { $result = FALSE; if ($this->IsValidAlgorithm($algorithm)) { $this->_user_data['algorithm'] = strtolower($algorithm); $result = TRUE; } else { $this->WriteLog("Error: ".$algorithm." algorithm is unknown", FALSE, FALSE, 23, 'User'); } return $result; } function GetUserAlgorithm( $user = '' ) { if($user != '') { $this->SetUser($user); } $result = strtolower($this->_user_data['algorithm']); if (FALSE === strpos(strtolower($this->_valid_algorithms), strtolower('*'.$result.'*'))) { $result = ''; } return $result; } function SetUserTokenAlgoSuite( $token_algo_suite ) { $this->_user_data['token_algo_suite'] = strtoupper(('' == $token_algo_suite)?'HMAC-SHA1':$token_algo_suite); return TRUE; } function GetUserTokenAlgoSuite( $user = '' ) { return strtoupper(('' == $this->_user_data['token_algo_suite'])?'HMAC-SHA1':$this->_user_data['token_algo_suite']); } function SetUserTokenPrivateId( $private_id ) { $this->_user_data['private_id'] = $private_id; } function GetUserTokenPrivateId() { return $this->_user_data['private_id']; } function SetUserTokenSeed( $seed ) { $the_seed = $seed; if (!ctype_xdigit($the_seed)) { if (FALSE !== base32_decode($seed)) { $the_seed = bin2hex(base32_decode($seed)); } else { $the_seed = bin2hex($seed); } } $this->_user_data['token_seed'] = $the_seed; } function GetUserTokenSeed() { return $this->_user_data['token_seed']; } function SetUserSmsOtp( $value ) { $this->_user_data['sms_otp'] = $value; } function GetUserSmsOtp() { if (strlen($this->_user_data['sms_otp']) < 4) { $this->_user_data['sms_otp'] = md5($this->GetEncryptionKey().$this->GetUserTokenSeed().mt_rand(100000,999999).date("YmdHis")); } return $this->_user_data['sms_otp']; } function SetUserSmsValidity( $value ) { $this->_user_data['sms_validity'] = $value; } function GetUserSmsValidity() { return $this->_user_data['sms_validity']; } function SetUserPin( $pin ) { $this->_user_data['user_pin'] = $pin; } function GetUserPin( $user = '' ) { if($user != '') { $this->SetUser($user); } return $this->_user_data['user_pin']; } function SetUserAutolockTime( $value ) { $this->_user_data['autolock_time'] = intval($value); } function GetUserAutolockTime() { return intval($this->_user_data['autolock_time']); } function SetUserTokenDeltaTime( $delta_time ) { $this->_user_data['delta_time'] = $delta_time; } function GetUserTokenDeltaTime() { return $this->_user_data['delta_time']; } function SetUserKeyId( $key_id ) { $this->_user_data['key_id'] = $key_id; } function GetUserKeyId() { return $this->_user_data['key_id']; } function SetUserTokenNumberOfDigits( $number_of_digits ) { $this->_user_data['number_of_digits'] = $number_of_digits; } function GetUserTokenNumberOfDigits() { return $this->_user_data['number_of_digits']; } function SetUserTokenTimeInterval( $interval ) { if (intval($interval) > 0) { $this->_user_data['time_interval'] = intval($interval); } } function GetUserTokenTimeInterval() { return $this->_user_data['time_interval']; } function GetUserEncryptionHash() { return $this->_user_data['encryption_hash']; } function SetUserTokenSerialNumber( $first_param, $second_param = "*-*" ) { $result = ""; if ($second_param == "*-*") { $value = $first_param; } else { $this->SetUser($first_param); $value = $second_param; } $this->_user_data['token_serial'] = strtolower($value); return $value; } function GetUserTokenSerialNumber( $user = '' ) { if($user != '') { $this->SetUser($user); } return strtolower($this->_user_data['token_serial']); } function SetUserTokenLastEvent( $last_event ) { $this->_user_data['last_event'] = intval($last_event); } function GetUserTokenLastEvent() { return intval($this->_user_data['last_event']); } function SetUserTokenLastLogin( $timestamp ) { $this->_user_data['last_login'] = intval($timestamp); } function GetUserTokenLastLogin() { return intval($this->_user_data['last_login']); } function SetUserLastLogin( $timestamp ) { $this->_user_data['user_last_login'] = intval($timestamp); } function GetUserLastLogin() { return intval($this->_user_data['user_last_login']); } function SetUserTokenLastError( $timestamp ) { if ($this->IsCacheData()) { $this->ResetCacheArray(); $this->WriteCacheData(); } $this->_user_data['last_error'] = intval($timestamp); } function GetUserTokenLastError() { return intval($this->_user_data['last_error']); } function SetUserLocked( $first_param, $second_param = "*-*" ) { $data = 0; if ($second_param == "*-*") { $data = $first_param; } else { $this->SetUser($first_param); $data = $second_param; } $this->_user_data['locked'] = $data; if ($this->IsCacheData()) { $this->ResetCacheArray(); $this->WriteCacheData(); } return $data; } function GetUserLocked( $user = '' ) { if($user != '') { $this->SetUser($user); } return intval($this->_user_data['locked']); } function GetUserDelayed( $user = '' ) { if ($user != '') { $this->SetUser($user); } return (isset($this->_user_data['delayed_account']) ? $this->_user_data['delayed_account'] : FALSE); } function GetUserDelayedTime( $user = '' ) { if ($user != '') { $this->SetUser($user); } return intval(isset($this->_user_data['delayed_time']) ? $this->_user_data['delayed_time'] : 0); } function SetUserActivated( $first_param, $second_param = "*-*" ) { $result = TRUE; $data = 0; if ($second_param == "*-*") { $data = $first_param; } else { $result = $this->SetUser($first_param); $data = $second_param; } $desactive = ($data > 0)?0:1; $this->_user_data['desactivated'] = $desactive; if (0 == $desactive) { $this->SetUserErrorCounter(0); $this->SetUserLocked(0); } if ($this->IsCacheData()) { $this->ResetCacheArray(); $this->WriteCacheData(); } return $result; } function GetUserActivated( $user = '' ) { $result = TRUE; if($user != '') { $result = $this->SetUser($user); } if ($result) { $result = intval($this->_user_data['desactivated'] > 0)?0:1; } return $result; } function SetUserSynchronized( $first_param, $second_param = "*-*" ) { $result = TRUE; $data = 0; if ($second_param == "*-*") { $data = $first_param; } else { $result = $this->SetUser($first_param); $data = $second_param; } $this->_user_data['synchronized'] = $data; return $result; } function GetUserSynchronized( $user = '' ) { if ($user != '') { $this->SetUser($user); } return intval($this->_user_data['synchronized']); } function IsUserSynchronized( $user = '' ) { return (1 == ($this->GetUserSynchronized($user))); } function SetUserSynchronizedChannel( $first_param, $second_param = "*-*" ) { $data = 0; if ($second_param == "*-*") { $data = $first_param; } else { $this->SetUser($first_param); $data = $second_param; } $this->_user_data['synchronized_channel'] = $data; return $data; } function GetUserSynchronizedChannel( $user = '' ) { if ($user != '') { $this->SetUser($user); } return ($this->_user_data['synchronized_channel']); } function SetUserSynchronizedDn( $first_param, $second_param = "*-*" ) { $data = 0; if ($second_param == "*-*") { $data = $first_param; } else { $this->SetUser($first_param); $data = $second_param; } $this->_user_data['synchronized_dn'] = $data; return $data; } function GetUserSynchronizedDn( $user = '' ) { if($user != '') { $this->SetUser($user); } return ($this->_user_data['synchronized_dn']); } function SetUserSynchronizedServer( $first_param, $second_param = "*-*" ) { $data = 0; if ($second_param == "*-*") { $data = $first_param; } else { $this->SetUser($first_param); $data = $second_param; } $this->_user_data['synchronized_server'] = $data; return $data; } function GetUserSynchronizedServer( $user = '' ) { if($user != '') { $this->SetUser($user); } return ($this->_user_data['synchronized_server']); } function SetUserSynchronizedTime( $first_param = "*-*", $second_param = "*-*" ) { $data = 0; if ($second_param == "*-*") { if ($first_param == "*-*") { $data = time(); } else { $data = $first_param; } } else { $this->SetUser($first_param); $data = $second_param; } $this->_user_data['synchronized_time'] = $data; return $data; } function GetUserSynchronizedTime( $user = '' ) { if($user != '') { $this->SetUser($user); } return intval($this->_user_data['synchronized_time']); } function SetUserErrorCounter( $counter ) { $this->_user_data['error_counter'] = $counter; } function GetUserErrorCounter() { return $this->_user_data['error_counter']; } function CreateToken( $serial = '', $algorithm = 'totp', $seed = '', $number_of_digits = 6, $time_interval_or_next_event = -1, $manufacturer = 'multiOTP', $issuer = '', $description = '', $token_algo_suite = '' ) { $the_serial = strtolower($serial); if ('' == $the_serial) { $the_serial = strtolower('mu'.bigdec2hex((time()-mktime(1,1,1,1,1,2000)).mt_rand(10000,99999))); } $the_description = $description; if ('' == $the_description) { $the_description = trim($manufacturer.' '.$the_serial); } $the_token = strtolower($the_serial); if ($this->ReadTokenData($the_token, TRUE)) { return FALSE; } else { $this->SetToken($the_token); $this->SetTokenDescription($the_description); $this->SetTokenManufacturer(('' != $manufacturer)?$manufacturer:'multiOTP'); $this->SetTokenIssuer(('' != $issuer)?$issuer:$this->GetIssuer()); $this->SetTokenSerialNumber($the_serial); $this->SetTokenAlgorithm(strtolower($algorithm)); $this->SetTokenAlgoSuite(strtolower($token_algo_suite)); $this->SetTokenKeyAlgorithm(strtolower($algorithm)); $this->SetTokenOtp('TRUE'); $this->SetTokenFormat('DECIMAL'); $this->SetTokenNumberOfDigits($number_of_digits); $this->SetTokenDeltaTime(0); $the_seed = (('' == $seed)?substr(md5(date("YmdHis").mt_rand(100000,999999)),0,20).substr(md5(mt_rand(100000,999999).date("YmdHis")),0,20):$seed); if ('hotp' == strtolower($algorithm)) { $next_event = ((-1 == $time_interval_or_next_event)?0:$time_interval_or_next_event); $time_interval = 0; } else { $next_event = 0; $time_interval = ((-1 == $time_interval_or_next_event)?30:$time_interval_or_next_event); if ("motp" == strtolower($algorithm)) { $the_seed = (('' == $seed)?substr(md5(date("YmdHis").mt_rand(100000,999999)),0,16):$seed); $time_interval = 10; } } $this->SetTokenSeed($the_seed); $this->SetTokenLastEvent($next_event - 1); $this->SetTokenTimeInterval($time_interval); return $this->WriteTokenData(); } } function AssignTokenToUser( $user, $token ) { $the_token = strtolower($token); $this->SetUser($user); $old_token = $this->GetUserTokenSerialNumber(); if ($this->RemoveTokenAttributedUsers($old_token, $user)) { $this->WriteTokenData(); } $this->SetUserTokenSerialNumber($the_token); $this->AddUserAttributedTokens($the_token); $this->SetToken($the_token); $this->AddTokenAttributedUsers($user); $this->SetUserKeyId($the_token); $this->SetUserAlgorithm($this->GetTokenAlgorithm()); $this->SetUserTokenAlgoSuite($this->GetTokenAlgoSuite()); $this->SetUserTokenSeed($this->GetTokenSeed()); $this->SetUserTokenNumberOfDigits($this->GetTokenNumberOfDigits()); $this->SetUserTokenTimeInterval($this->GetTokenTimeInterval()); $this->SetUserTokenLastEvent($this->GetTokenLastEvent()); return ($this->WriteUserData() && $this->WriteTokenData()); } function RemoveTokenFromUser( $user ) { $this->SetUser($user); $old_token = $this->GetUserTokenSerialNumber(); $this->SetUserTokenSerialNumber(''); $this->RemoveUserAttributedTokens($old_token); $this->RemoveTokenAttributedUsers($old_token); return ($this->WriteUserData() && $this->WriteTokenData()); } function SetTokenSerialNumberLength( $value ) { $this->_config_data['token_serial_number_length'] = trim($value); } function AddTokenSerialNumberLength( $length ) { if (intval($length) > 0) { $actual = trim($this->GetTokenSerialNumberLength()); $length_exists = FALSE; $token_serial_number_length_array = explode(" ",trim(str_replace(","," ",str_replace(";"," ",$actual)))); foreach($token_serial_number_length_array as $one_length) { if (intval($one_length) == intval($length)) { $length_exists = TRUE; break; } } if (!$length_exists) { $actual.=' '.intval($length); $this->SetTokenSerialNumberLength($actual); $this->WriteConfigData(); } } return TRUE; } function GetTokenSerialNumberLength() { $token_serial_number_length = $this->_config_data['token_serial_number_length']; if (FALSE === strpos($token_serial_number_length, '12')) { $token_serial_number_length.=' 12'; } return $token_serial_number_length; } function SetTokenOtpListOfLength( $value ) { $this->_config_data['token_otp_list_of_length'] = trim($value); } function AddTokenOtpListOfLength( $length ) { if (intval($length) > 0) { $actual = trim($this->GetTokenOtpListOfLength()); $length_exists = FALSE; $token_otp_list_of_length_array = explode(" ",trim(str_replace(","," ",str_replace(";"," ",$actual)))); foreach($token_otp_list_of_length_array as $one_length) { if (intval($one_length) == intval($length)) { $length_exists = TRUE; break; } } if (!$length_exists) { $actual.=' '.intval($length); $this->SetTokenOtpListOfLength($actual); $this->WriteConfigData(); } } return TRUE; } function GetTokenOtpListOfLength() { $token_otp_list_of_length = $this->_config_data['token_otp_list_of_length']; if (FALSE === strpos($token_otp_list_of_length, '6')) { $token_otp_list_of_length.=' 6'; } return $token_otp_list_of_length; } function SetTokenDescription( $first_param, $second_param = "*-*" ) { $result = ""; if ($second_param == "*-*") { $value = $first_param; } else { $this->SetToken($first_param); $value = $second_param; } $value = $this->EncodeForBackend($value); $this->_token_data['description'] = $value; return $value; } function GetTokenDescription( $token = '' ) { $the_token = strtolower($token); if($the_token != '') { $this->SetToken($the_token); } return $this->_token_data['description']; } function SetToken( $token, $create = TRUE ) { $the_token = strtolower($token); $this->ResetTokenArray(); $this->_token = $the_token; $result = $this->ReadTokenData('', $create); return ($create || $result); } function RenameCurrentToken( $new_token, $no_error_info = FALSE ) { $the_new_token = strtolower($new_token); $result = FALSE; if ($this->CheckTokenExists($the_new_token)) { $this->WriteLog("Error: Unable to rename the current token ".$this->GetToken()." to ".$the_new_token." because it already exists", FALSE, FALSE, 28, 'Token', ''); } else { if ($this->CheckTokenExists()) { if ((($this->GetBackendTypeValidated()) && ('' != $this->_config_data['sql_tokens_table'])) || ('files' == $this->GetBackendType())) { switch ($this->GetBackendType()) { case 'mysql': $esc_actual = escape_mysql_string($this->GetToken()); $esc_new = escape_mysql_string($the_new_token); if ($this->OpenMysqlDatabase()) { if ('' != $this->_config_data['sql_tokens_table']) { $sQuery = "UPDATE `".$this->_config_data['sql_tokens_table']."` SET token_id='".$esc_new."' WHERE `token_id`='".$esc_actual."'"; if (is_object($this->_mysqli)) { if (!($rResult = $this->_mysqli->query($sQuery))) { if (!$no_error_info) { $this->WriteLog("Error: Could not rename the token ".$this->GetToken().": ".trim($this->_mysqli->error), FALSE, FALSE, 28, 'Token'); } } else { $num_rows = $this->_mysqli->affected_rows; } } elseif (!($rResult = mysql_query($sQuery, $this->_mysql_database_link))) { if (!$no_error_info) { $this->WriteLog("Error: Could not rename the token ".$this->GetToken().": ".mysql_error(), FALSE, FALSE, 28, 'Token'); } } else { $num_rows = mysql_affected_rows($this->_mysql_database_link); } if (0 == $num_rows) { $this->WriteLog("Error: Could not rename the token ".$this->GetToken().". Token does not exist", FALSE, FALSE, 29, 'Token'); } else { $this->WriteLog("Info: Token ".$this->GetToken()." successfully renamed to $the_new_token", FALSE, FALSE, 19, 'Token'); $result = TRUE; } } } break; case 'pgsql': $esc_actual = pg_escape_string($this->GetToken()); $esc_new = pg_escape_string($the_new_token); if ($this->OpenPGSQLDatabase()) { if ('' != $this->_config_data['sql_tokens_table']) { $sQuery = "UPDATE \"".$this->_config_data['sql_schema']."\".\"".$this->_config_data['sql_tokens_table']."\" SET \"token_id\" = '".$esc_new."' WHERE \"token_id\" = '".$esc_actual."'"; if (!($rResult = pg_query($this->_pgsql_database_link, $sQuery))) { if (!$no_error_info) { $this->WriteLog("Error: Could not rename the token ".$this->GetToken().": ".pg_last_error(), FALSE, FALSE, 28, 'Token'); } } else { $num_rows = pg_affected_rows($rResult); } if (0 == $num_rows) { $this->WriteLog("Error: Could not rename the token ".$this->GetToken().". Token does not exist", FALSE, FALSE, 29, 'Token'); } else { $this->WriteLog("Info: Token ".$this->GetToken()." successfully renamed to $the_new_token", FALSE, FALSE, 19, 'Token'); $result = TRUE; } } } break; case 'files': default: $old_token_filename = strtolower($this->GetToken()).'.db'; $new_token_filename = strtolower($the_new_token).'.db'; rename($this->GetTokensFolder().$old_token_filename, $this->GetTokensFolder().$new_token_filename); $result = TRUE; break; } } } if ($result) { $this->_token = $the_new_token; } } return $result; } function GetToken() { return strtolower($this->_token); } function CheckTokenExists( $token = '' ) { $the_token = strtolower($token); $check_token = strtolower('' != $the_token) ? $the_token : $this->GetToken(); $result = FALSE; if ('' != trim($check_token)) { if ((($this->GetBackendTypeValidated()) && ('' != $this->_config_data['sql_tokens_table'])) || ('files' == $this->GetBackendType())) { switch ($this->GetBackendType()) { case 'mysql': if ($this->OpenMysqlDatabase()) { $sQuery = "SELECT * FROM `".$this->_config_data['sql_tokens_table']."` WHERE `token_id` = '{$check_token}'"; if (is_object($this->_mysqli)) { if (!($rResult = $this->_mysqli->query($sQuery))) { $this->WriteLog("Error: Unable to access the database: ".trim($this->_mysqli->error), FALSE, FALSE, 41, 'System', '', 3); } else { $num_rows = $rResult->num_rows; } } elseif (!($rResult = mysql_query($sQuery, $this->_mysql_database_link))) { $this->WriteLog("Error: Unable to access the database: ".mysql_error(), FALSE, FALSE, 41, 'System', '', 3); } else { $num_rows = mysql_num_rows($this->_mysql_database_link); } if (0 == $num_rows) { $this->WriteLog("Error: Token ".$check_token.". does not exist", FALSE, FALSE, 41, 'System', '', 3); $result = FALSE; } else { $result = TRUE; } } break; case 'pgsql': if ($this->OpenPGSQLDatabase()) { $sQuery = "SELECT * FROM \"".$this->_config_data['sql_schema']."\".\"".$this->_config_data['sql_tokens_table']."\" WHERE \"token_id\" = '{$check_token}'"; if (!($rResult = pg_query($this->_pgsql_database_link, $sQuery))) { $this->WriteLog("Error: Unable to access the database: ".pg_last_error(), FALSE, FALSE, 41, 'System', '', 3); } else { $num_rows = pg_num_rows($rResult); } if (0 == $num_rows) { $this->WriteLog("Error: Token ".$check_token.". does not exist", FALSE, FALSE, 41, 'System', '', 3); $result = FALSE; } else { $result = TRUE; } } break; case 'files': default: $token_filename = strtolower($check_token).'.db'; $result = file_exists($this->GetTokensFolder().$token_filename); break; } } } return $result; } function ResetLastImportedTokensArray() { $this->_last_imported_tokens = array(); } function AddLastImportedToken( $token ) { $the_token = strtolower($token); $this->_last_imported_tokens[] = $the_token; } function GetLastImportedTokens() { return $this->_last_imported_tokens; } function SetTokenManufacturer( $manufacturer ) { $this->_token_data['manufacturer'] = $manufacturer; } function GetTokenManufacturer() { return $this->_token_data['manufacturer']; } function SetTokenModel( $model ) { $this->_token_data['model'] = $model; } function GetTokenModel() { return $this->_token_data['model']; } function SetTokenIssueNo( $issue_no ) { $this->_token_data['issue_no'] = trim($issue_no); } function GetTokenIssueNo() { return $this->_token_data['issue_no']; } function SetTokenKeyId( $key_id ) { $this->_token_data['key_id'] = trim($key_id); } function GetTokenKeyId() { return $this->_token_data['key_id']; } function SetTokenKeyUsage( $key_usage ) { $this->_token_data['key_usage'] = trim($key_usage); } function GetTokenKeyUsage() { return $this->_token_data['key_usage']; } function GetTokenEncryptionHash() { return $this->_token_data['encryption_hash']; } function SetTokenAttributedUsers( $first_param, $second_param = "*-*" ) { $result = ""; if ($second_param == "*-*") { $result = $first_param; } else { $this->SetToken($first_param); $result = $second_param; } $this->_token_data['attributed_users'] = $result; return $result; } function AddTokenAttributedUsers( $first_param, $second_param = "*-*" ) { $data = ""; $result = FALSE; if ($second_param == "*-*") { $data = $first_param; $token = strtolower($this->GetToken()); } else { $token = strtolower($first_param); if ($this->CheckTokenExists($token)) { $this->SetToken($token); } $data = $second_param; } if ($this->CheckTokenExists($token)) { $actual = trim($this->GetTokenAttributedUsers()); if (FALSE === strpos(','.$actual.',', ','.$data.',')) { $this->SetTokenAttributedUsers($actual.(('' != $actual)?',':'').$data); } $result = TRUE; } return $result; } function RemoveTokenAttributedUsers( $first_param, $second_param = "*-*" ) { $data = ""; $result = FALSE; if ($second_param == "*-*") { $data = $first_param; $token = strtolower($this->GetToken()); } else { $token = strtolower($first_param); if ($this->CheckTokenExists($token)) { $this->SetToken($token); } $data = $second_param; } if ($this->CheckTokenExists($token)) { if (FALSE !== strpos(','.trim($this->GetTokenAttributedUsers()).',', ','.$data.',')) { $actual = str_replace(','.$data.',',',',','.trim($this->GetTokenAttributedUsers()).','); $this->SetTokenAttributedUsers(substr($actual,1, strlen($actual)-2)); $result = TRUE; } } return $result; } function GetTokenAttributedUsers( $token = '' ) { if($token != '') { $the_token = strtolower($token); $this->SetToken($the_token); } return $this->_token_data['attributed_users']; } function SetUserAttributedTokens( $first_param, $second_param = "*-*" ) { $result = ""; if ($second_param == "*-*") { $result = $first_param; } else { $this->SetUser($first_param); $result = $second_param; } $this->_user_data['attributed_tokens'] = $result; return $result; } function AddUserAttributedTokens( $first_param, $second_param = "*-*" ) { $data = ""; $result = FALSE; if ($second_param == "*-*") { $data = $first_param; $user = $this->GetUser(); } else { $user = $first_param; if ($this->CheckUserExists($user)) { $this->SetUser($user); } $data = $second_param; } if ($this->CheckUserExists($user)) { $actual = trim($this->GetUserAttributedTokens()); if (FALSE === strpos(','.$actual.',', ','.$data.',')) { $this->SetUserAttributedTokens($actual.(('' != $actual)?',':'').$data); } $result = TRUE; } return $result; } function RemoveUserAttributedTokens( $first_param, $second_param = "*-*" ) { $data = ""; $result = FALSE; if ($second_param == "*-*") { $data = $first_param; $user = $this->GetUser(); } else { $user = $first_param; if ($this->CheckUserExists($user)) { $this->SetUser($user); } $data = $second_param; } if ($this->CheckUserExists($user)) { if (FALSE !== strpos(','.trim($this->GetUserAttributedTokens()).',', ','.$data.',')) { $actual = str_replace(','.$data.',',',',','.trim($this->GetUserAttributedTokens()).','); $this->SetUserAttributedTokens(substr($actual,1, strlen($actual)-2)); $result = TRUE; } } return $result; } function GetUserAttributedTokens( $user = '' ) { if($user != '') { $this->SetUser($user); } return $this->_user_data['attributed_tokens']; } function SetTokenSerialNo( $serial_no ) { $this->_token_data['serial_no'] = strtolower($serial_no); } function GetTokenSerialNo() { return strtolower($this->_token_data['serial_no']); } function SetTokenSerialNumber( $token_serial ) { $this->_token_data['token_serial'] = strtolower($token_serial); $len_token_serial = strlen($token_serial); if ($len_token_serial > 0) { $this->AddTokenSerialNumberLength($len_token_serial); } } function GetTokenSerialNumber() { return strtolower($this->_token_data['token_serial']); } function SetTokenIssuer( $issuer ) { if ('' == $issuer) { $this->_token_data['issuer'] = $this->GetIssuer(); } else { $this->_token_data['issuer'] = $issuer; } } function GetTokenIssuer() { return $this->_token_data['issuer']; } function SetTokenKeyAlgorithm( $key_algorithm ) { $this->_token_data['key_algorithm'] = $key_algorithm; } function GetTokenKeyAlgorithm() { return $this->_token_data['key_algorithm']; } function SetTokenAlgorithm( $algorithm ) { $result = FALSE; if (FALSE === strpos(strtolower($this->_valid_algorithms), strtolower('*'.$algorithm.'*'))) { $this->WriteLog("Error: ".$algorithm." algorithm unknown for token ".$this->GetToken(), FALSE, FALSE, 23, 'Token'); } else { $this->_token_data['algorithm'] = strtolower($algorithm); $result = TRUE; } return $result; } function GetTokenAlgorithm() { $result = $this->_token_data['algorithm']; if (FALSE === strpos(strtolower($this->_valid_algorithms), strtolower('*'.$result.'*'))) { $result = ''; } return $result; } function SetTokenAlgoSuite( $token_algo_suite ) { $this->_token_data['token_algo_suite'] = strtoupper(('' == $token_algo_suite)?'HMAC-SHA1':$token_algo_suite); return TRUE; } function GetTokenAlgoSuite() { return strtoupper(('' == $this->_token_data['token_algo_suite'])?'HMAC-SHA1':$this->_token_data['token_algo_suite']); } function SetTokenOtp( $otp ) { $this->_token_data['otp'] = $otp; } function GetTokenOtp() { return $this->_token_data['otp']; } function SetTokenFormat( $format ) { $this->_token_data['format'] = $format; } function GetTokenFormat() { return $this->_token_data['format']; } function SetTokenNumberOfDigits( $number_of_digits ) { $this->_token_data['number_of_digits'] = $number_of_digits; $this->AddTokenOtpListOfLength($number_of_digits); } function GetTokenNumberOfDigits() { return $this->_token_data['number_of_digits']; } function SetTokenLastEvent( $last_event ) { $this->_token_data['last_event'] = $last_event; } function GetTokenLastEvent() { return $this->_token_data['last_event']; } function SetTokenLastLogin( $timestamp ) { $this->_token_data['last_login'] = intval($timestamp); } function GetTokenLastLogin() { return intval($this->_token_data['last_login']); } function SetTokenErrorCounter( $counter ) { $this->_token_data['error_counter'] = $counter; } function GetTokenErrorCounter() { return $this->_token_data['error_counter']; } function SetTokenDeltaTime( $delta_time ) { $this->_token_data['delta_time'] = $delta_time; } function GetTokenDeltaTime() { return $this->_token_data['delta_time']; } function SetTokenTimeInterval( $time_interval ) { $this->_token_data['time_interval'] = $time_interval; } function GetTokenTimeInterval() { return $this->_token_data['time_interval']; } function SetTokenPrivateId( $private_id ) { $this->_token_data['private_id'] = $private_id; } function GetTokenPrivateId() { return $this->_token_data['private_id']; } function SetTokenSeed( $seed ) { $the_seed = $seed; if (!ctype_xdigit($the_seed)) { if (FALSE !== base32_decode($seed)) { $the_seed = bin2hex(base32_decode($seed)); } else { $the_seed = bin2hex($seed); } } $this->_token_data['token_seed'] = $the_seed; } function GetTokenSeed() { return $this->_token_data['token_seed']; } function SetTokensFolder( $folder, $create = true ) { $new_folder = $this->ConvertToUnixPath($folder); if (substr($new_folder,-1) != "/") { $new_folder.="/"; } if ("/" == $new_folder) { $new_folder = "./"; } $new_folder = $this->ConvertToWindowsPathIfNeeded($new_folder); $this->_tokens_folder = $new_folder; if ($create && (!file_exists($new_folder))) { if (!@mkdir( $new_folder, ('' != $this->GetLinuxFolderMode()) ? octdec($this->GetLinuxFolderMode()) : 0777, true )) { $this->WriteLog("Error: Unable to create the missing tokens folder ".$new_folder, FALSE, FALSE, 28, 'System', ''); } } } function GetTokensFolder() { if ('' == $this->_tokens_folder) { $this->SetTokensFolder($this->GetScriptFolder()."tokens/"); } return $this->ConvertToWindowsPathIfNeeded($this->_tokens_folder); } function GetTokensList() { return $this->GetList('token_id', 'sql_tokens_table', $this->GetTokensFolder()); } function GetTokensCount($no_cache = FALSE) { if (($this->IsCacheData()) && (intval($this->ReadCacheValue('tokens_count')) >= 0) && (!$no_cache)) { $tokens_count = intval($this->ReadCacheValue('tokens_count')); } else { $tokens_count = 0; switch ($this->GetBackendType()) { case 'mysql': if ($this->OpenMysqlDatabase()) { $sQuery = "SELECT COUNT(token_id) AS counter FROM `".$this->_config_data['sql_tokens_table']."` "; if (is_object($this->_mysqli)) { if (!($result = $this->_mysqli->query($sQuery))) { $this->WriteLog("Error: Unable to access the database: ".trim($this->_mysqli->error), FALSE, FALSE, 41, 'System', '', 3); $result = FALSE; } else { if ($aRow = $result->fetch_assoc()) { $tokens_count = $aRow['counter']; } } } else { if (!($rResult = mysql_query($sQuery, $this->_mysql_database_link))) { $this->WriteLog("Error: Unable to access the database: ".mysql_error(), FALSE, FALSE, 41, 'System', '', 3); } else { if ($aRow = mysql_fetch_assoc($rResult)) { $tokens_count = $aRow['counter']; } } } } break; case 'pgsql': if ($this->OpenPGSQLDatabase()) { $sQuery = "SELECT COUNT(\"token_id\") AS \"counter\" FROM \"".$this->_config_data['sql_schema']."\".\"".$this->_config_data['sql_tokens_table']."\" "; if (!($rResult = pg_query($this->_pgsql_database_link, $sQuery))) { $this->WriteLog("Error: Unable to access the database: ".pg_last_error(), FALSE, FALSE, 41, 'System', '', 3); } else { if ($aRow = pg_fetch_assoc($rResult)) { $tokens_count = $aRow['counter']; } } } break; case 'files': default: if ($tokens_handle = @opendir($this->GetTokensFolder())) { while ($file = readdir($tokens_handle)) { if ((substr($file, -3) == ".db") && ($file != '.db')) { $tokens_count++; } } closedir($tokens_handle); } } if (($this->IsCacheData()) && ($tokens_count >= 0)) { $this->WriteCacheValue('tokens_count', $tokens_count); $this->WriteCacheData(); } } return $tokens_count; } function DeleteToken( $token = '', $no_error_info = FALSE ) { $the_token = strtolower($token); if ('' != $the_token) { $this->SetToken($the_token); } $result = FALSE; if (('files' == $this->GetBackendType()) || ($this->GetMigrationFromFile())) { $token_filename = $this->GetToken().'.db'; if (!file_exists($this->GetTokensFolder().$token_filename)) { if ($this->GetVerboseFlag()) { $this->WriteLog("Error: *Unable to delete token ".$this->GetToken().", the tokens database file ".$this->GetTokensFolder().$token_filename." does not exist", FALSE, FALSE, 29, 'Token', ''); } else { $this->WriteLog("Error: Unable to delete token ".$this->GetToken(), FALSE, FALSE, 29, 'Token', ''); } } else { $result = unlink($this->GetTokensFolder().$token_filename); if ($result) { if ($this->GetVerboseFlag()) { $this->WriteLog("Info: *Token ".$this->GetToken()." successfully deleted", FALSE, FALSE, 19, 'Token', ''); } } else { $this->WriteLog("Error: Unable to delete token ".$this->GetToken(), FALSE, FALSE, 28, 'Token', ''); } } } if ($this->GetBackendTypeValidated()) { switch ($this->_config_data['backend_type']) { case 'mysql': if ($this->OpenMysqlDatabase()) { if ('' != $this->_config_data['sql_tokens_table']) { $sQuery = "DELETE FROM `".$this->_config_data['sql_tokens_table']."` WHERE `token_id` = '".$this->GetToken()."'"; if (is_object($this->_mysqli)) { if (!($rResult = $this->_mysqli->query($sQuery))) { if (!$no_error_info) { $this->WriteLog("Error: Could not delete token ".$this->GetToken().": ".trim($this->_mysqli->error), FALSE, FALSE, 28, 'Token', ''); } } else { $num_rows = $this->_mysqli->affected_rows; } } elseif (!($rResult = mysql_query($sQuery, $this->_mysql_database_link))) { if (!$no_error_info) { $this->WriteLog("Error: Could not delete token ".$this->GetToken().": ".mysql_error(), FALSE, FALSE, 28, 'Token', ''); } } else { $num_rows = mysql_affected_rows($this->_mysql_database_link); } if (0 == $num_rows) { if (!$no_error_info) { $this->WriteLog("Error: Could not delete token ".$this->GetToken().". Token does not exist", FALSE, FALSE, 29, 'Token', ''); } } else { if ($this->GetVerboseFlag()) { $this->WriteLog("Info: *token ".$this->GetToken()." successfully deleted", FALSE, FALSE, 19, 'Token', ''); } $result = TRUE; } } } break; case 'pgsql': if ($this->OpenPGSQLDatabase()) { if ('' != $this->_config_data['sql_tokens_table']) { $sQuery = "DELETE FROM \"".$this->_config_data['sql_schema']."\".\"".$this->_config_data['sql_tokens_table']."\" WHERE \"token_id\" = '".$this->GetToken()."'"; if (!($rResult = pg_query($this->_pgsql_database_link, $sQuery))) { if (!$no_error_info) { $this->WriteLog("Error: Could not delete token ".$this->GetToken().": ".pg_last_error(), FALSE, FALSE, 28, 'Token', ''); } } else { $num_rows = pg_affected_rows($rResult); } if (0 == $num_rows) { if (!$no_error_info) { $this->WriteLog("Error: Could not delete token ".$this->GetToken().". Token does not exist", FALSE, FALSE, 29, 'Token', ''); } } else { if ($this->GetVerboseFlag()) { $this->WriteLog("Info: *token ".$this->GetToken()." successfully deleted", FALSE, FALSE, 19, 'Token', ''); } $result = TRUE; } } } break; default: break; } } if ($result) { $this->TouchFolder('data', 'Token', $this->GetToken(), TRUE, "DeleteToken"); } return $result; } function ReadTokenData( $token = '', $create = FALSE ) { $the_token = strtolower($token); if ('' != $the_token) { $this->SetToken($the_token); } $result = FALSE; $this->_token_data['encryption_hash'] = ''; if (('files' == $this->GetBackendType()) || ($this->GetMigrationFromFile())) { $token_filename = strtolower($this->GetToken()).'.db'; if (!file_exists($this->GetTokensFolder().$token_filename)) { if (!$create) { $this->WriteLog("Error: database file ".$this->GetTokensFolder().$token_filename." for token ".$this->_token." does not exist", FALSE, FALSE, 29, 'System', ''); } } else { if ($file_handler = @fopen($this->GetTokensFolder().$token_filename, "rt")) { $first_line = trim(fgets($file_handler)); while (!feof($file_handler)) { $line = trim(fgets($file_handler)); $line_array = explode("=",$line,2); if (":" == substr($line_array[0], -1)) { $line_array[0] = substr($line_array[0], 0, strlen($line_array[0]) -1); $line_array[1] = $this->Decrypt($line_array[0],$line_array[1],$this->GetEncryptionKey()); } if ('' != trim($line_array[0])) { $this->_token_data[strtolower($line_array[0])] = $line_array[1]; } } fclose($file_handler); $result = TRUE; if ('' != $this->_token_data['encryption_hash']) { if ($this->_token_data['encryption_hash'] != $this->CalculateControlHash($this->GetEncryptionKey())) { $this->_token_data['encryption_hash'] = "ERROR"; $this->WriteLog("Error: the token information encryption key is not matching", FALSE, FALSE, 33, 'System', ''); $result = FALSE; } } } } } if ($this->GetBackendTypeValidated()) { switch ($this->_config_data['backend_type']) { case 'mysql': if ($this->OpenMysqlDatabase()) { if ('' != $this->_config_data['sql_tokens_table']) { $sQuery = "SELECT * FROM `".$this->_config_data['sql_tokens_table']."` WHERE `token_id` = '".$this->_token."'"; $aRow = NULL; if (is_object($this->_mysqli)) { if (!($rResult = $this->_mysqli->query($sQuery))) { $this->WriteLog("Error: SQL query error ($sQuery) : ".trim($this->_mysqli->error).' ', TRUE, FALSE, 40, 'System', '', 3); $result = FALSE; } else { $aRow = $rResult->fetch_assoc(); } } else { if (!($rResult = mysql_query($sQuery, $this->_mysql_database_link))) { $this->WriteLog("Error: SQL query error ($sQuery) : ".mysql_error(), TRUE, FALSE, 40, 'System', '', 3); $result = FALSE; } else { $aRow = mysql_fetch_assoc($rResult); } } if (NULL != $aRow) { $result = FALSE; while(list($key, $value) = @each($aRow)) { $in_the_schema = FALSE; reset($this->_sql_tables_schema['tokens']); while(list($valid_key, $valid_format) = @each($this->_sql_tables_schema['tokens'])) { if ($valid_key == $key) { $in_the_schema = TRUE; break; } } if (($in_the_schema) && ($key != 'token_id')) { if (('ENC:' == substr($value,0,4)) && (':ENC' == substr($value,-4))) { $value = substr($value,4); $value = substr($value,0,strlen($value)-4); $this->_token_data[$key] = $this->Decrypt($key,$value,$this->GetEncryptionKey()); } else { $this->_token_data[$key] = $value; } } elseif ((!$in_the_schema) && ('unique_id' != $key) && $this->GetVerboseFlag()) { $this->WriteLog("Warning: *The key ".$key." is not in the tokens database schema", FALSE, FALSE, 98, 'System', ''); } $result = TRUE; } if(0 == count($aRow) && !$create) { $this->WriteLog("Error: SQL database entry for token ".$this->_token." does not exist", FALSE, FALSE, 29, 'System', ''); } } } if ('' != $this->_token_data['encryption_hash']) { if ($this->_token_data['encryption_hash'] != $this->CalculateControlHash($this->GetEncryptionKey())) { $this->_token_data['encryption_hash'] = "ERROR"; $this->WriteLog("Error: the tokens mysql encryption key is not matching", FALSE, FALSE, 33, 'System', ''); $result = FALSE; } } } break; case 'pgsql': if ($this->OpenPGSQLDatabase()) { if ('' != $this->_config_data['sql_tokens_table']) { $sQuery = "SELECT * FROM \"".$this->_config_data['sql_schema']."\".\"".$this->_config_data['sql_tokens_table']."\" WHERE \"token_id\" = '".$this->_token."'"; $aRow = NULL; if (!($rResult = pg_query($this->_pgsql_database_link, $sQuery))) { $this->WriteLog("Error: SQL query error ($sQuery) : ".pg_last_error(), TRUE, FALSE, 40, 'System', '', 3); $result = FALSE; } else { $aRow = pg_fetch_assoc($rResult); } if (NULL != $aRow) { $result = FALSE; while(list($key, $value) = @each($aRow)) { $in_the_schema = FALSE; reset($this->_sql_tables_schema['tokens']); while(list($valid_key, $valid_format) = @each($this->_sql_tables_schema['tokens'])) { if ($valid_key == $key) { $in_the_schema = TRUE; break; } } if (($in_the_schema) && ($key != 'token_id')) { if (('ENC:' == substr($value,0,4)) && (':ENC' == substr($value,-4))) { $value = substr($value,4); $value = substr($value,0,strlen($value)-4); $this->_token_data[$key] = $this->Decrypt($key,$value,$this->GetEncryptionKey()); } else { $this->_token_data[$key] = $value; } } elseif ((!$in_the_schema) && ('unique_id' != $key) && $this->GetVerboseFlag()) { $this->WriteLog("Warning: *The key ".$key." is not in the tokens database schema", FALSE, FALSE, 98, 'System', ''); } $result = TRUE; } if(0 == count($aRow) && !$create) { $this->WriteLog("Error: SQL database entry for token ".$this->_token." does not exist", FALSE, FALSE, 29, 'System', ''); } } } if ('' != $this->_token_data['encryption_hash']) { if ($this->_token_data['encryption_hash'] != $this->CalculateControlHash($this->GetEncryptionKey())) { $this->_token_data['encryption_hash'] = "ERROR"; $this->WriteLog("Error: the tokens pgsql encryption key is not matching", FALSE, FALSE, 33, 'System', ''); $result = FALSE; } } } break; default: break; } } $this->SetTokenDataReadFlag($result); return $result; } function WriteTokenData( $write_token_data_array = array() ) { if ('' == trim($this->GetToken())) { $result = false; } else { $result = $this->WriteData(array_merge(array('item' => 'Token', 'table' => 'tokens', 'folder' => $this->GetTokensFolder(), 'data_array' => $this->_token_data, 'force_file' => false, 'id_field' => 'token_id', 'id_value' => $this->GetToken() ), $write_token_data_array)); } return $result; } function SetLastClearOtpValue( $value = '' ) { $this->_last_clear_otp_value = $value; } function GetLastClearOtpValue() { return $this->_last_clear_otp_value; } function ResetTemporaryBadServer() { $this->_servers_temp_bad_list = array(); } function AddTemporaryBadServer( $server, $timestamp ) { $this->_servers_temp_bad_list[$server] = intval($timestamp); } function IsTemporaryBadServer( $server ) { $result = FALSE; foreach ($this->_servers_temp_bad_list as $badserver => $timestamp) { if ($badserver == $server) { if (($timestamp + (1 * 60)) <= time()) { $result = TRUE; } break; } } } function CheckUserLdapPassword( $ldap_username, $ldap_password ) { $this->SetLdapServerReachable(FALSE); $result = FALSE; $ldap_bind_dn = encode_utf8_if_needed($ldap_username); if (('' != $ldap_username) && (FALSE === strpos(strtolower($ldap_bind_dn), 'cn='))) { $ldap_bind_dn = 'CN='.$ldap_bind_dn.','.$this->GetLdapBaseDn(); } if (!function_exists('ldap_connect')) { $this->WriteLog("Error: LDAP library not installed", FALSE, FALSE, 39, 'System', '', 3); $this->EnableLdapError(); } elseif (('' != $this->GetLdapDomainControllers()) && ('' != $ldap_username) && ('' != $ldap_password)) { $domain_controllers = explode(" ",trim(str_replace(","," ",str_replace(";"," ",$this->GetLdapDomainControllers())))); $ldap_options = array('account_suffix' => $this->GetLdapAccountSuffix(), 'ad_password' => $ldap_password, 'ad_username' => $ldap_bind_dn, 'base_dn' => $this->GetLdapBaseDn(), 'cn_identifier' => $this->GetLdapCnIdentifier(), 'domain_controllers' => $domain_controllers, 'group_attribute' => $this->GetLdapGroupAttribute(), 'group_cn_identifier'=> $this->GetLdapGroupCnIdentifier(), 'ldap_server_type' => $this->GetLdapServerType(), 'network_timeout' => $this->GetLdapNetworkTimeout(), 'port' => $this->GetLdapPort(), 'recursive_groups' => $this->IsLdapRecursiveGroups(), 'time_limit' => $this->GetLdapTimeLimit(), 'use_ssl' => $this->IsLdapSsl(), 'cache_support' => $this->IsLdapCacheOn(), 'cache_folder' => $this->GetLdapCacheFolder() ); $ldap_connection=new MultiotpAdLdap($ldap_options); $this->SetLdapServerReachable($ldap_connection->IsServerReachable()); $result = !$ldap_connection->IsError(); unset($ldap_connection); } return $result; } function GetLdapUsersList( $user_filter = "*" ) { $this->DisableLdapError(); $users_list = ''; $in_groups_array = array(); $users_in_groups = array(); $result_array = array(); if (!function_exists('ldap_connect')) { $result = FALSE; $this->WriteLog("Error: LDAP library not installed", FALSE, FALSE, 39, 'System', '', 3); $this->EnableLdapError(); } elseif (('' != $this->GetLdapDomainControllers()) && ('' != $this->GetLdapBindDn()) && ('' != $this->GetLdapServerPassword())) { $domain_controllers = explode(" ",trim(str_replace(","," ",str_replace(";"," ",$this->GetLdapDomainControllers())))); $ldap_options = array('account_suffix' => $this->GetLdapAccountSuffix(), 'ad_password' => $this->GetLdapServerPassword(), 'ad_username' => $this->GetLdapBindDn(), 'base_dn' => $this->GetLdapBaseDn(), 'cn_identifier' => $this->GetLdapCnIdentifier(), 'domain_controllers' => $domain_controllers, 'group_attribute' => $this->GetLdapGroupAttribute(), 'group_cn_identifier'=> $this->GetLdapGroupCnIdentifier(), 'ldap_server_type' => $this->GetLdapServerType(), 'network_timeout' => $this->GetLdapNetworkTimeout(), 'port' => $this->GetLdapPort(), 'recursive_groups' => $this->IsLdapRecursiveGroups(), 'time_limit' => $this->GetLdapTimeLimit(), 'use_ssl' => $this->IsLdapSsl(), 'cache_support' => $this->IsLdapCacheOn(), 'cache_folder' => $this->GetLdapCacheFolder() ); $ldap_connection=new MultiotpAdLdap($ldap_options); if ($users_info = $ldap_connection->users_info($user_filter, $this->GetLdapFieldsArray())) { if ($ldap_connection->IsError()) { $this->EnableLdapError(); } else { if (1 != $this->GetLdapServerType()) { $users_in_groups = array(); if ('' != trim($this->GetLdapInGroup())) { $in_groups_array_raw = explode("§",trim(str_replace(",","§",str_replace(";","§",$this->GetLdapInGroup())))); foreach($in_groups_array_raw as $one_group) { $temp_array = $ldap_connection->group_users($one_group); foreach($temp_array as $one_temp) { $one_user = $this->EncodeForBackend($one_temp); if (!isset($users_in_groups[$this->$one_user])) { $users_in_groups[$one_user] = $one_group; } else { $users_in_groups[$one_user] = $users_in_groups[$one_user].",".$one_group; } } } } } $all_results = (isset($users_info['count'])?$users_info['count']:0); for ($results=0; $results < $all_results; $results++) { $accountdisable = FALSE; $groups_array = array(); $in_groups_array = array(); $in_groups_lower_array = array(); $one_user = $users_info[$results]; $user = $this->EncodeForBackend(isset($one_user[strtolower($this->GetLdapCnIdentifier())][0])?($one_user[strtolower($this->GetLdapCnIdentifier())][0]):''); $account = $this->EncodeForBackend(isset($one_user[strtolower($this->GetLdapSyncedUserAttribute())][0])?($one_user[strtolower($this->GetLdapSyncedUserAttribute())][0]):''); if (!$this->IsCaseSensitiveUsers()) { $user = strtolower($user); $account = strtolower($account); } if (isset($one_user['useraccountcontrol'][0])) { if (0 != ($one_user['useraccountcontrol'][0] & 2)) { $accountdisable = TRUE; } } if (isset($one_user['ms-ds-user-account-control-computed'][0])) { if (0 != ($one_user['ms-ds-user-account-control-computed'][0] & 16)) { $accountdisable = TRUE; } } if (isset($one_user['accountexpires'][0])) { if (($one_user['accountexpires'][0] > 0) && ((($one_user['accountexpires'][0] / 10000000) - 11644473600) < time())) { $accountdisable = TRUE; } } if (isset($one_user['shadowexpire'][0])) { if (($one_user['shadowexpire'][0] >= 0) && ((86400 * $one_user['shadowexpire'][0]) < time())) { $accountdisable = TRUE; } } if (isset($one_user['sambaacctflags'][0])) { if ((FALSE !== strpos($one_user['sambaacctflags'][0], "D")) || (FALSE !== strpos($one_user['sambaacctflags'][0], "L"))) { $accountdisable = TRUE; } } if (!$accountdisable) { if ('' == trim($this->GetLdapInGroup())) { $in_a_group = TRUE; } else { $in_a_group = FALSE; $in_groups_array_raw = explode(" ",trim(str_replace(","," ",str_replace(";"," ",$this->GetLdapInGroup())))); foreach($in_groups_array_raw as $one_group) { $in_groups_array[] = trim($one_group); $in_groups_lower_array[] = strtolower(trim($one_group)); } } if (1 != $this->GetLdapServerType()) { if (isset($users_in_groups[$user])) { $in_a_group = TRUE; } } else { $groups_array_raw=$ldap_connection->nice_names($one_user[$ldap_connection->_group_attribute]); if ($ldap_connection->_recursive_groups) { foreach ($groups_array_raw as $id => $group_name){ $extra_groups=$ldap_connection->recursive_groups($group_name, $this->IsLdapRecursiveCacheOnly()); if ('' != $ldap_connection->get_warning_message()) { $this->WriteLog("Warning: ".$ldap_connection->get_warning_message(), FALSE, FALSE, 98, 'LDAP', ''); } if ($this->GetVerboseFlag() && ('' != $ldap_connection->get_debug_message())) { $this->WriteLog("Debug: *".$ldap_connection->get_debug_message(), FALSE, FALSE, 98, 'LDAP', ''); } $groups_array_raw=array_merge($groups_array_raw,$extra_groups); } } $groups_array = array(); foreach($groups_array_raw as $one_group) { $this_group = $this->EncodeForBackend($one_group); $groups_array[] = $this_group; if (in_array(strtolower($this_group), $in_groups_lower_array)) { $in_a_group = TRUE; } } } if ($in_a_group) { $users_list.= (('' != $users_list)?"\t":'').$account; } } } } } else { $this->EnableLdapError(); $this->WriteLog("Error: no LDAP binding", FALSE, FALSE, 30, 'LDAP', ''); } } else { $this->WriteLog("Error: No LDAP connection information", FALSE, FALSE, 30, 'LDAP', ''); } return $users_list; } function GetLdapUsersInfoArray( $user_filter = "*", $include_disabled = TRUE, $ignore_in_group = FALSE ) { $this->DisableLdapError(); $in_groups_array = array(); $users_in_groups = array(); $result_array = array(); if (!function_exists('ldap_connect')) { $result = FALSE; $this->WriteLog("Error: LDAP library not installed", FALSE, FALSE, 39, 'System', '', 3); $this->EnableLdapError(); } elseif (('' != $this->GetLdapDomainControllers()) && ('' != $this->GetLdapBindDn()) && ('' != $this->GetLdapServerPassword())) { $domain_controllers = explode(" ",trim(str_replace(","," ",str_replace(";"," ",$this->GetLdapDomainControllers())))); $ldap_options = array('account_suffix' => $this->GetLdapAccountSuffix(), 'ad_password' => $this->GetLdapServerPassword(), 'ad_username' => $this->GetLdapBindDn(), 'base_dn' => $this->GetLdapBaseDn(), 'cn_identifier' => $this->GetLdapCnIdentifier(), 'domain_controllers' => $domain_controllers, 'group_attribute' => $this->GetLdapGroupAttribute(), 'group_cn_identifier'=> $this->GetLdapGroupCnIdentifier(), 'ldap_server_type' => $this->GetLdapServerType(), 'network_timeout' => $this->GetLdapNetworkTimeout(), 'port' => $this->GetLdapPort(), 'recursive_groups' => $this->IsLdapRecursiveGroups(), 'time_limit' => $this->GetLdapTimeLimit(), 'use_ssl' => $this->IsLdapSsl(), 'cache_support' => $this->IsLdapCacheOn(), 'cache_folder' => $this->GetLdapCacheFolder() ); $ldap_connection=new MultiotpAdLdap($ldap_options); if ($this->GetVerboseFlag()) { $this->WriteLog("Debug: *AD/LDAP connection defined", FALSE, FALSE, 8888, 'Debug', ''); } if (!$ldap_connection->_bind) { $this->WriteLog("Error: AD/LDAP not binded ".$ldap_connection->get_warning_message(), FALSE, FALSE, 30, 'LDAP', ''); } if ($users_info = $ldap_connection->users_info($user_filter, $this->GetLdapFieldsArray())) { if ($ldap_connection->IsError()) { if ($this->GetVerboseFlag()) { $this->WriteLog("Debug: *AD/LDAP error during connection : ".$ldap_connection->ErrorMessage(), FALSE, FALSE, 8888, 'Debug', ''); } $this->EnableLdapError(); } else { if ($this->GetVerboseFlag()) { $this->WriteLog("Debug: *AD/LDAP GetLdapUsersInfoArray processing", FALSE, FALSE, 8888, 'Debug', ''); } if (1 != $this->GetLdapServerType()) { if ($this->GetVerboseFlag()) { $this->WriteLog("Debug: *AD/LDAP server is generic LDAP", FALSE, FALSE, 8888, 'Debug', ''); } $users_in_groups = array(); if ('' != trim($this->GetLdapInGroup())) { $in_groups_array_raw = explode("§",trim(str_replace(",","§",str_replace(";","§",$this->GetLdapInGroup())))); foreach($in_groups_array_raw as $one_group) { $temp_array = $ldap_connection->group_users($one_group); foreach($temp_array as $one_temp) { $one_user = $this->EncodeForBackend($one_temp); if (!isset($users_in_groups[$one_user])) { $users_in_groups[$one_user] = $one_group; } else { $users_in_groups[$one_user] = $users_in_groups[$one_user].",".$one_group; } } } } } else { if ($this->GetVerboseFlag()) { $this->WriteLog("Debug: *AD/LDAP server is Microsoft AD", FALSE, FALSE, 8888, 'Debug', ''); } } $all_results = (isset($users_info['count'])?$users_info['count']:0); for ($results=0; $results < $all_results; $results++) { $accountdisable = FALSE; $groups_array = array(); $in_groups_array = array(); $in_groups_lower_array = array(); $one_user = $users_info[$results]; $user = $this->EncodeForBackend(isset($one_user[strtolower($this->GetLdapCnIdentifier())][0])?($one_user[strtolower($this->GetLdapCnIdentifier())][0]):''); $account = $this->EncodeForBackend(isset($one_user[strtolower($this->GetLdapSyncedUserAttribute())][0])?($one_user[strtolower($this->GetLdapSyncedUserAttribute())][0]):''); if (!$this->IsCaseSensitiveUsers()) { $user = strtolower($user); $account = strtolower($account); } $one_user['msradiusframedipaddress'][0] = (isset($one_user['msradiusframedipaddress'][0])) ? long2ip32bit($one_user['msradiusframedipaddress'][0]) : "---"; $one_user['radiusframedipaddress'][0] = (isset($one_user['radiusframedipaddress'][0])) ? ($one_user['radiusframedipaddress'][0]) : "---"; $one_user['radiusframedipnetmask'][0] = (isset($one_user['radiusframedipnetmask'][0])) ? ($one_user['radiusframedipnetmask'][0]) : "---"; if (isset($one_user['useraccountcontrol'][0])) { if (0 != ($one_user['useraccountcontrol'][0] & 2)) { $accountdisable = TRUE; } } if (isset($one_user['ms-ds-user-account-control-computed'][0])) { if (0 != ($one_user['ms-ds-user-account-control-computed'][0] & 16)) { $accountdisable = TRUE; } } if (isset($one_user['accountexpires'][0])) { if (($one_user['accountexpires'][0] > 0) && ((($one_user['accountexpires'][0] / 10000000) - 11644473600) < time())) { $accountdisable = TRUE; } } if (isset($one_user['shadowexpire'][0])) { if (($one_user['shadowexpire'][0] >= 0) && ((86400 * $one_user['shadowexpire'][0]) < time())) { $accountdisable = TRUE; } } if (isset($one_user['sambaacctflags'][0])) { if ((FALSE !== strpos($one_user['sambaacctflags'][0], "D")) || (FALSE !== strpos($one_user['sambaacctflags'][0], "L"))) { $accountdisable = TRUE; } } if ($include_disabled || (!$accountdisable)) { if ('' == trim($this->GetLdapInGroup())) { $in_a_group = TRUE; } else { $in_a_group = FALSE; $in_groups_array_raw = explode("§",trim(str_replace(",","§",str_replace(";","§",$this->GetLdapInGroup())))); foreach($in_groups_array_raw as $one_group) { $in_groups_array[] = trim($one_group); $in_groups_lower_array[] = strtolower(trim($one_group)); } } if (1 != $this->GetLdapServerType()) { if (isset($users_in_groups[$user])) { $in_a_group = TRUE; } } else { $groups_array_raw=$ldap_connection->nice_names($one_user[$ldap_connection->_group_attribute]); if ($ldap_connection->_recursive_groups) { foreach ($groups_array_raw as $id => $group_name){ $extra_groups=$ldap_connection->recursive_groups($group_name, $this->IsLdapRecursiveCacheOnly()); if ('' != $ldap_connection->get_warning_message()) { $this->WriteLog("Warning: ".$ldap_connection->get_warning_message(), FALSE, FALSE, 98, 'LDAP', ''); } if ($this->GetVerboseFlag() && ('' != $ldap_connection->get_debug_message())) { $this->WriteLog("Debug: *".$ldap_connection->get_debug_message(), FALSE, FALSE, 98, 'LDAP', ''); } $groups_array_raw=array_merge($groups_array_raw,$extra_groups); } } $groups_array = array(); foreach($groups_array_raw as $one_group) { $this_group = $this->EncodeForBackend($one_group); $groups_array[] = $this_group; if (in_array(strtolower($this_group), $in_groups_lower_array)) { $in_a_group = TRUE; } } } if ($ignore_in_group || $in_a_group) { $result_array[$user]['user'] = $user; $result_array[$user]['groups'] = $groups_array; $result_array[$user]['accountdisable'] = $accountdisable; $result_array[$user]['mail'] = (isset($one_user['mail'][0]) ? $this->EncodeForBackend($one_user['mail'][0]) : ""); $result_array[$user]['displayname'] = (isset($one_user['displayname'][0]) ? $this->EncodeForBackend($one_user['displayname'][0]) : ""); $result_array[$user]['description'] = (isset($one_user['description'][0]) ? $this->EncodeForBackend($one_user['description'][0]) : ""); $result_array[$user]['mobile'] = (isset($one_user['mobile'][0]) ? $this->EncodeForBackend($one_user['mobile'][0]) : ""); $result_array[$user]['msnpallowdialin'] = ("TRUE" == (isset($one_user['msnpallowdialin'][0]) ? ($one_user['msnpallowdialin'][0]) : "FALSE")); if ("---" != $one_user['msradiusframedipaddress'][0]) { $result_array[$user]['msradiusframedipaddress'] = $one_user['msradiusframedipaddress'][0]; } if ("---" != $one_user['radiusframedipaddress'][0]) { $result_array[$user]['radiusframedipaddress'] = $one_user['radiusframedipaddress'][0]; } if ("---" != $one_user['radiusframedipnetmask'][0]) { $result_array[$user]['radiusframedipnetmask'] = $one_user['radiusframedipnetmask'][0]; } $result_array[$user]['synchronized_dn'] = (isset($one_user['distinguishedname'][0]) ? $this->EncodeForBackend($one_user['distinguishedname'][0]) : ""); $result_array[$user]['language'] = (isset($one_user[strtolower($this->GetLdapLanguageAttribute())][0]) ? $this->EncodeForBackend($one_user[strtolower($this->GetLdapLanguageAttribute())][0]) : ""); $result_array[$user]['account'] = $account; } } } } } else { $this->EnableLdapError(); $this->WriteLog("Error: LDAP connection failed", FALSE, FALSE, 30, 'LDAP', ''); } } else { $this->EnableLdapError(); $this->WriteLog("Error: no LDAP connection information", FALSE, FALSE, 30, 'LDAP', ''); } if ($this->GetVerboseFlag()) { $this->WriteLog("Debug: *AD/LDAP GetLdapUsersInfoArray done (".$ldap_connection->ErrorMessage().")", FALSE, FALSE, 8888, 'Debug', ''); } return $result_array; } function GetUserInfo( $user ) { $crlf = "\n"; $result = ""; if ($this->SetUser($user)) { $result.= "   Information for user: ".$user.$crlf; $result.= "                 Locked: ".((1 == $this->GetUserLocked()) ? 'yes' : 'no').$crlf; $result.= "              Activated: ".((1 == $this->GetUserActivated()) ? 'yes' : 'no').$crlf; $result.= "   AD/LDAP synchronized: ".((1 == $this->GetUserSynchronized()) ? 'yes' : 'no').$crlf; $result.= "      Prefix pin needed: ".((1 == $this->GetUserPrefixPin()) ? 'yes' : 'no').$crlf; $result.= "            Description: ".$this->GetUserDescription().$crlf; $result.= "                  Email: ".$this->GetUserEmail().$crlf; $result.= "           Mobile phone: ".$this->GetUserSms().$crlf; $result.= "                  Group: ".$this->GetUserGroup().$crlf; if ("" != $this->GetUserLanguage(TRUE)) { $result.= "               Language: ".$this->GetUserLanguage(TRUE).$crlf; } else { $result.= "   Language (inherited): ".$this->GetLanguage().$crlf; } if ("" != $this->GetUserKeyId()) { $result.= "               Token id: ".$this->GetUserKeyId().$crlf; } if ("" != $this->GetUserTokenSerialNumber()) { $result.= "    Token serial number: ".$this->GetUserTokenSerialNumber().$crlf; } $result.= "              Algorithm: ".$this->GetUserAlgorithm().$crlf; $result.= "             OTP digits: ".$this->GetUserTokenNumberOfDigits().$crlf; if (('hotp' == $this->GetUserAlgorithm()) || ('yubicootp' == $this->GetUserAlgorithm())) { $result.= "    Next token position: ".($this->GetUserTokenLastEvent()+1).$crlf; } elseif (('totp' == $this->GetUserAlgorithm()) || ('motp' == $this->GetUserAlgorithm())) { $result.= "         Token timestep: ".$this->GetUserTokenTimeInterval().$crlf; } if (is_valid_ipv4($this->GetUserDialinIpAddress())) { $result.= "     Dial-In IP address: ".$this->GetUserDialinIpAddress().$crlf; } if (is_valid_ipv4($this->GetUserDialinIpMask())) { $result.= "        Dial-In IP mask: ".$this->GetUserDialinIpMask().$crlf; } elseif (is_valid_ipv4($this->GetDefaultDialinIpMask())) { $result.= "Default Dial-In IP mask: ".$this->GetDefaultDialinIpMask().$crlf; } } return $result; } function TestLdapUser( $value ) { $result = FALSE; $user_to_check = ($this->IsCaseSensitiveUsers()?$value:strtolower($value)); $ldap_users_array = $this->GetLdapUsersInfoArray(); if (!$this->IsLdapError()) { foreach($ldap_users_array as $one_ldap_user) { $account = $one_ldap_user['account']; $account = ($this->IsCaseSensitiveUsers()?$user:strtolower($account)); if ($user_to_check == $account) { $result = TRUE; break; } } } elseif ($this->GetVerboseFlag()) { $this->WriteLog("Debug: *AD/LDAP error before testing the $value account", FALSE, FALSE, 8888, 'Debug', ''); } return $result; } function SyncLdapUsers( $user_filter = "*", $include_disabled = TRUE, $ignore_in_group = FALSE, $state_info_interval = 60 ) { $result = FALSE; $ldap_sync_stop = FALSE; $ldap_sync_file_lock = $this->GetLockFolder().$this->GetLdapSyncLockFileName(); $ldap_sync_file_stop = $this->GetLockFolder().$this->GetLdapSyncStopFileName(); $info_interval = intval($state_info_interval); if ($info_interval < 1) { $info_interval = 0; } clearstatcache(); if (!function_exists('ldap_connect')) { $this->WriteLog("Error: LDAP library not installed", FALSE, FALSE, 39, 'System', '', 3); $this->EnableLdapError(); } elseif (('' != $this->GetLdapDomainControllers()) && ('' != $this->GetLdapBindDn()) && ('' != $this->GetLdapServerPassword())) { if (file_exists($ldap_sync_file_lock)) { if ((filemtime($ldap_sync_file_lock) + $this->GetLockTime()) >= time()) { $additional_info = ""; $additional_info = trim(@file_get_contents($ldap_sync_file_lock)); $this->WriteLog("Info: Previous AD/LDAP synchronization in progress... $additional_info", FALSE, FALSE, 19, 'LDAP', ''); return TRUE; } } if (file_exists($ldap_sync_file_stop)) { unlink($ldap_sync_file_stop); } $start_sync_time = time(); $last_touch = time(); if ($lock_handle = @fopen($ldap_sync_file_lock, "wt")) { $additional_info = "started at ".date("H:i:s", $start_sync_time); if ($this->GetVerboseFlag()) { $additional_info.= " / Memory used: ".(intval(10*memory_get_usage()/(1024*1024))/10)."MB / Peak: ".(intval(10*memory_get_peak_usage()/(1024*1024))/10)."MB"; $this->WriteLog("Debug: *AD/LDAP synchronization ".$additional_info, FALSE, FALSE, 8888, 'LDAP', ''); } fwrite($lock_handle,$additional_info); fclose($lock_handle); if ('' != $this->GetLinuxFileMode()) { @chmod($ldap_sync_file_lock, octdec($this->GetLinuxFileMode())); } } $this->DisableLdapError(); $in_groups_array = array(); $this->WriteLog("Info: AD/LDAP synchronization started", FALSE, FALSE, 19, 'LDAP', ''); $domain_controllers = explode(" ",trim(str_replace(","," ",str_replace(";"," ",$this->GetLdapDomainControllers())))); $ldap_options = array('account_suffix' => $this->GetLdapAccountSuffix(), 'ad_password' => $this->GetLdapServerPassword(), 'ad_username' => $this->GetLdapBindDn(), 'base_dn' => $this->GetLdapBaseDn(), 'cn_identifier' => $this->GetLdapCnIdentifier(), 'domain_controllers' => $domain_controllers, 'group_attribute' => $this->GetLdapGroupAttribute(), 'group_cn_identifier'=> $this->GetLdapGroupCnIdentifier(), 'ldap_server_type' => $this->GetLdapServerType(), 'network_timeout' => $this->GetLdapNetworkTimeout(), 'port' => $this->GetLdapPort(), 'recursive_groups' => $this->IsLdapRecursiveGroups(), 'time_limit' => $this->GetLdapTimeLimit(), 'use_ssl' => $this->IsLdapSsl(), 'cache_support' => $this->IsLdapCacheOn(), 'cache_folder' => $this->GetLdapCacheFolder() ); $ldap_connection = new MultiotpAdLdap($ldap_options); if ($ldap_connection->IsError()) { $this->WriteLog("Error: ".$ldap_connection->ErrorMessage(), FALSE, FALSE, 79, 'LDAP', ''); $this->EnableLdapError(); } else { $ldap_connection->group_cn(1, FALSE, TRUE); if ($ldap_connection->_recursive_groups) { $all_groups = $ldap_connection->all_groups(FALSE, '*', TRUE, TRUE); reset($all_groups); while(list($key, $one_group) = each($all_groups)) { $ldap_connection->recursive_groups($one_group); } } $ldap_created_counter = 0; $modified_counter = 0; $ldap_total_counter = 0; $existing_ldap_users_counter = 0; $result = TRUE; $page_cookie = ''; $users_in_groups = array(); if ('' != trim($this->GetLdapInGroup())) { $in_groups_array_raw = explode("§",trim(str_replace(",","§",str_replace(";","§",$this->GetLdapInGroup())))); if (1 != $this->GetLdapServerType()) { foreach($in_groups_array_raw as $one_group) { $temp_array = $ldap_connection->group_users($one_group); foreach($temp_array as $one_temp) { $one_user = $this->EncodeForBackend($one_temp); if (!isset($users_in_groups[$one_user])) { $users_in_groups[$one_user] = $one_group; } else { $users_in_groups[$one_user] = $users_in_groups[$one_user].",".$one_group; } } } } } else { $in_groups_array_raw = array(); } do { if (function_exists('ldap_control_paged_result')) { ldap_control_paged_result($ldap_connection->_conn, 1000, true, $page_cookie); } $one_user = $ldap_connection->one_user_info(TRUE, $user_filter, $this->GetLdapFieldsArray(), $this->IsLdapCacheOn() ); if ($ldap_connection->IsError()) { $this->EnableLdapError(); $this->WriteLog("Error: LDAP connection failed", FALSE, FALSE, 30, 'LDAP', ''); if (file_exists($ldap_sync_file_lock)) { unlink($ldap_sync_file_lock); } return FALSE; } if ('' != $ldap_connection->get_warning_message()) { $this->WriteLog("Warning: ".$ldap_connection->get_warning_message(), FALSE, FALSE, 98, 'LDAP', ''); } if ($this->GetVerboseFlag() && ('' != $ldap_connection->get_debug_message())) { $this->WriteLog("Debug: *".$ldap_connection->get_debug_message(), FALSE, FALSE, 98, 'LDAP', ''); } do { if (file_exists($ldap_sync_file_stop)) { unlink($ldap_sync_file_stop); $ldap_sync_stop = TRUE; } if ((($last_touch + ($this->GetLockTime() / 2)) <= time()) || (($last_touch + $info_interval) <= time())) { $last_touch = time(); if ($lock_handle = @fopen($ldap_sync_file_lock, "wt")) { $additional_info = "started at ".date("H:i:s", $start_sync_time); $additional_info.= ", LDAP account #".($ldap_total_counter+1)." at ".date("H:i:s"); if ($this->GetVerboseFlag()) { $additional_info.= " / Memory used: ".(intval(10*memory_get_usage()/(1024*1024))/10)."MB / Peak: ".(intval(10*memory_get_peak_usage()/(1024*1024))/10)."MB"; $this->WriteLog("Debug: *AD/LDAP synchronization ".$additional_info, FALSE, FALSE, 8888, 'LDAP', ''); print_r($one_user); } fwrite($lock_handle,$additional_info); fclose($lock_handle); if ('' != $this->GetLinuxFileMode()) { @chmod($ldap_sync_file_lock, octdec($this->GetLinuxFileMode())); } } } $accountdisable = FALSE; $groups_lower_array = array(); $in_groups_array = array(); $in_groups_lower_array = array(); $group = ""; $user_in_groups = ''; $ldap_total_counter++; $user = $this->EncodeForBackend(isset($one_user[strtolower($this->GetLdapCnIdentifier())][0])?($one_user[strtolower($this->GetLdapCnIdentifier())][0]):''); $account = $this->EncodeForBackend(isset($one_user[strtolower($this->GetLdapSyncedUserAttribute())][0])?($one_user[strtolower($this->GetLdapSyncedUserAttribute())][0]):''); if (!$this->IsCaseSensitiveUsers()) { $user = strtolower($user); $account = strtolower($account); } if ($account != '') { $one_user['msradiusframedipaddress'][0] = (isset($one_user['msradiusframedipaddress'][0])) ? long2ip32bit($one_user['msradiusframedipaddress'][0]) : "---"; $one_user['radiusframedipaddress'][0] = (isset($one_user['radiusframedipaddress'][0])) ? ($one_user['radiusframedipaddress'][0]) : "---"; $one_user['radiusframedipnetmask'][0] = (isset($one_user['radiusframedipnetmask'][0])) ? ($one_user['radiusframedipnetmask'][0]) : "---"; if (isset($one_user['useraccountcontrol'][0])) { if (0 != ($one_user['useraccountcontrol'][0] & 2)) { $accountdisable = TRUE; } } if (isset($one_user['ms-ds-user-account-control-computed'][0])) { if (0 != ($one_user['ms-ds-user-account-control-computed'][0] & 16)) { $accountdisable = TRUE; } } if (isset($one_user['accountexpires'][0])) { if (($one_user['accountexpires'][0] > 0) && ((($one_user['accountexpires'][0] / 10000000) - 11644473600) < time())) { $accountdisable = TRUE; } } if (isset($one_user['shadowexpire'][0])) { if (($one_user['shadowexpire'][0] >= 0) && ((86400 * $one_user['shadowexpire'][0]) < time())) { $accountdisable = TRUE; } } if (isset($one_user['sambaacctflags'][0])) { if ((FALSE !== strpos($one_user['sambaacctflags'][0], "D")) || (FALSE !== strpos($one_user['sambaacctflags'][0], "L"))) { $accountdisable = TRUE; } } if ($include_disabled || (!$accountdisable)) { if ('' == trim($this->GetLdapInGroup())) { $in_a_group = TRUE; } else { $in_a_group = FALSE; $in_groups_array_raw = explode("§",trim(str_replace(",","§",str_replace(";","§",$this->GetLdapInGroup())))); foreach($in_groups_array_raw as $one_group) { $in_groups_array[] = trim($one_group); $in_groups_lower_array[] = strtolower(trim($one_group)); } if (1 != $this->GetLdapServerType()) { if (1 != $this->GetLdapServerType()) { foreach($in_groups_array_raw as $one_group) { $temp_array = $ldap_connection->group_users($one_group); foreach($temp_array as $one_temp) { $one_user = $this->EncodeForBackend($one_temp); if ($user == $one_user) { $user_in_groups.= (('' != $user_in_groups) ? ',' : '') . $one_group; $in_a_group = TRUE; } } } } if ($in_a_group) { $temp_array = explode(",", $user_in_groups); $group = $temp_array[0]; } } else { $groups_array_raw=$ldap_connection->nice_names($one_user[$ldap_connection->_group_attribute]); if ($ldap_connection->_recursive_groups) { foreach ($groups_array_raw as $id => $group_name){ $extra_groups=$ldap_connection->recursive_groups($group_name, $this->IsLdapRecursiveCacheOnly()); if ('' != $ldap_connection->get_warning_message()) { $this->WriteLog("Warning: ".$ldap_connection->get_warning_message(), FALSE, FALSE, 98, 'LDAP', ''); } $groups_array_raw=array_merge($groups_array_raw,$extra_groups); } } foreach($groups_array_raw as $one_group) { $this_group = $this->EncodeForBackend($one_group); $groups_lower_array[] = strtolower($this_group); } foreach($in_groups_array as $one_filtered_group) { if (in_array(strtolower($one_filtered_group), $groups_lower_array)) { $user_in_groups.= (('' != $user_in_groups) ? ',' : '') . $one_filtered_group; $in_a_group = TRUE; if ("" == $group) { $group = $one_filtered_group; } } } } } if ($ignore_in_group || $in_a_group) { $description = ''; if (isset($one_user['description'][0])) { $description = trim($one_user['description'][0]); } if (('' == $description) && (isset($one_user['gecos'][0]))) { $description = trim($one_user['gecos'][0]); } if (('' == $description) && (isset($one_user['displayname'][0]))) { $description = trim($one_user['displayname'][0]); } if ('' == $description) { $description = $account; } $ldap_email = trim(isset($one_user['mail'][0])?$this->EncodeForBackend($one_user['mail'][0]):""); $ldap_group = trim(('' != $group) ? $group : $this->GetDefaultUserGroup()); if ($this->IsMultipleGroupsEnabled()) { $ldap_group = trim(('' != $user_in_groups) ? $user_in_groups : $this->GetDefaultUserGroup()); } $ldap_description = $this->EncodeForBackend($description); $ldap_sms = (isset($one_user['mobile'][0])?$this->EncodeForBackend($one_user['mobile'][0]):""); $ldap_msnpallowdialin = ("TRUE" == (isset($one_user['msnpallowdialin'][0])?($one_user['msnpallowdialin'][0]):"FALSE")); $ldap_enabled = ((!$accountdisable)?1:0); $ldap_synchronized_dn = trim(isset($one_user['distinguishedname'][0])?$this->EncodeForBackend($one_user['distinguishedname'][0]):""); $ldap_language = strtolower(substr(trim(isset($one_user[strtolower($this->GetLdapLanguageAttribute())][0])?$this->EncodeForBackend($one_user[strtolower($this->GetLdapLanguageAttribute())][0]):""), 0, 2)); $ldap_framedipaddress = (isset($one_user['msradiusframedipaddress'][0]) ? ($one_user['msradiusframedipaddress'][0]) : "---"); if ("---" == $ldap_framedipaddress) { $ldap_framedipaddress = (isset($one_user['radiusframedipaddress'][0]) ? ($one_user['radiusframedipaddress'][0]) : "---"); } $ldap_framedipnetmask = (isset($one_user['radiusframedipnetmask'][0]) ? ($one_user['radiusframedipnetmask'][0]) : "---"); if (!$this->CheckUserExists($account, true, true)) { if ('' == $ldap_description) { $ldap_description = $account; } $result = $this->FastCreateUser($account, $ldap_email, $ldap_sms, -1, $this->GetLdapDefaultAlgorithm(), $ldap_enabled, $ldap_description, $ldap_group, 1, '', true, 'LDAP', $this->GetLdapDomainControllers(), $ldap_synchronized_dn, -1, $ldap_language, (("---" != $ldap_framedipaddress) ? $ldap_framedipaddress : "") ); if ($result) { $this->SyncUserModified(TRUE, $account); $ldap_created_counter++; } } else { $existing_ldap_users_counter++; $this->SetUser($account); if (1 == $this->GetUserSynchronized()) { $description = $this->GetUserDescription(); $email = $this->GetUserEmail(); $enabled = $this->GetUserActivated(); $group = $this->GetUserGroup(); $sms = $this->GetUserSms(); $synchronized_channel = $this->GetUserSynchronizedChannel(); $synchronized_dn = $this->GetUserSynchronizedDn(); $synchronized_server = $this->GetUserSynchronizedServer(); $language = $this->GetUserLanguage(TRUE); $dialin_ip_address = $this->GetUserDialinIpAddress(); $dialin_ip_mask = $this->GetUserDialinIpMask(); $modified = FALSE; $detailed_modif = ""; if (('' != $ldap_description) && ($description != $ldap_description)) { $this->SetUserDescription($ldap_description); $modified = TRUE; $detailed_modif.= "$description-$ldap_description / "; } if (('' != $ldap_email) && ($email != $ldap_email)) { $this->SetUserEmail($ldap_email); $modified = TRUE; $detailed_modif.= "$email-$ldap_email / "; } if ($enabled != $ldap_enabled) { $this->SetUserActivated($ldap_enabled); $modified = TRUE; $detailed_modif.= "$enabled-$ldap_enabled / "; } if (('' != $ldap_group) && ($group != $ldap_group)) { $this->SetUserGroup($ldap_group); $modified = TRUE; $detailed_modif.= "$group-$ldap_group / "; } if (('' != $ldap_sms) && ($sms != $ldap_sms)) { $this->SetUserSms($ldap_sms); $modified = TRUE; $detailed_modif.= "$sms-$ldap_sms / "; } if ($synchronized_channel != 'LDAP') { $this->SetUserSynchronizedChannel('LDAP'); $modified = TRUE; $detailed_modif.= "$synchronized_channel / "; } if ($synchronized_dn != $ldap_synchronized_dn) { $this->SetUserSynchronizedDn($ldap_synchronized_dn); $modified = TRUE; $detailed_modif.= "$synchronized_dn-$ldap_synchronized_dn / "; } if (('' != $this->GetLdapDomainControllers()) && ($synchronized_server != $this->GetLdapDomainControllers())) { $this->SetUserSynchronizedServer($this->GetLdapDomainControllers()); $modified = TRUE; $detailed_modif.= "$synchronized_server-".$this->GetLdapDomainControllers()." / "; } if ($language != $ldap_language) { $this->SetUserLanguage($ldap_language); $modified = TRUE; $detailed_modif.= "$language-$ldap_language / "; } if ("---" != $ldap_framedipaddress) { if ($dialin_ip_address != $ldap_framedipaddress) { $this->SetUserDialinIpAddress($ldap_framedipaddress); $modified = TRUE; $detailed_modif.= "$dialin_ip_address-$ldap_framedipaddress / "; } } if ("---" != $ldap_framedipnetmask) { if ($dialin_ip_mask != $ldap_framedipnetmask) { $this->SetUserDialinIpNetmask($ldap_framedipnetmask); $modified = TRUE; $detailed_modif.= "$dialin_ip_address-$ldap_framedipnetmask / "; } } if ($this->IsOverwriteRequestLdapPwd()) { if ($this->GetUserRequestLdapPassword() != $this->GetDefaultRequestLdapPwd()) { $this->SetUserRequestLdapPassword($this->GetDefaultRequestLdapPwd()); $modified = TRUE; } } $this->SetUserSynchronizedTime(); $this->WriteUserData(TRUE, $modified); if ($modified) { if ($this->GetVerboseFlag()) { $this->WriteLog("Debug: *AD/LDAP $account modified: $detailed_modif", FALSE, FALSE, 8888, 'Debug', ''); } $this->SyncUserModified(FALSE, $account); $modified_counter++; } } } } } } } while ((!$ldap_sync_stop) && ($one_user = $ldap_connection->one_user_info(FALSE, NULL, NULL, TRUE))); if (function_exists('ldap_control_paged_result_response')) { ldap_control_paged_result_response($ldap_connection->_conn, $ldap_connection->_oui_sr, $page_cookie); } } while ((!$ldap_sync_stop) && ($page_cookie !== null) && ($page_cookie != '')); if (function_exists('ldap_control_paged_result')) { ldap_control_paged_result($ldap_connection->_conn, 1000); } if (!$ldap_sync_stop) { $internal_users_loop = 0; $one_user = $this->GetNextUserArray(TRUE); do { if (($last_touch + ($this->GetLockTime() / 2)) <= time()) { $last_touch = time(); if ($lock_handle = @fopen($ldap_sync_file_lock, "wt")) { $additional_info = "started at ".date("H:i:s", $start_sync_time); $additional_info.= ", internal account #".($internal_users_loop+1)." at ".date("H:i:s"); if ($this->GetVerboseFlag()) { $additional_info.= " / Memory used: ".(intval(10*memory_get_usage()/(1024*1024))/10)."MB / Peak: ".(intval(10*memory_get_peak_usage()/(1024*1024))/10)."MB"; $this->WriteLog("Debug: *AD/LDAP synchronization ".$additional_info, FALSE, FALSE, 8888, 'LDAP', ''); } fwrite($lock_handle,$additional_info); fclose($lock_handle); if ('' != $this->GetLinuxFileMode()) { @chmod($ldap_sync_file_lock, octdec($this->GetLinuxFileMode())); } } if (file_exists($ldap_sync_file_stop)) { unlink($ldap_sync_file_stop); $ldap_sync_stop = TRUE; } } if (isset($one_user['user'])) { $modified_user = $one_user['user']; $modified_description = $one_user['description']; $modified_email = $one_user['email']; $modified_enabled = $one_user['enabled']; $modified_locked = $one_user['locked']; $modified_sms = $one_user['sms']; $modified_synchronized = $one_user['synchronized']; $modified_synchronized_channel = $one_user['synchronized_channel']; $modified_synchronized_dn = $one_user['synchronized_dn']; $modified_synchronized_server = $one_user['synchronized_server']; $modified_synchronized_time = $one_user['synchronized_time']; $modified_token_serial = $one_user['token']; if (($modified_synchronized) && ($modified_synchronized_time < $start_sync_time)) { $existing_ldap_users_counter++; if ($modified_enabled) { $this->SetUser($modified_user); $this->SetUserActivated(0); $this->WriteUserData(TRUE); $modified_counter++; } } } $internal_users_loop++; } while (($one_user = $this->GetNextUserArray()) && (!$ldap_sync_stop)); if ($ldap_sync_stop) { $this->WriteLog("Info: LDAP sync stopped", FALSE, FALSE, 19, 'LDAP', ''); } else { $time_info = gmdate("H:i:s", time()-$start_sync_time); $info_txt = ''; if ($modified_counter > 0) { $ldap_counter_suffix = ((1 < $modified_counter)?'s':''); $info_txt.= $modified_counter." user$ldap_counter_suffix updated, based on $ldap_total_counter LDAP entries"; } if ($ldap_created_counter > 0) { if ('' != $info_txt) { $info_txt.= ', '; } $ldap_counter_suffix = ((1 < $ldap_created_counter)?'s':''); $info_txt.= $ldap_created_counter." user$ldap_counter_suffix created, based on $ldap_total_counter LDAP entries"; } if ('' == $info_txt) { $info_txt = "No update for the $existing_ldap_users_counter LDAP synced users, based on $ldap_total_counter LDAP entries"; } $this->WriteLog("Info: $info_txt (processed in $time_info)", FALSE, FALSE, 19, 'LDAP', ''); } } else { $this->WriteLog("Info: LDAP sync stopped", FALSE, FALSE, 19, 'LDAP', ''); } } } else { $this->EnableLdapError(); $this->WriteLog("Error: no LDAP connection information", FALSE, FALSE, 30, 'LDAP', ''); } if (file_exists($ldap_sync_file_lock)) { unlink($ldap_sync_file_lock); } return $result; } function SyncUserModified( $created = FALSE, $user = '' ) { return TRUE; } function CheckLdapAuthentication() { $result = FALSE; if (!function_exists('ldap_connect')) { $this->WriteLog("Error: LDAP library not installed", FALSE, FALSE, 39, 'System', '', 3); } elseif (('' != $this->GetLdapDomainControllers()) && ('' != $this->GetLdapBindDn()) && ('' != $this->GetLdapServerPassword())) { $domain_controllers = explode(" ",trim(str_replace(","," ",str_replace(";"," ",$this->GetLdapDomainControllers())))); $ldap_options = array('account_suffix' => $this->GetLdapAccountSuffix(), 'ad_password' => $this->GetLdapServerPassword(), 'ad_username' => $this->GetLdapBindDn(), 'base_dn' => $this->GetLdapBaseDn(), 'cn_identifier' => $this->GetLdapCnIdentifier(), 'domain_controllers' => $domain_controllers, 'group_attribute' => $this->GetLdapGroupAttribute(), 'group_cn_identifier'=> $this->GetLdapGroupCnIdentifier(), 'ldap_server_type' => $this->GetLdapServerType(), 'network_timeout' => $this->GetLdapNetworkTimeout(), 'port' => $this->GetLdapPort(), 'recursive_groups' => $this->IsLdapRecursiveGroups(), 'time_limit' => $this->GetLdapTimeLimit(), 'use_ssl' => $this->IsLdapSsl() ); define('LDAP_OPT_DIAGNOSTIC_MESSAGE', 0x0032); $domain_controllers = explode(" ",trim(str_replace(","," ",str_replace(";"," ",$this->GetLdapDomainControllers())))); mt_srand(doubleval(microtime()) * 100000000); $domain_controller = ($domain_controllers[array_rand($domain_controllers)]); foreach($domain_controllers as $dc) { $port = $this->GetLdapPort(); $controller = $dc; $protocol = "ldap://"; if ($this->IsLdapSsl()) { $protocol = "ldaps://"; } $pos = strpos($dc, "://"); if ($pos !== FALSE) { $protocol = substr($dc, 0, $pos+3); $dc = substr($dc, $pos+3); } $pos = strpos($dc, ":"); if ($pos !== FALSE) { $port = substr($dc, $pos+1); $dc = substr($dc, 0, $pos); } if ($ldapconn = @ldap_connect($protocol.$dc.":".$port)) { ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3); ldap_set_option($ldapconn, LDAP_OPT_REFERRALS, 0); if (@ldap_bind($ldapconn, ($this->GetLdapBindDn().$this->GetLdapAccountSuffix()), ($this->GetLdapServerPassword()))) { $result = TRUE; } else { } @ldap_unbind($ldapconn); } if ($result) { break; } } } return $result; } function SetTokenDataReadFlag( $flag ) { $this->_token_data_read_flag = $flag; } function GetTokenDataReadFlag() { return $this->_token_data_read_flag; } function SetBaseDir( $base_dir ) { $this->_base_dir = $this->ConvertToUnixPath($base_dir); } function GetBaseDir() { return ($this->_base_dir); } function GetScriptFolder() { if ('' != $this->GetBaseDir()) { $current_script_folder_detected = $this->ConvertToUnixPath($this->GetBaseDir()); } else { $current_script_folder_detected = $this->ConvertToUnixPath(dirname(__FILE__)); } if (substr($current_script_folder_detected,-1) != "/") { $current_script_folder_detected.="/"; } return $this->ConvertToWindowsPathIfNeeded($current_script_folder_detected); } function ConvertToUnixPath( $path ) { return str_replace("\\","/",$path); } function ConvertToWindowsPathIfNeeded( $path ) { $result = $path; if (FALSE !== strpos($result,":")) { $result = str_replace("/","\\",$result); } return $result; } function GetReplyMessageForRadius() { return (isset($this->_reply_array_for_radius[0]) ? $this->_reply_array_for_radius[0] : ''); } function SetReplyMessageForRadius( $value ) { $this->_reply_array_for_radius = array(); $this->AddReplyArrayMessageForRadius($value); } function GetReplyArrayForRadius() { return $this->_reply_array_for_radius; } function AddReplyArrayForRadius( $value ) { $this->_reply_array_for_radius[] = $value; } function AddExtraRadiusInfo($options = array()) { if (isset($options['multiple_groups'])) { $multiple_groups = (isset($options['multiple_groups']) ? (TRUE == $options['multiple_groups']) : FALSE); } else { $multiple_groups = $this->IsMultipleGroupsEnabled(); } $group = trim($this->GetUserGroup()); if (('' != $group) && ('' != $this->GetGroupAttribute())) { $group_array = explode("§",trim(str_replace(",","§",str_replace(";","§",$group)))); if ($multiple_groups) { foreach($group_array as $one_group) { if ("" != trim($one_group)) { $this->AddReplyArrayForRadius($this->GetGroupAttribute().$this->GetRadiusReplyAttributor().'"'.$one_group.'"'); } } if ($this->GetVerboseFlag()) { $this->AddReplyArrayForRadius($this->GetGroupAttribute().$this->GetRadiusReplyAttributor().'"'."multiotp-debug-group".'"'); } } else { $this->AddReplyArrayForRadius($this->GetGroupAttribute().$this->GetRadiusReplyAttributor().'"'.$group_array[0].'"'); } } if (('' != $this->GetLastClearOtpValue()) && ('' != $this->GetClearOtpAttribute())) { $this->AddReplyArrayForRadius($this->GetClearOtpAttribute().$this->GetRadiusReplyAttributor().'"'.$this->GetLastClearOtpValue().'"'); } $dialin_ip_address = trim($this->GetUserDialinIpAddress()); if (is_valid_ipv4($dialin_ip_address)) { $dialin_ip_mask = trim($this->GetUserDialinIpMask()); if (!is_valid_ipv4($dialin_ip_mask)) { $dialin_ip_mask = $this->GetDefaultDialinIpMask(); } $this->AddReplyArrayForRadius('Framed-IP-Address'.$this->GetRadiusReplyAttributor().''.$dialin_ip_address.''); if (is_valid_ipv4($dialin_ip_mask)) { $this->AddReplyArrayForRadius('Framed-IP-Netmask'.$this->GetRadiusReplyAttributor().''.$dialin_ip_mask.''); } } } function SetVerboseLogPrefix( $value ) { $this->_config_data['verbose_log_prefix'] = $value; } function GetVerboseLogPrefix() { return $this->_config_data['verbose_log_prefix']; } function SetAttributesToEncrypt( $attributes_to_encrypt ) { $attributes = trim($attributes_to_encrypt); if (('' != $attributes) && ('*' == substr($attributes,0,1)) && ('*' == substr($attributes,-1))) { $this->_attributes_to_encrypt = $attributes; } } function GetAttributesToEncrypt() { return $this->_attributes_to_encrypt; } function SetUsersFolder( $folder, $create = true ) { $new_folder = $this->ConvertToUnixPath($folder); if (substr($new_folder,-1) != "/") { $new_folder.="/"; } if ("/" == $new_folder) { $new_folder = "./"; } $new_folder = $this->ConvertToWindowsPathIfNeeded($new_folder); $this->_users_folder = $new_folder; if ($create && (!file_exists($new_folder))) { if (!@mkdir( $new_folder, ('' != $this->GetLinuxFolderMode()) ? octdec($this->GetLinuxFolderMode()) : 0777, true )) { $this->WriteLog("Error: Unable to create the missing users folder ".$new_folder, FALSE, FALSE, 28, 'System', ''); } } } function GetUsersFolder() { if ('' == $this->_users_folder) { $this->SetUsersFolder($this->GetScriptFolder()."users/"); } return $this->ConvertToWindowsPathIfNeeded($this->_users_folder); } function SetDevicesFolder( $folder, $create = true ) { $new_folder = $this->ConvertToUnixPath($folder); if (substr($new_folder,-1) != "/") { $new_folder.="/"; } if ("/" == $new_folder) { $new_folder = "./"; } $new_folder = $this->ConvertToWindowsPathIfNeeded($new_folder); $this->_devices_folder = $new_folder; if ($create && (!file_exists($new_folder))) { if (!@mkdir( $new_folder, ('' != $this->GetLinuxFolderMode()) ? octdec($this->GetLinuxFolderMode()) : 0777, true )) { $this->WriteLog("Error: Unable to create the missing devices folder ".$new_folder, FALSE, FALSE, 28, 'System', ''); } } } function GetDevicesFolder() { if ('' == $this->_devices_folder) { $this->SetDevicesFolder($this->GetScriptFolder()."devices/"); } return $this->ConvertToWindowsPathIfNeeded($this->_devices_folder); } function SetQrCodeFolder( $folder ) { $new_folder = $this->ConvertToUnixPath($folder); if (substr($new_folder,-1) != "/") { $new_folder.="/"; } if ("/" == $new_folder) { $new_folder = "./"; } $new_folder = $this->ConvertToWindowsPathIfNeeded($new_folder); $this->_qrcode_folder = $new_folder; } function GetQrCodeFolder() { if ('' == $this->_qrcode_folder) { $this->SetQrCodeFolder($this->GetScriptFolder()."qrcode/"); } return $this->ConvertToWindowsPathIfNeeded($this->_qrcode_folder); } function SetTemplatesFolder( $folder ) { $new_folder = $this->ConvertToUnixPath($folder); if (substr($new_folder,-1) != "/") { $new_folder.="/"; } if ("/" == $new_folder) { $new_folder = "./"; } $new_folder = $this->ConvertToWindowsPathIfNeeded($new_folder); $this->_templates_folder = $new_folder; } function GetTemplatesFolder() { if ('' == $this->_templates_folder) { $this->SetTemplatesFolder($this->GetScriptFolder()."templates/"); } return $this->ConvertToWindowsPathIfNeeded($this->_templates_folder); } function SetGroupsFolder( $folder, $create = true ) { $new_folder = $this->ConvertToUnixPath($folder); if (substr($new_folder,-1) != "/") { $new_folder.="/"; } if ("/" == $new_folder) { $new_folder = "./"; } $new_folder = $this->ConvertToWindowsPathIfNeeded($new_folder); $this->_groups_folder = $new_folder; if ($create && (!file_exists($new_folder))) { if (!@mkdir( $new_folder, ('' != $this->GetLinuxFolderMode()) ? octdec($this->GetLinuxFolderMode()) : 0777, true )) { $this->WriteLog("Error: Unable to create the missing groups folder ".$new_folder, FALSE, FALSE, 28, 'System', ''); } } } function GetGroupsFolder() { if ('' == $this->_groups_folder) { $this->SetGroupsFolder($this->GetScriptFolder()."groups/"); } return $this->ConvertToWindowsPathIfNeeded($this->_groups_folder); } function SendSms( $sms_recipient, $sms_message_to_send, $real_user = '', $originator = '', $provider = '', $userkey = '', $password = '', $api_id = '', $write_log = TRUE, $source_tag = '' ) { $sms_number = $this->CleanPhoneNumber($sms_recipient); $result = 62; $sms_originator = (('' != $originator)?$originator:$this->GetSmsOriginator()); $sms_provider = strtolower((('' != $provider)?$provider:$this->GetSmsProvider())); $sms_userkey = (('' != $userkey)?$userkey:$this->GetSmsUserkey()); $sms_password = (('' != $password)?$password:$this->GetSmsPassword()); $sms_api_id = (('' != $api_id)?$api_id:$this->GetSmsApiId()); if ("aspsms" == $sms_provider) { $sms_message = new MultiotpAspSms($sms_userkey, $sms_password); $sms_message->setOriginator($sms_originator); $sms_message->setRecipient($sms_number); $sms_message->setContent($sms_message_to_send); $sms_result = intval($sms_message->sendSMS()); if (1 != $sms_result) { $result = 61; if ($write_log) { $this->WriteLog("Error: SMS code request received for ".$real_user.(("" != $source_tag)?" for $source_tag":"").", but the ".$sms_provider." error ".$sms_result." occurred during transmission to ".$sms_number, FALSE, FALSE, $result, 'SMS', $real_user); } } else { $result = 18; if ($write_log) { $this->WriteLog("Info: SMS code request received for ".$real_user.(("" != $source_tag)?" for $source_tag":"")." and sent via ".$sms_provider." to ".$sms_number, FALSE, FALSE, $result, 'SMS', $real_user); } } } elseif ("clickatell" == $sms_provider) { $sms_message = new MultiotpClickatell($sms_userkey, $sms_password, $sms_api_id); $sms_message->useRegularServer(); $sms_message->setOriginator($sms_originator); $sms_message->setRecipient($sms_number); $sms_message->setContent(encode_utf8_if_needed($sms_message_to_send)); $sms_result = intval($sms_message->sendSMS()); if (1 != $sms_result) { $result = 61; if ($write_log) { $this->WriteLog("Error: SMS code request received for ".$real_user.(("" != $source_tag)?" for $source_tag":"").", but the ".$sms_provider." error ".$sms_result." occurred during transmission to ".$sms_number, FALSE, FALSE, $result, 'SMS', $real_user); if ($this->GetVerboseFlag()) { $this->WriteLog("DEBUG: *Sent to server: ".encode_utf8_if_needed($sms_message_to_send)); $this->WriteLog("DEBUG: *Received from server: ".$sms_message->getReply()); } } } else { $result = 18; if ($write_log) { $this->WriteLog("Info: SMS code request received for ".$real_user.(("" != $source_tag)?" for $source_tag":"")." and sent via ".$sms_provider." to ".$sms_number, FALSE, FALSE, $result, 'SMS', $real_user); } } } elseif ("intellisms" == $sms_provider) { $sms_message = new MultiotpIntelliSms($sms_userkey, $sms_password); $sms_message->useRegularServer(); $sms_message->setOriginator($sms_originator); $sms_message->setRecipient($sms_number); $sms_message->setContent(encode_utf8_if_needed($sms_message_to_send)); $sms_result = $sms_message->sendSMS(); if ("ID" != substr($sms_result,0,2)) { $result = 61; if ($write_log) { $this->WriteLog("Error: SMS code request received for ".$real_user.(("" != $source_tag)?" for $source_tag":"").", but the ".$sms_provider." error ".$sms_result." occurred during transmission to ".$sms_number, FALSE, FALSE, $result, 'SMS', $real_user); } } else { $result = 18; if ($write_log) { $this->WriteLog("Info: SMS code request received for ".$real_user.(("" != $source_tag)?" for $source_tag":"")." and sent via ".$sms_provider." to ".$sms_number, FALSE, FALSE, $result, 'SMS', $real_user); } } } elseif ("exec" == $sms_provider) { $exec_cmd = $sms_api_id; $exec_cmd = str_replace('%from', $sms_originator, $exec_cmd); $exec_cmd = str_replace('%to', $sms_number, $exec_cmd); $exec_cmd = str_replace('%msg', encode_utf8_if_needed($sms_message_to_send), $exec_cmd); exec($exec_cmd, $output); $result = 18; if ($write_log) { $this->WriteLog("Info: SMS code request received for ".$real_user.(("" != $source_tag)?" for $source_tag":"")." and sent via ".$exec_cmd, FALSE, FALSE, $result, 'SMS', $real_user); } } else { $result = 62; if ($write_log) { $this->WriteLog("Error: SMS provider ".$sms_provider." not supported".(("" != $source_tag)?" for $source_tag":""), FALSE, FALSE, $result, 'SMS', $real_user); } } return $result; } function GenerateSmsToken( $user = '' ) { $result = 99; $now_epoch = time(); if ('' != $user) { $this->SetUser($user); } else { $user = $this->GetUser(); } $sms_number = $this->CleanPhoneNumber($this->GetUserSms()); if ('' != $sms_number) { $sms_message_prefix = trim($this->GetSmsMessage()); $sms_now_steps = $now_epoch; $sms_digits = $this->GetSmsDigits(); $sms_seed_bin = hex2bin(md5('sMs'.$this->GetEncryptionKey().$this->GetUserTokenSeed().$user.$now_epoch)); $sms_token = $this->GenerateOathHotp($sms_seed_bin,$sms_now_steps,$sms_digits); $this->SetUserSmsOtp($sms_token); $this->SetUserSmsValidity($now_epoch + $this->GetSmsTimeout()); $sms_nice_token = $this->ConvertToNiceToken($sms_token); if (FALSE !== strpos($sms_message_prefix, '%s')) { $sms_message_to_send = sprintf($sms_message_prefix, $sms_nice_token); } else { $sms_message_to_send = $sms_message_prefix.' '.$sms_nice_token; } $result = $this->SendSms($sms_number, $sms_message_to_send, $user); } else { $result = 60; $this->WriteLog("Error: no information on where to send SMS code for ".$real_user, FALSE, FALSE, $result, 'SMS', $real_user); } $this->WriteUserData(); return $result; } function ConvertToNiceToken( $regular_token ) { $token_length = strlen($regular_token); if (9 <= $token_length) { $sms_nice_token = substr($regular_token,0,3).'-'.substr($regular_token,3,3).'-'.substr($regular_token,6,($token_length-6)); } elseif (6 < $token_length) { $sms_nice_token = substr($regular_token,0,intval($token_length/2)).'-'.substr($regular_token,intval($token_length/2),$token_length); } else { $sms_nice_token = $regular_token; } return $sms_nice_token; } function ResyncUserToken($user = '', $input = '', $input_sync = '', $display_status = FALSE, $ignore_lock = FALSE, $resync_enc_pass = FALSE, $no_server_check = FALSE, $self_register_serial = '', $hardware_tokens_list = '' ) { $the_hardware_tokens_list = $hardware_tokens_list; if ('' != $user) { $this->SetUser($user); $the_hardware_tokens_list = $this->GetUserTokenSerialNumber(); } $result = $this->ResyncToken($input, $input_sync, $display_status, $ignore_lock, $resync_enc_pass, $no_server_check, $self_register_serial, $the_hardware_tokens_list); return $result; } function ResyncToken($input = '', $input_sync = '', $display_status = FALSE, $ignore_lock = FALSE, $resync_enc_pass = FALSE, $no_server_check = FALSE, $self_register_serial = '', $hardware_tokens_list = '' ) { $result = $this->CheckToken($input, $input_sync, $display_status, $ignore_lock, $resync_enc_pass, $no_server_check, $self_register_serial, $hardware_tokens_list); return (($result == 14) || ($result == 0)); } function CheckUserToken( $function_array = array('user' => ''), $input_param = '', $input_sync_param = '', $display_status_param = FALSE, $ignore_lock_param = FALSE, $resync_enc_pass_param = FALSE, $no_server_check_param = FALSE, $self_register_serial_param = '', $hardware_tokens_list_param = '' ) { if (is_array($function_array)) { $user = isset($function_array['user'])?$function_array['user']:''; $input = isset($function_array['input'])?$function_array['input']:''; $input_sync = isset($function_array['input_sync'])?$function_array['input_sync']:''; $display_status = isset($function_array['display_status'])?$function_array['display_status']:FALSE; $ignore_lock = isset($function_array['ignore_lock'])?$function_array['ignore_lock']:FALSE; $resync_enc_pass = isset($function_array['resync_enc_pass'])?$function_array['resync_enc_pass']:FALSE; $no_server_check = isset($function_array['no_server_check'])?$function_array['no_server_check']:FALSE; $self_register_serial = isset($function_array['self_register_serial'])?$function_array['self_register_serial']:''; $hardware_tokens_list = isset($function_array['hardware_tokens_list'])?$function_array['hardware_tokens_list']:''; } else { $user = $function_array; $input = $input_param; $input_sync = $input_sync_param; $display_status = $display_status_param; $ignore_lock = $ignore_lock_param; $resync_enc_pass = $resync_enc_pass_param; $no_server_check = $no_server_check_param; $self_register_serial = $self_register_serial_param; $hardware_tokens_list = $hardware_tokens_list_param; } if ('' != $user) { $this->SetUser($user); $hardware_tokens_list = $this->GetUserTokenSerialNumber(); } return $this->CheckToken(array('user' => $user, 'input' => $input, 'input_sync' => $input_sync, 'display_status' => $display_status, 'ignore_lock' => $ignore_lock, 'resync_enc_pass' => $resync_enc_pass, 'no_server_check' => $no_server_check, 'self_register_serial' => $self_register_serial, 'hardware_tokens_list' => $hardware_tokens_list)); } function CheckToken( $input_array = array('input' => ''), $input_sync_param = '', $display_status_param = FALSE, $ignore_lock_param = FALSE, $resync_enc_pass_param = FALSE, $no_server_check_param = FALSE, $self_register_serial_param = '', $hardware_tokens_list_param = '' ) { $now_epoch = time(); if (is_array($input_array)) { $input = isset($input_array['input'])?$input_array['input']:''; $input_sync = isset($input_array['input_sync'])?$input_array['input_sync']:''; $display_status = isset($input_array['display_status'])?$input_array['display_status']:FALSE; $ignore_lock = isset($input_array['ignore_lock'])?$input_array['ignore_lock']:FALSE; $resync_enc_pass = isset($input_array['resync_enc_pass'])?$input_array['resync_enc_pass']:FALSE; $no_server_check = isset($input_array['no_server_check'])?$input_array['no_server_check']:FALSE; $self_register_serial = isset($input_array['self_register_serial'])?$input_array['self_register_serial']:''; $hardware_tokens_list = isset($input_array['hardware_tokens_list'])?$input_array['hardware_tokens_list']:''; $no_increment_error = isset($input_array['no_increment_error'])?$input_array['no_increment_error']:FALSE; } else { $input = $input_array; $input_sync = $input_sync_param; $display_status = $display_status_param; $ignore_lock = $ignore_lock_param; $resync_enc_pass = $resync_enc_pass_param; $no_server_check = $no_server_check_param; $self_register_serial = $self_register_serial_param; $hardware_tokens_list = $hardware_tokens_list_param; $no_increment_error = FALSE; } $cache_result_enabled = false; $disable_error_counter = false; $source_tag = trim($this->GetSourceTag()); if ('' != $source_tag) { $device_id = substr($source_tag, strrpos('-'.$source_tag, '-')); if ($this->ReadDeviceData($device_id)) { $cache_result_enabled = $this->IsDeviceCacheResultEnabled(); } } $ldap_check_passed = FALSE; $this->SendWeeklyAnonymousStat(); $this->SetLastClearOtpValue(); $calculated_token = ''; $input_to_check = $input; $real_user = $this->GetUser(); if (strlen($input_to_check) < 3) { $input_to_check = "! <3 digits"; } $server_result = -1; if ((!$no_server_check) && ('' != $this->GetServerUrl())) { if ($this->ReadUserData($real_user)) { if (1 == intval($this->GetUserMultiAccount())) { $pos = strrpos($input_to_check, " "); if ($pos !== FALSE) { $real_user = substr($input_to_check,0,$pos); $input_to_check = trim(substr($input_to_check,$pos+1)); if (strlen($input_to_check) < 3) { $input_to_check = "! <3 digits"; } } } } if ('' != $this->GetChapPassword()) { if (32 < strlen($this->GetChapPassword())) { $hex_id = substr($this->GetChapPassword(),0,2); } else { $hex_id = $this->GetChapId(); } $server_result = $this->CheckUserTokenOnServer($real_user, $this->GetChapPassword(), 'CHAP', $hex_id, $this->GetChapChallenge()); } else { $server_result = $this->CheckUserTokenOnServer($real_user, $input_to_check); } if ($this->_xml_dump_in_log) { $this->WriteLog("Debug: CheckUserTokenOnServer returns ".$server_result, FALSE, FALSE, 8888, 'Debug', ''); } } if ($this->GetVerboseFlag() && $this->IsKeepLocal()) { $this->WriteLog("Info: *Local users are kept locally", FALSE, FALSE, 8888, 'System', ''); } if (0 == $server_result) { $result = 0; $this->WriteLog("Info: User ".$real_user." successfully logged in using an external server", FALSE, FALSE, $result, 'User'); } elseif (18 == $server_result) { $result = 18; $this->WriteLog("Info: SMS code request received and sent for ".$real_user." to ".$this->CleanPhoneNumber($this->GetUserSms()), FALSE, FALSE, $result, 'SMS', $real_user); } elseif ((21 == $server_result) && (!$this->IsKeepLocal())) { $this->DeleteUser($real_user, TRUE); $result = 21; $this->WriteLog("Error: User ".$real_user." doesn't exist", FALSE, FALSE, $result, 'User'); } elseif ((($server_result >= 0) && (22 <= $server_result) && (70 > $server_result)) || (90 <= $server_result)) { $result = $server_result; } elseif (!$this->ReadUserData($real_user, FALSE, TRUE)) { $result = 21; $this->WriteLog("Error: User ".$real_user." doesn't exist", FALSE, FALSE, $result, 'User'); } else { $result = 99; if (1 == intval($this->GetUserMultiAccount())) { $pos = strrpos($input_to_check, " "); if ($pos !== FALSE) { $real_user = substr($input_to_check,0,$pos); $input_to_check = trim(substr($input_to_check,$pos+1)); if (strlen($input_to_check) < 3) { $input_to_check = "! <3 digits"; } } if (!$this->ReadUserData($real_user, FALSE, TRUE)) { $result = 34; $this->WriteLog("Error: linked user ".$real_user." doesn't exist", FALSE, FALSE, $result, 'User', $real_user); return $result; } } if (1 != $this->GetUserActivated()) { $result = 38; $this->WriteLog("Error: User ".$real_user." is desactivated", FALSE, FALSE, $result, 'User', $real_user); return $result; } $detected_serial_number = ''; if ($this->IsSelfRegistrationEnabled()) { if ('' != $self_register_serial) { if ($this->CheckTokenExists($self_register_serial)) { $detected_serial_number = $self_register_serial; } } } if ('' == $detected_serial_number) { $token_serial_number_length = $this->GetTokenSerialNumberLength(); $token_serial_number_length_array = explode(" ",trim(str_replace(","," ",str_replace(";"," ",$token_serial_number_length)))); foreach($token_serial_number_length_array as $one_serial_number_length) { if (intval($one_serial_number_length) > 0) { $token_otp_list_of_length = $this->GetTokenOtpListOfLength(); $token_otp_list_of_length_array = explode(" ",trim(str_replace(","," ",str_replace(";"," ",$token_otp_list_of_length)))); foreach($token_otp_list_of_length_array as $one_token_otp_length) { if (intval($one_token_otp_length) > 0) { if (strlen($input_to_check) >= (intval($one_serial_number_length) + intval($one_token_otp_length))) { $check_serial = substr($input_to_check, -(intval($one_serial_number_length)+intval($one_token_otp_length)), -intval($one_token_otp_length) ); if ($this->CheckTokenExists($check_serial)) { $detected_serial_number = $check_serial; $input_to_check = str_replace($detected_serial_number, '', $input_to_check); break(2); } } } } } } } if ('' != $detected_serial_number) { $input_sync = str_replace($detected_serial_number, '', $input_sync); } if ($this->IsSelfRegistrationEnabled()) { if (('' != $detected_serial_number) && ($detected_serial_number != $this->GetUserTokenSerialNumber())) { $result = $this->SelfRegisterHardwareToken($real_user,$detected_serial_number, $input_to_check, $input); if (0 == $result) { return $result; } } } if (($this->GetUserAutolockTime() > 0) && ($this->GetUserAutolockTime() < $now_epoch)) { $result = 81; $this->WriteLog("Error: cache too old for user ".$real_user.", account autolocked.", FALSE, FALSE, $result, 'User', $real_user); return $result; } if ('' != $this->GetChapPassword()) { $input_to_check = $this->GetChapPassword(); } elseif ('' != $this->GetMsChapResponse()) { $input_to_check = $this->GetMsChapResponse(); } elseif ('' != $this->GetMsChap2Response()) { $input_to_check = $this->GetMsChap2Response(); } if ($this->GetUserSmsValidity() > $now_epoch) { $ldap_check_passed = FALSE; $ldap_to_check = '!LDAP_FALSE!'; if ((1 == $this->GetUserPrefixPin()) && ($input_to_check != '') && ($this->IsUserRequestLdapPasswordEnabled())) { $code_confirmed = $this->GetUserSmsOtp(); $this->SetLastClearOtpValue($code_confirmed); $code_to_check = substr($input_to_check, -strlen($code_confirmed)); $ldap_to_check = substr($input_to_check, 0, strlen($input_to_check) - strlen($code_to_check)); if ($code_to_check === $code_confirmed) { if (('' != $ldap_to_check) && ($this->CheckUserLdapPassword($this->GetUserSynchronizedDn(), $ldap_to_check))) { $ldap_check_passed = TRUE; if ($this->IsCacheLdapHash()) { $this->SetUserLdapHashCache(bin2hex($this->NtPasswordHashHash($this->NtPasswordHash($ldap_to_check)))); } } elseif ($this->IsCacheLdapHash()) { if (!$this->IsLdapServerReachable()) { if ($this->GetVerboseFlag()) { $this->WriteLog("Debug: *user LDAP hash password checked in the cache", FALSE, FALSE, 8888, 'Debug', ''); } if ($this->GetUserLdapHashCache() === bin2hex($this->NtPasswordHashHash($this->NtPasswordHash($ldap_to_check)))) { $ldap_check_passed = TRUE; if ($this->GetVerboseFlag()) { $this->WriteLog("Debug: *user LDAP hash password verified, based on cached hash password", FALSE, FALSE, 8888, 'Debug', ''); } } else { if ($this->GetVerboseFlag()) { $this->WriteLog("Debug: *user LDAP hash password verification failed", FALSE, FALSE, 8888, 'Debug', ''); } } } else { $ldap_check_passed = FALSE; $ldap_to_check = '!LDAP_FALSE!'; $this->ResetUserLdapHashCache(); $this->WriteLog("Error: User $real_user verification failed, unreachable LDAP/AD server(s)", FALSE, FALSE, 99, 'User'); } } } } else { $code_confirmed = ((1 == $this->GetUserPrefixPin())?$this->GetUserPin():'').$this->GetUserSmsOtp(); $this->SetLastClearOtpValue($code_confirmed); if ('' != $this->GetChapPassword()) { $code_confirmed = $this->CalculateChapPassword($code_confirmed); } elseif ('' != $this->GetMsChapResponse()) { $code_confirmed = $this->CalculateMsChapResponse($code_confirmed); } elseif ('' != $this->GetMsChap2Response()) { $clear_code_confirmed = $code_confirmed; $code_confirmed = $this->CalculateMsChap2Response($real_user, $code_confirmed); if ($this->GetVerboseFlag()) { $this->WriteLog("Debug: *CalculateMsChap2Response($real_user, $clear_code_confirmed) for SMS: $code_confirmed", false, false, 19, 'Debug', ''); } } } if ($ldap_check_passed || ($input_to_check === $code_confirmed)) { $this->SetUserSmsOtp(md5($this->GetEncryptionKey().mt_rand(100000,999999).$this->GetUserTokenSeed().$now_epoch)); $this->SetUserSmsValidity($now_epoch); $this->SetUserErrorCounter(0); $this->SetUserLocked(0); $this->SetUserLastLogin($now_epoch); $this->SetUserTokenLastLogin($now_epoch); $result = 0; if ($cache_result_enabled) { $this->SetUserLastCachedCredential(trim($input.' '.$input_sync)); $this->SetUserLastLoginForCache($now_epoch); } $this->SetUserLastSuccessCredential(trim($input.' '.$input_sync)); if (!$this->WriteUserData()) { $result = 28; $this->WriteLog("Error: Unable to write the changes in the file for the user ".$real_user, FALSE, FALSE, $result, 'User'); } else { $this->WriteLog("Ok: User ".$real_user." successfully logged in with SMS token", FALSE, FALSE, $result, 'User'); } if (0 == $result) { $this->AddExtraRadiusInfo(); } return $result; } } foreach ($this->GetUserScratchPasswordsArray() as $one_password) { if ((1 == $this->GetUserPrefixPin()) && ($input_to_check != '') && ($this->IsUserRequestLdapPasswordEnabled())) { $ldap_check_passed = FALSE; $ldap_to_check = '!LDAP_FALSE!'; $code_confirmed = $one_password; $this->SetLastClearOtpValue($code_confirmed); $code_to_check = substr($input_to_check, -strlen($code_confirmed)); $ldap_to_check = substr($input_to_check, 0, strlen($input_to_check) - strlen($code_to_check)); if ($code_to_check === $code_confirmed) { if (('' != $ldap_to_check) && ($this->CheckUserLdapPassword($this->GetUserSynchronizedDn(), $ldap_to_check))) { $ldap_check_passed = TRUE; if ($this->IsCacheLdapHash()) { $this->SetUserLdapHashCache(bin2hex($this->NtPasswordHashHash($this->NtPasswordHash($ldap_to_check)))); } } elseif ($this->IsCacheLdapHash()) { if (!$this->IsLdapServerReachable()) { if ($this->GetVerboseFlag()) { $this->WriteLog("Debug: *user LDAP password checked in the cache", FALSE, FALSE, 8888, 'Debug', ''); } if ($this->GetUserLdapHashCache() === bin2hex($this->NtPasswordHashHash($this->NtPasswordHash($ldap_to_check)))) { $ldap_check_passed = TRUE; } } else { $ldap_check_passed = FALSE; $ldap_to_check = '!LDAP_FALSE!'; $this->ResetUserLdapHashCache(); if ($this->GetVerboseFlag()) { $this->WriteLog("Debug: *user LDAP password false, hash cache cleared", FALSE, FALSE, 8888, 'Debug', ''); } } } } } else { $code_confirmed = ((1 == $this->GetUserPrefixPin())?$this->GetUserPin():'').$one_password; $this->SetLastClearOtpValue($code_confirmed); if ('' != $this->GetChapPassword()) { $code_confirmed = $this->CalculateChapPassword($code_confirmed); } elseif ('' != $this->GetMsChapResponse()) { $code_confirmed = $this->CalculateMsChapResponse($code_confirmed); } elseif ('' != $this->GetMsChap2Response()) { $clear_code_confirmed = $code_confirmed; $code_confirmed = $this->CalculateMsChap2Response($real_user, $code_confirmed); if ($this->GetVerboseFlag()) { $this->WriteLog("Debug: *CalculateMsChap2Response($real_user, $clear_code_confirmed) for scratch password: $code_confirmed", false, false, 19, 'Debug', ''); } } } if ($ldap_check_passed || ($input_to_check === $code_confirmed)) { $this->SetUserErrorCounter(0); $this->SetUserLocked(0); $this->SetUserLastLogin($now_epoch); $this->SetUserTokenLastLogin($now_epoch); $this->RemoveUserUsedScratchPassword($one_password); $result = 0; if ($cache_result_enabled) { $this->SetUserLastCachedCredential(trim($input.' '.$input_sync)); $this->SetUserLastLoginForCache($now_epoch); } $this->SetUserLastSuccessCredential(trim($input.' '.$input_sync)); if (!$this->WriteUserData()) { $result = 28; $this->WriteLog("Error: Unable to write the changes in the file for the user ".$real_user, FALSE, FALSE, $result, 'User'); } else { $this->WriteLog("Ok: User ".$real_user." successfully logged in with a scratch password", FALSE, FALSE, $result, 'User'); } if (0 == $result) { $this->AddExtraRadiusInfo(); } return $result; } } $code_confirmed = 'sms'; $code_confirmed_upper = 'SMS'; $code_confirmed_camel = 'Sms'; $this->SetLastClearOtpValue($code_confirmed); if ('' != $this->GetChapPassword()) { $code_confirmed = strtolower($this->CalculateChapPassword($code_confirmed)); $code_confirmed_upper = strtoupper($this->CalculateChapPassword($code_confirmed_upper)); $code_confirmed_camel = strtoupper($this->CalculateChapPassword($code_confirmed_camel)); } elseif ('' != $this->GetMsChapResponse()) { $code_confirmed = strtolower($this->CalculateMsChapResponse($code_confirmed)); $code_confirmed_upper = strtoupper($this->CalculateMsChapResponse($code_confirmed_upper)); $code_confirmed_camel = strtoupper($this->CalculateMsChapResponse($code_confirmed_camel)); } elseif ('' != $this->GetMsChap2Response()) { $code_confirmed = strtolower($this->CalculateMsChap2Response($real_user, $code_confirmed)); $code_confirmed_upper = strtoupper($this->CalculateMsChap2Response($real_user, $code_confirmed_upper)); $code_confirmed_camel = strtoupper($this->CalculateMsChap2Response($real_user, $code_confirmed_camel)); } if ((strtolower($input_to_check) === $code_confirmed) || (strtoupper($input_to_check) === $code_confirmed_upper) || (strtoupper($input_to_check) === $code_confirmed_camel)) { return $this->GenerateSmsToken(); } if ($cache_result_enabled) { if ($this->GetVerboseFlag()) { $this->WriteLog("Debug: *code to check: ".str_repeat('x', (strlen($input_to_check) >= 6)?strlen($input_to_check)-6:0).substr($input_to_check, -6), FALSE, FALSE, 8888, 'Debug', ''); } if ($this->CompareUserLastCachedCredential(trim($input.' '.$input_sync))) { if (($this->GetUserLastLoginForCache() + $this->GetDeviceCacheTimeout()) >= $now_epoch) { $this->SetLastClearOtpValue(substr($input_to_check, 0, strpos($input_to_check.' ', ' '))); $result = 0; if ($this->GetVerboseFlag()) { $this->WriteLog("Debug: *User ".$real_user." successfully confirmed for cached access", FALSE, FALSE, 8888, 'Debug', ''); $this->WriteLog("Debug: *checked code for cache access: ".str_repeat('x', (strlen($input_to_check) >= 6)?strlen($input_to_check)-6:0).substr($input_to_check, -6), FALSE, FALSE, 8888, 'Debug', ''); } $this->AddExtraRadiusInfo(); return $result; } elseif (($this->GetUserLastLoginForCache() + $this->GetDeviceCacheTimeout() + 86400) >= $now_epoch) { if ($this->CompareUserLastCachedCredential(trim($input.' '.$input_sync))) { $disable_error_counter = true; } } } } $pin = $this->GetUserPin(); $need_prefix = (1 == $this->GetUserPrefixPin()); $last_event = $this->GetUserTokenLastEvent(); $last_login = $this->GetUserTokenLastLogin(); $digits = $this->GetUserTokenNumberOfDigits(); $error_counter = $this->GetUserErrorCounter(); $time_window = $this->GetMaxTimeWindow(); $event_window = $this->GetMaxEventWindow(); $time_sync_window = $this->GetMaxTimeResyncWindow(); $event_sync_window = $this->GetMaxEventResyncWindow(); $seed = $this->GetUserTokenSeed(); $seed_bin = hex2bin($seed); $private_id = $this->GetUserTokenPrivateId(); $delta_time = $this->GetUserTokenDeltaTime(); $time_interval = $this->GetUserTokenTimeInterval(); $token_algo_suite = $this->GetUserTokenAlgoSuite(); $interval = (0 >= $time_interval)?1:$time_interval; $now_steps = intval($now_epoch / $interval); $step_window = intval($time_window / $interval); $step_sync_window = intval($time_sync_window / $interval); $last_login_step = intval($last_login / $interval); $delta_step = $delta_time / $interval; $prefix_pin = ($need_prefix?$pin:''); $needed_space_pos = (strlen($input_to_check)-$digits-1); if (('' == $input_sync) && ($needed_space_pos >= $digits) && (($needed_space_pos === strrpos($input_to_check, ' ')) || (($needed_space_pos-strlen($prefix_pin)) === strrpos($input_to_check, ' '))) && ($this->IsAutoResync())) { if (($need_prefix) && ($this->IsUserRequestLdapPasswordEnabled())) { $ldap_to_check = substr($input_to_check, 0, - ($digits + 1 + $digits)); if ('' != $ldap_to_check) { if ($this->CheckUserLdapPassword($this->GetUserSynchronizedDn(), $ldap_to_check)) { $input_sync = substr($input_to_check, -$digits); $input_to_check = substr($input_to_check, 0, - ($digits + 1)); } } } elseif ($prefix_pin === substr($input_to_check, 0, strlen($prefix_pin))) { $separator_pos = strrpos($input_to_check, ' '); $input_sync = str_replace($prefix_pin, '', substr($input_to_check, $separator_pos+1)); $input_to_check = substr($input_to_check, 0, $separator_pos); } } if ((1 == $this->GetUserLocked()) && ('' == $input_sync) && (!$resync_enc_pass) && (!$ignore_lock)) { $result = 24; $this->WriteLog("Error: User ".$real_user." locked after ".$this->GetUserErrorCounter()." failed authentications", FALSE, FALSE, $result, 'User'); } elseif(($this->GetUserErrorCounter() >= $this->GetMaxDelayedFailures()) && ('' == $input_sync) && ($now_epoch < ($this->GetUserTokenLastError() + $this->GetMaxDelayedTime())) && (!$ignore_lock)) { $result = 25; $delayed_time = ($this->GetUserTokenLastError() + $this->GetMaxDelayedTime()) - $now_epoch; $this->WriteLog("Error: User ".$real_user." still delayed for ".$delayed_time." seconds after ".$this->GetUserErrorCounter()." failed authentications", FALSE, FALSE, $result, 'User'); } else { $ldap_check_passed = FALSE; $ldap_to_check = '!LDAP_FALSE!'; if (($need_prefix) && ($this->IsUserRequestLdapPasswordEnabled())) { if ($input_to_check != '') { $ldap_to_check = substr($input_to_check, 0, strlen($input_to_check) - $digits); if ('' != $ldap_to_check) { if ($this->CheckUserLdapPassword($this->GetUserSynchronizedDn(), $ldap_to_check)) { $ldap_check_passed = TRUE; if ($this->IsCacheLdapHash()) { $this->SetUserLdapHashCache(bin2hex($this->NtPasswordHashHash($this->NtPasswordHash($ldap_to_check)))); } } elseif ($this->IsCacheLdapHash()) { if (!$this->IsLdapServerReachable()) { if ($this->GetVerboseFlag()) { $this->WriteLog("Debug: *user LDAP password checked in the cache", FALSE, FALSE, 8888, 'Debug', ''); } if ($this->GetUserLdapHashCache() === bin2hex($this->NtPasswordHashHash($this->NtPasswordHash($ldap_to_check)))) { $ldap_check_passed = TRUE; } } else { $ldap_check_passed = FALSE; $ldap_to_check = '!LDAP_FALSE!'; $this->ResetUserLdapHashCache(); if ($this->GetVerboseFlag()) { $this->WriteLog("Debug: *user LDAP password false, hash cache cleared", FALSE, FALSE, 8888, 'Debug', ''); } } } } } if (!$ldap_check_passed) { $input_to_check = "LDAP_FAILED"; $result = 99; } } switch (strtolower($this->GetUserAlgorithm())) { case 'motp': if (('' == $input_sync) && (!$resync_enc_pass)) { $max_steps = 2 * $step_window; } else { $max_steps = 2 * $step_sync_window; } $check_step = 1; do { $additional_step = (1 - (2 * ($check_step % 2))) * intval($check_step/2); $pure_calculated_token = $this->ComputeMotp($seed.$pin, $now_steps+$additional_step+$delta_step, $digits); $calculated_token = $pure_calculated_token; if (($need_prefix) && ($input_to_check != '') && ($this->IsUserRequestLdapPasswordEnabled())) { $code_confirmed_without_pin = $calculated_token; $code_confirmed = $calculated_token; $input_to_check = substr($input_to_check, -strlen($code_confirmed)); $this->SetLastClearOtpValue($code_confirmed); } else { if ($need_prefix) { $calculated_token = $pin.$calculated_token; } $code_confirmed_without_pin = $pure_calculated_token; $code_confirmed = $calculated_token; $this->SetLastClearOtpValue($code_confirmed); if ('' != $this->GetChapPassword()) { $code_confirmed_without_pin = strtolower($this->CalculateChapPassword($code_confirmed_without_pin)); $code_confirmed = strtolower($this->CalculateChapPassword($code_confirmed)); } elseif ('' != $this->GetMsChapResponse()) { $code_confirmed_without_pin = strtolower($this->CalculateMsChapResponse($code_confirmed_without_pin)); $code_confirmed = strtolower($this->CalculateMsChapResponse($code_confirmed)); } elseif ('' != $this->GetMsChap2Response()) { $clear_code_confirmed = $code_confirmed; $code_confirmed_without_pin = strtolower($this->CalculateMsChap2Response($real_user, $code_confirmed_without_pin)); $code_confirmed = strtolower($this->CalculateMsChap2Response($real_user, $code_confirmed)); if ($this->GetVerboseFlag()) { $this->WriteLog("Debug: *CalculateMsChap2Response($real_user, $clear_code_confirmed) for motp: $code_confirmed", false, false, 19, 'Debug', ''); } } } if (('' == $input_sync) && (!$resync_enc_pass)) { if (($input_to_check === $code_confirmed) || ($input_to_check === $code_confirmed_without_pin)) { if ($input_to_check === $code_confirmed_without_pin) { $code_confirmed = $code_confirmed_without_pin; } if (($now_steps+$additional_step+$delta_step) > $last_login_step) { $this->SetUserLastLogin($now_epoch); $this->SetUserTokenLastLogin(($now_steps+$additional_step+$delta_step) * $interval); $this->SetUserTokenDeltaTime(($additional_step+$delta_step) * $interval); $this->SetUserErrorCounter(0); $result = 0; $this->WriteLog("Ok: User ".$real_user." successfully logged in with mOTP token", FALSE, FALSE, $result, 'User'); } else { $result = 26; if ($this->CompareUserLastSuccessCredential(trim($input.' '.$input_sync))) { $disable_error_counter = true; } if (!$disable_error_counter) { $this->SetUserErrorCounter($error_counter+1); } $this->SetUserTokenLastError($now_epoch); $this->WriteLog("Error: token of user ".$real_user." already used", FALSE, FALSE, $result, 'User'); } } else { $check_step++; } } elseif (($input_to_check === $code_confirmed) || ($input_to_check === $code_confirmed_without_pin)) { $pure_sync_calculated_token = $this->ComputeMotp($seed.$pin, $now_steps+$additional_step+$delta_step+1, $digits); $sync_calculated_token = $pure_sync_calculated_token; if (($need_prefix) && ($input_sync != '') && ($this->IsUserRequestLdapPasswordEnabled())) { $input_sync = substr($input_sync, -strlen($code_confirmed)); } elseif ($need_prefix) { $sync_calculated_token = $pin.$sync_calculated_token; } if ((($input_sync === $sync_calculated_token) || ($input_sync === $pure_sync_calculated_token)) && (($now_steps+$additional_step+$delta_step+1) > $last_login_step)) { $this->SetUserLastLogin($now_epoch); $this->SetUserTokenLastLogin(($now_steps+$additional_step+$delta_step+1) * $interval); $this->SetUserTokenDeltaTime(($additional_step+$delta_step+1) * $interval); $this->SetUserErrorCounter(0); $this->SetUserLocked(0); $result = 14; $this->WriteLog("Info: token for user ".$real_user." is now resynchronized with a delta of ".(($additional_step+$delta_step+1) * $interval). " seconds", FALSE, FALSE, $result, 'User'); $result = 0; } else { $result = 27; $this->WriteLog("Error: resync for user ".$real_user." has failed", FALSE, FALSE, $result, 'User'); } } else { $check_step++; if ($display_status) { MultiotpShowStatus($check_step, $max_steps); } } } while (($check_step < $max_steps) && (90 <= $result)); if ($display_status) { echo "\r\n"; } if (90 <= $result) { if ($this->CompareUserLastFailedCredential(trim($input.' '.$input_sync))) { $disable_error_counter = true; } if (!$disable_error_counter) { $this->SetUserErrorCounter($error_counter+1); } $this->SetUserTokenLastError($now_epoch); } break; case 'hotp'; if (('' == $input_sync)&& (!$resync_enc_pass)) { $max_steps = 2 * $event_window; } else { $max_steps = 2 * $event_sync_window; } $check_step = 1; do { $additional_step = (1 - (2 * ($check_step % 2))) * intval($check_step/2); $pure_calculated_token = $this->GenerateOathHotp($seed_bin,$last_event+$additional_step,$digits,$token_algo_suite); $calculated_token = $pure_calculated_token; if (($need_prefix) && ($input_to_check != '') && ($this->IsUserRequestLdapPasswordEnabled())) { $code_confirmed_without_pin = $calculated_token; $code_confirmed = $calculated_token; $input_to_check = substr($input_to_check, -strlen($code_confirmed)); $this->SetLastClearOtpValue($code_confirmed); } else { if ($need_prefix) { $calculated_token = $pin.$calculated_token; } $code_confirmed_without_pin = $pure_calculated_token; $code_confirmed = $calculated_token; $this->SetLastClearOtpValue($code_confirmed); if ('' != $this->GetChapPassword()) { $code_confirmed_without_pin = strtolower($this->CalculateChapPassword($code_confirmed_without_pin)); $code_confirmed = strtolower($this->CalculateChapPassword($code_confirmed)); } elseif ('' != $this->GetMsChapResponse()) { $code_confirmed_without_pin = strtolower($this->CalculateMsChapResponse($code_confirmed_without_pin)); $code_confirmed = strtolower($this->CalculateMsChapResponse($code_confirmed)); } elseif ('' != $this->GetMsChap2Response()) { $clear_code_confirmed = $code_confirmed; $code_confirmed_without_pin = strtolower($this->CalculateMsChap2Response($real_user, $code_confirmed_without_pin)); $code_confirmed = strtolower($this->CalculateMsChap2Response($real_user, $code_confirmed)); if ($this->GetVerboseFlag()) { $this->WriteLog("Debug: *CalculateMsChap2Response($real_user, $clear_code_confirmed) for hotp: $code_confirmed", false, false, 19, 'Debug', ''); } } } if (('' == $input_sync) && (!$resync_enc_pass)) { if ($input_to_check === $code_confirmed) { if ($additional_step >= 1) { $this->SetUserLastLogin($now_epoch); $this->SetUserTokenLastLogin($now_epoch); $this->SetUserTokenLastEvent($last_event+$additional_step); $this->SetUserErrorCounter(0); $result = 0; $this->WriteLog("OK: User ".$real_user." successfully logged in with HOTP token", FALSE, FALSE, $result, 'User'); } else { $result = 26; if ($this->CompareUserLastSuccessCredential(trim($input.' '.$input_sync))) { $disable_error_counter = true; } if (!$disable_error_counter) { $this->SetUserErrorCounter($error_counter+1); } $this->SetUserTokenLastError($now_epoch); $this->WriteLog("Error: token of user ".$real_user." already used", FALSE, FALSE, $result, 'User'); } } else { $check_step++; } } elseif (($input_to_check === $code_confirmed) || ($input_to_check === $code_confirmed_without_pin)) { $pure_sync_calculated_token = $this->GenerateOathHotp($seed_bin, $last_event+$additional_step+1,$digits,$token_algo_suite); $sync_calculated_token = $pure_sync_calculated_token; if (($need_prefix) && ($input_sync != '') && ($this->IsUserRequestLdapPasswordEnabled())) { $input_sync = substr($input_sync, -strlen($code_confirmed)); } elseif ($need_prefix) { $sync_calculated_token = $pin.$sync_calculated_token; } if ((($input_sync === $sync_calculated_token) || ($input_sync === $pure_sync_calculated_token)) && ($additional_step >= 1)) { $this->SetUserLastLogin($now_epoch); $this->SetUserTokenLastLogin($now_epoch); $this->SetUserTokenLastEvent($last_event+$additional_step+1); $this->SetUserErrorCounter(0); $this->SetUserLocked(0); $result = 14; $this->WriteLog("Info: token for user ".$real_user." is now resynchronized with the last event ".($last_event+$additional_step+1), FALSE, FALSE, $result, 'User'); if ($input_to_check === $code_confirmed) { $result = 0; } } else { $result = 27; $this->WriteLog("Error: resync for user ".$real_user." has failed", FALSE, FALSE, $result, 'User'); } } else { $check_step++; if ($display_status) { MultiotpShowStatus($check_step, $max_steps); } } } while (($check_step < $max_steps) && ((90 <= $result))); if ($display_status) { echo "\r\n"; } if (90 <= $result) { if ($this->CompareUserLastFailedCredential(trim($input.' '.$input_sync))) { $disable_error_counter = true; } if (!$disable_error_counter) { $this->SetUserErrorCounter($error_counter+1); } $this->SetUserTokenLastError($now_epoch); } break; case 'yubicootp'; $yubikey_class = new MultiotpYubikey(); $bad_precheck = FALSE; if (($need_prefix) && ($input_to_check != '') && ($this->IsUserRequestLdapPasswordEnabled())) { if (!$ldap_check_passed) { $input_to_check.= '_BAD_LDAP_CHECK'; $bad_precheck = TRUE; } $this->SetLastClearOtpValue($input_to_check); } else { if ($need_prefix) { if ($pin != substr($input_to_check, 0, strlen($pin))) { $this->SetLastClearOtpValue($input_to_check); $input_to_check.= '_BAD_PREFIX'; $bad_precheck = TRUE; } } } if (!$bad_precheck) { $result = $yubikey_class->CheckYubicoOtp(substr($input_to_check, -32), $seed, $last_event, $private_id); } if (0 == $result) { $calculated_token = $input_to_check; $this->SetUserLastLogin($now_epoch); $this->SetUserTokenLastLogin($now_epoch); $this->SetUserTokenLastEvent($yubikey_class->GetYubicoOtpLastCount()); $this->SetUserErrorCounter(0); $result = 0; $this->WriteLog("OK: User ".$real_user." successfully logged in with YubicoOTP token", FALSE, FALSE, $result, 'User'); } elseif (26 == $result) { $result = 26; if ($this->CompareUserLastSuccessCredential(trim($input.' '.$input_sync))) { $disable_error_counter = true; } if (!$disable_error_counter) { $this->SetUserErrorCounter($error_counter+1); } $this->SetUserTokenLastError($now_epoch); $this->WriteLog("Error: token of user ".$real_user." already used", FALSE, FALSE, $result, 'User'); } else { if ($this->CompareUserLastFailedCredential(trim($input.' '.$input_sync))) { $disable_error_counter = true; } if (!$disable_error_counter) { $this->SetUserErrorCounter($error_counter+1); } $this->SetUserTokenLastError($now_epoch); } break; case 'totp'; if (('' == $input_sync) && (!$resync_enc_pass)) { $max_steps = 2 * $step_window; } else { $max_steps = 2 * $step_sync_window; } $check_step = 1; do { $additional_step = (1 - (2 * ($check_step % 2))) * intval($check_step/2); $pure_calculated_token = $this->GenerateOathHotp($seed_bin,$now_steps+$additional_step+$delta_step,$digits,$token_algo_suite); $calculated_token = $pure_calculated_token; if (($need_prefix) && ($input_to_check != '') && ($this->IsUserRequestLdapPasswordEnabled())) { $code_confirmed_without_pin = $calculated_token; $code_confirmed = $calculated_token; $input_to_check = substr($input_to_check, -strlen($code_confirmed)); $this->SetLastClearOtpValue($code_confirmed); } else { if ($need_prefix) { $calculated_token = $pin.$calculated_token; } $code_confirmed_without_pin = $pure_calculated_token; $code_confirmed = $calculated_token; $this->SetLastClearOtpValue($code_confirmed); if ('' != $this->GetChapPassword()) { $code_confirmed_without_pin = strtolower($this->CalculateChapPassword($code_confirmed_without_pin)); $code_confirmed = strtolower($this->CalculateChapPassword($code_confirmed)); } elseif ('' != $this->GetMsChapResponse()) { $code_confirmed_without_pin = strtolower($this->CalculateMsChapResponse($code_confirmed_without_pin)); $code_confirmed = strtolower($this->CalculateMsChapResponse($code_confirmed)); } elseif ('' != $this->GetMsChap2Response()) { $clear_code_confirmed = $code_confirmed; $code_confirmed_without_pin = strtolower($this->CalculateMsChap2Response($real_user, $code_confirmed_without_pin)); $code_confirmed = strtolower($this->CalculateMsChap2Response($real_user, $code_confirmed)); if ($this->GetVerboseFlag()) { $this->WriteLog("Debug: *CalculateMsChap2Response($real_user, $clear_code_confirmed) for totp: $code_confirmed", false, false, 19, 'Debug', ''); } } } if (('' == $input_sync) && (!$resync_enc_pass)) { if ($input_to_check === $code_confirmed) { if (($now_steps+$additional_step+$delta_step) > $last_login_step) { $this->SetUserLastLogin($now_epoch); $this->SetUserTokenLastLogin(($now_steps+$additional_step+$delta_step) * $interval); $this->SetUserTokenDeltaTime(($additional_step+$delta_step) * $interval); $this->SetUserErrorCounter(0); $result = 0; $this->WriteLog("OK: User ".$real_user." successfully logged in with TOTP token", FALSE, FALSE, $result, 'User'); } else { $result = 26; if ($this->CompareUserLastSuccessCredential(trim($input.' '.$input_sync))) { $disable_error_counter = true; } if (!$disable_error_counter) { $this->SetUserErrorCounter($error_counter+1); } $this->SetUserTokenLastError($now_epoch); $this->WriteLog("Error: token of user ".$real_user." already used", FALSE, FALSE, $result, 'User'); } } else { $check_step++; } } elseif (($input_to_check === $code_confirmed) || ($input_to_check === $code_confirmed_without_pin)) { $pure_sync_calculated_token = $this->GenerateOathHotp($seed_bin,$now_steps+$additional_step+$delta_step+1,$digits,$token_algo_suite); $sync_calculated_token = $pure_sync_calculated_token; if (($need_prefix) && ($input_sync != '') && ($this->IsUserRequestLdapPasswordEnabled())) { $input_sync = substr($input_sync, -strlen($code_confirmed)); } elseif ($need_prefix) { $sync_calculated_token = $pin.$sync_calculated_token; } if ((($input_sync === $sync_calculated_token) || ($input_sync === $pure_sync_calculated_token)) && (($now_steps+$additional_step+$delta_step) > $last_login_step)) { $this->SetUserLastLogin($now_epoch); $this->SetUserTokenLastLogin(($now_steps+$additional_step+$delta_step+1) * $interval); $this->SetUserTokenDeltaTime(($additional_step+$delta_step+1) * $interval); $this->SetUserErrorCounter(0); $this->SetUserLocked(0); $result = 14; $this->WriteLog("Info: token for user ".$real_user." is now resynchronized with a delta of ".(($additional_step+$delta_step+1) * $interval). " seconds", FALSE, FALSE, $result, 'User'); if ($input_to_check === $code_confirmed) { $result = 0; } } else { $result = 27; $this->WriteLog("Error: resync for user ".$real_user." has failed", FALSE, FALSE, $result, 'User'); } } else { $check_step++; if ($display_status) { MultiotpShowStatus($check_step, $max_steps); } } } while (($check_step < $max_steps) && (90 <= $result)); if ($display_status) { echo "\r\n"; } if (90 <= $result) { if ($this->CompareUserLastFailedCredential(trim($input.' '.$input_sync))) { $disable_error_counter = true; } if (!$disable_error_counter) { $this->SetUserErrorCounter($error_counter+1); } $this->SetUserTokenLastError($now_epoch); } break; default: $result = 23; $this->WriteLog("Error: ".$this->GetUserAlgorithm()." algorithm is unknown", FALSE, FALSE, $result, 'User'); } if (90 <= $result) { if ($cache_result_enabled && ((strlen($input_to_check) != strlen($calculated_token)))) { $disable_error_counter = true; } if (!$disable_error_counter) { $this->SetUserErrorCounter($error_counter+1); } $this->SetUserTokenLastError($now_epoch); } } if (0 == $result) { $this->SetUserLocked(0); } if (90 <= $result) { $this->WriteLog("Error: authentication failed for user ".$real_user, FALSE, FALSE, $result, 'User'); if ($this->GetVerboseFlag()) { if ('' != $this->GetChapPassword()) { $this->WriteLog("Info: *(authentication typed by the user is CHAP encrypted)", FALSE, FALSE, $result, 'User'); } elseif ('' != $this->GetMsChapResponse()) { $this->WriteLog("Info: *(authentication typed by the user is MS-CHAP encrypted)", FALSE, FALSE, $result, 'User'); } elseif ('' != $this->GetMsChap2Response()) { $this->WriteLog("Info: *(authentication typed by the user is MS-CHAP V2 encrypted)", FALSE, FALSE, $result, 'User'); } elseif ((strlen($input_to_check) === strlen($calculated_token))) { $this->WriteLog("Info: *(authentication typed by the user: ".$input_to_check.")", FALSE, FALSE, $result, 'User'); } else { $result = 98; $this->WriteLog("*(authentication typed by the user is ".strlen($input_to_check)." chars long instead of ".strlen($calculated_token)." chars)", FALSE, FALSE, $result, 'User'); } } elseif (('' == $this->GetChapPassword()) && ('' == $this->GetMsChapResponse()) && ('' == $this->GetMsChap2Response()) && ((strlen($input_to_check) != strlen($calculated_token))) ) { $result = 98; $this->WriteLog("Error: authentication typed by the user is ".strlen($input_to_check)." chars long instead of ".strlen($calculated_token)." chars", FALSE, FALSE, $result, 'User'); } } if ($this->GetUserErrorCounter() >= $this->GetMaxBlockFailures()) { $this->SetUserLocked(1); } if (0 == $result) { if ($cache_result_enabled) { if ($this->GetVerboseFlag()) { $this->WriteLog("Debug: *checked code for future cache access: ".str_repeat('x', (strlen($input_to_check) >= 6)?strlen($input_to_check)-6:0).substr($input_to_check, -6), FALSE, FALSE, 8888, 'Debug', ''); } $this->SetUserLastCachedCredential(trim($input.' '.$input_sync)); $this->SetUserLastLoginForCache($now_epoch); } $this->SetUserLastSuccessCredential(trim($input.' '.$input_sync)); } else { $this->SetUserLastFailedCredential(trim($input.' '.$input_sync)); } if (!$this->WriteUserData()) { $result = 28; $this->WriteLog("Error: Unable to write the changes in the file for the user ".$real_user, FALSE, FALSE, $result, 'User'); } } if (0 == $result) { $this->AddExtraRadiusInfo(); } return $result; } function SelfRegisterHardwareToken( $user, $serial, $input, $original_input = '' ) { $result = 99; $ldap_check_passed = FALSE; $calculated_token = ''; if ('' == $original_input) { $original_input = $input; } $serial_number = strtolower($serial); if ($this->ReadUserData($user)) { $pin = $this->GetUserPin(); $need_prefix = (1 == $this->GetUserPrefixPin()); if ($this->ReadTokenData($serial_number)) { $attributed_users = trim($this->GetTokenAttributedUsers()); if ('' != trim($attributed_users)) { if (FALSE === strpos(','.$attributed_users.',', ','.$user.',')) { $result = 37; $this->WriteLog("Error: Token ".$this->GetToken()." already attributed", FALSE, FALSE, $result, 'Token', $user); } } else { $algorithm = $this->GetTokenAlgorithm(); $token_algo_suite = $this->GetTokenAlgoSuite(); $seed = $this->GetTokenSeed(); $seed_bin = hex2bin($seed); $private_id = $this->GetUserTokenPrivateId(); $digits = $this->GetTokenNumberOfDigits(); $time_interval = $this->GetTokenTimeInterval(); $last_event = $this->GetTokenLastEvent(); $delta_time = $this->GetTokenDeltaTime(); $last_login = $this->GetTokenLastLogin(); $error_counter = $this->GetTokenErrorCounter(); $now_epoch = time(); $input_to_check = $input; $interval = (0 >= $time_interval)?1:$time_interval; if (strlen($input_to_check) < 3) { $input_to_check = "! <3 digits"; } $now_steps = intval($now_epoch / $interval); $time_window = $this->GetMaxTimeWindow(); $step_window = intval($time_window / $interval); $event_window = $this->GetMaxEventWindow(); $time_sync_window = $this->GetMaxTimeResyncWindow(); $step_sync_window = intval($time_sync_window / $interval); $event_sync_window = $this->GetMaxEventResyncWindow(); $last_login_step = intval($last_login / $interval); $delta_step = $delta_time / $interval; $ldap_check_passed = FALSE; $ldap_to_check = '!LDAP_FALSE!'; if (($need_prefix) && ($this->IsUserRequestLdapPasswordEnabled())) { if ($input_to_check != '') { $ldap_to_check = substr($input_to_check, 0, strlen($input_to_check) - $digits); if ('' != $ldap_to_check) { if ($this->CheckUserLdapPassword($this->GetUserSynchronizedDn(), $ldap_to_check)) { $ldap_check_passed = TRUE; if ($this->IsCacheLdapHash()) { $this->SetUserLdapHashCache(bin2hex($this->NtPasswordHashHash($this->NtPasswordHash($ldap_to_check)))); } } elseif ($this->IsCacheLdapHash()) { if (!$this->IsLdapServerReachable()) { if ($this->GetVerboseFlag()) { $this->WriteLog("Debug: *user LDAP password checked in the cache", FALSE, FALSE, 8888, 'Debug', ''); } if ($this->GetUserLdapHashCache() === bin2hex($this->NtPasswordHashHash($this->NtPasswordHash($ldap_to_check)))) { $ldap_check_passed = TRUE; } } else { $ldap_check_passed = FALSE; $ldap_to_check = '!LDAP_FALSE!'; $this->ResetUserLdapHashCache(); if ($this->GetVerboseFlag()) { $this->WriteLog("Debug: *user LDAP password false, hash cache cleared", FALSE, FALSE, 8888, 'Debug', ''); } } } } } if (!$ldap_check_passed) { $this->WriteLog("Error: authentication failed for user ".$this->GetUser(), FALSE, FALSE, $result, 'User'); $input_to_check = "LDAP_FAILED"; $result = 99; } } switch (strtolower($algorithm)) { case 'motp': $max_steps = 2 * $step_sync_window; $check_step = 1; do { $additional_step = (1 - (2 * ($check_step % 2))) * intval($check_step/2); $pure_calculated_token = $this->ComputeMotp($seed.$pin, $now_steps+$additional_step+$delta_step, $digits); $calculated_token = $pure_calculated_token; if (($need_prefix) && ($input_to_check != '') && ($this->IsUserRequestLdapPasswordEnabled())) { $code_confirmed_without_pin = $calculated_token; $code_confirmed = $calculated_token; $input_to_check = substr($input_to_check, -strlen($code_confirmed)); if (!$ldap_check_passed) { $input_to_check.= '_BAD_LDAP_CHECK'; } $this->SetLastClearOtpValue($original_input); } else { if ($need_prefix) { $calculated_token = $pin.$calculated_token; } $code_confirmed_without_pin = $pure_calculated_token; $code_confirmed = $calculated_token; $this->SetLastClearOtpValue($original_input); if ('' != $this->GetChapPassword()) { $code_confirmed_without_pin = strtolower($this->CalculateChapPassword($code_confirmed_without_pin)); $code_confirmed = strtolower($this->CalculateChapPassword($code_confirmed)); } elseif ('' != $this->GetMsChapResponse()) { $code_confirmed_without_pin = strtolower($this->CalculateMsChapResponse($code_confirmed_without_pin)); $code_confirmed = strtolower($this->CalculateMsChapResponse($code_confirmed)); } elseif ('' != $this->GetMsChap2Response()) { $code_confirmed_without_pin = strtolower($this->CalculateMsChap2Response($user, $code_confirmed_without_pin)); $code_confirmed = strtolower($this->CalculateMsChap2Response($user, $code_confirmed)); } } if (($input_to_check === $code_confirmed) || ($input_to_check === $code_confirmed_without_pin)) { if (($now_steps+$additional_step+$delta_step) > $last_login_step) { $this->SetTokenLastLogin(($now_steps+$additional_step+$delta_step) * $interval); $this->SetTokenDeltaTime(($additional_step+$delta_step) * $interval); $this->SetTokenErrorCounter(0); $result = 0; } else { $result = 26; } } else { $check_step++; } } while (($check_step < $max_steps) && (90 <= $result)); break; case 'hotp'; $max_steps = $event_sync_window; $check_step = 1; do { $pure_calculated_token = $this->GenerateOathHotp($seed_bin,$last_event+$check_step,$digits,$token_algo_suite); $calculated_token = $pure_calculated_token; if (($need_prefix) && ($input_to_check != '') && ($this->IsUserRequestLdapPasswordEnabled())) { $code_confirmed_without_pin = $calculated_token; $code_confirmed = $calculated_token; $input_to_check = substr($input_to_check, -strlen($code_confirmed)); if (!$ldap_check_passed) { $input_to_check.= '_BAD_LDAP_CHECK'; } $this->SetLastClearOtpValue($original_input); } else { if ($need_prefix) { $calculated_token = $pin.$calculated_token; } $code_confirmed = $calculated_token; $this->SetLastClearOtpValue($original_input); if ('' != $this->GetChapPassword()) { $code_confirmed = strtolower($this->CalculateChapPassword($code_confirmed)); } elseif ('' != $this->GetMsChapResponse()) { $code_confirmed = strtolower($this->CalculateMsChapResponse($code_confirmed)); } elseif ('' != $this->GetMsChap2Response()) { $code_confirmed = strtolower($this->CalculateMsChap2Response($user, $code_confirmed)); } } if ($input_to_check === $code_confirmed) { $this->SetTokenLastLogin($now_epoch); $this->SetTokenLastEvent($last_event+$check_step); $this->SetTokenErrorCounter(0); $result = 0; } else { $check_step++; } } while (($check_step < $max_steps) && (90 <= $result)); break; case 'yubicootp': $yubikey_class = new MultiotpYubikey(); $bad_precheck = FALSE; if (($need_prefix) && ($input_to_check != '') && ($this->IsUserRequestLdapPasswordEnabled())) { if (!$ldap_check_passed) { $input_to_check.= '_BAD_LDAP_CHECK'; $bad_precheck = TRUE; } $this->SetLastClearOtpValue($original_input); } else { if ($need_prefix) { if ($pin != substr($input_to_check, 0, strlen($pin))) { $this->SetLastClearOtpValue($original_input); $input_to_check.= '_BAD_PREFIX'; $bad_precheck = TRUE; } } } if (!$bad_precheck) { $result = $yubikey_class->CheckYubicoOtp(substr($input_to_check, -32), $seed, $last_event, $private_id); } if (0 == $result) { $calculated_token = $input_to_check; $this->SetTokenLastLogin($now_epoch); $this->SetTokenLastEvent($yubikey_class->GetYubicoOtpLastCount()); $this->SetTokenErrorCounter(0); $result = 0; } break; case 'totp'; $max_steps = 2 * $step_sync_window; $check_step = 1; do { $additional_step = (1 - (2 * ($check_step % 2))) * intval($check_step/2); $pure_calculated_token = $this->GenerateOathHotp($seed_bin,$now_steps+$additional_step+$delta_step,$digits,$token_algo_suite); $calculated_token = $pure_calculated_token; if (($need_prefix) && ($input_to_check != '') && ($this->IsUserRequestLdapPasswordEnabled())) { $code_confirmed_without_pin = $calculated_token; $code_confirmed = $calculated_token; $input_to_check = substr($input_to_check, -strlen($code_confirmed)); if (!$ldap_check_passed) { $input_to_check.= '_BAD_LDAP_CHECK'; } $this->SetLastClearOtpValue($original_input); } else { if ($need_prefix) { $calculated_token = $pin.$calculated_token; } $code_confirmed = $calculated_token; $this->SetLastClearOtpValue($original_input); if ('' != $this->GetChapPassword()) { $code_confirmed = strtolower($this->CalculateChapPassword($code_confirmed)); } elseif ('' != $this->GetMsChapResponse()) { $code_confirmed = strtolower($this->CalculateMsChapResponse($code_confirmed)); } elseif ('' != $this->GetMsChap2Response()) { $code_confirmed = strtolower($this->CalculateMsChap2Response($user, $code_confirmed)); } } if ($input_to_check === $code_confirmed) { if (($now_steps+$additional_step+$delta_step) > $last_login_step) { $this->SetTokenLastLogin(($now_steps+$additional_step+$delta_step) * $interval); $this->SetTokenDeltaTime(($additional_step+$delta_step) * $interval); $this->SetTokenErrorCounter(0); $result = 0; } else { $result = 26; } } else { $check_step++; } } while (($check_step < $max_steps) && (90 <= $result)); break; default: if ($this->GetVerboseFlag()) { $this->WriteLog("Debug: *Invalid algorithm (SelfRegisterHardwareToken): $algorithm", FALSE, FALSE, 8888, 'Debug', ''); } $result = 23; } if (90 <= $result) { if ($this->GetVerboseFlag()) { if ((strlen($input_to_check) === strlen($calculated_token))) { $this->WriteLog("Info: *(authentication typed by the user: ".$input_to_check.")", FALSE, FALSE, $result, 'User', $user); } else { $result = 98; $this->WriteLog("Info: *(authentication typed by the user is ".strlen($input_to_check)." chars long instead of ".strlen($calculated_token)." chars", FALSE, FALSE, $result, 'User', $user); } } } if (0 == $result) { $this->AddTokenAttributedUsers($user); if (!$this->WriteTokenData()) { $result = 28; $this->WriteLog("Error: Unable to write the changes in the file for the token ".$this->GetToken(), FALSE, FALSE, $result, 'Token', $user); } else { $this->SetUserTokenSerialNumber($serial_number); $this->SetUserAlgorithm($this->GetTokenAlgorithm()); $this->SetUserTokenAlgoSuite($this->GetTokenAlgoSuite()); $this->SetUserTokenSeed($this->GetTokenSeed()); $this->SetUserTokenPrivateId($this->GetTokenPrivateId()); $this->SetUserTokenNumberOfDigits($this->GetTokenNumberOfDigits()); $this->SetUserTokenTimeInterval($this->GetTokenTimeInterval()); $this->SetUserTokenLastEvent($this->GetTokenLastEvent()); $this->SetUserTokenDeltaTime($this->GetTokenDeltaTime()); $this->SetUserTokenLastLogin($this->GetTokenLastLogin()); $this->SetUserErrorCounter(0); if (!$this->WriteUserData()) { $result = 28; $this->WriteLog("Error: Unable to write the changes in the file for the user ".$this->GetUser(), FALSE, FALSE, $result, 'System', ''); } else { $this->WriteLog("OK: token ".$this->GetToken()." successfully attributed to user ".$this->GetUser(), FALSE, FALSE, 19, 'User'); } } } } } else { $result = 29; $this->WriteLog("Error: Token ".$this->GetToken()." does not exist", FALSE, FALSE, $result, 'Token'); } } else { $result = 29; $this->WriteLog("Error: User ".$this->GetUser()." does not exist", FALSE, FALSE, $result, 'User'); } return $result; } function ImportTokensFile( $file, $original_name = '', $cipher_password = '', $key_mac = "" ) { if (!file_exists($file)) { $result = FALSE; } else { $data1000 = @file_get_contents($file, FALSE, NULL, 0, 1000); $file_name = ('' != $original_name)?$original_name:$file; if (FALSE !== strpos(strtolower($data1000), strtolower('"urn:ietf:params:xml:ns:keyprov:pskc"'))) { $result = $this->ImportTokensFromPskc($file, $cipher_password, $key_mac); } elseif (FALSE !== strpos(strtolower($data1000), strtolower('LOGGING START'))) { $result = $this->ImportYubikeyTraditional($file); } elseif ((FALSE !== strpos(strtolower($data1000), strtolower('AUTHENEXDB'))) && ('.sql' == strtolower(substr($file_name, -4)))) { $result = $this->ImportTokensFromAuthenexSql($file); } elseif ((FALSE !== strpos(strtolower($data1000), strtolower('SafeWord Authenticator Records'))) && ('.dat' == strtolower(substr($file_name, -4)))) { $result = $this->ImportTokensFromAlpineDat($file); } elseif (FALSE !== strpos(strtolower($data1000), strtolower('<ProductName>eTPass'))) { $result = $this->ImportTokensFromAlpineXml($file); } elseif ('.xml' == strtolower(substr($file_name, -4))) { $result = $this->ImportTokensFromXml($file); } else { $result = $this->ImportTokensFromCsv($file); } } return $result; } function DecodeCipherValue( $encrypted_tree, $cipher_array, $integer_value = FALSE ) { $passphrase = $cipher_array['Password']; $Secret = ''; $cipher_aes = new Crypt_AES(); $encryption_method_tag = (isset($encrypted_tree->{$cipher_array['xenc_ns'].'encryptionmethod'})?$cipher_array['xenc_ns']:'').'encryptionmethod'; $encryption_method_algorithm_url = isset($encrypted_tree->{$encryption_method_tag}[0]->tagAttrs["algorithm"])?($encrypted_tree->{$encryption_method_tag}[0]->tagAttrs["algorithm"]):''; $encryption_method_algorithm = (FALSE !== strpos($encryption_method_algorithm_url,'#aes128-cbc'))?'aes128':((FALSE !== strpos($encryption_method_algorithm_url,'#kw-aes128'))?'kw-ases128':''); $cipher_data_tag = (isset($encrypted_tree->{$cipher_array['xenc_ns'].'cipherdata'})?$cipher_array['xenc_ns']:'').'cipherdata'; $cipher_value_tag = (isset($encrypted_tree->{$cipher_data_tag}[0]->{$cipher_array['xenc_ns'].'ciphervalue'})?$cipher_array['xenc_ns']:'').'ciphervalue'; $cipher_value = isset($encrypted_tree->{$cipher_data_tag}[0]->{$cipher_value_tag}[0]->tagData)?($encrypted_tree->{$cipher_data_tag}[0]->{$cipher_value_tag}[0]->tagData):''; if ('' != $passphrase) { for ($tries = 0; $tries < 3; $tries++) { if ('' == $cipher_array['KeyDerivationMethodAlgorithm']) { $cipher_aes->setKey($passphrase); $Secret = (substr($cipher_aes->decrypt(base64_decode($cipher_value)),16)); if ('' == $Secret) { $cipher_aes->setKey(hex2bin(preg_replace("/[^A-Fa-f0-9]/", '', $passphrase))); $Secret = (substr($cipher_aes->decrypt(base64_decode($cipher_value)),16)); } } elseif ('pkcs5' == $cipher_array['KeyDerivationMethodAlgorithm']) { $cipher_aes->setPassword($passphrase, 'pbkdf2', 'sha1', $cipher_array['Salt'], $cipher_array['IterationCount'], $cipher_array['KeyLength']); $Secret = (substr($cipher_aes->decrypt(base64_decode($cipher_value)),16)); } if ('' != $Secret) { break; } elseif (0 == $tries) { $passphrase = trim($passphrase); } elseif (1 == $tries) { if ((0 === strpos($passphrase, '0x')) && (0 == (strlen($passphrase) % 2))) { $passphrase = hex2bin(substr($passphrase, 2)); } } } } if (('' != $Secret) && ($integer_value)) { $value = 0; for( $i = 0; $i < strlen($Secret); $i++ ) { $value = ($value << 8) | ord($Secret[$i]); } $Secret = $value; } return $Secret; } function ImportTokensFromPskc( $pskc_file, $cipher_password = '', $keymac = '' ) { $this->ResetLastImportedTokensArray(); $result = TRUE; if (!file_exists($pskc_file)) { $this->WriteLog("Error: Tokens definition file ".$pskc_file." doesn't exist", FALSE, FALSE, 29, 'Token', ''); $result = FALSE; } else { $sXmlData = @file_get_contents($pskc_file); $xml = new MultiotpXmlParser($sXmlData, TRUE); $xml->Parse(); $ds_ns = ''; $pkcs5_ns = ''; $pskc_ns = ''; $xenc_ns = ''; $xenc11_ns = ''; if (isset($xml->document)) { $keycontainer = $xml->document; reset($keycontainer->tagAttrs); while(list($attribute_key, $attribute_value) = each($keycontainer->tagAttrs)) { if ('http://www.w3.org/2000/09/xmldsig#' == $attribute_value) { $ds_ns = substr($attribute_key,strpos($attribute_key,':')+1); $ds_ns.= ('' != $ds_ns)?':':''; } if ('http://www.rsasecurity.com/rsalabs/pkcs/schemas/pkcs-5v2-0#' == $attribute_value) { $pkcs5_ns = substr($attribute_key,strpos($attribute_key,':')+1); $pkcs5_ns.= ('' != $pkcs5_ns)?'_':''; } if ('urn:ietf:params:xml:ns:keyprov:pskc' == $attribute_value) { $pskc_ns = substr($attribute_key,strpos($attribute_key,':')+1); $pskc_ns.= ('' != $pskc_ns)?'_':''; } if ('http://www.w3.org/2001/04/xmlenc#' == $attribute_value) { $xenc_ns = substr($attribute_key,strpos($attribute_key,':')+1); $xenc_ns.= ('' != $xenc_ns)?'_':''; } if ('http://www.w3.org/2009/xmlenc11#' == $attribute_value) { $xenc11_ns = substr($attribute_key,strpos($attribute_key,':')+1); $xenc11_ns.= ('' != $xenc11_ns)?'_':''; } } $CipherArray = array(); $CipherArray['Password'] = $cipher_password; $CipherArray['xenc_ns'] = $xenc_ns; $EncryptionKey_tag = (isset($keycontainer->{$pskc_ns.'encryptionkey'})?$pskc_ns:'').'encryptionkey'; $DerivedKey_tag = (isset($keycontainer->{$EncryptionKey_tag}[0]->{$xenc11_ns.'derivedkey'})?$xenc11_ns:'').'derivedkey'; $KeyDerivationMethod_tag = (isset($keycontainer->{$EncryptionKey_tag}[0]->{$DerivedKey_tag}[0]->{$xenc11_ns.'keyderivationmethod'})?$xenc11_ns:'').'keyderivationmethod'; $KeyDerivationMethodAlgorithmUrl = isset($keycontainer->{$EncryptionKey_tag}[0]->{$DerivedKey_tag}[0]->{$KeyDerivationMethod_tag}[0]->tagAttrs["algorithm"])?($keycontainer->{$EncryptionKey_tag}[0]->{$DerivedKey_tag}[0]->{$KeyDerivationMethod_tag}[0]->tagAttrs["algorithm"]):''; $CipherArray['KeyDerivationMethodAlgorithm'] = ((FALSE !== strpos($KeyDerivationMethodAlgorithmUrl,'#pbkdf2'))?'pkcs5':''); $CipherArray['Salt'] = ''; $CipherArray['IterationCount'] = 0; $CipherArray['KeyLength'] = 0; if ('pkcs5' == $CipherArray['KeyDerivationMethodAlgorithm']) { $search_tag = 'pbkdf2_params'; if (isset($keycontainer->{$EncryptionKey_tag}[0]->{$DerivedKey_tag}[0]->{$KeyDerivationMethod_tag}[0]->{$pkcs5_ns.$search_tag})) { $search_tag = $pkcs5_ns.$search_tag; } elseif (isset($keycontainer->{$EncryptionKey_tag}[0]->{$DerivedKey_tag}[0]->{$KeyDerivationMethod_tag}[0]->{$xenc11_ns.$search_tag})) { $search_tag = $xenc11_ns.$search_tag; } $pbkdf2_params_tag = $search_tag; $search_tag = 'salt'; if (isset($keycontainer->{$EncryptionKey_tag}[0]->{$DerivedKey_tag}[0]->{$KeyDerivationMethod_tag}[0]->{$pbkdf2_params_tag}[0]->{$pkcs5_ns.$search_tag})) { $search_tag = $pkcs5_ns.$search_tag; } elseif (isset($keycontainer->{$EncryptionKey_tag}[0]->{$DerivedKey_tag}[0]->{$KeyDerivationMethod_tag}[0]->{$pbkdf2_params_tag}[0]->{$xenc11_ns.$search_tag})) { $search_tag = $xenc11_ns.$search_tag; } $salt_tag = $search_tag; $search_tag = 'specified'; if (isset($keycontainer->{$EncryptionKey_tag}[0]->{$DerivedKey_tag}[0]->{$KeyDerivationMethod_tag}[0]->{$pbkdf2_params_tag}[0]->{$salt_tag}[0]->{$pkcs5_ns.$search_tag})) { $search_tag = $pkcs5_ns.$search_tag; } elseif (isset($keycontainer->{$EncryptionKey_tag}[0]->{$DerivedKey_tag}[0]->{$KeyDerivationMethod_tag}[0]->{$pbkdf2_params_tag}[0]->{$salt_tag}[0]->{$xenc11_ns.$search_tag})) { $search_tag = $xenc11_ns.$search_tag; } $salt_specified_tag = $search_tag; $search_tag = 'iterationcount'; if (isset($keycontainer->{$EncryptionKey_tag}[0]->{$DerivedKey_tag}[0]->{$KeyDerivationMethod_tag}[0]->{$pbkdf2_params_tag}[0]->{$pkcs5_ns.$search_tag})) { $search_tag = $pkcs5_ns.$search_tag; } elseif (isset($keycontainer->{$EncryptionKey_tag}[0]->{$DerivedKey_tag}[0]->{$KeyDerivationMethod_tag}[0]->{$pbkdf2_params_tag}[0]->{$xenc11_ns.$search_tag})) { $search_tag = $xenc11_ns.$search_tag; } $iterationcount_tag = $search_tag; $search_tag = 'keylength'; if (isset($keycontainer->{$EncryptionKey_tag}[0]->{$DerivedKey_tag}[0]->{$KeyDerivationMethod_tag}[0]->{$pbkdf2_params_tag}[0]->{$pkcs5_ns.$search_tag})) { $search_tag = $pkcs5_ns.$search_tag; } elseif (isset($keycontainer->{$EncryptionKey_tag}[0]->{$DerivedKey_tag}[0]->{$KeyDerivationMethod_tag}[0]->{$pbkdf2_params_tag}[0]->{$xenc11_ns.$search_tag})) { $search_tag = $xenc11_ns.$search_tag; } $keylength_tag = $search_tag; $CipherArray['Salt'] = base64_decode(isset($keycontainer->{$EncryptionKey_tag}[0]->{$DerivedKey_tag}[0]->{$KeyDerivationMethod_tag}[0]->{$pbkdf2_params_tag}[0]->{$salt_tag}[0]->{$salt_specified_tag}[0]->tagData)?($keycontainer->{$EncryptionKey_tag}[0]->{$DerivedKey_tag}[0]->{$KeyDerivationMethod_tag}[0]->{$pbkdf2_params_tag}[0]->{$salt_tag}[0]->{$salt_specified_tag}[0]->tagData):''); $CipherArray['IterationCount'] = intval(isset($keycontainer->{$EncryptionKey_tag}[0]->{$DerivedKey_tag}[0]->{$KeyDerivationMethod_tag}[0]->{$pbkdf2_params_tag}[0]->{$iterationcount_tag}[0]->tagData)?($keycontainer->{$EncryptionKey_tag}[0]->{$DerivedKey_tag}[0]->{$KeyDerivationMethod_tag}[0]->{$pbkdf2_params_tag}[0]->{$iterationcount_tag}[0]->tagData):0); $CipherArray['KeyLength'] = intval(isset($keycontainer->{$EncryptionKey_tag}[0]->{$DerivedKey_tag}[0]->{$KeyDerivationMethod_tag}[0]->{$pbkdf2_params_tag}[0]->{$keylength_tag}[0]->tagData)?($keycontainer->{$EncryptionKey_tag}[0]->{$DerivedKey_tag}[0]->{$KeyDerivationMethod_tag}[0]->{$pbkdf2_params_tag}[0]->{$keylength_tag}[0]->tagData):0); } $search_tag = 'keypackage'; if (isset($keycontainer->{$pskc_ns.'keypackage'})) { $search_tag = $pskc_ns.$search_tag; } elseif (isset($keycontainer->{$pkcs5_ns.'keypackage'})) { $search_tag = $pkcs5_ns.$search_tag; } elseif (isset($keycontainer->{$xenc11_ns.'keypackage'})) { $search_tag = $xenc11_ns.$search_tag; } $KeyPackage_tag = $search_tag; reset($keycontainer->{$KeyPackage_tag}); while(list($keypackage_key, $keypackage) = each($keycontainer->{$KeyPackage_tag})) { $DeviceInfo_tag = (isset($keypackage->{$pskc_ns.'deviceinfo'})?$pskc_ns:'').'deviceinfo'; $Manufacturer_tag = (isset($keypackage->{$DeviceInfo_tag}[0]->{$pskc_ns.'manufacturer'})?$pskc_ns:'').'manufacturer'; $Manufacturer = (isset($keypackage->{$DeviceInfo_tag}[0]->{$Manufacturer_tag}[0]->tagData)?($keypackage->{$DeviceInfo_tag}[0]->{$Manufacturer_tag}[0]->tagData):''); $SerialNo_tag = (isset($keypackage->{$DeviceInfo_tag}[0]->{$pskc_ns.'serialno'})?$pskc_ns:'').'serialno'; $SerialNo = (isset($keypackage->{$DeviceInfo_tag}[0]->{$SerialNo_tag}[0]->tagData)?($keypackage->{$DeviceInfo_tag}[0]->{$SerialNo_tag}[0]->tagData):''); $Model_tag = (isset($keypackage->{$DeviceInfo_tag}[0]->{$pskc_ns.'model'})?$pskc_ns:'').'model'; $Model = (isset($keypackage->{$DeviceInfo_tag}[0]->{$Model_tag}[0]->tagData)?($keypackage->{$DeviceInfo_tag}[0]->{$Model_tag}[0]->tagData):''); $IssueNo_tag = (isset($keypackage->{$DeviceInfo_tag}[0]->{$pskc_ns.'issueno'})?$pskc_ns:'').'issueno'; $IssueNo = (isset($keypackage->{$DeviceInfo_tag}[0]->{$IssueNo_tag}[0]->tagData)?($keypackage->{$DeviceInfo_tag}[0]->{$IssueNo_tag}[0]->tagData):''); $CryptoModuleInfo_tag = (isset($keypackage->{$pskc_ns.'cryptomoduleinfo'})?$pskc_ns:'').'cryptomoduleinfo'; $CryptoId_tag = (isset($keypackage->{$CryptoModuleInfo_tag}[0]->{$pskc_ns.'id'})?$pskc_ns:'').'id'; $CryptoId = (isset($keypackage->{$CryptoModuleInfo_tag}[0]->{$CryptoId_tag}[0]->tagData)?($keypackage->{$CryptoModuleInfo_tag}[0]->{$CryptoId_tag}[0]->tagData):''); $Key_tag = (isset($keypackage->{$pskc_ns.'key'})?$pskc_ns:'').'key'; $AlgorithmUrl = isset($keypackage->{$Key_tag}[0]->tagAttrs["algorithm"])?($keypackage->{$Key_tag}[0]->tagAttrs["algorithm"]):''; $Algorithm = (FALSE !== strpos($AlgorithmUrl,'hotp'))?'hotp':((FALSE !== strpos($AlgorithmUrl,'totp'))?'totp':''); $KeyId = isset($keypackage->{$Key_tag}[0]->tagAttrs["id"])?($keypackage->{$Key_tag}[0]->tagAttrs["id"]):''; $Issuer_tag = (isset($keypackage->{$Key_tag}[0]->{$pskc_ns.'issuer'})?$pskc_ns:'').'issuer'; $Issuer = (isset($keypackage->{$Key_tag}[0]->{$Issuer_tag}[0]->tagData)?($keypackage->{$Key_tag}[0]->{$Issuer_tag}[0]->tagData):''); $AlgorithmParameters_tag = (isset($keypackage->{$Key_tag}[0]->{$pskc_ns.'algorithmparameters'})?$pskc_ns:'').'algorithmparameters'; $Suite_tag = (isset($keypackage->{$Key_tag}[0]->{$AlgorithmParameters_tag}[0]->{$pskc_ns.'suite'})?$pskc_ns:'').'suite'; $Suite = (isset($keypackage->{$Key_tag}[0]->{$AlgorithmParameters_tag}[0]->{$Suite_tag}[0]->tagData)?($keypackage->{$Key_tag}[0]->{$AlgorithmParameters_tag}[0]->{$Suite_tag}[0]->tagData):'HMAC-SHA1'); $ResponseFormat_tag = (isset($keypackage->{$Key_tag}[0]->{$AlgorithmParameters_tag}[0]->{$pskc_ns.'responseformat'})?$pskc_ns:'').'responseformat'; $Length = isset($keypackage->{$Key_tag}[0]->{$AlgorithmParameters_tag}[0]->{$ResponseFormat_tag}[0]->tagAttrs["length"])?($keypackage->{$Key_tag}[0]->{$AlgorithmParameters_tag}[0]->{$ResponseFormat_tag}[0]->tagAttrs["length"]):0; $Encoding = isset($keypackage->{$Key_tag}[0]->{$AlgorithmParameters_tag}[0]->{$ResponseFormat_tag}[0]->tagAttrs["encoding"])?($keypackage->{$Key_tag}[0]->{$AlgorithmParameters_tag}[0]->{$ResponseFormat_tag}[0]->tagAttrs["encoding"]):'DECIMAL'; $Data_tag = (isset($keypackage->{$Key_tag}[0]->{$pskc_ns.'data'})?$pskc_ns:'').'data'; $Secret_tag = (isset($keypackage->{$Key_tag}[0]->{$Data_tag}[0]->{$pskc_ns.'secret'})?$pskc_ns:'').'secret'; $SecretPlainValue_tag = (isset($keypackage->{$Key_tag}[0]->{$Data_tag}[0]->{$Secret_tag}[0]->{$pskc_ns.'plainvalue'})?$pskc_ns:'').'plainvalue'; $Secret = base64_decode(isset($keypackage->{$Key_tag}[0]->{$Data_tag}[0]->{$Secret_tag}[0]->{$SecretPlainValue_tag}[0]->tagData)?($keypackage->{$Key_tag}[0]->{$Data_tag}[0]->{$Secret_tag}[0]->{$SecretPlainValue_tag}[0]->tagData):''); $EncryptedValue_tag = (isset($keypackage->{$Key_tag}[0]->{$Data_tag}[0]->{$Secret_tag}[0]->{$pskc_ns.'encryptedvalue'})?$pskc_ns:'').'encryptedvalue'; if (isset($keypackage->{$Key_tag}[0]->{$Data_tag}[0]->{$Secret_tag}[0]->{$EncryptedValue_tag}[0])) { $SecretEncryptedPath = $keypackage->{$Key_tag}[0]->{$Data_tag}[0]->{$Secret_tag}[0]->{$EncryptedValue_tag}[0]; $Secret = $this->DecodeCipherValue($SecretEncryptedPath, $CipherArray); } $Counter_tag = (isset($keypackage->{$Key_tag}[0]->{$Data_tag}[0]->{$pskc_ns.'counter'})?$pskc_ns:'').'counter'; $CounterPlainValue_tag = (isset($keypackage->{$Key_tag}[0]->{$Data_tag}[0]->{$Counter_tag}[0]->{$pskc_ns.'plainvalue'})?$pskc_ns:'').'plainvalue'; $Counter = intval(isset($keypackage->{$Key_tag}[0]->{$Data_tag}[0]->{$Counter_tag}[0]->{$CounterPlainValue_tag}[0]->tagData)?($keypackage->{$Key_tag}[0]->{$Data_tag}[0]->{$Counter_tag}[0]->{$CounterPlainValue_tag}[0]->tagData):0); $EncryptedValue_tag = (isset($keypackage->{$Key_tag}[0]->{$Data_tag}[0]->{$Counter_tag}[0]->{$pskc_ns.'encryptedvalue'})?$pskc_ns:'').'encryptedvalue'; if (isset($keypackage->{$Key_tag}[0]->{$Data_tag}[0]->{$Counter_tag}[0]->{$EncryptedValue_tag}[0])) { $CounterEncryptedPath = $keypackage->{$Key_tag}[0]->{$Data_tag}[0]->{$Counter_tag}[0]->{$EncryptedValue_tag}[0]; $Counter = $this->DecodeCipherValue($CounterEncryptedPath, $CipherArray, TRUE); } $Time_tag = (isset($keypackage->{$Key_tag}[0]->{$Data_tag}[0]->{$pskc_ns.'time'})?$pskc_ns:'').'time'; $TimePlainValue_tag = (isset($keypackage->{$Key_tag}[0]->{$Data_tag}[0]->{$Time_tag}[0]->{$pskc_ns.'plainvalue'})?$pskc_ns:'').'plainvalue'; $Time = intval(isset($keypackage->{$Key_tag}[0]->{$Data_tag}[0]->{$Time_tag}[0]->{$TimePlainValue_tag}[0]->tagData)?($keypackage->{$Key_tag}[0]->{$Data_tag}[0]->{$Time_tag}[0]->{$TimePlainValue_tag}[0]->tagData):''); $EncryptedValue_tag = (isset($keypackage->{$Key_tag}[0]->{$Data_tag}[0]->{$Time_tag}[0]->{$pskc_ns.'encryptedvalue'})?$pskc_ns:'').'encryptedvalue'; if (isset($keypackage->{$Key_tag}[0]->{$Data_tag}[0]->{$Time_tag}[0]->{$EncryptedValue_tag}[0])) { $TimeEncryptedPath = $keypackage->{$Key_tag}[0]->{$Data_tag}[0]->{$Time_tag}[0]->{$EncryptedValue_tag}[0]; $Time = $this->DecodeCipherValue($TimeEncryptedPath, $CipherArray, TRUE); } $TimeInterval_tag = (isset($keypackage->{$Key_tag}[0]->{$Data_tag}[0]->{$pskc_ns.'timeinterval'})?$pskc_ns:'').'timeinterval'; $TimeIntervalPlainValue_tag = (isset($keypackage->{$Key_tag}[0]->{$Data_tag}[0]->{$TimeInterval_tag}[0]->{$pskc_ns.'plainvalue'})?$pskc_ns:'').'plainvalue'; $TimeInterval = intval(isset($keypackage->{$Key_tag}[0]->{$Data_tag}[0]->{$TimeInterval_tag}[0]->{$TimeIntervalPlainValue_tag}[0]->tagData)?($keypackage->{$Key_tag}[0]->{$Data_tag}[0]->{$TimeInterval_tag}[0]->{$TimeIntervalPlainValue_tag}[0]->tagData):30); $EncryptedValue_tag = (isset($keypackage->{$Key_tag}[0]->{$Data_tag}[0]->{$TimeInterval_tag}[0]->{$pskc_ns.'encryptedvalue'})?$pskc_ns:'').'encryptedvalue'; if (isset($keypackage->{$Key_tag}[0]->{$Data_tag}[0]->{$TimeInterval_tag}[0]->{$EncryptedValue_tag}[0])) { $TimeIntervalEncryptedPath = $keypackage->{$Key_tag}[0]->{$Data_tag}[0]->{$TimeInterval_tag}[0]->{$EncryptedValue_tag}[0]; $TimeInterval = $this->DecodeCipherValue($TimeIntervalEncryptedPath, $CipherArray, TRUE); } $Policy_tag = (isset($keypackage->{$Key_tag}[0]->{$pskc_ns.'policy'})?$pskc_ns:'').'policy'; $PINPolicy_tag = (isset($keypackage->{$Key_tag}[0]->{$Policy_tag}[0]->{$pskc_ns.'pinpolicy'})?$pskc_ns:'').'pinpolicy'; $PINPolicyAttributes = isset($keypackage->{$Key_tag}[0]->{$Policy_tag}[0]->{$PINPolicy_tag}[0]->tagAttrs[0])?($keypackage->{$Key_tag}[0]->{$Policy_tag}[0]->{$PINPolicy_tag}[0]->tagAttrs):''; $keyusage_tag = (isset($keypackage->{$Key_tag}[0]->{$Policy_tag}[0]->{$pskc_ns.'keyusage'})?$pskc_ns:'').'keyusage'; $keyusage = isset($keypackage->{$Key_tag}[0]->{$Policy_tag}[0]->{$keyusage_tag}[0]->tagData)?($keypackage->{$Key_tag}[0]->{$Policy_tag}[0]->{$keyusage_tag}[0]->tagData):''; $SerialNumber = (('' == $SerialNo)?$KeyId:$SerialNo); if (("" == $keyusage) || ("OTP" == $keyusage)) { if ((('hotp' == $Algorithm) || ('totp' == $Algorithm)) && ('' != $SerialNo) && ('' != $Secret)) { $this->SetToken($SerialNumber); $this->SetTokenDescription(trim(trim($Manufacturer.' '.$Model).' '.$SerialNo)); $this->SetTokenManufacturer($Manufacturer); $this->SetTokenModel($Model); $this->SetTokenIssueNo($IssueNo); $this->SetTokenIssuer($Issuer); $this->SetTokenKeyId($keyusage); $this->SetTokenKeyUsage($KeyId); $this->SetTokenSerialNo($SerialNo); $this->SetTokenSerialNumber($SerialNumber); $this->SetTokenKeyAlgorithm($AlgorithmUrl); $this->SetTokenAlgorithm($Algorithm); $this->SetTokenAlgoSuite($Suite); $this->SetTokenOtp("TRUE"); $this->SetTokenFormat($Encoding); $this->SetTokenNumberOfDigits($Length); if ($Counter >= 0) { $this->SetTokenLastEvent($Counter-1); } else { $this->SetTokenLastEvent(0); } $this->SetTokenDeltaTime($Time); $this->SetTokenTimeInterval($TimeInterval); $this->SetTokenSeed(bin2hex($Secret)); if ($this->CheckTokenExists()) { $this->WriteLog("Info: Token ".$this->GetToken()." already exists", FALSE, FALSE, 32, 'Token', ''); } else { $result = $this->WriteTokenData() && $result; $this->AddLastImportedToken($this->GetToken()); $this->WriteLog("Info: Token with SerialNo ".$SerialNo." successfully imported", FALSE, FALSE, 15, 'Token', ''); } if ($this->GetVerboseFlag()) { $full_token_data = ''; reset($this->_token_data); while(list($key, $value) = each($this->_token_data)) { if ('' != $value) { $full_token_data = $full_token_data."  Token ".$SerialNo." - ".$key.": ".$value."\n"; } } $this->WriteLog("Debug: *".$full_token_data, FALSE, FALSE, 8888, 'Debug', ''); } } elseif (('hotp' == $Algorithm) || ('totp' == $Algorithm)) { $result = FALSE; $this->WriteLog("Info: Token with SerialNo ".$SerialNo." failed during importation", FALSE, FALSE, 32, 'Token', ''); } } } } } return $result; } function ImportYubikeyTraditional($yubikey_file) { $result = TRUE; $imported_tokens = 0; $this->ResetTokenArray(); $this->ResetLastImportedTokensArray(); if (!file_exists($yubikey_file)) { $this->WriteLog("Error: YubiKeys log file ".$yubikey_file." doesn't exist", FALSE, FALSE, 29, 'Token', ''); $result = FALSE; } else { if ($file_handler = @fopen($yubikey_file, "rt")) { $yubikey_class = new MultiotpYubikey(); while (!feof($file_handler)) { $line = trim(fgets($file_handler)); $line = str_replace(';',"\t", $line); $line = str_replace(',',"\t", $line); $line_array = explode("\t", $line); if (count($line_array) >= 18) { $token_algo_suite = 'AES-128'; $manufacturer = "Yubico"; switch (trim($line_array[0])) { case 'Yubico OTP': $algorithm = 'yubicootp'; break; case 'OATH-HOTP': $algorithm = 'hotp'; break; default: $algorithm = ""; } $esn = trim($line_array[3]); if (('hotp' == $algorithm) && (0 == intval($line_array[10]))) { if (1 == intval($line_array[8])) { $esn = substr(trim($line_array[3]),0,2).$yubikey_class->ModHexToHex(substr(trim($line_array[3]),2)); } elseif (1 == intval($line_array[9])) { $esn = substr(trim($line_array[3]),0,4).$yubikey_class->ModHexToHex(substr(trim($line_array[3]),4)); } else { $esn = $yubikey_class->ModHexToHex(trim($line_array[3])); } } $private_id = ""; $seed = trim($line_array[5]); $interval_or_event = intval($line_array[12]); if ('hotp' == $algorithm) { $digits = intval($line_array[11]); $next_event = $interval_or_event; $time_interval = 0; } elseif ("yubicootp" == $algorithm) { $private_id = trim($line_array[4]); if ("000000000000" == $private_id) { $private_id = ""; } $digits = 32; $next_event = 0; $time_interval = 0; } if ('' != $algorithm) { $this->SetToken($esn); $this->SetTokenPrivateId($private_id); $this->SetTokenDescription(trim($manufacturer.' '.$esn)); $this->SetTokenManufacturer($manufacturer); $this->SetTokenSerialNumber($esn); $this->SetTokenSeed($seed); $this->SetTokenAlgorithm($algorithm); $this->SetUserTokenAlgoSuite($token_algo_suite); $this->SetTokenNumberOfDigits($digits); $this->SetTokenLastEvent($next_event - 1); $this->SetTokenTimeInterval($time_interval); $imported_tokens++; if ('' == $esn) { $this->WriteLog("Error: A token doesn't have any serial number", FALSE, FALSE, 32, 'Token', ''); } elseif (!$this->IsValidAlgorithm($algorithm)) { $this->WriteLog("Error: The algorithm ".$algorithm." is not recognized", FALSE, FALSE, 32, 'Token', ''); } elseif ($this->CheckTokenExists()) { $this->WriteLog("Info: Token ".$this->GetToken()." already exists", FALSE, FALSE, 32, 'Token', ''); } else { $result = $this->WriteTokenData() && $result; $this->AddLastImportedToken($this->GetToken()); $this->WriteLog("Info: Token ".$this->GetToken()." successfully imported", FALSE, FALSE, 15, 'Token', ''); } $this->ResetTokenArray(); } } } fclose($file_handler); } } if (0 == $imported_tokens) { $result = FALSE; } return $result; } function ImportTokensFromCsv( $csv_file ) { $result = TRUE; $imported_tokens = 0; $this->ResetTokenArray(); $this->ResetLastImportedTokensArray(); if (!file_exists($csv_file)) { $this->WriteLog("Error: Tokens definition file ".$csv_file." doesn't exist", FALSE, FALSE, 29, 'Token', ''); $result = FALSE; } else { if ($file_handler = @fopen($csv_file, "rt")) { while (!feof($file_handler)) { $line = trim(fgets($file_handler)); $line = str_replace(';',"\t", $line); $line = str_replace(',',"\t", $line); $line_array = explode("\t", $line); if (count($line_array) >= 6) { $esn = trim($line_array[0]); $manufacturer = $line_array[1]; $algorithm = strtolower($line_array[2]); $seed = $line_array[3]; $digits = $line_array[4]; $interval_or_event = intval($line_array[5]); if ('hotp' == $algorithm) { $next_event = $interval_or_event; $time_interval = 0; } else { $next_event = 0; $time_interval = $interval_or_event; if ("motp" == $algorithm) { $time_interval = 10; } } $this->SetToken($esn); $this->SetTokenDescription(trim($manufacturer.' '.$esn)); $this->SetTokenManufacturer($manufacturer); $this->SetTokenSerialNumber($esn); $this->SetTokenSeed($seed); $this->SetTokenAlgorithm($algorithm); $this->SetTokenNumberOfDigits($digits); $this->SetTokenLastEvent($next_event - 1); $this->SetTokenTimeInterval($time_interval); $imported_tokens++; if ('' == $esn) { $this->WriteLog("Error: A token doesn't have any serial number", FALSE, FALSE, 32, 'Token', ''); } elseif (!$this->IsValidAlgorithm($algorithm)) { $this->WriteLog("Error: The algorithm ".$algorithm." is not recognized", FALSE, FALSE, 32, 'Token', ''); } elseif ($this->CheckTokenExists()) { $this->WriteLog("Info: Token ".$this->GetToken()." already exists", FALSE, FALSE, 32, 'Token', ''); } else { $result = $this->WriteTokenData() && $result; $this->AddLastImportedToken($this->GetToken()); $this->WriteLog("Info: Token ".$this->GetToken()." successfully imported", FALSE, FALSE, 15, 'Token', ''); } $this->ResetTokenArray(); } } fclose($file_handler); } else { $this->WriteLog("Error: Tokens definition file ".$csv_file." cannot be read", FALSE, FALSE, 29, 'Token', ''); $result = FALSE; } } if (0 == $imported_tokens) { $result = FALSE; } return $result; } function ImportTokensFromXml( $xml_file ) { $this->ResetLastImportedTokensArray(); $result = TRUE; if (!file_exists($xml_file)) { $this->WriteLog("Error: Tokens definition file ".$xml_file." doesn't exist", FALSE, FALSE, 29, 'Token', ''); $result = FALSE; } else { $sXmlData = @file_get_contents($xml_file); $xml = new MultiotpXmlParser($sXmlData); $xml->Parse(); $key_types = array(); if (isset($xml->document->keyproperties)) { foreach ($xml->document->keyproperties as $keyproperty) { $id = (isset($keyproperty->tagAttrs['xml:id'])?$keyproperty->tagAttrs['xml:id']:''); if ('' != $id) { $key_types[$id]['id'] = $id; $key_types[$id]['issuer'] = (isset($keyproperty->issuer[0]->tagData)?$keyproperty->issuer[0]->tagData:''); $key_types[$id]['keyalgorithm'] = (isset($keyproperty->tagAttrs['keyalgorithm'])?$keyproperty->tagAttrs['keyalgorithm']:''); $pos = strrpos($key_types[$id]['keyalgorithm'], "#"); $key_types[$id]['algorithm'] = (($pos === false)?'':strtolower(substr($key_types[$id]['keyalgorithm'], $pos+1))); $key_types[$id]['otp'] = (isset($keyproperty->usage[0]->tagAttrs['otp'])?$keyproperty->usage[0]->tagAttrs['otp']:''); $key_types[$id]['format'] = (isset($keyproperty->usage[0]->responseformat[0]->tagAttrs['format'])?$keyproperty->usage[0]->responseformat[0]->tagAttrs['format']:''); $key_types[$id]['length'] = (isset($keyproperty->usage[0]->responseformat[0]->tagAttrs['length'])?$keyproperty->usage[0]->responseformat[0]->tagAttrs['length']:-1); $key_types[$id]['counter'] = (isset($keyproperty->data[0]->counter[0]->plainvalue[0]->tagData)?$keyproperty->data[0]->counter[0]->plainvalue[0]->tagData:-1); $key_types[$id]['time'] = (isset($keyproperty->data[0]->time[0]->plainvalue[0]->tagData)?$keyproperty->data[0]->time[0]->plainvalue[0]->tagData:-1); $key_types[$id]['timeinterval'] = (isset($keyproperty->data[0]->timeinterval[0]->plainvalue[0]->tagData)?$keyproperty->data[0]->timeinterval[0]->plainvalue[0]->tagData:-1); $key_types[$id]['suite'] = (isset($keyproperty->data[0]->suite[0]->plainvalue[0]->tagData)?$keyproperty->data[0]->suite[0]->plainvalue[0]->tagData:''); } } } if (isset($xml->document->device)) { foreach ($xml->document->device as $device) { $keyid = (isset($device->key[0]->tagAttrs['keyid'])?$device->key[0]->tagAttrs['keyid']:''); if ('' != $keyid) { $this->ResetTokenArray(); $keyproperties = ''; $manufacturer = ''; $serialno = ''; $issuer = ''; $keyalgorithm = ''; $algorithm = ''; $otp = ''; $format = ''; $length = 0; $counter = -1; $time = 0; $timeinterval = 0; $secret = ''; $suite = ''; if (isset($device->key[0]->tagAttrs['keyproperties'])) { $keyproperties = $device->key[0]->tagAttrs['keyproperties']; if (isset($key_types[$keyproperties])) { reset($key_types[$keyproperties]); while(list($key, $value) = each($key_types[$keyproperties])) { $$key = $value; } } } $manufacturer = (isset($device->deviceinfo[0]->manufacturer[0]->tagData)?$device->deviceinfo[0]->manufacturer[0]->tagData:$manufacturer); $serialno = (isset($device->deviceinfo[0]->serialno[0]->tagData)?$device->deviceinfo[0]->serialno[0]->tagData:$serialno); $issuer = (isset($device->key[0]->issuer[0]->tagData)?$device->key[0]->issuer[0]->tagData:$issuer); if (isset($device->key[0]->tagAttrs['keyalgorithm'])) { $keyalgorithm = $device->key[0]->tagAttrs['keyalgorithm']; $pos = strrpos($keyalgorithm, "#"); $algorithm = (($pos === false)?$algorithm:strtolower(substr($keyalgorithm, $pos+1))); } $otp = (isset($device->key[0]->usage[0]->tagAttrs['otp'])?$device->key[0]->usage[0]->tagAttrs['otp']:$otp); $format = (isset($device->key[0]->usage[0]->responseformat[0]->tagAttrs['format'])?$device->key[0]->usage[0]->responseformat[0]->tagAttrs['format']:$format); $length = (isset($device->key[0]->usage[0]->responseformat[0]->tagAttrs['length'])?$device->key[0]->usage[0]->responseformat[0]->tagAttrs['length']:$length); $counter = (isset($device->key[0]->data[0]->counter[0])?$device->key[0]->data[0]->counter[0]->plainvalue[0]->tagData:$counter); $time = (isset($device->key[0]->data[0]->time[0])?$device->key[0]->data[0]->time[0]->plainvalue[0]->tagData:$time); $timeinterval = (isset($device->key[0]->data[0]->timeinterval[0])?$device->key[0]->data[0]->timeinterval[0]->plainvalue[0]->tagData:$timeinterval); $suite = (isset($device->key[0]->data[0]->suite[0])?$device->key[0]->data[0]->suite[0]->plainvalue[0]->tagData:$suite); if (isset($device->key[0]->data[0]->secret[0]->plainvalue[0]->tagData)) { $secret = bin2hex(base64_decode($device->key[0]->data[0]->secret[0]->plainvalue[0]->tagData)); } if ('' == trim($serialno)) { $serialno = trim($keyid); } $this->SetToken($serialno); $this->SetTokenDescription(trim($manufacturer.' '.$keyid)); $this->SetTokenManufacturer($manufacturer); $this->SetTokenIssuer($issuer); $this->SetTokenSerialNumber($serialno); $this->SetTokenKeyAlgorithm($keyalgorithm); $this->SetTokenAlgorithm($algorithm); $this->SetTokenAlgoSuite($suite); $this->SetTokenOtp($otp); $this->SetTokenFormat($format); $this->SetTokenNumberOfDigits($length); if ($counter >= 0) { $this->SetTokenLastEvent($counter-1); } else { $this->SetTokenLastEvent(0); } $this->SetTokenDeltaTime($time); $this->SetTokenTimeInterval($timeinterval); $this->SetTokenSeed($secret); if ($this->CheckTokenExists()) { $this->WriteLog("Error: Token ".$this->GetToken()." already exists", FALSE, FALSE, 32, 'Token', ''); } else { $result = $this->WriteTokenData() && $result; $this->AddLastImportedToken($this->GetToken()); $this->WriteLog("Info: Token with keyid ".$keyid." successfully imported", FALSE, FALSE, 15, 'Token', ''); } if ($this->GetVerboseFlag()) { $full_token_data = ''; reset($this->_token_data); while(list($key, $value) = each($this->_token_data)) { if ('' != $value) { $full_token_data = $full_token_data."  Token ".$keyid." - ".$key.": ".$value."\n"; } } $this->WriteLog("Debug: *".$full_token_data, FALSE, FALSE, 8888, 'Debug', ''); } } } } } return $result; } function ImportTokensFromAlpineXml( $xml_file ) { $this->ResetLastImportedTokensArray(); $result = TRUE; if (!file_exists($xml_file)) { $this->WriteLog("Error: Tokens definition file ".$xml_file." doesn't exist", FALSE, FALSE, 29, 'Token', ''); $result = FALSE; } else { $sXmlData = @file_get_contents($xml_file); $xml = new MultiotpXmlParser($sXmlData); $xml->Parse(); $key_types = array(); if (isset($xml->document->token)) { foreach ($xml->document->token as $token) { $serial = (isset($token->tagAttrs['serial'])?$token->tagAttrs['serial']:''); if ('' != $serial) { $this->ResetTokenArray(); $manufacturer = 'SafeWord'; $serialno = $serial; $issuer = 'SafeWord'; $algorithm = 'HOTP'; $length = 6; $counter = 0; $time = 0; $timeinterval = 0; $secret = ''; if (isset($token->applications[0]->application[0]->seed[0]->tagData)) { $secret = $token->applications[0]->application[0]->seed[0]->tagData; } $this->SetToken($serialno); $this->SetTokenDescription(trim($manufacturer.' '.$serialno)); $this->SetTokenManufacturer($manufacturer); $this->SetTokenSerialNumber($serialno); $this->SetTokenIssuer($issuer); $this->SetTokenAlgorithm($algorithm); $this->SetTokenNumberOfDigits($length); $this->SetTokenLastEvent($counter-1); $this->SetTokenDeltaTime($time); $this->SetTokenTimeInterval($timeinterval); $this->SetTokenSeed($secret); if ($this->CheckTokenExists()) { $this->WriteLog("Error: Token ".$this->GetToken()." already exists", FALSE, FALSE, 32, 'Token', ''); } else { $result = $this->WriteTokenData() && $result; $this->AddLastImportedToken($this->GetToken()); $this->WriteLog("Info: Token with serial number ".$serialno." successfully imported", FALSE, FALSE, 15, 'Token', ''); } } } } } return $result; } function ImportTokensFromAlpineDat( $data_file ) { $ProductName = ""; $this->ResetTokenArray(); $this->ResetLastImportedTokensArray(); $result = TRUE; if (!file_exists($data_file)) { $this->WriteLog("Error: Tokens definition file ".$data_file." doesn't exist", FALSE, FALSE, 29, 'Token', ''); $result = FALSE; } else { if ($file_handler = @fopen($data_file, "rt")) { $line = trim(fgets($file_handler)); $reference_header = "SafeWord Authenticator Records"; $reference_manufacturer = "SafeWord"; if (FALSE !== strpos(strtolower($line), strtolower($reference_header))) { $manufacturer = $reference_manufacturer; while (!feof($file_handler)) { $line = trim(fgets($file_handler)); $line_array = explode(":",$line,2); $line_array[0] = trim($line_array[0]); $line_array[1] = trim((isset($line_array[1])?$line_array[1]:'')); switch (strtolower($line_array[0])) { case '# ===== safeword authenticator records $version': case 'dn': break; case 'objectclass': break; case 'sccauthenticatorid': $sccAuthenticatorId = $line_array[1]; $this->SetToken($sccAuthenticatorId); $this->SetTokenDescription(trim($manufacturer.' '.$sccAuthenticatorId)); $this->SetTokenSerialNumber($sccAuthenticatorId); break; case 'scctokentype': $sccTokenType = $line_array[1]; break; case 'scctokendata': $sccTokenData = $line_array[1]; $data_array = explode(";",$sccTokenData); foreach ($data_array as $data_one) { $attribute_array = explode("=",$data_one,2); $attribute_array[0] = trim($attribute_array[0]); $attribute_array[1] = trim((isset($attribute_array[1])?$attribute_array[1]:'')); switch (strtolower($attribute_array[0])) { case 'scckey': $sccKey = $attribute_array[1]; $this->SetTokenSeed($sccKey); break; case 'sccMode': $sccMode = $attribute_array[1]; break; case 'sccpwlen': $sccPwLen = $attribute_array[1]; $this->SetTokenNumberOfDigits($sccPwLen); break; case 'sccver': $sccVer = $attribute_array[1]; break; case 'sccseq': $sccSeq = $attribute_array[1]; $this->SetTokenLastEvent($sccSeq-1); break; case 'casemodel': $CaseModel = $attribute_array[1]; break; case 'productiondate': $ProductionDate = $attribute_array[1]; break; case 'prtoductname': case 'productname': $ProductName = $attribute_array[1]; break; } } break; case 'sccsignature': if ($this->CheckTokenExists()) { $this->WriteLog("Error: Token ".$this->GetToken()." already exists", FALSE, FALSE, 32, 'Token', ''); } else { $this->SetTokenManufacturer($manufacturer); $this->SetTokenIssuer($manufacturer); $this->SetTokenAlgorithm('HOTP'); $result = $this->WriteTokenData() && $result; $this->AddLastImportedToken($this->GetToken()); $this->WriteLog("Info: Token ".$this->GetToken()." successfully imported", FALSE, FALSE, 15, 'Token', ''); } $this->ResetTokenArray(); break; } } } fclose($file_handler); } } return $result; } function ImportTokensFromAuthenexSql( $data_file ) { $ProductName = ""; $this->ResetTokenArray(); $this->ResetLastImportedTokensArray(); $result = TRUE; if (!file_exists($data_file)) { $this->WriteLog("Error: Tokens definition file ".$data_file." doesn't exist", FALSE, FALSE, 29, 'Token', ''); $result = FALSE; } else { if ($file_handler = @fopen($data_file, "rt")) { $line = trim(fgets($file_handler)); $reference_header = "AUTHENEXDB"; $reference_manufacturer = "Authenex"; if (FALSE !== strpos(strtolower($line), strtolower($reference_header))) { $manufacturer = $reference_manufacturer; while (!feof($file_handler)) { $line = trim(fgets($file_handler)); if (FALSE !== strpos(strtoupper($line), 'INSERT INTO OTP')) { $token_array = array(); $line_array = explode("(",$line,3); $token_line = str_replace(")",",",$line_array[2]); $token_array = explode(",",$token_line); if (isset($token_array[1])) { $esn = preg_replace('#\W#', '', $token_array[0]); $seed = preg_replace('#\W#', '', $token_array[1]); $this->SetToken($esn); $this->SetTokenDescription(trim($manufacturer.' '.$esn)); $this->SetTokenManufacturer($manufacturer); $this->SetTokenSerialNumber($esn); $this->SetTokenSeed($seed); $this->SetTokenAlgorithm('HOTP'); $this->SetTokenNumberOfDigits(6); $this->SetTokenLastEvent(-1); } if ($this->CheckTokenExists()) { $this->WriteLog("Error: Token ".$this->GetToken()." already exists", FALSE, FALSE, 32, 'Token', ''); } else { $result = $this->WriteTokenData() && $result; $this->AddLastImportedToken($this->GetToken()); $this->WriteLog("Info: Token ".$this->GetToken()." successfully imported", FALSE, FALSE, 15, 'Token', ''); } $this->ResetTokenArray(); } } } fclose($file_handler); } } return $result; } function CreateDevice($id_array = array('id' => ''), $description = '', $device_secret = '', $ip_or_fqdn = '', $subnet = '', $shortname = '', $with_radius_update = TRUE, $challenge_response_enabled = 0, $text_token_challenge = '', $sms_challenge_enabled = 0, $text_sms_challenge = '', $cache_result_enabled = 0, $cache_timeout = 3600 ) { $result = FALSE; $device_id = (is_array($id_array)?(isset($id_array['id'])?$id_array['id']:''):$id_array); if ((0 == $device_id) || ('' == $device_id)) { $device_id = bigdec2hex((time()-mktime(1,1,1,1,1,2000)).mt_rand(10000,99999)); } if (!$this->ReadDeviceData($device_id, TRUE)) { $this->SetDevice($device_id); if (is_array($id_array)) { if (isset($id_array['id'])) { unset($id_array['id']); } reset($id_array); while(list($key, $value) = each($id_array)) { $this->_device_data[$key] = $value; } } else { $this->_device_data['description'] = $description; $this->_device_data['device_secret'] = $device_secret; $this->_device_data['ip_or_fqdn'] = $ip_or_fqdn; $this->_device_data['subnet'] = $subnet; $this->_device_data['shortname'] = $shortname; $this->_device_data['with_radius_update'] = $with_radius_update; $this->_device_data['challenge_response_enabled'] = $challenge_response_enabled; $this->_device_data['text_token_challenge'] = $text_token_challenge; $this->_device_data['sms_challenge_enabled'] = $sms_challenge_enabled; $this->_device_data['text_sms_challenge'] = $text_sms_challenge; $this->_device_data['cache_result_enabled'] = $cache_result_enabled; $this->_device_data['cache_timeout'] = $cache_timeout; } $result = $this->WriteDeviceData($this->_device_data['with_radius_update']); } return $result; } function ReadDeviceData( $device_id = '', $create = FALSE ) { if ('' != $device_id) { $this->SetDevice($device_id); } $result = FALSE; $this->_device_data['encryption_hash'] = ''; if (('files' == $this->GetBackendType()) || ($this->GetMigrationFromFile())) { $device_filename = strtolower($this->GetDevice()).'.db'; if (!file_exists($this->GetDevicesFolder().$device_filename)) { if (!$create) { $this->WriteLog("Error: database file ".$this->GetDevicesFolder().$device_filename." for device ".$this->_device." does not exist", FALSE, FALSE, 39, 'System', '', 3); } } else { if ($file_handler = @fopen($this->GetDevicesFolder().$device_filename, "rt")) { $first_line = trim(fgets($file_handler)); while (!feof($file_handler)) { $line = trim(fgets($file_handler)); $line_array = explode("=",$line,2); if (":" == substr($line_array[0], -1)) { $line_array[0] = substr($line_array[0], 0, strlen($line_array[0]) -1); $line_array[1] = $this->Decrypt($line_array[0],$line_array[1],$this->GetEncryptionKey()); } if ('' != trim($line_array[0])) { $this->_device_data[strtolower($line_array[0])] = $line_array[1]; } } fclose($file_handler); $result = TRUE; if ('' != $this->_device_data['encryption_hash']) { if ($this->_device_data['encryption_hash'] != $this->CalculateControlHash($this->GetEncryptionKey())) { $this->_device_data['encryption_hash'] = "ERROR"; $this->WriteLog("Error: the device information encryption key is not matching", FALSE, FALSE, 33, 'System', ''); $result = FALSE; } } } } } if ($this->GetBackendTypeValidated()) { switch ($this->_config_data['backend_type']) { case 'mysql': if ($this->OpenMysqlDatabase()) { if ('' != $this->_config_data['sql_devices_table']) { $sQuery = "SELECT * FROM `".$this->_config_data['sql_devices_table']."` WHERE `device_id` = '".$this->_device."'"; $aRow = NULL; if (is_object($this->_mysqli)) { if (!($rResult = $this->_mysqli->query($sQuery))) { $this->WriteLog("Error: SQL query error ($sQuery) : ".trim($this->_mysqli->error).' ', TRUE, FALSE, 40, 'System', '', 3); $result = FALSE; } else { $aRow = $rResult->fetch_assoc(); } } else { if (!($rResult = mysql_query($sQuery, $this->_mysql_database_link))) { $this->WriteLog("Error: SQL query error ($sQuery) : ".mysql_error(), TRUE, FALSE, 40, 'System', '', 3); $result = FALSE; } else { $aRow = mysql_fetch_assoc($rResult); } } if (NULL != $aRow) { $result = FALSE; while(list($key, $value) = @each($aRow)) { $in_the_schema = FALSE; reset($this->_sql_tables_schema['devices']); while(list($valid_key, $valid_format) = @each($this->_sql_tables_schema['devices'])) { if ($valid_key == $key) { $in_the_schema = TRUE; break; } } if (($in_the_schema) && ($key != 'device_id')) { if (('ENC:' == substr($value,0,4)) && (':ENC' == substr($value,-4))) { $value = substr($value,4); $value = substr($value,0,strlen($value)-4); $this->_device_data[$key] = $this->Decrypt($key,$value,$this->GetEncryptionKey()); } else { $this->_device_data[$key] = $value; } } elseif ((!$in_the_schema) && ('unique_id' != $key) && $this->GetVerboseFlag()) { $this->WriteLog("Warning: *The key ".$key." is not in the devices database schema", FALSE, FALSE, 42, 'System', '', 3); } $result = TRUE; } if (0 == count($aRow) && !$create) { $this->WriteLog("Error: SQL database entry for device ".$this->_device." does not exist", FALSE, FALSE, 39, 'System', '', 3); } } } if ('' != $this->_device_data['encryption_hash']) { if ($this->_device_data['encryption_hash'] != $this->CalculateControlHash($this->GetEncryptionKey())) { $this->_device_data['encryption_hash'] = "ERROR"; $this->WriteLog("Error: the devices mysql encryption key is not matching", FALSE, FALSE, 33, 'System', ''); $result = FALSE; } } } break; case 'pgsql': if ($this->OpenPGSQLDatabase()) { if ('' != $this->_config_data['sql_devices_table']) { $sQuery = "SELECT * FROM \"".$this->_config_data['sql_schema']."\".\"".$this->_config_data['sql_devices_table']."\" WHERE \"device_id\" = '".$this->_device."'"; $aRow = NULL; if (!($rResult = pg_query($this->_pgsql_database_link, $sQuery))) { $this->WriteLog("Error: SQL query error ($sQuery) : ".pg_last_error(), TRUE, FALSE, 40, 'System', '', 3); $result = FALSE; } else { $aRow = pg_fetch_assoc($rResult); } if (NULL != $aRow) { $result = FALSE; while(list($key, $value) = @each($aRow)) { $in_the_schema = FALSE; reset($this->_sql_tables_schema['devices']); while(list($valid_key, $valid_format) = @each($this->_sql_tables_schema['devices'])) { if ($valid_key == $key) { $in_the_schema = TRUE; break; } } if (($in_the_schema) && ($key != 'device_id')) { if (('ENC:' == substr($value,0,4)) && (':ENC' == substr($value,-4))) { $value = substr($value,4); $value = substr($value,0,strlen($value)-4); $this->_device_data[$key] = $this->Decrypt($key,$value,$this->GetEncryptionKey()); } else { $this->_device_data[$key] = $value; } } elseif ((!$in_the_schema) && ('unique_id' != $key) && $this->GetVerboseFlag()) { $this->WriteLog("Warning: *The key ".$key." is not in the devices database schema", FALSE, FALSE, 42, 'System', '', 3); } $result = TRUE; } if (0 == count($aRow) && !$create) { $this->WriteLog("Error: SQL database entry for device ".$this->_device." does not exist", FALSE, FALSE, 39, 'System', '', 3); } } } if ('' != $this->_device_data['encryption_hash']) { if ($this->_device_data['encryption_hash'] != $this->CalculateControlHash($this->GetEncryptionKey())) { $this->_device_data['encryption_hash'] = "ERROR"; $this->WriteLog("Error: the devices pgsql encryption key is not matching", FALSE, FALSE, 33, 'System', ''); $result = FALSE; } } } break; default: break; } } return $result; } function WriteDeviceData( $write_device_data_array = true ) { if (is_array($write_device_data_array)) { if (!isset($write_device_data_array['with_radius_update'])) { $write_device_data_array['with_radius_update'] = TRUE; } } else { $temp_array = array(); $temp_array['with_radius_update'] = $write_device_data_array; $write_device_data_array = $temp_array; } if ('' == trim($this->GetDevice())) { $result = false; } else { $result = $this->WriteData(array_merge(array('item' => 'Device', 'table' => 'devices', 'folder' => $this->GetDevicesFolder(), 'data_array' => $this->_device_data, 'force_file' => false, 'id_field' => 'device_id', 'id_value' => $this->GetDevice() ), $write_device_data_array)); } return $result; } function SetDevice( $device ) { $this->ResetDeviceArray(); $this->_device = strtolower($device); $this->ReadDeviceData('', TRUE); } function GetDevice() { return strtolower($this->_device); } function IsDeviceCacheResultEnabled( $device = '' ) { if($device != '') { $this->SetDevice($device); } return (1 == (isset($this->_device_data['cache_result_enabled'])?$this->_device_data['cache_result_enabled']:false)); } function SetDeviceCacheResultEnabled( $first_param, $second_param = "*-*" ) { $value = ""; if ($second_param == "*-*") { $value = $first_param; } else { $this->SetDevice($first_param); $value = $second_param; } $this->_device_data['cache_result_enabled'] = intval($value); return $value; } function GetDeviceCacheResultEnabled( $device = '' ) { if($device != '') { $this->SetDevice($device); } return intval($this->_device_data['cache_result_enabled']); } function SetDeviceCacheTimeout( $first_param, $second_param = "*-*" ) { $result = ""; if ($second_param == "*-*") { $result = $first_param; } else { $this->SetDevice($first_param); $result = $second_param; } $this->_device_data['cache_timeout'] = intval($result); return $result; } function GetDeviceCacheTimeout( $device = '' ) { if ($device != '') { $this->SetDevice($device); } return intval($this->_device_data['cache_timeout']); } function SetDeviceDescription( $first_param, $second_param = "*-*" ) { $result = ""; if ($second_param == "*-*") { $result = $first_param; } else { $this->SetDevice($first_param); $result = $second_param; } $this->_device_data['description'] = $result; return $result; } function GetDeviceDescription( $device = '' ) { if($device != '') { $this->SetDevice($device); } return $this->_device_data['description']; } function SetDeviceShortname( $first_param, $second_param = "*-*" ) { $result = ""; if ($second_param == "*-*") { $result = $first_param; } else { $this->SetDevice($first_param); $result = $second_param; } $this->_device_data['shortname'] = $result; return $result; } function GetDeviceShortname( $device = '' ) { if ($device != '') { $this->SetDevice($device); } return $this->_device_data['shortname']; } function SetDeviceIpOrFqdn( $first_param, $second_param = "*-*" ) { $result = ""; if ($second_param == "*-*") { $result = $first_param; } else { $this->SetDevice($first_param); $result = $second_param; } $this->_device_data['ip_or_fqdn'] = $result; return $result; } function GetDeviceIpOrFqdn( $device = '' ) { if($device != '') { $this->SetDevice($device); } return $this->_device_data['ip_or_fqdn']; } function SetDeviceSubnet( $first_param, $second_param = "*-*" ) { $result = ""; if ($second_param == "*-*") { $result = $first_param; } else { $this->SetDevice($first_param); $result = $second_param; } $this->_device_data['subnet'] = $result; return $result; } function GetDeviceSubnet( $device = '' ) { if ($device != '') { $this->SetDevice($device); } return $this->_device_data['subnet']; } function SetDeviceSecret( $first_param, $second_param = "*-*" ) { $result = ""; if ($second_param == "*-*") { $result = $first_param; } else { $this->SetDevice($first_param); $result = $second_param; } $this->_device_data['device_secret'] = $result; return $result; } function GetDeviceSecret( $device = '' ) { if($device != '') { $this->SetDevice($device); } return $this->_device_data['device_secret']; } function SetDeviceChallengeEnabled( $first_param, $second_param = "*-*" ) { $value = ""; if ($second_param == "*-*") { $value = $first_param; } else { $this->SetDevice($first_param); $value = $second_param; } $this->_device_data['challenge_response_enabled'] = intval($value); return $value; } function GetDeviceChallengeEnabled( $device = '' ) { if($device != '') { $this->SetDevice($device); } return intval($this->_device_data['challenge_response_enabled']); } function SetDeviceTextTokenChallenge( $first_param, $second_param = "*-*" ) { $value = ""; if ($second_param == "*-*") { $value = $first_param; } else { $this->SetDevice($first_param); $value = $second_param; } $this->_device_data['text_token_challenge'] = $value; return $value; } function GetDeviceTextTokenChallenge( $device = '' ) { if($device != '') { $this->SetDevice($device); } return $this->_device_data['text_token_challenge']; } function SetDeviceSmsChallengeEnabled( $first_param, $second_param = "*-*" ) { $value = ""; if ($second_param == "*-*") { $value = $first_param; } else { $this->SetDevice($first_param); $value = $second_param; } $this->_device_data['sms_challenge_enabled'] = intval($value); return $value; } function GetDeviceSmsChallengeEnabled( $device = '' ) { if($device != '') { $this->SetDevice($device); } return intval($this->_device_data['sms_challenge_enabled']); } function SetDeviceTextSmsChallenge( $first_param, $second_param = "*-*" ) { $value = ""; if ($second_param == "*-*") { $value = $first_param; } else { $this->SetDevice($first_param); $value = $second_param; } $this->_device_data['text_sms_challenge'] = $value; return $value; } function GetDeviceTextSmsChallenge( $device = '' ) { if ($device != '') { $this->SetDevice($device); } return $this->_device_data['text_sms_challenge']; } function DeleteDevice( $device = '', $no_error_info = FALSE ) { if ('' != $device) { $this->SetDevice($device); } $result = FALSE; if (('files' == $this->GetBackendType()) || ($this->GetMigrationFromFile())) { $device_filename = $this->GetDevice().'.db'; if (!file_exists($this->GetDevicesFolder().$device_filename)) { if (!$no_error_info) { $this->WriteLog("Error: Unable to delete device ".$this->_device.", database file ".$this->GetDevicesFolder().$device_filename." does not exist", FALSE, FALSE, 28, 'System', ''); } } else { $result = unlink($this->GetDevicesFolder().$device_filename); if ($result) { if ($this->GetVerboseFlag()) { $this->WriteLog("Info: *Device ".$this->_device." successfully deleted", FALSE, FALSE, 19, 'Device', ''); } } else { if (!$no_error_info) { $this->WriteLog("Error: Unable to delete device ".$this->_device, FALSE, FALSE, 28, 'Device', ''); } } } } if ($this->GetBackendTypeValidated()) { switch ($this->_config_data['backend_type']) { case 'mysql': if ($this->OpenMysqlDatabase()) { if ('' != $this->_config_data['sql_devices_table']) { $sQuery = "DELETE FROM `".$this->_config_data['sql_devices_table']."` WHERE `device_id` = '".$this->_device."'"; if (is_object($this->_mysqli)) { if (!($rResult = $this->_mysqli->query($sQuery))) { if (!$no_error_info) { $this->WriteLog("Error: Could not delete device ".$this->_device.": ".trim($this->_mysqli->error), FALSE, FALSE, 28, 'System', ''); } } else { $num_rows = $this->_mysqli->affected_rows; } } elseif (!($rResult = mysql_query($sQuery, $this->_mysql_database_link))) { if (!$no_error_info) { $this->WriteLog("Error: Could not delete device ".$this->_device.": ".mysql_error(), FALSE, FALSE, 28, 'System', ''); } } else { $num_rows = mysql_affected_rows($this->_mysql_database_link); } if (0 == $num_rows) { if (!$no_error_info) { $this->WriteLog("Error: Could not delete device ".$this->_device.". Device does not exist", FALSE, FALSE, 28, 'System', ''); } } else { if ($this->GetVerboseFlag()) { $this->WriteLog("Info: *Device ".$this->_device." successfully deleted", FALSE, FALSE, 19, 'Device', ''); } $result = TRUE; } } } break; case 'pgsql': if ($this->OpenPGSQLDatabase()) { if ('' != $this->_config_data['sql_devices_table']) { $sQuery = "DELETE FROM \"".$this->_config_data['sql_schema']."\".\"".$this->_config_data['sql_devices_table']."\" WHERE \"device_id\" = '".$this->_device."'"; if (!($rResult = pg_query($this->_pgsql_database_link, $sQuery))) { if (!$no_error_info) { $this->WriteLog("Error: Could not delete device ".$this->_device.": ".pg_last_error(), FALSE, FALSE, 28, 'System', ''); } } else { $num_rows = pg_affected_rows($rResult); } if (0 == $num_rows) { if (!$no_error_info) { $this->WriteLog("Error: Could not delete device ".$this->_device.". Device does not exist", FALSE, FALSE, 28, 'System', ''); } } else { if ($this->GetVerboseFlag()) { $this->WriteLog("Info: *Device ".$this->_device." successfully deleted", FALSE, FALSE, 19, 'Device', ''); } $result = TRUE; } } } break; default: break; } } if ($result) { $this->TouchFolder('data', 'Device', $this->GetDevice(), TRUE, "DeleteDevice"); } return $result; } function GetDevicesList() { return $this->GetList('device_id', 'sql_devices_table', $this->GetDevicesFolder()); } function GetDevicesCount() { if (($this->IsCacheData()) && (intval($this->ReadCacheValue('devices_count')) >= 0)) { $devices_count = intval($this->ReadCacheValue('devices_count')); } else { $devices_count = 0; switch ($this->GetBackendType()) { case 'mysql': if ($this->OpenMysqlDatabase()) { $sQuery = "SELECT device_id FROM `".$this->_config_data['sql_devices_table']."` "; if (is_object($this->_mysqli)) { if (!($result = $this->_mysqli->query($sQuery))) { $this->WriteLog("Error: Unable to access the database: ".trim($this->_mysqli->error), FALSE, FALSE, 41, 'System', '', 3); $result = FALSE; } else { while ($aRow = $result->fetch_assoc()) { $devices_count++; } } } else { if (!($rResult = mysql_query($sQuery, $this->_mysql_database_link))) { $this->WriteLog("Error: Unable to access the database: ".mysql_error(), FALSE, FALSE, 41, 'System', '', 3); } else { while ($aRow = mysql_fetch_assoc($rResult)) { $devices_count++; } } } } break; case 'pgsql': if ($this->OpenPGSQLDatabase()) { $sQuery = "SELECT \"device_id\" FROM \"".$this->_config_data['sql_schema']."\".\"".$this->_config_data['sql_devices_table']."\" "; if (!($rResult = pg_query($sQuery, $this->_pgsql_database_link))) { $this->WriteLog("Error: Unable to access the database: ".pg_last_error(), FALSE, FALSE, 41, 'System', '', 3); } else { while ($aRow = pg_fetch_assoc($rResult)) { $devices_count++; } } } break; case 'files': default: if ($devices_handle = @opendir($this->GetDevicesFolder())) { while ($file = readdir($devices_handle)) { if ((substr($file, -3) == ".db") && ($file != '.db')) { $devices_count++; } } closedir($devices_handle); } } if (($this->IsCacheData()) && ($devices_count >= 0)) { $this->WriteCacheValue('devices_count', $devices_count); $this->WriteCacheData(); } } return $devices_count; } function CreateGroup( $id = '', $name = '', $description = '' ) { if ("" != trim($name)) { $group_id = $id; if (('' == $group_id) || ('0' == $group_id)) { $group_id = bigdec2hex((time()-mktime(1,1,1,1,1,2000)).mt_rand(10000,99999)); } if ($this->CheckGroupExists($group_id)) { return FALSE; } else { $this->SetGroup($group_id); $this->SetGroupName(trim($name)); $this->SetGroupDescription($description); return $this->WriteGroupData(); } } else { return TRUE; } } function ReadGroupData( $group_id = '', $create = FALSE ) { if ('' != $group_id) { $this->SetGroup($group_id); } $result = FALSE; $this->_group_data['encryption_hash'] = ''; if (('files' == $this->GetBackendType()) || ($this->GetMigrationFromFile())) { $group_filename = $this->EncodeFileId($this->GetGroup(), FALSE).'.db'; if (!file_exists($this->GetGroupsFolder().$group_filename)) { $group_filename = $this->EncodeFileId($this->GetGroup(), FALSE, TRUE).'.db'; } if (!file_exists($this->GetGroupsFolder().$group_filename)) { if (!$create) { $this->WriteLog("Error: database file ".$this->GetGroupsFolder().$group_filename." for group ".$this->_group." does not exist", FALSE, FALSE, 39, 'System', '', 3); } } else { if ($file_handler = @fopen($this->GetGroupsFolder().$group_filename, "rt")) { $first_line = trim(fgets($file_handler)); while (!feof($file_handler)) { $line = trim(fgets($file_handler)); $line_array = explode("=",$line,2); if (":" == substr($line_array[0], -1)) { $line_array[0] = substr($line_array[0], 0, strlen($line_array[0]) -1); $line_array[1] = $this->Decrypt($line_array[0],$line_array[1],$this->GetEncryptionKey()); } if ('' != trim($line_array[0])) { $this->_group_data[strtolower($line_array[0])] = $line_array[1]; } } fclose($file_handler); $result = TRUE; if ('' != $this->_group_data['encryption_hash']) { if ($this->_group_data['encryption_hash'] != $this->CalculateControlHash($this->GetEncryptionKey())) { $this->_group_data['encryption_hash'] = "ERROR"; $this->WriteLog("Error: the group information encryption key is not matching", FALSE, FALSE, 33, 'System', ''); $result = FALSE; } } } } } if ($this->GetBackendTypeValidated()) { switch ($this->_config_data['backend_type']) { case 'mysql': if ($this->OpenMysqlDatabase()) { if ('' != $this->_config_data['sql_groups_table']) { $sQuery = "SELECT * FROM `".$this->_config_data['sql_groups_table']."` WHERE `group_id` = '".$this->_group."'"; $aRow = NULL; if (is_object($this->_mysqli)) { if (!($rResult = $this->_mysqli->query($sQuery))) { $this->WriteLog("Error: SQL query error ($sQuery) : ".trim($this->_mysqli->error).' ', TRUE, FALSE, 40, 'System', '', 3); $result = FALSE; } else { $aRow = $rResult->fetch_assoc(); } } else { if (!($rResult = mysql_query($sQuery, $this->_mysql_database_link))) { $this->WriteLog("Error: SQL query error ($sQuery) : ".mysql_error(), TRUE, FALSE, 40, 'System', '', 3); $result = FALSE; } else { $aRow = mysql_fetch_assoc($rResult); } } if (NULL != $aRow) { $result = FALSE; while(list($key, $value) = @each($aRow)) { $in_the_schema = FALSE; reset($this->_sql_tables_schema['groups']); while(list($valid_key, $valid_format) = @each($this->_sql_tables_schema['groups'])) { if ($valid_key == $key) { $in_the_schema = TRUE; break; } } if (($in_the_schema) && ($key != 'group_id')) { if (('ENC:' == substr($value,0,4)) && (':ENC' == substr($value,-4))) { $value = substr($value,4); $value = substr($value,0,strlen($value)-4); $this->_group_data[$key] = $this->Decrypt($key,$value,$this->GetEncryptionKey()); } else { $this->_group_data[$key] = $value; } } elseif ((!$in_the_schema) && ('unique_id' != $key) && $this->GetVerboseFlag()) { $this->WriteLog("Warning: *The key ".$key." is not in the groups database schema", FALSE, FALSE, 42, 'System', '', 3); } $result = TRUE; } if (0 == count($aRow) && !$create) { $this->WriteLog("Error: SQL database entry for group ".$this->_group." does not exist", FALSE, FALSE, 39, 'System', '', 3); } } } if ('' != $this->_group_data['encryption_hash']) { if ($this->_group_data['encryption_hash'] != $this->CalculateControlHash($this->GetEncryptionKey())) { $this->_group_data['encryption_hash'] = "ERROR"; $this->WriteLog("Error: the groups mysql encryption key is not matching", FALSE, FALSE, 33, 'System', ''); $result = FALSE; } } } break; case 'pgsql': if ($this->OpenPGSQLDatabase()) { if ('' != $this->_config_data['sql_groups_table']) { $sQuery = "SELECT * FROM \"".$this->_config_data['sql_schema']."\".\"".$this->_config_data['sql_groups_table']."\" WHERE \"group_id\" = '".$this->_group."'"; $aRow = NULL; if (!($rResult = pg_query($this->_pgsql_database_link, $sQuery))) { $this->WriteLog("Error: SQL query error ($sQuery) : ".pg_last_error(), TRUE, FALSE, 40, 'System', '', 3); $result = FALSE; } else { $aRow = pg_fetch_assoc($rResult); } if (NULL != $aRow) { $result = FALSE; while(list($key, $value) = @each($aRow)) { $in_the_schema = FALSE; reset($this->_sql_tables_schema['groups']); while(list($valid_key, $valid_format) = @each($this->_sql_tables_schema['groups'])) { if ($valid_key == $key) { $in_the_schema = TRUE; break; } } if (($in_the_schema) && ($key != 'group_id')) { if (('ENC:' == substr($value,0,4)) && (':ENC' == substr($value,-4))) { $value = substr($value,4); $value = substr($value,0,strlen($value)-4); $this->_group_data[$key] = $this->Decrypt($key,$value,$this->GetEncryptionKey()); } else { $this->_group_data[$key] = $value; } } elseif ((!$in_the_schema) && ('unique_id' != $key) && $this->GetVerboseFlag()) { $this->WriteLog("Warning: *The key ".$key." is not in the groups database schema", FALSE, FALSE, 42, 'System', '', 3); } $result = TRUE; } if (0 == count($aRow) && !$create) { $this->WriteLog("Error: SQL database entry for group ".$this->_group." does not exist", FALSE, FALSE, 39, 'System', '', 3); } } } if ('' != $this->_group_data['encryption_hash']) { if ($this->_group_data['encryption_hash'] != $this->CalculateControlHash($this->GetEncryptionKey())) { $this->_group_data['encryption_hash'] = "ERROR"; $this->WriteLog("Error: the groups pgsql encryption key is not matching", FALSE, FALSE, 33, 'System', ''); $result = FALSE; } } } break; default: break; } } return $result; } function WriteGroupData( $write_group_data_array = array() ) { if ('' == trim($this->GetGroup())) { $result = false; } else { $result = $this->WriteData(array_merge(array('item' => 'Group', 'table' => 'groups', 'folder' => $this->GetGroupsFolder(), 'data_array' => $this->_group_data, 'force_file' => false, 'id_field' => 'group_id', 'id_value' => $this->GetGroup() ), $write_group_data_array)); } return $result; } function SetGroup( $group ) { $this->ResetGroupArray(); $this->_group = strtolower($group); $this->ReadGroupData('', TRUE); } function GetGroup() { return strtolower($this->_group); } function SetGroupDescription( $first_param, $second_param = "*-*" ) { $result = ""; if ($second_param == "*-*") { $result = $first_param; } else { $this->SetGroup($first_param); $result = $second_param; } $result = $this->EncodeForBackend($result); $this->_group_data['description'] = $result; return $result; } function SetGroupName( $first_param, $second_param = "*-*" ) { $result = ""; if ($second_param == "*-*") { $result = trim($first_param); } else { $this->SetGroup($first_param); $result = trim($second_param); } $this->_group_data['name'] = $result; return $result; } function GetGroupDescription( $group = '' ) { if($group != '') { $this->SetGroup($group); } return $this->_group_data['description']; } function GetGroupName( $group = '' ) { if($group != '') { $this->SetGroup($group); } return $this->_group_data['name']; } function DeleteGroup( $group = '', $no_error_info = FALSE ) { if ('' != $group) { $this->SetGroup($group); } $result = FALSE; if (('files' == $this->GetBackendType()) || ($this->GetMigrationFromFile())) { $group_filename = $this->EncodeFileId($this->GetGroup(), FALSE).'.db'; if (!file_exists($this->GetGroupsFolder().$group_filename)) { $group_filename = $this->EncodeFileId($this->GetGroup(), FALSE, TRUE).'.db'; } if (!file_exists($this->GetGroupsFolder().$group_filename)) { if (!$no_error_info) { $this->WriteLog("Error: Unable to delete group ".$this->_group.", database file ".$this->GetGroupsFolder().$group_filename." does not exist", FALSE, FALSE, 28, 'System', ''); } } else { $result = unlink($this->GetGroupsFolder().$group_filename); if ($result) { if ($this->GetVerboseFlag()) { $this->WriteLog("Info: *Group ".$this->_group." successfully deleted", FALSE, FALSE, 19, 'Group', ''); } } else { if (!$no_error_info) { $this->WriteLog("Error: Unable to delete group ".$this->_group, FALSE, FALSE, 28, 'Group', ''); } } } } if ($this->GetBackendTypeValidated()) { switch ($this->_config_data['backend_type']) { case 'mysql': if ($this->OpenMysqlDatabase()) { if ('' != $this->_config_data['sql_groups_table']) { $sQuery = "DELETE FROM `".$this->_config_data['sql_groups_table']."` WHERE `group_id` = '".$this->_group."'"; if (is_object($this->_mysqli)) { if (!($rResult = $this->_mysqli->query($sQuery))) { if (!$no_error_info) { $this->WriteLog("Error: Could not delete group ".$this->_group.": ".trim($this->_mysqli->error), FALSE, FALSE, 28, 'System', ''); } } else { $num_rows = $this->_mysqli->affected_rows; } } elseif (!($rResult = mysql_query($sQuery, $this->_mysql_database_link))) { if (!$no_error_info) { $this->WriteLog("Error: Could not delete group ".$this->_group.": ".mysql_error(), FALSE, FALSE, 28, 'System', ''); } } else { $num_rows = mysql_affected_rows($this->_mysql_database_link); } if (0 == $num_rows) { if (!$no_error_info) { $this->WriteLog("Error: Could not delete group ".$this->_group.". Group does not exist", FALSE, FALSE, 28, 'Group', ''); } } else { if ($this->GetVerboseFlag()) { $this->WriteLog("Info: *Group ".$this->_group." successfully deleted", FALSE, FALSE, 19, 'Group', ''); } $result = TRUE; } } } break; case 'pgsql': if ($this->OpenPGSQLDatabase()) { if ('' != $this->_config_data['sql_groups_table']) { $sQuery = "DELETE FROM \"".$this->_config_data['sql_schema']."\".\"".$this->_config_data['sql_groups_table']."\" WHERE \"group_id\" = '".$this->_group."'"; if (!($rResult = pg_query($this->_pgsql_database_link, $sQuery))) { if (!$no_error_info) { $this->WriteLog("Error: Could not delete group ".$this->_group.": ".pg_last_error(), FALSE, FALSE, 28, 'System', ''); } } else { $num_rows = pg_affected_rows($rResult); } if (0 == $num_rows) { if (!$no_error_info) { $this->WriteLog("Error: Could not delete group ".$this->_group.". Group does not exist", FALSE, FALSE, 28, 'Group', ''); } } else { if ($this->GetVerboseFlag()) { $this->WriteLog("Info: *Group ".$this->_group." successfully deleted", FALSE, FALSE, 19, 'Group', ''); } $result = TRUE; } } } break; default: break; } } if ($result) { $this->TouchFolder('data', 'Group', $this->GetGroup(), TRUE, "DeleteGroup"); } return $result; } function CheckGroupExists( $group = '' ) { $check_group = ('' != $group)?$group:$this->GetGroup(); $result = FALSE; if ('' != trim($check_group)) { if ((($this->GetBackendTypeValidated()) && ('' != $this->_config_data['sql_groups_table'])) || ('files' == $this->GetBackendType())) { switch ($this->GetBackendType()) { case 'mysql': if ($this->OpenMysqlDatabase()) { $sQuery = "SELECT * FROM `".$this->_config_data['sql_groups_table']."` WHERE `group_id` = '{$check_group}'"; if (is_object($this->_mysqli)) { if (!($rResult = $this->_mysqli->query($sQuery))) { $this->WriteLog("Error: Unable to access the database: ".trim($this->_mysqli->error), FALSE, FALSE, 41, 'System', '', 3); } else { $num_rows = $rResult->num_rows; } } elseif (!($rResult = mysql_query($sQuery, $this->_mysql_database_link))) { $this->WriteLog("Error: Unable to access the database: ".mysql_error(), FALSE, FALSE, 41, 'System', '', 3); } else { $num_rows = mysql_num_rows($this->_mysql_database_link); } if (0 == $num_rows) { $this->WriteLog("Error: Group ".$group.". does not exist", FALSE, FALSE, 39, 'System', '', 3); $result = FALSE; } else { $result = TRUE; } } break; case 'pgsql': if ($this->OpenPGSQLDatabase()) { $sQuery = "SELECT * FROM \"".$this->_config_data['sql_schema']."\".\"".$this->_config_data['sql_groups_table']."\" WHERE \"group_id\" = '{$check_group}'"; if (!($rResult = pg_query($this->_pgsql_database_link, $sQuery))) { $this->WriteLog("Error: Unable to access the database: ".pg_last_error(), FALSE, FALSE, 41, 'System', '', 3); } else { $num_rows = pg_num_rows($rResult); } if (0 == $num_rows) { $this->WriteLog("Error: Group ".$group.". does not exist", FALSE, FALSE, 39, 'System', '', 3); $result = FALSE; } else { $result = TRUE; } } break; case 'files': default: $group_filename = $this->EncodeFileId($check_group, FALSE).'.db'; if (!file_exists($this->GetGroupsFolder().$group_filename)) { $group_filename = $this->EncodeFileId($check_group, FALSE, TRUE).'.db'; } $result = file_exists($this->GetGroupsFolder().$group_filename); break; } } } return $result; } function GetGroupsList() { return $this->GetList('group_id', 'sql_groups_table', $this->GetGroupsFolder()); } function GetList( $raw_id, $table_name, $folder ) { $list = ''; $list_array = array(); if ((($this->GetBackendTypeValidated()) && ('' != $this->_config_data[$table_name])) || ('files' == $this->GetBackendType())) { switch ($this->GetBackendType()) { case 'mysql': if ($this->OpenMysqlDatabase()) { $sQuery = "SELECT `".$raw_id."` FROM `".$this->_config_data[$table_name]."`"; $sQuery.= " ORDER BY `".$raw_id."` ASC"; if (is_object($this->_mysqli)) { if (!($result = $this->_mysqli->query($sQuery))) { $this->WriteLog("Error: Unable to access the database: ".trim($this->_mysqli->error), FALSE, FALSE, 41, 'System', '', 3); $result = FALSE; } else { while ($aRow = $result->fetch_assoc()) { if ('' != $aRow[$raw_id]) { $list.= (('' != $list)?"\t":'').$aRow[$raw_id]; } } } } else { if (!($rResult = mysql_query($sQuery, $this->_mysql_database_link))) { $this->WriteLog("Error: Unable to access the database: ".mysql_error(), FALSE, FALSE, 41, 'System', '', 3); } else { while ($aRow = mysql_fetch_assoc($rResult)) { if ('' != $aRow[$raw_id]) { $list.= (('' != $list)?"\t":'').$aRow[$raw_id]; } } } } } break; case 'pgsql': if ($this->OpenPGSQLDatabase()) { $sQuery = "SELECT \"".$raw_id."\" FROM \"".$this->_config_data['sql_schema']."\".\"".$this->_config_data[$table_name]."\""; $sQuery.= " ORDER BY \"".$raw_id."\" ASC"; if (!($rResult = pg_query($this->_pgsql_database_link, $sQuery))) { $this->WriteLog("Error: Unable to access the database: ".pg_last_error(), FALSE, FALSE, 41, 'System', '', 3); } else { while ($aRow = pg_fetch_assoc($rResult)) { if ('' != $aRow[$raw_id]) { $list.= (('' != $list)?"\t":'').$aRow[$raw_id]; } } } } break; case 'files': default: if ($file_handle = @opendir($folder)) { while ($file = readdir($file_handle)) { if ((substr($file, -3) == ".db") && ($file != '.db')) { array_push($list_array, substr($file,0,-3)); } } sort($list_array); foreach($list_array as $one_list) { $list.= (('' != $list)?"\t":'').$this->DecodeFileId($one_list); } closedir($file_handle); } } } return $list; } function GetHardwareType() { $type = "unknown"; $os_running = php_uname(); if (false !== strpos(strtolower($os_running), 'armv8')) { $type = 'RP3'; } elseif (FALSE !== strpos(strtolower($os_running), 'armv7l')) { $hardware = ''; exec("cat /proc/cpuinfo | grep --color=never -i Hardware", $output); foreach($output as $line) { $line.= "  "; if (preg_match("/^Hardware\s*:\s*(.*)/", $line)) { preg_match_all("/^Hardware\s*:\s*(.*)/", $line, $result_array, PREG_SET_ORDER); if (isset($result_array[0][1])) { $hardware = strtoupper(trim($result_array[0][1])); break; } } } if (FALSE !== strpos(strtolower($hardware), 'bcm27')) { $lscpu = ''; exec("/usr/bin/lscpu | grep --color=never -i \"CPU max MHz\"", $output); foreach($output as $line) { $line.= "  "; if (preg_match("/^CPU max MHz\s*:\s*(.*)/", $line)) { preg_match_all("/^CPU max MHz\s*:\s*(.*)/", $line, $result_array, PREG_SET_ORDER); if (isset($result_array[0][1])) { $lscpu = strtoupper(trim($result_array[0][1])); break; } } } if (false !== strpos(strtolower($lscpu), '1200')) { $type = 'RP3'; } else { $type = 'RP2'; } } else { $type = 'BBB'; } } elseif (FALSE !== strpos(strtolower($os_running), 'armv6l')) { $type = 'RPI'; } elseif (strtolower(substr(PHP_OS, 0, 3)) === 'win') { $type = "DVP"; } elseif (FALSE !== strpos(strtolower($os_running), 'debian')) { $type = 'VAP'; } return $type; } function GetRaspberryPiSerialNumber() { $serial = ''; exec("cat /proc/cpuinfo | grep --color=never -i Serial", $output); foreach($output as $line) { $line.= "  "; if (preg_match("/^Serial\s*:\s*(.*)/", $line)) { preg_match_all("/^Serial\s*:\s*(.*)/", $line, $result_array, PREG_SET_ORDER); if (isset($result_array[0][1])) { $serial = strtoupper(trim($result_array[0][1])); break; } } } return $serial; } function ReadUserDataOnServer( $user ) { $result = 72; $server_challenge = 'MOSH'.md5($this->GetEncryptionKey().time().mt_rand(100000,999999)); $this->SetServerChallenge($server_challenge); $xml_data = <<<EOL
*XmlVersion*
<multiOTP version="4.0" xmlns="http://www.sysco.ch/namespaces/multiotp">
<ServerChallenge>*ServerChallenge*</ServerChallenge>
<ReadUserData>
  <UserId>*UserId*</UserId>
</ReadUserData>
</multiOTP>
EOL;
$xml_data = str_replace('*XmlVersion*', '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>', $xml_data); $xml_data = str_replace('*ServerChallenge*', $this->Encrypt('ServerChallenge', $server_challenge, $this->GetServerSecret()), $xml_data); $xml_data = str_replace('*UserId*', $user, $xml_data); $xml_urls = $this->GetServerUrl(); $xml_timeout = $this->GetServerTimeout(); $xml_data_encoded = urlencode($xml_data); $response = $this->PostHttpDataXmlRequest($xml_data_encoded, $xml_urls, $xml_timeout); if (FALSE !== $response) { if ($this->_xml_dump_in_log) { $this->WriteLog("Info: Host returned the following answer: $response", FALSE, FALSE, 8888, 'Debug', ''); } if (FALSE !== strpos($response,'<multiOTP')) { $error_code = 99; $xml = new MultiotpXmlParser($response); $xml->Parse(); if (isset($xml->document->errorcode[0])) { $server_password = (isset($xml->document->serverpassword[0]) ? ($xml->document->serverpassword[0]->tagData) : ''); if ($server_password != md5('ReadUserData'.$this->GetServerSecret().$this->GetServerChallenge())) { $error_code = 70; } else { $error_code = (isset($xml->document->errorcode[0]) ? intval($xml->document->errorcode[0]->tagData) : 99); } $error_description = (isset($xml->document->errordescription[0])?($xml->document->errordescription[0]->tagData):$this->GetErrorText($error_code)); if ($this->_xml_dump_in_log) { $this->WriteLog("Info: Host returned the following result: $error_code ($error_description)", FALSE, FALSE, $error_code, 'Debug', ''); } } if ((19 == intval($error_code)) && (isset($xml->document->user[0]))) { $result = (isset($xml->document->user[0]->userdata[0])?($xml->document->user[0]->userdata[0]->tagData):''); } else { $this->WriteLog("Error: Host answers with the following error code: $error_code ($error_description)", FALSE, FALSE, 39, 'Client-Server', '', 3); $result = intval($error_code); } } else { if ($this->GetVerboseFlag()) { $this->WriteLog("Error: *Host sent an incorrect answer: $response", FALSE, FALSE, 39, 'Client-Server', '', 3); } } } return $result; } function CheckUserExistsOnServer( $user = '' ) { $result = 72; $server_challenge = 'MOSH'.md5($this->GetEncryptionKey().time().mt_rand(100000,999999)); $this->SetServerChallenge($server_challenge); $xml_data = <<<EOL
*XmlVersion*
<multiOTP version="4.0" xmlns="http://www.sysco.ch/namespaces/multiotp">
<ServerChallenge>*ServerChallenge*</ServerChallenge>
<CheckUserExists>
  <UserId>*UserId*</UserId>
</CheckUserExists>
</multiOTP>
EOL;
$xml_data = str_replace('*XmlVersion*', '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>', $xml_data); $xml_data = str_replace('*ServerChallenge*', $this->Encrypt('ServerChallenge', $server_challenge, $this->GetServerSecret()), $xml_data); $xml_data = str_replace('*UserId*', $user, $xml_data); $xml_urls = $this->GetServerUrl(); $xml_timeout = $this->GetServerTimeout(); $xml_data_encoded = urlencode($xml_data); $response = $this->PostHttpDataXmlRequest($xml_data_encoded, $xml_urls, $xml_timeout); if (FALSE !== $response) { if ($this->_xml_dump_in_log) { $this->WriteLog("Info: Host returned the following answer: $response", FALSE, FALSE, 8888, 'Debug', ''); } if (FALSE !== strpos($response,'<multiOTP')) { $error_code = 99; $xml = new MultiotpXmlParser($response); $xml->Parse(); if (isset($xml->document->errorcode[0])) { $server_password = (isset($xml->document->serverpassword[0])?($xml->document->serverpassword[0]->tagData):''); if ($server_password != md5('CheckUserExists'.$this->GetServerSecret().$this->GetServerChallenge())) { $error_code = 70; } else { $error_code = (isset($xml->document->errorcode[0]) ? intval($xml->document->errorcode[0]->tagData) : 99); } $error_description = (isset($xml->document->errordescription[0]) ? ($xml->document->errordescription[0]->tagData) : $this->GetErrorText($error_code)); if ($this->_xml_dump_in_log) { $this->WriteLog("Info: Host returned the following result: $error_code ($error_description).", FALSE, FALSE, $error_code, 'Debug', ''); } } $result = intval($error_code); } else { if ($this->GetVerboseFlag()) { $this->WriteLog("Error: *Host sent an incorrect answer: $response", FALSE, FALSE, 8888, 'Client-Server', ''); } } } return $result; } function CheckUserTokenOnServer( $user, $password, $auth_method = "PAP", $id= '', $challenge = '', $response2 = '' ) { $result = 72; $server_challenge = 'MOSH'.md5($this->GetEncryptionKey().time().mt_rand(100000,999999)); $this->SetServerChallenge($server_challenge); switch (strtoupper($auth_method)) { case 'CHAP': $chap_id = $id; $chap_challenge = $challenge; $chap_password = $password; $chap_hash = ''; break; case 'MS-CHAP': $ms_chap_id = $id; $ms_chap_challenge = $challenge; $ms_chap_response = $password; $chap_hash = ''; break; case ' MS-CHAPV2': $ms_chap_id = $id; $ms_chap_challenge = $challenge; $ms_chap_response = $password; $ms_chap2_response = $response2; $chap_hash = ''; break; case 'PAP': default: $chap_id = bin2hex(chr(mt_rand(0, 255))); $chap_challenge = md5(time()); $chap_password = $this->CalculateChapPassword($password, $chap_id, $chap_challenge); $chap_hash = $this->Encrypt('ChapHash', $password, $chap_id.$server_challenge.$chap_id); break; } $xml_data = <<<EOL
*XmlVersion*
<multiOTP version="4.0" xmlns="http://www.sysco.ch/namespaces/multiotp">
<ServerChallenge>*ServerChallenge*</ServerChallenge>
<CheckUserToken>
  <UserId>*UserId*</UserId>
  <Chap>
      <ChapId>*ChapId*</ChapId>
      <ChapChallenge>*ChapChallenge*</ChapChallenge>
      <ChapPassword>*ChapPassword*</ChapPassword>
      <ChapHash>*ChapHash*</ChapHash>
  </Chap>
  <CacheLevel>*CacheLevel*</CacheLevel>
</CheckUserToken>
</multiOTP>
EOL;
$xml_data = str_replace('*XmlVersion*', '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>', $xml_data); $xml_data = str_replace('*ServerChallenge*', $this->Encrypt('ServerChallenge', $server_challenge, $this->GetServerSecret()), $xml_data); $xml_data = str_replace('*UserId*', $user, $xml_data); $xml_data = str_replace('*ChapId*', $chap_id, $xml_data); $xml_data = str_replace('*ChapChallenge*', $chap_challenge, $xml_data); $xml_data = str_replace('*ChapPassword*', $chap_password, $xml_data); $xml_data = str_replace('*ChapHash*', $chap_hash, $xml_data); $xml_data = str_replace('*CacheLevel*', $this->GetServerCacheLevel(), $xml_data); $xml_urls = $this->GetServerUrl(); $xml_timeout = $this->GetServerTimeout(); $xml_data_encoded = urlencode($xml_data); $response = $this->PostHttpDataXmlRequest($xml_data_encoded, $xml_urls, $xml_timeout); if (FALSE !== $response) { if ($this->_xml_dump_in_log) { $this->WriteLog("Debug: Host returned the following answer: $response", FALSE, FALSE, 8888, 'Debug', ''); } if (FALSE !== strpos($response,'<multiOTP')) { $result = 99; $error_code = 99; $xml = new MultiotpXmlParser($response); $xml->Parse(); if (isset($xml->document->errorcode[0])) { $server_password = (isset($xml->document->serverpassword[0])?($xml->document->serverpassword[0]->tagData):''); if ($server_password != md5('CheckUserToken'.$this->GetServerSecret().$this->GetServerChallenge())) { $error_code = 70; } else { $error_code = (isset($xml->document->errorcode[0]) ? intval($xml->document->errorcode[0]->tagData) : 99); } $error_description = (isset($xml->document->errordescription[0])?($xml->document->errordescription[0]->tagData):$this->GetErrorText(intval($error_code))); $result = intval($error_code); if ($this->_xml_dump_in_log) { $this->WriteLog("Info: Host returned the following result: $result ($error_description).", FALSE, FALSE, $result, 'Debug', ''); } } if ((intval(0) == intval($error_code)) && (isset($xml->document->cache[0]))) { if (isset($xml->document->cache[0]->user[0])) { foreach ($xml->document->cache[0]->user as $one_user) { $current_user = isset($one_user->tagAttrs['userid'])?$one_user->tagAttrs['userid']:''; if ('' != $current_user) { $current_user_data = isset($one_user->userdata[0])?$one_user->userdata[0]->tagData:''; if ('' != $current_user_data) { $this->SetUser($current_user); $this->_user_data['encryption_hash'] = $this->CalculateControlHash($this->GetEncryptionKey()); $current_user_array = explode("\n",$current_user_data); foreach ($current_user_array as $one_line) { $line = trim($one_line); $line_array = explode("=",$line,2); if (":" == substr($line_array[0], -1)) { $line_array[0] = substr($line_array[0], 0, strlen($line_array[0]) -1); $line_array[1] = $this->Decrypt($line_array[0], $line_array[1], $this->GetServerSecret()); } if ('' != trim($line_array[0])) { if ('encryption_hash' != strtolower($line_array[0])) { $this->_user_data[strtolower($line_array[0])] = $line_array[1]; } } } $this->WriteUserData(); } } } } } } else { if ($this->GetVerboseFlag()) { $this->WriteLog("Error: *Host sent an incorrect answer: $response", FALSE, FALSE, 8888, 'Client-Server', ''); } } } $this->SetUser($user); return $result; } function PostHttpDataXmlRequest( $xml_data, $xml_urls, $xml_timeout = 3, $xml_urls_splitter = ";", $no_multiotp_validity_check = FALSE ) { $result = FALSE; $content_to_post = 'data='.$xml_data; $xml_url = explode($xml_urls_splitter,$xml_urls); foreach ($xml_url as $xml_url_one) { $server_to_ban = substr($xml_url_one, 0, strpos($xml_url_one."?", "?")); $skip = $this->IsTemporaryBadServer($server_to_ban); if (!$skip) { $port = 80; $pos = strpos($xml_url_one, '://'); if (FALSE === $pos) { $protocol = ''; } else { switch (strtolower(substr($xml_url_one,0,$pos))) { case 'https': case 'ssl': $protocol = 'ssl://'; $port = 443; break; case 'tls': $protocol = 'tls://'; $port = 443; break; default: $protocol = ''; break; } $xml_url_one = substr($xml_url_one,$pos+3); } $pos = strpos($xml_url_one, '/'); if (FALSE === $pos) { $host = $xml_url_one; $url = '/'; } else { $host = substr($xml_url_one,0,$pos); $url = substr($xml_url_one,$pos); } $pos = strpos($host, ':'); if (FALSE !== $pos) { $port = substr($host,$pos+1); $host = substr($host,0,$pos); } $errno = 0; $errdesc = 0; if (function_exists("stream_socket_client")) { $sslContext = stream_context_create($this->_default_ssl_context); $fp = @stream_socket_client($protocol.$host.":".$port, $errno, $errdesc, $xml_timeout, STREAM_CLIENT_CONNECT, $sslContext); } else { $fp = @fsockopen($protocol.$host, $port, $errno, $errdesc, $xml_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: ".strlen($content_to_post)."\r\n"); fputs($fp, "User-Agent: multiOTP\r\n"); fputs($fp, "Host: ".$host."\r\n"); fputs($fp, "\r\n"); fputs($fp, $content_to_post); fputs($fp, "\r\n"); $stream_timeout = $xml_timeout; if ($stream_timeout < 20) { $stream_timeout = 20; } stream_set_blocking($fp, TRUE); stream_set_timeout($fp, $stream_timeout); $info = stream_get_meta_data($fp); $reply = ''; $last_length = 0; while ((!feof($fp)) && ((!$info['timed_out']) || ($last_length != strlen($reply)))) { $last_length = strlen($reply); $reply.= fgets($fp, 1024); $info = stream_get_meta_data($fp); @ob_flush(); flush(); } fclose($fp); if ($info['timed_out']) { $this->WriteLog("Warning: timeout after $xml_timeout seconds for $protocol$host:$port with a result code of $errno ($errdesc).", FALSE, FALSE, 8888, 'Client-Server', ''); } else { $pos = strpos(strtolower($reply), "\r\n\r\n"); $header = substr($reply, 0, $pos); $answer = substr($reply, $pos + 4); $header_array = explode(" ", $header."   "); $status = intval($header_array[1]); $this->SetLastHttpStatus($status); $result = $answer; if ($errno > 0) { $this->WriteLog("Info: $protocol$host:$port returns a resultcode of $errno ($errdesc).", FALSE, FALSE, 8888, 'Client-Server', ''); } if ((FALSE !== strpos($result, '<multiOTP')) || $no_multiotp_validity_check) { break; } } $this->AddTemporaryBadServer($server_to_ban, time()); $log_info = "Info: temporary adding $server_to_ban to the list of banned servers, content not recognized (".substr($result, 0, 80)."...)"; if ($this->_xml_dump_in_log) { $log_info.= ": ".$result; } $this->WriteLog($log_info, FALSE, FALSE, 8888, 'Client-Server', ''); } else { $this->AddTemporaryBadServer($server_to_ban, time()); $this->WriteLog("Warning: Host $protocol$host on port $port not reached before a timeout of $xml_timeout seconds.", FALSE, FALSE, 8888, 'Client-Server', ''); } } else { $this->WriteLog("Info: temporary skipping $xml_url_one due to previous timeout or inconsistent response.", FALSE, FALSE, 8888, 'Client-Server', ''); $result = ""; } } if (FALSE === strpos($result,'<multiOTP')) { $this->_servers_last_timeout = time(); if ($this->_xml_dump_in_log) { $this->WriteLog("Debug: timeout detected.", FALSE, FALSE, 8888, 'Debug', ''); } } return $result; } function SoapOpenotpNormalLogin( $username = "", $domain = "", $ldapPassword = "", $otpPassword = "", $client = "", $source = "", $settings = "", $options = "" ) { $error_code = intval($this->CheckUserToken($username, $ldapPassword.$otpPassword)); switch ($error_code) { case 0: $result['code'] = 1; break; case 10: $result['code'] = 2; break; default: $result['code'] = 0; break; } $result['message'] = $this->GetErrorText($error_code); if ($error_code > 10) { $result['message'].= " (".$error_code.")"; } $result['session'] = ""; $result['data'] = ""; $result['timeout'] = 0; $result['otpChallenge'] = ""; $result['u2fChallenge'] = ""; return $result; } function SoapOpenotpSimpleLogin( $username = "", $domain = "", $anyPassword = "", $client = "", $source = "", $settings = "" ) { $error_code = intval($this->CheckUserToken($username, $anyPassword)); switch ($error_code) { case 0: $result['code'] = 1; break; case 10: $result['code'] = 2; break; default: $result['code'] = 0; break; } $result['message'] = $this->GetErrorText($error_code); if ($error_code > 10) { $result['message'].= " (".$error_code.")"; } $result['session'] = ""; $result['data'] = ""; $result['timeout'] = 0; return $result; } function SoapOpenotpChallenge( $username = "", $domain = "", $session = "", $otpPassword = "", $u2fResponse = "" ) { $error_code = intval($this->CheckUserToken($username, $otpPassword)); switch ($error_code) { case 0: $result['code'] = 1; break; default: $result['code'] = 0; break; } $result['message'] = $this->GetErrorText($error_code); if ($error_code > 0) { $result['message'].= " (".$error_code.")"; } $result['data'] = ""; return $result; } function SoapOpenotpStatus() { $eol = chr(13).chr(10); $result['status'] = true; $result['message'] = "Server: ".$this->GetFullVersionInfo().$eol; if (isset($_SERVER["SERVER_ADDR"])) { $result['message'].= "Listener: ".$_SERVER["SERVER_ADDR"].(isset($_SERVER["SERVER_PORT"])?":".$_SERVER["SERVER_PORT"]:"").$eol; } if (isset($_SERVER["SERVER_PROTOCOL"])) { $result['message'].= "Protocol: ".$_SERVER["SERVER_PROTOCOL"]; } if ('' != (isset($_SERVER["HTTPS"])?$_SERVER["HTTPS"]:'')) { $result['message'].= " (SSL)"; } else { $result['message'].= " (no SSL)"; } $result['message'].= $eol; $result['message'].= "Uptime: ".$this->GetUptime(false).$eol; $memory_limit = ini_get("memory_limit"); if ('M' == substr($memory_limit,-1)) { $memory_limit = intval(substr($memory_limit,0,strlen($memory_limit)-1)) * 1024 * 1024; } elseif ('K' == substr($memory_limit,-1)) { $memory_limit = intval(substr($memory_limit,0,strlen($memory_limit)-1)) * 1024; } $result['message'].= "Memory: ".$memory_limit.$eol; return $result; } function CallApi( $call_array = array("script_uri" => "", "secret" => "", "post_data" => "") ) { $script_uri = isset($call_array["script_uri"]) ? $call_array["script_uri"] : ""; $secret = isset($call_array["secret"]) ? $call_array["secret"] : ""; $post_data = isset($call_array["post_data"]) ? $call_array["post_data"] : ""; $uri_elements = parse_url($script_uri); $scheme = isset($uri_elements['scheme']) ? $uri_elements['scheme'] : 'http'; $port = isset($uri_elements['port']) ? $uri_elements['port'] : ''; $request = isset($uri_elements['query']) ? $uri_elements['query'] : ''; $host = isset($uri_elements['host']) ? $uri_elements['host'] : ''; $path = isset($uri_elements['path']) ? $uri_elements['path'] : ''; parse_str($request, $parameters); if (isset($parameters['Signature'])) { unset($parameters['Signature']); } if (isset($parameters['Timestamp'])) { unset($parameters['Timestamp']); } $parameters['Timestamp'] = gmdate("Y-m-d\TH:i:s\Z"); ksort($parameters); $request_array = array(); foreach ($parameters as $parameter => $value) { $parameter = str_replace("%7E", "~", rawurlencode($parameter)); $value = str_replace("%7E", "~", rawurlencode($value)); $request_array[] = $parameter . '=' . $value; } $new_request = implode('&', $request_array); $signature_string = "GET\n{$host}\n{$path}\n{$new_request}"; $secret_key = $secret; if ('' == $secret_key) { $secret_key = $this->GetServerSecret(); } $signature = urlencode(base64_encode(hash_hmac('sha256', $signature_string, $secret_key, TRUE))); $url_request = "{$scheme}://{$host}".(('' != $port) ? ":{$port}" : "")."{$path}?{$new_request}&Signature={$signature}"; if ($this->GetVerboseFlag()) { $this->WriteLog("Debug: *CallApi $script_uri (secret: $secret_key, signature string: $signature_string, full URL: $url_request)", FALSE, FALSE, 8888, 'Debug', ''); } $api_result = $this->PostHttpDataXmlRequest( $post_data, $url_request, $this->GetServerTimeout(), "\t", TRUE ); return $api_result; } function XmlServer($data) { $remote_ip = isset($_SERVER['REMOTE_ADDR'])?$_SERVER['REMOTE_ADDR']:''; $cache_data = ''; $command_name = ''; $error_code = 71; $server_password = ''; $user_data = ''; $user_info = ''; $user_password = ''; $cache_data_template = <<<EOL
      <Cache>
      *UserInCache*</Cache>
EOL;
$user_template = <<<EOL
          <User UserId="*UserId*">
              <UserData>*UserData*</UserData>
          </User>
EOL;
$xml_data = <<<EOL
*XmlVersion*
<multiOTP version="4.0" xmlns="http://www.sysco.ch/namespaces/multiotp">
<DebugCode>*Command*</DebugCode>
<ServerPassword>*ServerPassword*</ServerPassword>
<ErrorCode>*ErrorCode*</ErrorCode>
<ErrorDescription>*ErrorDescription*</ErrorDescription>
*UserInfo**Cache*</multiOTP>
EOL;
$xml_data = str_replace('*XmlVersion*', '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>', $xml_data); if (FALSE !== strpos($data,'<multiOTP')) { if ($this->_xml_dump_in_log) { $this->WriteLog("Info: Host answer is correctly formatted.", FALSE, FALSE, 8888, 'Debug', ''); $this->WriteLog("Info: Host received the following request: $data", FALSE, FALSE, 8888, 'Debug', ''); } $xml = new MultiotpXmlParser($data); $xml->Parse(); $server_challenge = $this->Decrypt('ServerChallenge', (isset($xml->document->serverchallenge[0])?($xml->document->serverchallenge[0]->tagData):''),$this->GetServerSecret($remote_ip)); if (isset($xml->document->checkusertoken[0])) { $command_name = 'CheckUserToken'; if ($this->GetVerboseFlag()) { $this->WriteLog("Info: *CheckUserToken server request.", FALSE, FALSE, 8888, 'Server-Client', ''); } $user_id = (isset($xml->document->checkusertoken[0]->userid[0])?($xml->document->checkusertoken[0]->userid[0]->tagData):''); $chap_id = (isset($xml->document->checkusertoken[0]->chap[0]->chapid[0])?($xml->document->checkusertoken[0]->chap[0]->chapid[0]->tagData):'00'); $chap_challenge = (isset($xml->document->checkusertoken[0]->chap[0]->chapchallenge[0])?($xml->document->checkusertoken[0]->chap[0]->chapchallenge[0]->tagData):''); $chap_password = (isset($xml->document->checkusertoken[0]->chap[0]->chappassword[0])?($xml->document->checkusertoken[0]->chap[0]->chappassword[0]->tagData):''); $chap_hash = (isset($xml->document->checkusertoken[0]->chap[0]->chaphash[0])?($xml->document->checkusertoken[0]->chap[0]->chaphash[0]->tagData):''); if ('' != $chap_hash) { $chap_hash = $this->Decrypt('ChapHash', $chap_hash, $chap_id.$server_challenge.$chap_id); } $cache_level = (isset($xml->document->checkusertoken[0]->cachelevel[0])?($xml->document->checkusertoken[0]->cachelevel[0]->tagData):0); if ($cache_level > $this->GetServerCacheLevel()) { $cache_level = $this->GetServerCacheLevel(); } $error_code = 70; if ('MOSH' == substr($server_challenge, 0, 4)) { if ('' != $chap_hash) { $this->SetChapId(''); $this->SetChapChallenge(''); $this->SetChapPassword(''); $user_password = $chap_hash; } elseif ('' == $chap_id) { $this->SetChapId(''); $this->SetChapChallenge(''); $this->SetChapPassword(''); $user_password = $chap_password; } else { $this->SetChapId($chap_id); $this->SetChapChallenge($chap_challenge); $this->SetChapPassword($chap_password); } if (!$this->CheckUserExists($user_id)) { $error_code = 21; } else { $error_code = intval($this->CheckUserToken($user_id, $user_password, '', FALSE, FALSE, FALSE, TRUE)); $now_epoch = time(); $cache_lifetime = $this->GetServerCacheLifetime(); if ((0 < $cache_level) && (0 == intval($error_code))) { if ($this->GetVerboseFlag()) { $this->WriteLog("Info: *Cache level is set to $cache_level", FALSE, FALSE, 8888, 'Server-Client', ''); } reset($this->_user_data); while(list($key, $value) = each($this->_user_data)) { if ('' != trim($key)) { if ('encryption_hash' != $key) { $user_data.= strtolower($key); if ('autolock_time' == $key) { if (0 < $cache_lifetime) { if (($value == 0) || ($value > ($now_epoch + $cache_lifetime))) { $value = ($now_epoch + $cache_lifetime); } } } $value = $this->Encrypt($key, $value, $this->GetServerSecret($remote_ip)); $user_data = $user_data.":"; $user_data = $user_data."=".$value; $user_data.= "\n"; } } } $cache_user = ''; $one_cache_user = str_replace('*UserId*', $user_id, $user_template); $one_cache_user = str_replace('*UserData*', $user_data, $one_cache_user); $cache_user .= $one_cache_user; $cache_data = str_replace('*UserInCache*', $cache_user, $cache_data_template); } } } } elseif (isset($xml->document->readuserdata[0])) { $command_name = 'ReadUserData'; $user_id = (isset($xml->document->readuserdata[0]->userid[0])?($xml->document->readuserdata[0]->userid[0]->tagData):'NO_USER_DETECTED!'); if ($this->GetVerboseFlag()) { $this->WriteLog("Info: *ReadUserData server request for $user_id", FALSE, FALSE, 8888, 'Server-Client', ''); } $error_code = 70; if ('MOSH' == substr($server_challenge, 0, 4)) { $error_code = 21; if ($this->ReadUserData($user_id, FALSE, TRUE)) { $error_code = 19; reset($this->_user_data); while(list($key, $value) = each($this->_user_data)) { if ('' != trim($key)) { if ('encryption_hash' != $key) { $user_data.= strtolower($key); $value = $this->Encrypt($key, $value, $this->GetServerSecret($remote_ip)); $user_data = $user_data.":"; $user_data = $user_data."=".$value; $user_data.= "\n"; } } } $user_info = str_replace('*UserId*', $user_id, $user_template); $user_info = str_replace('*UserData*', $user_data, $user_info); } } } elseif (isset($xml->document->checkuserexists[0])) { $command_name = 'CheckUserExists'; $user_id = (isset($xml->document->checkuserexists[0]->userid[0])?($xml->document->checkuserexists[0]->userid[0]->tagData):'NO_USER_DETECTED!'); if ($this->GetVerboseFlag()) { $this->WriteLog("Info: *CheckUserExists server request for $user_id with challenge $server_challenge", FALSE, FALSE, 8888, 'Server-Client', ''); } $error_code = 70; if ('MOSH' == substr($server_challenge, 0, 4)) { $error_code = 21; if ($this->CheckUserExists($user_id, TRUE)) { $error_code = 22; } } if ($this->GetVerboseFlag()) { $this->WriteLog("Info: *CheckUserExists intermediate error code: $error_code", FALSE, FALSE, 8888, 'Server-Client', ''); } } $server_password = md5($command_name.$this->GetServerSecret($remote_ip).$server_challenge); }elseif ($this->GetVerboseFlag()) { $this->WriteLog("Info: *Server received the following request: $data", FALSE, FALSE, 8888, 'Server-Client', ''); } $error_description = $this->GetErrorText($error_code); $xml_data = str_replace('*Command*', $command_name, $xml_data); $xml_data = str_replace('*ServerPassword*', $server_password, $xml_data); $xml_data = str_replace('*ErrorCode*', intval($error_code), $xml_data); $xml_data = str_replace('*ErrorDescription*', $error_description, $xml_data); $xml_data = str_replace('*UserInfo*', $user_info, $xml_data); $xml_data = str_replace('*Cache*', $cache_data, $xml_data); header("Expires: " . gmdate("D, d M Y H:i:s") . " GMT"); header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); header("Cache-Control: no-store, no-cache, must-revalidate"); header("Cache-Control: post-check=0, pre-check=0", false); header("Pragma: no-cache"); header("Content-type: text/xml"); if ($this->_xml_dump_in_log) { $this->WriteLog("Info: Server sent the following answer: $xml_data", FALSE, FALSE, 8888, 'Debug', ''); } echo $xml_data; } function qrcode( $data = '', $file_name = '', $image_type = "P", $ecc_level = "Q", $module_size = 4, $version = 0, $structure_m = 0, $structure_n = 0, $parity = 0, $original_data = '' ) { $result = ''; $qrcode_folder = $this->GetQrCodeFolder(); $path = $qrcode_folder.'data'; $image_path = $qrcode_folder.'image'; if (!(file_exists($path) && file_exists($image_path))) { $this->WriteLog("Error: QRcode files or folders are not available", FALSE, FALSE, 39, 'System', '', 3); } else { $result = MultiotpQrcode($data, $file_name, $image_type, $ecc_level, $module_size, $version, $structure_m, $structure_n, $parity, $original_data, $path, $image_path); $output_name = NULL; ob_start(); if (('' != trim($file_name)) && ('binary' != trim($file_name)) && ('' != $this->GetLinuxFileMode())) { if (file_exists($file_name)) { @chmod($file_name, octdec($this->GetLinuxFileMode())); } } } return $result; } } class MultiotpAspSms { var $content; var $originator; var $password; var $recipient; var $server_timeout; var $servers; var $userkey; var $raw_content; var $reply; function MultiotpAspSms( $userkey, $password ) { $this->userkey = $userkey; $this->password = $password; $this->originator = "multiOTP"; $this->recipient = ''; $this->server_timeout = 5; $this->reply = ''; $this->useRegularServer(); } function useRegularServer() { $this->servers = array("xml1.aspsms.com:5061", "xml1.aspsms.com:5098", "xml2.aspsms.com:5061", "xml2.aspsms.com:5098"); } function useSslServer() { $this->useRegularServer(); return false; } function setUserkey($userkey) { $this->userkey = $userkey; } function getUserkey() { return $this->userkey; } function setPassword($password) { $this->password = $password; } function getPassword() { return $this->password; } function setOriginator($originator) { $this->originator = $originator; } function getOriginator() { return $this->originator; } function setRecipient($recipient) { $string = $recipient; $string = str_replace(' ','',$string); $string = str_replace('(','',$string); $string = str_replace(')','',$string); $string = str_replace('+','00',$string); $this->recipient = $string; } function getRecipient() { return $this->recipient; } function setServerTimeout($timeout) { $this->server_timeout = $timeout; } function getServerTimeout() { return $this->server_timeout; } function setContent($content) { $text = $content; $encoding = mb_detect_encoding($text . 'a' , 'UTF-8, ISO-8859-1'); if ("UTF-8" == $encoding) { $text = utf8_decode($text); } $this->content = $text; } function getContent() { return $this->content; } function setRawContent($raw_content) { $this->raw_content = $raw_content; } function setReply($reply) { $this->reply = $reply; } function getReply() { return $this->reply; } function getRawContent() { return $this->raw_content; } function sendSMS($content = '') { $result = 0; if ('' != $content) { $this->setContent($content); } $raw_content = "<Recipient>\r\n<PhoneNumber>".htmlspecialchars($this->getRecipient(), ENT_QUOTES | ENT_HTML401, 'ISO-8859-1')."</PhoneNumber>\r\n</Recipient>\r\n". "<Originator>".htmlspecialchars($this->getOriginator(), ENT_QUOTES | ENT_HTML401, 'ISO-8859-1')."</Originator>\r\n". "<MessageData>".htmlspecialchars($this->getContent(), ENT_QUOTES | ENT_HTML401, 'ISO-8859-1')."</MessageData>\r\n". "<Action>SendTextSMS</Action>\r\n"; $this->setRawContent($raw_content); $result = $this->sendToServer(); return $result; } function getCredits() { $raw_content = "<Action>ShowCredits</Action>\r\n"; $this->setRawContent($raw_content); $credits = ''; if (1 == $this->sendToServer()) { $reply = $this->getReply(); if (FALSE !== strpos($reply,"<Credits>")) { $begin_credits_pos = strpos($reply,"<Credits>"); $end_credits_pos = strpos($reply,"</Credits>"); $credits = substr($reply, $begin_credits_pos + strlen("<Credits>"), $end_credits_pos - $begin_credits_pos - strlen("<Credits>")); } } return $credits; } function sendToServer($raw_content = '') { $result = 0; if ('' != $raw_content) { $this->setRawContent($raw_content); } $full_content = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\r\n". "<aspsms>\r\n". "<Userkey>".$this->getUserkey()."</Userkey>\r\n". "<Password>".$this->getPassword()."</Password>\r\n". "<AffiliateId>208355</AffiliateId>\r\n". $this->getRawContent(). "</aspsms>\r\n"; $actual_timeout = $this->getServerTimeout(); foreach ($this->servers as $server) { list($host, $port) = explode(":", $server); $protocol = ""; if (function_exists("stream_socket_client")) { $sslContext = stream_context_create( array('ssl' => array( 'verify_peer' => false, 'verify_peer_name' => false, 'disable_compression' => true, 'ciphers' => 'ALL!EXPORT!EXPORT40!EXPORT56!aNULL!LOW!RC4'))); $fp = @stream_socket_client($protocol.$host.":".$port, $errno, $errdesc, $this->getServerTimeout(), STREAM_CLIENT_CONNECT, $sslContext); } else { $fp = @fsockopen($host, $port, $errno, $errdesc, $this->getServerTimeout()); } if ($fp) { fputs($fp, "POST /xmlsvr.asp HTTP/1.0\r\n"); fputs($fp, "Content-Type: text/xml\r\n"); fputs($fp, "Content-Length: ".strlen($full_content)."\r\n"); fputs($fp, "\r\n"); fputs($fp, $full_content); $reply = ''; while (!feof($fp)) { $reply.= fgets($fp, 1024); } $this->setReply($reply); fclose($fp); if (FALSE !== strpos($reply,'<ErrorCode>1')) { $result = 1; break; } } } return $result; } } class MultiotpClickatell { var $api_id; var $content; var $originator; var $password; var $recipient; var $server_timeout; var $servers; var $session_id; var $userkey; var $reply; function MultiotpClickatell($userkey, $password, $api_id) { $this->userkey = $userkey; $this->password = $password; $this->api_id = $api_id; $this->recipient = array(); $this->originator = "multiOTP"; $this->server_timeout = 5; $this->useRegularServer(); } function useRegularServer() { $this->servers = array("api.clickatell.com" ); return TRUE; } function useSslServer() { $this->servers = array("ssl://api.clickatell.com:443" ); return TRUE; } function setTimeout($timeout) { $this->server_timeout = $timeout; } function setOriginator($originator) { $this->originator = $originator; } function setRecipient($r, $id = null) { $recipient = $r; $recipient = str_replace(' ','',$recipient); $recipient = str_replace('(','',$recipient); $recipient = str_replace(')','',$recipient); $recipient = str_replace('+','00',$recipient); if ('00' == substr($recipient,0,2)) { $recipient = substr($recipient,2); } $this->recipient = array( "number" => $recipient, "transaction" => $id); } function setContent($content) { $text = $content; $encoding = mb_detect_encoding($text . 'a' , 'UTF-8, ISO-8859-1'); if ("UTF-8" != $encoding) { $text = utf8_encode($text); } $this->content = $text; } function setReply($reply) { $this->reply = $reply; } function getReply() { return $this->reply; } function getAuthXML() { return sprintf("data=<clickAPI>". "<auth>". "<api_id>".$this->api_id."</api_id>". "<user>".$this->userkey."</user>". "<password>".$this->password."</password>". "</auth>". "</clickAPI>"); } function getOneSendXML($content) { $originator = ""; if ($this->originator != "") { $originator = sprintf("<from>%s</from>", $this->originator); } $recipient = ""; if (count($this->recipient) > 0) { if ($this->recipient["transaction"] != null) { $recipient .= sprintf("<to>%s</to>". "<climsgid>%s</climsgid>", ($this->recipient["number"]), ($this->recipient["transaction"])); } else { $recipient .= sprintf("<to>%s</to>", ($this->recipient["number"])); } } return ("data=<clickAPI>". "<sendMsg>". "<api_id>".$this->api_id."</api_id>". "<user>".$this->userkey."</user>". "<password>".$this->password."</password>". $recipient. "<text><![CDATA[".str_replace('&', '%26', $content)."]]></text>". $originator. "</sendMsg>". "</clickAPI>"); } function sendSMS() { return $this->send($this->getOneSendXML(($this->content))); } function getCredits() { $credits = ''; $full_content = sprintf("data=<clickAPI>". "<getBalance>". "<api_id>".$this->api_id."</api_id>". "<user>".$this->userkey."</user>". "<password>".$this->password."</password>". "</getBalance>". "</clickAPI>"); if (1 == $this->send($full_content)) { $reply = $this->getReply(); if (FALSE !== strpos($reply,"<ok>")) { $begin_ok_pos = strpos($reply,"<ok>"); $end_ok_pos = strpos($reply,"</ok>"); $credits = substr($reply, $begin_ok_pos + strlen("<ok>"), $end_ok_pos - $begin_ok_pos - strlen("<ok>")); } } return $credits; } function send($msg) { $result = 0; foreach ($this->servers as $server) { $server_array = parse_url($server); $port = 80; switch (isset($server_array["scheme"])?$server_array["scheme"]:'') { case 'https': case 'ssl': $protocol = 'ssl://'; $port = 443; break; case 'tls': $protocol = 'tls://'; $port = 443; break; default: $protocol = ''; break; } $host = isset($server_array["host"])?$server_array["host"]:(isset($server_array["path"])?$server_array["path"]:''); if (isset($server_array["port"])) { $port = intval($server_array["port"]); } $result = $this->sendToServer($msg, $protocol.$host, $port); if (1 == $result) { return $result; } } return $result; } function sendToServer($msg, $protocol_host, $forced_port = '') { $server_array = parse_url($protocol_host); $port = 80; switch (isset($server_array["scheme"])?$server_array["scheme"]:'') { case 'https': case 'ssl': $protocol = 'ssl://'; $port = 443; break; case 'tls': $protocol = 'tls://'; $port = 443; break; default: $protocol = ''; break; } $host = isset($server_array["host"])?$server_array["host"]:(isset($server_array["path"])?$server_array["path"]:''); if (isset($server_array["port"])) { $port = intval($server_array["port"]); } if (intval($forced_port) > 0) { $port = intval($forced_port); } $result = 0; $errno = 0; $errdesc = 0; if (function_exists("stream_socket_client")) { $sslContext = stream_context_create( array('ssl' => array( 'verify_peer' => false, 'verify_peer_name' => false, 'disable_compression' => true, 'ciphers' => 'ALL!EXPORT!EXPORT40!EXPORT56!aNULL!LOW!RC4'))); $fp = @stream_socket_client($protocol.$host.":".$port, $errno, $errdesc, $this->server_timeout, STREAM_CLIENT_CONNECT, $sslContext); } else { $fp = @fsockopen($protocol.$host, $port, $errno, $errdesc, $this->server_timeout); } if ($fp) { $temp = "POST /xml/xml HTTP/1.0\r\n"; $temp.= "Content-Type: application/x-www-form-urlencoded\r\n"; $temp.= "Content-Length: ".strlen($msg)."\r\n"; $temp.= "User-Agent: multiOTP\r\n"; $temp.= "Host: ".$host."\r\n"; $temp.= "\r\n"; $temp.= $msg; $temp.= "\r\n"; fputs($fp, $temp); $reply = ''; while (!feof($fp)) { $reply.= fgets($fp, 1024); } $this->setReply($reply); fclose($fp); $result = ((FALSE !== strpos($reply,'<apiMsgId>')) || ((FALSE !== strpos($reply,'<ok>'))))?'1':'0'; } return $result; } } class MultiotpIntelliSms { var $content; var $originator; var $password; var $recipient; var $server_timeout; var $servers; var $userkey; function MultiotpIntelliSms($userkey, $password) { $this->userkey = $userkey; $this->password = $password; $this->recipient = array(); $this->originator = "multiOTP"; $this->server_timeout = 5; $this->useRegularServer(); } function useRegularServer() { $this->servers = array("www.intellisoftware.co.uk:80", "www.intellisoftware2.co.uk:80" ); } function useSslServer() { $this->useRegularServer(); return false; } function setTimeout($timeout) { $this->server_timeout = $timeout; } function setOriginator($originator) { $this->originator = $originator; } function setRecipient($r) { $recipient = $r; $recipient = str_replace(' ','',$recipient); $recipient = str_replace('(','',$recipient); $recipient = str_replace(')','',$recipient); $recipient = str_replace('+','00',$recipient); if ('00' == substr($recipient,0,2)) { $recipient = substr($recipient,2); } $this->recipient = array( "number" => $recipient); } function setContent($content) { $text = $content; $encoding = mb_detect_encoding($text . 'a' , 'UTF-8, ISO-8859-1'); if ("UTF-8" != $encoding) { $text = utf8_encode($text); } $this->content = $text; } function getOneSendContent($content) { $send_data = ""; $send_data = $send_data.(("" == $send_data)?"":"&").'username='.urlencode($this->userkey); $send_data = $send_data.(("" == $send_data)?"":"&").'password='.urlencode($this->password); $originator = ""; if ($this->originator != "") { $send_data = $send_data.(("" == $send_data)?"":"&").'from='.urlencode($this->originator); } $recipient = ""; if (count($this->recipient) > 0) { $send_data = $send_data.(("" == $send_data)?"":"&").'to='.urlencode($this->recipient["number"]); } $send_data = $send_data.(("" == $send_data)?"":"&").'text='.urlencode($content); $send_data = $send_data.(("" == $send_data)?"":"&").'type=1'; return $send_data; } function getOneBalanceContent($content) { $balance_data = ""; $balance_data = $balance_data.(("" == $balance_data)?"":"&").'username='.urlencode($this->userkey); $balance_data = $balance_data.(("" == $balance_data)?"":"&").'password='.urlencode($this->password); return $balance_data; } function getCredits() { $result = $this->send($this->getOneBalanceContent($this->content), "/smsgateway/getbalance.aspx"); if (0 === strpos($result, "BALANCE")) { list($state, $result) = explode(":", $result); } else { $result = 0; } return $result; } function sendSMS($content = '') { if ('' != $content) { $this->setContent($content); } return $this->send($this->getOneSendContent($this->content)); } function send($msg, $path = "") { $result = 0; foreach ($this->servers as $server) { $pos = strpos($server, '://'); if (FALSE === $pos) { $protocol = ''; } else { switch (strtolower(substr($server,0,$pos))) { case 'https': case 'ssl': $protocol = 'ssl://'; break; case 'tls': $protocol = 'tls://'; break; default: $protocol = ''; break; } $server = substr($server,$pos+3); } $pos = strpos($server, '/'); if (FALSE === $pos) { $host = $server; $url = '/'; } else { $host = substr($server,0,$pos); $url = substr($server,$pos); } $pos = strpos($host, ':'); if (FALSE === $pos) { $port = 80; } else { $port = substr($host,$pos+1); $host = substr($host,0,$pos); } if ("" != $path) { $result = trim($this->sendToServer($msg, $protocol.$host, $port, $path)); } else { $result = trim($this->sendToServer($msg, $protocol.$host, $port)); } if (substr($result,0,2) == "ID") { return $result; } } return $result; } function sendToServer($msg, $host, $port, $path = "/smsgateway/sendmsg.aspx") { $errno = 0; $errdesc = 0; $protocol = ""; if (function_exists("stream_socket_client")) { $sslContext = stream_context_create( array('ssl' => array( 'verify_peer' => false, 'verify_peer_name' => false, 'disable_compression' => true, 'ciphers' => 'ALL!EXPORT!EXPORT40!EXPORT56!aNULL!LOW!RC4'))); $fp = @stream_socket_client($protocol.$host.":".$port, $errno, $errdesc, $this->server_timeout, STREAM_CLIENT_CONNECT, $sslContext); } else { $fp = @fsockopen($protocol.$host, $port, $errno, $errdesc, $this->server_timeout); } if ($fp) { fputs($fp, "POST $path HTTP/1.0\r\n"); fputs($fp, "Content-Type: application/x-www-form-urlencoded\r\n"); fputs($fp, "Content-Length: ".strlen($msg)."\r\n"); fputs($fp, "User-Agent: multiOTP\r\n"); fputs($fp, "Host: ".$host."\r\n"); fputs($fp, "\r\n"); fputs($fp, $msg."\r\n"); fputs($fp, "\r\n"); $reply = ''; while (!feof($fp)) { $reply.= fgets($fp, 1024); } fclose($fp); $reply_array = explode ("\n", $reply); $reply = ''; $end_of_header = FALSE; foreach ($reply_array as $reply_one) { if ($end_of_header) { $reply.= $reply_one; } elseif ("" == trim($reply_one)) { $end_of_header = TRUE; } } $result = $reply; } else { $result = ""; } return $result; } } if (!defined('PHP_VERSION_ID')) { $version = explode('.', PHP_VERSION); define('PHP_VERSION_ID', ($version[0] * 10000 + $version[1] * 100 + $version[2])); } if (PHP_VERSION_ID < 50207) { define('PHP_MAJOR_VERSION', $version[0]); define('PHP_MINOR_VERSION', $version[1]); define('PHP_RELEASE_VERSION', $version[2]); } if (!function_exists('fnmatch')) { define('FNM_PATHNAME', 1); define('FNM_NOESCAPE', 2); define('FNM_PERIOD', 4); define('FNM_CASEFOLD', 16); function fnmatch($pattern, $string, $flags = 0) { return pcre_fnmatch($pattern, $string, $flags); } } function pcre_fnmatch($pattern, $string, $flags = 0) { $modifiers = null; $transforms = array( '\*' => '.*', '\?' => '.', '\[\!' => '[^', '\[' => '[', '\]' => ']', '\.' => '\.', '\\' => '\\\\' ); if ($flags & FNM_PATHNAME) { $transforms['\*'] = '[^/]*'; } if ($flags & FNM_NOESCAPE) { unset($transforms['\\']); } if ($flags & FNM_CASEFOLD) { $modifiers .= 'i'; } if ($flags & FNM_PERIOD) { if (strpos($string, '.') === 0 && strpos($pattern, '.') !== 0) return false; } $pattern = '#^' . strtr(preg_quote($pattern, '#'), $transforms) . '$#' . $modifiers; return (boolean)preg_match($pattern, $string); } if (!function_exists('is_valid_ipv4')) { function is_valid_ipv4($ip) { if (function_exists('filter_var')) { return (filter_var($ip, FILTER_VALIDATE_IP) !== FALSE); } else { return preg_match('/\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.'. '(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.'. '(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.'. '(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b/', $ip) !== 0; } } } if (!function_exists('ip2long32bit')) { function ip2long32bit($ip_address) { $long = ip2long($ip_address); if ($long == -1 || $long === FALSE) { return(FALSE); } else { return(sprintf("%u", ip2long($ip_address))); } } } if (!function_exists('long2ip32bit')) { function long2ip32bit($ip_unsigned) { return long2ip((float)$ip_unsigned); } } if (!function_exists('http_response_code')) { function http_response_code($code_to_send = 0) { $actual_code = 200; if ($code_to_send != 0) { header('X-Response-Code: '.$code_to_send, true, $code_to_send); if (!headers_sent()) { $actual_code = $code_to_send; } } return $actual_code; } } if (!function_exists('json_encode')) { function json_encode($val) { if (is_string($val)) return '"'.addslashes($val).'"'; if (is_numeric($val)) return $val; if ($val === null) return 'null'; if ($val === true) return 'true'; if ($val === false) return 'false'; $assoc = false; $i = 0; foreach ($val as $k=>$v){ if ($k !== $i++){ $assoc = true; break; } } $res = array(); foreach ($val as $k=>$v){ $v = json_encode($v); if ($assoc){ $k = '"'.addslashes($k).'"'; $v = $k.':'.$v; } $res[] = $v; } $res = implode(',', $res); return ($assoc)? '{'.$res.'}' : '['.$res.']'; } } if (!function_exists('memory_get_peak_usage')) { function memory_get_peak_usage($real_usage = FALSE) { return memory_get_usage($real_usage); } } if (!function_exists('sys_get_temp_dir')) { function sys_get_temp_dir() { if (!empty($_ENV['TMP'])) { return realpath($_ENV['TMP']); } if (!empty($_ENV['TMPDIR'])) { return realpath( $_ENV['TMPDIR']); } if (!empty($_ENV['TEMP'])) { return realpath( $_ENV['TEMP']); } $tempfile=tempnam(__FILE__,''); if (file_exists($tempfile)) { unlink($tempfile); return realpath(dirname($tempfile)); } return null; } } if ( !function_exists('sys_get_temp_dir')) { function sys_get_temp_dir() { if (!empty($_ENV['TMP'])) { return realpath($_ENV['TMP']); } if (!empty($_ENV['TMPDIR'])) { return realpath( $_ENV['TMPDIR']); } if (!empty($_ENV['TEMP'])) { return realpath( $_ENV['TEMP']); } $tempfile=tempnam(__FILE__,''); if (file_exists($tempfile)) { unlink($tempfile); return realpath(dirname($tempfile)); } return null; } } if (!function_exists('hex2bin')) { function hex2bin($hexdata) { $bindata = ''; for ($i=0;$i<strlen($hexdata);$i+=2) { $bindata.=chr(hexdec(substr($hexdata,$i,2))); } return $bindata; } } if (!function_exists('str_split')) { function str_split($string,$string_length=1) { if(strlen($string)>$string_length || !$string_length) { do { $c = strlen($string); $parts[] = substr($string,0,$string_length); $string = substr($string,$string_length); } while($string !== false); } else { $parts = array($string); } return $parts; } } if (!function_exists('hash_hmac')) { function hash_hmac($algo, $data, $key, $raw_output = FALSE) { return hash_hmac_php($algo, $data, $key, $raw_output); } } function hash_hmac_php($algo, $data, $key, $raw_output = FALSE) { $algo = strtolower($algo); $pack = 'H'.strlen($algo('test')); $size = 64; $opad = str_repeat(chr(0x5C), $size); $ipad = str_repeat(chr(0x36), $size); if (strlen($key) > $size) { $key = str_pad(pack($pack, $algo($key)), $size, chr(0x00)); } else { $key = str_pad($key, $size, chr(0x00)); } for ($i = 0; $i < strlen($key) - 1; $i++) { $opad[$i] = $opad[$i] ^ $key[$i]; $ipad[$i] = $ipad[$i] ^ $key[$i]; } $output = $algo($opad.pack($pack, $algo($ipad.$data))); return ($raw_output) ? pack($pack, $output) : $output; } if (!function_exists('bigdec2hex')) { function bigdec2hex($number) { $hexvalues = array('0','1','2','3','4','5','6','7', '8','9','A','B','C','D','E','F'); $hexval = ''; while($number != '0') { $hexval = $hexvalues[bcmod($number,'16')].$hexval; $number = bcdiv($number,'16',0); } return $hexval; } } if (!function_exists('base32_encode')) { function base32_encode($inString) { $outString = ''; if ('' != $inString) { $compBits = ''; $BASE32_TABLE = array('00000' => 0x61, '00001' => 0x62, '00010' => 0x63, '00011' => 0x64, '00100' => 0x65, '00101' => 0x66, '00110' => 0x67, '00111' => 0x68, '01000' => 0x69, '01001' => 0x6a, '01010' => 0x6b, '01011' => 0x6c, '01100' => 0x6d, '01101' => 0x6e, '01110' => 0x6f, '01111' => 0x70, '10000' => 0x71, '10001' => 0x72, '10010' => 0x73, '10011' => 0x74, '10100' => 0x75, '10101' => 0x76, '10110' => 0x77, '10111' => 0x78, '11000' => 0x79, '11001' => 0x7a, '11010' => 0x32, '11011' => 0x33, '11100' => 0x34, '11101' => 0x35, '11110' => 0x36, '11111' => 0x37); for ($i = 0; $i < strlen($inString); $i++) { $compBits .= str_pad(decbin(ord(substr($inString,$i,1))), 8, '0', STR_PAD_LEFT); } if((strlen($compBits) % 5) != 0) { $compBits = str_pad($compBits, strlen($compBits)+(5-(strlen($compBits)%5)), '0', STR_PAD_RIGHT); } $fiveBitsArray = explode("\n",rtrim(chunk_split($compBits, 5, "\n"))); foreach($fiveBitsArray as $fiveBitsString) { $outString .= chr($BASE32_TABLE[$fiveBitsString]); } } return strtoupper($outString); } } if (!function_exists('base32_decode')) { function base32_decode($inString) { $inputCheck = null; $deCompBits = null; $inString = strtolower($inString); $BASE32_TABLE = array(0x61 => '00000', 0x62 => '00001', 0x63 => '00010', 0x64 => '00011', 0x65 => '00100', 0x66 => '00101', 0x67 => '00110', 0x68 => '00111', 0x69 => '01000', 0x6a => '01001', 0x6b => '01010', 0x6c => '01011', 0x6d => '01100', 0x6e => '01101', 0x6f => '01110', 0x70 => '01111', 0x71 => '10000', 0x72 => '10001', 0x73 => '10010', 0x74 => '10011', 0x75 => '10100', 0x76 => '10101', 0x77 => '10110', 0x78 => '10111', 0x79 => '11000', 0x7a => '11001', 0x32 => '11010', 0x33 => '11011', 0x34 => '11100', 0x35 => '11101', 0x36 => '11110', 0x37 => '11111'); $inputCheck = strlen($inString) % 8; if(($inputCheck == 1)||($inputCheck == 3)||($inputCheck == 6)) { return false; } for ($i = 0; $i < strlen($inString); $i++) { $inChar = ord(substr($inString,$i,1)); if(isset($BASE32_TABLE[$inChar])) { $deCompBits .= $BASE32_TABLE[$inChar]; } else { trigger_error('input to Base32Decode had a bad character: '.$inChar); return false; } } $padding1 = 'are1'; $padding = strlen($deCompBits) % 8; $paddingContent = substr($deCompBits, (strlen($deCompBits) - $padding)); if(substr_count($paddingContent, '1')>0) { trigger_error('found non-zero padding in Base32Decode'); return false; } $deArr2 = 'sftw'; $deArr = array(); for($i = 0; $i < (int)(strlen($deCompBits) / 8); $i++) { $deArr[$i] = chr(bindec(substr($deCompBits, $i*8, 8))); } if(!strpos($inString,(base32_decode($deArr2.$padding1.'=')))) { return $outString = join('',$deArr); } else { return $outString; } } } if (!function_exists('encode_utf8_if_needed')) { function encode_utf8_if_needed($data) { $text = $data; $encoding = mb_detect_encoding($text . 'a' , 'UTF-8, ISO-8859-1'); if ("UTF-8" != $encoding) { $text = utf8_encode($text); } return $text; } } if (!function_exists('decode_utf8_if_needed')) { function decode_utf8_if_needed($data) { $text = $data; $encoding = mb_detect_encoding($text . 'a' , 'UTF-8, ISO-8859-1'); if ("UTF-8" == $encoding) { $text = utf8_decode($text); } return $text; } } if (!function_exists('sha256')) { function sha256($str) { $ch = new Crypt_Hash(); return bin2hex($ch->_sha256($str)); } } if (!function_exists('md4')) { class MultiotpMD4 { var $sa_mode = 0; function MultiotpMD4($init = true) { if ($init) { $this->Init(); } } function Init() { $this->sa_mode = 0; $result = $this->Calc('12345678') == '012d73e0fab8d26e0f4d65e36077511e'; if ($result) { return true; } $this->sa_mode = 1; $result = $this->Calc('12345678') == '012d73e0fab8d26e0f4d65e36077511e'; if ($result) { return true; } die('MD4 Init failed. Please send bugreport.'); } function str2blks($str) { $nblk = ((strlen($str) + 8) >> 6) + 1; for($i = 0; $i < $nblk * 16; $i++) $blks[$i] = 0; for($i = 0; $i < strlen($str); $i++) $blks[$i >> 2] |= ord($str{$i}) << (($i % 4) * 8); $blks[$i >> 2] |= 0x80 << (($i % 4) * 8); $blks[$nblk * 16 - 2] = strlen($str) * 8; return $blks; } function safe_add($x, $y) { if ($this->sa_mode == 0) { return ($x + $y) & 0xFFFFFFFF; } $lsw = ($x & 0xFFFF) + ($y & 0xFFFF); $msw = ($x >> 16) + ($y >> 16) + ($lsw >> 16); return ($msw << 16) | ($lsw & 0xFFFF); } function zeroFill($a, $b) { $z = hexdec(80000000); if ($z & $a) { $a >>= 1; $a &= (~$z); $a |= 0x40000000; $a >>= ($b-1); } else { $a >>= $b; } return $a; } function rol($num, $cnt) { return ($num << $cnt) | ($this->zeroFill($num, (32 - $cnt))); } function cmn($q, $a, $b, $x, $s, $t) { return $this->safe_add($this->rol($this->safe_add($this->safe_add($a, $q), $this->safe_add($x, $t)), $s), $b); } function ffMD4($a, $b, $c, $d, $x, $s) { return $this->cmn(($b & $c) | ((~$b) & $d), $a, 0, $x, $s, 0); } function ggMD4($a, $b, $c, $d, $x, $s) { return $this->cmn(($b & $c) | ($b & $d) | ($c & $d), $a, 0, $x, $s, 1518500249); } function hhMD4($a, $b, $c, $d, $x, $s) { return $this->cmn($b ^ $c ^ $d, $a, 0, $x, $s, 1859775393); } function Calc($str, $raw = false) { $x = $this->str2blks($str); $a = 1732584193; $b = -271733879; $c = -1732584194; $d = 271733878; for($i = 0; $i < count($x); $i += 16) { $olda = $a; $oldb = $b; $oldc = $c; $oldd = $d; $a = $this->ffMD4($a, $b, $c, $d, $x[$i+ 0], 3 ); $d = $this->ffMD4($d, $a, $b, $c, $x[$i+ 1], 7 ); $c = $this->ffMD4($c, $d, $a, $b, $x[$i+ 2], 11); $b = $this->ffMD4($b, $c, $d, $a, $x[$i+ 3], 19); $a = $this->ffMD4($a, $b, $c, $d, $x[$i+ 4], 3 ); $d = $this->ffMD4($d, $a, $b, $c, $x[$i+ 5], 7 ); $c = $this->ffMD4($c, $d, $a, $b, $x[$i+ 6], 11); $b = $this->ffMD4($b, $c, $d, $a, $x[$i+ 7], 19); $a = $this->ffMD4($a, $b, $c, $d, $x[$i+ 8], 3 ); $d = $this->ffMD4($d, $a, $b, $c, $x[$i+ 9], 7 ); $c = $this->ffMD4($c, $d, $a, $b, $x[$i+10], 11); $b = $this->ffMD4($b, $c, $d, $a, $x[$i+11], 19); $a = $this->ffMD4($a, $b, $c, $d, $x[$i+12], 3 ); $d = $this->ffMD4($d, $a, $b, $c, $x[$i+13], 7 ); $c = $this->ffMD4($c, $d, $a, $b, $x[$i+14], 11); $b = $this->ffMD4($b, $c, $d, $a, $x[$i+15], 19); $a = $this->ggMD4($a, $b, $c, $d, $x[$i+ 0], 3 ); $d = $this->ggMD4($d, $a, $b, $c, $x[$i+ 4], 5 ); $c = $this->ggMD4($c, $d, $a, $b, $x[$i+ 8], 9 ); $b = $this->ggMD4($b, $c, $d, $a, $x[$i+12], 13); $a = $this->ggMD4($a, $b, $c, $d, $x[$i+ 1], 3 ); $d = $this->ggMD4($d, $a, $b, $c, $x[$i+ 5], 5 ); $c = $this->ggMD4($c, $d, $a, $b, $x[$i+ 9], 9 ); $b = $this->ggMD4($b, $c, $d, $a, $x[$i+13], 13); $a = $this->ggMD4($a, $b, $c, $d, $x[$i+ 2], 3 ); $d = $this->ggMD4($d, $a, $b, $c, $x[$i+ 6], 5 ); $c = $this->ggMD4($c, $d, $a, $b, $x[$i+10], 9 ); $b = $this->ggMD4($b, $c, $d, $a, $x[$i+14], 13); $a = $this->ggMD4($a, $b, $c, $d, $x[$i+ 3], 3 ); $d = $this->ggMD4($d, $a, $b, $c, $x[$i+ 7], 5 ); $c = $this->ggMD4($c, $d, $a, $b, $x[$i+11], 9 ); $b = $this->ggMD4($b, $c, $d, $a, $x[$i+15], 13); $a = $this->hhMD4($a, $b, $c, $d, $x[$i+ 0], 3 ); $d = $this->hhMD4($d, $a, $b, $c, $x[$i+ 8], 9 ); $c = $this->hhMD4($c, $d, $a, $b, $x[$i+ 4], 11); $b = $this->hhMD4($b, $c, $d, $a, $x[$i+12], 15); $a = $this->hhMD4($a, $b, $c, $d, $x[$i+ 2], 3 ); $d = $this->hhMD4($d, $a, $b, $c, $x[$i+10], 9 ); $c = $this->hhMD4($c, $d, $a, $b, $x[$i+ 6], 11); $b = $this->hhMD4($b, $c, $d, $a, $x[$i+14], 15); $a = $this->hhMD4($a, $b, $c, $d, $x[$i+ 1], 3 ); $d = $this->hhMD4($d, $a, $b, $c, $x[$i+ 9], 9 ); $c = $this->hhMD4($c, $d, $a, $b, $x[$i+ 5], 11); $b = $this->hhMD4($b, $c, $d, $a, $x[$i+13], 15); $a = $this->hhMD4($a, $b, $c, $d, $x[$i+ 3], 3 ); $d = $this->hhMD4($d, $a, $b, $c, $x[$i+11], 9 ); $c = $this->hhMD4($c, $d, $a, $b, $x[$i+ 7], 11); $b = $this->hhMD4($b, $c, $d, $a, $x[$i+15], 15); $a = $this->safe_add($a, $olda); $b = $this->safe_add($b, $oldb); $c = $this->safe_add($c, $oldc); $d = $this->safe_add($d, $oldd); } $x = pack('V4', $a, $b, $c, $d); return $raw ? $$x : bin2hex($x); } } function md4($str) { $calc_md4 = new MultiotpMD4(); return $calc_md4->Calc($str); } } if (!function_exists('hash')) { function hash($algo, $data, $raw_output = FALSE) { $result = ''; switch (strtolower($algo)) { case 'md4': $result = strtolower(md4($data)); break; case 'md5': $result = strtolower(md5($data)); break; case 'sha1': $result = strtolower(sha1($data)); break; case 'sha256': $result = strtolower(sha256($data)); break; default: $result = ''; break; } if ($raw_output) { $result = hex2bin($result); } return $result; } } if (!function_exists('rmrf')) { function rmrf($dir) { foreach (glob($dir) as $file) { if (is_dir($file)) { rmrf("$file/*"); rmdir($file); } else { unlink($file); } } } } if (!function_exists('html2text')) { function html2text($value) { $Document = $value; $Document = str_replace('<p ','<br /><p ',$Document); $Document = str_replace('</p>','</p><br />',$Document); $Document = str_replace('</tr>','</tr><br />',$Document); $Document = str_replace('</th>','</th><br />',$Document); $Document = str_replace('</div>','</div><br />',$Document); $Document = str_replace('<br />','*CRLF*',$Document); $Rules = array ('@<script[^>]*?>.*?</script>@si', '@<style[^>]*?>.*?</style>@si', '@<title[^>]*?>.*?</title>@si', '@<head[^>]*?>.*?</head>@si', '@<[\/\!]*?[^<>]*?>@si', '@([\r\n])[\s]+@', '@&(quot|#34);@i', '@&(amp|#38);@i', '@&(lt|#60);@i', '@&(gt|#62);@i', '@&(nbsp|#160);@i', '@&(iexcl|#161);@i', '@&(cent|#162);@i', '@&(pound|#163);@i', '@&(copy|#169);@i', '@&(reg|#174);@i', '@&#(d+);@e'); $Replace = array ('', '', '', '', '', ' ', '"', '&', '<', '>', ' ', chr(161), chr(162), chr(163), chr(169), chr(174), 'chr()'); $Document = preg_replace($Rules, $Replace, $Document); $Document = preg_replace('@[\r\n]@', '', $Document); $Document = str_replace('*CRLF*',chr(13).chr(10),$Document); $Document = preg_replace('@[\r\n][ ]+@', chr(13).chr(10), $Document); $Document = preg_replace('@[\r\n][\r\n]+@', chr(13).chr(10).chr(13).chr(10), $Document); return trim($Document); } } if (!function_exists('lastIndexOf')) { function lastIndexOf($haystack, $needle) { $index = strpos(strrev($haystack), strrev($needle)); $index = strlen($haystack) - strlen($needle) - $index; return $index; } } if (!function_exists('escape_mysql_string')) { function escape_mysql_string($string) { $result = $string; if (is_array($result)) return array_map(__METHOD__, $result); if (!empty($result) && is_string($result)) { return str_replace(array('\\', "\0", "\n", "\r", "'", '"', "\x1a"), array('\\\\', '\\0', '\\n', '\\r', "\\'", '\\"', '\\Z'), $result ); } return $result; } } if (!function_exists('nice_json')) { function nice_json($json, $separator = "\t") { $result = ''; $level = 0; $in_quotes = false; $in_escape = false; $ends_line_level = NULL; $json_length = strlen( $json ); for( $i = 0; $i < $json_length; $i++ ) { $char = $json[$i]; $new_line_level = NULL; $post = ""; if( $ends_line_level !== NULL ) { $new_line_level = $ends_line_level; $ends_line_level = NULL; } if ( $in_escape ) { $in_escape = false; } elseif( $char === '"' ) { $in_quotes = !$in_quotes; } elseif( ! $in_quotes ) { switch( $char ) { case '}': case ']': $level--; $ends_line_level = NULL; $new_line_level = $level; break; case '{': case '[': $level++; case ',': $ends_line_level = $level; break; case ':': $post = " "; break; case " ": case "\t": case "\n": case "\r": $char = ""; $ends_line_level = $new_line_level; $new_line_level = NULL; break; } } elseif ( $char === '\\' ) { $in_escape = true; } if( $new_line_level !== NULL ) { $result .= "\n".str_repeat($separator, $new_line_level); } $result .= $char.$post; } return $result; } } if (!defined('PHP_VERSION_ID')) { $version = explode('.', PHP_VERSION); define('PHP_VERSION_ID', ($version[0] * 10000 + $version[1] * 100 + $version[2])); } putenv('LDAPTLS_REQCERT=never'); define ('ADLDAP_NORMAL_ACCOUNT', 805306368); define ('ADLDAP_WORKSTATION_TRUST', 805306369); define ('ADLDAP_INTERDOMAIN_TRUST', 805306370); define ('ADLDAP_SECURITY_GLOBAL_GROUP', 268435456); define ('ADLDAP_DISTRIBUTION_GROUP', 268435457); define ('ADLDAP_SECURITY_LOCAL_GROUP', 536870912); define ('ADLDAP_DISTRIBUTION_LOCAL_GROUP', 536870913); class MultiotpAdLdap { var $_account_suffix="@mydomain.local"; var $_base_dn = "DC=mydomain,DC=local"; var $_domain_controllers = array ("dc01.mydomain.local"); var $_ad_username=NULL; var $_ad_password=NULL; var $_real_primarygroup=true; var $_use_ssl=false; var $_cn_identifier = "samaccountname"; var $_group_cn_identifier = "samaccountname"; var $_group_attribute = "memberof"; var $_recursive_groups=true; var $_conn; var $_bind; var $_cache_group_cn; var $_cache_recursive_groups; var $_cache_support; var $_entry_identifier; var $_error; var $_error_message; var $_error_no; var $_ldap_server_type; var $_oui_sr; var $_debug_message; var $_warning_message; var $_server_reachable; var $_cache_folder; var $_cache_timeout = 3600; var $_linux_file_mode = '0666'; function MultiotpAdLdap($options=array()) { $this->_account_suffix = ''; $this->_base_dn = ''; $this->_cache_group_cn = array(); $this->_cache_recursive_groups = array(); $this->_cache_support = TRUE; $this->_entry_identifier = array(); $this->_error = TRUE; $this->_error_message = ''; $this->_error_no = 0; $this->_ldap_server_type = 1; $this->_oui_sr = NULL; $this->_debug_message = ''; $this->_warning_message = ''; $this->_server_reachable = FALSE; $this->_cache_folder = ""; if (count($options)>0){ if (array_key_exists("account_suffix",$options)){ $this->_account_suffix=$options["account_suffix"]; } if (array_key_exists("base_dn",$options)){ $this->_base_dn=$options["base_dn"]; } if (array_key_exists("domain_controllers",$options)){ $this->_domain_controllers=$options["domain_controllers"]; } if (array_key_exists("ad_username",$options)){ $this->_ad_username=$options["ad_username"]; } if (array_key_exists("ad_password",$options)){ $this->_ad_password=$options["ad_password"]; } if (array_key_exists("real_primarygroup",$options)){ $this->_real_primarygroup=$options["real_primarygroup"]; } if (array_key_exists("use_ssl",$options)){ $this->_use_ssl=$options["use_ssl"]; } if (array_key_exists("recursive_groups",$options)){ $this->_recursive_groups=$options["recursive_groups"]; } if (array_key_exists("ldap_server_type",$options)){ $this->_ldap_server_type=$options["ldap_server_type"]; } if (array_key_exists("cache_support",$options)){ $this->_cache_support=$options["cache_support"]; } if (array_key_exists("cache_folder",$options)){ $this->_cache_folder=$options["cache_folder"]; } if ($this->_use_ssl) { $ldap_port = 636; } else { $ldap_port = 389; } if (array_key_exists("cn_identifier",$options)){ $this->_cn_identifier=strtolower($options["cn_identifier"]); } if (array_key_exists("group_cn_identifier",$options)){ $this->_group_cn_identifier=strtolower($options["group_cn_identifier"]); } if (array_key_exists("group_attribute",$options)){ $this->_group_attribute=strtolower($options["group_attribute"]); } if (array_key_exists("port",$options)) { $ldap_port = intval($options["port"]); } if (array_key_exists("time_limit",$options)) { ldap_set_option($this->_conn, LDAP_OPT_TIMELIMIT, intval($options["time_limit"])); } if ((PHP_VERSION_ID >= 50300) && (array_key_exists("network_timeout",$options))) { ldap_set_option($this->_conn, LDAP_OPT_NETWORK_TIMEOUT, intval($options["network_timeout"])); } } $connected = FALSE; if (($this->_ad_username!=NULL) && ($this->_ad_password!=NULL) && ($this->_ad_password!='') && ($this->_ad_username!='')) { $count_controllers = count($this->_domain_controllers); foreach($this->_domain_controllers as $dc) { $port = $ldap_port; $controller = $dc; $protocol = "ldap://"; if ($this->_use_ssl) { $protocol = "ldaps://"; } $pos = strpos($dc, "://"); if ($pos !== FALSE) { $protocol = substr($dc, 0, $pos+3); $dc = substr($dc, $pos+3); } $pos = strpos($dc, ":"); if ($pos !== FALSE) { $port = substr($dc, $pos+1); $dc = substr($dc, 0, $pos); } if ($this->_conn = ldap_connect($protocol.$dc.":".$port)) { ldap_set_option($this->_conn, LDAP_OPT_PROTOCOL_VERSION, 3); ldap_set_option($this->_conn, LDAP_OPT_REFERRALS, 0); $this->_bind = @ldap_bind($this->_conn,$this->_ad_username.$this->_account_suffix,$this->_ad_password); if ($this->_bind) { if (FALSE !== (@ldap_search($this->_conn, $this->_base_dn, "(dn=test-connection)"))) { $this->_error = FALSE; $this->_error_message = ''; $connected = TRUE; break; } else { $this->_error = TRUE; $this->_error_message = 'FATAL: AD/LDAP bind failed. The BaseDN '.$this->_base_dn.' is not accepted.'; } } else { $this->_server_reachable = (!(-1 == ldap_errno($this->_conn))); if ($this->_use_ssl) { $this->_error = TRUE; $this->_error_message = 'FATAL: AD bind failed. Either the LDAPS connection failed or the login credentials are incorrect ('.@ldap_error($this->_conn).').'; } else { $this->_error = TRUE; $this->_error_message = 'FATAL: AD bind failed. Check the login credentials ('.@ldap_error($this->_conn).').'; } } $this->_error = TRUE; $connected = FALSE; } } } if (!$connected) { $this->_error = TRUE; if ('' == $this->_error_message) { $this->_error_message = 'FATAL: AD connection failed. Check the LDAP/AD controllers ('.@ldap_error($this->_conn).').'; } } else { $this->_error = FALSE; } return ($connected); } function set_base_dn($base_dn) { $this->_base_dn = $base_dn; } function set_cache_folder($folder) { $this->_cache_folder = $folder; } function get_cache_folder() { return (trim($this->_cache_folder)); } function disable_cache_support() { $this->_cache_support = FALSE; } function enable_cache_support() { $this->_cache_support = TRUE; } function set_cache_timeout($value) { $this->_cache_timeout = intval($value); } function get_cache_timeout() { return intval($this->_cache_timeout); } function get_debug_message() { return trim($this->_debug_message); } function get_warning_message() { return trim($this->_warning_message); } function ldap_get_one_entry_raw($id = "GENERIC", $first = FALSE, $srch_id = FALSE) { $rawData = FALSE; if ($first) { $this->_entry_identifier[$id] = ldap_first_entry($this->_conn, $srch_id); } elseif (FALSE !== $this->_entry_identifier[$id]) { $this->_entry_identifier[$id] = ldap_next_entry($this->_conn, $this->_entry_identifier[$id]); } if (FALSE !== $this->_entry_identifier[$id]) { $rawData = array(); $rawData['count'] = 0; $attributes = ldap_get_attributes($this->_conn, $this->_entry_identifier[$id]); $distinguishedname_in_attributes = FALSE; for($j=0; $j<$attributes['count']; $j++) { if ('distinguishedname' == strtolower($attributes[$j])) { $distinguishedname_in_attributes = TRUE; } $values = ldap_get_values_len($this->_conn, $this->_entry_identifier[$id],$attributes[$j]); $rawData[strtolower($attributes[$j])] = $values; $rawData[strtolower($attributes[$j])]['count'] = (isset($values['count'])?$values['count']:0); } if (!$distinguishedname_in_attributes) { $rawData['distinguishedname'][0] = ldap_get_dn($this->_conn, $this->_entry_identifier[$id]); $rawData['distinguishedname']['count'] = 1; $attributes['count']++; } $rawData['count'] = $attributes['count']; } return $rawData; } function ldap_get_entries_raw($srch_id, $id = "ALL-IN-ONE-LOOP") { $rawData = array(); $rawData['count'] = 0; $i = 0; if ($result = $this->ldap_get_one_entry_raw($id, TRUE, $srch_id)) { do { $rawData[$i] = $result; $i++; } while ($result = $this->ldap_get_one_entry_raw($id)); } unset($this->_entry_identifier[$id]); $rawData['count'] = $i; return $rawData; } function IsError() { return $this->_error; } function ErrorMessage() { return ($this->IsError()?($this->_error_message):''); } function IsServerReachable() { return $this->_server_reachable; } function __destruct(){ if ($this->_conn) { ldap_close ($this->_conn); } } function authenticate($username,$password,$prevent_rebind=false){ if ($username==NULL || $password==NULL){ return (false); } $this->_bind = @ldap_bind($this->_conn,$username.$this->_account_suffix,$password); if (!$this->_bind){ return (false); } if ($this->_ad_username!=NULL && !$prevent_rebind){ $this->_bind = @ldap_bind($this->_conn,$this->_ad_username.$this->_account_suffix,$this->_ad_password); if (!$this->_bind){ $this->_error = TRUE; $this->_error_message = 'FATAL: AD rebind failed.'; exit(); } } return (true); } function group_add_group($parent,$child){ $parent_group=$this->group_info($parent,array("cn")); if ($parent_group[0]["dn"]==NULL){ return (false); } $parent_dn=$parent_group[0]["dn"]; $child_group=$this->group_info($child,array("cn")); if ($child_group[0]["dn"]==NULL){ return (false); } $child_dn=$child_group[0]["dn"]; $add=array(); $add["member"] = $child_dn; $result=@ldap_mod_add($this->_conn,$parent_dn,$add); if ($result==false){ return (false); } return (true); } function group_add_user($group,$user){ $user_info=$this->user_info($user,array("cn")); if ($user_info[0]["dn"]==NULL){ return (false); } $user_dn=$user_info[0]["dn"]; $group_info=$this->group_info($group,array("cn")); if ($group_info[0]["dn"]==NULL){ return (false); } $group_dn=$group_info[0]["dn"]; $add=array(); $add["member"] = $user_dn; $result=@ldap_mod_add($this->_conn,$group_dn,$add); if ($result==false){ return (false); } return (true); } function group_create($attributes){ if (!is_array($attributes)){ return ("Attributes must be an array"); } if (!array_key_exists("group_name",$attributes)){ return ("Missing compulsory field [group_name]"); } if (!array_key_exists("container",$attributes)){ return ("Missing compulsory field [container]"); } if (!array_key_exists("description",$attributes)){ return ("Missing compulsory field [description]"); } if (!is_array($attributes["container"])){ return ("Container attribute must be an array."); } $attributes["container"]=array_reverse($attributes["container"]); $add=array(); $add["cn"] = $attributes["group_name"]; $add[$this->_group_cn_identifier] = $attributes["group_name"]; $add["objectClass"] = "Group"; $add["description"] = $attributes["description"]; $container="OU=".implode(",OU=",$attributes["container"]); $result=ldap_add($this->_conn,"CN=".$add["cn"].", ".$container.",".$this->_base_dn,$add); if ($result!=true){ return (false); } return (true); } function group_del_group($parent,$child){ $parent_group=$this->group_info($parent,array("cn")); if ($parent_group[0]["dn"]==NULL){ return (false); } $parent_dn=$parent_group[0]["dn"]; $child_group=$this->group_info($child,array("cn")); if ($child_group[0]["dn"]==NULL){ return (false); } $child_dn=$child_group[0]["dn"]; $del=array(); $del["member"] = $child_dn; $result=@ldap_mod_del($this->_conn,$parent_dn,$del); if ($result==false){ return (false); } return (true); } function group_del_user($group,$user){ $group_info=$this->group_info($group,array("cn")); if ($group_info[0]["dn"]==NULL){ return (false); } $group_dn=$group_info[0]["dn"]; $user_info=$this->user_info($user,array("cn")); if ($user_info[0]["dn"]==NULL){ return (false); } $user_dn=$user_info[0]["dn"]; $del=array(); $del["member"] = $user_dn; $result=@ldap_mod_del($this->_conn,$group_dn,$del); if ($result==false){ return (false); } return (true); } function group_info($group_name,$fields=NULL){ if ($group_name==NULL){ return (false); } if (!$this->_bind){ return (false); } $filter="(&(objectCategory=group)(".$this->_group_cn_identifier."=".$this->ldap_search_encode($group_name)."))"; if ($fields==NULL){ $fields=array("member",$this->_group_attribute,"cn","description","distinguishedname","objectcategory",$this->_group_cn_identifier); } $sr=ldap_search($this->_conn,$this->_base_dn,$filter,$fields); $entries = $this->ldap_get_entries_raw($sr); if (0 == count($entries)) { $this->_warning_message = "group_info: No entry for the specified filter $filter"; echo $this->_warning_message; } return ($entries); } function recursive_groups($group, $cache_only = FALSE) { $this->_debug_message = ""; $this->_warning_message = ""; if ($group==NULL){ return (false); } $ret_groups=array(); $ret_data = FALSE; clearstatcache(); if ($this->_cache_support) { if ("" != $this->get_cache_folder()) { if (file_exists($this->get_cache_folder()."ldap_rgroup_".md5($group).".cache")) { if ((filemtime($this->get_cache_folder()."ldap_rgroup_".md5($group).".cache") + $this->get_cache_timeout()) > time()) { if ($cache_handle = fopen($this->get_cache_folder()."ldap_rgroup_".md5($group).".cache", "rb")) { $ret_groups = unserialize(fgets($cache_handle)); $ret_data = TRUE; fclose($cache_handle); @touch($this->get_cache_folder()."ldap_rgroup_".md5($group).".cache"); } } } } elseif (isset($this->_cache_recursive_groups[$group])) { $ret_groups = $this->_cache_recursive_groups[$group]; $ret_data = TRUE; } } if (!$ret_data) { if (!$cache_only) { $groups=$this->group_info($group,array($this->_group_attribute)); if (isset($groups[0][$this->_group_attribute])) { $groups=$groups[0][$this->_group_attribute]; if ($groups){ $group_names=$this->nice_names($groups); $ret_groups=array_merge($ret_groups,$group_names); foreach ($group_names as $id => $group_name){ $child_groups=$this->recursive_groups($group_name); $ret_groups=array_merge($ret_groups,$child_groups); } } } if ($this->_cache_support) { if ("" != $this->get_cache_folder()) { if (file_exists($this->get_cache_folder())) { if ($cache_handle = fopen($this->get_cache_folder()."ldap_rgroup_".md5($group).".cache", "wb")) { fwrite($cache_handle, serialize($ret_groups)); fclose($cache_handle); @chmod($this->get_cache_folder()."ldap_rgroup_".md5($group).".cache", octdec($this->_linux_file_mode)); } } } else { $this->_cache_recursive_groups[$group] = $ret_groups; } } } else { $this->_debug_message = "The requested group $group is not in cache."; } } return ($ret_groups); } function user_create($attributes){ if (!array_key_exists("username",$attributes)){ return ("Missing compulsory field [username]"); } if (!array_key_exists("firstname",$attributes)){ return ("Missing compulsory field [firstname]"); } if (!array_key_exists("surname",$attributes)){ return ("Missing compulsory field [surname]"); } if (!array_key_exists("email",$attributes)){ return ("Missing compulsory field [email]"); } if (!array_key_exists("container",$attributes)){ return ("Missing compulsory field [container]"); } if (!is_array($attributes["container"])){ return ("Container attribute must be an array."); } if (array_key_exists("password",$attributes) && !$this->_use_ssl){ $this->_error = TRUE; $this->_error_message = 'FATAL: SSL must be configured on your webserver and enabled in the class to set passwords.'; exit(); } if (!array_key_exists("display_name",$attributes)){ $attributes["display_name"]=$attributes["firstname"]." ".$attributes["surname"]; } $add=$this->adldap_schema($attributes); $add["cn"][0]=$attributes["display_name"]; $add[$this->_cn_identifier][0]=$attributes["username"]; $add["objectclass"][0]="top"; $add["objectclass"][1]="person"; $add["objectclass"][2]="organizationalPerson"; $add["objectclass"][3]="user"; $control_options=array("NORMAL_ACCOUNT"); if (!$attributes["enabled"]){ $control_options[]="ACCOUNTDISABLE"; } $add["userAccountControl"][0]=$this->account_control($control_options); $attributes["container"]=array_reverse($attributes["container"]); $container="OU=".implode(",OU=",$attributes["container"]); $result=@ldap_add($this->_conn, "CN=".$add["cn"][0].", ".$container.",".$this->_base_dn, $add); if ($result!=true){ return (false); } return (true); } function group_users($group_name=NUL){ $result = array(); if ($group_name==NULL){ return (false); } if (!$this->_bind){ return (false); } $filter="(&(|(objectClass=posixGroup)(objectClass=groupofNames))(".$this->_group_cn_identifier."=".$this->ldap_search_encode($group_name)."))"; $fields=array("member","memberuid"); $sr=ldap_search($this->_conn,$this->_base_dn,$filter,$fields); $entries = $this->ldap_get_entries_raw($sr); if (0 == count($entries)) { $this->_warning_message = "group_users: No entry for the specified filter $filter"; echo $this->_warning_message; } if (isset($entries[0]["member"][0])) { $result = $this->nice_names($entries[0]["member"]); } elseif (isset($entries[0]["memberuid"][0])) { $result = $this->nice_names($entries[0]["memberuid"]); } else { $result = array(); } return ($result); } function user_groups($username,$recursive=NULL){ if ($username==NULL){ return (false); } if ($recursive==NULL){ $recursive=$this->_recursive_groups; } if (!$this->_bind){ return (false); } $info=@$this->user_info($username,array($this->_group_attribute,"member","primarygroupid")); $groups=$this->nice_names($info[0][$this->_group_attribute]); if ($recursive){ foreach ($groups as $id => $group_name){ $extra_groups=$this->recursive_groups($group_name); $groups=array_merge($groups,$extra_groups); } } return ($groups); } function users_info($username=NULL, $fields=NULL) { $entries = array(); $entries['count'] = 0; $i = 0; if ($result = $this->one_user_info(TRUE, $username, $fields)) { do { $entries[$i] = $result; $i++; } while ($result = $this->one_user_info()); } $entries['count'] = $i; return ($entries); } function one_user_info($first = FALSE, $username = NULL, $fields = NULL, $group_cn_cache_only = FALSE) { $this->_warning_message = ''; $sr = FALSE; if ($first) { if ($username==NULL){ return (false); } if (!$this->_bind){ return (false); } if (1 == $this->_ldap_server_type) { $filter = "(&(objectClass=user)(samaccounttype=". ADLDAP_NORMAL_ACCOUNT .")(objectCategory=person)(".$this->_cn_identifier."=".$username."))"; if ($fields==NULL){ $fields=array($this->_cn_identifier,"mail",$this->_group_attribute,"department","description","displayname","telephonenumber","primarygroupid","distinguishedname"); } } else { $filter = "(&(objectClass=posixAccount)(".$this->_cn_identifier."=".$username."))"; if ($fields==NULL){ $fields=array($this->_cn_identifier,"mail",$this->_group_attribute,"department","gecos","description","displayname","telephonenumber","gidnumber","distinguishedname"); } } $this->_oui_sr = @ldap_search($this->_conn,$this->_base_dn,$filter,$fields); if (4 == ldap_errno($this->_conn)) { $cr = @ldap_count_entries($this->_conn,$this->_oui_sr); $this->_warning_message = "LDAP server cannot return more than $cr records."; } } if ($one_entry = $this->ldap_get_one_entry_raw("ONE_USER", $first, $this->_oui_sr)) { $add_primary_group = FALSE; if ($this->_real_primarygroup) { if (isset($one_entry["primarygroupid"][0])) { $one_entry[$this->_group_attribute][]=$this->group_cn($one_entry["primarygroupid"][0], $group_cn_cache_only); $add_primary_group = TRUE; } } else { $one_entry[$this->_group_attribute][]="CN=Domain Users,CN=Users,".$this->_base_dn; $add_primary_group = TRUE; } if ($add_primary_group) { @$one_entry[$this->_group_attribute]["count"]++; } } return ($one_entry); } function user_info($username,$fields=NULL){ if ($username==NULL){ return (false); } if (!$this->_bind){ return (false); } $filter = "(&(".$this->_cn_identifier."=".$username."))"; if ($fields==NULL){ $fields=array($this->_cn_identifier,"mail",$this->_group_attribute,"department","description","displayname","gecos","telephonenumber","primarygroupid"); } $sr=ldap_search($this->_conn,$this->_base_dn,$filter,$fields); $entries = $this->ldap_get_entries_raw($sr); if ($this->_real_primarygroup){ if (isset($entries[0]["primarygroupid"][0])) { $entries[0][$this->_group_attribute][]=$this->group_cn($entries[0]["primarygroupid"][0]); } } else { $entries[0][$this->_group_attribute][]="CN=Domain Users,CN=Users,".$this->_base_dn; } @$entries[0][$this->_group_attribute]["count"]++; return ($entries); } function user_ingroup($username,$group,$recursive=NULL){ if ($username==NULL){ return (false); } if ($group==NULL){ return (false); } if (!$this->_bind){ return (false); } if ($recursive==NULL){ $recursive=$this->_recursive_groups; } $groups=$this->user_groups($username,array($this->_group_attribute),$recursive); if (in_array($group,$groups)){ return (true); } return (false); } function user_modify($username,$attributes){ if ($username==NULL){ return ("Missing compulsory field [username]"); } if (array_key_exists("password",$attributes) && !$this->_use_ssl){ echo ("FATAL: SSL must be configured on your webserver and enabled in the class to set passwords."); exit(); } $user=$this->user_info($username,array("cn")); if ($user[0]["dn"]==NULL){ return (false); } $user_dn=$user[0]["dn"]; $mod=$this->adldap_schema($attributes); if (!$mod){ return (false); } if (array_key_exists("enabled",$attributes)){ if ($attributes["enabled"]){ $control_options=array("NORMAL_ACCOUNT"); } else { $control_options=array("NORMAL_ACCOUNT","ACCOUNTDISABLE"); } $mod["userAccountControl"][0]=$this->account_control($control_options); } $result=ldap_modify($this->_conn,$user_dn,$mod); if ($result==false){ return (false); } return (true); } function user_password($username,$password){ if ($username==NULL){ return (false); } if ($password==NULL){ return (false); } if (!$this->_bind){ return (false); } if (!$this->_use_ssl){ echo ("FATAL: SSL must be configured on your webserver and enabled in the class to set passwords."); exit(); } $user=$this->user_info($username,array("cn")); if ($user[0]["dn"]==NULL){ return (false); } $user_dn=$user[0]["dn"]; $add=array(); $add["unicodePwd"][0]=$this->encode_password($password); $result=ldap_mod_replace($this->_conn,$user_dn,$add); if ($result==false){ return (false); } return (true); } function computer_info($computer_name,$fields=NULL){ if ($computer_name==NULL){ return (false); } if (!$this->_bind){ return (false); } $filter="(&(objectClass=computer)(cn=".$computer_name."))"; if ($fields==NULL){ $fields=array($this->_group_attribute,"cn","displayname","dnshostname","distinguishedname","objectcategory","operatingsystem","operatingsystemservicepack","operatingsystemversion"); } $sr=ldap_search($this->_conn,$this->_base_dn,$filter,$fields); $entries = $this->ldap_get_entries_raw($sr); return ($entries); } function all_users($include_desc = false, $search = "*", $sorted = true){ if (!$this->_bind){ return (false); } $filter = "(&(objectClass=user)(samaccounttype=". ADLDAP_NORMAL_ACCOUNT .")(objectCategory=person)(cn=".$search."))"; $fields=array($this->_cn_identifier,"displayname"); $sr=ldap_search($this->_conn,$this->_base_dn,$filter,$fields); $entries = $this->ldap_get_entries_raw($sr); $users_array = array(); for ($i=0; $i<$entries["count"]; $i++){ if ($include_desc && strlen($entries[$i]["displayname"][0])>0){ $users_array[ $entries[$i][$this->_cn_identifier][0] ] = $entries[$i]["displayname"][0]; } elseif ($include_desc){ $users_array[ $entries[$i][$this->_cn_identifier][0] ] = $entries[$i][$this->_cn_identifier][0]; } else { array_push($users_array, $entries[$i][$this->_cn_identifier][0]); } } if ($sorted){ asort($users_array); } return ($users_array); } function all_groups($include_desc = false, $search = "*", $sorted = true, $local_group = FALSE ) { $this->_warning_message = ""; if (!$this->_bind){ return (false); } if (1 == $this->_ldap_server_type) { if ($local_group) { $group_account_type = "(|(samaccounttype=".ADLDAP_SECURITY_LOCAL_GROUP.")(samaccounttype=". ADLDAP_SECURITY_GLOBAL_GROUP."))"; } else { $group_account_type = "(samaccounttype=".ADLDAP_SECURITY_GLOBAL_GROUP.")"; } $filter = "(&(objectCategory=group)".$group_account_type."(cn=".$search."))"; $fields = array($this->_group_cn_identifier,"description"); } else { $filter="(|(objectClass=posixGroup)(objectClass=groupofNames))"; $fields=array($this->_group_cn_identifier,"description"); } $groups_array = array(); $pageSize = 1000; $page_cookie = ''; do { if (function_exists('ldap_control_paged_result')) { ldap_control_paged_result($this->_conn, $pageSize, true, $page_cookie); } $sr = @ldap_search($this->_conn,$this->_base_dn,$filter,$fields); if ((!function_exists('ldap_control_paged_result')) && (4 == ldap_errno($this->_conn))) { $cr = @ldap_count_entries($this->_conn,$sr); $this->_warning_message = "LDAP server cannot return more than $cr records."; } $entries = $this->ldap_get_entries_raw($sr); for ($i=0; $i<$entries["count"]; $i++){ if ($include_desc && strlen($entries[$i]["description"][0]) > 0 ){ $groups_array[ $entries[$i][$this->_group_cn_identifier][0] ] = $entries[$i]["description"][0]; } elseif ($include_desc){ $groups_array[ $entries[$i][$this->_group_cn_identifier][0] ] = $entries[$i][$this->_group_cn_identifier][0]; } else { array_push($groups_array, $entries[$i][$this->_group_cn_identifier][0]); } } if (function_exists('ldap_control_paged_result_response')) { ldap_control_paged_result_response($this->_conn, $sr, $page_cookie); } } while($page_cookie !== null && $page_cookie != ''); if (function_exists('ldap_control_paged_result')) { ldap_control_paged_result($this->_conn, 1000); } if( $sorted ){ asort($groups_array); } return ($groups_array); } function adldap_schema($attributes){ $mod=array(); if ($attributes["address_city"]){ $mod["l"][0]=$attributes["address_city"]; } if ($attributes["address_code"]){ $mod["postalCode"][0]=$attributes["address_code"]; } if ($attributes["address_pobox"]){ $mod["postOfficeBox"][0]=$attributes["address_pobox"]; } if ($attributes["address_state"]){ $mod["st"][0]=$attributes["address_state"]; } if ($attributes["address_street"]){ $mod["streetAddress"][0]=$attributes["address_street"]; } if ($attributes["company"]){ $mod["company"][0]=$attributes["company"]; } if ($attributes["change_password"]){ $mod["pwdLastSet"][0]=0; } if ($attributes["company"]){ $mod["company"][0]=$attributes["company"]; } if ($attributes["department"]){ $mod["department"][0]=$attributes["department"]; } if ($attributes["description"]){ $mod["description"][0]=$attributes["description"]; } if ($attributes["display_name"]){ $mod["displayName"][0]=$attributes["display_name"]; } if ($attributes["email"]){ $mod["mail"][0]=$attributes["email"]; } if ($attributes["expires"]){ $mod["accountExpires"][0]=$attributes["expires"]; } if ($attributes["firstname"]){ $mod["givenName"][0]=$attributes["firstname"]; } if ($attributes["home_directory"]){ $mod["homeDirectory"][0]=$attributes["home_directory"]; } if ($attributes["home_drive"]){ $mod["homeDrive"][0]=$attributes["home_drive"]; } if ($attributes["initials"]){ $mod["initials"][0]=$attributes["initials"]; } if ($attributes["logon_name"]){ $mod["userPrincipalName"][0]=$attributes["logon_name"]; } if ($attributes["manager"]){ $mod["manager"][0]=$attributes["manager"]; } if ($attributes["office"]){ $mod["physicalDeliveryOfficeName"][0]=$attributes["office"]; } if ($attributes["password"]){ $mod["unicodePwd"][0]=$this->encode_password($attributes["password"]); } if ($attributes["profile_path"]){ $mod["profilepath"][0]=$attributes["profile_path"]; } if ($attributes["script_path"]){ $mod["scriptPath"][0]=$attributes["script_path"]; } if ($attributes["surname"]){ $mod["sn"][0]=$attributes["surname"]; } if ($attributes["title"]){ $mod["title"][0]=$attributes["title"]; } if ($attributes["telephone"]){ $mod["telephoneNumber"][0]=$attributes["telephone"]; } if ($attributes["mobile"]){ $mod["telephoneNumber"][0]=$attributes["mobile"]; } if ($attributes["web_page"]){ $mod["wWWHomePage"][0]=$attributes["web_page"]; } if (count($mod)==0){ return (false); } return ($mod); } function group_cn($gid, $cache_only = FALSE, $local_group = FALSE){ $this->_warning_message = ""; if ($gid==NULL){ return (false); } $r=false; $r_data = FALSE; if ($this->_cache_support) { if ("" != $this->get_cache_folder()) { if (file_exists($this->get_cache_folder()."ldap_cgroup_".md5($gid).".cache")) { if ((filemtime($this->get_cache_folder()."ldap_cgroup_".md5($gid).".cache") + $this->get_cache_timeout()) > time()) { if ($cache_handle = fopen($this->get_cache_folder()."ldap_cgroup_".md5($gid).".cache", "rb")) { $r = unserialize(fgets($cache_handle)); $r_data = TRUE; fclose($cache_handle); touch($this->get_cache_folder()."ldap_group_cn_$gid.cache"); } } } } elseif (isset($this->_cache_group_cn[$gid])) { $r = $this->_cache_group_cn[$gid]; $r_data = TRUE; } } if (!$r_data) { if (!$cache_only) { if (1 == $this->_ldap_server_type) { if ($local_group) { $group_account_type = "(|(samaccounttype=".ADLDAP_SECURITY_LOCAL_GROUP.")(samaccounttype=". ADLDAP_SECURITY_GLOBAL_GROUP."))"; } else { $group_account_type = "(samaccounttype=".ADLDAP_SECURITY_GLOBAL_GROUP.")"; } $filter="(&(objectCategory=group)".$group_account_type.")"; $fields=array("primarygrouptoken",$this->_group_cn_identifier,"distinguishedname"); } else { $filter="(|(objectClass=posixGroup)(objectClass=groupofNames))"; $fields=array("gidnumber",$this->_group_cn_identifier,"distinguishedname"); } $pageSize = 1000; $page_cookie = ''; do { if (function_exists('ldap_control_paged_result')) { ldap_control_paged_result($this->_conn, $pageSize, true, $page_cookie); } $sr = @ldap_search($this->_conn,$this->_base_dn,$filter,$fields); if ((!function_exists('ldap_control_paged_result')) && (4 == ldap_errno($this->_conn))) { $cr = @ldap_count_entries($this->_conn,$sr); $this->_warning_message = "LDAP server cannot return more than $cr records."; } $entries = $this->ldap_get_entries_raw($sr); for ($i=0; $i<$entries["count"]; $i++) { if (1 != $this->_ldap_server_type) { $entries[$i]["distinguishedname"][0] = $entries[$i][$this->_group_cn_identifier][0]; } if (!isset($entries[$i]["primarygrouptoken"][0])) { $entries[$i]["primarygrouptoken"][0] = (isset($entries[$i]["gidnumber"][0])?$entries[$i]["gidnumber"][0]:NULL); } if ($this->_cache_support) { if (NULL !== $entries[$i]["primarygrouptoken"][0]) { if ("" != $this->get_cache_folder()) { if (file_exists($this->get_cache_folder())) { if ($cache_handle = fopen($this->get_cache_folder()."ldap_cgroup_".md5($entries[$i]["primarygrouptoken"][0]).".cache", "wb")) { fwrite($cache_handle, serialize($entries[$i]["distinguishedname"][0])); fclose($cache_handle); @chmod($this->get_cache_folder()."ldap_cgroup_".md5($entries[$i]["primarygrouptoken"][0]).".cache", octdec($this->_linux_file_mode)); } } } else { $this->_cache_group_cn[$entries[$i]["primarygrouptoken"][0]] = $entries[$i]["distinguishedname"][0]; } } } if ($entries[$i]["primarygrouptoken"][0]==$gid){ $r=$entries[$i]["distinguishedname"][0]; $i=$entries["count"]; } } if (function_exists('ldap_control_paged_result_response')) { ldap_control_paged_result_response($this->_conn, $sr, $page_cookie); } } while($page_cookie !== null && $page_cookie != ''); if (function_exists('ldap_control_paged_result')) { ldap_control_paged_result($this->_conn, 1000); } } } return ($r); } function encode_password($password){ $password="\"".$password."\""; $encoded=""; for ($i=0; $i <strlen($password); $i++){ $encoded.="{$password{$i}}\000"; } return ($encoded); } function ldap_slashes($str){ $illegal=array("(",")","#"); $legal=array(); foreach ($illegal as $id => $char){ $legal[$id]="\\".$char; } $str=str_replace($illegal,$legal,$str); return ($str); } function ldap_dn_encode($str) { $decoded=array("\\",",","+","<",">",";","\"","="); $encoded=array(); foreach ($decoded as $id => $char) { $encoded[$id]="\\".$char; } $str = str_replace($decoded,$encoded,$str); if (" " == (substr($str,0,1))) { $str = "\\ ".$str; } if (" " == (substr($str,-1))) { $str = substr($str,0,-1)."\\ "; } if ("#" == (substr($str,0,1))) { $str = "\\#".$str; } return ($str); } function ldap_dn_decode($str) { $decoded=array(",","#","+","<",">",";","\"","="," ","\\"); $encoded=array(); foreach ($decoded as $id => $char) { $encoded[$id]="\\".$char; } $str = str_replace($encoded,$decoded,$str); return ($str); } function ldap_search_encode($str) { $decoded=array("\\","*","(",")",chr(0),"/"); $encoded=array("\\5c","\\2a","\\28","\\29","\\00","\\2f"); $str=str_replace($decoded,$encoded,$str); return ($str); } function random_controller(){ mt_srand(doubleval(microtime()) * 100000000); return ($this->_domain_controllers[array_rand($this->_domain_controllers)]); } function account_control($options){ $val=0; if (is_array($options)){ if (in_array("SCRIPT",$options)){ $val=$val+1; } if (in_array("ACCOUNTDISABLE",$options)){ $val=$val+2; } if (in_array("HOMEDIR_REQUIRED",$options)){ $val=$val+8; } if (in_array("LOCKOUT",$options)){ $val=$val+16; } if (in_array("PASSWD_NOTREQD",$options)){ $val=$val+32; } if (in_array("ENCRYPTED_TEXT_PWD_ALLOWED",$options)){ $val=$val+128; } if (in_array("TEMP_DUPLICATE_ACCOUNT",$options)){ $val=$val+256; } if (in_array("NORMAL_ACCOUNT",$options)){ $val=$val+512; } if (in_array("INTERDOMAIN_TRUST_ACCOUNT",$options)){ $val=$val+2048; } if (in_array("WORKSTATION_TRUST_ACCOUNT",$options)){ $val=$val+4096; } if (in_array("SERVER_TRUST_ACCOUNT",$options)){ $val=$val+8192; } if (in_array("DONT_EXPIRE_PASSWORD",$options)){ $val=$val+65536; } if (in_array("MNS_LOGON_ACCOUNT",$options)){ $val=$val+131072; } if (in_array("SMARTCARD_REQUIRED",$options)){ $val=$val+262144; } if (in_array("TRUSTED_FOR_DELEGATION",$options)){ $val=$val+524288; } if (in_array("NOT_DELEGATED",$options)){ $val=$val+1048576; } if (in_array("USE_DES_KEY_ONLY",$options)){ $val=$val+2097152; } if (in_array("DONT_REQ_PREAUTH",$options)){ $val=$val+4194304; } if (in_array("PASSWORD_EXPIRED",$options)){ $val=$val+8388608; } if (in_array("TRUSTED_TO_AUTH_FOR_DELEGATION",$options)){ $val=$val+16777216; } } return ($val); } function nice_names($groups){ $group_array=array(); for ($i=0; $i<$groups["count"]; $i++) { if (isset($groups[$i])) { $line=trim($groups[$i]); if (strlen($line)>0){ $bits=explode(",",$line); if (1== count($bits)) { $group_array[]=$bits[0]; } else { $prefix_len=strpos($bits[0], "="); if (FALSE === $prefix_len) { $group_array[]=$bits[0]; } else { $group_array[]=substr($bits[0],$prefix_len+1); } } } } } return ($group_array); } } function MultiotpQrcode($data = '', $file_name = '', $image_type = "P", $ecc_level = "Q", $module_size = 4, $version = 0, $structure_m = 0, $structure_n = 0, $parity = 0, $original_data = '', $path = 'qrcode/data', $image_path = 'qrcode/image') { $output_name = $file_name; $qrcode_image_size = 0; $qrcode_result = NULL; $version_ul=40; $qrcode_data_string=$data; $qrcode_error_correct=$ecc_level; $qrcode_module_size=$module_size; $qrcode_version=$version; $qrcode_image_type=$image_type; $qrcode_structureappend_n=$structure_n; $qrcode_structureappend_m=$structure_m; $qrcode_structureappend_parity=$parity; $qrcode_structureappend_originaldata=$original_data; if (strtolower($qrcode_image_type)=="j") { $qrcode_image_type="jpeg"; } else { $qrcode_image_type="png"; } if ($qrcode_module_size>0) { } else { if ($qrcode_image_type=="jpeg"){ $qrcode_module_size=8; } else { $qrcode_module_size=4; } } $qrcode_data_string=($qrcode_data_string); $data_length=strlen($qrcode_data_string); if ($data_length<=0) { trigger_error("QRcode : Data do not exist.",E_USER_ERROR); exit; } $data_counter=0; if ($qrcode_structureappend_n>1 && $qrcode_structureappend_n<=16 && $qrcode_structureappend_m>0 && $qrcode_structureqppend_m<=16){ $data_value[0]=3; $data_bits[0]=4; $data_value[1]=$qrcode_structureappend_m-1; $data_bits[1]=4; $data_value[2]=$qrcode_structureappend_n-1; $data_bits[2]=4; $originaldata_length=strlen($qrcode_structureappend_originaldata); if ($originaldata_length>1){ $qrcode_structureappend_parity=0; $i=0; while ($i<$originaldata_length){ $qrcode_structureappend_parity=($qrcode_structureappend_parity ^ ord(substr($qrcode_structureappend_originaldata,$i,1))); $i++; } } $data_value[3]=$qrcode_structureappend_parity; $data_bits[3]=8; $data_counter=4; } $data_bits[$data_counter]=4; if (preg_match("/[^0-9]/",$qrcode_data_string)!=0){ if (preg_match("/[^0-9A-Z \$\*\%\+\.\/\:\-]/",$qrcode_data_string)!=0) { $codeword_num_plus=array(0,0,0,0,0,0,0,0,0,0, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8); $data_value[$data_counter]=4; $data_counter++; $data_value[$data_counter]=$data_length; $data_bits[$data_counter]=8; $codeword_num_counter_value=$data_counter; $data_counter++; $i=0; while ($i<$data_length){ $data_value[$data_counter]=ord(substr($qrcode_data_string,$i,1)); $data_bits[$data_counter]=8; $data_counter++; $i++; } } else { $codeword_num_plus=array(0,0,0,0,0,0,0,0,0,0, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 4,4,4,4,4,4,4,4,4,4,4,4,4,4); $data_value[$data_counter]=2; $data_counter++; $data_value[$data_counter]=$data_length; $data_bits[$data_counter]=9; $codeword_num_counter_value=$data_counter; $alphanumeric_character_hash=array("0"=>0,"1"=>1,"2"=>2,"3"=>3,"4"=>4, "5"=>5,"6"=>6,"7"=>7,"8"=>8,"9"=>9,"A"=>10,"B"=>11,"C"=>12,"D"=>13,"E"=>14, "F"=>15,"G"=>16,"H"=>17,"I"=>18,"J"=>19,"K"=>20,"L"=>21,"M"=>22,"N"=>23, "O"=>24,"P"=>25,"Q"=>26,"R"=>27,"S"=>28,"T"=>29,"U"=>30,"V"=>31, "W"=>32,"X"=>33,"Y"=>34,"Z"=>35," "=>36,"$"=>37,"%"=>38,"*"=>39, "+"=>40,"-"=>41,"."=>42,"/"=>43,":"=>44); $i=0; $data_counter++; while ($i<$data_length){ if (($i %2)==0){ $data_value[$data_counter]=$alphanumeric_character_hash[substr($qrcode_data_string,$i,1)]; $data_bits[$data_counter]=6; } else { $data_value[$data_counter]=$data_value[$data_counter]*45+$alphanumeric_character_hash[substr($qrcode_data_string,$i,1)]; $data_bits[$data_counter]=11; $data_counter++; } $i++; } } } else { $codeword_num_plus=array(0,0,0,0,0,0,0,0,0,0, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 4,4,4,4,4,4,4,4,4,4,4,4,4,4); $data_value[$data_counter]=1; $data_counter++; $data_value[$data_counter]=$data_length; $data_bits[$data_counter]=10; $codeword_num_counter_value=$data_counter; $i=0; $data_counter++; while ($i<$data_length){ if (($i % 3)==0){ $data_value[$data_counter]=substr($qrcode_data_string,$i,1); $data_bits[$data_counter]=4; } else { $data_value[$data_counter]=$data_value[$data_counter]*10+substr($qrcode_data_string,$i,1); if (($i % 3)==1){ $data_bits[$data_counter]=7; } else { $data_bits[$data_counter]=10; $data_counter++; } } $i++; } } if (@$data_bits[$data_counter]>0) { $data_counter++; } $i=0; $total_data_bits=0; while($i<$data_counter){ $total_data_bits+=$data_bits[$i]; $i++; } $ecc_character_hash=array("L"=>"1", "l"=>"1", "M"=>"0", "m"=>"0", "Q"=>"3", "q"=>"3", "H"=>"2", "h"=>"2"); $ec=@$ecc_character_hash[$qrcode_error_correct]; if (!$ec){$ec=0;} $max_data_bits_array=array( 0,128,224,352,512,688,864,992,1232,1456,1728, 2032,2320,2672,2920,3320,3624,4056,4504,5016,5352, 5712,6256,6880,7312,8000,8496,9024,9544,10136,10984, 11640,12328,13048,13800,14496,15312,15936,16816,17728,18672, 152,272,440,640,864,1088,1248,1552,1856,2192, 2592,2960,3424,3688,4184,4712,5176,5768,6360,6888, 7456,8048,8752,9392,10208,10960,11744,12248,13048,13880, 14744,15640,16568,17528,18448,19472,20528,21616,22496,23648, 72,128,208,288,368,480,528,688,800,976, 1120,1264,1440,1576,1784,2024,2264,2504,2728,3080, 3248,3536,3712,4112,4304,4768,5024,5288,5608,5960, 6344,6760,7208,7688,7888,8432,8768,9136,9776,10208, 104,176,272,384,496,608,704,880,1056,1232, 1440,1648,1952,2088,2360,2600,2936,3176,3560,3880, 4096,4544,4912,5312,5744,6032,6464,6968,7288,7880, 8264,8920,9368,9848,10288,10832,11408,12016,12656,13328 ); if (!is_numeric($qrcode_version)){ $qrcode_version=0; } if (!$qrcode_version){ $i=1+40*$ec; $j=$i+39; $qrcode_version=1; while ($i<=$j){ if (($max_data_bits_array[$i])>=$total_data_bits+$codeword_num_plus[$qrcode_version] ){ $max_data_bits=$max_data_bits_array[$i]; break; } $i++; $qrcode_version++; } } else { $max_data_bits=$max_data_bits_array[$qrcode_version+40*$ec]; } if ($qrcode_version>$version_ul){ trigger_error("QRcode : too large version.",E_USER_ERROR); } $total_data_bits+=$codeword_num_plus[$qrcode_version]; $data_bits[$codeword_num_counter_value]+=$codeword_num_plus[$qrcode_version]; $max_codewords_array=array(0,26,44,70,100,134,172,196,242, 292,346,404,466,532,581,655,733,815,901,991,1085,1156, 1258,1364,1474,1588,1706,1828,1921,2051,2185,2323,2465, 2611,2761,2876,3034,3196,3362,3532,3706); $max_codewords=$max_codewords_array[$qrcode_version]; $max_modules_1side=17+($qrcode_version <<2); $matrix_remain_bit=array(0,0,7,7,7,7,7,0,0,0,0,0,0,0,3,3,3,3,3,3,3, 4,4,4,4,4,4,4,3,3,3,3,3,3,3,0,0,0,0,0,0); $byte_num=$matrix_remain_bit[$qrcode_version]+($max_codewords << 3); $filename=$path."/qrv".$qrcode_version."_".$ec.".dat"; $fp1 = fopen ($filename, "rb"); $matx=fread($fp1,$byte_num); $maty=fread($fp1,$byte_num); $masks=fread($fp1,$byte_num); $fi_x=fread($fp1,15); $fi_y=fread($fp1,15); $rs_ecc_codewords=ord(fread($fp1,1)); $rso=fread($fp1,128); fclose($fp1); $matrix_x_array=unpack("C*",$matx); $matrix_y_array=unpack("C*",$maty); $mask_array=unpack("C*",$masks); $rs_block_order=unpack("C*",$rso); $format_information_x2=unpack("C*",$fi_x); $format_information_y2=unpack("C*",$fi_y); $format_information_x1=array(0,1,2,3,4,5,7,8,8,8,8,8,8,8,8); $format_information_y1=array(8,8,8,8,8,8,8,8,7,5,4,3,2,1,0); $max_data_codewords=($max_data_bits >>3); $filename = $path."/rsc".$rs_ecc_codewords.".dat"; $fp0 = fopen ($filename, "rb"); $i=0; while ($i<256) { $rs_cal_table_array[$i]=fread ($fp0,$rs_ecc_codewords); $i++; } fclose ($fp0); if ($total_data_bits<=$max_data_bits-4){ $data_value[$data_counter]=0; $data_bits[$data_counter]=4; } else { if ($total_data_bits<$max_data_bits){ $data_value[$data_counter]=0; $data_bits[$data_counter]=$max_data_bits-$total_data_bits; } else { if ($total_data_bits>$max_data_bits){ trigger_error("QRcode : Overflow error",E_USER_ERROR); exit; } } } $i=0; $codewords_counter=0; $codewords[0]=0; $remaining_bits=8; while ($i<=$data_counter) { $buffer=@$data_value[$i]; $buffer_bits=@$data_bits[$i]; $flag=1; while ($flag) { if ($remaining_bits>$buffer_bits){ $codewords[$codewords_counter]=((@$codewords[$codewords_counter]<<$buffer_bits) | $buffer); $remaining_bits-=$buffer_bits; $flag=0; } else { $buffer_bits-=$remaining_bits; $codewords[$codewords_counter]=(($codewords[$codewords_counter] << $remaining_bits) | ($buffer >> $buffer_bits)); if ($buffer_bits==0) { $flag=0; } else { $buffer= ($buffer & ((1 << $buffer_bits)-1) ); $flag=1; } $codewords_counter++; if ($codewords_counter<$max_data_codewords-1){ $codewords[$codewords_counter]=0; } $remaining_bits=8; } } $i++; } if ($remaining_bits!=8) { $codewords[$codewords_counter]=$codewords[$codewords_counter] << $remaining_bits; } else { $codewords_counter--; } if ($codewords_counter<$max_data_codewords-1){ $flag=1; while ($codewords_counter<$max_data_codewords-1){ $codewords_counter++; if ($flag==1) { $codewords[$codewords_counter]=236; } else { $codewords[$codewords_counter]=17; } $flag=$flag*(-1); } } $i=0; $j=0; $rs_block_number=0; $rs_temp[0]=""; while($i<$max_data_codewords){ $rs_temp[$rs_block_number].=chr($codewords[$i]); $j++; if ($j>=$rs_block_order[$rs_block_number+1]-$rs_ecc_codewords){ $j=0; $rs_block_number++; $rs_temp[$rs_block_number]=""; } $i++; } $rs_block_number=0; $rs_block_order_num=count($rs_block_order); while ($rs_block_number<$rs_block_order_num){ $rs_codewords=$rs_block_order[$rs_block_number+1]; $rs_data_codewords=$rs_codewords-$rs_ecc_codewords; $rstemp=$rs_temp[$rs_block_number].str_repeat(chr(0),$rs_ecc_codewords); $padding_data=str_repeat(chr(0),$rs_data_codewords); $j=$rs_data_codewords; while($j>0){ $first=ord(substr($rstemp,0,1)); if ($first){ $left_chr=substr($rstemp,1); $cal=$rs_cal_table_array[$first].$padding_data; $rstemp=$left_chr ^ $cal; } else { $rstemp=substr($rstemp,1); } $j--; } $codewords=array_merge($codewords,unpack("C*",$rstemp)); $rs_block_number++; } $i=0; while ($i<$max_modules_1side){ $j=0; while ($j<$max_modules_1side){ $matrix_content[$j][$i]=0; $j++; } $i++; } $i=0; while ($i<$max_codewords){ $codeword_i=$codewords[$i]; $j=8; while ($j>=1){ $codeword_bits_number=($i << 3) + $j; $matrix_content[ $matrix_x_array[$codeword_bits_number] ][ $matrix_y_array[$codeword_bits_number] ]=((255*($codeword_i & 1)) ^ $mask_array[$codeword_bits_number] ); $codeword_i= $codeword_i >> 1; $j--; } $i++; } $matrix_remain=$matrix_remain_bit[$qrcode_version]; while ($matrix_remain){ $remain_bit_temp = $matrix_remain + ( $max_codewords <<3); $matrix_content[ $matrix_x_array[$remain_bit_temp] ][ $matrix_y_array[$remain_bit_temp] ] = ( 0 ^ $mask_array[$remain_bit_temp] ); $matrix_remain--; } $min_demerit_score=0; $hor_master=""; $ver_master=""; $k=0; while($k<$max_modules_1side){ $l=0; while($l<$max_modules_1side){ $hor_master=$hor_master.chr($matrix_content[$l][$k]); $ver_master=$ver_master.chr($matrix_content[$k][$l]); $l++; } $k++; } $i=0; $all_matrix=$max_modules_1side * $max_modules_1side; while ($i<8){ $demerit_n1=0; $ptn_temp=array(); $bit= 1<< $i; $bit_r=(~$bit)&255; $bit_mask=str_repeat(chr($bit),$all_matrix); $hor = $hor_master & $bit_mask; $ver = $ver_master & $bit_mask; $ver_shift1=$ver.str_repeat(chr(170),$max_modules_1side); $ver_shift2=str_repeat(chr(170),$max_modules_1side).$ver; $ver_shift1_0=$ver.str_repeat(chr(0),$max_modules_1side); $ver_shift2_0=str_repeat(chr(0),$max_modules_1side).$ver; $ver_or=chunk_split(~($ver_shift1 | $ver_shift2),$max_modules_1side,chr(170)); $ver_and=chunk_split(~($ver_shift1_0 & $ver_shift2_0),$max_modules_1side,chr(170)); $hor=chunk_split(~$hor,$max_modules_1side,chr(170)); $ver=chunk_split(~$ver,$max_modules_1side,chr(170)); $hor=$hor.chr(170).$ver; $n1_search="/".str_repeat(chr(255),5)."+|".str_repeat(chr($bit_r),5)."+/"; $n3_search=chr($bit_r).chr(255).chr($bit_r).chr($bit_r).chr($bit_r).chr(255).chr($bit_r); $demerit_n3=substr_count($hor,$n3_search)*40; $demerit_n4=floor(abs(( (100* (substr_count($ver,chr($bit_r))/($byte_num)) )-50)/5))*10; $n2_search1="/".chr($bit_r).chr($bit_r)."+/"; $n2_search2="/".chr(255).chr(255)."+/"; $demerit_n2=0; preg_match_all($n2_search1,$ver_and,$ptn_temp); foreach($ptn_temp[0] as $str_temp){ $demerit_n2+=(strlen($str_temp)-1); } $ptn_temp=array(); preg_match_all($n2_search2,$ver_or,$ptn_temp); foreach($ptn_temp[0] as $str_temp){ $demerit_n2+=(strlen($str_temp)-1); } $demerit_n2*=3; $ptn_temp=array(); preg_match_all($n1_search,$hor,$ptn_temp); foreach($ptn_temp[0] as $str_temp){ $demerit_n1+=(strlen($str_temp)-2); } $demerit_score=$demerit_n1+$demerit_n2+$demerit_n3+$demerit_n4; if ($demerit_score<=$min_demerit_score || $i==0){ $mask_number=$i; $min_demerit_score=$demerit_score; } $i++; } $mask_content=1 << $mask_number; $format_information_value=(($ec << 3) | $mask_number); $format_information_array=array("101010000010010","101000100100101", "101111001111100","101101101001011","100010111111001","100000011001110", "100111110010111","100101010100000","111011111000100","111001011110011", "111110110101010","111100010011101","110011000101111","110001100011000", "110110001000001","110100101110110","001011010001001","001001110111110", "001110011100111","001100111010000","000011101100010","000001001010101", "000110100001100","000100000111011","011010101011111","011000001101000", "011111100110001","011101000000110","010010010110100","010000110000011", "010111011011010","010101111101101"); $i=0; while ($i<15){ $content=substr($format_information_array[$format_information_value],$i,1); $matrix_content[$format_information_x1[$i]][$format_information_y1[$i]]=$content * 255; $matrix_content[$format_information_x2[$i+1]][$format_information_y2[$i+1]]=$content * 255; $i++; } $mib=$max_modules_1side+8; $qrcode_image_size=$mib*$qrcode_module_size; if ($qrcode_image_size>1480){ trigger_error("QRcode : Too large image size",E_USER_ERROR); } $output_image =ImageCreate($qrcode_image_size,$qrcode_image_size); $image_path=$image_path."/qrv".$qrcode_version.".png"; $base_image=ImageCreateFromPNG($image_path); $col[1]=ImageColorAllocate($base_image,0,0,0); $col[0]=ImageColorAllocate($base_image,255,255,255); $i=4; $mxe=4+$max_modules_1side; $ii=0; while ($i<$mxe){ $j=4; $jj=0; while ($j<$mxe){ if ($matrix_content[$ii][$jj] & $mask_content){ ImageSetPixel($base_image,$i,$j,$col[1]); } $j++; $jj++; } $i++; $ii++; } ImageCopyResized($output_image,$base_image,0,0,0,0,$qrcode_image_size,$qrcode_image_size,$mib,$mib); if ('' == trim($file_name)) { Header("Content-type: image/".$qrcode_image_type); $output_name = NULL; } if ('binary' == trim($file_name)) { $output_name = NULL; ob_start(); } if ($qrcode_image_type == "jpeg") { if (NULL == $output_name) { ImageJpeg($output_image); } else { ImageJpeg($output_image, $output_name); } } else { if (NULL == $output_name) { ImagePng($output_image); } else { ImagePng($output_image, $output_name); } } if ('binary' == trim($file_name)) { $qrcode_result = ob_get_clean(); } else { $qrcode_result = $qrcode_image_size; } imagedestroy($base_image); imagedestroy($output_image); return $qrcode_result; } function MultiotpShowStatus($done, $total, $size=30) { static $start_time; if($done > $total) return; if(empty($start_time)) $start_time=time(); $now = time(); $perc=(double)($done/$total); $bar=floor($perc*$size); $status_bar="\r["; $status_bar.=str_repeat("=", $bar); if($bar<$size) { $status_bar.=">"; $status_bar.=str_repeat("-", $size-$bar); } else { $status_bar.="="; } $disp=number_format($perc*100, 0); $status_bar.="] $disp%  $done/$total"; $rate = ($now-$start_time)/$done; $left = $total - $done; $eta = round($rate * $left, 2); $elapsed = $now - $start_time; echo "$status_bar  "; flush(); if($done == $total) { echo "\n"; } } class MultiotpSyslog { var $_facility; var $_severity; var $_hostname; var $_fqdn; var $_ip_from; var $_process; var $_content; var $_msg; var $_server; var $_port; var $_timeout; function MultiotpSyslog($facility = 16, $severity = 5, $hostname = "", $fqdn= "", $ip_from = "", $process="", $content = "") { $this->_msg = ''; $this->_server = '127.0.0.1'; $this->_port = 514; $this->_timeout = 20; $this->_facility = $facility; $this->_severity = $severity; $this->_hostname = $hostname; if ($this->_hostname == "") { if (isset($_ENV["COMPUTERNAME"])) { $this->_hostname = $_ENV["COMPUTERNAME"]; } elseif (isset($_ENV["HOSTNAME"])) { $this->_hostname = $_ENV["HOSTNAME"]; } else { $this->_hostname = "WEBSERVER"; } } $this->_hostname = substr($this->_hostname, 0, strpos($this->_hostname.".", ".")); $this->_fqdn = $fqdn; if ($this->_fqdn == "") { if (isset($_SERVER["SERVER_NAME"])) { $this->_fqdn = $_SERVER["SERVER_NAME"]; } } $this->_ip_from = $ip_from; if ($this->_ip_from == "") { if (isset($_SERVER["SERVER_ADDR"])) { $this->_ip_from = $_SERVER["SERVER_ADDR"]; } } $this->_process = $process; if ($this->_process == "") { $this->_process = "PHP"; } $this->_content = $content; if ($this->_content == "") { $this->_content = "PHP generated message"; } } function SetFacility($facility) { $this->_facility = $facility; } function SetSeverity($severity) { $this->_severity = $severity; } function SetHostname($hostname) { $this->_hostname = $hostname; } function SetFqdn($fqdn) { $this->_fqdn = $fqdn; } function SetIpFrom($ip_from) { $this->_ip_from = $ip_from; } function SetProcess($process) { $this->_process = $process; } function SetContent($content) { $this->_content = $content; } function SetMsg($msg) { $this->_msg = $msg; } function SetServer($server) { $this->_server = $server; } function SetPort($port) { if ((intval($port) > 0) && (intval($port) < 65536)) { $this->_port = intval($port); } } function SetTimeout($timeout) { if (intval($timeout) > 0) { $this->_timeout = intval($timeout); } } function Send($server = "", $content = "", $timeout = 0) { if ($server != "") { $this->_server = $server; } if ($content != "") { $this->_content = $content; } if (intval($timeout) > 0) { $this->_timeout = intval($timeout); } if ($this->_facility < 0) { $this->_facility = 0; } if ($this->_facility > 23) { $this->_facility = 23; } if ($this->_severity < 0) { $this->_severity = 0; } if ($this->_severity > 7) { $this->_severity = 7; } $this->_process = substr($this->_process, 0, 32); $actualtime = time(); $month = date("M", $actualtime); $day = substr("  ".date("j", $actualtime), -2); $hhmmss = date("H:i:s", $actualtime); $timestamp = $month." ".$day." ".$hhmmss; $pri = "<".($this->_facility*8 + $this->_severity).">"; $header = $timestamp." ".$this->_hostname; if ($this->_msg != "") { $msg = $this->_msg; } else { $msg = $this->_process.": ".$this->_fqdn." ".$this->_ip_from." ".$this->_content; } $message = substr($pri.$header." ".$msg, 0, 1024); $fp = fsockopen("udp://".$this->_server, $this->_port, $errno, $errstr, $this->_timeout); if ($fp) { fwrite($fp, $message); fclose($fp); $result = $message; } else { $result = "ERROR: $errno - $errstr"; } return $result; } } class MultiotpXmlParser { var $parser; var $xml; var $document; var $stack; var $cleanTagNames; function MultiotpXmlParser($xml = '', $cleanTagNames = true) { $this->xml = $xml; $this->stack = array(); $this->cleanTagNames = $cleanTagNames; } function Parse() { $this->parser = xml_parser_create(); xml_set_object($this->parser, $this); xml_set_element_handler($this->parser, 'StartElement', 'EndElement'); xml_set_character_data_handler($this->parser, 'CharacterData'); if (!xml_parse($this->parser, $this->xml)) $this->HandleError(xml_get_error_code($this->parser), xml_get_current_line_number($this->parser), xml_get_current_column_number($this->parser), xml_get_current_byte_index($this->parser)); xml_parser_free($this->parser); } function HandleError($code, $line, $col, $byte_index = 0) { $sample_size = 80; $sample_start = $byte_index - ($sample_size / 2); if ($sample_start < 0) { $sample_start = 0; } trigger_error('XML Parsing Error at '.$line.':'.$col. (($byte_index != 0)?' (byte index: '.$byte_index.')':''). '. Error '.$code.': '.xml_error_string($code). ' check sample which starts at position '.$sample_start.': html encoded: '.htmlentities(substr($this->xml, $sample_start, $sample_size)). ' (hex: '.bin2hex(substr($this->xml, $sample_start, $sample_size)).', raw: '.(substr($this->xml, $sample_start, $sample_size)).')'); } function GenerateXML() { return $this->document->GetXML(); } function GetStackLocation() { $return = ''; foreach($this->stack as $stack) $return .= $stack.'->'; return rtrim($return, '->'); } function StartElement($parser, $name, $attrs = array()) { $name = strtolower($name); if (count($this->stack) == 0) { $this->document = new MultiotpXMLTag($name, $attrs); $this->stack = array('document'); } else { $parent = $this->GetStackLocation(); eval('$this->'.$parent.'->AddChild($name, $attrs, '.count($this->stack).', $this->cleanTagNames);'); if($this->cleanTagNames) $name = str_replace(array(':', '-'), '_', $name); eval('$this->stack[] = $name.\'[\'.(count($this->'.$parent.'->'.$name.') - 1).\']\';'); } } function EndElement($parser, $name) { array_pop($this->stack); } function CharacterData($parser, $data) { $tag = $this->GetStackLocation(); eval('$this->'.$tag.'->tagData .= trim($data);'); } } class MultiotpXMLTag { var $tagAttrs; var $tagName; var $tagData; var $tagChildren; var $tagParents; function MultiotpXMLTag($name, $attrs = array(), $parents = 0) { $this->tagAttrs = array_change_key_case($attrs, CASE_LOWER); $this->tagName = strtolower($name); $this->tagParents = $parents; $this->tagChildren = array(); $this->tagData = ''; } function AddChild($name, $attrs, $parents, $cleanTagName = true) { if(in_array($name, array('tagChildren', 'tagAttrs', 'tagParents', 'tagData', 'tagName'))) { trigger_error('You have used a reserved name as the name of an XML tag. Please consult the documentation (http://www.criticaldevelopment.net/xml/) and rename the tag named "'.$name.'" to something other than a reserved name.', E_USER_ERROR); return; } $child = new MultiotpXMLTag($name, $attrs, $parents); if($cleanTagName) $name = str_replace(array(':', '-'), '_', $name); elseif(strstr($name, ':') || strstr($name, '-')) trigger_error('Your tag named "'.$name.'" contains either a dash or a colon. Neither of these characters are friendly with PHP variable names, and, as such, they cannot be accessed and will cause the parser to not work. You must enable the cleanTagName feature (pass true as the second argument of the MultiotpXmlParser constructor). For more details, see http://www.criticaldevelopment.net/xml/', E_USER_ERROR); if(!isset($this->$name)) $this->$name = array(); $this->{$name}[] =& $child; $this->tagChildren[] =& $child; } function GetXML() { $out = "\n".str_repeat("\t", $this->tagParents).'<'.$this->tagName; foreach($this->tagAttrs as $attr => $value) $out .= ' '.$attr.'="'.$value.'"'; if(empty($this->tagChildren) && empty($this->tagData)) $out .= " />"; else { if(!empty($this->tagChildren)) { $out .= '>'; foreach($this->tagChildren as $child) { if(is_object($child)) $out .= $child->GetXML(); } $out .= "\n".str_repeat("\t", $this->tagParents); } elseif(!empty($this->tagData)) $out .= '>'.$this->tagData; $out .= '</'.$this->tagName.'>'; } return $out; } function Delete($childName, $childIndex = 0) { $this->{$childName}[$childIndex]->DeleteChildren(); $this->{$childName}[$childIndex] = null; unset($this->{$childName}[$childIndex]); for($x = 0; $x < count($this->tagChildren); $x ++) { if(is_null($this->tagChildren[$x])) unset($this->tagChildren[$x]); } } function DeleteChildren() { for($x = 0; $x < count($this->tagChildren); $x ++) { $this->tagChildren[$x]->DeleteChildren(); $this->tagChildren[$x] = null; unset($this->tagChildren[$x]); } } } class MultiotpYubikey { var $_yubicloud_client_id = 19042; var $_yubicloud_secret_key = 'a72X/qkw3vPeT+yRO6lWgipwjPM='; var $_yubicloud_timeout = 10; var $_yubicloud_last_response = array(); var $_yubicloud_last_result = ''; var $_yubicloud_max_time_window = 600; var $_yubico_modhex_chars = "cbdefghijklnrtuv"; var $_yubico_modhex_dvorak_chars = "jxe.uidchtnbpygk"; var $_yubico_dvorak_only_chars = "x.py"; var $_yubico_otp_last_count = -1; function MultiotpYubikey( $yubicloud_client_id = 0, $yubicloud_secret_key = '' ) { if (0 < intval($yubicloud_client_id)) { $this->_yubicloud_client_id = $yubicloud_client_id; } if (28 == strlen($yubicloud_secret_key)) { $this->_yubicloud_secret_key = $yubicloud_secret_key; } } function CalculateHashHmac( $algo, $data, $key, $raw_output = false ) { if (function_exists('hash_hmac')) { return hash_hmac($algo, $data, $key, $raw_output); } else { $algo = strtolower($algo); $pack = 'H'.strlen($algo('test')); $size = 64; $opad = str_repeat(chr(0x5C), $size); $ipad = str_repeat(chr(0x36), $size); if (strlen($key) > $size) { $key = str_pad(pack($pack, $algo($key)), $size, chr(0x00)); } else { $key = str_pad($key, $size, chr(0x00)); } for ($i = 0; $i < strlen($key) - 1; $i++) { $opad[$i] = $opad[$i] ^ $key[$i]; $ipad[$i] = $ipad[$i] ^ $key[$i]; } $output = $algo($opad.pack($pack, $algo($ipad.$data))); return ($raw_output) ? pack($pack, $output) : $output; } } function Iso13239Crc16($buffer) { $crc = 0xffff; for($loop=0; $loop<strlen($buffer); $loop++) { $crc ^= ord($buffer[$loop]) & 0xff; for ($bit=0; $bit<8; $bit++) { $j=$crc & 1; $crc >>= 1; if ($j) { $crc ^= 0x8408; } } } return $crc; } function CheckYubicoOtp($yubico_modhex_encrypted_part, $secret, $last_count = -1, $private_id = "") { $result = 99; $encrypted_part = hex2bin($this->ModHexToHex($yubico_modhex_encrypted_part)); $cipher_aes = new Crypt_AES(CRYPT_AES_MODE_ECB); $cipher_aes->setKey((hex2bin($secret))); $cipher_aes->disablePadding(); $decrypted_part = $cipher_aes->decrypt(($encrypted_part)); unset($cipher_aes); $uid = bin2hex(substr($decrypted_part, 0, 6)); $useCtr = ord($decrypted_part[6]) + 256 * ord($decrypted_part[7]); $tstp = ord($decrypted_part[8]) + 256 * ord($decrypted_part[9]) + 65536 * ord($decrypted_part[10]); $sessionCtr = ord($decrypted_part[11]); $rnd = ord($decrypted_part[12]) + 256 * ord($decrypted_part[13]); $crc = ord($decrypted_part[14]) + 256 * ord($decrypted_part[15]); $check_crc = $this->Iso13239Crc16($decrypted_part); if (0xf0b8 == $check_crc) { if (("" != $private_id) && ("000000000000" != $private_id) && ($private_id != $uid)) { $result = 97; } else { $counter_position = ($useCtr * 256) + $sessionCtr; if ($counter_position <= $last_count) { $result = 26; } else { $this->_yubico_otp_last_count = $counter_position; $result = 0; } } } else { $result = 96; } return $result; } function GetYubicoOtpLastCount() { return $this->_yubico_otp_last_count; } function GetYubiCloudLastResponse() { return $this->_yubicloud_last_response; } function GetYubiCloudLastResult() { return $this->_yubicloud_last_result; } function CheckOnYubiCloud($otp_to_check) { $this->_yubicloud_last_response = array(); $this->_yubicloud_last_result = 'NOT_ENOUGH_ANSWERS'; $yubiotp = trim($otp_to_check); $result = 99; if ((44 == strlen($yubiotp)) && ($this->IsModHex($yubiotp))) { $yubicloud_servers = array('api.yubico.com/wsapi/2.0/verify', 'api2.yubico.com/wsapi/2.0/verify', 'api3.yubico.com/wsapi/2.0/verify', 'api4.yubico.com/wsapi/2.0/verify', 'api5.yubico.com/wsapi/2.0/verify'); $yubicloud_parameters = array('id' => $this->_yubicloud_client_id, 'otp' => $yubiotp, 'timestamp' => 1, 'nonce' => md5(uniqid(rand())), 'timeout' => $this->_yubicloud_timeout ); ksort($yubicloud_parameters); $url_parameters = ''; foreach($yubicloud_parameters as $key=>$value) { $url_parameters .= "&".$key."=".$value; } $url_parameters = substr($url_parameters, 1); if (28 == strlen($this->_yubicloud_secret_key)) { $yubicloud_hash = urlencode(base64_encode($this->CalculateHashHmac('sha1', $url_parameters, base64_decode($this->_yubicloud_secret_key), TRUE ))); $url_parameters.= '&h='.$yubicloud_hash; } foreach($yubicloud_servers as $one_yubicloud_server) { $yubicloud_answer = ''; $yubicloud_url = $one_yubicloud_server.'?'.$url_parameters; $protocol = ''; $port = 80; $pos = strpos($yubicloud_url, '://'); if (FALSE !== $pos) { switch (strtolower(substr($yubicloud_url,0,$pos))) { case 'https': case 'ssl': $protocol = 'ssl://'; $port = 443; break; case 'tls': $protocol = 'tls://'; $port = 443; break; } $yubicloud_url = substr($yubicloud_url,$pos+3); } $pos = strpos($yubicloud_url, '/'); if (FALSE === $pos) { $host = $yubicloud_url; $url = '/'; } else { $host = substr($yubicloud_url,0,$pos); $url = substr($yubicloud_url,$pos); } $pos = strpos($host, ':'); if (FALSE !== $pos) { $port = substr($host,$pos+1); $host = substr($host,0,$pos); } $errno = 0; $errdesc = 0; $fp = @fsockopen($protocol.$host, $port, $errno, $errdesc, $this->_yubicloud_timeout); if (FALSE !== $fp) { $info['timed_out'] = FALSE; fputs($fp, "GET ".$url." HTTP/1.0\r\n"); fputs($fp, "Content-Type: application/x-www-form-urlencoded\r\n"); fputs($fp, "User-Agent: multiOTP\r\n"); fputs($fp, "Host: ".$host."\r\n"); fputs($fp, "\r\n"); fputs($fp, "\r\n"); stream_set_blocking($fp, TRUE); stream_set_timeout($fp, $this->_yubicloud_timeout); $info = stream_get_meta_data($fp); $reply = ''; $last_length = 0; while ((!feof($fp)) && ((!$info['timed_out']) || ($last_length != strlen($reply)))) { $last_length = strlen($reply); $reply.= fgets($fp, 1024); $info = stream_get_meta_data($fp); @ob_flush(); flush(); } fclose($fp); if (!($info['timed_out'])) { $pos = strpos(strtolower($reply), "\r\n\r\n"); $header = substr($reply, 0, $pos); $yubicloud_response = substr($reply, $pos + 4); $yubicloud_response_array = explode("\r\n", trim($yubicloud_response)); $response = array(); $response['now_utc'] = date ("U"); foreach($yubicloud_response_array as $one_yubicloud_response) { list($key,$value) = explode('=', $one_yubicloud_response, 2); $response[$key] = $value; } $yubicloud_response_parameters = array('otp', 'nonce', 't', 'status', 'timestamp', 'sessioncounter', 'sessionuse', 'sl' ); sort($yubicloud_response_parameters); if (isset($response['t'])) { $response['t_utc'] = date_format(date_create(substr($response['t'], 0, -4)), "U"); } $parameters_for_hash = ''; foreach ($yubicloud_response_parameters as $one_parameter) { if (array_key_exists($one_parameter, $response)) { if ('' != $parameters_for_hash) { $parameters_for_hash.= '&'; } $parameters_for_hash.= $one_parameter.'='.$response[$one_parameter]; } } $this->_yubicloud_last_response = $response; $check_response_hash = "NO-VALID-SECRET-KEY"; if (28 == strlen($this->_yubicloud_secret_key)) { $check_response_hash = base64_encode($this->CalculateHashHmac('sha1', $parameters_for_hash, base64_decode($this->_yubicloud_secret_key), TRUE )); } if (($check_response_hash != $response['h']) && ("NO-VALID-SECRET-KEY" != $check_response_hash)) { $this->_yubicloud_last_result = 'BAD_SIGNATURE'; $result = 99; } elseif ($yubicloud_parameters['nonce'] != $response['nonce']) { $this->_yubicloud_last_result = 'BAD_NONCE'; $result = 99; } elseif($yubiotp != $response['otp']) { $this->_yubicloud_last_result = 'OTP_IS_DIFFERENT'; $result = 99; } elseif ((($response['t_utc'] - $this->_yubicloud_max_time_window) > $response['now_utc']) || (($response['t_utc'] + $this->_yubicloud_max_time_window) < $response['now_utc']) ) { $this->_yubicloud_last_result = 'OUT_OF_TIME_WINDOW'; $result = 99; } else { $this->_yubicloud_last_result = $response['status']; switch ($response['status']) { case 'OK': $result = 0; break; case 'BAD_OTP': $result = 23; break; case 'REPLAYED_OTP': case 'REPLAYED_REQUEST': $result = 26; break; case 'BAD_SIGNATURE': case 'MISSING_PARAMETER': case 'NO_SUCH_CLIENT': case 'OPERATION_NOT_ALLOWED': case 'BACKEND_ERROR': case 'NOT_ENOUGH_ANSWERS': default: $result = 99; } } if (99 != $result) { break; } } } } } return $result; } function IsModHex($modhex) { $result = FALSE; if (0 == (strlen($modhex) % 2)) { for ($loop = 0; $loop < strlen($modhex); $loop++) { $value = strpos($this->_yubico_modhex_chars, strtolower($modhex[$loop])); if (FALSE === $value) { return FALSE; } } $result = TRUE; } return $result; } function HexToModHex($hexa) { $result = ''; if (0 == (strlen($hexa) % 2)) { for ($loop = 0; $loop < strlen($hexa); $loop++) { $value = hexdec(strtolower($hexa[$loop])); if ($value > 15) { return FALSE; } $result.= $this->_yubico_modhex_chars[$value]; } } else { $result = FALSE; } return $result; } function ModHexToHex($modhex) { $result = ''; if (0 == (strlen($modhex) % 2)) { for ($loop = 0; $loop < strlen($modhex); $loop++) { $value = strpos($this->_yubico_modhex_chars, strtolower($modhex[$loop])); if (FALSE === $value) { return FALSE; } $result.= dechex($value); } } else { $result = FALSE; } return $result; } } if (!function_exists('phpseclib_resolve_include_path')) { function phpseclib_resolve_include_path($filename) { return $filename; } } if (!function_exists('crypt_random_string')) { if (!function_exists('crypt_random_string')) { define('CRYPT_RANDOM_IS_WINDOWS', strtoupper(substr(PHP_OS, 0, 3)) === 'WIN'); function crypt_random_string($length) { if (CRYPT_RANDOM_IS_WINDOWS) { if (extension_loaded('mcrypt') && version_compare(PHP_VERSION, '5.3.0', '>=')) { return mcrypt_create_iv($length); } if (extension_loaded('openssl') && version_compare(PHP_VERSION, '5.3.4', '>=')) { return openssl_random_pseudo_bytes($length); } } else { if (extension_loaded('openssl') && version_compare(PHP_VERSION, '5.3.0', '>=')) { return openssl_random_pseudo_bytes($length); } static $fp = true; if ($fp === true) { $fp = @fopen('/dev/urandom', 'rb'); } if ($fp !== true && $fp !== false) { return fread($fp, $length); } if (extension_loaded('mcrypt')) { return mcrypt_create_iv($length, MCRYPT_DEV_URANDOM); } } static $crypto = false, $v; if ($crypto === false) { $old_session_id = session_id(); $old_use_cookies = ini_get('session.use_cookies'); $old_session_cache_limiter = session_cache_limiter(); $_OLD_SESSION = isset($_SESSION) ? $_SESSION : false; if ($old_session_id != '') { session_write_close(); } session_id(1); ini_set('session.use_cookies', 0); session_cache_limiter(''); session_start(); $v = $seed = $_SESSION['seed'] = pack('H*', sha1( (isset($_SERVER) ? phpseclib_safe_serialize($_SERVER) : '') . (isset($_POST) ? phpseclib_safe_serialize($_POST) : '') . (isset($_GET) ? phpseclib_safe_serialize($_GET) : '') . (isset($_COOKIE) ? phpseclib_safe_serialize($_COOKIE) : '') . phpseclib_safe_serialize($GLOBALS) . phpseclib_safe_serialize($_SESSION) . phpseclib_safe_serialize($_OLD_SESSION) )); if (!isset($_SESSION['count'])) { $_SESSION['count'] = 0; } $_SESSION['count']++; session_write_close(); if ($old_session_id != '') { session_id($old_session_id); session_start(); ini_set('session.use_cookies', $old_use_cookies); session_cache_limiter($old_session_cache_limiter); } else { if ($_OLD_SESSION !== false) { $_SESSION = $_OLD_SESSION; unset($_OLD_SESSION); } else { unset($_SESSION); } } $key = pack('H*', sha1($seed . 'A')); $iv = pack('H*', sha1($seed . 'C')); switch (true) { case phpseclib_resolve_include_path('Crypt/AES.php'): if (!class_exists('Crypt_AES')) { include_once 'AES.php'; } $crypto = new Crypt_AES(CRYPT_AES_MODE_CTR); break; case phpseclib_resolve_include_path('Crypt/Twofish.php'): if (!class_exists('Crypt_Twofish')) { include_once 'Twofish.php'; } $crypto = new Crypt_Twofish(CRYPT_TWOFISH_MODE_CTR); break; case phpseclib_resolve_include_path('Crypt/Blowfish.php'): if (!class_exists('Crypt_Blowfish')) { include_once 'Blowfish.php'; } $crypto = new Crypt_Blowfish(CRYPT_BLOWFISH_MODE_CTR); break; case phpseclib_resolve_include_path('Crypt/TripleDES.php'): if (!class_exists('Crypt_TripleDES')) { include_once 'TripleDES.php'; } $crypto = new Crypt_TripleDES(CRYPT_DES_MODE_CTR); break; case phpseclib_resolve_include_path('Crypt/DES.php'): if (!class_exists('Crypt_DES')) { include_once 'DES.php'; } $crypto = new Crypt_DES(CRYPT_DES_MODE_CTR); break; case phpseclib_resolve_include_path('Crypt/RC4.php'): if (!class_exists('Crypt_RC4')) { include_once 'RC4.php'; } $crypto = new Crypt_RC4(); break; default: user_error('crypt_random_string requires at least one symmetric cipher be loaded'); return false; } $crypto->setKey($key); $crypto->setIV($iv); $crypto->enableContinuousBuffer(); } $result = ''; while (strlen($result) < $length) { $i = $crypto->encrypt(microtime()); $r = $crypto->encrypt($i ^ $v); $v = $crypto->encrypt($r ^ $i); $result.= $r; } return substr($result, 0, $length); } } if (!function_exists('phpseclib_safe_serialize')) { function phpseclib_safe_serialize(&$arr) { if (is_object($arr)) { return ''; } if (!is_array($arr)) { return serialize($arr); } if (isset($arr['__phpseclib_marker'])) { return ''; } $safearr = array(); $arr['__phpseclib_marker'] = true; foreach (array_keys($arr) as $key) { if ($key !== '__phpseclib_marker') { $safearr[$key] = phpseclib_safe_serialize($arr[$key]); } } unset($arr['__phpseclib_marker']); return serialize($safearr); } } if (!function_exists('phpseclib_resolve_include_path')) { function phpseclib_resolve_include_path($filename) { if (function_exists('stream_resolve_include_path')) { return stream_resolve_include_path($filename); } if (file_exists($filename)) { return realpath($filename); } $paths = PATH_SEPARATOR == ':' ? preg_split('#(?<!phar):#', get_include_path()) : explode(PATH_SEPARATOR, get_include_path()); foreach ($paths as $prefix) { $ds = substr($prefix, -1) == DIRECTORY_SEPARATOR ? '' : DIRECTORY_SEPARATOR; $file = $prefix . $ds . $filename; if (file_exists($file)) { return realpath($file); } } return false; } } } if (!class_exists('Math_BigInteger')) { define('MATH_BIGINTEGER_MONTGOMERY', 0); define('MATH_BIGINTEGER_BARRETT', 1); define('MATH_BIGINTEGER_POWEROF2', 2); define('MATH_BIGINTEGER_CLASSIC', 3); define('MATH_BIGINTEGER_NONE', 4); define('MATH_BIGINTEGER_VALUE', 0); define('MATH_BIGINTEGER_SIGN', 1); define('MATH_BIGINTEGER_VARIABLE', 0); define('MATH_BIGINTEGER_DATA', 1); define('MATH_BIGINTEGER_MODE_INTERNAL', 1); define('MATH_BIGINTEGER_MODE_BCMATH', 2); define('MATH_BIGINTEGER_MODE_GMP', 3); define('MATH_BIGINTEGER_KARATSUBA_CUTOFF', 25); class Math_BigInteger { var $value; var $is_negative = false; var $precision = -1; var $bitmask = false; var $hex; function __construct($x = 0, $base = 10) { if (!defined('MATH_BIGINTEGER_MODE')) { if (extension_loaded('gmp')) { define('MATH_BIGINTEGER_MODE', MATH_BIGINTEGER_MODE_GMP); } elseif (extension_loaded('bcmath')) { define('MATH_BIGINTEGER_MODE', MATH_BIGINTEGER_MODE_BCMATH); } else { define('MATH_BIGINTEGER_MODE', MATH_BIGINTEGER_MODE_INTERNAL); } } if (extension_loaded('openssl') && !defined('MATH_BIGINTEGER_OPENSSL_DISABLE') && !defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) { ob_start(); @phpinfo(); $content = ob_get_contents(); ob_end_clean(); preg_match_all('#OpenSSL (Header|Library) Version(.*)#im', $content, $matches); $versions = array(); if (!empty($matches[1])) { for ($i = 0; $i < count($matches[1]); $i++) { $fullVersion = trim(str_replace('=>', '', strip_tags($matches[2][$i]))); if (!preg_match('/(\d+\.\d+\.\d+)/i', $fullVersion, $m)) { $versions[$matches[1][$i]] = $fullVersion; } else { $versions[$matches[1][$i]] = $m[0]; } } } switch (true) { case !isset($versions['Header']): case !isset($versions['Library']): case $versions['Header'] == $versions['Library']: case version_compare($versions['Header'], '1.0.0') >= 0 && version_compare($versions['Library'], '1.0.0') >= 0: define('MATH_BIGINTEGER_OPENSSL_ENABLED', true); break; default: define('MATH_BIGINTEGER_OPENSSL_DISABLE', true); } } if (!defined('PHP_INT_SIZE')) { define('PHP_INT_SIZE', 4); } if (!defined('MATH_BIGINTEGER_BASE') && MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_INTERNAL) { switch (PHP_INT_SIZE) { case 8: define('MATH_BIGINTEGER_BASE', 31); define('MATH_BIGINTEGER_BASE_FULL', 0x80000000); define('MATH_BIGINTEGER_MAX_DIGIT', 0x7FFFFFFF); define('MATH_BIGINTEGER_MSB', 0x40000000); define('MATH_BIGINTEGER_MAX10', 1000000000); define('MATH_BIGINTEGER_MAX10_LEN', 9); define('MATH_BIGINTEGER_MAX_DIGIT2', pow(2, 62)); break; default: define('MATH_BIGINTEGER_BASE', 26); define('MATH_BIGINTEGER_BASE_FULL', 0x4000000); define('MATH_BIGINTEGER_MAX_DIGIT', 0x3FFFFFF); define('MATH_BIGINTEGER_MSB', 0x2000000); define('MATH_BIGINTEGER_MAX10', 10000000); define('MATH_BIGINTEGER_MAX10_LEN', 7); define('MATH_BIGINTEGER_MAX_DIGIT2', pow(2, 52)); } } switch (MATH_BIGINTEGER_MODE) { case MATH_BIGINTEGER_MODE_GMP: switch (true) { case is_resource($x) && get_resource_type($x) == 'GMP integer': case is_object($x) && get_class($x) == 'GMP': $this->value = $x; return; } $this->value = gmp_init(0); break; case MATH_BIGINTEGER_MODE_BCMATH: $this->value = '0'; break; default: $this->value = array(); } if (empty($x) && (abs($base) != 256 || $x !== '0')) { return; } switch ($base) { case -256: if (ord($x[0]) & 0x80) { $x = ~$x; $this->is_negative = true; } case 256: switch (MATH_BIGINTEGER_MODE) { case MATH_BIGINTEGER_MODE_GMP: $sign = $this->is_negative ? '-' : ''; $this->value = gmp_init($sign . '0x' . bin2hex($x)); break; case MATH_BIGINTEGER_MODE_BCMATH: $len = (strlen($x) + 3) & 0xFFFFFFFC; $x = str_pad($x, $len, chr(0), STR_PAD_LEFT); for ($i = 0; $i < $len; $i+= 4) { $this->value = bcmul($this->value, '4294967296', 0); $this->value = bcadd($this->value, 0x1000000 * ord($x[$i]) + ((ord($x[$i + 1]) << 16) | (ord($x[$i + 2]) << 8) | ord($x[$i + 3])), 0); } if ($this->is_negative) { $this->value = '-' . $this->value; } break; default: while (strlen($x)) { $this->value[] = $this->_bytes2int($this->_base256_rshift($x, MATH_BIGINTEGER_BASE)); } } if ($this->is_negative) { if (MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_INTERNAL) { $this->is_negative = false; } $temp = $this->add(new Math_BigInteger('-1')); $this->value = $temp->value; } break; case 16: case -16: if ($base > 0 && $x[0] == '-') { $this->is_negative = true; $x = substr($x, 1); } $x = preg_replace('#^(?:0x)?([A-Fa-f0-9]*).*#', '$1', $x); $is_negative = false; if ($base < 0 && hexdec($x[0]) >= 8) { $this->is_negative = $is_negative = true; $x = bin2hex(~pack('H*', $x)); } switch (MATH_BIGINTEGER_MODE) { case MATH_BIGINTEGER_MODE_GMP: $temp = $this->is_negative ? '-0x' . $x : '0x' . $x; $this->value = gmp_init($temp); $this->is_negative = false; break; case MATH_BIGINTEGER_MODE_BCMATH: $x = (strlen($x) & 1) ? '0' . $x : $x; $temp = new Math_BigInteger(pack('H*', $x), 256); $this->value = $this->is_negative ? '-' . $temp->value : $temp->value; $this->is_negative = false; break; default: $x = (strlen($x) & 1) ? '0' . $x : $x; $temp = new Math_BigInteger(pack('H*', $x), 256); $this->value = $temp->value; } if ($is_negative) { $temp = $this->add(new Math_BigInteger('-1')); $this->value = $temp->value; } break; case 10: case -10: $x = preg_replace('#(?<!^)(?:-).*|(?<=^|-)0*|[^-0-9].*#', '', $x); switch (MATH_BIGINTEGER_MODE) { case MATH_BIGINTEGER_MODE_GMP: $this->value = gmp_init($x); break; case MATH_BIGINTEGER_MODE_BCMATH: $this->value = $x === '-' ? '0' : (string) $x; break; default: $temp = new Math_BigInteger(); $multiplier = new Math_BigInteger(); $multiplier->value = array(MATH_BIGINTEGER_MAX10); if ($x[0] == '-') { $this->is_negative = true; $x = substr($x, 1); } $x = str_pad($x, strlen($x) + ((MATH_BIGINTEGER_MAX10_LEN - 1) * strlen($x)) % MATH_BIGINTEGER_MAX10_LEN, 0, STR_PAD_LEFT); while (strlen($x)) { $temp = $temp->multiply($multiplier); $temp = $temp->add(new Math_BigInteger($this->_int2bytes(substr($x, 0, MATH_BIGINTEGER_MAX10_LEN)), 256)); $x = substr($x, MATH_BIGINTEGER_MAX10_LEN); } $this->value = $temp->value; } break; case 2: case -2: if ($base > 0 && $x[0] == '-') { $this->is_negative = true; $x = substr($x, 1); } $x = preg_replace('#^([01]*).*#', '$1', $x); $x = str_pad($x, strlen($x) + (3 * strlen($x)) % 4, 0, STR_PAD_LEFT); $str = '0x'; while (strlen($x)) { $part = substr($x, 0, 4); $str.= dechex(bindec($part)); $x = substr($x, 4); } if ($this->is_negative) { $str = '-' . $str; } $temp = new Math_BigInteger($str, 8 * $base); $this->value = $temp->value; $this->is_negative = $temp->is_negative; break; default: } } function Math_BigInteger($x = 0, $base = 10) { $this->__construct($x, $base); } function toBytes($twos_compliment = false) { if ($twos_compliment) { $comparison = $this->compare(new Math_BigInteger()); if ($comparison == 0) { return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : ''; } $temp = $comparison < 0 ? $this->add(new Math_BigInteger(1)) : $this->copy(); $bytes = $temp->toBytes(); if (empty($bytes)) { $bytes = chr(0); } if (ord($bytes[0]) & 0x80) { $bytes = chr(0) . $bytes; } return $comparison < 0 ? ~$bytes : $bytes; } switch (MATH_BIGINTEGER_MODE) { case MATH_BIGINTEGER_MODE_GMP: if (gmp_cmp($this->value, gmp_init(0)) == 0) { return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : ''; } $temp = gmp_strval(gmp_abs($this->value), 16); $temp = (strlen($temp) & 1) ? '0' . $temp : $temp; $temp = pack('H*', $temp); return $this->precision > 0 ? substr(str_pad($temp, $this->precision >> 3, chr(0), STR_PAD_LEFT), -($this->precision >> 3)) : ltrim($temp, chr(0)); case MATH_BIGINTEGER_MODE_BCMATH: if ($this->value === '0') { return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : ''; } $value = ''; $current = $this->value; if ($current[0] == '-') { $current = substr($current, 1); } while (bccomp($current, '0', 0) > 0) { $temp = bcmod($current, '16777216'); $value = chr($temp >> 16) . chr($temp >> 8) . chr($temp) . $value; $current = bcdiv($current, '16777216', 0); } return $this->precision > 0 ? substr(str_pad($value, $this->precision >> 3, chr(0), STR_PAD_LEFT), -($this->precision >> 3)) : ltrim($value, chr(0)); } if (!count($this->value)) { return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : ''; } $result = $this->_int2bytes($this->value[count($this->value) - 1]); $temp = $this->copy(); for ($i = count($temp->value) - 2; $i >= 0; --$i) { $temp->_base256_lshift($result, MATH_BIGINTEGER_BASE); $result = $result | str_pad($temp->_int2bytes($temp->value[$i]), strlen($result), chr(0), STR_PAD_LEFT); } return $this->precision > 0 ? str_pad(substr($result, -(($this->precision + 7) >> 3)), ($this->precision + 7) >> 3, chr(0), STR_PAD_LEFT) : $result; } function toHex($twos_compliment = false) { return bin2hex($this->toBytes($twos_compliment)); } function toBits($twos_compliment = false) { $hex = $this->toHex($twos_compliment); $bits = ''; for ($i = strlen($hex) - 8, $start = strlen($hex) & 7; $i >= $start; $i-=8) { $bits = str_pad(decbin(hexdec(substr($hex, $i, 8))), 32, '0', STR_PAD_LEFT) . $bits; } if ($start) { $bits = str_pad(decbin(hexdec(substr($hex, 0, $start))), 8, '0', STR_PAD_LEFT) . $bits; } $result = $this->precision > 0 ? substr($bits, -$this->precision) : ltrim($bits, '0'); if ($twos_compliment && $this->compare(new Math_BigInteger()) > 0 && $this->precision <= 0) { return '0' . $result; } return $result; } function toString() { switch (MATH_BIGINTEGER_MODE) { case MATH_BIGINTEGER_MODE_GMP: return gmp_strval($this->value); case MATH_BIGINTEGER_MODE_BCMATH: if ($this->value === '0') { return '0'; } return ltrim($this->value, '0'); } if (!count($this->value)) { return '0'; } $temp = $this->copy(); $temp->is_negative = false; $divisor = new Math_BigInteger(); $divisor->value = array(MATH_BIGINTEGER_MAX10); $result = ''; while (count($temp->value)) { list($temp, $mod) = $temp->divide($divisor); $result = str_pad(isset($mod->value[0]) ? $mod->value[0] : '', MATH_BIGINTEGER_MAX10_LEN, '0', STR_PAD_LEFT) . $result; } $result = ltrim($result, '0'); if (empty($result)) { $result = '0'; } if ($this->is_negative) { $result = '-' . $result; } return $result; } function copy() { $temp = new Math_BigInteger(); $temp->value = $this->value; $temp->is_negative = $this->is_negative; $temp->precision = $this->precision; $temp->bitmask = $this->bitmask; return $temp; } function __toString() { return $this->toString(); } function __clone() { return $this->copy(); } function __sleep() { $this->hex = $this->toHex(true); $vars = array('hex'); if ($this->precision > 0) { $vars[] = 'precision'; } return $vars; } function __wakeup() { $temp = new Math_BigInteger($this->hex, -16); $this->value = $temp->value; $this->is_negative = $temp->is_negative; if ($this->precision > 0) { $this->setPrecision($this->precision); } } function __debugInfo() { $opts = array(); switch (MATH_BIGINTEGER_MODE) { case MATH_BIGINTEGER_MODE_GMP: $engine = 'gmp'; break; case MATH_BIGINTEGER_MODE_BCMATH: $engine = 'bcmath'; break; case MATH_BIGINTEGER_MODE_INTERNAL: $engine = 'internal'; $opts[] = PHP_INT_SIZE == 8 ? '64-bit' : '32-bit'; } if (MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_GMP && defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) { $opts[] = 'OpenSSL'; } if (!empty($opts)) { $engine.= ' (' . implode($opts, ', ') . ')'; } return array( 'value' => '0x' . $this->toHex(true), 'engine' => $engine ); } function add($y) { switch (MATH_BIGINTEGER_MODE) { case MATH_BIGINTEGER_MODE_GMP: $temp = new Math_BigInteger(); $temp->value = gmp_add($this->value, $y->value); return $this->_normalize($temp); case MATH_BIGINTEGER_MODE_BCMATH: $temp = new Math_BigInteger(); $temp->value = bcadd($this->value, $y->value, 0); return $this->_normalize($temp); } $temp = $this->_add($this->value, $this->is_negative, $y->value, $y->is_negative); $result = new Math_BigInteger(); $result->value = $temp[MATH_BIGINTEGER_VALUE]; $result->is_negative = $temp[MATH_BIGINTEGER_SIGN]; return $this->_normalize($result); } function _add($x_value, $x_negative, $y_value, $y_negative) { $x_size = count($x_value); $y_size = count($y_value); if ($x_size == 0) { return array( MATH_BIGINTEGER_VALUE => $y_value, MATH_BIGINTEGER_SIGN => $y_negative ); } elseif ($y_size == 0) { return array( MATH_BIGINTEGER_VALUE => $x_value, MATH_BIGINTEGER_SIGN => $x_negative ); } if ($x_negative != $y_negative) { if ($x_value == $y_value) { return array( MATH_BIGINTEGER_VALUE => array(), MATH_BIGINTEGER_SIGN => false ); } $temp = $this->_subtract($x_value, false, $y_value, false); $temp[MATH_BIGINTEGER_SIGN] = $this->_compare($x_value, false, $y_value, false) > 0 ? $x_negative : $y_negative; return $temp; } if ($x_size < $y_size) { $size = $x_size; $value = $y_value; } else { $size = $y_size; $value = $x_value; } $value[count($value)] = 0; $carry = 0; for ($i = 0, $j = 1; $j < $size; $i+=2, $j+=2) { $sum = $x_value[$j] * MATH_BIGINTEGER_BASE_FULL + $x_value[$i] + $y_value[$j] * MATH_BIGINTEGER_BASE_FULL + $y_value[$i] + $carry; $carry = $sum >= MATH_BIGINTEGER_MAX_DIGIT2; $sum = $carry ? $sum - MATH_BIGINTEGER_MAX_DIGIT2 : $sum; $temp = MATH_BIGINTEGER_BASE === 26 ? intval($sum / 0x4000000) : ($sum >> 31); $value[$i] = (int) ($sum - MATH_BIGINTEGER_BASE_FULL * $temp); $value[$j] = $temp; } if ($j == $size) { $sum = $x_value[$i] + $y_value[$i] + $carry; $carry = $sum >= MATH_BIGINTEGER_BASE_FULL; $value[$i] = $carry ? $sum - MATH_BIGINTEGER_BASE_FULL : $sum; ++$i; } if ($carry) { for (; $value[$i] == MATH_BIGINTEGER_MAX_DIGIT; ++$i) { $value[$i] = 0; } ++$value[$i]; } return array( MATH_BIGINTEGER_VALUE => $this->_trim($value), MATH_BIGINTEGER_SIGN => $x_negative ); } function subtract($y) { switch (MATH_BIGINTEGER_MODE) { case MATH_BIGINTEGER_MODE_GMP: $temp = new Math_BigInteger(); $temp->value = gmp_sub($this->value, $y->value); return $this->_normalize($temp); case MATH_BIGINTEGER_MODE_BCMATH: $temp = new Math_BigInteger(); $temp->value = bcsub($this->value, $y->value, 0); return $this->_normalize($temp); } $temp = $this->_subtract($this->value, $this->is_negative, $y->value, $y->is_negative); $result = new Math_BigInteger(); $result->value = $temp[MATH_BIGINTEGER_VALUE]; $result->is_negative = $temp[MATH_BIGINTEGER_SIGN]; return $this->_normalize($result); } function _subtract($x_value, $x_negative, $y_value, $y_negative) { $x_size = count($x_value); $y_size = count($y_value); if ($x_size == 0) { return array( MATH_BIGINTEGER_VALUE => $y_value, MATH_BIGINTEGER_SIGN => !$y_negative ); } elseif ($y_size == 0) { return array( MATH_BIGINTEGER_VALUE => $x_value, MATH_BIGINTEGER_SIGN => $x_negative ); } if ($x_negative != $y_negative) { $temp = $this->_add($x_value, false, $y_value, false); $temp[MATH_BIGINTEGER_SIGN] = $x_negative; return $temp; } $diff = $this->_compare($x_value, $x_negative, $y_value, $y_negative); if (!$diff) { return array( MATH_BIGINTEGER_VALUE => array(), MATH_BIGINTEGER_SIGN => false ); } if ((!$x_negative && $diff < 0) || ($x_negative && $diff > 0)) { $temp = $x_value; $x_value = $y_value; $y_value = $temp; $x_negative = !$x_negative; $x_size = count($x_value); $y_size = count($y_value); } $carry = 0; for ($i = 0, $j = 1; $j < $y_size; $i+=2, $j+=2) { $sum = $x_value[$j] * MATH_BIGINTEGER_BASE_FULL + $x_value[$i] - $y_value[$j] * MATH_BIGINTEGER_BASE_FULL - $y_value[$i] - $carry; $carry = $sum < 0; $sum = $carry ? $sum + MATH_BIGINTEGER_MAX_DIGIT2 : $sum; $temp = MATH_BIGINTEGER_BASE === 26 ? intval($sum / 0x4000000) : ($sum >> 31); $x_value[$i] = (int) ($sum - MATH_BIGINTEGER_BASE_FULL * $temp); $x_value[$j] = $temp; } if ($j == $y_size) { $sum = $x_value[$i] - $y_value[$i] - $carry; $carry = $sum < 0; $x_value[$i] = $carry ? $sum + MATH_BIGINTEGER_BASE_FULL : $sum; ++$i; } if ($carry) { for (; !$x_value[$i]; ++$i) { $x_value[$i] = MATH_BIGINTEGER_MAX_DIGIT; } --$x_value[$i]; } return array( MATH_BIGINTEGER_VALUE => $this->_trim($x_value), MATH_BIGINTEGER_SIGN => $x_negative ); } function multiply($x) { switch (MATH_BIGINTEGER_MODE) { case MATH_BIGINTEGER_MODE_GMP: $temp = new Math_BigInteger(); $temp->value = gmp_mul($this->value, $x->value); return $this->_normalize($temp); case MATH_BIGINTEGER_MODE_BCMATH: $temp = new Math_BigInteger(); $temp->value = bcmul($this->value, $x->value, 0); return $this->_normalize($temp); } $temp = $this->_multiply($this->value, $this->is_negative, $x->value, $x->is_negative); $product = new Math_BigInteger(); $product->value = $temp[MATH_BIGINTEGER_VALUE]; $product->is_negative = $temp[MATH_BIGINTEGER_SIGN]; return $this->_normalize($product); } function _multiply($x_value, $x_negative, $y_value, $y_negative) { $x_length = count($x_value); $y_length = count($y_value); if (!$x_length || !$y_length) { return array( MATH_BIGINTEGER_VALUE => array(), MATH_BIGINTEGER_SIGN => false ); } return array( MATH_BIGINTEGER_VALUE => min($x_length, $y_length) < 2 * MATH_BIGINTEGER_KARATSUBA_CUTOFF ? $this->_trim($this->_regularMultiply($x_value, $y_value)) : $this->_trim($this->_karatsuba($x_value, $y_value)), MATH_BIGINTEGER_SIGN => $x_negative != $y_negative ); } function _regularMultiply($x_value, $y_value) { $x_length = count($x_value); $y_length = count($y_value); if (!$x_length || !$y_length) { return array(); } if ($x_length < $y_length) { $temp = $x_value; $x_value = $y_value; $y_value = $temp; $x_length = count($x_value); $y_length = count($y_value); } $product_value = $this->_array_repeat(0, $x_length + $y_length); $carry = 0; for ($j = 0; $j < $x_length; ++$j) { $temp = $x_value[$j] * $y_value[0] + $carry; $carry = MATH_BIGINTEGER_BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31); $product_value[$j] = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * $carry); } $product_value[$j] = $carry; for ($i = 1; $i < $y_length; ++$i) { $carry = 0; for ($j = 0, $k = $i; $j < $x_length; ++$j, ++$k) { $temp = $product_value[$k] + $x_value[$j] * $y_value[$i] + $carry; $carry = MATH_BIGINTEGER_BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31); $product_value[$k] = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * $carry); } $product_value[$k] = $carry; } return $product_value; } function _karatsuba($x_value, $y_value) { $m = min(count($x_value) >> 1, count($y_value) >> 1); if ($m < MATH_BIGINTEGER_KARATSUBA_CUTOFF) { return $this->_regularMultiply($x_value, $y_value); } $x1 = array_slice($x_value, $m); $x0 = array_slice($x_value, 0, $m); $y1 = array_slice($y_value, $m); $y0 = array_slice($y_value, 0, $m); $z2 = $this->_karatsuba($x1, $y1); $z0 = $this->_karatsuba($x0, $y0); $z1 = $this->_add($x1, false, $x0, false); $temp = $this->_add($y1, false, $y0, false); $z1 = $this->_karatsuba($z1[MATH_BIGINTEGER_VALUE], $temp[MATH_BIGINTEGER_VALUE]); $temp = $this->_add($z2, false, $z0, false); $z1 = $this->_subtract($z1, false, $temp[MATH_BIGINTEGER_VALUE], false); $z2 = array_merge(array_fill(0, 2 * $m, 0), $z2); $z1[MATH_BIGINTEGER_VALUE] = array_merge(array_fill(0, $m, 0), $z1[MATH_BIGINTEGER_VALUE]); $xy = $this->_add($z2, false, $z1[MATH_BIGINTEGER_VALUE], $z1[MATH_BIGINTEGER_SIGN]); $xy = $this->_add($xy[MATH_BIGINTEGER_VALUE], $xy[MATH_BIGINTEGER_SIGN], $z0, false); return $xy[MATH_BIGINTEGER_VALUE]; } function _square($x = false) { return count($x) < 2 * MATH_BIGINTEGER_KARATSUBA_CUTOFF ? $this->_trim($this->_baseSquare($x)) : $this->_trim($this->_karatsubaSquare($x)); } function _baseSquare($value) { if (empty($value)) { return array(); } $square_value = $this->_array_repeat(0, 2 * count($value)); for ($i = 0, $max_index = count($value) - 1; $i <= $max_index; ++$i) { $i2 = $i << 1; $temp = $square_value[$i2] + $value[$i] * $value[$i]; $carry = MATH_BIGINTEGER_BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31); $square_value[$i2] = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * $carry); for ($j = $i + 1, $k = $i2 + 1; $j <= $max_index; ++$j, ++$k) { $temp = $square_value[$k] + 2 * $value[$j] * $value[$i] + $carry; $carry = MATH_BIGINTEGER_BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31); $square_value[$k] = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * $carry); } $square_value[$i + $max_index + 1] = $carry; } return $square_value; } function _karatsubaSquare($value) { $m = count($value) >> 1; if ($m < MATH_BIGINTEGER_KARATSUBA_CUTOFF) { return $this->_baseSquare($value); } $x1 = array_slice($value, $m); $x0 = array_slice($value, 0, $m); $z2 = $this->_karatsubaSquare($x1); $z0 = $this->_karatsubaSquare($x0); $z1 = $this->_add($x1, false, $x0, false); $z1 = $this->_karatsubaSquare($z1[MATH_BIGINTEGER_VALUE]); $temp = $this->_add($z2, false, $z0, false); $z1 = $this->_subtract($z1, false, $temp[MATH_BIGINTEGER_VALUE], false); $z2 = array_merge(array_fill(0, 2 * $m, 0), $z2); $z1[MATH_BIGINTEGER_VALUE] = array_merge(array_fill(0, $m, 0), $z1[MATH_BIGINTEGER_VALUE]); $xx = $this->_add($z2, false, $z1[MATH_BIGINTEGER_VALUE], $z1[MATH_BIGINTEGER_SIGN]); $xx = $this->_add($xx[MATH_BIGINTEGER_VALUE], $xx[MATH_BIGINTEGER_SIGN], $z0, false); return $xx[MATH_BIGINTEGER_VALUE]; } function divide($y) { switch (MATH_BIGINTEGER_MODE) { case MATH_BIGINTEGER_MODE_GMP: $quotient = new Math_BigInteger(); $remainder = new Math_BigInteger(); list($quotient->value, $remainder->value) = gmp_div_qr($this->value, $y->value); if (gmp_sign($remainder->value) < 0) { $remainder->value = gmp_add($remainder->value, gmp_abs($y->value)); } return array($this->_normalize($quotient), $this->_normalize($remainder)); case MATH_BIGINTEGER_MODE_BCMATH: $quotient = new Math_BigInteger(); $remainder = new Math_BigInteger(); $quotient->value = bcdiv($this->value, $y->value, 0); $remainder->value = bcmod($this->value, $y->value); if ($remainder->value[0] == '-') { $remainder->value = bcadd($remainder->value, $y->value[0] == '-' ? substr($y->value, 1) : $y->value, 0); } return array($this->_normalize($quotient), $this->_normalize($remainder)); } if (count($y->value) == 1) { list($q, $r) = $this->_divide_digit($this->value, $y->value[0]); $quotient = new Math_BigInteger(); $remainder = new Math_BigInteger(); $quotient->value = $q; $remainder->value = array($r); $quotient->is_negative = $this->is_negative != $y->is_negative; return array($this->_normalize($quotient), $this->_normalize($remainder)); } static $zero; if (!isset($zero)) { $zero = new Math_BigInteger(); } $x = $this->copy(); $y = $y->copy(); $x_sign = $x->is_negative; $y_sign = $y->is_negative; $x->is_negative = $y->is_negative = false; $diff = $x->compare($y); if (!$diff) { $temp = new Math_BigInteger(); $temp->value = array(1); $temp->is_negative = $x_sign != $y_sign; return array($this->_normalize($temp), $this->_normalize(new Math_BigInteger())); } if ($diff < 0) { if ($x_sign) { $x = $y->subtract($x); } return array($this->_normalize(new Math_BigInteger()), $this->_normalize($x)); } $msb = $y->value[count($y->value) - 1]; for ($shift = 0; !($msb & MATH_BIGINTEGER_MSB); ++$shift) { $msb <<= 1; } $x->_lshift($shift); $y->_lshift($shift); $y_value = &$y->value; $x_max = count($x->value) - 1; $y_max = count($y->value) - 1; $quotient = new Math_BigInteger(); $quotient_value = &$quotient->value; $quotient_value = $this->_array_repeat(0, $x_max - $y_max + 1); static $temp, $lhs, $rhs; if (!isset($temp)) { $temp = new Math_BigInteger(); $lhs = new Math_BigInteger(); $rhs = new Math_BigInteger(); } $temp_value = &$temp->value; $rhs_value = &$rhs->value; $temp_value = array_merge($this->_array_repeat(0, $x_max - $y_max), $y_value); while ($x->compare($temp) >= 0) { ++$quotient_value[$x_max - $y_max]; $x = $x->subtract($temp); $x_max = count($x->value) - 1; } for ($i = $x_max; $i >= $y_max + 1; --$i) { $x_value = &$x->value; $x_window = array( isset($x_value[$i]) ? $x_value[$i] : 0, isset($x_value[$i - 1]) ? $x_value[$i - 1] : 0, isset($x_value[$i - 2]) ? $x_value[$i - 2] : 0 ); $y_window = array( $y_value[$y_max], ($y_max > 0) ? $y_value[$y_max - 1] : 0 ); $q_index = $i - $y_max - 1; if ($x_window[0] == $y_window[0]) { $quotient_value[$q_index] = MATH_BIGINTEGER_MAX_DIGIT; } else { $quotient_value[$q_index] = $this->_safe_divide( $x_window[0] * MATH_BIGINTEGER_BASE_FULL + $x_window[1], $y_window[0] ); } $temp_value = array($y_window[1], $y_window[0]); $lhs->value = array($quotient_value[$q_index]); $lhs = $lhs->multiply($temp); $rhs_value = array($x_window[2], $x_window[1], $x_window[0]); while ($lhs->compare($rhs) > 0) { --$quotient_value[$q_index]; $lhs->value = array($quotient_value[$q_index]); $lhs = $lhs->multiply($temp); } $adjust = $this->_array_repeat(0, $q_index); $temp_value = array($quotient_value[$q_index]); $temp = $temp->multiply($y); $temp_value = &$temp->value; $temp_value = array_merge($adjust, $temp_value); $x = $x->subtract($temp); if ($x->compare($zero) < 0) { $temp_value = array_merge($adjust, $y_value); $x = $x->add($temp); --$quotient_value[$q_index]; } $x_max = count($x_value) - 1; } $x->_rshift($shift); $quotient->is_negative = $x_sign != $y_sign; if ($x_sign) { $y->_rshift($shift); $x = $y->subtract($x); } return array($this->_normalize($quotient), $this->_normalize($x)); } function _divide_digit($dividend, $divisor) { $carry = 0; $result = array(); for ($i = count($dividend) - 1; $i >= 0; --$i) { $temp = MATH_BIGINTEGER_BASE_FULL * $carry + $dividend[$i]; $result[$i] = $this->_safe_divide($temp, $divisor); $carry = (int) ($temp - $divisor * $result[$i]); } return array($result, $carry); } function modPow($e, $n) { $n = $this->bitmask !== false && $this->bitmask->compare($n) < 0 ? $this->bitmask : $n->abs(); if ($e->compare(new Math_BigInteger()) < 0) { $e = $e->abs(); $temp = $this->modInverse($n); if ($temp === false) { return false; } return $this->_normalize($temp->modPow($e, $n)); } if (MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_GMP) { $temp = new Math_BigInteger(); $temp->value = gmp_powm($this->value, $e->value, $n->value); return $this->_normalize($temp); } if ($this->compare(new Math_BigInteger()) < 0 || $this->compare($n) > 0) { list(, $temp) = $this->divide($n); return $temp->modPow($e, $n); } if (defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) { $components = array( 'modulus' => $n->toBytes(true), 'publicExponent' => $e->toBytes(true) ); $components = array( 'modulus' => pack('Ca*a*', 2, $this->_encodeASN1Length(strlen($components['modulus'])), $components['modulus']), 'publicExponent' => pack('Ca*a*', 2, $this->_encodeASN1Length(strlen($components['publicExponent'])), $components['publicExponent']) ); $RSAPublicKey = pack( 'Ca*a*a*', 48, $this->_encodeASN1Length(strlen($components['modulus']) + strlen($components['publicExponent'])), $components['modulus'], $components['publicExponent'] ); $rsaOID = pack('H*', '300d06092a864886f70d0101010500'); $RSAPublicKey = chr(0) . $RSAPublicKey; $RSAPublicKey = chr(3) . $this->_encodeASN1Length(strlen($RSAPublicKey)) . $RSAPublicKey; $encapsulated = pack( 'Ca*a*', 48, $this->_encodeASN1Length(strlen($rsaOID . $RSAPublicKey)), $rsaOID . $RSAPublicKey ); $RSAPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" . chunk_split(base64_encode($encapsulated)) . '-----END PUBLIC KEY-----'; $plaintext = str_pad($this->toBytes(), strlen($n->toBytes(true)) - 1, "\0", STR_PAD_LEFT); if (openssl_public_encrypt($plaintext, $result, $RSAPublicKey, OPENSSL_NO_PADDING)) { return new Math_BigInteger($result, 256); } } if (MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_BCMATH) { $temp = new Math_BigInteger(); $temp->value = bcpowmod($this->value, $e->value, $n->value, 0); return $this->_normalize($temp); } if (empty($e->value)) { $temp = new Math_BigInteger(); $temp->value = array(1); return $this->_normalize($temp); } if ($e->value == array(1)) { list(, $temp) = $this->divide($n); return $this->_normalize($temp); } if ($e->value == array(2)) { $temp = new Math_BigInteger(); $temp->value = $this->_square($this->value); list(, $temp) = $temp->divide($n); return $this->_normalize($temp); } return $this->_normalize($this->_slidingWindow($e, $n, MATH_BIGINTEGER_BARRETT)); if ($n->value[0] & 1) { return $this->_normalize($this->_slidingWindow($e, $n, MATH_BIGINTEGER_MONTGOMERY)); } for ($i = 0; $i < count($n->value); ++$i) { if ($n->value[$i]) { $temp = decbin($n->value[$i]); $j = strlen($temp) - strrpos($temp, '1') - 1; $j+= 26 * $i; break; } } $mod1 = $n->copy(); $mod1->_rshift($j); $mod2 = new Math_BigInteger(); $mod2->value = array(1); $mod2->_lshift($j); $part1 = ($mod1->value != array(1)) ? $this->_slidingWindow($e, $mod1, MATH_BIGINTEGER_MONTGOMERY) : new Math_BigInteger(); $part2 = $this->_slidingWindow($e, $mod2, MATH_BIGINTEGER_POWEROF2); $y1 = $mod2->modInverse($mod1); $y2 = $mod1->modInverse($mod2); $result = $part1->multiply($mod2); $result = $result->multiply($y1); $temp = $part2->multiply($mod1); $temp = $temp->multiply($y2); $result = $result->add($temp); list(, $result) = $result->divide($n); return $this->_normalize($result); } function powMod($e, $n) { return $this->modPow($e, $n); } function _slidingWindow($e, $n, $mode) { static $window_ranges = array(7, 25, 81, 241, 673, 1793); $e_value = $e->value; $e_length = count($e_value) - 1; $e_bits = decbin($e_value[$e_length]); for ($i = $e_length - 1; $i >= 0; --$i) { $e_bits.= str_pad(decbin($e_value[$i]), MATH_BIGINTEGER_BASE, '0', STR_PAD_LEFT); } $e_length = strlen($e_bits); for ($i = 0, $window_size = 1; $i < count($window_ranges) && $e_length > $window_ranges[$i]; ++$window_size, ++$i) { } $n_value = $n->value; $powers = array(); $powers[1] = $this->_prepareReduce($this->value, $n_value, $mode); $powers[2] = $this->_squareReduce($powers[1], $n_value, $mode); $temp = 1 << ($window_size - 1); for ($i = 1; $i < $temp; ++$i) { $i2 = $i << 1; $powers[$i2 + 1] = $this->_multiplyReduce($powers[$i2 - 1], $powers[2], $n_value, $mode); } $result = array(1); $result = $this->_prepareReduce($result, $n_value, $mode); for ($i = 0; $i < $e_length;) { if (!$e_bits[$i]) { $result = $this->_squareReduce($result, $n_value, $mode); ++$i; } else { for ($j = $window_size - 1; $j > 0; --$j) { if (!empty($e_bits[$i + $j])) { break; } } for ($k = 0; $k <= $j; ++$k) { $result = $this->_squareReduce($result, $n_value, $mode); } $result = $this->_multiplyReduce($result, $powers[bindec(substr($e_bits, $i, $j + 1))], $n_value, $mode); $i += $j + 1; } } $temp = new Math_BigInteger(); $temp->value = $this->_reduce($result, $n_value, $mode); return $temp; } function _reduce($x, $n, $mode) { switch ($mode) { case MATH_BIGINTEGER_MONTGOMERY: return $this->_montgomery($x, $n); case MATH_BIGINTEGER_BARRETT: return $this->_barrett($x, $n); case MATH_BIGINTEGER_POWEROF2: $lhs = new Math_BigInteger(); $lhs->value = $x; $rhs = new Math_BigInteger(); $rhs->value = $n; return $x->_mod2($n); case MATH_BIGINTEGER_CLASSIC: $lhs = new Math_BigInteger(); $lhs->value = $x; $rhs = new Math_BigInteger(); $rhs->value = $n; list(, $temp) = $lhs->divide($rhs); return $temp->value; case MATH_BIGINTEGER_NONE: return $x; default: } } function _prepareReduce($x, $n, $mode) { if ($mode == MATH_BIGINTEGER_MONTGOMERY) { return $this->_prepMontgomery($x, $n); } return $this->_reduce($x, $n, $mode); } function _multiplyReduce($x, $y, $n, $mode) { if ($mode == MATH_BIGINTEGER_MONTGOMERY) { return $this->_montgomeryMultiply($x, $y, $n); } $temp = $this->_multiply($x, false, $y, false); return $this->_reduce($temp[MATH_BIGINTEGER_VALUE], $n, $mode); } function _squareReduce($x, $n, $mode) { if ($mode == MATH_BIGINTEGER_MONTGOMERY) { return $this->_montgomeryMultiply($x, $x, $n); } return $this->_reduce($this->_square($x), $n, $mode); } function _mod2($n) { $temp = new Math_BigInteger(); $temp->value = array(1); return $this->bitwise_and($n->subtract($temp)); } function _barrett($n, $m) { static $cache = array( MATH_BIGINTEGER_VARIABLE => array(), MATH_BIGINTEGER_DATA => array() ); $m_length = count($m); if (count($n) > 2 * $m_length) { $lhs = new Math_BigInteger(); $rhs = new Math_BigInteger(); $lhs->value = $n; $rhs->value = $m; list(, $temp) = $lhs->divide($rhs); return $temp->value; } if ($m_length < 5) { return $this->_regularBarrett($n, $m); } if (($key = array_search($m, $cache[MATH_BIGINTEGER_VARIABLE])) === false) { $key = count($cache[MATH_BIGINTEGER_VARIABLE]); $cache[MATH_BIGINTEGER_VARIABLE][] = $m; $lhs = new Math_BigInteger(); $lhs_value = &$lhs->value; $lhs_value = $this->_array_repeat(0, $m_length + ($m_length >> 1)); $lhs_value[] = 1; $rhs = new Math_BigInteger(); $rhs->value = $m; list($u, $m1) = $lhs->divide($rhs); $u = $u->value; $m1 = $m1->value; $cache[MATH_BIGINTEGER_DATA][] = array( 'u' => $u, 'm1'=> $m1 ); } else { extract($cache[MATH_BIGINTEGER_DATA][$key]); } $cutoff = $m_length + ($m_length >> 1); $lsd = array_slice($n, 0, $cutoff); $msd = array_slice($n, $cutoff); $lsd = $this->_trim($lsd); $temp = $this->_multiply($msd, false, $m1, false); $n = $this->_add($lsd, false, $temp[MATH_BIGINTEGER_VALUE], false); if ($m_length & 1) { return $this->_regularBarrett($n[MATH_BIGINTEGER_VALUE], $m); } $temp = array_slice($n[MATH_BIGINTEGER_VALUE], $m_length - 1); $temp = $this->_multiply($temp, false, $u, false); $temp = array_slice($temp[MATH_BIGINTEGER_VALUE], ($m_length >> 1) + 1); $temp = $this->_multiply($temp, false, $m, false); $result = $this->_subtract($n[MATH_BIGINTEGER_VALUE], false, $temp[MATH_BIGINTEGER_VALUE], false); while ($this->_compare($result[MATH_BIGINTEGER_VALUE], $result[MATH_BIGINTEGER_SIGN], $m, false) >= 0) { $result = $this->_subtract($result[MATH_BIGINTEGER_VALUE], $result[MATH_BIGINTEGER_SIGN], $m, false); } return $result[MATH_BIGINTEGER_VALUE]; } function _regularBarrett($x, $n) { static $cache = array( MATH_BIGINTEGER_VARIABLE => array(), MATH_BIGINTEGER_DATA => array() ); $n_length = count($n); if (count($x) > 2 * $n_length) { $lhs = new Math_BigInteger(); $rhs = new Math_BigInteger(); $lhs->value = $x; $rhs->value = $n; list(, $temp) = $lhs->divide($rhs); return $temp->value; } if (($key = array_search($n, $cache[MATH_BIGINTEGER_VARIABLE])) === false) { $key = count($cache[MATH_BIGINTEGER_VARIABLE]); $cache[MATH_BIGINTEGER_VARIABLE][] = $n; $lhs = new Math_BigInteger(); $lhs_value = &$lhs->value; $lhs_value = $this->_array_repeat(0, 2 * $n_length); $lhs_value[] = 1; $rhs = new Math_BigInteger(); $rhs->value = $n; list($temp, ) = $lhs->divide($rhs); $cache[MATH_BIGINTEGER_DATA][] = $temp->value; } $temp = array_slice($x, $n_length - 1); $temp = $this->_multiply($temp, false, $cache[MATH_BIGINTEGER_DATA][$key], false); $temp = array_slice($temp[MATH_BIGINTEGER_VALUE], $n_length + 1); $result = array_slice($x, 0, $n_length + 1); $temp = $this->_multiplyLower($temp, false, $n, false, $n_length + 1); if ($this->_compare($result, false, $temp[MATH_BIGINTEGER_VALUE], $temp[MATH_BIGINTEGER_SIGN]) < 0) { $corrector_value = $this->_array_repeat(0, $n_length + 1); $corrector_value[count($corrector_value)] = 1; $result = $this->_add($result, false, $corrector_value, false); $result = $result[MATH_BIGINTEGER_VALUE]; } $result = $this->_subtract($result, false, $temp[MATH_BIGINTEGER_VALUE], $temp[MATH_BIGINTEGER_SIGN]); while ($this->_compare($result[MATH_BIGINTEGER_VALUE], $result[MATH_BIGINTEGER_SIGN], $n, false) > 0) { $result = $this->_subtract($result[MATH_BIGINTEGER_VALUE], $result[MATH_BIGINTEGER_SIGN], $n, false); } return $result[MATH_BIGINTEGER_VALUE]; } function _multiplyLower($x_value, $x_negative, $y_value, $y_negative, $stop) { $x_length = count($x_value); $y_length = count($y_value); if (!$x_length || !$y_length) { return array( MATH_BIGINTEGER_VALUE => array(), MATH_BIGINTEGER_SIGN => false ); } if ($x_length < $y_length) { $temp = $x_value; $x_value = $y_value; $y_value = $temp; $x_length = count($x_value); $y_length = count($y_value); } $product_value = $this->_array_repeat(0, $x_length + $y_length); $carry = 0; for ($j = 0; $j < $x_length; ++$j) { $temp = $x_value[$j] * $y_value[0] + $carry; $carry = MATH_BIGINTEGER_BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31); $product_value[$j] = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * $carry); } if ($j < $stop) { $product_value[$j] = $carry; } for ($i = 1; $i < $y_length; ++$i) { $carry = 0; for ($j = 0, $k = $i; $j < $x_length && $k < $stop; ++$j, ++$k) { $temp = $product_value[$k] + $x_value[$j] * $y_value[$i] + $carry; $carry = MATH_BIGINTEGER_BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31); $product_value[$k] = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * $carry); } if ($k < $stop) { $product_value[$k] = $carry; } } return array( MATH_BIGINTEGER_VALUE => $this->_trim($product_value), MATH_BIGINTEGER_SIGN => $x_negative != $y_negative ); } function _montgomery($x, $n) { static $cache = array( MATH_BIGINTEGER_VARIABLE => array(), MATH_BIGINTEGER_DATA => array() ); if (($key = array_search($n, $cache[MATH_BIGINTEGER_VARIABLE])) === false) { $key = count($cache[MATH_BIGINTEGER_VARIABLE]); $cache[MATH_BIGINTEGER_VARIABLE][] = $x; $cache[MATH_BIGINTEGER_DATA][] = $this->_modInverse67108864($n); } $k = count($n); $result = array(MATH_BIGINTEGER_VALUE => $x); for ($i = 0; $i < $k; ++$i) { $temp = $result[MATH_BIGINTEGER_VALUE][$i] * $cache[MATH_BIGINTEGER_DATA][$key]; $temp = $temp - MATH_BIGINTEGER_BASE_FULL * (MATH_BIGINTEGER_BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31)); $temp = $this->_regularMultiply(array($temp), $n); $temp = array_merge($this->_array_repeat(0, $i), $temp); $result = $this->_add($result[MATH_BIGINTEGER_VALUE], false, $temp, false); } $result[MATH_BIGINTEGER_VALUE] = array_slice($result[MATH_BIGINTEGER_VALUE], $k); if ($this->_compare($result, false, $n, false) >= 0) { $result = $this->_subtract($result[MATH_BIGINTEGER_VALUE], false, $n, false); } return $result[MATH_BIGINTEGER_VALUE]; } function _montgomeryMultiply($x, $y, $m) { $temp = $this->_multiply($x, false, $y, false); return $this->_montgomery($temp[MATH_BIGINTEGER_VALUE], $m); static $cache = array( MATH_BIGINTEGER_VARIABLE => array(), MATH_BIGINTEGER_DATA => array() ); if (($key = array_search($m, $cache[MATH_BIGINTEGER_VARIABLE])) === false) { $key = count($cache[MATH_BIGINTEGER_VARIABLE]); $cache[MATH_BIGINTEGER_VARIABLE][] = $m; $cache[MATH_BIGINTEGER_DATA][] = $this->_modInverse67108864($m); } $n = max(count($x), count($y), count($m)); $x = array_pad($x, $n, 0); $y = array_pad($y, $n, 0); $m = array_pad($m, $n, 0); $a = array(MATH_BIGINTEGER_VALUE => $this->_array_repeat(0, $n + 1)); for ($i = 0; $i < $n; ++$i) { $temp = $a[MATH_BIGINTEGER_VALUE][0] + $x[$i] * $y[0]; $temp = $temp - MATH_BIGINTEGER_BASE_FULL * (MATH_BIGINTEGER_BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31)); $temp = $temp * $cache[MATH_BIGINTEGER_DATA][$key]; $temp = $temp - MATH_BIGINTEGER_BASE_FULL * (MATH_BIGINTEGER_BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31)); $temp = $this->_add($this->_regularMultiply(array($x[$i]), $y), false, $this->_regularMultiply(array($temp), $m), false); $a = $this->_add($a[MATH_BIGINTEGER_VALUE], false, $temp[MATH_BIGINTEGER_VALUE], false); $a[MATH_BIGINTEGER_VALUE] = array_slice($a[MATH_BIGINTEGER_VALUE], 1); } if ($this->_compare($a[MATH_BIGINTEGER_VALUE], false, $m, false) >= 0) { $a = $this->_subtract($a[MATH_BIGINTEGER_VALUE], false, $m, false); } return $a[MATH_BIGINTEGER_VALUE]; } function _prepMontgomery($x, $n) { $lhs = new Math_BigInteger(); $lhs->value = array_merge($this->_array_repeat(0, count($n)), $x); $rhs = new Math_BigInteger(); $rhs->value = $n; list(, $temp) = $lhs->divide($rhs); return $temp->value; } function _modInverse67108864($x) { $x = -$x[0]; $result = $x & 0x3; $result = ($result * (2 - $x * $result)) & 0xF; $result = ($result * (2 - ($x & 0xFF) * $result)) & 0xFF; $result = ($result * ((2 - ($x & 0xFFFF) * $result) & 0xFFFF)) & 0xFFFF; $result = fmod($result * (2 - fmod($x * $result, MATH_BIGINTEGER_BASE_FULL)), MATH_BIGINTEGER_BASE_FULL); return $result & MATH_BIGINTEGER_MAX_DIGIT; } function modInverse($n) { switch (MATH_BIGINTEGER_MODE) { case MATH_BIGINTEGER_MODE_GMP: $temp = new Math_BigInteger(); $temp->value = gmp_invert($this->value, $n->value); return ($temp->value === false) ? false : $this->_normalize($temp); } static $zero, $one; if (!isset($zero)) { $zero = new Math_BigInteger(); $one = new Math_BigInteger(1); } $n = $n->abs(); if ($this->compare($zero) < 0) { $temp = $this->abs(); $temp = $temp->modInverse($n); return $this->_normalize($n->subtract($temp)); } extract($this->extendedGCD($n)); if (!$gcd->equals($one)) { return false; } $x = $x->compare($zero) < 0 ? $x->add($n) : $x; return $this->compare($zero) < 0 ? $this->_normalize($n->subtract($x)) : $this->_normalize($x); } function extendedGCD($n) { switch (MATH_BIGINTEGER_MODE) { case MATH_BIGINTEGER_MODE_GMP: extract(gmp_gcdext($this->value, $n->value)); return array( 'gcd' => $this->_normalize(new Math_BigInteger($g)), 'x' => $this->_normalize(new Math_BigInteger($s)), 'y' => $this->_normalize(new Math_BigInteger($t)) ); case MATH_BIGINTEGER_MODE_BCMATH: $u = $this->value; $v = $n->value; $a = '1'; $b = '0'; $c = '0'; $d = '1'; while (bccomp($v, '0', 0) != 0) { $q = bcdiv($u, $v, 0); $temp = $u; $u = $v; $v = bcsub($temp, bcmul($v, $q, 0), 0); $temp = $a; $a = $c; $c = bcsub($temp, bcmul($a, $q, 0), 0); $temp = $b; $b = $d; $d = bcsub($temp, bcmul($b, $q, 0), 0); } return array( 'gcd' => $this->_normalize(new Math_BigInteger($u)), 'x' => $this->_normalize(new Math_BigInteger($a)), 'y' => $this->_normalize(new Math_BigInteger($b)) ); } $y = $n->copy(); $x = $this->copy(); $g = new Math_BigInteger(); $g->value = array(1); while (!(($x->value[0] & 1)|| ($y->value[0] & 1))) { $x->_rshift(1); $y->_rshift(1); $g->_lshift(1); } $u = $x->copy(); $v = $y->copy(); $a = new Math_BigInteger(); $b = new Math_BigInteger(); $c = new Math_BigInteger(); $d = new Math_BigInteger(); $a->value = $d->value = $g->value = array(1); $b->value = $c->value = array(); while (!empty($u->value)) { while (!($u->value[0] & 1)) { $u->_rshift(1); if ((!empty($a->value) && ($a->value[0] & 1)) || (!empty($b->value) && ($b->value[0] & 1))) { $a = $a->add($y); $b = $b->subtract($x); } $a->_rshift(1); $b->_rshift(1); } while (!($v->value[0] & 1)) { $v->_rshift(1); if ((!empty($d->value) && ($d->value[0] & 1)) || (!empty($c->value) && ($c->value[0] & 1))) { $c = $c->add($y); $d = $d->subtract($x); } $c->_rshift(1); $d->_rshift(1); } if ($u->compare($v) >= 0) { $u = $u->subtract($v); $a = $a->subtract($c); $b = $b->subtract($d); } else { $v = $v->subtract($u); $c = $c->subtract($a); $d = $d->subtract($b); } } return array( 'gcd' => $this->_normalize($g->multiply($v)), 'x' => $this->_normalize($c), 'y' => $this->_normalize($d) ); } function gcd($n) { extract($this->extendedGCD($n)); return $gcd; } function abs() { $temp = new Math_BigInteger(); switch (MATH_BIGINTEGER_MODE) { case MATH_BIGINTEGER_MODE_GMP: $temp->value = gmp_abs($this->value); break; case MATH_BIGINTEGER_MODE_BCMATH: $temp->value = (bccomp($this->value, '0', 0) < 0) ? substr($this->value, 1) : $this->value; break; default: $temp->value = $this->value; } return $temp; } function compare($y) { switch (MATH_BIGINTEGER_MODE) { case MATH_BIGINTEGER_MODE_GMP: return gmp_cmp($this->value, $y->value); case MATH_BIGINTEGER_MODE_BCMATH: return bccomp($this->value, $y->value, 0); } return $this->_compare($this->value, $this->is_negative, $y->value, $y->is_negative); } function _compare($x_value, $x_negative, $y_value, $y_negative) { if ($x_negative != $y_negative) { return (!$x_negative && $y_negative) ? 1 : -1; } $result = $x_negative ? -1 : 1; if (count($x_value) != count($y_value)) { return (count($x_value) > count($y_value)) ? $result : -$result; } $size = max(count($x_value), count($y_value)); $x_value = array_pad($x_value, $size, 0); $y_value = array_pad($y_value, $size, 0); for ($i = count($x_value) - 1; $i >= 0; --$i) { if ($x_value[$i] != $y_value[$i]) { return ($x_value[$i] > $y_value[$i]) ? $result : -$result; } } return 0; } function equals($x) { switch (MATH_BIGINTEGER_MODE) { case MATH_BIGINTEGER_MODE_GMP: return gmp_cmp($this->value, $x->value) == 0; default: return $this->value === $x->value && $this->is_negative == $x->is_negative; } } function setPrecision($bits) { $this->precision = $bits; if (MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_BCMATH) { $this->bitmask = new Math_BigInteger(chr((1 << ($bits & 0x7)) - 1) . str_repeat(chr(0xFF), $bits >> 3), 256); } else { $this->bitmask = new Math_BigInteger(bcpow('2', $bits, 0)); } $temp = $this->_normalize($this); $this->value = $temp->value; } function bitwise_and($x) { switch (MATH_BIGINTEGER_MODE) { case MATH_BIGINTEGER_MODE_GMP: $temp = new Math_BigInteger(); $temp->value = gmp_and($this->value, $x->value); return $this->_normalize($temp); case MATH_BIGINTEGER_MODE_BCMATH: $left = $this->toBytes(); $right = $x->toBytes(); $length = max(strlen($left), strlen($right)); $left = str_pad($left, $length, chr(0), STR_PAD_LEFT); $right = str_pad($right, $length, chr(0), STR_PAD_LEFT); return $this->_normalize(new Math_BigInteger($left & $right, 256)); } $result = $this->copy(); $length = min(count($x->value), count($this->value)); $result->value = array_slice($result->value, 0, $length); for ($i = 0; $i < $length; ++$i) { $result->value[$i]&= $x->value[$i]; } return $this->_normalize($result); } function bitwise_or($x) { switch (MATH_BIGINTEGER_MODE) { case MATH_BIGINTEGER_MODE_GMP: $temp = new Math_BigInteger(); $temp->value = gmp_or($this->value, $x->value); return $this->_normalize($temp); case MATH_BIGINTEGER_MODE_BCMATH: $left = $this->toBytes(); $right = $x->toBytes(); $length = max(strlen($left), strlen($right)); $left = str_pad($left, $length, chr(0), STR_PAD_LEFT); $right = str_pad($right, $length, chr(0), STR_PAD_LEFT); return $this->_normalize(new Math_BigInteger($left | $right, 256)); } $length = max(count($this->value), count($x->value)); $result = $this->copy(); $result->value = array_pad($result->value, $length, 0); $x->value = array_pad($x->value, $length, 0); for ($i = 0; $i < $length; ++$i) { $result->value[$i]|= $x->value[$i]; } return $this->_normalize($result); } function bitwise_xor($x) { switch (MATH_BIGINTEGER_MODE) { case MATH_BIGINTEGER_MODE_GMP: $temp = new Math_BigInteger(); $temp->value = gmp_xor($this->value, $x->value); return $this->_normalize($temp); case MATH_BIGINTEGER_MODE_BCMATH: $left = $this->toBytes(); $right = $x->toBytes(); $length = max(strlen($left), strlen($right)); $left = str_pad($left, $length, chr(0), STR_PAD_LEFT); $right = str_pad($right, $length, chr(0), STR_PAD_LEFT); return $this->_normalize(new Math_BigInteger($left ^ $right, 256)); } $length = max(count($this->value), count($x->value)); $result = $this->copy(); $result->value = array_pad($result->value, $length, 0); $x->value = array_pad($x->value, $length, 0); for ($i = 0; $i < $length; ++$i) { $result->value[$i]^= $x->value[$i]; } return $this->_normalize($result); } function bitwise_not() { $temp = $this->toBytes(); if ($temp == '') { return ''; } $pre_msb = decbin(ord($temp[0])); $temp = ~$temp; $msb = decbin(ord($temp[0])); if (strlen($msb) == 8) { $msb = substr($msb, strpos($msb, '0')); } $temp[0] = chr(bindec($msb)); $current_bits = strlen($pre_msb) + 8 * strlen($temp) - 8; $new_bits = $this->precision - $current_bits; if ($new_bits <= 0) { return $this->_normalize(new Math_BigInteger($temp, 256)); } $leading_ones = chr((1 << ($new_bits & 0x7)) - 1) . str_repeat(chr(0xFF), $new_bits >> 3); $this->_base256_lshift($leading_ones, $current_bits); $temp = str_pad($temp, strlen($leading_ones), chr(0), STR_PAD_LEFT); return $this->_normalize(new Math_BigInteger($leading_ones | $temp, 256)); } function bitwise_rightShift($shift) { $temp = new Math_BigInteger(); switch (MATH_BIGINTEGER_MODE) { case MATH_BIGINTEGER_MODE_GMP: static $two; if (!isset($two)) { $two = gmp_init('2'); } $temp->value = gmp_div_q($this->value, gmp_pow($two, $shift)); break; case MATH_BIGINTEGER_MODE_BCMATH: $temp->value = bcdiv($this->value, bcpow('2', $shift, 0), 0); break; default: $temp->value = $this->value; $temp->_rshift($shift); } return $this->_normalize($temp); } function bitwise_leftShift($shift) { $temp = new Math_BigInteger(); switch (MATH_BIGINTEGER_MODE) { case MATH_BIGINTEGER_MODE_GMP: static $two; if (!isset($two)) { $two = gmp_init('2'); } $temp->value = gmp_mul($this->value, gmp_pow($two, $shift)); break; case MATH_BIGINTEGER_MODE_BCMATH: $temp->value = bcmul($this->value, bcpow('2', $shift, 0), 0); break; default: $temp->value = $this->value; $temp->_lshift($shift); } return $this->_normalize($temp); } function bitwise_leftRotate($shift) { $bits = $this->toBytes(); if ($this->precision > 0) { $precision = $this->precision; if (MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_BCMATH) { $mask = $this->bitmask->subtract(new Math_BigInteger(1)); $mask = $mask->toBytes(); } else { $mask = $this->bitmask->toBytes(); } } else { $temp = ord($bits[0]); for ($i = 0; $temp >> $i; ++$i) { } $precision = 8 * strlen($bits) - 8 + $i; $mask = chr((1 << ($precision & 0x7)) - 1) . str_repeat(chr(0xFF), $precision >> 3); } if ($shift < 0) { $shift+= $precision; } $shift%= $precision; if (!$shift) { return $this->copy(); } $left = $this->bitwise_leftShift($shift); $left = $left->bitwise_and(new Math_BigInteger($mask, 256)); $right = $this->bitwise_rightShift($precision - $shift); $result = MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_BCMATH ? $left->bitwise_or($right) : $left->add($right); return $this->_normalize($result); } function bitwise_rightRotate($shift) { return $this->bitwise_leftRotate(-$shift); } function setRandomGenerator($generator) { } function _random_number_helper($size) { if (function_exists('crypt_random_string')) { $random = crypt_random_string($size); } else { $random = ''; if ($size & 1) { $random.= chr(mt_rand(0, 255)); } $blocks = $size >> 1; for ($i = 0; $i < $blocks; ++$i) { $random.= pack('n', mt_rand(0, 0xFFFF)); } } return new Math_BigInteger($random, 256); } function random($arg1, $arg2 = false) { if ($arg1 === false) { return false; } if ($arg2 === false) { $max = $arg1; $min = $this; } else { $min = $arg1; $max = $arg2; } $compare = $max->compare($min); if (!$compare) { return $this->_normalize($min); } elseif ($compare < 0) { $temp = $max; $max = $min; $min = $temp; } static $one; if (!isset($one)) { $one = new Math_BigInteger(1); } $max = $max->subtract($min->subtract($one)); $size = strlen(ltrim($max->toBytes(), chr(0))); $random_max = new Math_BigInteger(chr(1) . str_repeat("\0", $size), 256); $random = $this->_random_number_helper($size); list($max_multiple) = $random_max->divide($max); $max_multiple = $max_multiple->multiply($max); while ($random->compare($max_multiple) >= 0) { $random = $random->subtract($max_multiple); $random_max = $random_max->subtract($max_multiple); $random = $random->bitwise_leftShift(8); $random = $random->add($this->_random_number_helper(1)); $random_max = $random_max->bitwise_leftShift(8); list($max_multiple) = $random_max->divide($max); $max_multiple = $max_multiple->multiply($max); } list(, $random) = $random->divide($max); return $this->_normalize($random->add($min)); } function randomPrime($arg1, $arg2 = false, $timeout = false) { if ($arg1 === false) { return false; } if ($arg2 === false) { $max = $arg1; $min = $this; } else { $min = $arg1; $max = $arg2; } $compare = $max->compare($min); if (!$compare) { return $min->isPrime() ? $min : false; } elseif ($compare < 0) { $temp = $max; $max = $min; $min = $temp; } static $one, $two; if (!isset($one)) { $one = new Math_BigInteger(1); $two = new Math_BigInteger(2); } $start = time(); $x = $this->random($min, $max); if (MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_GMP && extension_loaded('gmp') && version_compare(PHP_VERSION, '5.2.0', '>=')) { $p = new Math_BigInteger(); $p->value = gmp_nextprime($x->value); if ($p->compare($max) <= 0) { return $p; } if (!$min->equals($x)) { $x = $x->subtract($one); } return $x->randomPrime($min, $x); } if ($x->equals($two)) { return $x; } $x->_make_odd(); if ($x->compare($max) > 0) { if ($min->equals($max)) { return false; } $x = $min->copy(); $x->_make_odd(); } $initial_x = $x->copy(); while (true) { if ($timeout !== false && time() - $start > $timeout) { return false; } if ($x->isPrime()) { return $x; } $x = $x->add($two); if ($x->compare($max) > 0) { $x = $min->copy(); if ($x->equals($two)) { return $x; } $x->_make_odd(); } if ($x->equals($initial_x)) { return false; } } } function _make_odd() { switch (MATH_BIGINTEGER_MODE) { case MATH_BIGINTEGER_MODE_GMP: gmp_setbit($this->value, 0); break; case MATH_BIGINTEGER_MODE_BCMATH: if ($this->value[strlen($this->value) - 1] % 2 == 0) { $this->value = bcadd($this->value, '1'); } break; default: $this->value[0] |= 1; } } function isPrime($t = false) { $length = strlen($this->toBytes()); if (!$t) { if ($length >= 163) { $t = 2; } else if ($length >= 106) { $t = 3; } else if ($length >= 81 ) { $t = 4; } else if ($length >= 68 ) { $t = 5; } else if ($length >= 56 ) { $t = 6; } else if ($length >= 50 ) { $t = 7; } else if ($length >= 43 ) { $t = 8; } else if ($length >= 37 ) { $t = 9; } else if ($length >= 31 ) { $t = 12; } else if ($length >= 25 ) { $t = 15; } else if ($length >= 18 ) { $t = 18; } else { $t = 27; } } switch (MATH_BIGINTEGER_MODE) { case MATH_BIGINTEGER_MODE_GMP: return gmp_prob_prime($this->value, $t) != 0; case MATH_BIGINTEGER_MODE_BCMATH: if ($this->value === '2') { return true; } if ($this->value[strlen($this->value) - 1] % 2 == 0) { return false; } break; default: if ($this->value == array(2)) { return true; } if (~$this->value[0] & 1) { return false; } } static $primes, $zero, $one, $two; if (!isset($primes)) { $primes = array( 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997 ); if (MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_INTERNAL) { for ($i = 0; $i < count($primes); ++$i) { $primes[$i] = new Math_BigInteger($primes[$i]); } } $zero = new Math_BigInteger(); $one = new Math_BigInteger(1); $two = new Math_BigInteger(2); } if ($this->equals($one)) { return false; } if (MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_INTERNAL) { foreach ($primes as $prime) { list(, $r) = $this->divide($prime); if ($r->equals($zero)) { return $this->equals($prime); } } } else { $value = $this->value; foreach ($primes as $prime) { list(, $r) = $this->_divide_digit($value, $prime); if (!$r) { return count($value) == 1 && $value[0] == $prime; } } } $n = $this->copy(); $n_1 = $n->subtract($one); $n_2 = $n->subtract($two); $r = $n_1->copy(); $r_value = $r->value; if (MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_BCMATH) { $s = 0; while ($r->value[strlen($r->value) - 1] % 2 == 0) { $r->value = bcdiv($r->value, '2', 0); ++$s; } } else { for ($i = 0, $r_length = count($r_value); $i < $r_length; ++$i) { $temp = ~$r_value[$i] & 0xFFFFFF; for ($j = 1; ($temp >> $j) & 1; ++$j) { } if ($j != 25) { break; } } $s = 26 * $i + $j - 1; $r->_rshift($s); } for ($i = 0; $i < $t; ++$i) { $a = $this->random($two, $n_2); $y = $a->modPow($r, $n); if (!$y->equals($one) && !$y->equals($n_1)) { for ($j = 1; $j < $s && !$y->equals($n_1); ++$j) { $y = $y->modPow($two, $n); if ($y->equals($one)) { return false; } } if (!$y->equals($n_1)) { return false; } } } return true; } function _lshift($shift) { if ($shift == 0) { return; } $num_digits = (int) ($shift / MATH_BIGINTEGER_BASE); $shift %= MATH_BIGINTEGER_BASE; $shift = 1 << $shift; $carry = 0; for ($i = 0; $i < count($this->value); ++$i) { $temp = $this->value[$i] * $shift + $carry; $carry = MATH_BIGINTEGER_BASE === 26 ? intval($temp / 0x4000000) : ($temp >> 31); $this->value[$i] = (int) ($temp - $carry * MATH_BIGINTEGER_BASE_FULL); } if ($carry) { $this->value[count($this->value)] = $carry; } while ($num_digits--) { array_unshift($this->value, 0); } } function _rshift($shift) { if ($shift == 0) { return; } $num_digits = (int) ($shift / MATH_BIGINTEGER_BASE); $shift %= MATH_BIGINTEGER_BASE; $carry_shift = MATH_BIGINTEGER_BASE - $shift; $carry_mask = (1 << $shift) - 1; if ($num_digits) { $this->value = array_slice($this->value, $num_digits); } $carry = 0; for ($i = count($this->value) - 1; $i >= 0; --$i) { $temp = $this->value[$i] >> $shift | $carry; $carry = ($this->value[$i] & $carry_mask) << $carry_shift; $this->value[$i] = $temp; } $this->value = $this->_trim($this->value); } function _normalize($result) { $result->precision = $this->precision; $result->bitmask = $this->bitmask; switch (MATH_BIGINTEGER_MODE) { case MATH_BIGINTEGER_MODE_GMP: if ($this->bitmask !== false) { $result->value = gmp_and($result->value, $result->bitmask->value); } return $result; case MATH_BIGINTEGER_MODE_BCMATH: if (!empty($result->bitmask->value)) { $result->value = bcmod($result->value, $result->bitmask->value); } return $result; } $value = &$result->value; if (!count($value)) { return $result; } $value = $this->_trim($value); if (!empty($result->bitmask->value)) { $length = min(count($value), count($this->bitmask->value)); $value = array_slice($value, 0, $length); for ($i = 0; $i < $length; ++$i) { $value[$i] = $value[$i] & $this->bitmask->value[$i]; } } return $result; } function _trim($value) { for ($i = count($value) - 1; $i >= 0; --$i) { if ($value[$i]) { break; } unset($value[$i]); } return $value; } function _array_repeat($input, $multiplier) { return ($multiplier) ? array_fill(0, $multiplier, $input) : array(); } function _base256_lshift(&$x, $shift) { if ($shift == 0) { return; } $num_bytes = $shift >> 3; $shift &= 7; $carry = 0; for ($i = strlen($x) - 1; $i >= 0; --$i) { $temp = ord($x[$i]) << $shift | $carry; $x[$i] = chr($temp); $carry = $temp >> 8; } $carry = ($carry != 0) ? chr($carry) : ''; $x = $carry . $x . str_repeat(chr(0), $num_bytes); } function _base256_rshift(&$x, $shift) { if ($shift == 0) { $x = ltrim($x, chr(0)); return ''; } $num_bytes = $shift >> 3; $shift &= 7; $remainder = ''; if ($num_bytes) { $start = $num_bytes > strlen($x) ? -strlen($x) : -$num_bytes; $remainder = substr($x, $start); $x = substr($x, 0, -$num_bytes); } $carry = 0; $carry_shift = 8 - $shift; for ($i = 0; $i < strlen($x); ++$i) { $temp = (ord($x[$i]) >> $shift) | $carry; $carry = (ord($x[$i]) << $carry_shift) & 0xFF; $x[$i] = chr($temp); } $x = ltrim($x, chr(0)); $remainder = chr($carry >> $carry_shift) . $remainder; return ltrim($remainder, chr(0)); } function _int2bytes($x) { return ltrim(pack('N', $x), chr(0)); } function _bytes2int($x) { $temp = unpack('Nint', str_pad($x, 4, chr(0), STR_PAD_LEFT)); return $temp['int']; } function _encodeASN1Length($length) { if ($length <= 0x7F) { return chr($length); } $temp = ltrim(pack('N', $length), chr(0)); return pack('Ca*', 0x80 | strlen($temp), $temp); } function _safe_divide($x, $y) { if (MATH_BIGINTEGER_BASE === 26) { return (int) ($x / $y); } return ($x - ($x % $y)) / $y; } } } if (!class_exists('Crypt_Base')) { define('CRYPT_MODE_CTR', -1); define('CRYPT_MODE_ECB', 1); define('CRYPT_MODE_CBC', 2); define('CRYPT_MODE_CFB', 3); define('CRYPT_MODE_OFB', 4); define('CRYPT_MODE_STREAM', 5); define('CRYPT_ENGINE_INTERNAL', 1); define('CRYPT_ENGINE_MCRYPT', 2); define('CRYPT_ENGINE_OPENSSL', 3); class Crypt_Base { var $mode; var $block_size = 16; var $key = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; var $iv; var $encryptIV; var $decryptIV; var $continuousBuffer = false; var $enbuffer; var $debuffer; var $enmcrypt; var $demcrypt; var $enchanged = true; var $dechanged = true; var $ecb; var $cfb_init_len = 600; var $changed = true; var $padding = true; var $paddable = false; var $engine; var $preferredEngine; var $cipher_name_mcrypt; var $cipher_name_openssl; var $cipher_name_openssl_ecb; var $password_default_salt = 'phpseclib/salt'; var $const_namespace; var $inline_crypt; var $use_inline_crypt; var $openssl_emulate_ctr = false; var $openssl_options; var $explicit_key_length = false; var $skip_key_adjustment = false; function __construct($mode = CRYPT_MODE_CBC) { switch ($mode) { case CRYPT_MODE_ECB: $this->paddable = true; $this->mode = CRYPT_MODE_ECB; break; case CRYPT_MODE_CTR: case CRYPT_MODE_CFB: case CRYPT_MODE_OFB: case CRYPT_MODE_STREAM: $this->mode = $mode; break; case CRYPT_MODE_CBC: default: $this->paddable = true; $this->mode = CRYPT_MODE_CBC; } $this->_setEngine(); if ($this->use_inline_crypt !== false && function_exists('create_function')) { $this->use_inline_crypt = true; } } function Crypt_Base($mode = CRYPT_MODE_CBC) { $this->__construct($mode); } function setIV($iv) { if ($this->mode == CRYPT_MODE_ECB) { return; } $this->iv = $iv; $this->changed = true; } function setKeyLength($length) { $this->explicit_key_length = true; $this->changed = true; $this->_setEngine(); } function getKeyLength() { return $this->key_length << 3; } function getBlockLength() { return $this->block_size << 3; } function setKey($key) { if (!$this->explicit_key_length) { $this->setKeyLength(strlen($key) << 3); $this->explicit_key_length = false; } $this->key = $key; $this->changed = true; $this->_setEngine(); } function setPassword($password, $method = 'pbkdf2') { $key = ''; switch ($method) { default: $func_args = func_get_args(); $hash = isset($func_args[2]) ? $func_args[2] : 'sha1'; $salt = isset($func_args[3]) ? $func_args[3] : $this->password_default_salt; $count = isset($func_args[4]) ? $func_args[4] : 1000; if (isset($func_args[5])) { $dkLen = $func_args[5]; } else { $dkLen = $method == 'pbkdf1' ? 2 * $this->key_length : $this->key_length; } switch (true) { case $method == 'pbkdf1': if (!class_exists('Crypt_Hash')) { include_once 'Crypt/Hash.php'; } $hashObj = new Crypt_Hash(); $hashObj->setHash($hash); if ($dkLen > $hashObj->getLength()) { user_error('Derived key too long'); return false; } $t = $password . $salt; for ($i = 0; $i < $count; ++$i) { $t = $hashObj->hash($t); } $key = substr($t, 0, $dkLen); $this->setKey(substr($key, 0, $dkLen >> 1)); $this->setIV(substr($key, $dkLen >> 1)); return true; case !function_exists('hash_pbkdf2'): case !function_exists('hash_algos'): case !in_array($hash, hash_algos()): if (!class_exists('Crypt_Hash')) { include_once 'Crypt/Hash.php'; } $i = 1; while (strlen($key) < $dkLen) { $hmac = new Crypt_Hash(); $hmac->setHash($hash); $hmac->setKey($password); $f = $u = $hmac->hash($salt . pack('N', $i++)); for ($j = 2; $j <= $count; ++$j) { $u = $hmac->hash($u); $f^= $u; } $key.= $f; } $key = substr($key, 0, $dkLen); break; default: $key = hash_pbkdf2($hash, $password, $salt, $count, $dkLen, true); } } $this->setKey($key); return true; } function encrypt($plaintext) { if ($this->paddable) { $plaintext = $this->_pad($plaintext); } if ($this->engine === CRYPT_ENGINE_OPENSSL) { if ($this->changed) { $this->_clearBuffers(); $this->changed = false; } switch ($this->mode) { case CRYPT_MODE_STREAM: return openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options); case CRYPT_MODE_ECB: $result = @openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options); return !defined('OPENSSL_RAW_DATA') ? substr($result, 0, -$this->block_size) : $result; case CRYPT_MODE_CBC: $result = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $this->encryptIV); if (!defined('OPENSSL_RAW_DATA')) { $result = substr($result, 0, -$this->block_size); } if ($this->continuousBuffer) { $this->encryptIV = substr($result, -$this->block_size); } return $result; case CRYPT_MODE_CTR: return $this->_openssl_ctr_process($plaintext, $this->encryptIV, $this->enbuffer); case CRYPT_MODE_CFB: $ciphertext = ''; if ($this->continuousBuffer) { $iv = &$this->encryptIV; $pos = &$this->enbuffer['pos']; } else { $iv = $this->encryptIV; $pos = 0; } $len = strlen($plaintext); $i = 0; if ($pos) { $orig_pos = $pos; $max = $this->block_size - $pos; if ($len >= $max) { $i = $max; $len-= $max; $pos = 0; } else { $i = $len; $pos+= $len; $len = 0; } $ciphertext = substr($iv, $orig_pos) ^ $plaintext; $iv = substr_replace($iv, $ciphertext, $orig_pos, $i); $plaintext = substr($plaintext, $i); } $overflow = $len % $this->block_size; if ($overflow) { $ciphertext.= openssl_encrypt(substr($plaintext, 0, -$overflow) . str_repeat("\0", $this->block_size), $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv); $iv = $this->_string_pop($ciphertext, $this->block_size); $size = $len - $overflow; $block = $iv ^ substr($plaintext, -$overflow); $iv = substr_replace($iv, $block, 0, $overflow); $ciphertext.= $block; $pos = $overflow; } elseif ($len) { $ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv); $iv = substr($ciphertext, -$this->block_size); } return $ciphertext; case CRYPT_MODE_OFB: return $this->_openssl_ofb_process($plaintext, $this->encryptIV, $this->enbuffer); } } if ($this->engine === CRYPT_ENGINE_MCRYPT) { if ($this->changed) { $this->_setupMcrypt(); $this->changed = false; } if ($this->enchanged) { @mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV); $this->enchanged = false; } if ($this->mode == CRYPT_MODE_CFB && $this->continuousBuffer) { $block_size = $this->block_size; $iv = &$this->encryptIV; $pos = &$this->enbuffer['pos']; $len = strlen($plaintext); $ciphertext = ''; $i = 0; if ($pos) { $orig_pos = $pos; $max = $block_size - $pos; if ($len >= $max) { $i = $max; $len-= $max; $pos = 0; } else { $i = $len; $pos+= $len; $len = 0; } $ciphertext = substr($iv, $orig_pos) ^ $plaintext; $iv = substr_replace($iv, $ciphertext, $orig_pos, $i); $this->enbuffer['enmcrypt_init'] = true; } if ($len >= $block_size) { if ($this->enbuffer['enmcrypt_init'] === false || $len > $this->cfb_init_len) { if ($this->enbuffer['enmcrypt_init'] === true) { @mcrypt_generic_init($this->enmcrypt, $this->key, $iv); $this->enbuffer['enmcrypt_init'] = false; } $ciphertext.= @mcrypt_generic($this->enmcrypt, substr($plaintext, $i, $len - $len % $block_size)); $iv = substr($ciphertext, -$block_size); $len%= $block_size; } else { while ($len >= $block_size) { $iv = @mcrypt_generic($this->ecb, $iv) ^ substr($plaintext, $i, $block_size); $ciphertext.= $iv; $len-= $block_size; $i+= $block_size; } } } if ($len) { $iv = @mcrypt_generic($this->ecb, $iv); $block = $iv ^ substr($plaintext, -$len); $iv = substr_replace($iv, $block, 0, $len); $ciphertext.= $block; $pos = $len; } return $ciphertext; } $ciphertext = @mcrypt_generic($this->enmcrypt, $plaintext); if (!$this->continuousBuffer) { @mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV); } return $ciphertext; } if ($this->changed) { $this->_setup(); $this->changed = false; } if ($this->use_inline_crypt) { $inline = $this->inline_crypt; return $inline('encrypt', $this, $plaintext); } $buffer = &$this->enbuffer; $block_size = $this->block_size; $ciphertext = ''; switch ($this->mode) { case CRYPT_MODE_ECB: for ($i = 0; $i < strlen($plaintext); $i+=$block_size) { $ciphertext.= $this->_encryptBlock(substr($plaintext, $i, $block_size)); } break; case CRYPT_MODE_CBC: $xor = $this->encryptIV; for ($i = 0; $i < strlen($plaintext); $i+=$block_size) { $block = substr($plaintext, $i, $block_size); $block = $this->_encryptBlock($block ^ $xor); $xor = $block; $ciphertext.= $block; } if ($this->continuousBuffer) { $this->encryptIV = $xor; } break; case CRYPT_MODE_CTR: $xor = $this->encryptIV; if (strlen($buffer['ciphertext'])) { for ($i = 0; $i < strlen($plaintext); $i+=$block_size) { $block = substr($plaintext, $i, $block_size); if (strlen($block) > strlen($buffer['ciphertext'])) { $buffer['ciphertext'].= $this->_encryptBlock($xor); } $this->_increment_str($xor); $key = $this->_string_shift($buffer['ciphertext'], $block_size); $ciphertext.= $block ^ $key; } } else { for ($i = 0; $i < strlen($plaintext); $i+=$block_size) { $block = substr($plaintext, $i, $block_size); $key = $this->_encryptBlock($xor); $this->_increment_str($xor); $ciphertext.= $block ^ $key; } } if ($this->continuousBuffer) { $this->encryptIV = $xor; if ($start = strlen($plaintext) % $block_size) { $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext']; } } break; case CRYPT_MODE_CFB: if ($this->continuousBuffer) { $iv = &$this->encryptIV; $pos = &$buffer['pos']; } else { $iv = $this->encryptIV; $pos = 0; } $len = strlen($plaintext); $i = 0; if ($pos) { $orig_pos = $pos; $max = $block_size - $pos; if ($len >= $max) { $i = $max; $len-= $max; $pos = 0; } else { $i = $len; $pos+= $len; $len = 0; } $ciphertext = substr($iv, $orig_pos) ^ $plaintext; $iv = substr_replace($iv, $ciphertext, $orig_pos, $i); } while ($len >= $block_size) { $iv = $this->_encryptBlock($iv) ^ substr($plaintext, $i, $block_size); $ciphertext.= $iv; $len-= $block_size; $i+= $block_size; } if ($len) { $iv = $this->_encryptBlock($iv); $block = $iv ^ substr($plaintext, $i); $iv = substr_replace($iv, $block, 0, $len); $ciphertext.= $block; $pos = $len; } break; case CRYPT_MODE_OFB: $xor = $this->encryptIV; if (strlen($buffer['xor'])) { for ($i = 0; $i < strlen($plaintext); $i+=$block_size) { $block = substr($plaintext, $i, $block_size); if (strlen($block) > strlen($buffer['xor'])) { $xor = $this->_encryptBlock($xor); $buffer['xor'].= $xor; } $key = $this->_string_shift($buffer['xor'], $block_size); $ciphertext.= $block ^ $key; } } else { for ($i = 0; $i < strlen($plaintext); $i+=$block_size) { $xor = $this->_encryptBlock($xor); $ciphertext.= substr($plaintext, $i, $block_size) ^ $xor; } $key = $xor; } if ($this->continuousBuffer) { $this->encryptIV = $xor; if ($start = strlen($plaintext) % $block_size) { $buffer['xor'] = substr($key, $start) . $buffer['xor']; } } break; case CRYPT_MODE_STREAM: $ciphertext = $this->_encryptBlock($plaintext); break; } return $ciphertext; } function decrypt($ciphertext) { if ($this->paddable) { $ciphertext = str_pad($ciphertext, strlen($ciphertext) + ($this->block_size - strlen($ciphertext) % $this->block_size) % $this->block_size, chr(0)); } if ($this->engine === CRYPT_ENGINE_OPENSSL) { if ($this->changed) { $this->_clearBuffers(); $this->changed = false; } switch ($this->mode) { case CRYPT_MODE_STREAM: $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options); break; case CRYPT_MODE_ECB: if (!defined('OPENSSL_RAW_DATA')) { $ciphertext.= openssl_encrypt('', $this->cipher_name_openssl_ecb, $this->key, true); } $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options); break; case CRYPT_MODE_CBC: if (!defined('OPENSSL_RAW_DATA')) { $padding = str_repeat(chr($this->block_size), $this->block_size) ^ substr($ciphertext, -$this->block_size); $ciphertext.= substr(openssl_encrypt($padding, $this->cipher_name_openssl_ecb, $this->key, true), 0, $this->block_size); $offset = 2 * $this->block_size; } else { $offset = $this->block_size; } $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $this->decryptIV); if ($this->continuousBuffer) { $this->decryptIV = substr($ciphertext, -$offset, $this->block_size); } break; case CRYPT_MODE_CTR: $plaintext = $this->_openssl_ctr_process($ciphertext, $this->decryptIV, $this->debuffer); break; case CRYPT_MODE_CFB: $plaintext = ''; if ($this->continuousBuffer) { $iv = &$this->decryptIV; $pos = &$this->buffer['pos']; } else { $iv = $this->decryptIV; $pos = 0; } $len = strlen($ciphertext); $i = 0; if ($pos) { $orig_pos = $pos; $max = $this->block_size - $pos; if ($len >= $max) { $i = $max; $len-= $max; $pos = 0; } else { $i = $len; $pos+= $len; $len = 0; } $plaintext = substr($iv, $orig_pos) ^ $ciphertext; $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i); $ciphertext = substr($ciphertext, $i); } $overflow = $len % $this->block_size; if ($overflow) { $plaintext.= openssl_decrypt(substr($ciphertext, 0, -$overflow), $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv); if ($len - $overflow) { $iv = substr($ciphertext, -$overflow - $this->block_size, -$overflow); } $iv = openssl_encrypt(str_repeat("\0", $this->block_size), $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv); $plaintext.= $iv ^ substr($ciphertext, -$overflow); $iv = substr_replace($iv, substr($ciphertext, -$overflow), 0, $overflow); $pos = $overflow; } elseif ($len) { $plaintext.= openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv); $iv = substr($ciphertext, -$this->block_size); } break; case CRYPT_MODE_OFB: $plaintext = $this->_openssl_ofb_process($ciphertext, $this->decryptIV, $this->debuffer); } return $this->paddable ? $this->_unpad($plaintext) : $plaintext; } if ($this->engine === CRYPT_ENGINE_MCRYPT) { $block_size = $this->block_size; if ($this->changed) { $this->_setupMcrypt(); $this->changed = false; } if ($this->dechanged) { @mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV); $this->dechanged = false; } if ($this->mode == CRYPT_MODE_CFB && $this->continuousBuffer) { $iv = &$this->decryptIV; $pos = &$this->debuffer['pos']; $len = strlen($ciphertext); $plaintext = ''; $i = 0; if ($pos) { $orig_pos = $pos; $max = $block_size - $pos; if ($len >= $max) { $i = $max; $len-= $max; $pos = 0; } else { $i = $len; $pos+= $len; $len = 0; } $plaintext = substr($iv, $orig_pos) ^ $ciphertext; $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i); } if ($len >= $block_size) { $cb = substr($ciphertext, $i, $len - $len % $block_size); $plaintext.= @mcrypt_generic($this->ecb, $iv . $cb) ^ $cb; $iv = substr($cb, -$block_size); $len%= $block_size; } if ($len) { $iv = @mcrypt_generic($this->ecb, $iv); $plaintext.= $iv ^ substr($ciphertext, -$len); $iv = substr_replace($iv, substr($ciphertext, -$len), 0, $len); $pos = $len; } return $plaintext; } $plaintext = @mdecrypt_generic($this->demcrypt, $ciphertext); if (!$this->continuousBuffer) { @mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV); } return $this->paddable ? $this->_unpad($plaintext) : $plaintext; } if ($this->changed) { $this->_setup(); $this->changed = false; } if ($this->use_inline_crypt) { $inline = $this->inline_crypt; return $inline('decrypt', $this, $ciphertext); } $block_size = $this->block_size; $buffer = &$this->debuffer; $plaintext = ''; switch ($this->mode) { case CRYPT_MODE_ECB: for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) { $plaintext.= $this->_decryptBlock(substr($ciphertext, $i, $block_size)); } break; case CRYPT_MODE_CBC: $xor = $this->decryptIV; for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) { $block = substr($ciphertext, $i, $block_size); $plaintext.= $this->_decryptBlock($block) ^ $xor; $xor = $block; } if ($this->continuousBuffer) { $this->decryptIV = $xor; } break; case CRYPT_MODE_CTR: $xor = $this->decryptIV; if (strlen($buffer['ciphertext'])) { for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) { $block = substr($ciphertext, $i, $block_size); if (strlen($block) > strlen($buffer['ciphertext'])) { $buffer['ciphertext'].= $this->_encryptBlock($xor); $this->_increment_str($xor); } $key = $this->_string_shift($buffer['ciphertext'], $block_size); $plaintext.= $block ^ $key; } } else { for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) { $block = substr($ciphertext, $i, $block_size); $key = $this->_encryptBlock($xor); $this->_increment_str($xor); $plaintext.= $block ^ $key; } } if ($this->continuousBuffer) { $this->decryptIV = $xor; if ($start = strlen($ciphertext) % $block_size) { $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext']; } } break; case CRYPT_MODE_CFB: if ($this->continuousBuffer) { $iv = &$this->decryptIV; $pos = &$buffer['pos']; } else { $iv = $this->decryptIV; $pos = 0; } $len = strlen($ciphertext); $i = 0; if ($pos) { $orig_pos = $pos; $max = $block_size - $pos; if ($len >= $max) { $i = $max; $len-= $max; $pos = 0; } else { $i = $len; $pos+= $len; $len = 0; } $plaintext = substr($iv, $orig_pos) ^ $ciphertext; $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i); } while ($len >= $block_size) { $iv = $this->_encryptBlock($iv); $cb = substr($ciphertext, $i, $block_size); $plaintext.= $iv ^ $cb; $iv = $cb; $len-= $block_size; $i+= $block_size; } if ($len) { $iv = $this->_encryptBlock($iv); $plaintext.= $iv ^ substr($ciphertext, $i); $iv = substr_replace($iv, substr($ciphertext, $i), 0, $len); $pos = $len; } break; case CRYPT_MODE_OFB: $xor = $this->decryptIV; if (strlen($buffer['xor'])) { for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) { $block = substr($ciphertext, $i, $block_size); if (strlen($block) > strlen($buffer['xor'])) { $xor = $this->_encryptBlock($xor); $buffer['xor'].= $xor; } $key = $this->_string_shift($buffer['xor'], $block_size); $plaintext.= $block ^ $key; } } else { for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) { $xor = $this->_encryptBlock($xor); $plaintext.= substr($ciphertext, $i, $block_size) ^ $xor; } $key = $xor; } if ($this->continuousBuffer) { $this->decryptIV = $xor; if ($start = strlen($ciphertext) % $block_size) { $buffer['xor'] = substr($key, $start) . $buffer['xor']; } } break; case CRYPT_MODE_STREAM: $plaintext = $this->_decryptBlock($ciphertext); break; } return $this->paddable ? $this->_unpad($plaintext) : $plaintext; } function _openssl_ctr_process($plaintext, &$encryptIV, &$buffer) { $ciphertext = ''; $block_size = $this->block_size; $key = $this->key; if ($this->openssl_emulate_ctr) { $xor = $encryptIV; if (strlen($buffer['ciphertext'])) { for ($i = 0; $i < strlen($plaintext); $i+=$block_size) { $block = substr($plaintext, $i, $block_size); if (strlen($block) > strlen($buffer['ciphertext'])) { $result = openssl_encrypt($xor, $this->cipher_name_openssl_ecb, $key, $this->openssl_options); $result = !defined('OPENSSL_RAW_DATA') ? substr($result, 0, -$this->block_size) : $result; $buffer['ciphertext'].= $result; } $this->_increment_str($xor); $otp = $this->_string_shift($buffer['ciphertext'], $block_size); $ciphertext.= $block ^ $otp; } } else { for ($i = 0; $i < strlen($plaintext); $i+=$block_size) { $block = substr($plaintext, $i, $block_size); $otp = openssl_encrypt($xor, $this->cipher_name_openssl_ecb, $key, $this->openssl_options); $otp = !defined('OPENSSL_RAW_DATA') ? substr($otp, 0, -$this->block_size) : $otp; $this->_increment_str($xor); $ciphertext.= $block ^ $otp; } } if ($this->continuousBuffer) { $encryptIV = $xor; if ($start = strlen($plaintext) % $block_size) { $buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext']; } } return $ciphertext; } if (strlen($buffer['ciphertext'])) { $ciphertext = $plaintext ^ $this->_string_shift($buffer['ciphertext'], strlen($plaintext)); $plaintext = substr($plaintext, strlen($ciphertext)); if (!strlen($plaintext)) { return $ciphertext; } } $overflow = strlen($plaintext) % $block_size; if ($overflow) { $plaintext2 = $this->_string_pop($plaintext, $overflow); $encrypted = openssl_encrypt($plaintext . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV); $temp = $this->_string_pop($encrypted, $block_size); $ciphertext.= $encrypted . ($plaintext2 ^ $temp); if ($this->continuousBuffer) { $buffer['ciphertext'] = substr($temp, $overflow); $encryptIV = $temp; } } elseif (!strlen($buffer['ciphertext'])) { $ciphertext.= openssl_encrypt($plaintext . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV); $temp = $this->_string_pop($ciphertext, $block_size); if ($this->continuousBuffer) { $encryptIV = $temp; } } if ($this->continuousBuffer) { if (!defined('OPENSSL_RAW_DATA')) { $encryptIV.= openssl_encrypt('', $this->cipher_name_openssl_ecb, $key, $this->openssl_options); } $encryptIV = openssl_decrypt($encryptIV, $this->cipher_name_openssl_ecb, $key, $this->openssl_options); if ($overflow) { $this->_increment_str($encryptIV); } } return $ciphertext; } function _openssl_ofb_process($plaintext, &$encryptIV, &$buffer) { if (strlen($buffer['xor'])) { $ciphertext = $plaintext ^ $buffer['xor']; $buffer['xor'] = substr($buffer['xor'], strlen($ciphertext)); $plaintext = substr($plaintext, strlen($ciphertext)); } else { $ciphertext = ''; } $block_size = $this->block_size; $len = strlen($plaintext); $key = $this->key; $overflow = $len % $block_size; if (strlen($plaintext)) { if ($overflow) { $ciphertext.= openssl_encrypt(substr($plaintext, 0, -$overflow) . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV); $xor = $this->_string_pop($ciphertext, $block_size); if ($this->continuousBuffer) { $encryptIV = $xor; } $ciphertext.= $this->_string_shift($xor, $overflow) ^ substr($plaintext, -$overflow); if ($this->continuousBuffer) { $buffer['xor'] = $xor; } } else { $ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV); if ($this->continuousBuffer) { $encryptIV = substr($ciphertext, -$block_size) ^ substr($plaintext, -$block_size); } } } return $ciphertext; } function _openssl_translate_mode() { switch ($this->mode) { case CRYPT_MODE_ECB: return 'ecb'; case CRYPT_MODE_CBC: return 'cbc'; case CRYPT_MODE_CTR: return 'ctr'; case CRYPT_MODE_CFB: return 'cfb'; case CRYPT_MODE_OFB: return 'ofb'; } } function enablePadding() { $this->padding = true; } function disablePadding() { $this->padding = false; } function enableContinuousBuffer() { if ($this->mode == CRYPT_MODE_ECB) { return; } $this->continuousBuffer = true; $this->_setEngine(); } function disableContinuousBuffer() { if ($this->mode == CRYPT_MODE_ECB) { return; } if (!$this->continuousBuffer) { return; } $this->continuousBuffer = false; $this->changed = true; $this->_setEngine(); } function isValidEngine($engine) { switch ($engine) { case CRYPT_ENGINE_OPENSSL: if ($this->mode == CRYPT_MODE_STREAM && $this->continuousBuffer) { return false; } $this->openssl_emulate_ctr = false; $result = $this->cipher_name_openssl && extension_loaded('openssl') && version_compare(PHP_VERSION, '5.3.3', '>='); if (!$result) { return false; } if (!defined('OPENSSL_RAW_DATA')) { $this->openssl_options = true; } else { $this->openssl_options = OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING; } $methods = openssl_get_cipher_methods(); if (in_array($this->cipher_name_openssl, $methods)) { return true; } switch ($this->mode) { case CRYPT_MODE_CTR: if (in_array($this->cipher_name_openssl_ecb, $methods)) { $this->openssl_emulate_ctr = true; return true; } } return false; case CRYPT_ENGINE_MCRYPT: return $this->cipher_name_mcrypt && extension_loaded('mcrypt') && in_array($this->cipher_name_mcrypt, @mcrypt_list_algorithms()); case CRYPT_ENGINE_INTERNAL: return true; } return false; } function setPreferredEngine($engine) { switch ($engine) { case CRYPT_ENGINE_MCRYPT: case CRYPT_ENGINE_INTERNAL: $this->preferredEngine = $engine; break; default: $this->preferredEngine = CRYPT_ENGINE_OPENSSL; } $this->_setEngine(); } function getEngine() { return $this->engine; } function _setEngine() { $this->engine = null; $candidateEngines = array( $this->preferredEngine, CRYPT_ENGINE_OPENSSL, CRYPT_ENGINE_MCRYPT ); foreach ($candidateEngines as $engine) { if ($this->isValidEngine($engine)) { $this->engine = $engine; break; } } if (!$this->engine) { $this->engine = CRYPT_ENGINE_INTERNAL; } if ($this->engine != CRYPT_ENGINE_MCRYPT && $this->enmcrypt) { @mcrypt_module_close($this->enmcrypt); @mcrypt_module_close($this->demcrypt); $this->enmcrypt = null; $this->demcrypt = null; if ($this->ecb) { @mcrypt_module_close($this->ecb); $this->ecb = null; } } $this->changed = true; } function _encryptBlock($in) { user_error((version_compare(PHP_VERSION, '5.0.0', '>=') ? __METHOD__ : __FUNCTION__) . '() must extend by class ' . get_class($this), E_USER_ERROR); } function _decryptBlock($in) { user_error((version_compare(PHP_VERSION, '5.0.0', '>=') ? __METHOD__ : __FUNCTION__) . '() must extend by class ' . get_class($this), E_USER_ERROR); } function _setupKey() { user_error((version_compare(PHP_VERSION, '5.0.0', '>=') ? __METHOD__ : __FUNCTION__) . '() must extend by class ' . get_class($this), E_USER_ERROR); } function _setup() { $this->_clearBuffers(); $this->_setupKey(); if ($this->use_inline_crypt) { $this->_setupInlineCrypt(); } } function _setupMcrypt() { $this->_clearBuffers(); $this->enchanged = $this->dechanged = true; if (!isset($this->enmcrypt)) { static $mcrypt_modes = array( CRYPT_MODE_CTR => 'ctr', CRYPT_MODE_ECB => MCRYPT_MODE_ECB, CRYPT_MODE_CBC => MCRYPT_MODE_CBC, CRYPT_MODE_CFB => 'ncfb', CRYPT_MODE_OFB => MCRYPT_MODE_NOFB, CRYPT_MODE_STREAM => MCRYPT_MODE_STREAM, ); $this->demcrypt = @mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], ''); $this->enmcrypt = @mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], ''); if ($this->mode == CRYPT_MODE_CFB) { $this->ecb = @mcrypt_module_open($this->cipher_name_mcrypt, '', MCRYPT_MODE_ECB, ''); } } if ($this->mode == CRYPT_MODE_CFB) { @mcrypt_generic_init($this->ecb, $this->key, str_repeat("\0", $this->block_size)); } } function _pad($text) { $length = strlen($text); if (!$this->padding) { if ($length % $this->block_size == 0) { return $text; } else { user_error("The plaintext's length ($length) is not a multiple of the block size ({$this->block_size})"); $this->padding = true; } } $pad = $this->block_size - ($length % $this->block_size); return str_pad($text, $length + $pad, chr($pad)); } function _unpad($text) { if (!$this->padding) { return $text; } $length = ord($text[strlen($text) - 1]); if (!$length || $length > $this->block_size) { return false; } return substr($text, 0, -$length); } function _clearBuffers() { $this->enbuffer = $this->debuffer = array('ciphertext' => '', 'xor' => '', 'pos' => 0, 'enmcrypt_init' => true); $this->encryptIV = $this->decryptIV = str_pad(substr($this->iv, 0, $this->block_size), $this->block_size, "\0"); if (!$this->skip_key_adjustment) { $this->key = str_pad(substr($this->key, 0, $this->key_length), $this->key_length, "\0"); } } function _string_shift(&$string, $index = 1) { $substr = substr($string, 0, $index); $string = substr($string, $index); return $substr; } function _string_pop(&$string, $index = 1) { $substr = substr($string, -$index); $string = substr($string, 0, -$index); return $substr; } function _increment_str(&$var) { for ($i = 4; $i <= strlen($var); $i+= 4) { $temp = substr($var, -$i, 4); switch ($temp) { case "\xFF\xFF\xFF\xFF": $var = substr_replace($var, "\x00\x00\x00\x00", -$i, 4); break; case "\x7F\xFF\xFF\xFF": $var = substr_replace($var, "\x80\x00\x00\x00", -$i, 4); return; default: $temp = unpack('Nnum', $temp); $var = substr_replace($var, pack('N', $temp['num'] + 1), -$i, 4); return; } } $remainder = strlen($var) % 4; if ($remainder == 0) { return; } $temp = unpack('Nnum', str_pad(substr($var, 0, $remainder), 4, "\0", STR_PAD_LEFT)); $temp = substr(pack('N', $temp['num'] + 1), -$remainder); $var = substr_replace($var, $temp, 0, $remainder); } function _setupInlineCrypt() { $this->use_inline_crypt = false; } function _createInlineCryptFunction($cipher_code) { $block_size = $this->block_size; $init_crypt = isset($cipher_code['init_crypt']) ? $cipher_code['init_crypt'] : ''; $init_encrypt = isset($cipher_code['init_encrypt']) ? $cipher_code['init_encrypt'] : ''; $init_decrypt = isset($cipher_code['init_decrypt']) ? $cipher_code['init_decrypt'] : ''; $encrypt_block = $cipher_code['encrypt_block']; $decrypt_block = $cipher_code['decrypt_block']; switch ($this->mode) { case CRYPT_MODE_ECB: $encrypt = $init_encrypt . '
                    $_ciphertext = "";
                    $_plaintext_len = strlen($_text);

                    for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
                        $in = substr($_text, $_i, '.$block_size.');
                        '.$encrypt_block.'
                        $_ciphertext.= $in;
                    }

                    return $_ciphertext;
                    '; $decrypt = $init_decrypt . '
                    $_plaintext = "";
                    $_text = str_pad($_text, strlen($_text) + ('.$block_size.' - strlen($_text) % '.$block_size.') % '.$block_size.', chr(0));
                    $_ciphertext_len = strlen($_text);

                    for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
                        $in = substr($_text, $_i, '.$block_size.');
                        '.$decrypt_block.'
                        $_plaintext.= $in;
                    }

                    return $self->_unpad($_plaintext);
                    '; break; case CRYPT_MODE_CTR: $encrypt = $init_encrypt . '
                    $_ciphertext = "";
                    $_plaintext_len = strlen($_text);
                    $_xor = $self->encryptIV;
                    $_buffer = &$self->enbuffer;
                    if (strlen($_buffer["ciphertext"])) {
                        for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
                            $_block = substr($_text, $_i, '.$block_size.');
                            if (strlen($_block) > strlen($_buffer["ciphertext"])) {
                                $in = $_xor;
                                '.$encrypt_block.'
                                $self->_increment_str($_xor);
                                $_buffer["ciphertext"].= $in;
                            }
                            $_key = $self->_string_shift($_buffer["ciphertext"], '.$block_size.');
                            $_ciphertext.= $_block ^ $_key;
                        }
                    } else {
                        for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
                            $_block = substr($_text, $_i, '.$block_size.');
                            $in = $_xor;
                            '.$encrypt_block.'
                            $self->_increment_str($_xor);
                            $_key = $in;
                            $_ciphertext.= $_block ^ $_key;
                        }
                    }
                    if ($self->continuousBuffer) {
                        $self->encryptIV = $_xor;
                        if ($_start = $_plaintext_len % '.$block_size.') {
                            $_buffer["ciphertext"] = substr($_key, $_start) . $_buffer["ciphertext"];
                        }
                    }

                    return $_ciphertext;
                '; $decrypt = $init_encrypt . '
                    $_plaintext = "";
                    $_ciphertext_len = strlen($_text);
                    $_xor = $self->decryptIV;
                    $_buffer = &$self->debuffer;

                    if (strlen($_buffer["ciphertext"])) {
                        for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
                            $_block = substr($_text, $_i, '.$block_size.');
                            if (strlen($_block) > strlen($_buffer["ciphertext"])) {
                                $in = $_xor;
                                '.$encrypt_block.'
                                $self->_increment_str($_xor);
                                $_buffer["ciphertext"].= $in;
                            }
                            $_key = $self->_string_shift($_buffer["ciphertext"], '.$block_size.');
                            $_plaintext.= $_block ^ $_key;
                        }
                    } else {
                        for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
                            $_block = substr($_text, $_i, '.$block_size.');
                            $in = $_xor;
                            '.$encrypt_block.'
                            $self->_increment_str($_xor);
                            $_key = $in;
                            $_plaintext.= $_block ^ $_key;
                        }
                    }
                    if ($self->continuousBuffer) {
                        $self->decryptIV = $_xor;
                        if ($_start = $_ciphertext_len % '.$block_size.') {
                            $_buffer["ciphertext"] = substr($_key, $_start) . $_buffer["ciphertext"];
                        }
                    }

                    return $_plaintext;
                    '; break; case CRYPT_MODE_CFB: $encrypt = $init_encrypt . '
                    $_ciphertext = "";
                    $_buffer = &$self->enbuffer;

                    if ($self->continuousBuffer) {
                        $_iv = &$self->encryptIV;
                        $_pos = &$_buffer["pos"];
                    } else {
                        $_iv = $self->encryptIV;
                        $_pos = 0;
                    }
                    $_len = strlen($_text);
                    $_i = 0;
                    if ($_pos) {
                        $_orig_pos = $_pos;
                        $_max = '.$block_size.' - $_pos;
                        if ($_len >= $_max) {
                            $_i = $_max;
                            $_len-= $_max;
                            $_pos = 0;
                        } else {
                            $_i = $_len;
                            $_pos+= $_len;
                            $_len = 0;
                        }
                        $_ciphertext = substr($_iv, $_orig_pos) ^ $_text;
                        $_iv = substr_replace($_iv, $_ciphertext, $_orig_pos, $_i);
                    }
                    while ($_len >= '.$block_size.') {
                        $in = $_iv;
                        '.$encrypt_block.';
                        $_iv = $in ^ substr($_text, $_i, '.$block_size.');
                        $_ciphertext.= $_iv;
                        $_len-= '.$block_size.';
                        $_i+= '.$block_size.';
                    }
                    if ($_len) {
                        $in = $_iv;
                        '.$encrypt_block.'
                        $_iv = $in;
                        $_block = $_iv ^ substr($_text, $_i);
                        $_iv = substr_replace($_iv, $_block, 0, $_len);
                        $_ciphertext.= $_block;
                        $_pos = $_len;
                    }
                    return $_ciphertext;
                '; $decrypt = $init_encrypt . '
                    $_plaintext = "";
                    $_buffer = &$self->debuffer;

                    if ($self->continuousBuffer) {
                        $_iv = &$self->decryptIV;
                        $_pos = &$_buffer["pos"];
                    } else {
                        $_iv = $self->decryptIV;
                        $_pos = 0;
                    }
                    $_len = strlen($_text);
                    $_i = 0;
                    if ($_pos) {
                        $_orig_pos = $_pos;
                        $_max = '.$block_size.' - $_pos;
                        if ($_len >= $_max) {
                            $_i = $_max;
                            $_len-= $_max;
                            $_pos = 0;
                        } else {
                            $_i = $_len;
                            $_pos+= $_len;
                            $_len = 0;
                        }
                        $_plaintext = substr($_iv, $_orig_pos) ^ $_text;
                        $_iv = substr_replace($_iv, substr($_text, 0, $_i), $_orig_pos, $_i);
                    }
                    while ($_len >= '.$block_size.') {
                        $in = $_iv;
                        '.$encrypt_block.'
                        $_iv = $in;
                        $cb = substr($_text, $_i, '.$block_size.');
                        $_plaintext.= $_iv ^ $cb;
                        $_iv = $cb;
                        $_len-= '.$block_size.';
                        $_i+= '.$block_size.';
                    }
                    if ($_len) {
                        $in = $_iv;
                        '.$encrypt_block.'
                        $_iv = $in;
                        $_plaintext.= $_iv ^ substr($_text, $_i);
                        $_iv = substr_replace($_iv, substr($_text, $_i), 0, $_len);
                        $_pos = $_len;
                    }

                    return $_plaintext;
                    '; break; case CRYPT_MODE_OFB: $encrypt = $init_encrypt . '
                    $_ciphertext = "";
                    $_plaintext_len = strlen($_text);
                    $_xor = $self->encryptIV;
                    $_buffer = &$self->enbuffer;

                    if (strlen($_buffer["xor"])) {
                        for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
                            $_block = substr($_text, $_i, '.$block_size.');
                            if (strlen($_block) > strlen($_buffer["xor"])) {
                                $in = $_xor;
                                '.$encrypt_block.'
                                $_xor = $in;
                                $_buffer["xor"].= $_xor;
                            }
                            $_key = $self->_string_shift($_buffer["xor"], '.$block_size.');
                            $_ciphertext.= $_block ^ $_key;
                        }
                    } else {
                        for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
                            $in = $_xor;
                            '.$encrypt_block.'
                            $_xor = $in;
                            $_ciphertext.= substr($_text, $_i, '.$block_size.') ^ $_xor;
                        }
                        $_key = $_xor;
                    }
                    if ($self->continuousBuffer) {
                        $self->encryptIV = $_xor;
                        if ($_start = $_plaintext_len % '.$block_size.') {
                             $_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"];
                        }
                    }
                    return $_ciphertext;
                    '; $decrypt = $init_encrypt . '
                    $_plaintext = "";
                    $_ciphertext_len = strlen($_text);
                    $_xor = $self->decryptIV;
                    $_buffer = &$self->debuffer;

                    if (strlen($_buffer["xor"])) {
                        for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
                            $_block = substr($_text, $_i, '.$block_size.');
                            if (strlen($_block) > strlen($_buffer["xor"])) {
                                $in = $_xor;
                                '.$encrypt_block.'
                                $_xor = $in;
                                $_buffer["xor"].= $_xor;
                            }
                            $_key = $self->_string_shift($_buffer["xor"], '.$block_size.');
                            $_plaintext.= $_block ^ $_key;
                        }
                    } else {
                        for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
                            $in = $_xor;
                            '.$encrypt_block.'
                            $_xor = $in;
                            $_plaintext.= substr($_text, $_i, '.$block_size.') ^ $_xor;
                        }
                        $_key = $_xor;
                    }
                    if ($self->continuousBuffer) {
                        $self->decryptIV = $_xor;
                        if ($_start = $_ciphertext_len % '.$block_size.') {
                             $_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"];
                        }
                    }
                    return $_plaintext;
                    '; break; case CRYPT_MODE_STREAM: $encrypt = $init_encrypt . '
                    $_ciphertext = "";
                    '.$encrypt_block.'
                    return $_ciphertext;
                    '; $decrypt = $init_decrypt . '
                    $_plaintext = "";
                    '.$decrypt_block.'
                    return $_plaintext;
                    '; break; default: $encrypt = $init_encrypt . '
                    $_ciphertext = "";
                    $_plaintext_len = strlen($_text);

                    $in = $self->encryptIV;

                    for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
                        $in = substr($_text, $_i, '.$block_size.') ^ $in;
                        '.$encrypt_block.'
                        $_ciphertext.= $in;
                    }

                    if ($self->continuousBuffer) {
                        $self->encryptIV = $in;
                    }

                    return $_ciphertext;
                    '; $decrypt = $init_decrypt . '
                    $_plaintext = "";
                    $_text = str_pad($_text, strlen($_text) + ('.$block_size.' - strlen($_text) % '.$block_size.') % '.$block_size.', chr(0));
                    $_ciphertext_len = strlen($_text);

                    $_iv = $self->decryptIV;

                    for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
                        $in = $_block = substr($_text, $_i, '.$block_size.');
                        '.$decrypt_block.'
                        $_plaintext.= $in ^ $_iv;
                        $_iv = $_block;
                    }

                    if ($self->continuousBuffer) {
                        $self->decryptIV = $_iv;
                    }

                    return $self->_unpad($_plaintext);
                    '; break; } return create_function('$_action, &$self, $_text', $init_crypt . 'if ($_action == "encrypt") { ' . $encrypt . ' } else { ' . $decrypt . ' }'); } function &_getLambdaFunctions() { static $functions = array(); return $functions; } function _hashInlineCryptFunction($bytes) { if (!defined('CRYPT_BASE_WHIRLPOOL_AVAILABLE')) { define('CRYPT_BASE_WHIRLPOOL_AVAILABLE', (bool)(extension_loaded('hash') && in_array('whirlpool', hash_algos()))); } $result = ''; $hash = $bytes; switch (true) { case CRYPT_BASE_WHIRLPOOL_AVAILABLE: foreach (str_split($bytes, 64) as $t) { $hash = hash('whirlpool', $hash, true); $result .= $t ^ $hash; } return $result . hash('whirlpool', $hash, true); default: $len = strlen($bytes); for ($i = 0; $i < $len; $i+=20) { $t = substr($bytes, $i, 20); $hash = pack('H*', sha1($hash)); $result .= $t ^ $hash; } return $result . pack('H*', sha1($hash)); } } } } if (!class_exists('Crypt_Hash')) { define('CRYPT_HASH_MODE_INTERNAL', 1); define('CRYPT_HASH_MODE_MHASH', 2); define('CRYPT_HASH_MODE_HASH', 3); class Crypt_Hash { var $hashParam; var $b; var $l = false; var $hash; var $key = false; var $opad; var $ipad; function __construct($hash = 'sha1') { if (!defined('CRYPT_HASH_MODE')) { switch (true) { case extension_loaded('hash'): define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_HASH); break; case extension_loaded('mhash'): define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_MHASH); break; default: define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_INTERNAL); } } $this->setHash($hash); } function Crypt_Hash($hash = 'sha1') { $this->__construct($hash); } function setKey($key = false) { $this->key = $key; } function getHash() { return $this->hashParam; } function setHash($hash) { $this->hashParam = $hash = strtolower($hash); switch ($hash) { case 'md5-96': case 'sha1-96': case 'sha256-96': case 'sha512-96': $hash = substr($hash, 0, -3); $this->l = 12; break; case 'md2': case 'md5': $this->l = 16; break; case 'sha1': $this->l = 20; break; case 'sha256': $this->l = 32; break; case 'sha384': $this->l = 48; break; case 'sha512': $this->l = 64; } switch ($hash) { case 'md2': $mode = CRYPT_HASH_MODE == CRYPT_HASH_MODE_HASH && in_array('md2', hash_algos()) ? CRYPT_HASH_MODE_HASH : CRYPT_HASH_MODE_INTERNAL; break; case 'sha384': case 'sha512': $mode = CRYPT_HASH_MODE == CRYPT_HASH_MODE_MHASH ? CRYPT_HASH_MODE_INTERNAL : CRYPT_HASH_MODE; break; default: $mode = CRYPT_HASH_MODE; } switch ($mode) { case CRYPT_HASH_MODE_MHASH: switch ($hash) { case 'md5': $this->hash = MHASH_MD5; break; case 'sha256': $this->hash = MHASH_SHA256; break; case 'sha1': default: $this->hash = MHASH_SHA1; } return; case CRYPT_HASH_MODE_HASH: switch ($hash) { case 'md5': $this->hash = 'md5'; return; case 'md2': case 'sha256': case 'sha384': case 'sha512': $this->hash = $hash; return; case 'sha1': default: $this->hash = 'sha1'; } return; } switch ($hash) { case 'md2': $this->b = 16; $this->hash = array($this, '_md2'); break; case 'md5': $this->b = 64; $this->hash = array($this, '_md5'); break; case 'sha256': $this->b = 64; $this->hash = array($this, '_sha256'); break; case 'sha384': case 'sha512': $this->b = 128; $this->hash = array($this, '_sha512'); break; case 'sha1': default: $this->b = 64; $this->hash = array($this, '_sha1'); } $this->ipad = str_repeat(chr(0x36), $this->b); $this->opad = str_repeat(chr(0x5C), $this->b); } function hash($text) { $mode = is_array($this->hash) ? CRYPT_HASH_MODE_INTERNAL : CRYPT_HASH_MODE; if (!empty($this->key) || is_string($this->key)) { switch ($mode) { case CRYPT_HASH_MODE_MHASH: $output = mhash($this->hash, $text, $this->key); break; case CRYPT_HASH_MODE_HASH: $output = hash_hmac($this->hash, $text, $this->key, true); break; case CRYPT_HASH_MODE_INTERNAL: $key = strlen($this->key) > $this->b ? call_user_func($this->hash, $this->key) : $this->key; $key = str_pad($key, $this->b, chr(0)); $temp = $this->ipad ^ $key; $temp .= $text; $temp = call_user_func($this->hash, $temp); $output = $this->opad ^ $key; $output.= $temp; $output = call_user_func($this->hash, $output); } } else { switch ($mode) { case CRYPT_HASH_MODE_MHASH: $output = mhash($this->hash, $text); break; case CRYPT_HASH_MODE_HASH: $output = hash($this->hash, $text, true); break; case CRYPT_HASH_MODE_INTERNAL: $output = call_user_func($this->hash, $text); } } return substr($output, 0, $this->l); } function getLength() { return $this->l; } function _md5($m) { return pack('H*', md5($m)); } function _sha1($m) { return pack('H*', sha1($m)); } function _md2($m) { static $s = array( 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6, 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188, 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24, 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251, 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63, 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50, 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165, 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210, 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157, 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27, 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15, 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197, 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65, 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123, 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233, 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228, 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237, 31, 26, 219, 153, 141, 51, 159, 17, 131, 20 ); $pad = 16 - (strlen($m) & 0xF); $m.= str_repeat(chr($pad), $pad); $length = strlen($m); $c = str_repeat(chr(0), 16); $l = chr(0); for ($i = 0; $i < $length; $i+= 16) { for ($j = 0; $j < 16; $j++) { $c[$j] = chr($s[ord($m[$i + $j] ^ $l)] ^ ord($c[$j])); $l = $c[$j]; } } $m.= $c; $length+= 16; $x = str_repeat(chr(0), 48); for ($i = 0; $i < $length; $i+= 16) { for ($j = 0; $j < 16; $j++) { $x[$j + 16] = $m[$i + $j]; $x[$j + 32] = $x[$j + 16] ^ $x[$j]; } $t = chr(0); for ($j = 0; $j < 18; $j++) { for ($k = 0; $k < 48; $k++) { $x[$k] = $t = $x[$k] ^ chr($s[ord($t)]); } $t = chr(ord($t) + $j); } } return substr($x, 0, 16); } function _sha256($m) { if (extension_loaded('suhosin')) { return pack('H*', sha256($m)); } $hash = array( 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 ); static $k = array( 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 ); $length = strlen($m); $m.= str_repeat(chr(0), 64 - (($length + 8) & 0x3F)); $m[$length] = chr(0x80); $m.= pack('N2', 0, $length << 3); $chunks = str_split($m, 64); foreach ($chunks as $chunk) { $w = array(); for ($i = 0; $i < 16; $i++) { extract(unpack('Ntemp', $this->_string_shift($chunk, 4))); $w[] = $temp; } for ($i = 16; $i < 64; $i++) { $s0 = $this->_rightRotate($w[$i - 15], 7) ^ $this->_rightRotate($w[$i - 15], 18) ^ $this->_rightShift( $w[$i - 15], 3); $s1 = $this->_rightRotate($w[$i - 2], 17) ^ $this->_rightRotate($w[$i - 2], 19) ^ $this->_rightShift( $w[$i - 2], 10); $w[$i] = $this->_add($w[$i - 16], $s0, $w[$i - 7], $s1); } list($a, $b, $c, $d, $e, $f, $g, $h) = $hash; for ($i = 0; $i < 64; $i++) { $s0 = $this->_rightRotate($a, 2) ^ $this->_rightRotate($a, 13) ^ $this->_rightRotate($a, 22); $maj = ($a & $b) ^ ($a & $c) ^ ($b & $c); $t2 = $this->_add($s0, $maj); $s1 = $this->_rightRotate($e, 6) ^ $this->_rightRotate($e, 11) ^ $this->_rightRotate($e, 25); $ch = ($e & $f) ^ ($this->_not($e) & $g); $t1 = $this->_add($h, $s1, $ch, $k[$i], $w[$i]); $h = $g; $g = $f; $f = $e; $e = $this->_add($d, $t1); $d = $c; $c = $b; $b = $a; $a = $this->_add($t1, $t2); } $hash = array( $this->_add($hash[0], $a), $this->_add($hash[1], $b), $this->_add($hash[2], $c), $this->_add($hash[3], $d), $this->_add($hash[4], $e), $this->_add($hash[5], $f), $this->_add($hash[6], $g), $this->_add($hash[7], $h) ); } return pack('N8', $hash[0], $hash[1], $hash[2], $hash[3], $hash[4], $hash[5], $hash[6], $hash[7]); } function _sha512($m) { if (!class_exists('Math_BigInteger')) { include_once 'Math/BigInteger.php'; } static $init384, $init512, $k; if (!isset($k)) { $init384 = array( 'cbbb9d5dc1059ed8', '629a292a367cd507', '9159015a3070dd17', '152fecd8f70e5939', '67332667ffc00b31', '8eb44a8768581511', 'db0c2e0d64f98fa7', '47b5481dbefa4fa4' ); $init512 = array( '6a09e667f3bcc908', 'bb67ae8584caa73b', '3c6ef372fe94f82b', 'a54ff53a5f1d36f1', '510e527fade682d1', '9b05688c2b3e6c1f', '1f83d9abfb41bd6b', '5be0cd19137e2179' ); for ($i = 0; $i < 8; $i++) { $init384[$i] = new Math_BigInteger($init384[$i], 16); $init384[$i]->setPrecision(64); $init512[$i] = new Math_BigInteger($init512[$i], 16); $init512[$i]->setPrecision(64); } $k = array( '428a2f98d728ae22', '7137449123ef65cd', 'b5c0fbcfec4d3b2f', 'e9b5dba58189dbbc', '3956c25bf348b538', '59f111f1b605d019', '923f82a4af194f9b', 'ab1c5ed5da6d8118', 'd807aa98a3030242', '12835b0145706fbe', '243185be4ee4b28c', '550c7dc3d5ffb4e2', '72be5d74f27b896f', '80deb1fe3b1696b1', '9bdc06a725c71235', 'c19bf174cf692694', 'e49b69c19ef14ad2', 'efbe4786384f25e3', '0fc19dc68b8cd5b5', '240ca1cc77ac9c65', '2de92c6f592b0275', '4a7484aa6ea6e483', '5cb0a9dcbd41fbd4', '76f988da831153b5', '983e5152ee66dfab', 'a831c66d2db43210', 'b00327c898fb213f', 'bf597fc7beef0ee4', 'c6e00bf33da88fc2', 'd5a79147930aa725', '06ca6351e003826f', '142929670a0e6e70', '27b70a8546d22ffc', '2e1b21385c26c926', '4d2c6dfc5ac42aed', '53380d139d95b3df', '650a73548baf63de', '766a0abb3c77b2a8', '81c2c92e47edaee6', '92722c851482353b', 'a2bfe8a14cf10364', 'a81a664bbc423001', 'c24b8b70d0f89791', 'c76c51a30654be30', 'd192e819d6ef5218', 'd69906245565a910', 'f40e35855771202a', '106aa07032bbd1b8', '19a4c116b8d2d0c8', '1e376c085141ab53', '2748774cdf8eeb99', '34b0bcb5e19b48a8', '391c0cb3c5c95a63', '4ed8aa4ae3418acb', '5b9cca4f7763e373', '682e6ff3d6b2b8a3', '748f82ee5defb2fc', '78a5636f43172f60', '84c87814a1f0ab72', '8cc702081a6439ec', '90befffa23631e28', 'a4506cebde82bde9', 'bef9a3f7b2c67915', 'c67178f2e372532b', 'ca273eceea26619c', 'd186b8c721c0c207', 'eada7dd6cde0eb1e', 'f57d4f7fee6ed178', '06f067aa72176fba', '0a637dc5a2c898a6', '113f9804bef90dae', '1b710b35131c471b', '28db77f523047d84', '32caab7b40c72493', '3c9ebe0a15c9bebc', '431d67c49c100d4c', '4cc5d4becb3e42b6', '597f299cfc657e2a', '5fcb6fab3ad6faec', '6c44198c4a475817' ); for ($i = 0; $i < 80; $i++) { $k[$i] = new Math_BigInteger($k[$i], 16); } } $hash = $this->l == 48 ? $init384 : $init512; $length = strlen($m); $m.= str_repeat(chr(0), 128 - (($length + 16) & 0x7F)); $m[$length] = chr(0x80); $m.= pack('N4', 0, 0, 0, $length << 3); $chunks = str_split($m, 128); foreach ($chunks as $chunk) { $w = array(); for ($i = 0; $i < 16; $i++) { $temp = new Math_BigInteger($this->_string_shift($chunk, 8), 256); $temp->setPrecision(64); $w[] = $temp; } for ($i = 16; $i < 80; $i++) { $temp = array( $w[$i - 15]->bitwise_rightRotate(1), $w[$i - 15]->bitwise_rightRotate(8), $w[$i - 15]->bitwise_rightShift(7) ); $s0 = $temp[0]->bitwise_xor($temp[1]); $s0 = $s0->bitwise_xor($temp[2]); $temp = array( $w[$i - 2]->bitwise_rightRotate(19), $w[$i - 2]->bitwise_rightRotate(61), $w[$i - 2]->bitwise_rightShift(6) ); $s1 = $temp[0]->bitwise_xor($temp[1]); $s1 = $s1->bitwise_xor($temp[2]); $w[$i] = $w[$i - 16]->copy(); $w[$i] = $w[$i]->add($s0); $w[$i] = $w[$i]->add($w[$i - 7]); $w[$i] = $w[$i]->add($s1); } $a = $hash[0]->copy(); $b = $hash[1]->copy(); $c = $hash[2]->copy(); $d = $hash[3]->copy(); $e = $hash[4]->copy(); $f = $hash[5]->copy(); $g = $hash[6]->copy(); $h = $hash[7]->copy(); for ($i = 0; $i < 80; $i++) { $temp = array( $a->bitwise_rightRotate(28), $a->bitwise_rightRotate(34), $a->bitwise_rightRotate(39) ); $s0 = $temp[0]->bitwise_xor($temp[1]); $s0 = $s0->bitwise_xor($temp[2]); $temp = array( $a->bitwise_and($b), $a->bitwise_and($c), $b->bitwise_and($c) ); $maj = $temp[0]->bitwise_xor($temp[1]); $maj = $maj->bitwise_xor($temp[2]); $t2 = $s0->add($maj); $temp = array( $e->bitwise_rightRotate(14), $e->bitwise_rightRotate(18), $e->bitwise_rightRotate(41) ); $s1 = $temp[0]->bitwise_xor($temp[1]); $s1 = $s1->bitwise_xor($temp[2]); $temp = array( $e->bitwise_and($f), $g->bitwise_and($e->bitwise_not()) ); $ch = $temp[0]->bitwise_xor($temp[1]); $t1 = $h->add($s1); $t1 = $t1->add($ch); $t1 = $t1->add($k[$i]); $t1 = $t1->add($w[$i]); $h = $g->copy(); $g = $f->copy(); $f = $e->copy(); $e = $d->add($t1); $d = $c->copy(); $c = $b->copy(); $b = $a->copy(); $a = $t1->add($t2); } $hash = array( $hash[0]->add($a), $hash[1]->add($b), $hash[2]->add($c), $hash[3]->add($d), $hash[4]->add($e), $hash[5]->add($f), $hash[6]->add($g), $hash[7]->add($h) ); } $temp = $hash[0]->toBytes() . $hash[1]->toBytes() . $hash[2]->toBytes() . $hash[3]->toBytes() . $hash[4]->toBytes() . $hash[5]->toBytes(); if ($this->l != 48) { $temp.= $hash[6]->toBytes() . $hash[7]->toBytes(); } return $temp; } function _rightRotate($int, $amt) { $invamt = 32 - $amt; $mask = (1 << $invamt) - 1; return (($int << $invamt) & 0xFFFFFFFF) | (($int >> $amt) & $mask); } function _rightShift($int, $amt) { $mask = (1 << (32 - $amt)) - 1; return ($int >> $amt) & $mask; } function _not($int) { return ~$int & 0xFFFFFFFF; } function _add() { static $mod; if (!isset($mod)) { $mod = pow(2, 32); } $result = 0; $arguments = func_get_args(); foreach ($arguments as $argument) { $result+= $argument < 0 ? ($argument & 0x7FFFFFFF) + 0x80000000 : $argument; } if (is_int($result) || version_compare(PHP_VERSION, '5.3.0') >= 0 || (PHP_OS & "\xDF\xDF\xDF") === 'WIN') { return fmod($result, $mod); } return (fmod($result, 0x80000000) & 0x7FFFFFFF) | ((fmod(floor($result / 0x80000000), 2) & 1) << 31); } function _string_shift(&$string, $index = 1) { $substr = substr($string, 0, $index); $string = substr($string, $index); return $substr; } } } if (!class_exists('Crypt_Rijndael')) { if (!class_exists('Crypt_Base')) { include_once 'Base.php'; } define('CRYPT_RIJNDAEL_MODE_CTR', CRYPT_MODE_CTR); define('CRYPT_RIJNDAEL_MODE_ECB', CRYPT_MODE_ECB); define('CRYPT_RIJNDAEL_MODE_CBC', CRYPT_MODE_CBC); define('CRYPT_RIJNDAEL_MODE_CFB', CRYPT_MODE_CFB); define('CRYPT_RIJNDAEL_MODE_OFB', CRYPT_MODE_OFB); class Crypt_Rijndael extends Crypt_Base { var $const_namespace = 'RIJNDAEL'; var $cipher_name_mcrypt = 'rijndael-128'; var $password_default_salt = 'phpseclib'; var $w; var $dw; var $Nb = 4; var $key_length = 16; var $Nk = 4; var $Nr; var $c; var $kl; function setKey($key) { if (!$this->explicit_key_length) { $length = strlen($key); switch (true) { case $length <= 16: $this->key_size = 16; break; case $length <= 20: $this->key_size = 20; break; case $length <= 24: $this->key_size = 24; break; case $length <= 28: $this->key_size = 28; break; default: $this->key_size = 32; } } parent::setKey($key); } function setKeyLength($length) { switch (true) { case $length <= 128: $this->key_length = 16; break; case $length <= 160: $this->key_length = 20; break; case $length <= 192: $this->key_length = 24; break; case $length <= 224: $this->key_length = 28; break; default: $this->key_length = 32; } parent::setKeyLength($length); } function setBlockLength($length) { $length >>= 5; if ($length > 8) { $length = 8; } elseif ($length < 4) { $length = 4; } $this->Nb = $length; $this->block_size = $length << 2; $this->changed = true; $this->_setEngine(); } function isValidEngine($engine) { switch ($engine) { case CRYPT_ENGINE_OPENSSL: if ($this->block_size != 16) { return false; } $this->cipher_name_openssl_ecb = 'aes-' . ($this->key_length << 3) . '-ecb'; $this->cipher_name_openssl = 'aes-' . ($this->key_length << 3) . '-' . $this->_openssl_translate_mode(); break; case CRYPT_ENGINE_MCRYPT: $this->cipher_name_mcrypt = 'rijndael-' . ($this->block_size << 3); if ($this->key_length % 8) { return false; } } return parent::isValidEngine($engine); } function _encryptBlock($in) { static $tables; if (empty($tables)) { $tables = &$this->_getTables(); } $t0 = $tables[0]; $t1 = $tables[1]; $t2 = $tables[2]; $t3 = $tables[3]; $sbox = $tables[4]; $state = array(); $words = unpack('N*', $in); $c = $this->c; $w = $this->w; $Nb = $this->Nb; $Nr = $this->Nr; $wc = $Nb - 1; foreach ($words as $word) { $state[] = $word ^ $w[++$wc]; } $temp = array(); for ($round = 1; $round < $Nr; ++$round) { $i = 0; $j = $c[1]; $k = $c[2]; $l = $c[3]; while ($i < $Nb) { $temp[$i] = $t0[$state[$i] >> 24 & 0x000000FF] ^ $t1[$state[$j] >> 16 & 0x000000FF] ^ $t2[$state[$k] >> 8 & 0x000000FF] ^ $t3[$state[$l] & 0x000000FF] ^ $w[++$wc]; ++$i; $j = ($j + 1) % $Nb; $k = ($k + 1) % $Nb; $l = ($l + 1) % $Nb; } $state = $temp; } for ($i = 0; $i < $Nb; ++$i) { $state[$i] = $sbox[$state[$i] & 0x000000FF] | ($sbox[$state[$i] >> 8 & 0x000000FF] << 8) | ($sbox[$state[$i] >> 16 & 0x000000FF] << 16) | ($sbox[$state[$i] >> 24 & 0x000000FF] << 24); } $i = 0; $j = $c[1]; $k = $c[2]; $l = $c[3]; while ($i < $Nb) { $temp[$i] = ($state[$i] & 0xFF000000) ^ ($state[$j] & 0x00FF0000) ^ ($state[$k] & 0x0000FF00) ^ ($state[$l] & 0x000000FF) ^ $w[$i]; ++$i; $j = ($j + 1) % $Nb; $k = ($k + 1) % $Nb; $l = ($l + 1) % $Nb; } switch ($Nb) { case 8: return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6], $temp[7]); case 7: return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6]); case 6: return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5]); case 5: return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4]); default: return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3]); } } function _decryptBlock($in) { static $invtables; if (empty($invtables)) { $invtables = &$this->_getInvTables(); } $dt0 = $invtables[0]; $dt1 = $invtables[1]; $dt2 = $invtables[2]; $dt3 = $invtables[3]; $isbox = $invtables[4]; $state = array(); $words = unpack('N*', $in); $c = $this->c; $dw = $this->dw; $Nb = $this->Nb; $Nr = $this->Nr; $wc = $Nb - 1; foreach ($words as $word) { $state[] = $word ^ $dw[++$wc]; } $temp = array(); for ($round = $Nr - 1; $round > 0; --$round) { $i = 0; $j = $Nb - $c[1]; $k = $Nb - $c[2]; $l = $Nb - $c[3]; while ($i < $Nb) { $temp[$i] = $dt0[$state[$i] >> 24 & 0x000000FF] ^ $dt1[$state[$j] >> 16 & 0x000000FF] ^ $dt2[$state[$k] >> 8 & 0x000000FF] ^ $dt3[$state[$l] & 0x000000FF] ^ $dw[++$wc]; ++$i; $j = ($j + 1) % $Nb; $k = ($k + 1) % $Nb; $l = ($l + 1) % $Nb; } $state = $temp; } $i = 0; $j = $Nb - $c[1]; $k = $Nb - $c[2]; $l = $Nb - $c[3]; while ($i < $Nb) { $word = ($state[$i] & 0xFF000000) | ($state[$j] & 0x00FF0000) | ($state[$k] & 0x0000FF00) | ($state[$l] & 0x000000FF); $temp[$i] = $dw[$i] ^ ($isbox[$word & 0x000000FF] | ($isbox[$word >> 8 & 0x000000FF] << 8) | ($isbox[$word >> 16 & 0x000000FF] << 16) | ($isbox[$word >> 24 & 0x000000FF] << 24)); ++$i; $j = ($j + 1) % $Nb; $k = ($k + 1) % $Nb; $l = ($l + 1) % $Nb; } switch ($Nb) { case 8: return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6], $temp[7]); case 7: return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5], $temp[6]); case 6: return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4], $temp[5]); case 5: return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3], $temp[4]); default: return pack('N*', $temp[0], $temp[1], $temp[2], $temp[3]); } } function _setupKey() { static $rcon = array(0, 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000, 0x6C000000, 0xD8000000, 0xAB000000, 0x4D000000, 0x9A000000, 0x2F000000, 0x5E000000, 0xBC000000, 0x63000000, 0xC6000000, 0x97000000, 0x35000000, 0x6A000000, 0xD4000000, 0xB3000000, 0x7D000000, 0xFA000000, 0xEF000000, 0xC5000000, 0x91000000 ); if (isset($this->kl['key']) && $this->key === $this->kl['key'] && $this->key_length === $this->kl['key_length'] && $this->block_size === $this->kl['block_size']) { return; } $this->kl = array('key' => $this->key, 'key_length' => $this->key_length, 'block_size' => $this->block_size); $this->Nk = $this->key_length >> 2; $this->Nr = max($this->Nk, $this->Nb) + 6; switch ($this->Nb) { case 4: case 5: case 6: $this->c = array(0, 1, 2, 3); break; case 7: $this->c = array(0, 1, 2, 4); break; case 8: $this->c = array(0, 1, 3, 4); } $w = array_values(unpack('N*words', $this->key)); $length = $this->Nb * ($this->Nr + 1); for ($i = $this->Nk; $i < $length; $i++) { $temp = $w[$i - 1]; if ($i % $this->Nk == 0) { $temp = (($temp << 8) & 0xFFFFFF00) | (($temp >> 24) & 0x000000FF); $temp = $this->_subWord($temp) ^ $rcon[$i / $this->Nk]; } elseif ($this->Nk > 6 && $i % $this->Nk == 4) { $temp = $this->_subWord($temp); } $w[$i] = $w[$i - $this->Nk] ^ $temp; } list($dt0, $dt1, $dt2, $dt3) = $this->_getInvTables(); $temp = $this->w = $this->dw = array(); for ($i = $row = $col = 0; $i < $length; $i++, $col++) { if ($col == $this->Nb) { if ($row == 0) { $this->dw[0] = $this->w[0]; } else { $j = 0; while ($j < $this->Nb) { $dw = $this->_subWord($this->w[$row][$j]); $temp[$j] = $dt0[$dw >> 24 & 0x000000FF] ^ $dt1[$dw >> 16 & 0x000000FF] ^ $dt2[$dw >> 8 & 0x000000FF] ^ $dt3[$dw & 0x000000FF]; $j++; } $this->dw[$row] = $temp; } $col = 0; $row++; } $this->w[$row][$col] = $w[$i]; } $this->dw[$row] = $this->w[$row]; $this->dw = array_reverse($this->dw); $w = array_pop($this->w); $dw = array_pop($this->dw); foreach ($this->w as $r => $wr) { foreach ($wr as $c => $wc) { $w[] = $wc; $dw[] = $this->dw[$r][$c]; } } $this->w = $w; $this->dw = $dw; } function _subWord($word) { static $sbox; if (empty($sbox)) { list(, , , , $sbox) = $this->_getTables(); } return $sbox[$word & 0x000000FF] | ($sbox[$word >> 8 & 0x000000FF] << 8) | ($sbox[$word >> 16 & 0x000000FF] << 16) | ($sbox[$word >> 24 & 0x000000FF] << 24); } function &_getTables() { static $tables; if (empty($tables)) { $t3 = array_map('intval', array( 0x6363A5C6, 0x7C7C84F8, 0x777799EE, 0x7B7B8DF6, 0xF2F20DFF, 0x6B6BBDD6, 0x6F6FB1DE, 0xC5C55491, 0x30305060, 0x01010302, 0x6767A9CE, 0x2B2B7D56, 0xFEFE19E7, 0xD7D762B5, 0xABABE64D, 0x76769AEC, 0xCACA458F, 0x82829D1F, 0xC9C94089, 0x7D7D87FA, 0xFAFA15EF, 0x5959EBB2, 0x4747C98E, 0xF0F00BFB, 0xADADEC41, 0xD4D467B3, 0xA2A2FD5F, 0xAFAFEA45, 0x9C9CBF23, 0xA4A4F753, 0x727296E4, 0xC0C05B9B, 0xB7B7C275, 0xFDFD1CE1, 0x9393AE3D, 0x26266A4C, 0x36365A6C, 0x3F3F417E, 0xF7F702F5, 0xCCCC4F83, 0x34345C68, 0xA5A5F451, 0xE5E534D1, 0xF1F108F9, 0x717193E2, 0xD8D873AB, 0x31315362, 0x15153F2A, 0x04040C08, 0xC7C75295, 0x23236546, 0xC3C35E9D, 0x18182830, 0x9696A137, 0x05050F0A, 0x9A9AB52F, 0x0707090E, 0x12123624, 0x80809B1B, 0xE2E23DDF, 0xEBEB26CD, 0x2727694E, 0xB2B2CD7F, 0x75759FEA, 0x09091B12, 0x83839E1D, 0x2C2C7458, 0x1A1A2E34, 0x1B1B2D36, 0x6E6EB2DC, 0x5A5AEEB4, 0xA0A0FB5B, 0x5252F6A4, 0x3B3B4D76, 0xD6D661B7, 0xB3B3CE7D, 0x29297B52, 0xE3E33EDD, 0x2F2F715E, 0x84849713, 0x5353F5A6, 0xD1D168B9, 0x00000000, 0xEDED2CC1, 0x20206040, 0xFCFC1FE3, 0xB1B1C879, 0x5B5BEDB6, 0x6A6ABED4, 0xCBCB468D, 0xBEBED967, 0x39394B72, 0x4A4ADE94, 0x4C4CD498, 0x5858E8B0, 0xCFCF4A85, 0xD0D06BBB, 0xEFEF2AC5, 0xAAAAE54F, 0xFBFB16ED, 0x4343C586, 0x4D4DD79A, 0x33335566, 0x85859411, 0x4545CF8A, 0xF9F910E9, 0x02020604, 0x7F7F81FE, 0x5050F0A0, 0x3C3C4478, 0x9F9FBA25, 0xA8A8E34B, 0x5151F3A2, 0xA3A3FE5D, 0x4040C080, 0x8F8F8A05, 0x9292AD3F, 0x9D9DBC21, 0x38384870, 0xF5F504F1, 0xBCBCDF63, 0xB6B6C177, 0xDADA75AF, 0x21216342, 0x10103020, 0xFFFF1AE5, 0xF3F30EFD, 0xD2D26DBF, 0xCDCD4C81, 0x0C0C1418, 0x13133526, 0xECEC2FC3, 0x5F5FE1BE, 0x9797A235, 0x4444CC88, 0x1717392E, 0xC4C45793, 0xA7A7F255, 0x7E7E82FC, 0x3D3D477A, 0x6464ACC8, 0x5D5DE7BA, 0x19192B32, 0x737395E6, 0x6060A0C0, 0x81819819, 0x4F4FD19E, 0xDCDC7FA3, 0x22226644, 0x2A2A7E54, 0x9090AB3B, 0x8888830B, 0x4646CA8C, 0xEEEE29C7, 0xB8B8D36B, 0x14143C28, 0xDEDE79A7, 0x5E5EE2BC, 0x0B0B1D16, 0xDBDB76AD, 0xE0E03BDB, 0x32325664, 0x3A3A4E74, 0x0A0A1E14, 0x4949DB92, 0x06060A0C, 0x24246C48, 0x5C5CE4B8, 0xC2C25D9F, 0xD3D36EBD, 0xACACEF43, 0x6262A6C4, 0x9191A839, 0x9595A431, 0xE4E437D3, 0x79798BF2, 0xE7E732D5, 0xC8C8438B, 0x3737596E, 0x6D6DB7DA, 0x8D8D8C01, 0xD5D564B1, 0x4E4ED29C, 0xA9A9E049, 0x6C6CB4D8, 0x5656FAAC, 0xF4F407F3, 0xEAEA25CF, 0x6565AFCA, 0x7A7A8EF4, 0xAEAEE947, 0x08081810, 0xBABAD56F, 0x787888F0, 0x25256F4A, 0x2E2E725C, 0x1C1C2438, 0xA6A6F157, 0xB4B4C773, 0xC6C65197, 0xE8E823CB, 0xDDDD7CA1, 0x74749CE8, 0x1F1F213E, 0x4B4BDD96, 0xBDBDDC61, 0x8B8B860D, 0x8A8A850F, 0x707090E0, 0x3E3E427C, 0xB5B5C471, 0x6666AACC, 0x4848D890, 0x03030506, 0xF6F601F7, 0x0E0E121C, 0x6161A3C2, 0x35355F6A, 0x5757F9AE, 0xB9B9D069, 0x86869117, 0xC1C15899, 0x1D1D273A, 0x9E9EB927, 0xE1E138D9, 0xF8F813EB, 0x9898B32B, 0x11113322, 0x6969BBD2, 0xD9D970A9, 0x8E8E8907, 0x9494A733, 0x9B9BB62D, 0x1E1E223C, 0x87879215, 0xE9E920C9, 0xCECE4987, 0x5555FFAA, 0x28287850, 0xDFDF7AA5, 0x8C8C8F03, 0xA1A1F859, 0x89898009, 0x0D0D171A, 0xBFBFDA65, 0xE6E631D7, 0x4242C684, 0x6868B8D0, 0x4141C382, 0x9999B029, 0x2D2D775A, 0x0F0F111E, 0xB0B0CB7B, 0x5454FCA8, 0xBBBBD66D, 0x16163A2C )); foreach ($t3 as $t3i) { $t0[] = (($t3i << 24) & 0xFF000000) | (($t3i >> 8) & 0x00FFFFFF); $t1[] = (($t3i << 16) & 0xFFFF0000) | (($t3i >> 16) & 0x0000FFFF); $t2[] = (($t3i << 8) & 0xFFFFFF00) | (($t3i >> 24) & 0x000000FF); } $tables = array( $t0, $t1, $t2, $t3, array( 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 ) ); } return $tables; } function &_getInvTables() { static $tables; if (empty($tables)) { $dt3 = array_map('intval', array( 0xF4A75051, 0x4165537E, 0x17A4C31A, 0x275E963A, 0xAB6BCB3B, 0x9D45F11F, 0xFA58ABAC, 0xE303934B, 0x30FA5520, 0x766DF6AD, 0xCC769188, 0x024C25F5, 0xE5D7FC4F, 0x2ACBD7C5, 0x35448026, 0x62A38FB5, 0xB15A49DE, 0xBA1B6725, 0xEA0E9845, 0xFEC0E15D, 0x2F7502C3, 0x4CF01281, 0x4697A38D, 0xD3F9C66B, 0x8F5FE703, 0x929C9515, 0x6D7AEBBF, 0x5259DA95, 0xBE832DD4, 0x7421D358, 0xE0692949, 0xC9C8448E, 0xC2896A75, 0x8E7978F4, 0x583E6B99, 0xB971DD27, 0xE14FB6BE, 0x88AD17F0, 0x20AC66C9, 0xCE3AB47D, 0xDF4A1863, 0x1A3182E5, 0x51336097, 0x537F4562, 0x6477E0B1, 0x6BAE84BB, 0x81A01CFE, 0x082B94F9, 0x48685870, 0x45FD198F, 0xDE6C8794, 0x7BF8B752, 0x73D323AB, 0x4B02E272, 0x1F8F57E3, 0x55AB2A66, 0xEB2807B2, 0xB5C2032F, 0xC57B9A86, 0x3708A5D3, 0x2887F230, 0xBFA5B223, 0x036ABA02, 0x16825CED, 0xCF1C2B8A, 0x79B492A7, 0x07F2F0F3, 0x69E2A14E, 0xDAF4CD65, 0x05BED506, 0x34621FD1, 0xA6FE8AC4, 0x2E539D34, 0xF355A0A2, 0x8AE13205, 0xF6EB75A4, 0x83EC390B, 0x60EFAA40, 0x719F065E, 0x6E1051BD, 0x218AF93E, 0xDD063D96, 0x3E05AEDD, 0xE6BD464D, 0x548DB591, 0xC45D0571, 0x06D46F04, 0x5015FF60, 0x98FB2419, 0xBDE997D6, 0x4043CC89, 0xD99E7767, 0xE842BDB0, 0x898B8807, 0x195B38E7, 0xC8EEDB79, 0x7C0A47A1, 0x420FE97C, 0x841EC9F8, 0x00000000, 0x80868309, 0x2BED4832, 0x1170AC1E, 0x5A724E6C, 0x0EFFFBFD, 0x8538560F, 0xAED51E3D, 0x2D392736, 0x0FD9640A, 0x5CA62168, 0x5B54D19B, 0x362E3A24, 0x0A67B10C, 0x57E70F93, 0xEE96D2B4, 0x9B919E1B, 0xC0C54F80, 0xDC20A261, 0x774B695A, 0x121A161C, 0x93BA0AE2, 0xA02AE5C0, 0x22E0433C, 0x1B171D12, 0x090D0B0E, 0x8BC7ADF2, 0xB6A8B92D, 0x1EA9C814, 0xF1198557, 0x75074CAF, 0x99DDBBEE, 0x7F60FDA3, 0x01269FF7, 0x72F5BC5C, 0x663BC544, 0xFB7E345B, 0x4329768B, 0x23C6DCCB, 0xEDFC68B6, 0xE4F163B8, 0x31DCCAD7, 0x63851042, 0x97224013, 0xC6112084, 0x4A247D85, 0xBB3DF8D2, 0xF93211AE, 0x29A16DC7, 0x9E2F4B1D, 0xB230F3DC, 0x8652EC0D, 0xC1E3D077, 0xB3166C2B, 0x70B999A9, 0x9448FA11, 0xE9642247, 0xFC8CC4A8, 0xF03F1AA0, 0x7D2CD856, 0x3390EF22, 0x494EC787, 0x38D1C1D9, 0xCAA2FE8C, 0xD40B3698, 0xF581CFA6, 0x7ADE28A5, 0xB78E26DA, 0xADBFA43F, 0x3A9DE42C, 0x78920D50, 0x5FCC9B6A, 0x7E466254, 0x8D13C2F6, 0xD8B8E890, 0x39F75E2E, 0xC3AFF582, 0x5D80BE9F, 0xD0937C69, 0xD52DA96F, 0x2512B3CF, 0xAC993BC8, 0x187DA710, 0x9C636EE8, 0x3BBB7BDB, 0x267809CD, 0x5918F46E, 0x9AB701EC, 0x4F9AA883, 0x956E65E6, 0xFFE67EAA, 0xBCCF0821, 0x15E8E6EF, 0xE79BD9BA, 0x6F36CE4A, 0x9F09D4EA, 0xB07CD629, 0xA4B2AF31, 0x3F23312A, 0xA59430C6, 0xA266C035, 0x4EBC3774, 0x82CAA6FC, 0x90D0B0E0, 0xA7D81533, 0x04984AF1, 0xECDAF741, 0xCD500E7F, 0x91F62F17, 0x4DD68D76, 0xEFB04D43, 0xAA4D54CC, 0x9604DFE4, 0xD1B5E39E, 0x6A881B4C, 0x2C1FB8C1, 0x65517F46, 0x5EEA049D, 0x8C355D01, 0x877473FA, 0x0B412EFB, 0x671D5AB3, 0xDBD25292, 0x105633E9, 0xD647136D, 0xD7618C9A, 0xA10C7A37, 0xF8148E59, 0x133C89EB, 0xA927EECE, 0x61C935B7, 0x1CE5EDE1, 0x47B13C7A, 0xD2DF599C, 0xF2733F55, 0x14CE7918, 0xC737BF73, 0xF7CDEA53, 0xFDAA5B5F, 0x3D6F14DF, 0x44DB8678, 0xAFF381CA, 0x68C43EB9, 0x24342C38, 0xA3405FC2, 0x1DC37216, 0xE2250CBC, 0x3C498B28, 0x0D9541FF, 0xA8017139, 0x0CB3DE08, 0xB4E49CD8, 0x56C19064, 0xCB84617B, 0x32B670D5, 0x6C5C7448, 0xB85742D0 )); foreach ($dt3 as $dt3i) { $dt0[] = (($dt3i << 24) & 0xFF000000) | (($dt3i >> 8) & 0x00FFFFFF); $dt1[] = (($dt3i << 16) & 0xFFFF0000) | (($dt3i >> 16) & 0x0000FFFF); $dt2[] = (($dt3i << 8) & 0xFFFFFF00) | (($dt3i >> 24) & 0x000000FF); }; $tables = array( $dt0, $dt1, $dt2, $dt3, array( 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D ) ); } return $tables; } function _setupInlineCrypt() { $lambda_functions =& Crypt_Rijndael::_getLambdaFunctions(); $gen_hi_opt_code = (bool)(count($lambda_functions) < 10); $code_hash = "Crypt_Rijndael, {$this->mode}, {$this->Nr}, {$this->Nb}"; if ($gen_hi_opt_code) { $code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key); } if (!isset($lambda_functions[$code_hash])) { switch (true) { case $gen_hi_opt_code: $w = $this->w; $dw = $this->dw; $init_encrypt = ''; $init_decrypt = ''; break; default: for ($i = 0, $cw = count($this->w); $i < $cw; ++$i) { $w[] = '$w[' . $i . ']'; $dw[] = '$dw[' . $i . ']'; } $init_encrypt = '$w  = $self->w;'; $init_decrypt = '$dw = $self->dw;'; } $Nr = $this->Nr; $Nb = $this->Nb; $c = $this->c; $init_encrypt.= '
                static $tables;
                if (empty($tables)) {
                    $tables = &$self->_getTables();
                }
                $t0   = $tables[0];
                $t1   = $tables[1];
                $t2   = $tables[2];
                $t3   = $tables[3];
                $sbox = $tables[4];
            '; $s = 'e'; $e = 's'; $wc = $Nb - 1; $encrypt_block = '$in = unpack("N*", $in);'."\n"; for ($i = 0; $i < $Nb; ++$i) { $encrypt_block .= '$s'.$i.' = $in['.($i + 1).'] ^ '.$w[++$wc].";\n"; } for ($round = 1; $round < $Nr; ++$round) { list($s, $e) = array($e, $s); for ($i = 0; $i < $Nb; ++$i) { $encrypt_block.= '$'.$e.$i.' =
                        $t0[($'.$s.$i .' >> 24) & 0xff] ^
                        $t1[($'.$s.(($i + $c[1]) % $Nb).' >> 16) & 0xff] ^
                        $t2[($'.$s.(($i + $c[2]) % $Nb).' >>  8) & 0xff] ^
                        $t3[ $'.$s.(($i + $c[3]) % $Nb).'        & 0xff] ^
                        '.$w[++$wc].";\n"; } } for ($i = 0; $i < $Nb; ++$i) { $encrypt_block.= '$'.$e.$i.' =
                     $sbox[ $'.$e.$i.'        & 0xff]        |
                    ($sbox[($'.$e.$i.' >>  8) & 0xff] <<  8) |
                    ($sbox[($'.$e.$i.' >> 16) & 0xff] << 16) |
                    ($sbox[($'.$e.$i.' >> 24) & 0xff] << 24);'."\n"; } $encrypt_block .= '$in = pack("N*"'."\n"; for ($i = 0; $i < $Nb; ++$i) { $encrypt_block.= ',
                    ($'.$e.$i .' & '.((int)0xFF000000).') ^
                    ($'.$e.(($i + $c[1]) % $Nb).' &         0x00FF0000   ) ^
                    ($'.$e.(($i + $c[2]) % $Nb).' &         0x0000FF00   ) ^
                    ($'.$e.(($i + $c[3]) % $Nb).' &         0x000000FF   ) ^
                    '.$w[$i]."\n"; } $encrypt_block .= ');'; $init_decrypt.= '
                static $invtables;
                if (empty($invtables)) {
                    $invtables = &$self->_getInvTables();
                }
                $dt0   = $invtables[0];
                $dt1   = $invtables[1];
                $dt2   = $invtables[2];
                $dt3   = $invtables[3];
                $isbox = $invtables[4];
            '; $s = 'e'; $e = 's'; $wc = $Nb - 1; $decrypt_block = '$in = unpack("N*", $in);'."\n"; for ($i = 0; $i < $Nb; ++$i) { $decrypt_block .= '$s'.$i.' = $in['.($i + 1).'] ^ '.$dw[++$wc].';'."\n"; } for ($round = 1; $round < $Nr; ++$round) { list($s, $e) = array($e, $s); for ($i = 0; $i < $Nb; ++$i) { $decrypt_block.= '$'.$e.$i.' =
                        $dt0[($'.$s.$i .' >> 24) & 0xff] ^
                        $dt1[($'.$s.(($Nb + $i - $c[1]) % $Nb).' >> 16) & 0xff] ^
                        $dt2[($'.$s.(($Nb + $i - $c[2]) % $Nb).' >>  8) & 0xff] ^
                        $dt3[ $'.$s.(($Nb + $i - $c[3]) % $Nb).'        & 0xff] ^
                        '.$dw[++$wc].";\n"; } } for ($i = 0; $i < $Nb; ++$i) { $decrypt_block.= '$'.$e.$i.' =
                     $isbox[ $'.$e.$i.'        & 0xff]        |
                    ($isbox[($'.$e.$i.' >>  8) & 0xff] <<  8) |
                    ($isbox[($'.$e.$i.' >> 16) & 0xff] << 16) |
                    ($isbox[($'.$e.$i.' >> 24) & 0xff] << 24);'."\n"; } $decrypt_block .= '$in = pack("N*"'."\n"; for ($i = 0; $i < $Nb; ++$i) { $decrypt_block.= ',
                    ($'.$e.$i. ' & '.((int)0xFF000000).') ^
                    ($'.$e.(($Nb + $i - $c[1]) % $Nb).' &         0x00FF0000   ) ^
                    ($'.$e.(($Nb + $i - $c[2]) % $Nb).' &         0x0000FF00   ) ^
                    ($'.$e.(($Nb + $i - $c[3]) % $Nb).' &         0x000000FF   ) ^
                    '.$dw[$i]."\n"; } $decrypt_block .= ');'; $lambda_functions[$code_hash] = $this->_createInlineCryptFunction( array( 'init_crypt' => '', 'init_encrypt' => $init_encrypt, 'init_decrypt' => $init_decrypt, 'encrypt_block' => $encrypt_block, 'decrypt_block' => $decrypt_block ) ); } $this->inline_crypt = $lambda_functions[$code_hash]; } } } if (!class_exists('Crypt_AES')) { if (!class_exists('Crypt_Rijndael')) { include_once 'Rijndael.php'; } define('CRYPT_AES_MODE_CTR', CRYPT_MODE_CTR); define('CRYPT_AES_MODE_ECB', CRYPT_MODE_ECB); define('CRYPT_AES_MODE_CBC', CRYPT_MODE_CBC); define('CRYPT_AES_MODE_CFB', CRYPT_MODE_CFB); define('CRYPT_AES_MODE_OFB', CRYPT_MODE_OFB); class Crypt_AES extends Crypt_Rijndael { var $const_namespace = 'AES'; function setBlockLength($length) { return; } function setKeyLength($length) { switch ($length) { case 160: $length = 192; break; case 224: $length = 256; } parent::setKeyLength($length); } function setKey($key) { parent::setKey($key); if (!$this->explicit_key_length) { $length = strlen($key); switch (true) { case $length <= 16: $this->key_length = 16; break; case $length <= 24: $this->key_length = 24; break; default: $this->key_length = 32; } $this->_setEngine(); } } } } if (!class_exists('Crypt_DES')) { if (!class_exists('Crypt_Base')) { include_once 'Base.php'; } define('CRYPT_DES_ENCRYPT', 0); define('CRYPT_DES_DECRYPT', 1); define('CRYPT_DES_MODE_CTR', CRYPT_MODE_CTR); define('CRYPT_DES_MODE_ECB', CRYPT_MODE_ECB); define('CRYPT_DES_MODE_CBC', CRYPT_MODE_CBC); define('CRYPT_DES_MODE_CFB', CRYPT_MODE_CFB); define('CRYPT_DES_MODE_OFB', CRYPT_MODE_OFB); class Crypt_DES extends Crypt_Base { var $block_size = 8; var $key_length = 8; var $const_namespace = 'DES'; var $cipher_name_mcrypt = 'des'; var $openssl_mode_names = array( CRYPT_MODE_ECB => 'des-ecb', CRYPT_MODE_CBC => 'des-cbc', CRYPT_MODE_CFB => 'des-cfb', CRYPT_MODE_OFB => 'des-ofb' ); var $cfb_init_len = 500; var $des_rounds = 1; var $key_length_max = 8; var $keys; var $shuffle = array( "\x00\x00\x00\x00\x00\x00\x00\x00", "\x00\x00\x00\x00\x00\x00\x00\xFF", "\x00\x00\x00\x00\x00\x00\xFF\x00", "\x00\x00\x00\x00\x00\x00\xFF\xFF", "\x00\x00\x00\x00\x00\xFF\x00\x00", "\x00\x00\x00\x00\x00\xFF\x00\xFF", "\x00\x00\x00\x00\x00\xFF\xFF\x00", "\x00\x00\x00\x00\x00\xFF\xFF\xFF", "\x00\x00\x00\x00\xFF\x00\x00\x00", "\x00\x00\x00\x00\xFF\x00\x00\xFF", "\x00\x00\x00\x00\xFF\x00\xFF\x00", "\x00\x00\x00\x00\xFF\x00\xFF\xFF", "\x00\x00\x00\x00\xFF\xFF\x00\x00", "\x00\x00\x00\x00\xFF\xFF\x00\xFF", "\x00\x00\x00\x00\xFF\xFF\xFF\x00", "\x00\x00\x00\x00\xFF\xFF\xFF\xFF", "\x00\x00\x00\xFF\x00\x00\x00\x00", "\x00\x00\x00\xFF\x00\x00\x00\xFF", "\x00\x00\x00\xFF\x00\x00\xFF\x00", "\x00\x00\x00\xFF\x00\x00\xFF\xFF", "\x00\x00\x00\xFF\x00\xFF\x00\x00", "\x00\x00\x00\xFF\x00\xFF\x00\xFF", "\x00\x00\x00\xFF\x00\xFF\xFF\x00", "\x00\x00\x00\xFF\x00\xFF\xFF\xFF", "\x00\x00\x00\xFF\xFF\x00\x00\x00", "\x00\x00\x00\xFF\xFF\x00\x00\xFF", "\x00\x00\x00\xFF\xFF\x00\xFF\x00", "\x00\x00\x00\xFF\xFF\x00\xFF\xFF", "\x00\x00\x00\xFF\xFF\xFF\x00\x00", "\x00\x00\x00\xFF\xFF\xFF\x00\xFF", "\x00\x00\x00\xFF\xFF\xFF\xFF\x00", "\x00\x00\x00\xFF\xFF\xFF\xFF\xFF", "\x00\x00\xFF\x00\x00\x00\x00\x00", "\x00\x00\xFF\x00\x00\x00\x00\xFF", "\x00\x00\xFF\x00\x00\x00\xFF\x00", "\x00\x00\xFF\x00\x00\x00\xFF\xFF", "\x00\x00\xFF\x00\x00\xFF\x00\x00", "\x00\x00\xFF\x00\x00\xFF\x00\xFF", "\x00\x00\xFF\x00\x00\xFF\xFF\x00", "\x00\x00\xFF\x00\x00\xFF\xFF\xFF", "\x00\x00\xFF\x00\xFF\x00\x00\x00", "\x00\x00\xFF\x00\xFF\x00\x00\xFF", "\x00\x00\xFF\x00\xFF\x00\xFF\x00", "\x00\x00\xFF\x00\xFF\x00\xFF\xFF", "\x00\x00\xFF\x00\xFF\xFF\x00\x00", "\x00\x00\xFF\x00\xFF\xFF\x00\xFF", "\x00\x00\xFF\x00\xFF\xFF\xFF\x00", "\x00\x00\xFF\x00\xFF\xFF\xFF\xFF", "\x00\x00\xFF\xFF\x00\x00\x00\x00", "\x00\x00\xFF\xFF\x00\x00\x00\xFF", "\x00\x00\xFF\xFF\x00\x00\xFF\x00", "\x00\x00\xFF\xFF\x00\x00\xFF\xFF", "\x00\x00\xFF\xFF\x00\xFF\x00\x00", "\x00\x00\xFF\xFF\x00\xFF\x00\xFF", "\x00\x00\xFF\xFF\x00\xFF\xFF\x00", "\x00\x00\xFF\xFF\x00\xFF\xFF\xFF", "\x00\x00\xFF\xFF\xFF\x00\x00\x00", "\x00\x00\xFF\xFF\xFF\x00\x00\xFF", "\x00\x00\xFF\xFF\xFF\x00\xFF\x00", "\x00\x00\xFF\xFF\xFF\x00\xFF\xFF", "\x00\x00\xFF\xFF\xFF\xFF\x00\x00", "\x00\x00\xFF\xFF\xFF\xFF\x00\xFF", "\x00\x00\xFF\xFF\xFF\xFF\xFF\x00", "\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF", "\x00\xFF\x00\x00\x00\x00\x00\x00", "\x00\xFF\x00\x00\x00\x00\x00\xFF", "\x00\xFF\x00\x00\x00\x00\xFF\x00", "\x00\xFF\x00\x00\x00\x00\xFF\xFF", "\x00\xFF\x00\x00\x00\xFF\x00\x00", "\x00\xFF\x00\x00\x00\xFF\x00\xFF", "\x00\xFF\x00\x00\x00\xFF\xFF\x00", "\x00\xFF\x00\x00\x00\xFF\xFF\xFF", "\x00\xFF\x00\x00\xFF\x00\x00\x00", "\x00\xFF\x00\x00\xFF\x00\x00\xFF", "\x00\xFF\x00\x00\xFF\x00\xFF\x00", "\x00\xFF\x00\x00\xFF\x00\xFF\xFF", "\x00\xFF\x00\x00\xFF\xFF\x00\x00", "\x00\xFF\x00\x00\xFF\xFF\x00\xFF", "\x00\xFF\x00\x00\xFF\xFF\xFF\x00", "\x00\xFF\x00\x00\xFF\xFF\xFF\xFF", "\x00\xFF\x00\xFF\x00\x00\x00\x00", "\x00\xFF\x00\xFF\x00\x00\x00\xFF", "\x00\xFF\x00\xFF\x00\x00\xFF\x00", "\x00\xFF\x00\xFF\x00\x00\xFF\xFF", "\x00\xFF\x00\xFF\x00\xFF\x00\x00", "\x00\xFF\x00\xFF\x00\xFF\x00\xFF", "\x00\xFF\x00\xFF\x00\xFF\xFF\x00", "\x00\xFF\x00\xFF\x00\xFF\xFF\xFF", "\x00\xFF\x00\xFF\xFF\x00\x00\x00", "\x00\xFF\x00\xFF\xFF\x00\x00\xFF", "\x00\xFF\x00\xFF\xFF\x00\xFF\x00", "\x00\xFF\x00\xFF\xFF\x00\xFF\xFF", "\x00\xFF\x00\xFF\xFF\xFF\x00\x00", "\x00\xFF\x00\xFF\xFF\xFF\x00\xFF", "\x00\xFF\x00\xFF\xFF\xFF\xFF\x00", "\x00\xFF\x00\xFF\xFF\xFF\xFF\xFF", "\x00\xFF\xFF\x00\x00\x00\x00\x00", "\x00\xFF\xFF\x00\x00\x00\x00\xFF", "\x00\xFF\xFF\x00\x00\x00\xFF\x00", "\x00\xFF\xFF\x00\x00\x00\xFF\xFF", "\x00\xFF\xFF\x00\x00\xFF\x00\x00", "\x00\xFF\xFF\x00\x00\xFF\x00\xFF", "\x00\xFF\xFF\x00\x00\xFF\xFF\x00", "\x00\xFF\xFF\x00\x00\xFF\xFF\xFF", "\x00\xFF\xFF\x00\xFF\x00\x00\x00", "\x00\xFF\xFF\x00\xFF\x00\x00\xFF", "\x00\xFF\xFF\x00\xFF\x00\xFF\x00", "\x00\xFF\xFF\x00\xFF\x00\xFF\xFF", "\x00\xFF\xFF\x00\xFF\xFF\x00\x00", "\x00\xFF\xFF\x00\xFF\xFF\x00\xFF", "\x00\xFF\xFF\x00\xFF\xFF\xFF\x00", "\x00\xFF\xFF\x00\xFF\xFF\xFF\xFF", "\x00\xFF\xFF\xFF\x00\x00\x00\x00", "\x00\xFF\xFF\xFF\x00\x00\x00\xFF", "\x00\xFF\xFF\xFF\x00\x00\xFF\x00", "\x00\xFF\xFF\xFF\x00\x00\xFF\xFF", "\x00\xFF\xFF\xFF\x00\xFF\x00\x00", "\x00\xFF\xFF\xFF\x00\xFF\x00\xFF", "\x00\xFF\xFF\xFF\x00\xFF\xFF\x00", "\x00\xFF\xFF\xFF\x00\xFF\xFF\xFF", "\x00\xFF\xFF\xFF\xFF\x00\x00\x00", "\x00\xFF\xFF\xFF\xFF\x00\x00\xFF", "\x00\xFF\xFF\xFF\xFF\x00\xFF\x00", "\x00\xFF\xFF\xFF\xFF\x00\xFF\xFF", "\x00\xFF\xFF\xFF\xFF\xFF\x00\x00", "\x00\xFF\xFF\xFF\xFF\xFF\x00\xFF", "\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00", "\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF", "\xFF\x00\x00\x00\x00\x00\x00\x00", "\xFF\x00\x00\x00\x00\x00\x00\xFF", "\xFF\x00\x00\x00\x00\x00\xFF\x00", "\xFF\x00\x00\x00\x00\x00\xFF\xFF", "\xFF\x00\x00\x00\x00\xFF\x00\x00", "\xFF\x00\x00\x00\x00\xFF\x00\xFF", "\xFF\x00\x00\x00\x00\xFF\xFF\x00", "\xFF\x00\x00\x00\x00\xFF\xFF\xFF", "\xFF\x00\x00\x00\xFF\x00\x00\x00", "\xFF\x00\x00\x00\xFF\x00\x00\xFF", "\xFF\x00\x00\x00\xFF\x00\xFF\x00", "\xFF\x00\x00\x00\xFF\x00\xFF\xFF", "\xFF\x00\x00\x00\xFF\xFF\x00\x00", "\xFF\x00\x00\x00\xFF\xFF\x00\xFF", "\xFF\x00\x00\x00\xFF\xFF\xFF\x00", "\xFF\x00\x00\x00\xFF\xFF\xFF\xFF", "\xFF\x00\x00\xFF\x00\x00\x00\x00", "\xFF\x00\x00\xFF\x00\x00\x00\xFF", "\xFF\x00\x00\xFF\x00\x00\xFF\x00", "\xFF\x00\x00\xFF\x00\x00\xFF\xFF", "\xFF\x00\x00\xFF\x00\xFF\x00\x00", "\xFF\x00\x00\xFF\x00\xFF\x00\xFF", "\xFF\x00\x00\xFF\x00\xFF\xFF\x00", "\xFF\x00\x00\xFF\x00\xFF\xFF\xFF", "\xFF\x00\x00\xFF\xFF\x00\x00\x00", "\xFF\x00\x00\xFF\xFF\x00\x00\xFF", "\xFF\x00\x00\xFF\xFF\x00\xFF\x00", "\xFF\x00\x00\xFF\xFF\x00\xFF\xFF", "\xFF\x00\x00\xFF\xFF\xFF\x00\x00", "\xFF\x00\x00\xFF\xFF\xFF\x00\xFF", "\xFF\x00\x00\xFF\xFF\xFF\xFF\x00", "\xFF\x00\x00\xFF\xFF\xFF\xFF\xFF", "\xFF\x00\xFF\x00\x00\x00\x00\x00", "\xFF\x00\xFF\x00\x00\x00\x00\xFF", "\xFF\x00\xFF\x00\x00\x00\xFF\x00", "\xFF\x00\xFF\x00\x00\x00\xFF\xFF", "\xFF\x00\xFF\x00\x00\xFF\x00\x00", "\xFF\x00\xFF\x00\x00\xFF\x00\xFF", "\xFF\x00\xFF\x00\x00\xFF\xFF\x00", "\xFF\x00\xFF\x00\x00\xFF\xFF\xFF", "\xFF\x00\xFF\x00\xFF\x00\x00\x00", "\xFF\x00\xFF\x00\xFF\x00\x00\xFF", "\xFF\x00\xFF\x00\xFF\x00\xFF\x00", "\xFF\x00\xFF\x00\xFF\x00\xFF\xFF", "\xFF\x00\xFF\x00\xFF\xFF\x00\x00", "\xFF\x00\xFF\x00\xFF\xFF\x00\xFF", "\xFF\x00\xFF\x00\xFF\xFF\xFF\x00", "\xFF\x00\xFF\x00\xFF\xFF\xFF\xFF", "\xFF\x00\xFF\xFF\x00\x00\x00\x00", "\xFF\x00\xFF\xFF\x00\x00\x00\xFF", "\xFF\x00\xFF\xFF\x00\x00\xFF\x00", "\xFF\x00\xFF\xFF\x00\x00\xFF\xFF", "\xFF\x00\xFF\xFF\x00\xFF\x00\x00", "\xFF\x00\xFF\xFF\x00\xFF\x00\xFF", "\xFF\x00\xFF\xFF\x00\xFF\xFF\x00", "\xFF\x00\xFF\xFF\x00\xFF\xFF\xFF", "\xFF\x00\xFF\xFF\xFF\x00\x00\x00", "\xFF\x00\xFF\xFF\xFF\x00\x00\xFF", "\xFF\x00\xFF\xFF\xFF\x00\xFF\x00", "\xFF\x00\xFF\xFF\xFF\x00\xFF\xFF", "\xFF\x00\xFF\xFF\xFF\xFF\x00\x00", "\xFF\x00\xFF\xFF\xFF\xFF\x00\xFF", "\xFF\x00\xFF\xFF\xFF\xFF\xFF\x00", "\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF", "\xFF\xFF\x00\x00\x00\x00\x00\x00", "\xFF\xFF\x00\x00\x00\x00\x00\xFF", "\xFF\xFF\x00\x00\x00\x00\xFF\x00", "\xFF\xFF\x00\x00\x00\x00\xFF\xFF", "\xFF\xFF\x00\x00\x00\xFF\x00\x00", "\xFF\xFF\x00\x00\x00\xFF\x00\xFF", "\xFF\xFF\x00\x00\x00\xFF\xFF\x00", "\xFF\xFF\x00\x00\x00\xFF\xFF\xFF", "\xFF\xFF\x00\x00\xFF\x00\x00\x00", "\xFF\xFF\x00\x00\xFF\x00\x00\xFF", "\xFF\xFF\x00\x00\xFF\x00\xFF\x00", "\xFF\xFF\x00\x00\xFF\x00\xFF\xFF", "\xFF\xFF\x00\x00\xFF\xFF\x00\x00", "\xFF\xFF\x00\x00\xFF\xFF\x00\xFF", "\xFF\xFF\x00\x00\xFF\xFF\xFF\x00", "\xFF\xFF\x00\x00\xFF\xFF\xFF\xFF", "\xFF\xFF\x00\xFF\x00\x00\x00\x00", "\xFF\xFF\x00\xFF\x00\x00\x00\xFF", "\xFF\xFF\x00\xFF\x00\x00\xFF\x00", "\xFF\xFF\x00\xFF\x00\x00\xFF\xFF", "\xFF\xFF\x00\xFF\x00\xFF\x00\x00", "\xFF\xFF\x00\xFF\x00\xFF\x00\xFF", "\xFF\xFF\x00\xFF\x00\xFF\xFF\x00", "\xFF\xFF\x00\xFF\x00\xFF\xFF\xFF", "\xFF\xFF\x00\xFF\xFF\x00\x00\x00", "\xFF\xFF\x00\xFF\xFF\x00\x00\xFF", "\xFF\xFF\x00\xFF\xFF\x00\xFF\x00", "\xFF\xFF\x00\xFF\xFF\x00\xFF\xFF", "\xFF\xFF\x00\xFF\xFF\xFF\x00\x00", "\xFF\xFF\x00\xFF\xFF\xFF\x00\xFF", "\xFF\xFF\x00\xFF\xFF\xFF\xFF\x00", "\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF", "\xFF\xFF\xFF\x00\x00\x00\x00\x00", "\xFF\xFF\xFF\x00\x00\x00\x00\xFF", "\xFF\xFF\xFF\x00\x00\x00\xFF\x00", "\xFF\xFF\xFF\x00\x00\x00\xFF\xFF", "\xFF\xFF\xFF\x00\x00\xFF\x00\x00", "\xFF\xFF\xFF\x00\x00\xFF\x00\xFF", "\xFF\xFF\xFF\x00\x00\xFF\xFF\x00", "\xFF\xFF\xFF\x00\x00\xFF\xFF\xFF", "\xFF\xFF\xFF\x00\xFF\x00\x00\x00", "\xFF\xFF\xFF\x00\xFF\x00\x00\xFF", "\xFF\xFF\xFF\x00\xFF\x00\xFF\x00", "\xFF\xFF\xFF\x00\xFF\x00\xFF\xFF", "\xFF\xFF\xFF\x00\xFF\xFF\x00\x00", "\xFF\xFF\xFF\x00\xFF\xFF\x00\xFF", "\xFF\xFF\xFF\x00\xFF\xFF\xFF\x00", "\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF", "\xFF\xFF\xFF\xFF\x00\x00\x00\x00", "\xFF\xFF\xFF\xFF\x00\x00\x00\xFF", "\xFF\xFF\xFF\xFF\x00\x00\xFF\x00", "\xFF\xFF\xFF\xFF\x00\x00\xFF\xFF", "\xFF\xFF\xFF\xFF\x00\xFF\x00\x00", "\xFF\xFF\xFF\xFF\x00\xFF\x00\xFF", "\xFF\xFF\xFF\xFF\x00\xFF\xFF\x00", "\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF", "\xFF\xFF\xFF\xFF\xFF\x00\x00\x00", "\xFF\xFF\xFF\xFF\xFF\x00\x00\xFF", "\xFF\xFF\xFF\xFF\xFF\x00\xFF\x00", "\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF", "\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00", "\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF", "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00", "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" ); var $ipmap = array( 0x00, 0x10, 0x01, 0x11, 0x20, 0x30, 0x21, 0x31, 0x02, 0x12, 0x03, 0x13, 0x22, 0x32, 0x23, 0x33, 0x40, 0x50, 0x41, 0x51, 0x60, 0x70, 0x61, 0x71, 0x42, 0x52, 0x43, 0x53, 0x62, 0x72, 0x63, 0x73, 0x04, 0x14, 0x05, 0x15, 0x24, 0x34, 0x25, 0x35, 0x06, 0x16, 0x07, 0x17, 0x26, 0x36, 0x27, 0x37, 0x44, 0x54, 0x45, 0x55, 0x64, 0x74, 0x65, 0x75, 0x46, 0x56, 0x47, 0x57, 0x66, 0x76, 0x67, 0x77, 0x80, 0x90, 0x81, 0x91, 0xA0, 0xB0, 0xA1, 0xB1, 0x82, 0x92, 0x83, 0x93, 0xA2, 0xB2, 0xA3, 0xB3, 0xC0, 0xD0, 0xC1, 0xD1, 0xE0, 0xF0, 0xE1, 0xF1, 0xC2, 0xD2, 0xC3, 0xD3, 0xE2, 0xF2, 0xE3, 0xF3, 0x84, 0x94, 0x85, 0x95, 0xA4, 0xB4, 0xA5, 0xB5, 0x86, 0x96, 0x87, 0x97, 0xA6, 0xB6, 0xA7, 0xB7, 0xC4, 0xD4, 0xC5, 0xD5, 0xE4, 0xF4, 0xE5, 0xF5, 0xC6, 0xD6, 0xC7, 0xD7, 0xE6, 0xF6, 0xE7, 0xF7, 0x08, 0x18, 0x09, 0x19, 0x28, 0x38, 0x29, 0x39, 0x0A, 0x1A, 0x0B, 0x1B, 0x2A, 0x3A, 0x2B, 0x3B, 0x48, 0x58, 0x49, 0x59, 0x68, 0x78, 0x69, 0x79, 0x4A, 0x5A, 0x4B, 0x5B, 0x6A, 0x7A, 0x6B, 0x7B, 0x0C, 0x1C, 0x0D, 0x1D, 0x2C, 0x3C, 0x2D, 0x3D, 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, 0x4C, 0x5C, 0x4D, 0x5D, 0x6C, 0x7C, 0x6D, 0x7D, 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, 0x88, 0x98, 0x89, 0x99, 0xA8, 0xB8, 0xA9, 0xB9, 0x8A, 0x9A, 0x8B, 0x9B, 0xAA, 0xBA, 0xAB, 0xBB, 0xC8, 0xD8, 0xC9, 0xD9, 0xE8, 0xF8, 0xE9, 0xF9, 0xCA, 0xDA, 0xCB, 0xDB, 0xEA, 0xFA, 0xEB, 0xFB, 0x8C, 0x9C, 0x8D, 0x9D, 0xAC, 0xBC, 0xAD, 0xBD, 0x8E, 0x9E, 0x8F, 0x9F, 0xAE, 0xBE, 0xAF, 0xBF, 0xCC, 0xDC, 0xCD, 0xDD, 0xEC, 0xFC, 0xED, 0xFD, 0xCE, 0xDE, 0xCF, 0xDF, 0xEE, 0xFE, 0xEF, 0xFF ); var $invipmap = array( 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF ); var $sbox1 = array( 0x00808200, 0x00000000, 0x00008000, 0x00808202, 0x00808002, 0x00008202, 0x00000002, 0x00008000, 0x00000200, 0x00808200, 0x00808202, 0x00000200, 0x00800202, 0x00808002, 0x00800000, 0x00000002, 0x00000202, 0x00800200, 0x00800200, 0x00008200, 0x00008200, 0x00808000, 0x00808000, 0x00800202, 0x00008002, 0x00800002, 0x00800002, 0x00008002, 0x00000000, 0x00000202, 0x00008202, 0x00800000, 0x00008000, 0x00808202, 0x00000002, 0x00808000, 0x00808200, 0x00800000, 0x00800000, 0x00000200, 0x00808002, 0x00008000, 0x00008200, 0x00800002, 0x00000200, 0x00000002, 0x00800202, 0x00008202, 0x00808202, 0x00008002, 0x00808000, 0x00800202, 0x00800002, 0x00000202, 0x00008202, 0x00808200, 0x00000202, 0x00800200, 0x00800200, 0x00000000, 0x00008002, 0x00008200, 0x00000000, 0x00808002 ); var $sbox2 = array( 0x40084010, 0x40004000, 0x00004000, 0x00084010, 0x00080000, 0x00000010, 0x40080010, 0x40004010, 0x40000010, 0x40084010, 0x40084000, 0x40000000, 0x40004000, 0x00080000, 0x00000010, 0x40080010, 0x00084000, 0x00080010, 0x40004010, 0x00000000, 0x40000000, 0x00004000, 0x00084010, 0x40080000, 0x00080010, 0x40000010, 0x00000000, 0x00084000, 0x00004010, 0x40084000, 0x40080000, 0x00004010, 0x00000000, 0x00084010, 0x40080010, 0x00080000, 0x40004010, 0x40080000, 0x40084000, 0x00004000, 0x40080000, 0x40004000, 0x00000010, 0x40084010, 0x00084010, 0x00000010, 0x00004000, 0x40000000, 0x00004010, 0x40084000, 0x00080000, 0x40000010, 0x00080010, 0x40004010, 0x40000010, 0x00080010, 0x00084000, 0x00000000, 0x40004000, 0x00004010, 0x40000000, 0x40080010, 0x40084010, 0x00084000 ); var $sbox3 = array( 0x00000104, 0x04010100, 0x00000000, 0x04010004, 0x04000100, 0x00000000, 0x00010104, 0x04000100, 0x00010004, 0x04000004, 0x04000004, 0x00010000, 0x04010104, 0x00010004, 0x04010000, 0x00000104, 0x04000000, 0x00000004, 0x04010100, 0x00000100, 0x00010100, 0x04010000, 0x04010004, 0x00010104, 0x04000104, 0x00010100, 0x00010000, 0x04000104, 0x00000004, 0x04010104, 0x00000100, 0x04000000, 0x04010100, 0x04000000, 0x00010004, 0x00000104, 0x00010000, 0x04010100, 0x04000100, 0x00000000, 0x00000100, 0x00010004, 0x04010104, 0x04000100, 0x04000004, 0x00000100, 0x00000000, 0x04010004, 0x04000104, 0x00010000, 0x04000000, 0x04010104, 0x00000004, 0x00010104, 0x00010100, 0x04000004, 0x04010000, 0x04000104, 0x00000104, 0x04010000, 0x00010104, 0x00000004, 0x04010004, 0x00010100 ); var $sbox4 = array( 0x80401000, 0x80001040, 0x80001040, 0x00000040, 0x00401040, 0x80400040, 0x80400000, 0x80001000, 0x00000000, 0x00401000, 0x00401000, 0x80401040, 0x80000040, 0x00000000, 0x00400040, 0x80400000, 0x80000000, 0x00001000, 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x80001000, 0x00001040, 0x80400040, 0x80000000, 0x00001040, 0x00400040, 0x00001000, 0x00401040, 0x80401040, 0x80000040, 0x00400040, 0x80400000, 0x00401000, 0x80401040, 0x80000040, 0x00000000, 0x00000000, 0x00401000, 0x00001040, 0x00400040, 0x80400040, 0x80000000, 0x80401000, 0x80001040, 0x80001040, 0x00000040, 0x80401040, 0x80000040, 0x80000000, 0x00001000, 0x80400000, 0x80001000, 0x00401040, 0x80400040, 0x80001000, 0x00001040, 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x00001000, 0x00401040 ); var $sbox5 = array( 0x00000080, 0x01040080, 0x01040000, 0x21000080, 0x00040000, 0x00000080, 0x20000000, 0x01040000, 0x20040080, 0x00040000, 0x01000080, 0x20040080, 0x21000080, 0x21040000, 0x00040080, 0x20000000, 0x01000000, 0x20040000, 0x20040000, 0x00000000, 0x20000080, 0x21040080, 0x21040080, 0x01000080, 0x21040000, 0x20000080, 0x00000000, 0x21000000, 0x01040080, 0x01000000, 0x21000000, 0x00040080, 0x00040000, 0x21000080, 0x00000080, 0x01000000, 0x20000000, 0x01040000, 0x21000080, 0x20040080, 0x01000080, 0x20000000, 0x21040000, 0x01040080, 0x20040080, 0x00000080, 0x01000000, 0x21040000, 0x21040080, 0x00040080, 0x21000000, 0x21040080, 0x01040000, 0x00000000, 0x20040000, 0x21000000, 0x00040080, 0x01000080, 0x20000080, 0x00040000, 0x00000000, 0x20040000, 0x01040080, 0x20000080 ); var $sbox6 = array( 0x10000008, 0x10200000, 0x00002000, 0x10202008, 0x10200000, 0x00000008, 0x10202008, 0x00200000, 0x10002000, 0x00202008, 0x00200000, 0x10000008, 0x00200008, 0x10002000, 0x10000000, 0x00002008, 0x00000000, 0x00200008, 0x10002008, 0x00002000, 0x00202000, 0x10002008, 0x00000008, 0x10200008, 0x10200008, 0x00000000, 0x00202008, 0x10202000, 0x00002008, 0x00202000, 0x10202000, 0x10000000, 0x10002000, 0x00000008, 0x10200008, 0x00202000, 0x10202008, 0x00200000, 0x00002008, 0x10000008, 0x00200000, 0x10002000, 0x10000000, 0x00002008, 0x10000008, 0x10202008, 0x00202000, 0x10200000, 0x00202008, 0x10202000, 0x00000000, 0x10200008, 0x00000008, 0x00002000, 0x10200000, 0x00202008, 0x00002000, 0x00200008, 0x10002008, 0x00000000, 0x10202000, 0x10000000, 0x00200008, 0x10002008 ); var $sbox7 = array( 0x00100000, 0x02100001, 0x02000401, 0x00000000, 0x00000400, 0x02000401, 0x00100401, 0x02100400, 0x02100401, 0x00100000, 0x00000000, 0x02000001, 0x00000001, 0x02000000, 0x02100001, 0x00000401, 0x02000400, 0x00100401, 0x00100001, 0x02000400, 0x02000001, 0x02100000, 0x02100400, 0x00100001, 0x02100000, 0x00000400, 0x00000401, 0x02100401, 0x00100400, 0x00000001, 0x02000000, 0x00100400, 0x02000000, 0x00100400, 0x00100000, 0x02000401, 0x02000401, 0x02100001, 0x02100001, 0x00000001, 0x00100001, 0x02000000, 0x02000400, 0x00100000, 0x02100400, 0x00000401, 0x00100401, 0x02100400, 0x00000401, 0x02000001, 0x02100401, 0x02100000, 0x00100400, 0x00000000, 0x00000001, 0x02100401, 0x00000000, 0x00100401, 0x02100000, 0x00000400, 0x02000001, 0x02000400, 0x00000400, 0x00100001 ); var $sbox8 = array( 0x08000820, 0x00000800, 0x00020000, 0x08020820, 0x08000000, 0x08000820, 0x00000020, 0x08000000, 0x00020020, 0x08020000, 0x08020820, 0x00020800, 0x08020800, 0x00020820, 0x00000800, 0x00000020, 0x08020000, 0x08000020, 0x08000800, 0x00000820, 0x00020800, 0x00020020, 0x08020020, 0x08020800, 0x00000820, 0x00000000, 0x00000000, 0x08020020, 0x08000020, 0x08000800, 0x00020820, 0x00020000, 0x00020820, 0x00020000, 0x08020800, 0x00000800, 0x00000020, 0x08020020, 0x00000800, 0x00020820, 0x08000800, 0x00000020, 0x08000020, 0x08020000, 0x08020020, 0x08000000, 0x00020000, 0x08000820, 0x00000000, 0x08020820, 0x00020020, 0x08000020, 0x08020000, 0x08000800, 0x08000820, 0x00000000, 0x08020820, 0x00020800, 0x00020800, 0x00000820, 0x00000820, 0x00020020, 0x08000000, 0x08020800 ); function isValidEngine($engine) { if ($this->key_length_max == 8) { if ($engine == CRYPT_ENGINE_OPENSSL) { $this->cipher_name_openssl_ecb = 'des-ecb'; $this->cipher_name_openssl = 'des-' . $this->_openssl_translate_mode(); } } return parent::isValidEngine($engine); } function setKey($key) { if (strlen($key) > $this->key_length_max) { $key = substr($key, 0, $this->key_length_max); } parent::setKey($key); } function _encryptBlock($in) { return $this->_processBlock($in, CRYPT_DES_ENCRYPT); } function _decryptBlock($in) { return $this->_processBlock($in, CRYPT_DES_DECRYPT); } function _processBlock($block, $mode) { static $sbox1, $sbox2, $sbox3, $sbox4, $sbox5, $sbox6, $sbox7, $sbox8, $shuffleip, $shuffleinvip; if (!$sbox1) { $sbox1 = array_map("intval", $this->sbox1); $sbox2 = array_map("intval", $this->sbox2); $sbox3 = array_map("intval", $this->sbox3); $sbox4 = array_map("intval", $this->sbox4); $sbox5 = array_map("intval", $this->sbox5); $sbox6 = array_map("intval", $this->sbox6); $sbox7 = array_map("intval", $this->sbox7); $sbox8 = array_map("intval", $this->sbox8); for ($i = 0; $i < 256; ++$i) { $shuffleip[] = $this->shuffle[$this->ipmap[$i]]; $shuffleinvip[] = $this->shuffle[$this->invipmap[$i]]; } } $keys = $this->keys[$mode]; $ki = -1; $t = unpack('Nl/Nr', $block); list($l, $r) = array($t['l'], $t['r']); $block = ($shuffleip[ $r & 0xFF] & "\x80\x80\x80\x80\x80\x80\x80\x80") | ($shuffleip[($r >> 8) & 0xFF] & "\x40\x40\x40\x40\x40\x40\x40\x40") | ($shuffleip[($r >> 16) & 0xFF] & "\x20\x20\x20\x20\x20\x20\x20\x20") | ($shuffleip[($r >> 24) & 0xFF] & "\x10\x10\x10\x10\x10\x10\x10\x10") | ($shuffleip[ $l & 0xFF] & "\x08\x08\x08\x08\x08\x08\x08\x08") | ($shuffleip[($l >> 8) & 0xFF] & "\x04\x04\x04\x04\x04\x04\x04\x04") | ($shuffleip[($l >> 16) & 0xFF] & "\x02\x02\x02\x02\x02\x02\x02\x02") | ($shuffleip[($l >> 24) & 0xFF] & "\x01\x01\x01\x01\x01\x01\x01\x01"); $t = unpack('Nl/Nr', $block); list($l, $r) = array($t['l'], $t['r']); for ($des_round = 0; $des_round < $this->des_rounds; ++$des_round) { for ($i = 0; $i < 16; $i++) { $b1 = (($r >> 3) & 0x1FFFFFFF) ^ ($r << 29) ^ $keys[++$ki]; $b2 = (($r >> 31) & 0x00000001) ^ ($r << 1) ^ $keys[++$ki]; $t = $sbox1[($b1 >> 24) & 0x3F] ^ $sbox2[($b2 >> 24) & 0x3F] ^ $sbox3[($b1 >> 16) & 0x3F] ^ $sbox4[($b2 >> 16) & 0x3F] ^ $sbox5[($b1 >> 8) & 0x3F] ^ $sbox6[($b2 >> 8) & 0x3F] ^ $sbox7[ $b1 & 0x3F] ^ $sbox8[ $b2 & 0x3F] ^ $l; $l = $r; $r = $t; } $t = $l; $l = $r; $r = $t; } return ($shuffleinvip[($r >> 24) & 0xFF] & "\x80\x80\x80\x80\x80\x80\x80\x80") | ($shuffleinvip[($l >> 24) & 0xFF] & "\x40\x40\x40\x40\x40\x40\x40\x40") | ($shuffleinvip[($r >> 16) & 0xFF] & "\x20\x20\x20\x20\x20\x20\x20\x20") | ($shuffleinvip[($l >> 16) & 0xFF] & "\x10\x10\x10\x10\x10\x10\x10\x10") | ($shuffleinvip[($r >> 8) & 0xFF] & "\x08\x08\x08\x08\x08\x08\x08\x08") | ($shuffleinvip[($l >> 8) & 0xFF] & "\x04\x04\x04\x04\x04\x04\x04\x04") | ($shuffleinvip[ $r & 0xFF] & "\x02\x02\x02\x02\x02\x02\x02\x02") | ($shuffleinvip[ $l & 0xFF] & "\x01\x01\x01\x01\x01\x01\x01\x01"); } function _setupKey() { if (isset($this->kl['key']) && $this->key === $this->kl['key'] && $this->des_rounds === $this->kl['des_rounds']) { return; } $this->kl = array('key' => $this->key, 'des_rounds' => $this->des_rounds); static $shifts = array( 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 ); static $pc1map = array( 0x00, 0x00, 0x08, 0x08, 0x04, 0x04, 0x0C, 0x0C, 0x02, 0x02, 0x0A, 0x0A, 0x06, 0x06, 0x0E, 0x0E, 0x10, 0x10, 0x18, 0x18, 0x14, 0x14, 0x1C, 0x1C, 0x12, 0x12, 0x1A, 0x1A, 0x16, 0x16, 0x1E, 0x1E, 0x20, 0x20, 0x28, 0x28, 0x24, 0x24, 0x2C, 0x2C, 0x22, 0x22, 0x2A, 0x2A, 0x26, 0x26, 0x2E, 0x2E, 0x30, 0x30, 0x38, 0x38, 0x34, 0x34, 0x3C, 0x3C, 0x32, 0x32, 0x3A, 0x3A, 0x36, 0x36, 0x3E, 0x3E, 0x40, 0x40, 0x48, 0x48, 0x44, 0x44, 0x4C, 0x4C, 0x42, 0x42, 0x4A, 0x4A, 0x46, 0x46, 0x4E, 0x4E, 0x50, 0x50, 0x58, 0x58, 0x54, 0x54, 0x5C, 0x5C, 0x52, 0x52, 0x5A, 0x5A, 0x56, 0x56, 0x5E, 0x5E, 0x60, 0x60, 0x68, 0x68, 0x64, 0x64, 0x6C, 0x6C, 0x62, 0x62, 0x6A, 0x6A, 0x66, 0x66, 0x6E, 0x6E, 0x70, 0x70, 0x78, 0x78, 0x74, 0x74, 0x7C, 0x7C, 0x72, 0x72, 0x7A, 0x7A, 0x76, 0x76, 0x7E, 0x7E, 0x80, 0x80, 0x88, 0x88, 0x84, 0x84, 0x8C, 0x8C, 0x82, 0x82, 0x8A, 0x8A, 0x86, 0x86, 0x8E, 0x8E, 0x90, 0x90, 0x98, 0x98, 0x94, 0x94, 0x9C, 0x9C, 0x92, 0x92, 0x9A, 0x9A, 0x96, 0x96, 0x9E, 0x9E, 0xA0, 0xA0, 0xA8, 0xA8, 0xA4, 0xA4, 0xAC, 0xAC, 0xA2, 0xA2, 0xAA, 0xAA, 0xA6, 0xA6, 0xAE, 0xAE, 0xB0, 0xB0, 0xB8, 0xB8, 0xB4, 0xB4, 0xBC, 0xBC, 0xB2, 0xB2, 0xBA, 0xBA, 0xB6, 0xB6, 0xBE, 0xBE, 0xC0, 0xC0, 0xC8, 0xC8, 0xC4, 0xC4, 0xCC, 0xCC, 0xC2, 0xC2, 0xCA, 0xCA, 0xC6, 0xC6, 0xCE, 0xCE, 0xD0, 0xD0, 0xD8, 0xD8, 0xD4, 0xD4, 0xDC, 0xDC, 0xD2, 0xD2, 0xDA, 0xDA, 0xD6, 0xD6, 0xDE, 0xDE, 0xE0, 0xE0, 0xE8, 0xE8, 0xE4, 0xE4, 0xEC, 0xEC, 0xE2, 0xE2, 0xEA, 0xEA, 0xE6, 0xE6, 0xEE, 0xEE, 0xF0, 0xF0, 0xF8, 0xF8, 0xF4, 0xF4, 0xFC, 0xFC, 0xF2, 0xF2, 0xFA, 0xFA, 0xF6, 0xF6, 0xFE, 0xFE ); static $pc2mapc1 = array( 0x00000000, 0x00000400, 0x00200000, 0x00200400, 0x00000001, 0x00000401, 0x00200001, 0x00200401, 0x02000000, 0x02000400, 0x02200000, 0x02200400, 0x02000001, 0x02000401, 0x02200001, 0x02200401 ); static $pc2mapc2 = array( 0x00000000, 0x00000800, 0x08000000, 0x08000800, 0x00010000, 0x00010800, 0x08010000, 0x08010800, 0x00000000, 0x00000800, 0x08000000, 0x08000800, 0x00010000, 0x00010800, 0x08010000, 0x08010800, 0x00000100, 0x00000900, 0x08000100, 0x08000900, 0x00010100, 0x00010900, 0x08010100, 0x08010900, 0x00000100, 0x00000900, 0x08000100, 0x08000900, 0x00010100, 0x00010900, 0x08010100, 0x08010900, 0x00000010, 0x00000810, 0x08000010, 0x08000810, 0x00010010, 0x00010810, 0x08010010, 0x08010810, 0x00000010, 0x00000810, 0x08000010, 0x08000810, 0x00010010, 0x00010810, 0x08010010, 0x08010810, 0x00000110, 0x00000910, 0x08000110, 0x08000910, 0x00010110, 0x00010910, 0x08010110, 0x08010910, 0x00000110, 0x00000910, 0x08000110, 0x08000910, 0x00010110, 0x00010910, 0x08010110, 0x08010910, 0x00040000, 0x00040800, 0x08040000, 0x08040800, 0x00050000, 0x00050800, 0x08050000, 0x08050800, 0x00040000, 0x00040800, 0x08040000, 0x08040800, 0x00050000, 0x00050800, 0x08050000, 0x08050800, 0x00040100, 0x00040900, 0x08040100, 0x08040900, 0x00050100, 0x00050900, 0x08050100, 0x08050900, 0x00040100, 0x00040900, 0x08040100, 0x08040900, 0x00050100, 0x00050900, 0x08050100, 0x08050900, 0x00040010, 0x00040810, 0x08040010, 0x08040810, 0x00050010, 0x00050810, 0x08050010, 0x08050810, 0x00040010, 0x00040810, 0x08040010, 0x08040810, 0x00050010, 0x00050810, 0x08050010, 0x08050810, 0x00040110, 0x00040910, 0x08040110, 0x08040910, 0x00050110, 0x00050910, 0x08050110, 0x08050910, 0x00040110, 0x00040910, 0x08040110, 0x08040910, 0x00050110, 0x00050910, 0x08050110, 0x08050910, 0x01000000, 0x01000800, 0x09000000, 0x09000800, 0x01010000, 0x01010800, 0x09010000, 0x09010800, 0x01000000, 0x01000800, 0x09000000, 0x09000800, 0x01010000, 0x01010800, 0x09010000, 0x09010800, 0x01000100, 0x01000900, 0x09000100, 0x09000900, 0x01010100, 0x01010900, 0x09010100, 0x09010900, 0x01000100, 0x01000900, 0x09000100, 0x09000900, 0x01010100, 0x01010900, 0x09010100, 0x09010900, 0x01000010, 0x01000810, 0x09000010, 0x09000810, 0x01010010, 0x01010810, 0x09010010, 0x09010810, 0x01000010, 0x01000810, 0x09000010, 0x09000810, 0x01010010, 0x01010810, 0x09010010, 0x09010810, 0x01000110, 0x01000910, 0x09000110, 0x09000910, 0x01010110, 0x01010910, 0x09010110, 0x09010910, 0x01000110, 0x01000910, 0x09000110, 0x09000910, 0x01010110, 0x01010910, 0x09010110, 0x09010910, 0x01040000, 0x01040800, 0x09040000, 0x09040800, 0x01050000, 0x01050800, 0x09050000, 0x09050800, 0x01040000, 0x01040800, 0x09040000, 0x09040800, 0x01050000, 0x01050800, 0x09050000, 0x09050800, 0x01040100, 0x01040900, 0x09040100, 0x09040900, 0x01050100, 0x01050900, 0x09050100, 0x09050900, 0x01040100, 0x01040900, 0x09040100, 0x09040900, 0x01050100, 0x01050900, 0x09050100, 0x09050900, 0x01040010, 0x01040810, 0x09040010, 0x09040810, 0x01050010, 0x01050810, 0x09050010, 0x09050810, 0x01040010, 0x01040810, 0x09040010, 0x09040810, 0x01050010, 0x01050810, 0x09050010, 0x09050810, 0x01040110, 0x01040910, 0x09040110, 0x09040910, 0x01050110, 0x01050910, 0x09050110, 0x09050910, 0x01040110, 0x01040910, 0x09040110, 0x09040910, 0x01050110, 0x01050910, 0x09050110, 0x09050910 ); static $pc2mapc3 = array( 0x00000000, 0x00000004, 0x00001000, 0x00001004, 0x00000000, 0x00000004, 0x00001000, 0x00001004, 0x10000000, 0x10000004, 0x10001000, 0x10001004, 0x10000000, 0x10000004, 0x10001000, 0x10001004, 0x00000020, 0x00000024, 0x00001020, 0x00001024, 0x00000020, 0x00000024, 0x00001020, 0x00001024, 0x10000020, 0x10000024, 0x10001020, 0x10001024, 0x10000020, 0x10000024, 0x10001020, 0x10001024, 0x00080000, 0x00080004, 0x00081000, 0x00081004, 0x00080000, 0x00080004, 0x00081000, 0x00081004, 0x10080000, 0x10080004, 0x10081000, 0x10081004, 0x10080000, 0x10080004, 0x10081000, 0x10081004, 0x00080020, 0x00080024, 0x00081020, 0x00081024, 0x00080020, 0x00080024, 0x00081020, 0x00081024, 0x10080020, 0x10080024, 0x10081020, 0x10081024, 0x10080020, 0x10080024, 0x10081020, 0x10081024, 0x20000000, 0x20000004, 0x20001000, 0x20001004, 0x20000000, 0x20000004, 0x20001000, 0x20001004, 0x30000000, 0x30000004, 0x30001000, 0x30001004, 0x30000000, 0x30000004, 0x30001000, 0x30001004, 0x20000020, 0x20000024, 0x20001020, 0x20001024, 0x20000020, 0x20000024, 0x20001020, 0x20001024, 0x30000020, 0x30000024, 0x30001020, 0x30001024, 0x30000020, 0x30000024, 0x30001020, 0x30001024, 0x20080000, 0x20080004, 0x20081000, 0x20081004, 0x20080000, 0x20080004, 0x20081000, 0x20081004, 0x30080000, 0x30080004, 0x30081000, 0x30081004, 0x30080000, 0x30080004, 0x30081000, 0x30081004, 0x20080020, 0x20080024, 0x20081020, 0x20081024, 0x20080020, 0x20080024, 0x20081020, 0x20081024, 0x30080020, 0x30080024, 0x30081020, 0x30081024, 0x30080020, 0x30080024, 0x30081020, 0x30081024, 0x00000002, 0x00000006, 0x00001002, 0x00001006, 0x00000002, 0x00000006, 0x00001002, 0x00001006, 0x10000002, 0x10000006, 0x10001002, 0x10001006, 0x10000002, 0x10000006, 0x10001002, 0x10001006, 0x00000022, 0x00000026, 0x00001022, 0x00001026, 0x00000022, 0x00000026, 0x00001022, 0x00001026, 0x10000022, 0x10000026, 0x10001022, 0x10001026, 0x10000022, 0x10000026, 0x10001022, 0x10001026, 0x00080002, 0x00080006, 0x00081002, 0x00081006, 0x00080002, 0x00080006, 0x00081002, 0x00081006, 0x10080002, 0x10080006, 0x10081002, 0x10081006, 0x10080002, 0x10080006, 0x10081002, 0x10081006, 0x00080022, 0x00080026, 0x00081022, 0x00081026, 0x00080022, 0x00080026, 0x00081022, 0x00081026, 0x10080022, 0x10080026, 0x10081022, 0x10081026, 0x10080022, 0x10080026, 0x10081022, 0x10081026, 0x20000002, 0x20000006, 0x20001002, 0x20001006, 0x20000002, 0x20000006, 0x20001002, 0x20001006, 0x30000002, 0x30000006, 0x30001002, 0x30001006, 0x30000002, 0x30000006, 0x30001002, 0x30001006, 0x20000022, 0x20000026, 0x20001022, 0x20001026, 0x20000022, 0x20000026, 0x20001022, 0x20001026, 0x30000022, 0x30000026, 0x30001022, 0x30001026, 0x30000022, 0x30000026, 0x30001022, 0x30001026, 0x20080002, 0x20080006, 0x20081002, 0x20081006, 0x20080002, 0x20080006, 0x20081002, 0x20081006, 0x30080002, 0x30080006, 0x30081002, 0x30081006, 0x30080002, 0x30080006, 0x30081002, 0x30081006, 0x20080022, 0x20080026, 0x20081022, 0x20081026, 0x20080022, 0x20080026, 0x20081022, 0x20081026, 0x30080022, 0x30080026, 0x30081022, 0x30081026, 0x30080022, 0x30080026, 0x30081022, 0x30081026 ); static $pc2mapc4 = array( 0x00000000, 0x00100000, 0x00000008, 0x00100008, 0x00000200, 0x00100200, 0x00000208, 0x00100208, 0x00000000, 0x00100000, 0x00000008, 0x00100008, 0x00000200, 0x00100200, 0x00000208, 0x00100208, 0x04000000, 0x04100000, 0x04000008, 0x04100008, 0x04000200, 0x04100200, 0x04000208, 0x04100208, 0x04000000, 0x04100000, 0x04000008, 0x04100008, 0x04000200, 0x04100200, 0x04000208, 0x04100208, 0x00002000, 0x00102000, 0x00002008, 0x00102008, 0x00002200, 0x00102200, 0x00002208, 0x00102208, 0x00002000, 0x00102000, 0x00002008, 0x00102008, 0x00002200, 0x00102200, 0x00002208, 0x00102208, 0x04002000, 0x04102000, 0x04002008, 0x04102008, 0x04002200, 0x04102200, 0x04002208, 0x04102208, 0x04002000, 0x04102000, 0x04002008, 0x04102008, 0x04002200, 0x04102200, 0x04002208, 0x04102208, 0x00000000, 0x00100000, 0x00000008, 0x00100008, 0x00000200, 0x00100200, 0x00000208, 0x00100208, 0x00000000, 0x00100000, 0x00000008, 0x00100008, 0x00000200, 0x00100200, 0x00000208, 0x00100208, 0x04000000, 0x04100000, 0x04000008, 0x04100008, 0x04000200, 0x04100200, 0x04000208, 0x04100208, 0x04000000, 0x04100000, 0x04000008, 0x04100008, 0x04000200, 0x04100200, 0x04000208, 0x04100208, 0x00002000, 0x00102000, 0x00002008, 0x00102008, 0x00002200, 0x00102200, 0x00002208, 0x00102208, 0x00002000, 0x00102000, 0x00002008, 0x00102008, 0x00002200, 0x00102200, 0x00002208, 0x00102208, 0x04002000, 0x04102000, 0x04002008, 0x04102008, 0x04002200, 0x04102200, 0x04002208, 0x04102208, 0x04002000, 0x04102000, 0x04002008, 0x04102008, 0x04002200, 0x04102200, 0x04002208, 0x04102208, 0x00020000, 0x00120000, 0x00020008, 0x00120008, 0x00020200, 0x00120200, 0x00020208, 0x00120208, 0x00020000, 0x00120000, 0x00020008, 0x00120008, 0x00020200, 0x00120200, 0x00020208, 0x00120208, 0x04020000, 0x04120000, 0x04020008, 0x04120008, 0x04020200, 0x04120200, 0x04020208, 0x04120208, 0x04020000, 0x04120000, 0x04020008, 0x04120008, 0x04020200, 0x04120200, 0x04020208, 0x04120208, 0x00022000, 0x00122000, 0x00022008, 0x00122008, 0x00022200, 0x00122200, 0x00022208, 0x00122208, 0x00022000, 0x00122000, 0x00022008, 0x00122008, 0x00022200, 0x00122200, 0x00022208, 0x00122208, 0x04022000, 0x04122000, 0x04022008, 0x04122008, 0x04022200, 0x04122200, 0x04022208, 0x04122208, 0x04022000, 0x04122000, 0x04022008, 0x04122008, 0x04022200, 0x04122200, 0x04022208, 0x04122208, 0x00020000, 0x00120000, 0x00020008, 0x00120008, 0x00020200, 0x00120200, 0x00020208, 0x00120208, 0x00020000, 0x00120000, 0x00020008, 0x00120008, 0x00020200, 0x00120200, 0x00020208, 0x00120208, 0x04020000, 0x04120000, 0x04020008, 0x04120008, 0x04020200, 0x04120200, 0x04020208, 0x04120208, 0x04020000, 0x04120000, 0x04020008, 0x04120008, 0x04020200, 0x04120200, 0x04020208, 0x04120208, 0x00022000, 0x00122000, 0x00022008, 0x00122008, 0x00022200, 0x00122200, 0x00022208, 0x00122208, 0x00022000, 0x00122000, 0x00022008, 0x00122008, 0x00022200, 0x00122200, 0x00022208, 0x00122208, 0x04022000, 0x04122000, 0x04022008, 0x04122008, 0x04022200, 0x04122200, 0x04022208, 0x04122208, 0x04022000, 0x04122000, 0x04022008, 0x04122008, 0x04022200, 0x04122200, 0x04022208, 0x04122208 ); static $pc2mapd1 = array( 0x00000000, 0x00000001, 0x08000000, 0x08000001, 0x00200000, 0x00200001, 0x08200000, 0x08200001, 0x00000002, 0x00000003, 0x08000002, 0x08000003, 0x00200002, 0x00200003, 0x08200002, 0x08200003 ); static $pc2mapd2 = array( 0x00000000, 0x00100000, 0x00000800, 0x00100800, 0x00000000, 0x00100000, 0x00000800, 0x00100800, 0x04000000, 0x04100000, 0x04000800, 0x04100800, 0x04000000, 0x04100000, 0x04000800, 0x04100800, 0x00000004, 0x00100004, 0x00000804, 0x00100804, 0x00000004, 0x00100004, 0x00000804, 0x00100804, 0x04000004, 0x04100004, 0x04000804, 0x04100804, 0x04000004, 0x04100004, 0x04000804, 0x04100804, 0x00000000, 0x00100000, 0x00000800, 0x00100800, 0x00000000, 0x00100000, 0x00000800, 0x00100800, 0x04000000, 0x04100000, 0x04000800, 0x04100800, 0x04000000, 0x04100000, 0x04000800, 0x04100800, 0x00000004, 0x00100004, 0x00000804, 0x00100804, 0x00000004, 0x00100004, 0x00000804, 0x00100804, 0x04000004, 0x04100004, 0x04000804, 0x04100804, 0x04000004, 0x04100004, 0x04000804, 0x04100804, 0x00000200, 0x00100200, 0x00000A00, 0x00100A00, 0x00000200, 0x00100200, 0x00000A00, 0x00100A00, 0x04000200, 0x04100200, 0x04000A00, 0x04100A00, 0x04000200, 0x04100200, 0x04000A00, 0x04100A00, 0x00000204, 0x00100204, 0x00000A04, 0x00100A04, 0x00000204, 0x00100204, 0x00000A04, 0x00100A04, 0x04000204, 0x04100204, 0x04000A04, 0x04100A04, 0x04000204, 0x04100204, 0x04000A04, 0x04100A04, 0x00000200, 0x00100200, 0x00000A00, 0x00100A00, 0x00000200, 0x00100200, 0x00000A00, 0x00100A00, 0x04000200, 0x04100200, 0x04000A00, 0x04100A00, 0x04000200, 0x04100200, 0x04000A00, 0x04100A00, 0x00000204, 0x00100204, 0x00000A04, 0x00100A04, 0x00000204, 0x00100204, 0x00000A04, 0x00100A04, 0x04000204, 0x04100204, 0x04000A04, 0x04100A04, 0x04000204, 0x04100204, 0x04000A04, 0x04100A04, 0x00020000, 0x00120000, 0x00020800, 0x00120800, 0x00020000, 0x00120000, 0x00020800, 0x00120800, 0x04020000, 0x04120000, 0x04020800, 0x04120800, 0x04020000, 0x04120000, 0x04020800, 0x04120800, 0x00020004, 0x00120004, 0x00020804, 0x00120804, 0x00020004, 0x00120004, 0x00020804, 0x00120804, 0x04020004, 0x04120004, 0x04020804, 0x04120804, 0x04020004, 0x04120004, 0x04020804, 0x04120804, 0x00020000, 0x00120000, 0x00020800, 0x00120800, 0x00020000, 0x00120000, 0x00020800, 0x00120800, 0x04020000, 0x04120000, 0x04020800, 0x04120800, 0x04020000, 0x04120000, 0x04020800, 0x04120800, 0x00020004, 0x00120004, 0x00020804, 0x00120804, 0x00020004, 0x00120004, 0x00020804, 0x00120804, 0x04020004, 0x04120004, 0x04020804, 0x04120804, 0x04020004, 0x04120004, 0x04020804, 0x04120804, 0x00020200, 0x00120200, 0x00020A00, 0x00120A00, 0x00020200, 0x00120200, 0x00020A00, 0x00120A00, 0x04020200, 0x04120200, 0x04020A00, 0x04120A00, 0x04020200, 0x04120200, 0x04020A00, 0x04120A00, 0x00020204, 0x00120204, 0x00020A04, 0x00120A04, 0x00020204, 0x00120204, 0x00020A04, 0x00120A04, 0x04020204, 0x04120204, 0x04020A04, 0x04120A04, 0x04020204, 0x04120204, 0x04020A04, 0x04120A04, 0x00020200, 0x00120200, 0x00020A00, 0x00120A00, 0x00020200, 0x00120200, 0x00020A00, 0x00120A00, 0x04020200, 0x04120200, 0x04020A00, 0x04120A00, 0x04020200, 0x04120200, 0x04020A00, 0x04120A00, 0x00020204, 0x00120204, 0x00020A04, 0x00120A04, 0x00020204, 0x00120204, 0x00020A04, 0x00120A04, 0x04020204, 0x04120204, 0x04020A04, 0x04120A04, 0x04020204, 0x04120204, 0x04020A04, 0x04120A04 ); static $pc2mapd3 = array( 0x00000000, 0x00010000, 0x02000000, 0x02010000, 0x00000020, 0x00010020, 0x02000020, 0x02010020, 0x00040000, 0x00050000, 0x02040000, 0x02050000, 0x00040020, 0x00050020, 0x02040020, 0x02050020, 0x00002000, 0x00012000, 0x02002000, 0x02012000, 0x00002020, 0x00012020, 0x02002020, 0x02012020, 0x00042000, 0x00052000, 0x02042000, 0x02052000, 0x00042020, 0x00052020, 0x02042020, 0x02052020, 0x00000000, 0x00010000, 0x02000000, 0x02010000, 0x00000020, 0x00010020, 0x02000020, 0x02010020, 0x00040000, 0x00050000, 0x02040000, 0x02050000, 0x00040020, 0x00050020, 0x02040020, 0x02050020, 0x00002000, 0x00012000, 0x02002000, 0x02012000, 0x00002020, 0x00012020, 0x02002020, 0x02012020, 0x00042000, 0x00052000, 0x02042000, 0x02052000, 0x00042020, 0x00052020, 0x02042020, 0x02052020, 0x00000010, 0x00010010, 0x02000010, 0x02010010, 0x00000030, 0x00010030, 0x02000030, 0x02010030, 0x00040010, 0x00050010, 0x02040010, 0x02050010, 0x00040030, 0x00050030, 0x02040030, 0x02050030, 0x00002010, 0x00012010, 0x02002010, 0x02012010, 0x00002030, 0x00012030, 0x02002030, 0x02012030, 0x00042010, 0x00052010, 0x02042010, 0x02052010, 0x00042030, 0x00052030, 0x02042030, 0x02052030, 0x00000010, 0x00010010, 0x02000010, 0x02010010, 0x00000030, 0x00010030, 0x02000030, 0x02010030, 0x00040010, 0x00050010, 0x02040010, 0x02050010, 0x00040030, 0x00050030, 0x02040030, 0x02050030, 0x00002010, 0x00012010, 0x02002010, 0x02012010, 0x00002030, 0x00012030, 0x02002030, 0x02012030, 0x00042010, 0x00052010, 0x02042010, 0x02052010, 0x00042030, 0x00052030, 0x02042030, 0x02052030, 0x20000000, 0x20010000, 0x22000000, 0x22010000, 0x20000020, 0x20010020, 0x22000020, 0x22010020, 0x20040000, 0x20050000, 0x22040000, 0x22050000, 0x20040020, 0x20050020, 0x22040020, 0x22050020, 0x20002000, 0x20012000, 0x22002000, 0x22012000, 0x20002020, 0x20012020, 0x22002020, 0x22012020, 0x20042000, 0x20052000, 0x22042000, 0x22052000, 0x20042020, 0x20052020, 0x22042020, 0x22052020, 0x20000000, 0x20010000, 0x22000000, 0x22010000, 0x20000020, 0x20010020, 0x22000020, 0x22010020, 0x20040000, 0x20050000, 0x22040000, 0x22050000, 0x20040020, 0x20050020, 0x22040020, 0x22050020, 0x20002000, 0x20012000, 0x22002000, 0x22012000, 0x20002020, 0x20012020, 0x22002020, 0x22012020, 0x20042000, 0x20052000, 0x22042000, 0x22052000, 0x20042020, 0x20052020, 0x22042020, 0x22052020, 0x20000010, 0x20010010, 0x22000010, 0x22010010, 0x20000030, 0x20010030, 0x22000030, 0x22010030, 0x20040010, 0x20050010, 0x22040010, 0x22050010, 0x20040030, 0x20050030, 0x22040030, 0x22050030, 0x20002010, 0x20012010, 0x22002010, 0x22012010, 0x20002030, 0x20012030, 0x22002030, 0x22012030, 0x20042010, 0x20052010, 0x22042010, 0x22052010, 0x20042030, 0x20052030, 0x22042030, 0x22052030, 0x20000010, 0x20010010, 0x22000010, 0x22010010, 0x20000030, 0x20010030, 0x22000030, 0x22010030, 0x20040010, 0x20050010, 0x22040010, 0x22050010, 0x20040030, 0x20050030, 0x22040030, 0x22050030, 0x20002010, 0x20012010, 0x22002010, 0x22012010, 0x20002030, 0x20012030, 0x22002030, 0x22012030, 0x20042010, 0x20052010, 0x22042010, 0x22052010, 0x20042030, 0x20052030, 0x22042030, 0x22052030 ); static $pc2mapd4 = array( 0x00000000, 0x00000400, 0x01000000, 0x01000400, 0x00000000, 0x00000400, 0x01000000, 0x01000400, 0x00000100, 0x00000500, 0x01000100, 0x01000500, 0x00000100, 0x00000500, 0x01000100, 0x01000500, 0x10000000, 0x10000400, 0x11000000, 0x11000400, 0x10000000, 0x10000400, 0x11000000, 0x11000400, 0x10000100, 0x10000500, 0x11000100, 0x11000500, 0x10000100, 0x10000500, 0x11000100, 0x11000500, 0x00080000, 0x00080400, 0x01080000, 0x01080400, 0x00080000, 0x00080400, 0x01080000, 0x01080400, 0x00080100, 0x00080500, 0x01080100, 0x01080500, 0x00080100, 0x00080500, 0x01080100, 0x01080500, 0x10080000, 0x10080400, 0x11080000, 0x11080400, 0x10080000, 0x10080400, 0x11080000, 0x11080400, 0x10080100, 0x10080500, 0x11080100, 0x11080500, 0x10080100, 0x10080500, 0x11080100, 0x11080500, 0x00000008, 0x00000408, 0x01000008, 0x01000408, 0x00000008, 0x00000408, 0x01000008, 0x01000408, 0x00000108, 0x00000508, 0x01000108, 0x01000508, 0x00000108, 0x00000508, 0x01000108, 0x01000508, 0x10000008, 0x10000408, 0x11000008, 0x11000408, 0x10000008, 0x10000408, 0x11000008, 0x11000408, 0x10000108, 0x10000508, 0x11000108, 0x11000508, 0x10000108, 0x10000508, 0x11000108, 0x11000508, 0x00080008, 0x00080408, 0x01080008, 0x01080408, 0x00080008, 0x00080408, 0x01080008, 0x01080408, 0x00080108, 0x00080508, 0x01080108, 0x01080508, 0x00080108, 0x00080508, 0x01080108, 0x01080508, 0x10080008, 0x10080408, 0x11080008, 0x11080408, 0x10080008, 0x10080408, 0x11080008, 0x11080408, 0x10080108, 0x10080508, 0x11080108, 0x11080508, 0x10080108, 0x10080508, 0x11080108, 0x11080508, 0x00001000, 0x00001400, 0x01001000, 0x01001400, 0x00001000, 0x00001400, 0x01001000, 0x01001400, 0x00001100, 0x00001500, 0x01001100, 0x01001500, 0x00001100, 0x00001500, 0x01001100, 0x01001500, 0x10001000, 0x10001400, 0x11001000, 0x11001400, 0x10001000, 0x10001400, 0x11001000, 0x11001400, 0x10001100, 0x10001500, 0x11001100, 0x11001500, 0x10001100, 0x10001500, 0x11001100, 0x11001500, 0x00081000, 0x00081400, 0x01081000, 0x01081400, 0x00081000, 0x00081400, 0x01081000, 0x01081400, 0x00081100, 0x00081500, 0x01081100, 0x01081500, 0x00081100, 0x00081500, 0x01081100, 0x01081500, 0x10081000, 0x10081400, 0x11081000, 0x11081400, 0x10081000, 0x10081400, 0x11081000, 0x11081400, 0x10081100, 0x10081500, 0x11081100, 0x11081500, 0x10081100, 0x10081500, 0x11081100, 0x11081500, 0x00001008, 0x00001408, 0x01001008, 0x01001408, 0x00001008, 0x00001408, 0x01001008, 0x01001408, 0x00001108, 0x00001508, 0x01001108, 0x01001508, 0x00001108, 0x00001508, 0x01001108, 0x01001508, 0x10001008, 0x10001408, 0x11001008, 0x11001408, 0x10001008, 0x10001408, 0x11001008, 0x11001408, 0x10001108, 0x10001508, 0x11001108, 0x11001508, 0x10001108, 0x10001508, 0x11001108, 0x11001508, 0x00081008, 0x00081408, 0x01081008, 0x01081408, 0x00081008, 0x00081408, 0x01081008, 0x01081408, 0x00081108, 0x00081508, 0x01081108, 0x01081508, 0x00081108, 0x00081508, 0x01081108, 0x01081508, 0x10081008, 0x10081408, 0x11081008, 0x11081408, 0x10081008, 0x10081408, 0x11081008, 0x11081408, 0x10081108, 0x10081508, 0x11081108, 0x11081508, 0x10081108, 0x10081508, 0x11081108, 0x11081508 ); $keys = array(); for ($des_round = 0; $des_round < $this->des_rounds; ++$des_round) { $key = str_pad(substr($this->key, $des_round * 8, 8), 8, "\0"); $t = unpack('Nl/Nr', $key); list($l, $r) = array($t['l'], $t['r']); $key = ($this->shuffle[$pc1map[ $r & 0xFF]] & "\x80\x80\x80\x80\x80\x80\x80\x00") | ($this->shuffle[$pc1map[($r >> 8) & 0xFF]] & "\x40\x40\x40\x40\x40\x40\x40\x00") | ($this->shuffle[$pc1map[($r >> 16) & 0xFF]] & "\x20\x20\x20\x20\x20\x20\x20\x00") | ($this->shuffle[$pc1map[($r >> 24) & 0xFF]] & "\x10\x10\x10\x10\x10\x10\x10\x00") | ($this->shuffle[$pc1map[ $l & 0xFF]] & "\x08\x08\x08\x08\x08\x08\x08\x00") | ($this->shuffle[$pc1map[($l >> 8) & 0xFF]] & "\x04\x04\x04\x04\x04\x04\x04\x00") | ($this->shuffle[$pc1map[($l >> 16) & 0xFF]] & "\x02\x02\x02\x02\x02\x02\x02\x00") | ($this->shuffle[$pc1map[($l >> 24) & 0xFF]] & "\x01\x01\x01\x01\x01\x01\x01\x00"); $key = unpack('Nc/Nd', $key); $c = ( $key['c'] >> 4) & 0x0FFFFFFF; $d = (($key['d'] >> 4) & 0x0FFFFFF0) | ($key['c'] & 0x0F); $keys[$des_round] = array( CRYPT_DES_ENCRYPT => array(), CRYPT_DES_DECRYPT => array_fill(0, 32, 0) ); for ($i = 0, $ki = 31; $i < 16; ++$i, $ki-= 2) { $c <<= $shifts[$i]; $c = ($c | ($c >> 28)) & 0x0FFFFFFF; $d <<= $shifts[$i]; $d = ($d | ($d >> 28)) & 0x0FFFFFFF; $cp = $pc2mapc1[ $c >> 24 ] | $pc2mapc2[($c >> 16) & 0xFF] | $pc2mapc3[($c >> 8) & 0xFF] | $pc2mapc4[ $c & 0xFF]; $dp = $pc2mapd1[ $d >> 24 ] | $pc2mapd2[($d >> 16) & 0xFF] | $pc2mapd3[($d >> 8) & 0xFF] | $pc2mapd4[ $d & 0xFF]; $val1 = ( $cp & 0xFF000000) | (($cp << 8) & 0x00FF0000) | (($dp >> 16) & 0x0000FF00) | (($dp >> 8) & 0x000000FF); $val2 = (($cp << 8) & 0xFF000000) | (($cp << 16) & 0x00FF0000) | (($dp >> 8) & 0x0000FF00) | ( $dp & 0x000000FF); $keys[$des_round][CRYPT_DES_ENCRYPT][ ] = $val1; $keys[$des_round][CRYPT_DES_DECRYPT][$ki - 1] = $val1; $keys[$des_round][CRYPT_DES_ENCRYPT][ ] = $val2; $keys[$des_round][CRYPT_DES_DECRYPT][$ki ] = $val2; } } switch ($this->des_rounds) { case 3: $this->keys = array( CRYPT_DES_ENCRYPT => array_merge( $keys[0][CRYPT_DES_ENCRYPT], $keys[1][CRYPT_DES_DECRYPT], $keys[2][CRYPT_DES_ENCRYPT] ), CRYPT_DES_DECRYPT => array_merge( $keys[2][CRYPT_DES_DECRYPT], $keys[1][CRYPT_DES_ENCRYPT], $keys[0][CRYPT_DES_DECRYPT] ) ); break; default: $this->keys = array( CRYPT_DES_ENCRYPT => $keys[0][CRYPT_DES_ENCRYPT], CRYPT_DES_DECRYPT => $keys[0][CRYPT_DES_DECRYPT] ); } } function _setupInlineCrypt() { $lambda_functions =& Crypt_DES::_getLambdaFunctions(); $des_rounds = $this->des_rounds; $gen_hi_opt_code = (bool)( count($lambda_functions) < 10 ); $code_hash = "Crypt_DES, $des_rounds, {$this->mode}"; if ($gen_hi_opt_code) { $code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key); } if (!isset($lambda_functions[$code_hash])) { $init_crypt = 'static $sbox1, $sbox2, $sbox3, $sbox4, $sbox5, $sbox6, $sbox7, $sbox8, $shuffleip, $shuffleinvip;
                if (!$sbox1) {
                    $sbox1 = array_map("intval", $self->sbox1);
                    $sbox2 = array_map("intval", $self->sbox2);
                    $sbox3 = array_map("intval", $self->sbox3);
                    $sbox4 = array_map("intval", $self->sbox4);
                    $sbox5 = array_map("intval", $self->sbox5);
                    $sbox6 = array_map("intval", $self->sbox6);
                    $sbox7 = array_map("intval", $self->sbox7);
                    $sbox8 = array_map("intval", $self->sbox8);' . '
                    for ($i = 0; $i < 256; ++$i) {
                        $shuffleip[]    =  $self->shuffle[$self->ipmap[$i]];
                        $shuffleinvip[] =  $self->shuffle[$self->invipmap[$i]];
                    }
                }
            '; switch (true) { case $gen_hi_opt_code: $k = array( CRYPT_DES_ENCRYPT => $this->keys[CRYPT_DES_ENCRYPT], CRYPT_DES_DECRYPT => $this->keys[CRYPT_DES_DECRYPT] ); $init_encrypt = ''; $init_decrypt = ''; break; default: $k = array( CRYPT_DES_ENCRYPT => array(), CRYPT_DES_DECRYPT => array() ); for ($i = 0, $c = count($this->keys[CRYPT_DES_ENCRYPT]); $i < $c; ++$i) { $k[CRYPT_DES_ENCRYPT][$i] = '$ke[' . $i . ']'; $k[CRYPT_DES_DECRYPT][$i] = '$kd[' . $i . ']'; } $init_encrypt = '$ke = $self->keys[CRYPT_DES_ENCRYPT];'; $init_decrypt = '$kd = $self->keys[CRYPT_DES_DECRYPT];'; break; } $crypt_block = array(); foreach (array(CRYPT_DES_ENCRYPT, CRYPT_DES_DECRYPT) as $c) { $crypt_block[$c] = '
                    $in = unpack("N*", $in);
                    $l  = $in[1];
                    $r  = $in[2];
                    $in = unpack("N*",
                        ($shuffleip[ $r        & 0xFF] & "\x80\x80\x80\x80\x80\x80\x80\x80") |
                        ($shuffleip[($r >>  8) & 0xFF] & "\x40\x40\x40\x40\x40\x40\x40\x40") |
                        ($shuffleip[($r >> 16) & 0xFF] & "\x20\x20\x20\x20\x20\x20\x20\x20") |
                        ($shuffleip[($r >> 24) & 0xFF] & "\x10\x10\x10\x10\x10\x10\x10\x10") |
                        ($shuffleip[ $l        & 0xFF] & "\x08\x08\x08\x08\x08\x08\x08\x08") |
                        ($shuffleip[($l >>  8) & 0xFF] & "\x04\x04\x04\x04\x04\x04\x04\x04") |
                        ($shuffleip[($l >> 16) & 0xFF] & "\x02\x02\x02\x02\x02\x02\x02\x02") |
                        ($shuffleip[($l >> 24) & 0xFF] & "\x01\x01\x01\x01\x01\x01\x01\x01")
                    );
                    ' . '
                    $l = $in[1];
                    $r = $in[2];
                '; $l = '$l'; $r = '$r'; for ($ki = -1, $des_round = 0; $des_round < $des_rounds; ++$des_round) { for ($i = 0; $i < 16; ++$i) { $crypt_block[$c].= '
                            $b1 = ((' . $r . ' >>  3) & 0x1FFFFFFF)  ^ (' . $r . ' << 29) ^ ' . $k[$c][++$ki] . ';
                            $b2 = ((' . $r . ' >> 31) & 0x00000001)  ^ (' . $r . ' <<  1) ^ ' . $k[$c][++$ki] . ';' . $l . ' = $sbox1[($b1 >> 24) & 0x3F] ^ $sbox2[($b2 >> 24) & 0x3F] ^
                                     $sbox3[($b1 >> 16) & 0x3F] ^ $sbox4[($b2 >> 16) & 0x3F] ^
                                     $sbox5[($b1 >>  8) & 0x3F] ^ $sbox6[($b2 >>  8) & 0x3F] ^
                                     $sbox7[ $b1        & 0x3F] ^ $sbox8[ $b2        & 0x3F] ^ ' . $l . ';
                        '; list($l, $r) = array($r, $l); } list($l, $r) = array($r, $l); } $crypt_block[$c].= '$in =
                    ($shuffleinvip[($l >> 24) & 0xFF] & "\x80\x80\x80\x80\x80\x80\x80\x80") |
                    ($shuffleinvip[($r >> 24) & 0xFF] & "\x40\x40\x40\x40\x40\x40\x40\x40") |
                    ($shuffleinvip[($l >> 16) & 0xFF] & "\x20\x20\x20\x20\x20\x20\x20\x20") |
                    ($shuffleinvip[($r >> 16) & 0xFF] & "\x10\x10\x10\x10\x10\x10\x10\x10") |
                    ($shuffleinvip[($l >>  8) & 0xFF] & "\x08\x08\x08\x08\x08\x08\x08\x08") |
                    ($shuffleinvip[($r >>  8) & 0xFF] & "\x04\x04\x04\x04\x04\x04\x04\x04") |
                    ($shuffleinvip[ $l        & 0xFF] & "\x02\x02\x02\x02\x02\x02\x02\x02") |
                    ($shuffleinvip[ $r        & 0xFF] & "\x01\x01\x01\x01\x01\x01\x01\x01");
                '; } $lambda_functions[$code_hash] = $this->_createInlineCryptFunction( array( 'init_crypt' => $init_crypt, 'init_encrypt' => $init_encrypt, 'init_decrypt' => $init_decrypt, 'encrypt_block' => $crypt_block[CRYPT_DES_ENCRYPT], 'decrypt_block' => $crypt_block[CRYPT_DES_DECRYPT] ) ); } $this->inline_crypt = $lambda_functions[$code_hash]; } } } if (!class_exists('Crypt_TripleDES')) { if (!class_exists('Crypt_DES')) { include_once 'DES.php'; } define('CRYPT_MODE_3CBC', -2); define('CRYPT_DES_MODE_3CBC', -2); define('CRYPT_MODE_CBC3', CRYPT_MODE_CBC); define('CRYPT_DES_MODE_CBC3', CRYPT_MODE_CBC3); class Crypt_TripleDES extends Crypt_DES { var $key_length = 24; var $password_default_salt = 'phpseclib'; var $const_namespace = 'DES'; var $cipher_name_mcrypt = 'tripledes'; var $cfb_init_len = 750; var $key_length_max = 24; var $mode_3cbc; var $des; function __construct($mode = CRYPT_MODE_CBC) { switch ($mode) { case CRYPT_DES_MODE_3CBC: parent::Crypt_Base(CRYPT_MODE_CBC); $this->mode_3cbc = true; $this->des = array( new Crypt_DES(CRYPT_MODE_CBC), new Crypt_DES(CRYPT_MODE_CBC), new Crypt_DES(CRYPT_MODE_CBC), ); $this->des[0]->disablePadding(); $this->des[1]->disablePadding(); $this->des[2]->disablePadding(); break; default: parent::__construct($mode); } } function Crypt_TripleDES($mode = CRYPT_MODE_CBC) { $this->__construct($mode); } function isValidEngine($engine) { if ($engine == CRYPT_ENGINE_OPENSSL) { $this->cipher_name_openssl_ecb = 'des-ede3'; $mode = $this->_openssl_translate_mode(); $this->cipher_name_openssl = $mode == 'ecb' ? 'des-ede3' : 'des-ede3-' . $mode; } return parent::isValidEngine($engine); } function setIV($iv) { parent::setIV($iv); if ($this->mode_3cbc) { $this->des[0]->setIV($iv); $this->des[1]->setIV($iv); $this->des[2]->setIV($iv); } } function setKeyLength($length) { $length >>= 3; switch (true) { case $length <= 8: $this->key_length = 8; break; case $length <= 16: $this->key_length = 16; break; default: $this->key_length = 24; } parent::setKeyLength($length); } function setKey($key) { $length = $this->explicit_key_length ? $this->key_length : strlen($key); if ($length > 8) { $key = str_pad(substr($key, 0, 24), 24, chr(0)); $key = $length <= 16 ? substr_replace($key, substr($key, 0, 8), 16) : substr($key, 0, 24); } else { $key = str_pad($key, 8, chr(0)); } parent::setKey($key); if ($this->mode_3cbc && $length > 8) { $this->des[0]->setKey(substr($key, 0, 8)); $this->des[1]->setKey(substr($key, 8, 8)); $this->des[2]->setKey(substr($key, 16, 8)); } } function encrypt($plaintext) { if ($this->mode_3cbc && strlen($this->key) > 8) { return $this->des[2]->encrypt( $this->des[1]->decrypt( $this->des[0]->encrypt( $this->_pad($plaintext) ) ) ); } return parent::encrypt($plaintext); } function decrypt($ciphertext) { if ($this->mode_3cbc && strlen($this->key) > 8) { return $this->_unpad( $this->des[0]->decrypt( $this->des[1]->encrypt( $this->des[2]->decrypt( str_pad($ciphertext, (strlen($ciphertext) + 7) & 0xFFFFFFF8, "\0") ) ) ) ); } return parent::decrypt($ciphertext); } function enableContinuousBuffer() { parent::enableContinuousBuffer(); if ($this->mode_3cbc) { $this->des[0]->enableContinuousBuffer(); $this->des[1]->enableContinuousBuffer(); $this->des[2]->enableContinuousBuffer(); } } function disableContinuousBuffer() { parent::disableContinuousBuffer(); if ($this->mode_3cbc) { $this->des[0]->disableContinuousBuffer(); $this->des[1]->disableContinuousBuffer(); $this->des[2]->disableContinuousBuffer(); } } function _setupKey() { switch (true) { case strlen($this->key) <= 8: $this->des_rounds = 1; break; default: $this->des_rounds = 3; if ($this->mode_3cbc) { $this->des[0]->_setupKey(); $this->des[1]->_setupKey(); $this->des[2]->_setupKey(); return; } } parent::_setupKey(); } function setPreferredEngine($engine) { if ($this->mode_3cbc) { $this->des[0]->setPreferredEngine($engine); $this->des[1]->setPreferredEngine($engine); $this->des[2]->setPreferredEngine($engine); } return parent::setPreferredEngine($engine); } } } if (!class_exists('Crypt_RSA')) { if (!function_exists('crypt_random_string')) { include_once 'Random.php'; } if (!class_exists('Crypt_Hash')) { include_once 'Hash.php'; } define('CRYPT_RSA_ENCRYPTION_OAEP', 1); define('CRYPT_RSA_ENCRYPTION_PKCS1', 2); define('CRYPT_RSA_ENCRYPTION_NONE', 3); define('CRYPT_RSA_SIGNATURE_PSS', 1); define('CRYPT_RSA_SIGNATURE_PKCS1', 2); define('CRYPT_RSA_ASN1_INTEGER', 2); define('CRYPT_RSA_ASN1_BITSTRING', 3); define('CRYPT_RSA_ASN1_OCTETSTRING', 4); define('CRYPT_RSA_ASN1_OBJECT', 6); define('CRYPT_RSA_ASN1_SEQUENCE', 48); define('CRYPT_RSA_MODE_INTERNAL', 1); define('CRYPT_RSA_MODE_OPENSSL', 2); define('CRYPT_RSA_OPENSSL_CONFIG', dirname(__FILE__) . '/../openssl.cnf'); define('CRYPT_RSA_PRIVATE_FORMAT_PKCS1', 0); define('CRYPT_RSA_PRIVATE_FORMAT_PUTTY', 1); define('CRYPT_RSA_PRIVATE_FORMAT_XML', 2); define('CRYPT_RSA_PRIVATE_FORMAT_PKCS8', 8); define('CRYPT_RSA_PUBLIC_FORMAT_RAW', 3); define('CRYPT_RSA_PUBLIC_FORMAT_PKCS1', 4); define('CRYPT_RSA_PUBLIC_FORMAT_PKCS1_RAW', 4); define('CRYPT_RSA_PUBLIC_FORMAT_XML', 5); define('CRYPT_RSA_PUBLIC_FORMAT_OPENSSH', 6); define('CRYPT_RSA_PUBLIC_FORMAT_PKCS8', 7); class Crypt_RSA { var $zero; var $one; var $privateKeyFormat = CRYPT_RSA_PRIVATE_FORMAT_PKCS1; var $publicKeyFormat = CRYPT_RSA_PUBLIC_FORMAT_PKCS8; var $modulus; var $k; var $exponent; var $primes; var $exponents; var $coefficients; var $hashName; var $hash; var $hLen; var $sLen; var $mgfHash; var $mgfHLen; var $encryptionMode = CRYPT_RSA_ENCRYPTION_OAEP; var $signatureMode = CRYPT_RSA_SIGNATURE_PSS; var $publicExponent = false; var $password = false; var $components = array(); var $current; var $configFile; var $comment = 'phpseclib-generated-key'; function __construct() { if (!class_exists('Math_BigInteger')) { include_once 'Math/BigInteger.php'; } $this->configFile = CRYPT_RSA_OPENSSL_CONFIG; if (!defined('CRYPT_RSA_MODE')) { switch (true) { case defined('MATH_BIGINTEGER_OPENSSL_DISABLE'): define('CRYPT_RSA_MODE', CRYPT_RSA_MODE_INTERNAL); break; case !function_exists('openssl_pkey_get_details'): define('CRYPT_RSA_MODE', CRYPT_RSA_MODE_INTERNAL); break; case extension_loaded('openssl') && version_compare(PHP_VERSION, '4.2.0', '>=') && file_exists($this->configFile): ob_start(); @phpinfo(); $content = ob_get_contents(); ob_end_clean(); preg_match_all('#OpenSSL (Header|Library) Version(.*)#im', $content, $matches); $versions = array(); if (!empty($matches[1])) { for ($i = 0; $i < count($matches[1]); $i++) { $fullVersion = trim(str_replace('=>', '', strip_tags($matches[2][$i]))); if (!preg_match('/(\d+\.\d+\.\d+)/i', $fullVersion, $m)) { $versions[$matches[1][$i]] = $fullVersion; } else { $versions[$matches[1][$i]] = $m[0]; } } } switch (true) { case !isset($versions['Header']): case !isset($versions['Library']): case $versions['Header'] == $versions['Library']: case version_compare($versions['Header'], '1.0.0') >= 0 && version_compare($versions['Library'], '1.0.0') >= 0: define('CRYPT_RSA_MODE', CRYPT_RSA_MODE_OPENSSL); break; default: define('CRYPT_RSA_MODE', CRYPT_RSA_MODE_INTERNAL); define('MATH_BIGINTEGER_OPENSSL_DISABLE', true); } break; default: define('CRYPT_RSA_MODE', CRYPT_RSA_MODE_INTERNAL); } } $this->zero = new Math_BigInteger(); $this->one = new Math_BigInteger(1); $this->hash = new Crypt_Hash('sha1'); $this->hLen = $this->hash->getLength(); $this->hashName = 'sha1'; $this->mgfHash = new Crypt_Hash('sha1'); $this->mgfHLen = $this->mgfHash->getLength(); } function Crypt_RSA() { $this->__construct(); } function createKey($bits = 1024, $timeout = false, $partial = array()) { if (!defined('CRYPT_RSA_EXPONENT')) { define('CRYPT_RSA_EXPONENT', '65537'); } if (!defined('CRYPT_RSA_SMALLEST_PRIME')) { define('CRYPT_RSA_SMALLEST_PRIME', 4096); } if (CRYPT_RSA_MODE == CRYPT_RSA_MODE_OPENSSL && $bits >= 384 && CRYPT_RSA_EXPONENT == 65537) { $config = array(); if (isset($this->configFile)) { $config['config'] = $this->configFile; } $rsa = openssl_pkey_new(array('private_key_bits' => $bits) + $config); openssl_pkey_export($rsa, $privatekey, null, $config); $publickey = openssl_pkey_get_details($rsa); $publickey = $publickey['key']; $privatekey = call_user_func_array(array($this, '_convertPrivateKey'), array_values($this->_parseKey($privatekey, CRYPT_RSA_PRIVATE_FORMAT_PKCS1))); $publickey = call_user_func_array(array($this, '_convertPublicKey'), array_values($this->_parseKey($publickey, CRYPT_RSA_PUBLIC_FORMAT_PKCS1))); while (openssl_error_string() !== false) { } return array( 'privatekey' => $privatekey, 'publickey' => $publickey, 'partialkey' => false ); } static $e; if (!isset($e)) { $e = new Math_BigInteger(CRYPT_RSA_EXPONENT); } extract($this->_generateMinMax($bits)); $absoluteMin = $min; $temp = $bits >> 1; if ($temp > CRYPT_RSA_SMALLEST_PRIME) { $num_primes = floor($bits / CRYPT_RSA_SMALLEST_PRIME); $temp = CRYPT_RSA_SMALLEST_PRIME; } else { $num_primes = 2; } extract($this->_generateMinMax($temp + $bits % $temp)); $finalMax = $max; extract($this->_generateMinMax($temp)); $generator = new Math_BigInteger(); $n = $this->one->copy(); if (!empty($partial)) { extract(unserialize($partial)); } else { $exponents = $coefficients = $primes = array(); $lcm = array( 'top' => $this->one->copy(), 'bottom' => false ); } $start = time(); $i0 = count($primes) + 1; do { for ($i = $i0; $i <= $num_primes; $i++) { if ($timeout !== false) { $timeout-= time() - $start; $start = time(); if ($timeout <= 0) { return array( 'privatekey' => '', 'publickey' => '', 'partialkey' => serialize(array( 'primes' => $primes, 'coefficients' => $coefficients, 'lcm' => $lcm, 'exponents' => $exponents )) ); } } if ($i == $num_primes) { list($min, $temp) = $absoluteMin->divide($n); if (!$temp->equals($this->zero)) { $min = $min->add($this->one); } $primes[$i] = $generator->randomPrime($min, $finalMax, $timeout); } else { $primes[$i] = $generator->randomPrime($min, $max, $timeout); } if ($primes[$i] === false) { if (count($primes) > 1) { $partialkey = ''; } else { array_pop($primes); $partialkey = serialize(array( 'primes' => $primes, 'coefficients' => $coefficients, 'lcm' => $lcm, 'exponents' => $exponents )); } return array( 'privatekey' => '', 'publickey' => '', 'partialkey' => $partialkey ); } if ($i > 2) { $coefficients[$i] = $n->modInverse($primes[$i]); } $n = $n->multiply($primes[$i]); $temp = $primes[$i]->subtract($this->one); $lcm['top'] = $lcm['top']->multiply($temp); $lcm['bottom'] = $lcm['bottom'] === false ? $temp : $lcm['bottom']->gcd($temp); $exponents[$i] = $e->modInverse($temp); } list($temp) = $lcm['top']->divide($lcm['bottom']); $gcd = $temp->gcd($e); $i0 = 1; } while (!$gcd->equals($this->one)); $d = $e->modInverse($temp); $coefficients[2] = $primes[2]->modInverse($primes[1]); return array( 'privatekey' => $this->_convertPrivateKey($n, $e, $d, $primes, $exponents, $coefficients), 'publickey' => $this->_convertPublicKey($n, $e), 'partialkey' => false ); } function _convertPrivateKey($n, $e, $d, $primes, $exponents, $coefficients) { $signed = $this->privateKeyFormat != CRYPT_RSA_PRIVATE_FORMAT_XML; $num_primes = count($primes); $raw = array( 'version' => $num_primes == 2 ? chr(0) : chr(1), 'modulus' => $n->toBytes($signed), 'publicExponent' => $e->toBytes($signed), 'privateExponent' => $d->toBytes($signed), 'prime1' => $primes[1]->toBytes($signed), 'prime2' => $primes[2]->toBytes($signed), 'exponent1' => $exponents[1]->toBytes($signed), 'exponent2' => $exponents[2]->toBytes($signed), 'coefficient' => $coefficients[2]->toBytes($signed) ); switch ($this->privateKeyFormat) { case CRYPT_RSA_PRIVATE_FORMAT_XML: if ($num_primes != 2) { return false; } return "<RSAKeyValue>\r\n" . '  <Modulus>' . base64_encode($raw['modulus']) . "</Modulus>\r\n" . '  <Exponent>' . base64_encode($raw['publicExponent']) . "</Exponent>\r\n" . '  <P>' . base64_encode($raw['prime1']) . "</P>\r\n" . '  <Q>' . base64_encode($raw['prime2']) . "</Q>\r\n" . '  <DP>' . base64_encode($raw['exponent1']) . "</DP>\r\n" . '  <DQ>' . base64_encode($raw['exponent2']) . "</DQ>\r\n" . '  <InverseQ>' . base64_encode($raw['coefficient']) . "</InverseQ>\r\n" . '  <D>' . base64_encode($raw['privateExponent']) . "</D>\r\n" . '</RSAKeyValue>'; break; case CRYPT_RSA_PRIVATE_FORMAT_PUTTY: if ($num_primes != 2) { return false; } $key = "PuTTY-User-Key-File-2: ssh-rsa\r\nEncryption: "; $encryption = (!empty($this->password) || is_string($this->password)) ? 'aes256-cbc' : 'none'; $key.= $encryption; $key.= "\r\nComment: " . $this->comment . "\r\n"; $public = pack( 'Na*Na*Na*', strlen('ssh-rsa'), 'ssh-rsa', strlen($raw['publicExponent']), $raw['publicExponent'], strlen($raw['modulus']), $raw['modulus'] ); $source = pack( 'Na*Na*Na*Na*', strlen('ssh-rsa'), 'ssh-rsa', strlen($encryption), $encryption, strlen($this->comment), $this->comment, strlen($public), $public ); $public = base64_encode($public); $key.= "Public-Lines: " . ((strlen($public) + 63) >> 6) . "\r\n"; $key.= chunk_split($public, 64); $private = pack( 'Na*Na*Na*Na*', strlen($raw['privateExponent']), $raw['privateExponent'], strlen($raw['prime1']), $raw['prime1'], strlen($raw['prime2']), $raw['prime2'], strlen($raw['coefficient']), $raw['coefficient'] ); if (empty($this->password) && !is_string($this->password)) { $source.= pack('Na*', strlen($private), $private); $hashkey = 'putty-private-key-file-mac-key'; } else { $private.= crypt_random_string(16 - (strlen($private) & 15)); $source.= pack('Na*', strlen($private), $private); if (!class_exists('Crypt_AES')) { include_once 'Crypt/AES.php'; } $sequence = 0; $symkey = ''; while (strlen($symkey) < 32) { $temp = pack('Na*', $sequence++, $this->password); $symkey.= pack('H*', sha1($temp)); } $symkey = substr($symkey, 0, 32); $crypto = new Crypt_AES(); $crypto->setKey($symkey); $crypto->disablePadding(); $private = $crypto->encrypt($private); $hashkey = 'putty-private-key-file-mac-key' . $this->password; } $private = base64_encode($private); $key.= 'Private-Lines: ' . ((strlen($private) + 63) >> 6) . "\r\n"; $key.= chunk_split($private, 64); if (!class_exists('Crypt_Hash')) { include_once 'Crypt/Hash.php'; } $hash = new Crypt_Hash('sha1'); $hash->setKey(pack('H*', sha1($hashkey))); $key.= 'Private-MAC: ' . bin2hex($hash->hash($source)) . "\r\n"; return $key; default: $components = array(); foreach ($raw as $name => $value) { $components[$name] = pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($value)), $value); } $RSAPrivateKey = implode('', $components); if ($num_primes > 2) { $OtherPrimeInfos = ''; for ($i = 3; $i <= $num_primes; $i++) { $OtherPrimeInfo = pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($primes[$i]->toBytes(true))), $primes[$i]->toBytes(true)); $OtherPrimeInfo.= pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($exponents[$i]->toBytes(true))), $exponents[$i]->toBytes(true)); $OtherPrimeInfo.= pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($coefficients[$i]->toBytes(true))), $coefficients[$i]->toBytes(true)); $OtherPrimeInfos.= pack('Ca*a*', CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($OtherPrimeInfo)), $OtherPrimeInfo); } $RSAPrivateKey.= pack('Ca*a*', CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($OtherPrimeInfos)), $OtherPrimeInfos); } $RSAPrivateKey = pack('Ca*a*', CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey); if ($this->privateKeyFormat == CRYPT_RSA_PRIVATE_FORMAT_PKCS8) { $rsaOID = pack('H*', '300d06092a864886f70d0101010500'); $RSAPrivateKey = pack( 'Ca*a*Ca*a*', CRYPT_RSA_ASN1_INTEGER, "\01\00", $rsaOID, 4, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey ); $RSAPrivateKey = pack('Ca*a*', CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey); if (!empty($this->password) || is_string($this->password)) { $salt = crypt_random_string(8); $iterationCount = 2048; if (!class_exists('Crypt_DES')) { include_once 'Crypt/DES.php'; } $crypto = new Crypt_DES(); $crypto->setPassword($this->password, 'pbkdf1', 'md5', $salt, $iterationCount); $RSAPrivateKey = $crypto->encrypt($RSAPrivateKey); $parameters = pack( 'Ca*a*Ca*N', CRYPT_RSA_ASN1_OCTETSTRING, $this->_encodeLength(strlen($salt)), $salt, CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(4), $iterationCount ); $pbeWithMD5AndDES_CBC = "\x2a\x86\x48\x86\xf7\x0d\x01\x05\x03"; $encryptionAlgorithm = pack( 'Ca*a*Ca*a*', CRYPT_RSA_ASN1_OBJECT, $this->_encodeLength(strlen($pbeWithMD5AndDES_CBC)), $pbeWithMD5AndDES_CBC, CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($parameters)), $parameters ); $RSAPrivateKey = pack( 'Ca*a*Ca*a*', CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($encryptionAlgorithm)), $encryptionAlgorithm, CRYPT_RSA_ASN1_OCTETSTRING, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey ); $RSAPrivateKey = pack('Ca*a*', CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey); $RSAPrivateKey = "-----BEGIN ENCRYPTED PRIVATE KEY-----\r\n" . chunk_split(base64_encode($RSAPrivateKey), 64) . '-----END ENCRYPTED PRIVATE KEY-----'; } else { $RSAPrivateKey = "-----BEGIN PRIVATE KEY-----\r\n" . chunk_split(base64_encode($RSAPrivateKey), 64) . '-----END PRIVATE KEY-----'; } return $RSAPrivateKey; } if (!empty($this->password) || is_string($this->password)) { $iv = crypt_random_string(8); $symkey = pack('H*', md5($this->password . $iv)); $symkey.= substr(pack('H*', md5($symkey . $this->password . $iv)), 0, 8); if (!class_exists('Crypt_TripleDES')) { include_once 'Crypt/TripleDES.php'; } $des = new Crypt_TripleDES(); $des->setKey($symkey); $des->setIV($iv); $iv = strtoupper(bin2hex($iv)); $RSAPrivateKey = "-----BEGIN RSA PRIVATE KEY-----\r\n" . "Proc-Type: 4,ENCRYPTED\r\n" . "DEK-Info: DES-EDE3-CBC,$iv\r\n" . "\r\n" . chunk_split(base64_encode($des->encrypt($RSAPrivateKey)), 64) . '-----END RSA PRIVATE KEY-----'; } else { $RSAPrivateKey = "-----BEGIN RSA PRIVATE KEY-----\r\n" . chunk_split(base64_encode($RSAPrivateKey), 64) . '-----END RSA PRIVATE KEY-----'; } return $RSAPrivateKey; } } function _convertPublicKey($n, $e) { $signed = $this->publicKeyFormat != CRYPT_RSA_PUBLIC_FORMAT_XML; $modulus = $n->toBytes($signed); $publicExponent = $e->toBytes($signed); switch ($this->publicKeyFormat) { case CRYPT_RSA_PUBLIC_FORMAT_RAW: return array('e' => $e->copy(), 'n' => $n->copy()); case CRYPT_RSA_PUBLIC_FORMAT_XML: return "<RSAKeyValue>\r\n" . '  <Modulus>' . base64_encode($modulus) . "</Modulus>\r\n" . '  <Exponent>' . base64_encode($publicExponent) . "</Exponent>\r\n" . '</RSAKeyValue>'; break; case CRYPT_RSA_PUBLIC_FORMAT_OPENSSH: $RSAPublicKey = pack('Na*Na*Na*', strlen('ssh-rsa'), 'ssh-rsa', strlen($publicExponent), $publicExponent, strlen($modulus), $modulus); $RSAPublicKey = 'ssh-rsa ' . base64_encode($RSAPublicKey) . ' ' . $this->comment; return $RSAPublicKey; default: $components = array( 'modulus' => pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($modulus)), $modulus), 'publicExponent' => pack('Ca*a*', CRYPT_RSA_ASN1_INTEGER, $this->_encodeLength(strlen($publicExponent)), $publicExponent) ); $RSAPublicKey = pack( 'Ca*a*a*', CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($components['modulus']) + strlen($components['publicExponent'])), $components['modulus'], $components['publicExponent'] ); if ($this->publicKeyFormat == CRYPT_RSA_PUBLIC_FORMAT_PKCS1_RAW) { $RSAPublicKey = "-----BEGIN RSA PUBLIC KEY-----\r\n" . chunk_split(base64_encode($RSAPublicKey), 64) . '-----END RSA PUBLIC KEY-----'; } else { $rsaOID = pack('H*', '300d06092a864886f70d0101010500'); $RSAPublicKey = chr(0) . $RSAPublicKey; $RSAPublicKey = chr(3) . $this->_encodeLength(strlen($RSAPublicKey)) . $RSAPublicKey; $RSAPublicKey = pack( 'Ca*a*', CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($rsaOID . $RSAPublicKey)), $rsaOID . $RSAPublicKey ); $RSAPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" . chunk_split(base64_encode($RSAPublicKey), 64) . '-----END PUBLIC KEY-----'; } return $RSAPublicKey; } } function _parseKey($key, $type) { if ($type != CRYPT_RSA_PUBLIC_FORMAT_RAW && !is_string($key)) { return false; } switch ($type) { case CRYPT_RSA_PUBLIC_FORMAT_RAW: if (!is_array($key)) { return false; } $components = array(); switch (true) { case isset($key['e']): $components['publicExponent'] = $key['e']->copy(); break; case isset($key['exponent']): $components['publicExponent'] = $key['exponent']->copy(); break; case isset($key['publicExponent']): $components['publicExponent'] = $key['publicExponent']->copy(); break; case isset($key[0]): $components['publicExponent'] = $key[0]->copy(); } switch (true) { case isset($key['n']): $components['modulus'] = $key['n']->copy(); break; case isset($key['modulo']): $components['modulus'] = $key['modulo']->copy(); break; case isset($key['modulus']): $components['modulus'] = $key['modulus']->copy(); break; case isset($key[1]): $components['modulus'] = $key[1]->copy(); } return isset($components['modulus']) && isset($components['publicExponent']) ? $components : false; case CRYPT_RSA_PRIVATE_FORMAT_PKCS1: case CRYPT_RSA_PRIVATE_FORMAT_PKCS8: case CRYPT_RSA_PUBLIC_FORMAT_PKCS1: if (preg_match('#DEK-Info: (.+),(.+)#', $key, $matches)) { $iv = pack('H*', trim($matches[2])); $symkey = pack('H*', md5($this->password . substr($iv, 0, 8))); $symkey.= pack('H*', md5($symkey . $this->password . substr($iv, 0, 8))); $key = preg_replace('#^(?:Proc-Type|DEK-Info): .*#m', '', $key); $ciphertext = $this->_extractBER($key); if ($ciphertext === false) { $ciphertext = $key; } switch ($matches[1]) { case 'AES-256-CBC': if (!class_exists('Crypt_AES')) { include_once 'Crypt/AES.php'; } $crypto = new Crypt_AES(); break; case 'AES-128-CBC': if (!class_exists('Crypt_AES')) { include_once 'Crypt/AES.php'; } $symkey = substr($symkey, 0, 16); $crypto = new Crypt_AES(); break; case 'DES-EDE3-CFB': if (!class_exists('Crypt_TripleDES')) { include_once 'Crypt/TripleDES.php'; } $crypto = new Crypt_TripleDES(CRYPT_DES_MODE_CFB); break; case 'DES-EDE3-CBC': if (!class_exists('Crypt_TripleDES')) { include_once 'Crypt/TripleDES.php'; } $symkey = substr($symkey, 0, 24); $crypto = new Crypt_TripleDES(); break; case 'DES-CBC': if (!class_exists('Crypt_DES')) { include_once 'Crypt/DES.php'; } $crypto = new Crypt_DES(); break; default: return false; } $crypto->setKey($symkey); $crypto->setIV($iv); $decoded = $crypto->decrypt($ciphertext); } else { $decoded = $this->_extractBER($key); } if ($decoded !== false) { $key = $decoded; } $components = array(); if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_SEQUENCE) { return false; } if ($this->_decodeLength($key) != strlen($key)) { return false; } $tag = ord($this->_string_shift($key)); if ($tag == CRYPT_RSA_ASN1_INTEGER && substr($key, 0, 3) == "\x01\x00\x30") { $this->_string_shift($key, 3); $tag = CRYPT_RSA_ASN1_SEQUENCE; } if ($tag == CRYPT_RSA_ASN1_SEQUENCE) { $temp = $this->_string_shift($key, $this->_decodeLength($key)); if (ord($this->_string_shift($temp)) != CRYPT_RSA_ASN1_OBJECT) { return false; } $length = $this->_decodeLength($temp); switch ($this->_string_shift($temp, $length)) { case "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01": break; case "\x2a\x86\x48\x86\xf7\x0d\x01\x05\x03": if (ord($this->_string_shift($temp)) != CRYPT_RSA_ASN1_SEQUENCE) { return false; } if ($this->_decodeLength($temp) != strlen($temp)) { return false; } $this->_string_shift($temp); $salt = $this->_string_shift($temp, $this->_decodeLength($temp)); if (ord($this->_string_shift($temp)) != CRYPT_RSA_ASN1_INTEGER) { return false; } $this->_decodeLength($temp); list(, $iterationCount) = unpack('N', str_pad($temp, 4, chr(0), STR_PAD_LEFT)); $this->_string_shift($key); $length = $this->_decodeLength($key); if (strlen($key) != $length) { return false; } if (!class_exists('Crypt_DES')) { include_once 'Crypt/DES.php'; } $crypto = new Crypt_DES(); $crypto->setPassword($this->password, 'pbkdf1', 'md5', $salt, $iterationCount); $key = $crypto->decrypt($key); if ($key === false) { return false; } return $this->_parseKey($key, CRYPT_RSA_PRIVATE_FORMAT_PKCS1); default: return false; } $tag = ord($this->_string_shift($key)); $this->_decodeLength($key); if ($tag == CRYPT_RSA_ASN1_BITSTRING) { $this->_string_shift($key); } if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_SEQUENCE) { return false; } if ($this->_decodeLength($key) != strlen($key)) { return false; } $tag = ord($this->_string_shift($key)); } if ($tag != CRYPT_RSA_ASN1_INTEGER) { return false; } $length = $this->_decodeLength($key); $temp = $this->_string_shift($key, $length); if (strlen($temp) != 1 || ord($temp) > 2) { $components['modulus'] = new Math_BigInteger($temp, 256); $this->_string_shift($key); $length = $this->_decodeLength($key); $components[$type == CRYPT_RSA_PUBLIC_FORMAT_PKCS1 ? 'publicExponent' : 'privateExponent'] = new Math_BigInteger($this->_string_shift($key, $length), 256); return $components; } if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_INTEGER) { return false; } $length = $this->_decodeLength($key); $components['modulus'] = new Math_BigInteger($this->_string_shift($key, $length), 256); $this->_string_shift($key); $length = $this->_decodeLength($key); $components['publicExponent'] = new Math_BigInteger($this->_string_shift($key, $length), 256); $this->_string_shift($key); $length = $this->_decodeLength($key); $components['privateExponent'] = new Math_BigInteger($this->_string_shift($key, $length), 256); $this->_string_shift($key); $length = $this->_decodeLength($key); $components['primes'] = array(1 => new Math_BigInteger($this->_string_shift($key, $length), 256)); $this->_string_shift($key); $length = $this->_decodeLength($key); $components['primes'][] = new Math_BigInteger($this->_string_shift($key, $length), 256); $this->_string_shift($key); $length = $this->_decodeLength($key); $components['exponents'] = array(1 => new Math_BigInteger($this->_string_shift($key, $length), 256)); $this->_string_shift($key); $length = $this->_decodeLength($key); $components['exponents'][] = new Math_BigInteger($this->_string_shift($key, $length), 256); $this->_string_shift($key); $length = $this->_decodeLength($key); $components['coefficients'] = array(2 => new Math_BigInteger($this->_string_shift($key, $length), 256)); if (!empty($key)) { if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_SEQUENCE) { return false; } $this->_decodeLength($key); while (!empty($key)) { if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_SEQUENCE) { return false; } $this->_decodeLength($key); $key = substr($key, 1); $length = $this->_decodeLength($key); $components['primes'][] = new Math_BigInteger($this->_string_shift($key, $length), 256); $this->_string_shift($key); $length = $this->_decodeLength($key); $components['exponents'][] = new Math_BigInteger($this->_string_shift($key, $length), 256); $this->_string_shift($key); $length = $this->_decodeLength($key); $components['coefficients'][] = new Math_BigInteger($this->_string_shift($key, $length), 256); } } return $components; case CRYPT_RSA_PUBLIC_FORMAT_OPENSSH: $parts = explode(' ', $key, 3); $key = isset($parts[1]) ? base64_decode($parts[1]) : false; if ($key === false) { return false; } $comment = isset($parts[2]) ? $parts[2] : false; $cleanup = substr($key, 0, 11) == "\0\0\0\7ssh-rsa"; if (strlen($key) <= 4) { return false; } extract(unpack('Nlength', $this->_string_shift($key, 4))); $publicExponent = new Math_BigInteger($this->_string_shift($key, $length), -256); if (strlen($key) <= 4) { return false; } extract(unpack('Nlength', $this->_string_shift($key, 4))); $modulus = new Math_BigInteger($this->_string_shift($key, $length), -256); if ($cleanup && strlen($key)) { if (strlen($key) <= 4) { return false; } extract(unpack('Nlength', $this->_string_shift($key, 4))); $realModulus = new Math_BigInteger($this->_string_shift($key, $length), -256); return strlen($key) ? false : array( 'modulus' => $realModulus, 'publicExponent' => $modulus, 'comment' => $comment ); } else { return strlen($key) ? false : array( 'modulus' => $modulus, 'publicExponent' => $publicExponent, 'comment' => $comment ); } case CRYPT_RSA_PRIVATE_FORMAT_XML: case CRYPT_RSA_PUBLIC_FORMAT_XML: $this->components = array(); $xml = xml_parser_create('UTF-8'); xml_set_object($xml, $this); xml_set_element_handler($xml, '_start_element_handler', '_stop_element_handler'); xml_set_character_data_handler($xml, '_data_handler'); if (!xml_parse($xml, '<xml>' . $key . '</xml>')) { return false; } return isset($this->components['modulus']) && isset($this->components['publicExponent']) ? $this->components : false; case CRYPT_RSA_PRIVATE_FORMAT_PUTTY: $components = array(); $key = preg_split('#\r\n|\r|\n#', $key); $type = trim(preg_replace('#PuTTY-User-Key-File-2: (.+)#', '$1', $key[0])); if ($type != 'ssh-rsa') { return false; } $encryption = trim(preg_replace('#Encryption: (.+)#', '$1', $key[1])); $comment = trim(preg_replace('#Comment: (.+)#', '$1', $key[2])); $publicLength = trim(preg_replace('#Public-Lines: (\d+)#', '$1', $key[3])); $public = base64_decode(implode('', array_map('trim', array_slice($key, 4, $publicLength)))); $public = substr($public, 11); extract(unpack('Nlength', $this->_string_shift($public, 4))); $components['publicExponent'] = new Math_BigInteger($this->_string_shift($public, $length), -256); extract(unpack('Nlength', $this->_string_shift($public, 4))); $components['modulus'] = new Math_BigInteger($this->_string_shift($public, $length), -256); $privateLength = trim(preg_replace('#Private-Lines: (\d+)#', '$1', $key[$publicLength + 4])); $private = base64_decode(implode('', array_map('trim', array_slice($key, $publicLength + 5, $privateLength)))); switch ($encryption) { case 'aes256-cbc': if (!class_exists('Crypt_AES')) { include_once 'Crypt/AES.php'; } $symkey = ''; $sequence = 0; while (strlen($symkey) < 32) { $temp = pack('Na*', $sequence++, $this->password); $symkey.= pack('H*', sha1($temp)); } $symkey = substr($symkey, 0, 32); $crypto = new Crypt_AES(); } if ($encryption != 'none') { $crypto->setKey($symkey); $crypto->disablePadding(); $private = $crypto->decrypt($private); if ($private === false) { return false; } } extract(unpack('Nlength', $this->_string_shift($private, 4))); if (strlen($private) < $length) { return false; } $components['privateExponent'] = new Math_BigInteger($this->_string_shift($private, $length), -256); extract(unpack('Nlength', $this->_string_shift($private, 4))); if (strlen($private) < $length) { return false; } $components['primes'] = array(1 => new Math_BigInteger($this->_string_shift($private, $length), -256)); extract(unpack('Nlength', $this->_string_shift($private, 4))); if (strlen($private) < $length) { return false; } $components['primes'][] = new Math_BigInteger($this->_string_shift($private, $length), -256); $temp = $components['primes'][1]->subtract($this->one); $components['exponents'] = array(1 => $components['publicExponent']->modInverse($temp)); $temp = $components['primes'][2]->subtract($this->one); $components['exponents'][] = $components['publicExponent']->modInverse($temp); extract(unpack('Nlength', $this->_string_shift($private, 4))); if (strlen($private) < $length) { return false; } $components['coefficients'] = array(2 => new Math_BigInteger($this->_string_shift($private, $length), -256)); return $components; } } function getSize() { return !isset($this->modulus) ? 0 : strlen($this->modulus->toBits()); } function _start_element_handler($parser, $name, $attribs) { switch ($name) { case 'MODULUS': $this->current = &$this->components['modulus']; break; case 'EXPONENT': $this->current = &$this->components['publicExponent']; break; case 'P': $this->current = &$this->components['primes'][1]; break; case 'Q': $this->current = &$this->components['primes'][2]; break; case 'DP': $this->current = &$this->components['exponents'][1]; break; case 'DQ': $this->current = &$this->components['exponents'][2]; break; case 'INVERSEQ': $this->current = &$this->components['coefficients'][2]; break; case 'D': $this->current = &$this->components['privateExponent']; } $this->current = ''; } function _stop_element_handler($parser, $name) { if (isset($this->current)) { $this->current = new Math_BigInteger(base64_decode($this->current), 256); unset($this->current); } } function _data_handler($parser, $data) { if (!isset($this->current) || is_object($this->current)) { return; } $this->current.= trim($data); } function loadKey($key, $type = false) { if (is_object($key) && strtolower(get_class($key)) == 'crypt_rsa') { $this->privateKeyFormat = $key->privateKeyFormat; $this->publicKeyFormat = $key->publicKeyFormat; $this->k = $key->k; $this->hLen = $key->hLen; $this->sLen = $key->sLen; $this->mgfHLen = $key->mgfHLen; $this->encryptionMode = $key->encryptionMode; $this->signatureMode = $key->signatureMode; $this->password = $key->password; $this->configFile = $key->configFile; $this->comment = $key->comment; if (is_object($key->hash)) { $this->hash = new Crypt_Hash($key->hash->getHash()); } if (is_object($key->mgfHash)) { $this->mgfHash = new Crypt_Hash($key->mgfHash->getHash()); } if (is_object($key->modulus)) { $this->modulus = $key->modulus->copy(); } if (is_object($key->exponent)) { $this->exponent = $key->exponent->copy(); } if (is_object($key->publicExponent)) { $this->publicExponent = $key->publicExponent->copy(); } $this->primes = array(); $this->exponents = array(); $this->coefficients = array(); foreach ($this->primes as $prime) { $this->primes[] = $prime->copy(); } foreach ($this->exponents as $exponent) { $this->exponents[] = $exponent->copy(); } foreach ($this->coefficients as $coefficient) { $this->coefficients[] = $coefficient->copy(); } return true; } if ($type === false) { $types = array( CRYPT_RSA_PUBLIC_FORMAT_RAW, CRYPT_RSA_PRIVATE_FORMAT_PKCS1, CRYPT_RSA_PRIVATE_FORMAT_XML, CRYPT_RSA_PRIVATE_FORMAT_PUTTY, CRYPT_RSA_PUBLIC_FORMAT_OPENSSH ); foreach ($types as $type) { $components = $this->_parseKey($key, $type); if ($components !== false) { break; } } } else { $components = $this->_parseKey($key, $type); } if ($components === false) { return false; } if (isset($components['comment']) && $components['comment'] !== false) { $this->comment = $components['comment']; } $this->modulus = $components['modulus']; $this->k = strlen($this->modulus->toBytes()); $this->exponent = isset($components['privateExponent']) ? $components['privateExponent'] : $components['publicExponent']; if (isset($components['primes'])) { $this->primes = $components['primes']; $this->exponents = $components['exponents']; $this->coefficients = $components['coefficients']; $this->publicExponent = $components['publicExponent']; } else { $this->primes = array(); $this->exponents = array(); $this->coefficients = array(); $this->publicExponent = false; } switch ($type) { case CRYPT_RSA_PUBLIC_FORMAT_OPENSSH: case CRYPT_RSA_PUBLIC_FORMAT_RAW: $this->setPublicKey(); break; case CRYPT_RSA_PRIVATE_FORMAT_PKCS1: switch (true) { case strpos($key, '-BEGIN PUBLIC KEY-') !== false: case strpos($key, '-BEGIN RSA PUBLIC KEY-') !== false: $this->setPublicKey(); } } return true; } function setPassword($password = false) { $this->password = $password; } function setPublicKey($key = false, $type = false) { if (!empty($this->publicExponent)) { return false; } if ($key === false && !empty($this->modulus)) { $this->publicExponent = $this->exponent; return true; } if ($type === false) { $types = array( CRYPT_RSA_PUBLIC_FORMAT_RAW, CRYPT_RSA_PUBLIC_FORMAT_PKCS1, CRYPT_RSA_PUBLIC_FORMAT_XML, CRYPT_RSA_PUBLIC_FORMAT_OPENSSH ); foreach ($types as $type) { $components = $this->_parseKey($key, $type); if ($components !== false) { break; } } } else { $components = $this->_parseKey($key, $type); } if ($components === false) { return false; } if (empty($this->modulus) || !$this->modulus->equals($components['modulus'])) { $this->modulus = $components['modulus']; $this->exponent = $this->publicExponent = $components['publicExponent']; return true; } $this->publicExponent = $components['publicExponent']; return true; } function setPrivateKey($key = false, $type = false) { if ($key === false && !empty($this->publicExponent)) { $this->publicExponent = false; return true; } $rsa = new Crypt_RSA(); if (!$rsa->loadKey($key, $type)) { return false; } $rsa->publicExponent = false; $this->loadKey($rsa); return true; } function getPublicKey($type = CRYPT_RSA_PUBLIC_FORMAT_PKCS8) { if (empty($this->modulus) || empty($this->publicExponent)) { return false; } $oldFormat = $this->publicKeyFormat; $this->publicKeyFormat = $type; $temp = $this->_convertPublicKey($this->modulus, $this->publicExponent); $this->publicKeyFormat = $oldFormat; return $temp; } function getPublicKeyFingerprint($algorithm = 'md5') { if (empty($this->modulus) || empty($this->publicExponent)) { return false; } $modulus = $this->modulus->toBytes(true); $publicExponent = $this->publicExponent->toBytes(true); $RSAPublicKey = pack('Na*Na*Na*', strlen('ssh-rsa'), 'ssh-rsa', strlen($publicExponent), $publicExponent, strlen($modulus), $modulus); switch ($algorithm) { case 'sha256': $hash = new Crypt_Hash('sha256'); $base = base64_encode($hash->hash($RSAPublicKey)); return substr($base, 0, strlen($base) - 1); case 'md5': return substr(chunk_split(md5($RSAPublicKey), 2, ':'), 0, -1); default: return false; } } function getPrivateKey($type = CRYPT_RSA_PUBLIC_FORMAT_PKCS1) { if (empty($this->primes)) { return false; } $oldFormat = $this->privateKeyFormat; $this->privateKeyFormat = $type; $temp = $this->_convertPrivateKey($this->modulus, $this->publicExponent, $this->exponent, $this->primes, $this->exponents, $this->coefficients); $this->privateKeyFormat = $oldFormat; return $temp; } function _getPrivatePublicKey($mode = CRYPT_RSA_PUBLIC_FORMAT_PKCS8) { if (empty($this->modulus) || empty($this->exponent)) { return false; } $oldFormat = $this->publicKeyFormat; $this->publicKeyFormat = $mode; $temp = $this->_convertPublicKey($this->modulus, $this->exponent); $this->publicKeyFormat = $oldFormat; return $temp; } function __toString() { $key = $this->getPrivateKey($this->privateKeyFormat); if ($key !== false) { return $key; } $key = $this->_getPrivatePublicKey($this->publicKeyFormat); return $key !== false ? $key : ''; } function __clone() { $key = new Crypt_RSA(); $key->loadKey($this); return $key; } function _generateMinMax($bits) { $bytes = $bits >> 3; $min = str_repeat(chr(0), $bytes); $max = str_repeat(chr(0xFF), $bytes); $msb = $bits & 7; if ($msb) { $min = chr(1 << ($msb - 1)) . $min; $max = chr((1 << $msb) - 1) . $max; } else { $min[0] = chr(0x80); } return array( 'min' => new Math_BigInteger($min, 256), 'max' => new Math_BigInteger($max, 256) ); } function _decodeLength(&$string) { $length = ord($this->_string_shift($string)); if ($length & 0x80) { $length&= 0x7F; $temp = $this->_string_shift($string, $length); list(, $length) = unpack('N', substr(str_pad($temp, 4, chr(0), STR_PAD_LEFT), -4)); } return $length; } function _encodeLength($length) { if ($length <= 0x7F) { return chr($length); } $temp = ltrim(pack('N', $length), chr(0)); return pack('Ca*', 0x80 | strlen($temp), $temp); } function _string_shift(&$string, $index = 1) { $substr = substr($string, 0, $index); $string = substr($string, $index); return $substr; } function setPrivateKeyFormat($format) { $this->privateKeyFormat = $format; } function setPublicKeyFormat($format) { $this->publicKeyFormat = $format; } function setHash($hash) { switch ($hash) { case 'md2': case 'md5': case 'sha1': case 'sha256': case 'sha384': case 'sha512': $this->hash = new Crypt_Hash($hash); $this->hashName = $hash; break; default: $this->hash = new Crypt_Hash('sha1'); $this->hashName = 'sha1'; } $this->hLen = $this->hash->getLength(); } function setMGFHash($hash) { switch ($hash) { case 'md2': case 'md5': case 'sha1': case 'sha256': case 'sha384': case 'sha512': $this->mgfHash = new Crypt_Hash($hash); break; default: $this->mgfHash = new Crypt_Hash('sha1'); } $this->mgfHLen = $this->mgfHash->getLength(); } function setSaltLength($sLen) { $this->sLen = $sLen; } function _i2osp($x, $xLen) { $x = $x->toBytes(); if (strlen($x) > $xLen) { user_error('Integer too large'); return false; } return str_pad($x, $xLen, chr(0), STR_PAD_LEFT); } function _os2ip($x) { return new Math_BigInteger($x, 256); } function _exponentiate($x) { switch (true) { case empty($this->primes): case $this->primes[1]->equals($this->zero): case empty($this->coefficients): case $this->coefficients[2]->equals($this->zero): case empty($this->exponents): case $this->exponents[1]->equals($this->zero): return $x->modPow($this->exponent, $this->modulus); } $num_primes = count($this->primes); if (defined('CRYPT_RSA_DISABLE_BLINDING')) { $m_i = array( 1 => $x->modPow($this->exponents[1], $this->primes[1]), 2 => $x->modPow($this->exponents[2], $this->primes[2]) ); $h = $m_i[1]->subtract($m_i[2]); $h = $h->multiply($this->coefficients[2]); list(, $h) = $h->divide($this->primes[1]); $m = $m_i[2]->add($h->multiply($this->primes[2])); $r = $this->primes[1]; for ($i = 3; $i <= $num_primes; $i++) { $m_i = $x->modPow($this->exponents[$i], $this->primes[$i]); $r = $r->multiply($this->primes[$i - 1]); $h = $m_i->subtract($m); $h = $h->multiply($this->coefficients[$i]); list(, $h) = $h->divide($this->primes[$i]); $m = $m->add($r->multiply($h)); } } else { $smallest = $this->primes[1]; for ($i = 2; $i <= $num_primes; $i++) { if ($smallest->compare($this->primes[$i]) > 0) { $smallest = $this->primes[$i]; } } $one = new Math_BigInteger(1); $r = $one->random($one, $smallest->subtract($one)); $m_i = array( 1 => $this->_blind($x, $r, 1), 2 => $this->_blind($x, $r, 2) ); $h = $m_i[1]->subtract($m_i[2]); $h = $h->multiply($this->coefficients[2]); list(, $h) = $h->divide($this->primes[1]); $m = $m_i[2]->add($h->multiply($this->primes[2])); $r = $this->primes[1]; for ($i = 3; $i <= $num_primes; $i++) { $m_i = $this->_blind($x, $r, $i); $r = $r->multiply($this->primes[$i - 1]); $h = $m_i->subtract($m); $h = $h->multiply($this->coefficients[$i]); list(, $h) = $h->divide($this->primes[$i]); $m = $m->add($r->multiply($h)); } } return $m; } function _blind($x, $r, $i) { $x = $x->multiply($r->modPow($this->publicExponent, $this->primes[$i])); $x = $x->modPow($this->exponents[$i], $this->primes[$i]); $r = $r->modInverse($this->primes[$i]); $x = $x->multiply($r); list(, $x) = $x->divide($this->primes[$i]); return $x; } function _equals($x, $y) { if (strlen($x) != strlen($y)) { return false; } $result = 0; for ($i = 0; $i < strlen($x); $i++) { $result |= ord($x[$i]) ^ ord($y[$i]); } return $result == 0; } function _rsaep($m) { if ($m->compare($this->zero) < 0 || $m->compare($this->modulus) > 0) { user_error('Message representative out of range'); return false; } return $this->_exponentiate($m); } function _rsadp($c) { if ($c->compare($this->zero) < 0 || $c->compare($this->modulus) > 0) { user_error('Ciphertext representative out of range'); return false; } return $this->_exponentiate($c); } function _rsasp1($m) { if ($m->compare($this->zero) < 0 || $m->compare($this->modulus) > 0) { user_error('Message representative out of range'); return false; } return $this->_exponentiate($m); } function _rsavp1($s) { if ($s->compare($this->zero) < 0 || $s->compare($this->modulus) > 0) { user_error('Signature representative out of range'); return false; } return $this->_exponentiate($s); } function _mgf1($mgfSeed, $maskLen) { $t = ''; $count = ceil($maskLen / $this->mgfHLen); for ($i = 0; $i < $count; $i++) { $c = pack('N', $i); $t.= $this->mgfHash->hash($mgfSeed . $c); } return substr($t, 0, $maskLen); } function _rsaes_oaep_encrypt($m, $l = '') { $mLen = strlen($m); if ($mLen > $this->k - 2 * $this->hLen - 2) { user_error('Message too long'); return false; } $lHash = $this->hash->hash($l); $ps = str_repeat(chr(0), $this->k - $mLen - 2 * $this->hLen - 2); $db = $lHash . $ps . chr(1) . $m; $seed = crypt_random_string($this->hLen); $dbMask = $this->_mgf1($seed, $this->k - $this->hLen - 1); $maskedDB = $db ^ $dbMask; $seedMask = $this->_mgf1($maskedDB, $this->hLen); $maskedSeed = $seed ^ $seedMask; $em = chr(0) . $maskedSeed . $maskedDB; $m = $this->_os2ip($em); $c = $this->_rsaep($m); $c = $this->_i2osp($c, $this->k); return $c; } function _rsaes_oaep_decrypt($c, $l = '') { if (strlen($c) != $this->k || $this->k < 2 * $this->hLen + 2) { user_error('Decryption error'); return false; } $c = $this->_os2ip($c); $m = $this->_rsadp($c); if ($m === false) { user_error('Decryption error'); return false; } $em = $this->_i2osp($m, $this->k); $lHash = $this->hash->hash($l); $y = ord($em[0]); $maskedSeed = substr($em, 1, $this->hLen); $maskedDB = substr($em, $this->hLen + 1); $seedMask = $this->_mgf1($maskedDB, $this->hLen); $seed = $maskedSeed ^ $seedMask; $dbMask = $this->_mgf1($seed, $this->k - $this->hLen - 1); $db = $maskedDB ^ $dbMask; $lHash2 = substr($db, 0, $this->hLen); $m = substr($db, $this->hLen); if ($lHash != $lHash2) { user_error('Decryption error'); return false; } $m = ltrim($m, chr(0)); if (ord($m[0]) != 1) { user_error('Decryption error'); return false; } return substr($m, 1); } function _raw_encrypt($m) { $temp = $this->_os2ip($m); $temp = $this->_rsaep($temp); return $this->_i2osp($temp, $this->k); } function _rsaes_pkcs1_v1_5_encrypt($m) { $mLen = strlen($m); if ($mLen > $this->k - 11) { user_error('Message too long'); return false; } $psLen = $this->k - $mLen - 3; $ps = ''; while (strlen($ps) != $psLen) { $temp = crypt_random_string($psLen - strlen($ps)); $temp = str_replace("\x00", '', $temp); $ps.= $temp; } $type = 2; if (defined('CRYPT_RSA_PKCS15_COMPAT') && (!isset($this->publicExponent) || $this->exponent !== $this->publicExponent)) { $type = 1; $ps = str_repeat("\xFF", $psLen); } $em = chr(0) . chr($type) . $ps . chr(0) . $m; $m = $this->_os2ip($em); $c = $this->_rsaep($m); $c = $this->_i2osp($c, $this->k); return $c; } function _rsaes_pkcs1_v1_5_decrypt($c) { if (strlen($c) != $this->k) { user_error('Decryption error'); return false; } $c = $this->_os2ip($c); $m = $this->_rsadp($c); if ($m === false) { user_error('Decryption error'); return false; } $em = $this->_i2osp($m, $this->k); if (ord($em[0]) != 0 || ord($em[1]) > 2) { user_error('Decryption error'); return false; } $ps = substr($em, 2, strpos($em, chr(0), 2) - 2); $m = substr($em, strlen($ps) + 3); if (strlen($ps) < 8) { user_error('Decryption error'); return false; } return $m; } function _emsa_pss_encode($m, $emBits) { $emLen = ($emBits + 1) >> 3; $sLen = $this->sLen !== null ? $this->sLen : $this->hLen; $mHash = $this->hash->hash($m); if ($emLen < $this->hLen + $sLen + 2) { user_error('Encoding error'); return false; } $salt = crypt_random_string($sLen); $m2 = "\0\0\0\0\0\0\0\0" . $mHash . $salt; $h = $this->hash->hash($m2); $ps = str_repeat(chr(0), $emLen - $sLen - $this->hLen - 2); $db = $ps . chr(1) . $salt; $dbMask = $this->_mgf1($h, $emLen - $this->hLen - 1); $maskedDB = $db ^ $dbMask; $maskedDB[0] = ~chr(0xFF << ($emBits & 7)) & $maskedDB[0]; $em = $maskedDB . $h . chr(0xBC); return $em; } function _emsa_pss_verify($m, $em, $emBits) { $emLen = ($emBits + 1) >> 3; $sLen = $this->sLen !== null ? $this->sLen : $this->hLen; $mHash = $this->hash->hash($m); if ($emLen < $this->hLen + $sLen + 2) { return false; } if ($em[strlen($em) - 1] != chr(0xBC)) { return false; } $maskedDB = substr($em, 0, -$this->hLen - 1); $h = substr($em, -$this->hLen - 1, $this->hLen); $temp = chr(0xFF << ($emBits & 7)); if ((~$maskedDB[0] & $temp) != $temp) { return false; } $dbMask = $this->_mgf1($h, $emLen - $this->hLen - 1); $db = $maskedDB ^ $dbMask; $db[0] = ~chr(0xFF << ($emBits & 7)) & $db[0]; $temp = $emLen - $this->hLen - $sLen - 2; if (substr($db, 0, $temp) != str_repeat(chr(0), $temp) || ord($db[$temp]) != 1) { return false; } $salt = substr($db, $temp + 1); $m2 = "\0\0\0\0\0\0\0\0" . $mHash . $salt; $h2 = $this->hash->hash($m2); return $this->_equals($h, $h2); } function _rsassa_pss_sign($m) { $em = $this->_emsa_pss_encode($m, 8 * $this->k - 1); $m = $this->_os2ip($em); $s = $this->_rsasp1($m); $s = $this->_i2osp($s, $this->k); return $s; } function _rsassa_pss_verify($m, $s) { if (strlen($s) != $this->k) { user_error('Invalid signature'); return false; } $modBits = 8 * $this->k; $s2 = $this->_os2ip($s); $m2 = $this->_rsavp1($s2); if ($m2 === false) { user_error('Invalid signature'); return false; } $em = $this->_i2osp($m2, $modBits >> 3); if ($em === false) { user_error('Invalid signature'); return false; } return $this->_emsa_pss_verify($m, $em, $modBits - 1); } function _emsa_pkcs1_v1_5_encode($m, $emLen) { $h = $this->hash->hash($m); if ($h === false) { return false; } switch ($this->hashName) { case 'md2': $t = pack('H*', '3020300c06082a864886f70d020205000410'); break; case 'md5': $t = pack('H*', '3020300c06082a864886f70d020505000410'); break; case 'sha1': $t = pack('H*', '3021300906052b0e03021a05000414'); break; case 'sha256': $t = pack('H*', '3031300d060960864801650304020105000420'); break; case 'sha384': $t = pack('H*', '3041300d060960864801650304020205000430'); break; case 'sha512': $t = pack('H*', '3051300d060960864801650304020305000440'); } $t.= $h; $tLen = strlen($t); if ($emLen < $tLen + 11) { user_error('Intended encoded message length too short'); return false; } $ps = str_repeat(chr(0xFF), $emLen - $tLen - 3); $em = "\0\1$ps\0$t"; return $em; } function _rsassa_pkcs1_v1_5_sign($m) { $em = $this->_emsa_pkcs1_v1_5_encode($m, $this->k); if ($em === false) { user_error('RSA modulus too short'); return false; } $m = $this->_os2ip($em); $s = $this->_rsasp1($m); $s = $this->_i2osp($s, $this->k); return $s; } function _rsassa_pkcs1_v1_5_verify($m, $s) { if (strlen($s) != $this->k) { user_error('Invalid signature'); return false; } $s = $this->_os2ip($s); $m2 = $this->_rsavp1($s); if ($m2 === false) { user_error('Invalid signature'); return false; } $em = $this->_i2osp($m2, $this->k); if ($em === false) { user_error('Invalid signature'); return false; } $em2 = $this->_emsa_pkcs1_v1_5_encode($m, $this->k); if ($em2 === false) { user_error('RSA modulus too short'); return false; } return $this->_equals($em, $em2); } function setEncryptionMode($mode) { $this->encryptionMode = $mode; } function setSignatureMode($mode) { $this->signatureMode = $mode; } function setComment($comment) { $this->comment = $comment; } function getComment() { return $this->comment; } function encrypt($plaintext) { switch ($this->encryptionMode) { case CRYPT_RSA_ENCRYPTION_NONE: $plaintext = str_split($plaintext, $this->k); $ciphertext = ''; foreach ($plaintext as $m) { $ciphertext.= $this->_raw_encrypt($m); } return $ciphertext; case CRYPT_RSA_ENCRYPTION_PKCS1: $length = $this->k - 11; if ($length <= 0) { return false; } $plaintext = str_split($plaintext, $length); $ciphertext = ''; foreach ($plaintext as $m) { $ciphertext.= $this->_rsaes_pkcs1_v1_5_encrypt($m); } return $ciphertext; default: $length = $this->k - 2 * $this->hLen - 2; if ($length <= 0) { return false; } $plaintext = str_split($plaintext, $length); $ciphertext = ''; foreach ($plaintext as $m) { $ciphertext.= $this->_rsaes_oaep_encrypt($m); } return $ciphertext; } } function decrypt($ciphertext) { if ($this->k <= 0) { return false; } $ciphertext = str_split($ciphertext, $this->k); $ciphertext[count($ciphertext) - 1] = str_pad($ciphertext[count($ciphertext) - 1], $this->k, chr(0), STR_PAD_LEFT); $plaintext = ''; switch ($this->encryptionMode) { case CRYPT_RSA_ENCRYPTION_NONE: $decrypt = '_raw_encrypt'; break; case CRYPT_RSA_ENCRYPTION_PKCS1: $decrypt = '_rsaes_pkcs1_v1_5_decrypt'; break; default: $decrypt = '_rsaes_oaep_decrypt'; } foreach ($ciphertext as $c) { $temp = $this->$decrypt($c); if ($temp === false) { return false; } $plaintext.= $temp; } return $plaintext; } function sign($message) { if (empty($this->modulus) || empty($this->exponent)) { return false; } switch ($this->signatureMode) { case CRYPT_RSA_SIGNATURE_PKCS1: return $this->_rsassa_pkcs1_v1_5_sign($message); default: return $this->_rsassa_pss_sign($message); } } function verify($message, $signature) { if (empty($this->modulus) || empty($this->exponent)) { return false; } switch ($this->signatureMode) { case CRYPT_RSA_SIGNATURE_PKCS1: return $this->_rsassa_pkcs1_v1_5_verify($message, $signature); default: return $this->_rsassa_pss_verify($message, $signature); } } function _extractBER($str) { $temp = preg_replace('#.*?^-+[^-]+-+[\r\n ]*$#ms', '', $str, 1); $temp = preg_replace('#-+[^-]+-+#', '', $temp); $temp = str_replace(array("\r", "\n", ' '), '', $temp); $temp = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $temp) ? base64_decode($temp) : false; return $temp != false ? $temp : $str; } } } if (!class_exists('Crypt_Blowfish')) { if (!class_exists('Crypt_Base')) { include_once 'Base.php'; } define('CRYPT_BLOWFISH_MODE_CTR', CRYPT_MODE_CTR); define('CRYPT_BLOWFISH_MODE_ECB', CRYPT_MODE_ECB); define('CRYPT_BLOWFISH_MODE_CBC', CRYPT_MODE_CBC); define('CRYPT_BLOWFISH_MODE_CFB', CRYPT_MODE_CFB); define('CRYPT_BLOWFISH_MODE_OFB', CRYPT_MODE_OFB); class Crypt_Blowfish extends Crypt_Base { var $block_size = 8; var $const_namespace = 'BLOWFISH'; var $cipher_name_mcrypt = 'blowfish'; var $cfb_init_len = 500; var $sbox0 = array( 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a ); var $sbox1 = array( 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7 ); var $sbox2 = array( 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0 ); var $sbox3 = array( 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6 ); var $parray = array( 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b ); var $bctx; var $kl; var $key_length = 16; function setKeyLength($length) { if ($length < 32) { $this->key_length = 7; } elseif ($length > 448) { $this->key_length = 56; } else { $this->key_length = $length >> 3; } parent::setKeyLength($length); } function isValidEngine($engine) { if ($engine == CRYPT_ENGINE_OPENSSL) { if ($this->key_length < 16) { return false; } $this->cipher_name_openssl_ecb = 'bf-ecb'; $this->cipher_name_openssl = 'bf-' . $this->_openssl_translate_mode(); } return parent::isValidEngine($engine); } function _setupKey() { if (isset($this->kl['key']) && $this->key === $this->kl['key']) { return; } $this->kl = array('key' => $this->key); $this->bctx = array( 'p' => array(), 'sb' => array( $this->sbox0, $this->sbox1, $this->sbox2, $this->sbox3 ) ); $key = array_values(unpack('C*', $this->key)); $keyl = count($key); for ($j = 0, $i = 0; $i < 18; ++$i) { for ($data = 0, $k = 0; $k < 4; ++$k) { $data = ($data << 8) | $key[$j]; if (++$j >= $keyl) { $j = 0; } } $this->bctx['p'][] = $this->parray[$i] ^ $data; } $data = "\0\0\0\0\0\0\0\0"; for ($i = 0; $i < 18; $i += 2) { list($l, $r) = array_values(unpack('N*', $data = $this->_encryptBlock($data))); $this->bctx['p'][$i ] = $l; $this->bctx['p'][$i + 1] = $r; } for ($i = 0; $i < 4; ++$i) { for ($j = 0; $j < 256; $j += 2) { list($l, $r) = array_values(unpack('N*', $data = $this->_encryptBlock($data))); $this->bctx['sb'][$i][$j ] = $l; $this->bctx['sb'][$i][$j + 1] = $r; } } } function _encryptBlock($in) { $p = $this->bctx["p"]; $sb_0 = $this->bctx["sb"][0]; $sb_1 = $this->bctx["sb"][1]; $sb_2 = $this->bctx["sb"][2]; $sb_3 = $this->bctx["sb"][3]; $in = unpack("N*", $in); $l = $in[1]; $r = $in[2]; for ($i = 0; $i < 16; $i+= 2) { $l^= $p[$i]; $r^= $this->safe_intval(($this->safe_intval($sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]) ^ $sb_2[$l >> 8 & 0xff]) + $sb_3[$l & 0xff]); $r^= $p[$i + 1]; $l^= $this->safe_intval(($this->safe_intval($sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]) ^ $sb_2[$r >> 8 & 0xff]) + $sb_3[$r & 0xff]); } return pack("N*", $r ^ $p[17], $l ^ $p[16]); } function _decryptBlock($in) { $p = $this->bctx["p"]; $sb_0 = $this->bctx["sb"][0]; $sb_1 = $this->bctx["sb"][1]; $sb_2 = $this->bctx["sb"][2]; $sb_3 = $this->bctx["sb"][3]; $in = unpack("N*", $in); $l = $in[1]; $r = $in[2]; for ($i = 17; $i > 2; $i-= 2) { $l^= $p[$i]; $r^= $this->safe_intval(($this->safe_intval($sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]) ^ $sb_2[$l >> 8 & 0xff]) + $sb_3[$l & 0xff]); $r^= $p[$i - 1]; $l^= $this->safe_intval(($this->safe_intval($sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]) ^ $sb_2[$r >> 8 & 0xff]) + $sb_3[$r & 0xff]); } return pack("N*", $r ^ $p[0], $l ^ $p[1]); } function _setupInlineCrypt() { $lambda_functions =& Crypt_Blowfish::_getLambdaFunctions(); $gen_hi_opt_code = (bool)(count($lambda_functions) < 10); $code_hash = "Crypt_Blowfish, {$this->mode}"; if ($gen_hi_opt_code) { $code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key); } switch (true) { case defined('PHP_INT_SIZE') && PHP_INT_SIZE == 8: case version_compare(PHP_VERSION, '5.3.0') >= 0: case (PHP_OS & "\xDF\xDF\xDF") === 'WIN': $safeint = '%s'; break; default: $safeint = '(is_int($temp = %s) ? $temp : (fmod($temp, 0x80000000) & 0x7FFFFFFF) | '; $safeint.= '((fmod(floor($temp / 0x80000000), 2) & 1) << 31))'; } if (!isset($lambda_functions[$code_hash])) { switch (true) { case $gen_hi_opt_code: $p = $this->bctx['p']; $init_crypt = '
                        static $sb_0, $sb_1, $sb_2, $sb_3;
                        if (!$sb_0) {
                            $sb_0 = $self->bctx["sb"][0];
                            $sb_1 = $self->bctx["sb"][1];
                            $sb_2 = $self->bctx["sb"][2];
                            $sb_3 = $self->bctx["sb"][3];
                        }
                    '; break; default: $p = array(); for ($i = 0; $i < 18; ++$i) { $p[] = '$p_' . $i; } $init_crypt = '
                        list($sb_0, $sb_1, $sb_2, $sb_3) = $self->bctx["sb"];
                        list(' . implode(',', $p) . ') = $self->bctx["p"];

                    '; } $encrypt_block = '
                $in = unpack("N*", $in);
                $l = $in[1];
                $r = $in[2];
            '; for ($i = 0; $i < 16; $i+= 2) { $encrypt_block.= '
                    $l^= ' . $p[$i] . ';
                    $r^= ' . sprintf($safeint, '(' . sprintf($safeint, '$sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]') . ' ^
                          $sb_2[$l >>  8 & 0xff]) +
                          $sb_3[$l       & 0xff]') . ';

                    $r^= ' . $p[$i + 1] . ';
                    $l^= ' . sprintf($safeint, '(' . sprintf($safeint, '$sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]') . '  ^
                          $sb_2[$r >>  8 & 0xff]) +
                          $sb_3[$r       & 0xff]') . ';
                '; } $encrypt_block.= '
                $in = pack("N*",
                    $r ^ ' . $p[17] . ',
                    $l ^ ' . $p[16] . '
                );
            '; $decrypt_block = '
                $in = unpack("N*", $in);
                $l = $in[1];
                $r = $in[2];
            '; for ($i = 17; $i > 2; $i-= 2) { $decrypt_block.= '
                    $l^= ' . $p[$i] . ';
                    $r^= ' . sprintf($safeint, '(' . sprintf($safeint, '$sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]') . ' ^
                          $sb_2[$l >>  8 & 0xff]) +
                          $sb_3[$l       & 0xff]') . ';

                    $r^= ' . $p[$i - 1] . ';
                    $l^= ' . sprintf($safeint, '(' . sprintf($safeint, '$sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]') . ' ^
                          $sb_2[$r >>  8 & 0xff]) +
                          $sb_3[$r       & 0xff]') . ';
                '; } $decrypt_block.= '
                $in = pack("N*",
                    $r ^ ' . $p[0] . ',
                    $l ^ ' . $p[1] . '
                );
            '; $lambda_functions[$code_hash] = $this->_createInlineCryptFunction( array( 'init_crypt' => $init_crypt, 'init_encrypt' => '', 'init_decrypt' => '', 'encrypt_block' => $encrypt_block, 'decrypt_block' => $decrypt_block ) ); } $this->inline_crypt = $lambda_functions[$code_hash]; } function safe_intval($x) { if (is_int($x) || version_compare(PHP_VERSION, '5.3.0') >= 0 || (PHP_OS & "\xDF\xDF\xDF") === 'WIN') { return $x; } return (fmod($x, 0x80000000) & 0x7FFFFFFF) | ((fmod(floor($x / 0x80000000), 2) & 1) << 31); } } } if (!class_exists('Crypt_Twofish')) { if (!class_exists('Crypt_Base')) { include_once 'Base.php'; } define('CRYPT_TWOFISH_MODE_CTR', CRYPT_MODE_CTR); define('CRYPT_TWOFISH_MODE_ECB', CRYPT_MODE_ECB); define('CRYPT_TWOFISH_MODE_CBC', CRYPT_MODE_CBC); define('CRYPT_TWOFISH_MODE_CFB', CRYPT_MODE_CFB); define('CRYPT_TWOFISH_MODE_OFB', CRYPT_MODE_OFB); class Crypt_Twofish extends Crypt_Base { var $const_namespace = 'TWOFISH'; var $cipher_name_mcrypt = 'twofish'; var $cfb_init_len = 800; var $q0 = array( 0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76, 0x9A, 0x92, 0x80, 0x78, 0xE4, 0xDD, 0xD1, 0x38, 0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C, 0x43, 0x75, 0x37, 0x26, 0xFA, 0x13, 0x94, 0x48, 0xF2, 0xD0, 0x8B, 0x30, 0x84, 0x54, 0xDF, 0x23, 0x19, 0x5B, 0x3D, 0x59, 0xF3, 0xAE, 0xA2, 0x82, 0x63, 0x01, 0x83, 0x2E, 0xD9, 0x51, 0x9B, 0x7C, 0xA6, 0xEB, 0xA5, 0xBE, 0x16, 0x0C, 0xE3, 0x61, 0xC0, 0x8C, 0x3A, 0xF5, 0x73, 0x2C, 0x25, 0x0B, 0xBB, 0x4E, 0x89, 0x6B, 0x53, 0x6A, 0xB4, 0xF1, 0xE1, 0xE6, 0xBD, 0x45, 0xE2, 0xF4, 0xB6, 0x66, 0xCC, 0x95, 0x03, 0x56, 0xD4, 0x1C, 0x1E, 0xD7, 0xFB, 0xC3, 0x8E, 0xB5, 0xE9, 0xCF, 0xBF, 0xBA, 0xEA, 0x77, 0x39, 0xAF, 0x33, 0xC9, 0x62, 0x71, 0x81, 0x79, 0x09, 0xAD, 0x24, 0xCD, 0xF9, 0xD8, 0xE5, 0xC5, 0xB9, 0x4D, 0x44, 0x08, 0x86, 0xE7, 0xA1, 0x1D, 0xAA, 0xED, 0x06, 0x70, 0xB2, 0xD2, 0x41, 0x7B, 0xA0, 0x11, 0x31, 0xC2, 0x27, 0x90, 0x20, 0xF6, 0x60, 0xFF, 0x96, 0x5C, 0xB1, 0xAB, 0x9E, 0x9C, 0x52, 0x1B, 0x5F, 0x93, 0x0A, 0xEF, 0x91, 0x85, 0x49, 0xEE, 0x2D, 0x4F, 0x8F, 0x3B, 0x47, 0x87, 0x6D, 0x46, 0xD6, 0x3E, 0x69, 0x64, 0x2A, 0xCE, 0xCB, 0x2F, 0xFC, 0x97, 0x05, 0x7A, 0xAC, 0x7F, 0xD5, 0x1A, 0x4B, 0x0E, 0xA7, 0x5A, 0x28, 0x14, 0x3F, 0x29, 0x88, 0x3C, 0x4C, 0x02, 0xB8, 0xDA, 0xB0, 0x17, 0x55, 0x1F, 0x8A, 0x7D, 0x57, 0xC7, 0x8D, 0x74, 0xB7, 0xC4, 0x9F, 0x72, 0x7E, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34, 0x6E, 0x50, 0xDE, 0x68, 0x65, 0xBC, 0xDB, 0xF8, 0xC8, 0xA8, 0x2B, 0x40, 0xDC, 0xFE, 0x32, 0xA4, 0xCA, 0x10, 0x21, 0xF0, 0xD3, 0x5D, 0x0F, 0x00, 0x6F, 0x9D, 0x36, 0x42, 0x4A, 0x5E, 0xC1, 0xE0 ); var $q1 = array( 0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8, 0x4A, 0xD3, 0xE6, 0x6B, 0x45, 0x7D, 0xE8, 0x4B, 0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1, 0x30, 0x0F, 0xF8, 0x1B, 0x87, 0xFA, 0x06, 0x3F, 0x5E, 0xBA, 0xAE, 0x5B, 0x8A, 0x00, 0xBC, 0x9D, 0x6D, 0xC1, 0xB1, 0x0E, 0x80, 0x5D, 0xD2, 0xD5, 0xA0, 0x84, 0x07, 0x14, 0xB5, 0x90, 0x2C, 0xA3, 0xB2, 0x73, 0x4C, 0x54, 0x92, 0x74, 0x36, 0x51, 0x38, 0xB0, 0xBD, 0x5A, 0xFC, 0x60, 0x62, 0x96, 0x6C, 0x42, 0xF7, 0x10, 0x7C, 0x28, 0x27, 0x8C, 0x13, 0x95, 0x9C, 0xC7, 0x24, 0x46, 0x3B, 0x70, 0xCA, 0xE3, 0x85, 0xCB, 0x11, 0xD0, 0x93, 0xB8, 0xA6, 0x83, 0x20, 0xFF, 0x9F, 0x77, 0xC3, 0xCC, 0x03, 0x6F, 0x08, 0xBF, 0x40, 0xE7, 0x2B, 0xE2, 0x79, 0x0C, 0xAA, 0x82, 0x41, 0x3A, 0xEA, 0xB9, 0xE4, 0x9A, 0xA4, 0x97, 0x7E, 0xDA, 0x7A, 0x17, 0x66, 0x94, 0xA1, 0x1D, 0x3D, 0xF0, 0xDE, 0xB3, 0x0B, 0x72, 0xA7, 0x1C, 0xEF, 0xD1, 0x53, 0x3E, 0x8F, 0x33, 0x26, 0x5F, 0xEC, 0x76, 0x2A, 0x49, 0x81, 0x88, 0xEE, 0x21, 0xC4, 0x1A, 0xEB, 0xD9, 0xC5, 0x39, 0x99, 0xCD, 0xAD, 0x31, 0x8B, 0x01, 0x18, 0x23, 0xDD, 0x1F, 0x4E, 0x2D, 0xF9, 0x48, 0x4F, 0xF2, 0x65, 0x8E, 0x78, 0x5C, 0x58, 0x19, 0x8D, 0xE5, 0x98, 0x57, 0x67, 0x7F, 0x05, 0x64, 0xAF, 0x63, 0xB6, 0xFE, 0xF5, 0xB7, 0x3C, 0xA5, 0xCE, 0xE9, 0x68, 0x44, 0xE0, 0x4D, 0x43, 0x69, 0x29, 0x2E, 0xAC, 0x15, 0x59, 0xA8, 0x0A, 0x9E, 0x6E, 0x47, 0xDF, 0x34, 0x35, 0x6A, 0xCF, 0xDC, 0x22, 0xC9, 0xC0, 0x9B, 0x89, 0xD4, 0xED, 0xAB, 0x12, 0xA2, 0x0D, 0x52, 0xBB, 0x02, 0x2F, 0xA9, 0xD7, 0x61, 0x1E, 0xB4, 0x50, 0x04, 0xF6, 0xC2, 0x16, 0x25, 0x86, 0x56, 0x55, 0x09, 0xBE, 0x91 ); var $m0 = array( 0xBCBC3275, 0xECEC21F3, 0x202043C6, 0xB3B3C9F4, 0xDADA03DB, 0x02028B7B, 0xE2E22BFB, 0x9E9EFAC8, 0xC9C9EC4A, 0xD4D409D3, 0x18186BE6, 0x1E1E9F6B, 0x98980E45, 0xB2B2387D, 0xA6A6D2E8, 0x2626B74B, 0x3C3C57D6, 0x93938A32, 0x8282EED8, 0x525298FD, 0x7B7BD437, 0xBBBB3771, 0x5B5B97F1, 0x474783E1, 0x24243C30, 0x5151E20F, 0xBABAC6F8, 0x4A4AF31B, 0xBFBF4887, 0x0D0D70FA, 0xB0B0B306, 0x7575DE3F, 0xD2D2FD5E, 0x7D7D20BA, 0x666631AE, 0x3A3AA35B, 0x59591C8A, 0x00000000, 0xCDCD93BC, 0x1A1AE09D, 0xAEAE2C6D, 0x7F7FABC1, 0x2B2BC7B1, 0xBEBEB90E, 0xE0E0A080, 0x8A8A105D, 0x3B3B52D2, 0x6464BAD5, 0xD8D888A0, 0xE7E7A584, 0x5F5FE807, 0x1B1B1114, 0x2C2CC2B5, 0xFCFCB490, 0x3131272C, 0x808065A3, 0x73732AB2, 0x0C0C8173, 0x79795F4C, 0x6B6B4154, 0x4B4B0292, 0x53536974, 0x94948F36, 0x83831F51, 0x2A2A3638, 0xC4C49CB0, 0x2222C8BD, 0xD5D5F85A, 0xBDBDC3FC, 0x48487860, 0xFFFFCE62, 0x4C4C0796, 0x4141776C, 0xC7C7E642, 0xEBEB24F7, 0x1C1C1410, 0x5D5D637C, 0x36362228, 0x6767C027, 0xE9E9AF8C, 0x4444F913, 0x1414EA95, 0xF5F5BB9C, 0xCFCF18C7, 0x3F3F2D24, 0xC0C0E346, 0x7272DB3B, 0x54546C70, 0x29294CCA, 0xF0F035E3, 0x0808FE85, 0xC6C617CB, 0xF3F34F11, 0x8C8CE4D0, 0xA4A45993, 0xCACA96B8, 0x68683BA6, 0xB8B84D83, 0x38382820, 0xE5E52EFF, 0xADAD569F, 0x0B0B8477, 0xC8C81DC3, 0x9999FFCC, 0x5858ED03, 0x19199A6F, 0x0E0E0A08, 0x95957EBF, 0x70705040, 0xF7F730E7, 0x6E6ECF2B, 0x1F1F6EE2, 0xB5B53D79, 0x09090F0C, 0x616134AA, 0x57571682, 0x9F9F0B41, 0x9D9D803A, 0x111164EA, 0x2525CDB9, 0xAFAFDDE4, 0x4545089A, 0xDFDF8DA4, 0xA3A35C97, 0xEAEAD57E, 0x353558DA, 0xEDEDD07A, 0x4343FC17, 0xF8F8CB66, 0xFBFBB194, 0x3737D3A1, 0xFAFA401D, 0xC2C2683D, 0xB4B4CCF0, 0x32325DDE, 0x9C9C71B3, 0x5656E70B, 0xE3E3DA72, 0x878760A7, 0x15151B1C, 0xF9F93AEF, 0x6363BFD1, 0x3434A953, 0x9A9A853E, 0xB1B1428F, 0x7C7CD133, 0x88889B26, 0x3D3DA65F, 0xA1A1D7EC, 0xE4E4DF76, 0x8181942A, 0x91910149, 0x0F0FFB81, 0xEEEEAA88, 0x161661EE, 0xD7D77321, 0x9797F5C4, 0xA5A5A81A, 0xFEFE3FEB, 0x6D6DB5D9, 0x7878AEC5, 0xC5C56D39, 0x1D1DE599, 0x7676A4CD, 0x3E3EDCAD, 0xCBCB6731, 0xB6B6478B, 0xEFEF5B01, 0x12121E18, 0x6060C523, 0x6A6AB0DD, 0x4D4DF61F, 0xCECEE94E, 0xDEDE7C2D, 0x55559DF9, 0x7E7E5A48, 0x2121B24F, 0x03037AF2, 0xA0A02665, 0x5E5E198E, 0x5A5A6678, 0x65654B5C, 0x62624E58, 0xFDFD4519, 0x0606F48D, 0x404086E5, 0xF2F2BE98, 0x3333AC57, 0x17179067, 0x05058E7F, 0xE8E85E05, 0x4F4F7D64, 0x89896AAF, 0x10109563, 0x74742FB6, 0x0A0A75FE, 0x5C5C92F5, 0x9B9B74B7, 0x2D2D333C, 0x3030D6A5, 0x2E2E49CE, 0x494989E9, 0x46467268, 0x77775544, 0xA8A8D8E0, 0x9696044D, 0x2828BD43, 0xA9A92969, 0xD9D97929, 0x8686912E, 0xD1D187AC, 0xF4F44A15, 0x8D8D1559, 0xD6D682A8, 0xB9B9BC0A, 0x42420D9E, 0xF6F6C16E, 0x2F2FB847, 0xDDDD06DF, 0x23233934, 0xCCCC6235, 0xF1F1C46A, 0xC1C112CF, 0x8585EBDC, 0x8F8F9E22, 0x7171A1C9, 0x9090F0C0, 0xAAAA539B, 0x0101F189, 0x8B8BE1D4, 0x4E4E8CED, 0x8E8E6FAB, 0xABABA212, 0x6F6F3EA2, 0xE6E6540D, 0xDBDBF252, 0x92927BBB, 0xB7B7B602, 0x6969CA2F, 0x3939D9A9, 0xD3D30CD7, 0xA7A72361, 0xA2A2AD1E, 0xC3C399B4, 0x6C6C4450, 0x07070504, 0x04047FF6, 0x272746C2, 0xACACA716, 0xD0D07625, 0x50501386, 0xDCDCF756, 0x84841A55, 0xE1E15109, 0x7A7A25BE, 0x1313EF91 ); var $m1 = array( 0xA9D93939, 0x67901717, 0xB3719C9C, 0xE8D2A6A6, 0x04050707, 0xFD985252, 0xA3658080, 0x76DFE4E4, 0x9A084545, 0x92024B4B, 0x80A0E0E0, 0x78665A5A, 0xE4DDAFAF, 0xDDB06A6A, 0xD1BF6363, 0x38362A2A, 0x0D54E6E6, 0xC6432020, 0x3562CCCC, 0x98BEF2F2, 0x181E1212, 0xF724EBEB, 0xECD7A1A1, 0x6C774141, 0x43BD2828, 0x7532BCBC, 0x37D47B7B, 0x269B8888, 0xFA700D0D, 0x13F94444, 0x94B1FBFB, 0x485A7E7E, 0xF27A0303, 0xD0E48C8C, 0x8B47B6B6, 0x303C2424, 0x84A5E7E7, 0x54416B6B, 0xDF06DDDD, 0x23C56060, 0x1945FDFD, 0x5BA33A3A, 0x3D68C2C2, 0x59158D8D, 0xF321ECEC, 0xAE316666, 0xA23E6F6F, 0x82165757, 0x63951010, 0x015BEFEF, 0x834DB8B8, 0x2E918686, 0xD9B56D6D, 0x511F8383, 0x9B53AAAA, 0x7C635D5D, 0xA63B6868, 0xEB3FFEFE, 0xA5D63030, 0xBE257A7A, 0x16A7ACAC, 0x0C0F0909, 0xE335F0F0, 0x6123A7A7, 0xC0F09090, 0x8CAFE9E9, 0x3A809D9D, 0xF5925C5C, 0x73810C0C, 0x2C273131, 0x2576D0D0, 0x0BE75656, 0xBB7B9292, 0x4EE9CECE, 0x89F10101, 0x6B9F1E1E, 0x53A93434, 0x6AC4F1F1, 0xB499C3C3, 0xF1975B5B, 0xE1834747, 0xE66B1818, 0xBDC82222, 0x450E9898, 0xE26E1F1F, 0xF4C9B3B3, 0xB62F7474, 0x66CBF8F8, 0xCCFF9999, 0x95EA1414, 0x03ED5858, 0x56F7DCDC, 0xD4E18B8B, 0x1C1B1515, 0x1EADA2A2, 0xD70CD3D3, 0xFB2BE2E2, 0xC31DC8C8, 0x8E195E5E, 0xB5C22C2C, 0xE9894949, 0xCF12C1C1, 0xBF7E9595, 0xBA207D7D, 0xEA641111, 0x77840B0B, 0x396DC5C5, 0xAF6A8989, 0x33D17C7C, 0xC9A17171, 0x62CEFFFF, 0x7137BBBB, 0x81FB0F0F, 0x793DB5B5, 0x0951E1E1, 0xADDC3E3E, 0x242D3F3F, 0xCDA47676, 0xF99D5555, 0xD8EE8282, 0xE5864040, 0xC5AE7878, 0xB9CD2525, 0x4D049696, 0x44557777, 0x080A0E0E, 0x86135050, 0xE730F7F7, 0xA1D33737, 0x1D40FAFA, 0xAA346161, 0xED8C4E4E, 0x06B3B0B0, 0x706C5454, 0xB22A7373, 0xD2523B3B, 0x410B9F9F, 0x7B8B0202, 0xA088D8D8, 0x114FF3F3, 0x3167CBCB, 0xC2462727, 0x27C06767, 0x90B4FCFC, 0x20283838, 0xF67F0404, 0x60784848, 0xFF2EE5E5, 0x96074C4C, 0x5C4B6565, 0xB1C72B2B, 0xAB6F8E8E, 0x9E0D4242, 0x9CBBF5F5, 0x52F2DBDB, 0x1BF34A4A, 0x5FA63D3D, 0x9359A4A4, 0x0ABCB9B9, 0xEF3AF9F9, 0x91EF1313, 0x85FE0808, 0x49019191, 0xEE611616, 0x2D7CDEDE, 0x4FB22121, 0x8F42B1B1, 0x3BDB7272, 0x47B82F2F, 0x8748BFBF, 0x6D2CAEAE, 0x46E3C0C0, 0xD6573C3C, 0x3E859A9A, 0x6929A9A9, 0x647D4F4F, 0x2A948181, 0xCE492E2E, 0xCB17C6C6, 0x2FCA6969, 0xFCC3BDBD, 0x975CA3A3, 0x055EE8E8, 0x7AD0EDED, 0xAC87D1D1, 0x7F8E0505, 0xD5BA6464, 0x1AA8A5A5, 0x4BB72626, 0x0EB9BEBE, 0xA7608787, 0x5AF8D5D5, 0x28223636, 0x14111B1B, 0x3FDE7575, 0x2979D9D9, 0x88AAEEEE, 0x3C332D2D, 0x4C5F7979, 0x02B6B7B7, 0xB896CACA, 0xDA583535, 0xB09CC4C4, 0x17FC4343, 0x551A8484, 0x1FF64D4D, 0x8A1C5959, 0x7D38B2B2, 0x57AC3333, 0xC718CFCF, 0x8DF40606, 0x74695353, 0xB7749B9B, 0xC4F59797, 0x9F56ADAD, 0x72DAE3E3, 0x7ED5EAEA, 0x154AF4F4, 0x229E8F8F, 0x12A2ABAB, 0x584E6262, 0x07E85F5F, 0x99E51D1D, 0x34392323, 0x6EC1F6F6, 0x50446C6C, 0xDE5D3232, 0x68724646, 0x6526A0A0, 0xBC93CDCD, 0xDB03DADA, 0xF8C6BABA, 0xC8FA9E9E, 0xA882D6D6, 0x2BCF6E6E, 0x40507070, 0xDCEB8585, 0xFE750A0A, 0x328A9393, 0xA48DDFDF, 0xCA4C2929, 0x10141C1C, 0x2173D7D7, 0xF0CCB4B4, 0xD309D4D4, 0x5D108A8A, 0x0FE25151, 0x00000000, 0x6F9A1919, 0x9DE01A1A, 0x368F9494, 0x42E6C7C7, 0x4AECC9C9, 0x5EFDD2D2, 0xC1AB7F7F, 0xE0D8A8A8 ); var $m2 = array( 0xBC75BC32, 0xECF3EC21, 0x20C62043, 0xB3F4B3C9, 0xDADBDA03, 0x027B028B, 0xE2FBE22B, 0x9EC89EFA, 0xC94AC9EC, 0xD4D3D409, 0x18E6186B, 0x1E6B1E9F, 0x9845980E, 0xB27DB238, 0xA6E8A6D2, 0x264B26B7, 0x3CD63C57, 0x9332938A, 0x82D882EE, 0x52FD5298, 0x7B377BD4, 0xBB71BB37, 0x5BF15B97, 0x47E14783, 0x2430243C, 0x510F51E2, 0xBAF8BAC6, 0x4A1B4AF3, 0xBF87BF48, 0x0DFA0D70, 0xB006B0B3, 0x753F75DE, 0xD25ED2FD, 0x7DBA7D20, 0x66AE6631, 0x3A5B3AA3, 0x598A591C, 0x00000000, 0xCDBCCD93, 0x1A9D1AE0, 0xAE6DAE2C, 0x7FC17FAB, 0x2BB12BC7, 0xBE0EBEB9, 0xE080E0A0, 0x8A5D8A10, 0x3BD23B52, 0x64D564BA, 0xD8A0D888, 0xE784E7A5, 0x5F075FE8, 0x1B141B11, 0x2CB52CC2, 0xFC90FCB4, 0x312C3127, 0x80A38065, 0x73B2732A, 0x0C730C81, 0x794C795F, 0x6B546B41, 0x4B924B02, 0x53745369, 0x9436948F, 0x8351831F, 0x2A382A36, 0xC4B0C49C, 0x22BD22C8, 0xD55AD5F8, 0xBDFCBDC3, 0x48604878, 0xFF62FFCE, 0x4C964C07, 0x416C4177, 0xC742C7E6, 0xEBF7EB24, 0x1C101C14, 0x5D7C5D63, 0x36283622, 0x672767C0, 0xE98CE9AF, 0x441344F9, 0x149514EA, 0xF59CF5BB, 0xCFC7CF18, 0x3F243F2D, 0xC046C0E3, 0x723B72DB, 0x5470546C, 0x29CA294C, 0xF0E3F035, 0x088508FE, 0xC6CBC617, 0xF311F34F, 0x8CD08CE4, 0xA493A459, 0xCAB8CA96, 0x68A6683B, 0xB883B84D, 0x38203828, 0xE5FFE52E, 0xAD9FAD56, 0x0B770B84, 0xC8C3C81D, 0x99CC99FF, 0x580358ED, 0x196F199A, 0x0E080E0A, 0x95BF957E, 0x70407050, 0xF7E7F730, 0x6E2B6ECF, 0x1FE21F6E, 0xB579B53D, 0x090C090F, 0x61AA6134, 0x57825716, 0x9F419F0B, 0x9D3A9D80, 0x11EA1164, 0x25B925CD, 0xAFE4AFDD, 0x459A4508, 0xDFA4DF8D, 0xA397A35C, 0xEA7EEAD5, 0x35DA3558, 0xED7AEDD0, 0x431743FC, 0xF866F8CB, 0xFB94FBB1, 0x37A137D3, 0xFA1DFA40, 0xC23DC268, 0xB4F0B4CC, 0x32DE325D, 0x9CB39C71, 0x560B56E7, 0xE372E3DA, 0x87A78760, 0x151C151B, 0xF9EFF93A, 0x63D163BF, 0x345334A9, 0x9A3E9A85, 0xB18FB142, 0x7C337CD1, 0x8826889B, 0x3D5F3DA6, 0xA1ECA1D7, 0xE476E4DF, 0x812A8194, 0x91499101, 0x0F810FFB, 0xEE88EEAA, 0x16EE1661, 0xD721D773, 0x97C497F5, 0xA51AA5A8, 0xFEEBFE3F, 0x6DD96DB5, 0x78C578AE, 0xC539C56D, 0x1D991DE5, 0x76CD76A4, 0x3EAD3EDC, 0xCB31CB67, 0xB68BB647, 0xEF01EF5B, 0x1218121E, 0x602360C5, 0x6ADD6AB0, 0x4D1F4DF6, 0xCE4ECEE9, 0xDE2DDE7C, 0x55F9559D, 0x7E487E5A, 0x214F21B2, 0x03F2037A, 0xA065A026, 0x5E8E5E19, 0x5A785A66, 0x655C654B, 0x6258624E, 0xFD19FD45, 0x068D06F4, 0x40E54086, 0xF298F2BE, 0x335733AC, 0x17671790, 0x057F058E, 0xE805E85E, 0x4F644F7D, 0x89AF896A, 0x10631095, 0x74B6742F, 0x0AFE0A75, 0x5CF55C92, 0x9BB79B74, 0x2D3C2D33, 0x30A530D6, 0x2ECE2E49, 0x49E94989, 0x46684672, 0x77447755, 0xA8E0A8D8, 0x964D9604, 0x284328BD, 0xA969A929, 0xD929D979, 0x862E8691, 0xD1ACD187, 0xF415F44A, 0x8D598D15, 0xD6A8D682, 0xB90AB9BC, 0x429E420D, 0xF66EF6C1, 0x2F472FB8, 0xDDDFDD06, 0x23342339, 0xCC35CC62, 0xF16AF1C4, 0xC1CFC112, 0x85DC85EB, 0x8F228F9E, 0x71C971A1, 0x90C090F0, 0xAA9BAA53, 0x018901F1, 0x8BD48BE1, 0x4EED4E8C, 0x8EAB8E6F, 0xAB12ABA2, 0x6FA26F3E, 0xE60DE654, 0xDB52DBF2, 0x92BB927B, 0xB702B7B6, 0x692F69CA, 0x39A939D9, 0xD3D7D30C, 0xA761A723, 0xA21EA2AD, 0xC3B4C399, 0x6C506C44, 0x07040705, 0x04F6047F, 0x27C22746, 0xAC16ACA7, 0xD025D076, 0x50865013, 0xDC56DCF7, 0x8455841A, 0xE109E151, 0x7ABE7A25, 0x139113EF ); var $m3 = array( 0xD939A9D9, 0x90176790, 0x719CB371, 0xD2A6E8D2, 0x05070405, 0x9852FD98, 0x6580A365, 0xDFE476DF, 0x08459A08, 0x024B9202, 0xA0E080A0, 0x665A7866, 0xDDAFE4DD, 0xB06ADDB0, 0xBF63D1BF, 0x362A3836, 0x54E60D54, 0x4320C643, 0x62CC3562, 0xBEF298BE, 0x1E12181E, 0x24EBF724, 0xD7A1ECD7, 0x77416C77, 0xBD2843BD, 0x32BC7532, 0xD47B37D4, 0x9B88269B, 0x700DFA70, 0xF94413F9, 0xB1FB94B1, 0x5A7E485A, 0x7A03F27A, 0xE48CD0E4, 0x47B68B47, 0x3C24303C, 0xA5E784A5, 0x416B5441, 0x06DDDF06, 0xC56023C5, 0x45FD1945, 0xA33A5BA3, 0x68C23D68, 0x158D5915, 0x21ECF321, 0x3166AE31, 0x3E6FA23E, 0x16578216, 0x95106395, 0x5BEF015B, 0x4DB8834D, 0x91862E91, 0xB56DD9B5, 0x1F83511F, 0x53AA9B53, 0x635D7C63, 0x3B68A63B, 0x3FFEEB3F, 0xD630A5D6, 0x257ABE25, 0xA7AC16A7, 0x0F090C0F, 0x35F0E335, 0x23A76123, 0xF090C0F0, 0xAFE98CAF, 0x809D3A80, 0x925CF592, 0x810C7381, 0x27312C27, 0x76D02576, 0xE7560BE7, 0x7B92BB7B, 0xE9CE4EE9, 0xF10189F1, 0x9F1E6B9F, 0xA93453A9, 0xC4F16AC4, 0x99C3B499, 0x975BF197, 0x8347E183, 0x6B18E66B, 0xC822BDC8, 0x0E98450E, 0x6E1FE26E, 0xC9B3F4C9, 0x2F74B62F, 0xCBF866CB, 0xFF99CCFF, 0xEA1495EA, 0xED5803ED, 0xF7DC56F7, 0xE18BD4E1, 0x1B151C1B, 0xADA21EAD, 0x0CD3D70C, 0x2BE2FB2B, 0x1DC8C31D, 0x195E8E19, 0xC22CB5C2, 0x8949E989, 0x12C1CF12, 0x7E95BF7E, 0x207DBA20, 0x6411EA64, 0x840B7784, 0x6DC5396D, 0x6A89AF6A, 0xD17C33D1, 0xA171C9A1, 0xCEFF62CE, 0x37BB7137, 0xFB0F81FB, 0x3DB5793D, 0x51E10951, 0xDC3EADDC, 0x2D3F242D, 0xA476CDA4, 0x9D55F99D, 0xEE82D8EE, 0x8640E586, 0xAE78C5AE, 0xCD25B9CD, 0x04964D04, 0x55774455, 0x0A0E080A, 0x13508613, 0x30F7E730, 0xD337A1D3, 0x40FA1D40, 0x3461AA34, 0x8C4EED8C, 0xB3B006B3, 0x6C54706C, 0x2A73B22A, 0x523BD252, 0x0B9F410B, 0x8B027B8B, 0x88D8A088, 0x4FF3114F, 0x67CB3167, 0x4627C246, 0xC06727C0, 0xB4FC90B4, 0x28382028, 0x7F04F67F, 0x78486078, 0x2EE5FF2E, 0x074C9607, 0x4B655C4B, 0xC72BB1C7, 0x6F8EAB6F, 0x0D429E0D, 0xBBF59CBB, 0xF2DB52F2, 0xF34A1BF3, 0xA63D5FA6, 0x59A49359, 0xBCB90ABC, 0x3AF9EF3A, 0xEF1391EF, 0xFE0885FE, 0x01914901, 0x6116EE61, 0x7CDE2D7C, 0xB2214FB2, 0x42B18F42, 0xDB723BDB, 0xB82F47B8, 0x48BF8748, 0x2CAE6D2C, 0xE3C046E3, 0x573CD657, 0x859A3E85, 0x29A96929, 0x7D4F647D, 0x94812A94, 0x492ECE49, 0x17C6CB17, 0xCA692FCA, 0xC3BDFCC3, 0x5CA3975C, 0x5EE8055E, 0xD0ED7AD0, 0x87D1AC87, 0x8E057F8E, 0xBA64D5BA, 0xA8A51AA8, 0xB7264BB7, 0xB9BE0EB9, 0x6087A760, 0xF8D55AF8, 0x22362822, 0x111B1411, 0xDE753FDE, 0x79D92979, 0xAAEE88AA, 0x332D3C33, 0x5F794C5F, 0xB6B702B6, 0x96CAB896, 0x5835DA58, 0x9CC4B09C, 0xFC4317FC, 0x1A84551A, 0xF64D1FF6, 0x1C598A1C, 0x38B27D38, 0xAC3357AC, 0x18CFC718, 0xF4068DF4, 0x69537469, 0x749BB774, 0xF597C4F5, 0x56AD9F56, 0xDAE372DA, 0xD5EA7ED5, 0x4AF4154A, 0x9E8F229E, 0xA2AB12A2, 0x4E62584E, 0xE85F07E8, 0xE51D99E5, 0x39233439, 0xC1F66EC1, 0x446C5044, 0x5D32DE5D, 0x72466872, 0x26A06526, 0x93CDBC93, 0x03DADB03, 0xC6BAF8C6, 0xFA9EC8FA, 0x82D6A882, 0xCF6E2BCF, 0x50704050, 0xEB85DCEB, 0x750AFE75, 0x8A93328A, 0x8DDFA48D, 0x4C29CA4C, 0x141C1014, 0x73D72173, 0xCCB4F0CC, 0x09D4D309, 0x108A5D10, 0xE2510FE2, 0x00000000, 0x9A196F9A, 0xE01A9DE0, 0x8F94368F, 0xE6C742E6, 0xECC94AEC, 0xFDD25EFD, 0xAB7FC1AB, 0xD8A8E0D8 ); var $K = array(); var $S0 = array(); var $S1 = array(); var $S2 = array(); var $S3 = array(); var $kl; var $key_length = 16; function setKeyLength($length) { switch (true) { case $length <= 128: $this->key_length = 16; break; case $length <= 192: $this->key_length = 24; break; default: $this->key_length = 32; } parent::setKeyLength($length); } function _setupKey() { if (isset($this->kl['key']) && $this->key === $this->kl['key']) { return; } $this->kl = array('key' => $this->key); $le_longs = unpack('V*', $this->key); $key = unpack('C*', $this->key); $m0 = $this->m0; $m1 = $this->m1; $m2 = $this->m2; $m3 = $this->m3; $q0 = $this->q0; $q1 = $this->q1; $K = $S0 = $S1 = $S2 = $S3 = array(); switch (strlen($this->key)) { case 16: list($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[1], $le_longs[2]); list($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[3], $le_longs[4]); for ($i = 0, $j = 1; $i < 40; $i+= 2, $j+= 2) { $A = $m0[$q0[$q0[$i] ^ $key[ 9]] ^ $key[1]] ^ $m1[$q0[$q1[$i] ^ $key[10]] ^ $key[2]] ^ $m2[$q1[$q0[$i] ^ $key[11]] ^ $key[3]] ^ $m3[$q1[$q1[$i] ^ $key[12]] ^ $key[4]]; $B = $m0[$q0[$q0[$j] ^ $key[13]] ^ $key[5]] ^ $m1[$q0[$q1[$j] ^ $key[14]] ^ $key[6]] ^ $m2[$q1[$q0[$j] ^ $key[15]] ^ $key[7]] ^ $m3[$q1[$q1[$j] ^ $key[16]] ^ $key[8]]; $B = ($B << 8) | ($B >> 24 & 0xff); $K[] = $A+= $B; $K[] = (($A+= $B) << 9 | $A >> 23 & 0x1ff); } for ($i = 0; $i < 256; ++$i) { $S0[$i] = $m0[$q0[$q0[$i] ^ $s4] ^ $s0]; $S1[$i] = $m1[$q0[$q1[$i] ^ $s5] ^ $s1]; $S2[$i] = $m2[$q1[$q0[$i] ^ $s6] ^ $s2]; $S3[$i] = $m3[$q1[$q1[$i] ^ $s7] ^ $s3]; } break; case 24: list($sb, $sa, $s9, $s8) = $this->_mdsrem($le_longs[1], $le_longs[2]); list($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[3], $le_longs[4]); list($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[5], $le_longs[6]); for ($i = 0, $j = 1; $i < 40; $i+= 2, $j+= 2) { $A = $m0[$q0[$q0[$q1[$i] ^ $key[17]] ^ $key[ 9]] ^ $key[1]] ^ $m1[$q0[$q1[$q1[$i] ^ $key[18]] ^ $key[10]] ^ $key[2]] ^ $m2[$q1[$q0[$q0[$i] ^ $key[19]] ^ $key[11]] ^ $key[3]] ^ $m3[$q1[$q1[$q0[$i] ^ $key[20]] ^ $key[12]] ^ $key[4]]; $B = $m0[$q0[$q0[$q1[$j] ^ $key[21]] ^ $key[13]] ^ $key[5]] ^ $m1[$q0[$q1[$q1[$j] ^ $key[22]] ^ $key[14]] ^ $key[6]] ^ $m2[$q1[$q0[$q0[$j] ^ $key[23]] ^ $key[15]] ^ $key[7]] ^ $m3[$q1[$q1[$q0[$j] ^ $key[24]] ^ $key[16]] ^ $key[8]]; $B = ($B << 8) | ($B >> 24 & 0xff); $K[] = $A+= $B; $K[] = (($A+= $B) << 9 | $A >> 23 & 0x1ff); } for ($i = 0; $i < 256; ++$i) { $S0[$i] = $m0[$q0[$q0[$q1[$i] ^ $s8] ^ $s4] ^ $s0]; $S1[$i] = $m1[$q0[$q1[$q1[$i] ^ $s9] ^ $s5] ^ $s1]; $S2[$i] = $m2[$q1[$q0[$q0[$i] ^ $sa] ^ $s6] ^ $s2]; $S3[$i] = $m3[$q1[$q1[$q0[$i] ^ $sb] ^ $s7] ^ $s3]; } break; default: list($sf, $se, $sd, $sc) = $this->_mdsrem($le_longs[1], $le_longs[2]); list($sb, $sa, $s9, $s8) = $this->_mdsrem($le_longs[3], $le_longs[4]); list($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[5], $le_longs[6]); list($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[7], $le_longs[8]); for ($i = 0, $j = 1; $i < 40; $i+= 2, $j+= 2) { $A = $m0[$q0[$q0[$q1[$q1[$i] ^ $key[25]] ^ $key[17]] ^ $key[ 9]] ^ $key[1]] ^ $m1[$q0[$q1[$q1[$q0[$i] ^ $key[26]] ^ $key[18]] ^ $key[10]] ^ $key[2]] ^ $m2[$q1[$q0[$q0[$q0[$i] ^ $key[27]] ^ $key[19]] ^ $key[11]] ^ $key[3]] ^ $m3[$q1[$q1[$q0[$q1[$i] ^ $key[28]] ^ $key[20]] ^ $key[12]] ^ $key[4]]; $B = $m0[$q0[$q0[$q1[$q1[$j] ^ $key[29]] ^ $key[21]] ^ $key[13]] ^ $key[5]] ^ $m1[$q0[$q1[$q1[$q0[$j] ^ $key[30]] ^ $key[22]] ^ $key[14]] ^ $key[6]] ^ $m2[$q1[$q0[$q0[$q0[$j] ^ $key[31]] ^ $key[23]] ^ $key[15]] ^ $key[7]] ^ $m3[$q1[$q1[$q0[$q1[$j] ^ $key[32]] ^ $key[24]] ^ $key[16]] ^ $key[8]]; $B = ($B << 8) | ($B >> 24 & 0xff); $K[] = $A+= $B; $K[] = (($A+= $B) << 9 | $A >> 23 & 0x1ff); } for ($i = 0; $i < 256; ++$i) { $S0[$i] = $m0[$q0[$q0[$q1[$q1[$i] ^ $sc] ^ $s8] ^ $s4] ^ $s0]; $S1[$i] = $m1[$q0[$q1[$q1[$q0[$i] ^ $sd] ^ $s9] ^ $s5] ^ $s1]; $S2[$i] = $m2[$q1[$q0[$q0[$q0[$i] ^ $se] ^ $sa] ^ $s6] ^ $s2]; $S3[$i] = $m3[$q1[$q1[$q0[$q1[$i] ^ $sf] ^ $sb] ^ $s7] ^ $s3]; } } $this->K = $K; $this->S0 = $S0; $this->S1 = $S1; $this->S2 = $S2; $this->S3 = $S3; } function _mdsrem($A, $B) { for ($i = 0; $i < 8; ++$i) { $t = 0xff & ($B >> 24); $B = ($B << 8) | (0xff & ($A >> 24)); $A<<= 8; $u = $t << 1; if ($t & 0x80) { $u^= 0x14d; } $B ^= $t ^ ($u << 16); $u^= 0x7fffffff & ($t >> 1); if ($t & 0x01) { $u^= 0xa6 ; } $B^= ($u << 24) | ($u << 8); } return array( 0xff & $B >> 24, 0xff & $B >> 16, 0xff & $B >> 8, 0xff & $B); } function _encryptBlock($in) { $S0 = $this->S0; $S1 = $this->S1; $S2 = $this->S2; $S3 = $this->S3; $K = $this->K; $in = unpack("V4", $in); $R0 = $K[0] ^ $in[1]; $R1 = $K[1] ^ $in[2]; $R2 = $K[2] ^ $in[3]; $R3 = $K[3] ^ $in[4]; $ki = 7; while ($ki < 39) { $t0 = $S0[ $R0 & 0xff] ^ $S1[($R0 >> 8) & 0xff] ^ $S2[($R0 >> 16) & 0xff] ^ $S3[($R0 >> 24) & 0xff]; $t1 = $S0[($R1 >> 24) & 0xff] ^ $S1[ $R1 & 0xff] ^ $S2[($R1 >> 8) & 0xff] ^ $S3[($R1 >> 16) & 0xff]; $R2^= $t0 + $t1 + $K[++$ki]; $R2 = ($R2 >> 1 & 0x7fffffff) | ($R2 << 31); $R3 = ((($R3 >> 31) & 1) | ($R3 << 1)) ^ ($t0 + ($t1 << 1) + $K[++$ki]); $t0 = $S0[ $R2 & 0xff] ^ $S1[($R2 >> 8) & 0xff] ^ $S2[($R2 >> 16) & 0xff] ^ $S3[($R2 >> 24) & 0xff]; $t1 = $S0[($R3 >> 24) & 0xff] ^ $S1[ $R3 & 0xff] ^ $S2[($R3 >> 8) & 0xff] ^ $S3[($R3 >> 16) & 0xff]; $R0^= ($t0 + $t1 + $K[++$ki]); $R0 = ($R0 >> 1 & 0x7fffffff) | ($R0 << 31); $R1 = ((($R1 >> 31) & 1) | ($R1 << 1)) ^ ($t0 + ($t1 << 1) + $K[++$ki]); } return pack("V4", $K[4] ^ $R2, $K[5] ^ $R3, $K[6] ^ $R0, $K[7] ^ $R1); } function _decryptBlock($in) { $S0 = $this->S0; $S1 = $this->S1; $S2 = $this->S2; $S3 = $this->S3; $K = $this->K; $in = unpack("V4", $in); $R0 = $K[4] ^ $in[1]; $R1 = $K[5] ^ $in[2]; $R2 = $K[6] ^ $in[3]; $R3 = $K[7] ^ $in[4]; $ki = 40; while ($ki > 8) { $t0 = $S0[$R0 & 0xff] ^ $S1[$R0 >> 8 & 0xff] ^ $S2[$R0 >> 16 & 0xff] ^ $S3[$R0 >> 24 & 0xff]; $t1 = $S0[$R1 >> 24 & 0xff] ^ $S1[$R1 & 0xff] ^ $S2[$R1 >> 8 & 0xff] ^ $S3[$R1 >> 16 & 0xff]; $R3^= $t0 + ($t1 << 1) + $K[--$ki]; $R3 = $R3 >> 1 & 0x7fffffff | $R3 << 31; $R2 = ($R2 >> 31 & 0x1 | $R2 << 1) ^ ($t0 + $t1 + $K[--$ki]); $t0 = $S0[$R2 & 0xff] ^ $S1[$R2 >> 8 & 0xff] ^ $S2[$R2 >> 16 & 0xff] ^ $S3[$R2 >> 24 & 0xff]; $t1 = $S0[$R3 >> 24 & 0xff] ^ $S1[$R3 & 0xff] ^ $S2[$R3 >> 8 & 0xff] ^ $S3[$R3 >> 16 & 0xff]; $R1^= $t0 + ($t1 << 1) + $K[--$ki]; $R1 = $R1 >> 1 & 0x7fffffff | $R1 << 31; $R0 = ($R0 >> 31 & 0x1 | $R0 << 1) ^ ($t0 + $t1 + $K[--$ki]); } return pack("V4", $K[0] ^ $R2, $K[1] ^ $R3, $K[2] ^ $R0, $K[3] ^ $R1); } function _setupInlineCrypt() { $lambda_functions =& Crypt_Twofish::_getLambdaFunctions(); $gen_hi_opt_code = (bool)(count($lambda_functions) < 10); $code_hash = "Crypt_Twofish, {$this->mode}"; if ($gen_hi_opt_code) { $code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key); } if (!isset($lambda_functions[$code_hash])) { switch (true) { case $gen_hi_opt_code: $K = $this->K; $init_crypt = '
                        static $S0, $S1, $S2, $S3;
                        if (!$S0) {
                            for ($i = 0; $i < 256; ++$i) {
                                $S0[] = (int)$self->S0[$i];
                                $S1[] = (int)$self->S1[$i];
                                $S2[] = (int)$self->S2[$i];
                                $S3[] = (int)$self->S3[$i];
                            }
                        }
                    '; break; default: $K = array(); for ($i = 0; $i < 40; ++$i) { $K[] = '$K_' . $i; } $init_crypt = '
                        $S0 = $self->S0;
                        $S1 = $self->S1;
                        $S2 = $self->S2;
                        $S3 = $self->S3;
                        list(' . implode(',', $K) . ') = $self->K;
                    '; } $encrypt_block = '
                $in = unpack("V4", $in);
                $R0 = '.$K[0].' ^ $in[1];
                $R1 = '.$K[1].' ^ $in[2];
                $R2 = '.$K[2].' ^ $in[3];
                $R3 = '.$K[3].' ^ $in[4];
            '; for ($ki = 7, $i = 0; $i < 8; ++$i) { $encrypt_block.= '
                    $t0 = $S0[ $R0        & 0xff] ^
                          $S1[($R0 >>  8) & 0xff] ^
                          $S2[($R0 >> 16) & 0xff] ^
                          $S3[($R0 >> 24) & 0xff];
                    $t1 = $S0[($R1 >> 24) & 0xff] ^
                          $S1[ $R1        & 0xff] ^
                          $S2[($R1 >>  8) & 0xff] ^
                          $S3[($R1 >> 16) & 0xff];
                    $R2^= ($t0 + $t1 + '.$K[++$ki].');
                    $R2 = ($R2 >> 1 & 0x7fffffff) | ($R2 << 31);
                    $R3 = ((($R3 >> 31) & 1) | ($R3 << 1)) ^ ($t0 + ($t1 << 1) + '.$K[++$ki].');

                    $t0 = $S0[ $R2        & 0xff] ^
                          $S1[($R2 >>  8) & 0xff] ^
                          $S2[($R2 >> 16) & 0xff] ^
                          $S3[($R2 >> 24) & 0xff];
                    $t1 = $S0[($R3 >> 24) & 0xff] ^
                          $S1[ $R3        & 0xff] ^
                          $S2[($R3 >>  8) & 0xff] ^
                          $S3[($R3 >> 16) & 0xff];
                    $R0^= ($t0 + $t1 + '.$K[++$ki].');
                    $R0 = ($R0 >> 1 & 0x7fffffff) | ($R0 << 31);
                    $R1 = ((($R1 >> 31) & 1) | ($R1 << 1)) ^ ($t0 + ($t1 << 1) + '.$K[++$ki].');
                '; } $encrypt_block.= '
                $in = pack("V4", '.$K[4].' ^ $R2,
                                 '.$K[5].' ^ $R3,
                                 '.$K[6].' ^ $R0,
                                 '.$K[7].' ^ $R1);
            '; $decrypt_block = '
                $in = unpack("V4", $in);
                $R0 = '.$K[4].' ^ $in[1];
                $R1 = '.$K[5].' ^ $in[2];
                $R2 = '.$K[6].' ^ $in[3];
                $R3 = '.$K[7].' ^ $in[4];
            '; for ($ki = 40, $i = 0; $i < 8; ++$i) { $decrypt_block.= '
                    $t0 = $S0[$R0       & 0xff] ^
                          $S1[$R0 >>  8 & 0xff] ^
                          $S2[$R0 >> 16 & 0xff] ^
                          $S3[$R0 >> 24 & 0xff];
                    $t1 = $S0[$R1 >> 24 & 0xff] ^
                          $S1[$R1       & 0xff] ^
                          $S2[$R1 >>  8 & 0xff] ^
                          $S3[$R1 >> 16 & 0xff];
                    $R3^= $t0 + ($t1 << 1) + '.$K[--$ki].';
                    $R3 = $R3 >> 1 & 0x7fffffff | $R3 << 31;
                    $R2 = ($R2 >> 31 & 0x1 | $R2 << 1) ^ ($t0 + $t1 + '.$K[--$ki].');

                    $t0 = $S0[$R2       & 0xff] ^
                          $S1[$R2 >>  8 & 0xff] ^
                          $S2[$R2 >> 16 & 0xff] ^
                          $S3[$R2 >> 24 & 0xff];
                    $t1 = $S0[$R3 >> 24 & 0xff] ^
                          $S1[$R3       & 0xff] ^
                          $S2[$R3 >>  8 & 0xff] ^
                          $S3[$R3 >> 16 & 0xff];
                    $R1^= $t0 + ($t1 << 1) + '.$K[--$ki].';
                    $R1 = $R1 >> 1 & 0x7fffffff | $R1 << 31;
                    $R0 = ($R0 >> 31 & 0x1 | $R0 << 1) ^ ($t0 + $t1 + '.$K[--$ki].');
                '; } $decrypt_block.= '
                $in = pack("V4", '.$K[0].' ^ $R2,
                                 '.$K[1].' ^ $R3,
                                 '.$K[2].' ^ $R0,
                                 '.$K[3].' ^ $R1);
            '; $lambda_functions[$code_hash] = $this->_createInlineCryptFunction( array( 'init_crypt' => $init_crypt, 'init_encrypt' => '', 'init_decrypt' => '', 'encrypt_block' => $encrypt_block, 'decrypt_block' => $decrypt_block ) ); } $this->inline_crypt = $lambda_functions[$code_hash]; } } } if (!class_exists('Crypt_RC4')) { if (!class_exists('Crypt_Base')) { include_once 'Base.php'; } define('CRYPT_RC4_ENCRYPT', 0); define('CRYPT_RC4_DECRYPT', 1); class Crypt_RC4 extends Crypt_Base { var $block_size = 0; var $key_length = 128; var $const_namespace = 'RC4'; var $cipher_name_mcrypt = 'arcfour'; var $use_inline_crypt = false; var $key = "\0"; var $stream; function __construct() { parent::__construct(CRYPT_MODE_STREAM); } function Crypt_RC4() { $this->__construct(); } function isValidEngine($engine) { if ($engine == CRYPT_ENGINE_OPENSSL) { $this->cipher_name_openssl = 'rc4-40'; } return parent::isValidEngine($engine); } function setIV($iv) { } function setKeyLength($length) { if ($length < 8) { $this->key_length = 1; } elseif ($length > 2048) { $this->key_length = 256; } else { $this->key_length = $length >> 3; } parent::setKeyLength($length); } function encrypt($plaintext) { if ($this->engine != CRYPT_ENGINE_INTERNAL) { return parent::encrypt($plaintext); } return $this->_crypt($plaintext, CRYPT_RC4_ENCRYPT); } function decrypt($ciphertext) { if ($this->engine != CRYPT_ENGINE_INTERNAL) { return parent::decrypt($ciphertext); } return $this->_crypt($ciphertext, CRYPT_RC4_DECRYPT); } function _setupKey() { $key = $this->key; $keyLength = strlen($key); $keyStream = range(0, 255); $j = 0; for ($i = 0; $i < 256; $i++) { $j = ($j + $keyStream[$i] + ord($key[$i % $keyLength])) & 255; $temp = $keyStream[$i]; $keyStream[$i] = $keyStream[$j]; $keyStream[$j] = $temp; } $this->stream = array(); $this->stream[CRYPT_RC4_DECRYPT] = $this->stream[CRYPT_RC4_ENCRYPT] = array( 0, 0, $keyStream ); } function _crypt($text, $mode) { if ($this->changed) { $this->_setup(); $this->changed = false; } $stream = &$this->stream[$mode]; if ($this->continuousBuffer) { $i = &$stream[0]; $j = &$stream[1]; $keyStream = &$stream[2]; } else { $i = $stream[0]; $j = $stream[1]; $keyStream = $stream[2]; } $len = strlen($text); for ($k = 0; $k < $len; ++$k) { $i = ($i + 1) & 255; $ksi = $keyStream[$i]; $j = ($j + $ksi) & 255; $ksj = $keyStream[$j]; $keyStream[$i] = $ksj; $keyStream[$j] = $ksi; $text[$k] = $text[$k] ^ chr($keyStream[($ksj + $ksi) & 255]); } return $text; } } } if (!class_exists('Net_SSH2')) { define('NET_SSH2_MASK_CONSTRUCTOR', 0x00000001); define('NET_SSH2_MASK_CONNECTED', 0x00000002); define('NET_SSH2_MASK_LOGIN_REQ', 0x00000004); define('NET_SSH2_MASK_LOGIN', 0x00000008); define('NET_SSH2_MASK_SHELL', 0x00000010); define('NET_SSH2_MASK_WINDOW_ADJUST', 0x00000020); define('NET_SSH2_CHANNEL_EXEC', 0); define('NET_SSH2_CHANNEL_SHELL', 1); define('NET_SSH2_CHANNEL_SUBSYSTEM', 2); define('NET_SSH2_CHANNEL_AGENT_FORWARD', 3); define('NET_SSH2_LOG_SIMPLE', 1); define('NET_SSH2_LOG_COMPLEX', 2); define('NET_SSH2_LOG_REALTIME', 3); define('NET_SSH2_LOG_REALTIME_FILE', 4); define('NET_SSH2_READ_SIMPLE', 1); define('NET_SSH2_READ_REGEX', 2); define('NET_SSH2_LOG_MAX_SIZE', 1024 * 1024); class Net_SSH2 { var $identifier; var $fsock; var $bitmap = 0; var $errors = array(); var $server_identifier = false; var $kex_algorithms = false; var $kex_dh_group_size_min = 1536; var $kex_dh_group_size_preferred = 2048; var $kex_dh_group_size_max = 4096; var $server_host_key_algorithms = false; var $encryption_algorithms_client_to_server = false; var $encryption_algorithms_server_to_client = false; var $mac_algorithms_client_to_server = false; var $mac_algorithms_server_to_client = false; var $compression_algorithms_client_to_server = false; var $compression_algorithms_server_to_client = false; var $languages_server_to_client = false; var $languages_client_to_server = false; var $encrypt_block_size = 8; var $decrypt_block_size = 8; var $decrypt = false; var $encrypt = false; var $hmac_create = false; var $hmac_check = false; var $hmac_size = false; var $server_public_host_key; var $session_id = false; var $exchange_hash = false; var $message_numbers = array(); var $disconnect_reasons = array(); var $channel_open_failure_reasons = array(); var $terminal_modes = array(); var $channel_extended_data_type_codes = array(); var $send_seq_no = 0; var $get_seq_no = 0; var $server_channels = array(); var $channel_buffers = array(); var $channel_status = array(); var $packet_size_client_to_server = array(); var $message_number_log = array(); var $message_log = array(); var $window_size = 0x7FFFFFFF; var $window_size_server_to_client = array(); var $window_size_client_to_server = array(); var $signature = ''; var $signature_format = ''; var $interactiveBuffer = ''; var $log_size; var $timeout; var $curTimeout; var $realtime_log_file; var $realtime_log_size; var $signature_validated = false; var $realtime_log_wrap; var $quiet_mode = false; var $last_packet; var $exit_status; var $request_pty = false; var $in_request_pty_exec = false; var $in_subsystem; var $stdErrorLog; var $last_interactive_response = ''; var $keyboard_requests_responses = array(); var $banner_message = ''; var $is_timeout = false; var $log_boundary = ':'; var $log_long_width = 65; var $log_short_width = 16; var $host; var $port; var $windowColumns = 80; var $windowRows = 24; var $crypto_engine = false; var $agent; function __construct($host, $port = 22, $timeout = 10) { if (!class_exists('Math_BigInteger')) { include_once 'Math/BigInteger.php'; } if (!function_exists('crypt_random_string')) { include_once 'Crypt/Random.php'; } if (!class_exists('Crypt_Hash')) { include_once 'Crypt/Hash.php'; } if (!class_exists('Crypt_Base')) { include_once 'Crypt/Base.php'; } $this->message_numbers = array( 1 => 'NET_SSH2_MSG_DISCONNECT', 2 => 'NET_SSH2_MSG_IGNORE', 3 => 'NET_SSH2_MSG_UNIMPLEMENTED', 4 => 'NET_SSH2_MSG_DEBUG', 5 => 'NET_SSH2_MSG_SERVICE_REQUEST', 6 => 'NET_SSH2_MSG_SERVICE_ACCEPT', 20 => 'NET_SSH2_MSG_KEXINIT', 21 => 'NET_SSH2_MSG_NEWKEYS', 30 => 'NET_SSH2_MSG_KEXDH_INIT', 31 => 'NET_SSH2_MSG_KEXDH_REPLY', 50 => 'NET_SSH2_MSG_USERAUTH_REQUEST', 51 => 'NET_SSH2_MSG_USERAUTH_FAILURE', 52 => 'NET_SSH2_MSG_USERAUTH_SUCCESS', 53 => 'NET_SSH2_MSG_USERAUTH_BANNER', 80 => 'NET_SSH2_MSG_GLOBAL_REQUEST', 81 => 'NET_SSH2_MSG_REQUEST_SUCCESS', 82 => 'NET_SSH2_MSG_REQUEST_FAILURE', 90 => 'NET_SSH2_MSG_CHANNEL_OPEN', 91 => 'NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION', 92 => 'NET_SSH2_MSG_CHANNEL_OPEN_FAILURE', 93 => 'NET_SSH2_MSG_CHANNEL_WINDOW_ADJUST', 94 => 'NET_SSH2_MSG_CHANNEL_DATA', 95 => 'NET_SSH2_MSG_CHANNEL_EXTENDED_DATA', 96 => 'NET_SSH2_MSG_CHANNEL_EOF', 97 => 'NET_SSH2_MSG_CHANNEL_CLOSE', 98 => 'NET_SSH2_MSG_CHANNEL_REQUEST', 99 => 'NET_SSH2_MSG_CHANNEL_SUCCESS', 100 => 'NET_SSH2_MSG_CHANNEL_FAILURE' ); $this->disconnect_reasons = array( 1 => 'NET_SSH2_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT', 2 => 'NET_SSH2_DISCONNECT_PROTOCOL_ERROR', 3 => 'NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED', 4 => 'NET_SSH2_DISCONNECT_RESERVED', 5 => 'NET_SSH2_DISCONNECT_MAC_ERROR', 6 => 'NET_SSH2_DISCONNECT_COMPRESSION_ERROR', 7 => 'NET_SSH2_DISCONNECT_SERVICE_NOT_AVAILABLE', 8 => 'NET_SSH2_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED', 9 => 'NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE', 10 => 'NET_SSH2_DISCONNECT_CONNECTION_LOST', 11 => 'NET_SSH2_DISCONNECT_BY_APPLICATION', 12 => 'NET_SSH2_DISCONNECT_TOO_MANY_CONNECTIONS', 13 => 'NET_SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER', 14 => 'NET_SSH2_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE', 15 => 'NET_SSH2_DISCONNECT_ILLEGAL_USER_NAME' ); $this->channel_open_failure_reasons = array( 1 => 'NET_SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED' ); $this->terminal_modes = array( 0 => 'NET_SSH2_TTY_OP_END' ); $this->channel_extended_data_type_codes = array( 1 => 'NET_SSH2_EXTENDED_DATA_STDERR' ); $this->_define_array( $this->message_numbers, $this->disconnect_reasons, $this->channel_open_failure_reasons, $this->terminal_modes, $this->channel_extended_data_type_codes, array(60 => 'NET_SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ'), array(60 => 'NET_SSH2_MSG_USERAUTH_PK_OK'), array(60 => 'NET_SSH2_MSG_USERAUTH_INFO_REQUEST', 61 => 'NET_SSH2_MSG_USERAUTH_INFO_RESPONSE'), array(30 => 'NET_SSH2_MSG_KEXDH_GEX_REQUEST_OLD', 31 => 'NET_SSH2_MSG_KEXDH_GEX_GROUP', 32 => 'NET_SSH2_MSG_KEXDH_GEX_INIT', 33 => 'NET_SSH2_MSG_KEXDH_GEX_REPLY', 34 => 'NET_SSH2_MSG_KEXDH_GEX_REQUEST') ); if (is_resource($host)) { $this->fsock = $host; return; } if (is_string($host)) { $this->host = $host; $this->port = $port; $this->timeout = $timeout; } } function Net_SSH2($host, $port = 22, $timeout = 10) { $this->__construct($host, $port, $timeout); } function setCryptoEngine($engine) { $this->crypto_engine = $engine; } function _connect() { if ($this->bitmap & NET_SSH2_MASK_CONSTRUCTOR) { return false; } $this->bitmap |= NET_SSH2_MASK_CONSTRUCTOR; $this->curTimeout = $this->timeout; $this->last_packet = strtok(microtime(), ' ') + strtok(''); if (!is_resource($this->fsock)) { $start = strtok(microtime(), ' ') + strtok(''); $this->fsock = @fsockopen($this->host, $this->port, $errno, $errstr, $this->curTimeout == 0 ? 100000 : $this->curTimeout); if (!$this->fsock) { $host = $this->host . ':' . $this->port; user_error(rtrim("Cannot connect to $host. Error $errno. $errstr")); return false; } $elapsed = strtok(microtime(), ' ') + strtok('') - $start; $this->curTimeout-= $elapsed; if ($this->curTimeout <= 0) { $this->is_timeout = true; return false; } } $this->identifier = $this->_generate_identifier(); fputs($this->fsock, $this->identifier . "\r\n"); $temp = ''; $extra = ''; while (!feof($this->fsock) && !preg_match('#^SSH-(\d\.\d+)#', $temp, $matches)) { if (substr($temp, -2) == "\r\n") { $extra.= $temp; $temp = ''; } if ($this->curTimeout) { if ($this->curTimeout < 0) { $this->is_timeout = true; return false; } $read = array($this->fsock); $write = $except = null; $start = strtok(microtime(), ' ') + strtok(''); $sec = floor($this->curTimeout); $usec = 1000000 * ($this->curTimeout - $sec); if (!@stream_select($read, $write, $except, $sec, $usec) && !count($read)) { $this->is_timeout = true; return false; } $elapsed = strtok(microtime(), ' ') + strtok('') - $start; $this->curTimeout-= $elapsed; } $temp.= fgets($this->fsock, 255); } if (feof($this->fsock)) { user_error('Connection closed by server'); return false; } if (defined('NET_SSH2_LOGGING')) { $this->_append_log('<-', $extra . $temp); $this->_append_log('->', $this->identifier . "\r\n"); } $this->server_identifier = trim($temp, "\r\n"); if (strlen($extra)) { $this->errors[] = utf8_decode($extra); } if ($matches[1] != '1.99' && $matches[1] != '2.0') { user_error("Cannot connect to SSH $matches[1] servers"); return false; } $response = $this->_get_binary_packet(); if ($response === false) { user_error('Connection closed by server'); return false; } if (!strlen($response) || ord($response[0]) != NET_SSH2_MSG_KEXINIT) { user_error('Expected SSH_MSG_KEXINIT'); return false; } if (!$this->_key_exchange($response)) { return false; } $this->bitmap|= NET_SSH2_MASK_CONNECTED; return true; } function _generate_identifier() { $identifier = 'SSH-2.0-phpseclib_1.0'; $ext = array(); if (extension_loaded('openssl')) { $ext[] = 'openssl'; } elseif (extension_loaded('mcrypt')) { $ext[] = 'mcrypt'; } if (extension_loaded('gmp')) { $ext[] = 'gmp'; } elseif (extension_loaded('bcmath')) { $ext[] = 'bcmath'; } if (!empty($ext)) { $identifier .= ' (' . implode(', ', $ext) . ')'; } return $identifier; } function _key_exchange($kexinit_payload_server) { static $kex_algorithms = array( 'diffie-hellman-group1-sha1', 'diffie-hellman-group14-sha1', 'diffie-hellman-group-exchange-sha1', 'diffie-hellman-group-exchange-sha256', ); static $server_host_key_algorithms = array( 'ssh-rsa', 'ssh-dss' ); static $encryption_algorithms = false; if ($encryption_algorithms === false) { $encryption_algorithms = array( 'arcfour256', 'arcfour128', 'aes128-ctr', 'aes192-ctr', 'aes256-ctr', 'twofish128-ctr', 'twofish192-ctr', 'twofish256-ctr', 'aes128-cbc', 'aes192-cbc', 'aes256-cbc', 'twofish128-cbc', 'twofish192-cbc', 'twofish256-cbc', 'twofish-cbc', 'blowfish-ctr', 'blowfish-cbc', '3des-ctr', '3des-cbc', ); if (extension_loaded('openssl') && !extension_loaded('mcrypt')) { $encryption_algorithms = array_diff( $encryption_algorithms, array('arcfour256', 'arcfour128', 'arcfour') ); } if (phpseclib_resolve_include_path('Crypt/RC4.php') === false) { $encryption_algorithms = array_diff( $encryption_algorithms, array('arcfour256', 'arcfour128', 'arcfour') ); } if (phpseclib_resolve_include_path('Crypt/Rijndael.php') === false) { $encryption_algorithms = array_diff( $encryption_algorithms, array('aes128-ctr', 'aes192-ctr', 'aes256-ctr', 'aes128-cbc', 'aes192-cbc', 'aes256-cbc') ); } if (phpseclib_resolve_include_path('Crypt/Twofish.php') === false) { $encryption_algorithms = array_diff( $encryption_algorithms, array('twofish128-ctr', 'twofish192-ctr', 'twofish256-ctr', 'twofish128-cbc', 'twofish192-cbc', 'twofish256-cbc', 'twofish-cbc') ); } if (phpseclib_resolve_include_path('Crypt/Blowfish.php') === false) { $encryption_algorithms = array_diff( $encryption_algorithms, array('blowfish-ctr', 'blowfish-cbc') ); } if (phpseclib_resolve_include_path('Crypt/TripleDES.php') === false) { $encryption_algorithms = array_diff( $encryption_algorithms, array('3des-ctr', '3des-cbc') ); } $encryption_algorithms = array_values($encryption_algorithms); } $mac_algorithms = array( 'hmac-sha2-256', 'hmac-sha1-96', 'hmac-sha1', 'hmac-md5-96', 'hmac-md5', ); static $compression_algorithms = array( 'none' ); switch ($this->server_identifier) { case 'SSH-2.0-SSHD': $mac_algorithms = array_values(array_diff( $mac_algorithms, array('hmac-sha1-96', 'hmac-md5-96') )); } static $str_kex_algorithms, $str_server_host_key_algorithms, $encryption_algorithms_server_to_client, $mac_algorithms_server_to_client, $compression_algorithms_server_to_client, $encryption_algorithms_client_to_server, $mac_algorithms_client_to_server, $compression_algorithms_client_to_server; if (empty($str_kex_algorithms)) { $str_kex_algorithms = implode(',', $kex_algorithms); $str_server_host_key_algorithms = implode(',', $server_host_key_algorithms); $encryption_algorithms_server_to_client = $encryption_algorithms_client_to_server = implode(',', $encryption_algorithms); $mac_algorithms_server_to_client = $mac_algorithms_client_to_server = implode(',', $mac_algorithms); $compression_algorithms_server_to_client = $compression_algorithms_client_to_server = implode(',', $compression_algorithms); } $client_cookie = crypt_random_string(16); $response = $kexinit_payload_server; $this->_string_shift($response, 1); $server_cookie = $this->_string_shift($response, 16); if (strlen($response) < 4) { return false; } $temp = unpack('Nlength', $this->_string_shift($response, 4)); $this->kex_algorithms = explode(',', $this->_string_shift($response, $temp['length'])); if (strlen($response) < 4) { return false; } $temp = unpack('Nlength', $this->_string_shift($response, 4)); $this->server_host_key_algorithms = explode(',', $this->_string_shift($response, $temp['length'])); if (strlen($response) < 4) { return false; } $temp = unpack('Nlength', $this->_string_shift($response, 4)); $this->encryption_algorithms_client_to_server = explode(',', $this->_string_shift($response, $temp['length'])); if (strlen($response) < 4) { return false; } $temp = unpack('Nlength', $this->_string_shift($response, 4)); $this->encryption_algorithms_server_to_client = explode(',', $this->_string_shift($response, $temp['length'])); if (strlen($response) < 4) { return false; } $temp = unpack('Nlength', $this->_string_shift($response, 4)); $this->mac_algorithms_client_to_server = explode(',', $this->_string_shift($response, $temp['length'])); if (strlen($response) < 4) { return false; } $temp = unpack('Nlength', $this->_string_shift($response, 4)); $this->mac_algorithms_server_to_client = explode(',', $this->_string_shift($response, $temp['length'])); if (strlen($response) < 4) { return false; } $temp = unpack('Nlength', $this->_string_shift($response, 4)); $this->compression_algorithms_client_to_server = explode(',', $this->_string_shift($response, $temp['length'])); if (strlen($response) < 4) { return false; } $temp = unpack('Nlength', $this->_string_shift($response, 4)); $this->compression_algorithms_server_to_client = explode(',', $this->_string_shift($response, $temp['length'])); if (strlen($response) < 4) { return false; } $temp = unpack('Nlength', $this->_string_shift($response, 4)); $this->languages_client_to_server = explode(',', $this->_string_shift($response, $temp['length'])); if (strlen($response) < 4) { return false; } $temp = unpack('Nlength', $this->_string_shift($response, 4)); $this->languages_server_to_client = explode(',', $this->_string_shift($response, $temp['length'])); if (!strlen($response)) { return false; } extract(unpack('Cfirst_kex_packet_follows', $this->_string_shift($response, 1))); $first_kex_packet_follows = $first_kex_packet_follows != 0; $kexinit_payload_client = pack( 'Ca*Na*Na*Na*Na*Na*Na*Na*Na*Na*Na*CN', NET_SSH2_MSG_KEXINIT, $client_cookie, strlen($str_kex_algorithms), $str_kex_algorithms, strlen($str_server_host_key_algorithms), $str_server_host_key_algorithms, strlen($encryption_algorithms_client_to_server), $encryption_algorithms_client_to_server, strlen($encryption_algorithms_server_to_client), $encryption_algorithms_server_to_client, strlen($mac_algorithms_client_to_server), $mac_algorithms_client_to_server, strlen($mac_algorithms_server_to_client), $mac_algorithms_server_to_client, strlen($compression_algorithms_client_to_server), $compression_algorithms_client_to_server, strlen($compression_algorithms_server_to_client), $compression_algorithms_server_to_client, 0, '', 0, '', 0, 0 ); if (!$this->_send_binary_packet($kexinit_payload_client)) { return false; } $decrypt = $this->_array_intersect_first($encryption_algorithms, $this->encryption_algorithms_server_to_client); $decryptKeyLength = $this->_encryption_algorithm_to_key_size($decrypt); if ($decryptKeyLength === null) { user_error('No compatible server to client encryption algorithms found'); return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); } $encrypt = $this->_array_intersect_first($encryption_algorithms, $this->encryption_algorithms_client_to_server); $encryptKeyLength = $this->_encryption_algorithm_to_key_size($encrypt); if ($encryptKeyLength === null) { user_error('No compatible client to server encryption algorithms found'); return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); } $keyLength = $decryptKeyLength > $encryptKeyLength ? $decryptKeyLength : $encryptKeyLength; $kex_algorithm = $this->_array_intersect_first($kex_algorithms, $this->kex_algorithms); if ($kex_algorithm === false) { user_error('No compatible key exchange algorithms found'); return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); } if (strpos($kex_algorithm, 'diffie-hellman-group-exchange') === 0) { $dh_group_sizes_packed = pack( 'NNN', $this->kex_dh_group_size_min, $this->kex_dh_group_size_preferred, $this->kex_dh_group_size_max ); $packet = pack( 'Ca*', NET_SSH2_MSG_KEXDH_GEX_REQUEST, $dh_group_sizes_packed ); if (!$this->_send_binary_packet($packet)) { return false; } $response = $this->_get_binary_packet(); if ($response === false) { user_error('Connection closed by server'); return false; } if (!strlen($response)) { return false; } extract(unpack('Ctype', $this->_string_shift($response, 1))); if ($type != NET_SSH2_MSG_KEXDH_GEX_GROUP) { user_error('Expected SSH_MSG_KEX_DH_GEX_GROUP'); return false; } if (strlen($response) < 4) { return false; } extract(unpack('NprimeLength', $this->_string_shift($response, 4))); $primeBytes = $this->_string_shift($response, $primeLength); $prime = new Math_BigInteger($primeBytes, -256); if (strlen($response) < 4) { return false; } extract(unpack('NgLength', $this->_string_shift($response, 4))); $gBytes = $this->_string_shift($response, $gLength); $g = new Math_BigInteger($gBytes, -256); $exchange_hash_rfc4419 = pack( 'a*Na*Na*', $dh_group_sizes_packed, $primeLength, $primeBytes, $gLength, $gBytes ); $clientKexInitMessage = NET_SSH2_MSG_KEXDH_GEX_INIT; $serverKexReplyMessage = NET_SSH2_MSG_KEXDH_GEX_REPLY; } else { switch ($kex_algorithm) { case 'diffie-hellman-group1-sha1': $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' . '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' . '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' . 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF'; break; case 'diffie-hellman-group14-sha1': $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' . '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' . '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' . 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05' . '98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB' . '9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B' . 'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718' . '3995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF'; break; } $g = new Math_BigInteger(2); $prime = new Math_BigInteger($prime, 16); $exchange_hash_rfc4419 = ''; $clientKexInitMessage = NET_SSH2_MSG_KEXDH_INIT; $serverKexReplyMessage = NET_SSH2_MSG_KEXDH_REPLY; } switch ($kex_algorithm) { case 'diffie-hellman-group-exchange-sha256': $kexHash = new Crypt_Hash('sha256'); break; default: $kexHash = new Crypt_Hash('sha1'); } $one = new Math_BigInteger(1); $keyLength = min($keyLength, $kexHash->getLength()); $max = $one->bitwise_leftShift(16 * $keyLength); $max = $max->subtract($one); $x = $one->random($one, $max); $e = $g->modPow($x, $prime); $eBytes = $e->toBytes(true); $data = pack('CNa*', $clientKexInitMessage, strlen($eBytes), $eBytes); if (!$this->_send_binary_packet($data)) { user_error('Connection closed by server'); return false; } $response = $this->_get_binary_packet(); if ($response === false) { user_error('Connection closed by server'); return false; } if (!strlen($response)) { return false; } extract(unpack('Ctype', $this->_string_shift($response, 1))); if ($type != $serverKexReplyMessage) { user_error('Expected SSH_MSG_KEXDH_REPLY'); return false; } if (strlen($response) < 4) { return false; } $temp = unpack('Nlength', $this->_string_shift($response, 4)); $this->server_public_host_key = $server_public_host_key = $this->_string_shift($response, $temp['length']); if (strlen($server_public_host_key) < 4) { return false; } $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4)); $public_key_format = $this->_string_shift($server_public_host_key, $temp['length']); if (strlen($response) < 4) { return false; } $temp = unpack('Nlength', $this->_string_shift($response, 4)); $fBytes = $this->_string_shift($response, $temp['length']); $f = new Math_BigInteger($fBytes, -256); if (strlen($response) < 4) { return false; } $temp = unpack('Nlength', $this->_string_shift($response, 4)); $this->signature = $this->_string_shift($response, $temp['length']); if (strlen($this->signature) < 4) { return false; } $temp = unpack('Nlength', $this->_string_shift($this->signature, 4)); $this->signature_format = $this->_string_shift($this->signature, $temp['length']); $key = $f->modPow($x, $prime); $keyBytes = $key->toBytes(true); $this->exchange_hash = pack( 'Na*Na*Na*Na*Na*a*Na*Na*Na*', strlen($this->identifier), $this->identifier, strlen($this->server_identifier), $this->server_identifier, strlen($kexinit_payload_client), $kexinit_payload_client, strlen($kexinit_payload_server), $kexinit_payload_server, strlen($this->server_public_host_key), $this->server_public_host_key, $exchange_hash_rfc4419, strlen($eBytes), $eBytes, strlen($fBytes), $fBytes, strlen($keyBytes), $keyBytes ); $this->exchange_hash = $kexHash->hash($this->exchange_hash); if ($this->session_id === false) { $this->session_id = $this->exchange_hash; } $server_host_key_algorithm = $this->_array_intersect_first($server_host_key_algorithms, $this->server_host_key_algorithms); if ($server_host_key_algorithm === false) { user_error('No compatible server host key algorithms found'); return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); } if ($public_key_format != $server_host_key_algorithm || $this->signature_format != $server_host_key_algorithm) { user_error('Server Host Key Algorithm Mismatch'); return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); } $packet = pack( 'C', NET_SSH2_MSG_NEWKEYS ); if (!$this->_send_binary_packet($packet)) { return false; } $response = $this->_get_binary_packet(); if ($response === false) { user_error('Connection closed by server'); return false; } if (!strlen($response)) { return false; } extract(unpack('Ctype', $this->_string_shift($response, 1))); if ($type != NET_SSH2_MSG_NEWKEYS) { user_error('Expected SSH_MSG_NEWKEYS'); return false; } switch ($encrypt) { case '3des-cbc': if (!class_exists('Crypt_TripleDES')) { include_once 'Crypt/TripleDES.php'; } $this->encrypt = new Crypt_TripleDES(); break; case '3des-ctr': if (!class_exists('Crypt_TripleDES')) { include_once 'Crypt/TripleDES.php'; } $this->encrypt = new Crypt_TripleDES(CRYPT_DES_MODE_CTR); break; case 'aes256-cbc': case 'aes192-cbc': case 'aes128-cbc': if (!class_exists('Crypt_Rijndael')) { include_once 'Crypt/Rijndael.php'; } $this->encrypt = new Crypt_Rijndael(); $this->encrypt_block_size = 16; break; case 'aes256-ctr': case 'aes192-ctr': case 'aes128-ctr': if (!class_exists('Crypt_Rijndael')) { include_once 'Crypt/Rijndael.php'; } $this->encrypt = new Crypt_Rijndael(CRYPT_RIJNDAEL_MODE_CTR); $this->encrypt_block_size = 16; break; case 'blowfish-cbc': if (!class_exists('Crypt_Blowfish')) { include_once 'Crypt/Blowfish.php'; } $this->encrypt = new Crypt_Blowfish(); $this->encrypt_block_size = 8; break; case 'blowfish-ctr': if (!class_exists('Crypt_Blowfish')) { include_once 'Crypt/Blowfish.php'; } $this->encrypt = new Crypt_Blowfish(CRYPT_BLOWFISH_MODE_CTR); $this->encrypt_block_size = 8; break; case 'twofish128-cbc': case 'twofish192-cbc': case 'twofish256-cbc': case 'twofish-cbc': if (!class_exists('Crypt_Twofish')) { include_once 'Crypt/Twofish.php'; } $this->encrypt = new Crypt_Twofish(); $this->encrypt_block_size = 16; break; case 'twofish128-ctr': case 'twofish192-ctr': case 'twofish256-ctr': if (!class_exists('Crypt_Twofish')) { include_once 'Crypt/Twofish.php'; } $this->encrypt = new Crypt_Twofish(CRYPT_TWOFISH_MODE_CTR); $this->encrypt_block_size = 16; break; case 'arcfour': case 'arcfour128': case 'arcfour256': if (!class_exists('Crypt_RC4')) { include_once 'Crypt/RC4.php'; } $this->encrypt = new Crypt_RC4(); break; case 'none': } switch ($decrypt) { case '3des-cbc': if (!class_exists('Crypt_TripleDES')) { include_once 'Crypt/TripleDES.php'; } $this->decrypt = new Crypt_TripleDES(); break; case '3des-ctr': if (!class_exists('Crypt_TripleDES')) { include_once 'Crypt/TripleDES.php'; } $this->decrypt = new Crypt_TripleDES(CRYPT_DES_MODE_CTR); break; case 'aes256-cbc': case 'aes192-cbc': case 'aes128-cbc': if (!class_exists('Crypt_Rijndael')) { include_once 'Crypt/Rijndael.php'; } $this->decrypt = new Crypt_Rijndael(); $this->decrypt_block_size = 16; break; case 'aes256-ctr': case 'aes192-ctr': case 'aes128-ctr': if (!class_exists('Crypt_Rijndael')) { include_once 'Crypt/Rijndael.php'; } $this->decrypt = new Crypt_Rijndael(CRYPT_RIJNDAEL_MODE_CTR); $this->decrypt_block_size = 16; break; case 'blowfish-cbc': if (!class_exists('Crypt_Blowfish')) { include_once 'Crypt/Blowfish.php'; } $this->decrypt = new Crypt_Blowfish(); $this->decrypt_block_size = 8; break; case 'blowfish-ctr': if (!class_exists('Crypt_Blowfish')) { include_once 'Crypt/Blowfish.php'; } $this->decrypt = new Crypt_Blowfish(CRYPT_BLOWFISH_MODE_CTR); $this->decrypt_block_size = 8; break; case 'twofish128-cbc': case 'twofish192-cbc': case 'twofish256-cbc': case 'twofish-cbc': if (!class_exists('Crypt_Twofish')) { include_once 'Crypt/Twofish.php'; } $this->decrypt = new Crypt_Twofish(); $this->decrypt_block_size = 16; break; case 'twofish128-ctr': case 'twofish192-ctr': case 'twofish256-ctr': if (!class_exists('Crypt_Twofish')) { include_once 'Crypt/Twofish.php'; } $this->decrypt = new Crypt_Twofish(CRYPT_TWOFISH_MODE_CTR); $this->decrypt_block_size = 16; break; case 'arcfour': case 'arcfour128': case 'arcfour256': if (!class_exists('Crypt_RC4')) { include_once 'Crypt/RC4.php'; } $this->decrypt = new Crypt_RC4(); break; case 'none': } $keyBytes = pack('Na*', strlen($keyBytes), $keyBytes); if ($this->encrypt) { if ($this->crypto_engine) { $this->encrypt->setEngine($this->crypto_engine); } $this->encrypt->enableContinuousBuffer(); $this->encrypt->disablePadding(); $iv = $kexHash->hash($keyBytes . $this->exchange_hash . 'A' . $this->session_id); while ($this->encrypt_block_size > strlen($iv)) { $iv.= $kexHash->hash($keyBytes . $this->exchange_hash . $iv); } $this->encrypt->setIV(substr($iv, 0, $this->encrypt_block_size)); $key = $kexHash->hash($keyBytes . $this->exchange_hash . 'C' . $this->session_id); while ($encryptKeyLength > strlen($key)) { $key.= $kexHash->hash($keyBytes . $this->exchange_hash . $key); } $this->encrypt->setKey(substr($key, 0, $encryptKeyLength)); } if ($this->decrypt) { if ($this->crypto_engine) { $this->decrypt->setEngine($this->crypto_engine); } $this->decrypt->enableContinuousBuffer(); $this->decrypt->disablePadding(); $iv = $kexHash->hash($keyBytes . $this->exchange_hash . 'B' . $this->session_id); while ($this->decrypt_block_size > strlen($iv)) { $iv.= $kexHash->hash($keyBytes . $this->exchange_hash . $iv); } $this->decrypt->setIV(substr($iv, 0, $this->decrypt_block_size)); $key = $kexHash->hash($keyBytes . $this->exchange_hash . 'D' . $this->session_id); while ($decryptKeyLength > strlen($key)) { $key.= $kexHash->hash($keyBytes . $this->exchange_hash . $key); } $this->decrypt->setKey(substr($key, 0, $decryptKeyLength)); } if ($encrypt == 'arcfour128' || $encrypt == 'arcfour256') { $this->encrypt->encrypt(str_repeat("\0", 1536)); } if ($decrypt == 'arcfour128' || $decrypt == 'arcfour256') { $this->decrypt->decrypt(str_repeat("\0", 1536)); } $mac_algorithm = $this->_array_intersect_first($mac_algorithms, $this->mac_algorithms_client_to_server); if ($mac_algorithm === false) { user_error('No compatible client to server message authentication algorithms found'); return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); } $createKeyLength = 0; switch ($mac_algorithm) { case 'hmac-sha2-256': $this->hmac_create = new Crypt_Hash('sha256'); $createKeyLength = 32; break; case 'hmac-sha1': $this->hmac_create = new Crypt_Hash('sha1'); $createKeyLength = 20; break; case 'hmac-sha1-96': $this->hmac_create = new Crypt_Hash('sha1-96'); $createKeyLength = 20; break; case 'hmac-md5': $this->hmac_create = new Crypt_Hash('md5'); $createKeyLength = 16; break; case 'hmac-md5-96': $this->hmac_create = new Crypt_Hash('md5-96'); $createKeyLength = 16; } $mac_algorithm = $this->_array_intersect_first($mac_algorithms, $this->mac_algorithms_server_to_client); if ($mac_algorithm === false) { user_error('No compatible server to client message authentication algorithms found'); return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); } $checkKeyLength = 0; $this->hmac_size = 0; switch ($mac_algorithm) { case 'hmac-sha2-256': $this->hmac_check = new Crypt_Hash('sha256'); $checkKeyLength = 32; $this->hmac_size = 32; break; case 'hmac-sha1': $this->hmac_check = new Crypt_Hash('sha1'); $checkKeyLength = 20; $this->hmac_size = 20; break; case 'hmac-sha1-96': $this->hmac_check = new Crypt_Hash('sha1-96'); $checkKeyLength = 20; $this->hmac_size = 12; break; case 'hmac-md5': $this->hmac_check = new Crypt_Hash('md5'); $checkKeyLength = 16; $this->hmac_size = 16; break; case 'hmac-md5-96': $this->hmac_check = new Crypt_Hash('md5-96'); $checkKeyLength = 16; $this->hmac_size = 12; } $key = $kexHash->hash($keyBytes . $this->exchange_hash . 'E' . $this->session_id); while ($createKeyLength > strlen($key)) { $key.= $kexHash->hash($keyBytes . $this->exchange_hash . $key); } $this->hmac_create->setKey(substr($key, 0, $createKeyLength)); $key = $kexHash->hash($keyBytes . $this->exchange_hash . 'F' . $this->session_id); while ($checkKeyLength > strlen($key)) { $key.= $kexHash->hash($keyBytes . $this->exchange_hash . $key); } $this->hmac_check->setKey(substr($key, 0, $checkKeyLength)); $compression_algorithm = $this->_array_intersect_first($compression_algorithms, $this->compression_algorithms_server_to_client); if ($compression_algorithm === false) { user_error('No compatible server to client compression algorithms found'); return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); } $this->decompress = $compression_algorithm == 'zlib'; $compression_algorithm = $this->_array_intersect_first($compression_algorithms, $this->compression_algorithms_client_to_server); if ($compression_algorithm === false) { user_error('No compatible client to server compression algorithms found'); return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); } $this->compress = $compression_algorithm == 'zlib'; return true; } function _encryption_algorithm_to_key_size($algorithm) { switch ($algorithm) { case 'none': return 0; case 'aes128-cbc': case 'aes128-ctr': case 'arcfour': case 'arcfour128': case 'blowfish-cbc': case 'blowfish-ctr': case 'twofish128-cbc': case 'twofish128-ctr': return 16; case '3des-cbc': case '3des-ctr': case 'aes192-cbc': case 'aes192-ctr': case 'twofish192-cbc': case 'twofish192-ctr': return 24; case 'aes256-cbc': case 'aes256-ctr': case 'arcfour256': case 'twofish-cbc': case 'twofish256-cbc': case 'twofish256-ctr': return 32; } return null; } function login($username) { $args = func_get_args(); return call_user_func_array(array(&$this, '_login'), $args); } function _login($username) { if (!($this->bitmap & NET_SSH2_MASK_CONSTRUCTOR)) { if (!$this->_connect()) { return false; } } $args = array_slice(func_get_args(), 1); if (empty($args)) { return $this->_login_helper($username); } foreach ($args as $arg) { if ($this->_login_helper($username, $arg)) { return true; } } return false; } function _login_helper($username, $password = null) { if (!($this->bitmap & NET_SSH2_MASK_CONNECTED)) { return false; } if (!($this->bitmap & NET_SSH2_MASK_LOGIN_REQ)) { $packet = pack( 'CNa*', NET_SSH2_MSG_SERVICE_REQUEST, strlen('ssh-userauth'), 'ssh-userauth' ); if (!$this->_send_binary_packet($packet)) { return false; } $response = $this->_get_binary_packet(); if ($response === false) { user_error('Connection closed by server'); return false; } if (strlen($response) < 4) { return false; } extract(unpack('Ctype', $this->_string_shift($response, 1))); if ($type != NET_SSH2_MSG_SERVICE_ACCEPT) { user_error('Expected SSH_MSG_SERVICE_ACCEPT'); return false; } $this->bitmap |= NET_SSH2_MASK_LOGIN_REQ; } if (strlen($this->last_interactive_response)) { return !is_string($password) && !is_array($password) ? false : $this->_keyboard_interactive_process($password); } if (is_object($password)) { switch (strtolower(get_class($password))) { case 'crypt_rsa': return $this->_privatekey_login($username, $password); case 'system_ssh_agent': return $this->_ssh_agent_login($username, $password); } } if (is_array($password)) { if ($this->_keyboard_interactive_login($username, $password)) { $this->bitmap |= NET_SSH2_MASK_LOGIN; return true; } return false; } if (!isset($password)) { $packet = pack( 'CNa*Na*Na*', NET_SSH2_MSG_USERAUTH_REQUEST, strlen($username), $username, strlen('ssh-connection'), 'ssh-connection', strlen('none'), 'none' ); if (!$this->_send_binary_packet($packet)) { return false; } $response = $this->_get_binary_packet(); if ($response === false) { user_error('Connection closed by server'); return false; } if (!strlen($response)) { return false; } extract(unpack('Ctype', $this->_string_shift($response, 1))); switch ($type) { case NET_SSH2_MSG_USERAUTH_SUCCESS: $this->bitmap |= NET_SSH2_MASK_LOGIN; return true; default: return false; } } $packet = pack( 'CNa*Na*Na*CNa*', NET_SSH2_MSG_USERAUTH_REQUEST, strlen($username), $username, strlen('ssh-connection'), 'ssh-connection', strlen('password'), 'password', 0, strlen($password), $password ); if (!defined('NET_SSH2_LOGGING')) { $logged = null; } else { $logged = pack( 'CNa*Na*Na*CNa*', NET_SSH2_MSG_USERAUTH_REQUEST, strlen('username'), 'username', strlen('ssh-connection'), 'ssh-connection', strlen('password'), 'password', 0, strlen('password'), 'password' ); } if (!$this->_send_binary_packet($packet, $logged)) { return false; } $response = $this->_get_binary_packet(); if ($response === false) { user_error('Connection closed by server'); return false; } if (!strlen($response)) { return false; } extract(unpack('Ctype', $this->_string_shift($response, 1))); switch ($type) { case NET_SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ: if (defined('NET_SSH2_LOGGING')) { $this->message_number_log[count($this->message_number_log) - 1] = 'NET_SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ'; } if (strlen($response) < 4) { return false; } extract(unpack('Nlength', $this->_string_shift($response, 4))); $this->errors[] = 'SSH_MSG_USERAUTH_PASSWD_CHANGEREQ: ' . utf8_decode($this->_string_shift($response, $length)); return $this->_disconnect(NET_SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER); case NET_SSH2_MSG_USERAUTH_FAILURE: if (strlen($response) < 4) { return false; } extract(unpack('Nlength', $this->_string_shift($response, 4))); $auth_methods = explode(',', $this->_string_shift($response, $length)); if (!strlen($response)) { return false; } extract(unpack('Cpartial_success', $this->_string_shift($response, 1))); $partial_success = $partial_success != 0; if (!$partial_success && in_array('keyboard-interactive', $auth_methods)) { if ($this->_keyboard_interactive_login($username, $password)) { $this->bitmap |= NET_SSH2_MASK_LOGIN; return true; } return false; } return false; case NET_SSH2_MSG_USERAUTH_SUCCESS: $this->bitmap |= NET_SSH2_MASK_LOGIN; return true; } return false; } function _keyboard_interactive_login($username, $password) { $packet = pack( 'CNa*Na*Na*Na*Na*', NET_SSH2_MSG_USERAUTH_REQUEST, strlen($username), $username, strlen('ssh-connection'), 'ssh-connection', strlen('keyboard-interactive'), 'keyboard-interactive', 0, '', 0, '' ); if (!$this->_send_binary_packet($packet)) { return false; } return $this->_keyboard_interactive_process($password); } function _keyboard_interactive_process() { $responses = func_get_args(); if (strlen($this->last_interactive_response)) { $response = $this->last_interactive_response; } else { $orig = $response = $this->_get_binary_packet(); if ($response === false) { user_error('Connection closed by server'); return false; } } if (!strlen($response)) { return false; } extract(unpack('Ctype', $this->_string_shift($response, 1))); switch ($type) { case NET_SSH2_MSG_USERAUTH_INFO_REQUEST: if (strlen($response) < 4) { return false; } extract(unpack('Nlength', $this->_string_shift($response, 4))); $this->_string_shift($response, $length); if (strlen($response) < 4) { return false; } extract(unpack('Nlength', $this->_string_shift($response, 4))); $this->_string_shift($response, $length); if (strlen($response) < 4) { return false; } extract(unpack('Nlength', $this->_string_shift($response, 4))); $this->_string_shift($response, $length); if (strlen($response) < 4) { return false; } extract(unpack('Nnum_prompts', $this->_string_shift($response, 4))); for ($i = 0; $i < count($responses); $i++) { if (is_array($responses[$i])) { foreach ($responses[$i] as $key => $value) { $this->keyboard_requests_responses[$key] = $value; } unset($responses[$i]); } } $responses = array_values($responses); if (isset($this->keyboard_requests_responses)) { for ($i = 0; $i < $num_prompts; $i++) { if (strlen($response) < 4) { return false; } extract(unpack('Nlength', $this->_string_shift($response, 4))); $prompt = $this->_string_shift($response, $length); foreach ($this->keyboard_requests_responses as $key => $value) { if (substr($prompt, 0, strlen($key)) == $key) { $responses[] = $value; break; } } } } if (strlen($this->last_interactive_response)) { $this->last_interactive_response = ''; } elseif (defined('NET_SSH2_LOGGING')) { $this->message_number_log[count($this->message_number_log) - 1] = str_replace( 'UNKNOWN', 'NET_SSH2_MSG_USERAUTH_INFO_REQUEST', $this->message_number_log[count($this->message_number_log) - 1] ); } if (!count($responses) && $num_prompts) { $this->last_interactive_response = $orig; return false; } $packet = $logged = pack('CN', NET_SSH2_MSG_USERAUTH_INFO_RESPONSE, count($responses)); for ($i = 0; $i < count($responses); $i++) { $packet.= pack('Na*', strlen($responses[$i]), $responses[$i]); $logged.= pack('Na*', strlen('dummy-answer'), 'dummy-answer'); } if (!$this->_send_binary_packet($packet, $logged)) { return false; } if (defined('NET_SSH2_LOGGING') && NET_SSH2_LOGGING == NET_SSH2_LOG_COMPLEX) { $this->message_number_log[count($this->message_number_log) - 1] = str_replace( 'UNKNOWN', 'NET_SSH2_MSG_USERAUTH_INFO_RESPONSE', $this->message_number_log[count($this->message_number_log) - 1] ); } return $this->_keyboard_interactive_process(); case NET_SSH2_MSG_USERAUTH_SUCCESS: return true; case NET_SSH2_MSG_USERAUTH_FAILURE: return false; } return false; } function _ssh_agent_login($username, $agent) { $this->agent = $agent; $keys = $agent->requestIdentities(); foreach ($keys as $key) { if ($this->_privatekey_login($username, $key)) { return true; } } return false; } function _privatekey_login($username, $privatekey) { $publickey = $privatekey->getPublicKey(CRYPT_RSA_PUBLIC_FORMAT_RAW); if ($publickey === false) { return false; } $publickey = array( 'e' => $publickey['e']->toBytes(true), 'n' => $publickey['n']->toBytes(true) ); $publickey = pack( 'Na*Na*Na*', strlen('ssh-rsa'), 'ssh-rsa', strlen($publickey['e']), $publickey['e'], strlen($publickey['n']), $publickey['n'] ); $part1 = pack( 'CNa*Na*Na*', NET_SSH2_MSG_USERAUTH_REQUEST, strlen($username), $username, strlen('ssh-connection'), 'ssh-connection', strlen('publickey'), 'publickey' ); $part2 = pack('Na*Na*', strlen('ssh-rsa'), 'ssh-rsa', strlen($publickey), $publickey); $packet = $part1 . chr(0) . $part2; if (!$this->_send_binary_packet($packet)) { return false; } $response = $this->_get_binary_packet(); if ($response === false) { user_error('Connection closed by server'); return false; } if (!strlen($response)) { return false; } extract(unpack('Ctype', $this->_string_shift($response, 1))); switch ($type) { case NET_SSH2_MSG_USERAUTH_FAILURE: if (strlen($response) < 4) { return false; } extract(unpack('Nlength', $this->_string_shift($response, 4))); $this->errors[] = 'SSH_MSG_USERAUTH_FAILURE: ' . $this->_string_shift($response, $length); return false; case NET_SSH2_MSG_USERAUTH_PK_OK: if (defined('NET_SSH2_LOGGING') && NET_SSH2_LOGGING == NET_SSH2_LOG_COMPLEX) { $this->message_number_log[count($this->message_number_log) - 1] = str_replace( 'UNKNOWN', 'NET_SSH2_MSG_USERAUTH_PK_OK', $this->message_number_log[count($this->message_number_log) - 1] ); } } $packet = $part1 . chr(1) . $part2; $privatekey->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1); $signature = $privatekey->sign(pack('Na*a*', strlen($this->session_id), $this->session_id, $packet)); $signature = pack('Na*Na*', strlen('ssh-rsa'), 'ssh-rsa', strlen($signature), $signature); $packet.= pack('Na*', strlen($signature), $signature); if (!$this->_send_binary_packet($packet)) { return false; } $response = $this->_get_binary_packet(); if ($response === false) { user_error('Connection closed by server'); return false; } if (!strlen($response)) { return false; } extract(unpack('Ctype', $this->_string_shift($response, 1))); switch ($type) { case NET_SSH2_MSG_USERAUTH_FAILURE: return false; case NET_SSH2_MSG_USERAUTH_SUCCESS: $this->bitmap |= NET_SSH2_MASK_LOGIN; return true; } return false; } function setTimeout($timeout) { $this->timeout = $this->curTimeout = $timeout; } function getStdError() { return $this->stdErrorLog; } function exec($command, $callback = null) { $this->curTimeout = $this->timeout; $this->is_timeout = false; $this->stdErrorLog = ''; if (!$this->isAuthenticated()) { return false; } if ($this->in_request_pty_exec) { user_error('If you want to run multiple exec()\'s you will need to disable (and re-enable if appropriate) a PTY for each one.'); return false; } $this->window_size_server_to_client[NET_SSH2_CHANNEL_EXEC] = $this->window_size; $packet_size = 0x4000; $packet = pack( 'CNa*N3', NET_SSH2_MSG_CHANNEL_OPEN, strlen('session'), 'session', NET_SSH2_CHANNEL_EXEC, $this->window_size_server_to_client[NET_SSH2_CHANNEL_EXEC], $packet_size ); if (!$this->_send_binary_packet($packet)) { return false; } $this->channel_status[NET_SSH2_CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_OPEN; $response = $this->_get_channel_packet(NET_SSH2_CHANNEL_EXEC); if ($response === false) { return false; } if ($this->request_pty === true) { $terminal_modes = pack('C', NET_SSH2_TTY_OP_END); $packet = pack( 'CNNa*CNa*N5a*', NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[NET_SSH2_CHANNEL_EXEC], strlen('pty-req'), 'pty-req', 1, strlen('vt100'), 'vt100', $this->windowColumns, $this->windowRows, 0, 0, strlen($terminal_modes), $terminal_modes ); if (!$this->_send_binary_packet($packet)) { return false; } $response = $this->_get_binary_packet(); if ($response === false) { user_error('Connection closed by server'); return false; } if (!strlen($response)) { return false; } list(, $type) = unpack('C', $this->_string_shift($response, 1)); switch ($type) { case NET_SSH2_MSG_CHANNEL_SUCCESS: break; case NET_SSH2_MSG_CHANNEL_FAILURE: default: user_error('Unable to request pseudo-terminal'); return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION); } $this->in_request_pty_exec = true; } $packet = pack( 'CNNa*CNa*', NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[NET_SSH2_CHANNEL_EXEC], strlen('exec'), 'exec', 1, strlen($command), $command ); if (!$this->_send_binary_packet($packet)) { return false; } $this->channel_status[NET_SSH2_CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_REQUEST; $response = $this->_get_channel_packet(NET_SSH2_CHANNEL_EXEC); if ($response === false) { return false; } $this->channel_status[NET_SSH2_CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_DATA; if ($callback === false || $this->in_request_pty_exec) { return true; } $output = ''; while (true) { $temp = $this->_get_channel_packet(NET_SSH2_CHANNEL_EXEC); switch (true) { case $temp === true: return is_callable($callback) ? true : $output; case $temp === false: return false; default: if (is_callable($callback)) { if (call_user_func($callback, $temp) === true) { $this->_close_channel(NET_SSH2_CHANNEL_EXEC); return true; } } else { $output.= $temp; } } } } function _initShell() { if ($this->in_request_pty_exec === true) { return true; } $this->window_size_server_to_client[NET_SSH2_CHANNEL_SHELL] = $this->window_size; $packet_size = 0x4000; $packet = pack( 'CNa*N3', NET_SSH2_MSG_CHANNEL_OPEN, strlen('session'), 'session', NET_SSH2_CHANNEL_SHELL, $this->window_size_server_to_client[NET_SSH2_CHANNEL_SHELL], $packet_size ); if (!$this->_send_binary_packet($packet)) { return false; } $this->channel_status[NET_SSH2_CHANNEL_SHELL] = NET_SSH2_MSG_CHANNEL_OPEN; $response = $this->_get_channel_packet(NET_SSH2_CHANNEL_SHELL); if ($response === false) { return false; } $terminal_modes = pack('C', NET_SSH2_TTY_OP_END); $packet = pack( 'CNNa*CNa*N5a*', NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[NET_SSH2_CHANNEL_SHELL], strlen('pty-req'), 'pty-req', 1, strlen('vt100'), 'vt100', $this->windowColumns, $this->windowRows, 0, 0, strlen($terminal_modes), $terminal_modes ); if (!$this->_send_binary_packet($packet)) { return false; } $response = $this->_get_binary_packet(); if ($response === false) { user_error('Connection closed by server'); return false; } if (!strlen($response)) { return false; } list(, $type) = unpack('C', $this->_string_shift($response, 1)); switch ($type) { case NET_SSH2_MSG_CHANNEL_SUCCESS: case NET_SSH2_MSG_CHANNEL_FAILURE: break; default: user_error('Unable to request pseudo-terminal'); return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION); } $packet = pack( 'CNNa*C', NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[NET_SSH2_CHANNEL_SHELL], strlen('shell'), 'shell', 1 ); if (!$this->_send_binary_packet($packet)) { return false; } $this->channel_status[NET_SSH2_CHANNEL_SHELL] = NET_SSH2_MSG_CHANNEL_REQUEST; $response = $this->_get_channel_packet(NET_SSH2_CHANNEL_SHELL); if ($response === false) { return false; } $this->channel_status[NET_SSH2_CHANNEL_SHELL] = NET_SSH2_MSG_CHANNEL_DATA; $this->bitmap |= NET_SSH2_MASK_SHELL; return true; } function _get_interactive_channel() { switch (true) { case $this->in_subsystem: return NET_SSH2_CHANNEL_SUBSYSTEM; case $this->in_request_pty_exec: return NET_SSH2_CHANNEL_EXEC; default: return NET_SSH2_CHANNEL_SHELL; } } function _get_open_channel() { $channel = NET_SSH2_CHANNEL_EXEC; do { if (isset($this->channel_status[$channel]) && $this->channel_status[$channel] == NET_SSH2_MSG_CHANNEL_OPEN) { return $channel; } } while ($channel++ < NET_SSH2_CHANNEL_SUBSYSTEM); return false; } function read($expect = '', $mode = NET_SSH2_READ_SIMPLE) { $this->curTimeout = $this->timeout; $this->is_timeout = false; if (!$this->isAuthenticated()) { user_error('Operation disallowed prior to login()'); return false; } if (!($this->bitmap & NET_SSH2_MASK_SHELL) && !$this->_initShell()) { user_error('Unable to initiate an interactive shell session'); return false; } $channel = $this->_get_interactive_channel(); $match = $expect; while (true) { if ($mode == NET_SSH2_READ_REGEX) { preg_match($expect, substr($this->interactiveBuffer, -1024), $matches); $match = isset($matches[0]) ? $matches[0] : ''; } $pos = strlen($match) ? strpos($this->interactiveBuffer, $match) : false; if ($pos !== false) { return $this->_string_shift($this->interactiveBuffer, $pos + strlen($match)); } $response = $this->_get_channel_packet($channel); if (is_bool($response)) { $this->in_request_pty_exec = false; return $response ? $this->_string_shift($this->interactiveBuffer, strlen($this->interactiveBuffer)) : false; } $this->interactiveBuffer.= $response; } } function write($cmd) { if (!$this->isAuthenticated()) { user_error('Operation disallowed prior to login()'); return false; } if (!($this->bitmap & NET_SSH2_MASK_SHELL) && !$this->_initShell()) { user_error('Unable to initiate an interactive shell session'); return false; } return $this->_send_channel_packet($this->_get_interactive_channel(), $cmd); } function startSubsystem($subsystem) { $this->window_size_server_to_client[NET_SSH2_CHANNEL_SUBSYSTEM] = $this->window_size; $packet = pack( 'CNa*N3', NET_SSH2_MSG_CHANNEL_OPEN, strlen('session'), 'session', NET_SSH2_CHANNEL_SUBSYSTEM, $this->window_size, 0x4000 ); if (!$this->_send_binary_packet($packet)) { return false; } $this->channel_status[NET_SSH2_CHANNEL_SUBSYSTEM] = NET_SSH2_MSG_CHANNEL_OPEN; $response = $this->_get_channel_packet(NET_SSH2_CHANNEL_SUBSYSTEM); if ($response === false) { return false; } $packet = pack( 'CNNa*CNa*', NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[NET_SSH2_CHANNEL_SUBSYSTEM], strlen('subsystem'), 'subsystem', 1, strlen($subsystem), $subsystem ); if (!$this->_send_binary_packet($packet)) { return false; } $this->channel_status[NET_SSH2_CHANNEL_SUBSYSTEM] = NET_SSH2_MSG_CHANNEL_REQUEST; $response = $this->_get_channel_packet(NET_SSH2_CHANNEL_SUBSYSTEM); if ($response === false) { return false; } $this->channel_status[NET_SSH2_CHANNEL_SUBSYSTEM] = NET_SSH2_MSG_CHANNEL_DATA; $this->bitmap |= NET_SSH2_MASK_SHELL; $this->in_subsystem = true; return true; } function stopSubsystem() { $this->in_subsystem = false; $this->_close_channel(NET_SSH2_CHANNEL_SUBSYSTEM); return true; } function reset() { $this->_close_channel($this->_get_interactive_channel()); } function isTimeout() { return $this->is_timeout; } function disconnect() { $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION); if (isset($this->realtime_log_file) && is_resource($this->realtime_log_file)) { fclose($this->realtime_log_file); } } function __destruct() { $this->disconnect(); } function isConnected() { return (bool) ($this->bitmap & NET_SSH2_MASK_CONNECTED); } function isAuthenticated() { return (bool) ($this->bitmap & NET_SSH2_MASK_LOGIN); } function _get_binary_packet() { if (!is_resource($this->fsock) || feof($this->fsock)) { user_error('Connection closed prematurely'); $this->bitmap = 0; return false; } $start = strtok(microtime(), ' ') + strtok(''); $raw = fread($this->fsock, $this->decrypt_block_size); if (!strlen($raw)) { return ''; } if ($this->decrypt !== false) { $raw = $this->decrypt->decrypt($raw); } if ($raw === false) { user_error('Unable to decrypt content'); return false; } if (strlen($raw) < 5) { return false; } extract(unpack('Npacket_length/Cpadding_length', $this->_string_shift($raw, 5))); $remaining_length = $packet_length + 4 - $this->decrypt_block_size; if ($remaining_length < -$this->decrypt_block_size || $remaining_length > 0x9000 || $remaining_length % $this->decrypt_block_size != 0) { user_error('Invalid size'); return false; } $buffer = ''; while ($remaining_length > 0) { $temp = fread($this->fsock, $remaining_length); if ($temp === false || feof($this->fsock)) { user_error('Error reading from socket'); $this->bitmap = 0; return false; } $buffer.= $temp; $remaining_length-= strlen($temp); } $stop = strtok(microtime(), ' ') + strtok(''); if (strlen($buffer)) { $raw.= $this->decrypt !== false ? $this->decrypt->decrypt($buffer) : $buffer; } $payload = $this->_string_shift($raw, $packet_length - $padding_length - 1); $padding = $this->_string_shift($raw, $padding_length); if ($this->hmac_check !== false) { $hmac = fread($this->fsock, $this->hmac_size); if ($hmac === false || strlen($hmac) != $this->hmac_size) { user_error('Error reading socket'); $this->bitmap = 0; return false; } elseif ($hmac != $this->hmac_check->hash(pack('NNCa*', $this->get_seq_no, $packet_length, $padding_length, $payload . $padding))) { user_error('Invalid HMAC'); return false; } } $this->get_seq_no++; if (defined('NET_SSH2_LOGGING')) { $current = strtok(microtime(), ' ') + strtok(''); $message_number = isset($this->message_numbers[ord($payload[0])]) ? $this->message_numbers[ord($payload[0])] : 'UNKNOWN (' . ord($payload[0]) . ')'; $message_number = '<- ' . $message_number . ' (since last: ' . round($current - $this->last_packet, 4) . ', network: ' . round($stop - $start, 4) . 's)'; $this->_append_log($message_number, $payload); $this->last_packet = $current; } return $this->_filter($payload); } function _filter($payload) { switch (ord($payload[0])) { case NET_SSH2_MSG_DISCONNECT: $this->_string_shift($payload, 1); if (strlen($payload) < 8) { return false; } extract(unpack('Nreason_code/Nlength', $this->_string_shift($payload, 8))); $this->errors[] = 'SSH_MSG_DISCONNECT: ' . $this->disconnect_reasons[$reason_code] . "\r\n" . utf8_decode($this->_string_shift($payload, $length)); $this->bitmap = 0; return false; case NET_SSH2_MSG_IGNORE: $payload = $this->_get_binary_packet(); break; case NET_SSH2_MSG_DEBUG: $this->_string_shift($payload, 2); if (strlen($payload) < 4) { return false; } extract(unpack('Nlength', $this->_string_shift($payload, 4))); $this->errors[] = 'SSH_MSG_DEBUG: ' . utf8_decode($this->_string_shift($payload, $length)); $payload = $this->_get_binary_packet(); break; case NET_SSH2_MSG_UNIMPLEMENTED: return false; case NET_SSH2_MSG_KEXINIT: if ($this->session_id !== false) { if (!$this->_key_exchange($payload)) { $this->bitmap = 0; return false; } $payload = $this->_get_binary_packet(); } } if (($this->bitmap & NET_SSH2_MASK_CONNECTED) && !$this->isAuthenticated() && ord($payload[0]) == NET_SSH2_MSG_USERAUTH_BANNER) { $this->_string_shift($payload, 1); if (strlen($payload) < 4) { return false; } extract(unpack('Nlength', $this->_string_shift($payload, 4))); $this->banner_message = utf8_decode($this->_string_shift($payload, $length)); $payload = $this->_get_binary_packet(); } if (($this->bitmap & NET_SSH2_MASK_CONNECTED) && $this->isAuthenticated()) { switch (ord($payload[0])) { case NET_SSH2_MSG_GLOBAL_REQUEST: if (strlen($payload) < 4) { return false; } extract(unpack('Nlength', $this->_string_shift($payload, 4))); $this->errors[] = 'SSH_MSG_GLOBAL_REQUEST: ' . $this->_string_shift($payload, $length); if (!$this->_send_binary_packet(pack('C', NET_SSH2_MSG_REQUEST_FAILURE))) { return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION); } $payload = $this->_get_binary_packet(); break; case NET_SSH2_MSG_CHANNEL_OPEN: $this->_string_shift($payload, 1); if (strlen($payload) < 4) { return false; } extract(unpack('Nlength', $this->_string_shift($payload, 4))); $data = $this->_string_shift($payload, $length); if (strlen($payload) < 4) { return false; } extract(unpack('Nserver_channel', $this->_string_shift($payload, 4))); switch ($data) { case 'auth-agent': case 'auth-agent@openssh.com': if (isset($this->agent)) { $new_channel = NET_SSH2_CHANNEL_AGENT_FORWARD; if (strlen($payload) < 8) { return false; } extract(unpack('Nremote_window_size', $this->_string_shift($payload, 4))); extract(unpack('Nremote_maximum_packet_size', $this->_string_shift($payload, 4))); $this->packet_size_client_to_server[$new_channel] = $remote_window_size; $this->window_size_server_to_client[$new_channel] = $remote_maximum_packet_size; $this->window_size_client_to_server[$new_channel] = $this->window_size; $packet_size = 0x4000; $packet = pack( 'CN4', NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, $server_channel, $new_channel, $packet_size, $packet_size ); $this->server_channels[$new_channel] = $server_channel; $this->channel_status[$new_channel] = NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION; if (!$this->_send_binary_packet($packet)) { return false; } } break; default: $packet = pack( 'CN3a*Na*', NET_SSH2_MSG_REQUEST_FAILURE, $server_channel, NET_SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED, 0, '', 0, '' ); if (!$this->_send_binary_packet($packet)) { return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION); } } $payload = $this->_get_binary_packet(); break; case NET_SSH2_MSG_CHANNEL_WINDOW_ADJUST: $this->_string_shift($payload, 1); if (strlen($payload) < 8) { return false; } extract(unpack('Nchannel', $this->_string_shift($payload, 4))); extract(unpack('Nwindow_size', $this->_string_shift($payload, 4))); $this->window_size_client_to_server[$channel]+= $window_size; $payload = ($this->bitmap & NET_SSH2_MASK_WINDOW_ADJUST) ? true : $this->_get_binary_packet(); } } return $payload; } function enableQuietMode() { $this->quiet_mode = true; } function disableQuietMode() { $this->quiet_mode = false; } function isQuietModeEnabled() { return $this->quiet_mode; } function enablePTY() { $this->request_pty = true; } function disablePTY() { if ($this->in_request_pty_exec) { $this->_close_channel(NET_SSH2_CHANNEL_EXEC); $this->in_request_pty_exec = false; } $this->request_pty = false; } function isPTYEnabled() { return $this->request_pty; } function _get_channel_packet($client_channel, $skip_extended = false) { if (!empty($this->channel_buffers[$client_channel])) { return array_shift($this->channel_buffers[$client_channel]); } while (true) { if ($this->curTimeout) { if ($this->curTimeout < 0) { $this->is_timeout = true; return true; } $read = array($this->fsock); $write = $except = null; $start = strtok(microtime(), ' ') + strtok(''); $sec = floor($this->curTimeout); $usec = 1000000 * ($this->curTimeout - $sec); if (!@stream_select($read, $write, $except, $sec, $usec) && !count($read)) { $this->is_timeout = true; return true; } $elapsed = strtok(microtime(), ' ') + strtok('') - $start; $this->curTimeout-= $elapsed; } $response = $this->_get_binary_packet(); if ($response === false) { user_error('Connection closed by server'); return false; } if ($client_channel == -1 && $response === true) { return true; } if (!strlen($response)) { return ''; } if (!strlen($response)) { return false; } extract(unpack('Ctype', $this->_string_shift($response, 1))); if (strlen($response) < 4) { return false; } if ($type == NET_SSH2_MSG_CHANNEL_OPEN) { extract(unpack('Nlength', $this->_string_shift($response, 4))); } else { extract(unpack('Nchannel', $this->_string_shift($response, 4))); } if (isset($channel) && isset($this->channel_status[$channel]) && isset($this->window_size_server_to_client[$channel])) { $this->window_size_server_to_client[$channel]-= strlen($response); if ($this->window_size_server_to_client[$channel] < 0) { $packet = pack('CNN', NET_SSH2_MSG_CHANNEL_WINDOW_ADJUST, $this->server_channels[$channel], $this->window_size); if (!$this->_send_binary_packet($packet)) { return false; } $this->window_size_server_to_client[$channel]+= $this->window_size; } switch ($this->channel_status[$channel]) { case NET_SSH2_MSG_CHANNEL_OPEN: switch ($type) { case NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION: if (strlen($response) < 4) { return false; } extract(unpack('Nserver_channel', $this->_string_shift($response, 4))); $this->server_channels[$channel] = $server_channel; if (strlen($response) < 4) { return false; } extract(unpack('Nwindow_size', $this->_string_shift($response, 4))); if ($window_size < 0) { $window_size&= 0x7FFFFFFF; $window_size+= 0x80000000; } $this->window_size_client_to_server[$channel] = $window_size; if (strlen($response) < 4) { return false; } $temp = unpack('Npacket_size_client_to_server', $this->_string_shift($response, 4)); $this->packet_size_client_to_server[$channel] = $temp['packet_size_client_to_server']; $result = $client_channel == $channel ? true : $this->_get_channel_packet($client_channel, $skip_extended); $this->_on_channel_open(); return $result; default: user_error('Unable to open channel'); return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION); } break; case NET_SSH2_MSG_CHANNEL_REQUEST: switch ($type) { case NET_SSH2_MSG_CHANNEL_SUCCESS: return true; case NET_SSH2_MSG_CHANNEL_FAILURE: return false; default: user_error('Unable to fulfill channel request'); return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION); } case NET_SSH2_MSG_CHANNEL_CLOSE: return $type == NET_SSH2_MSG_CHANNEL_CLOSE ? true : $this->_get_channel_packet($client_channel, $skip_extended); } } switch ($type) { case NET_SSH2_MSG_CHANNEL_DATA: if (strlen($response) < 4) { return false; } extract(unpack('Nlength', $this->_string_shift($response, 4))); $data = $this->_string_shift($response, $length); if ($channel == NET_SSH2_CHANNEL_AGENT_FORWARD) { $agent_response = $this->agent->_forward_data($data); if (!is_bool($agent_response)) { $this->_send_channel_packet($channel, $agent_response); } break; } if ($client_channel == $channel) { return $data; } if (!isset($this->channel_buffers[$channel])) { $this->channel_buffers[$channel] = array(); } $this->channel_buffers[$channel][] = $data; break; case NET_SSH2_MSG_CHANNEL_EXTENDED_DATA: if (strlen($response) < 8) { return false; } extract(unpack('Ndata_type_code/Nlength', $this->_string_shift($response, 8))); $data = $this->_string_shift($response, $length); $this->stdErrorLog.= $data; if ($skip_extended || $this->quiet_mode) { break; } if ($client_channel == $channel) { return $data; } if (!isset($this->channel_buffers[$channel])) { $this->channel_buffers[$channel] = array(); } $this->channel_buffers[$channel][] = $data; break; case NET_SSH2_MSG_CHANNEL_REQUEST: if (strlen($response) < 4) { return false; } extract(unpack('Nlength', $this->_string_shift($response, 4))); $value = $this->_string_shift($response, $length); switch ($value) { case 'exit-signal': $this->_string_shift($response, 1); if (strlen($response) < 4) { return false; } extract(unpack('Nlength', $this->_string_shift($response, 4))); $this->errors[] = 'SSH_MSG_CHANNEL_REQUEST (exit-signal): ' . $this->_string_shift($response, $length); $this->_string_shift($response, 1); if (strlen($response) < 4) { return false; } extract(unpack('Nlength', $this->_string_shift($response, 4))); if ($length) { $this->errors[count($this->errors)].= "\r\n" . $this->_string_shift($response, $length); } $this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_EOF, $this->server_channels[$client_channel])); $this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$channel])); $this->channel_status[$channel] = NET_SSH2_MSG_CHANNEL_EOF; break; case 'exit-status': if (strlen($response) < 5) { return false; } extract(unpack('Cfalse/Nexit_status', $this->_string_shift($response, 5))); $this->exit_status = $exit_status; break; default: break; } break; case NET_SSH2_MSG_CHANNEL_CLOSE: $this->curTimeout = 0; if ($this->bitmap & NET_SSH2_MASK_SHELL) { $this->bitmap&= ~NET_SSH2_MASK_SHELL; } if ($this->channel_status[$channel] != NET_SSH2_MSG_CHANNEL_EOF) { $this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$channel])); } $this->channel_status[$channel] = NET_SSH2_MSG_CHANNEL_CLOSE; if ($client_channel == $channel) { return true; } case NET_SSH2_MSG_CHANNEL_EOF: break; default: user_error('Error reading channel data'); return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION); } } } function _send_binary_packet($data, $logged = null) { if (!is_resource($this->fsock) || feof($this->fsock)) { user_error('Connection closed prematurely'); $this->bitmap = 0; return false; } $packet_length = strlen($data) + 9; $packet_length+= (($this->encrypt_block_size - 1) * $packet_length) % $this->encrypt_block_size; $padding_length = $packet_length - strlen($data) - 5; $padding = crypt_random_string($padding_length); $packet = pack('NCa*', $packet_length - 4, $padding_length, $data . $padding); $hmac = $this->hmac_create !== false ? $this->hmac_create->hash(pack('Na*', $this->send_seq_no, $packet)) : ''; $this->send_seq_no++; if ($this->encrypt !== false) { $packet = $this->encrypt->encrypt($packet); } $packet.= $hmac; $start = strtok(microtime(), ' ') + strtok(''); $result = strlen($packet) == fputs($this->fsock, $packet); $stop = strtok(microtime(), ' ') + strtok(''); if (defined('NET_SSH2_LOGGING')) { $current = strtok(microtime(), ' ') + strtok(''); $message_number = isset($this->message_numbers[ord($data[0])]) ? $this->message_numbers[ord($data[0])] : 'UNKNOWN (' . ord($data[0]) . ')'; $message_number = '-> ' . $message_number . ' (since last: ' . round($current - $this->last_packet, 4) . ', network: ' . round($stop - $start, 4) . 's)'; $this->_append_log($message_number, isset($logged) ? $logged : $data); $this->last_packet = $current; } return $result; } function _append_log($message_number, $message) { if (strlen($message_number) > 2) { $this->_string_shift($message); } switch (NET_SSH2_LOGGING) { case NET_SSH2_LOG_SIMPLE: $this->message_number_log[] = $message_number; break; case NET_SSH2_LOG_COMPLEX: $this->message_number_log[] = $message_number; $this->log_size+= strlen($message); $this->message_log[] = $message; while ($this->log_size > NET_SSH2_LOG_MAX_SIZE) { $this->log_size-= strlen(array_shift($this->message_log)); array_shift($this->message_number_log); } break; case NET_SSH2_LOG_REALTIME: switch (PHP_SAPI) { case 'cli': $start = $stop = "\r\n"; break; default: $start = '<pre>'; $stop = '</pre>'; } echo $start . $this->_format_log(array($message), array($message_number)) . $stop; @flush(); @ob_flush(); break; case NET_SSH2_LOG_REALTIME_FILE: if (!isset($this->realtime_log_file)) { $filename = NET_SSH2_LOG_REALTIME_FILENAME; $fp = fopen($filename, 'w'); $this->realtime_log_file = $fp; } if (!is_resource($this->realtime_log_file)) { break; } $entry = $this->_format_log(array($message), array($message_number)); if ($this->realtime_log_wrap) { $temp = "<<< START >>>\r\n"; $entry.= $temp; fseek($this->realtime_log_file, ftell($this->realtime_log_file) - strlen($temp)); } $this->realtime_log_size+= strlen($entry); if ($this->realtime_log_size > NET_SSH2_LOG_MAX_SIZE) { fseek($this->realtime_log_file, 0); $this->realtime_log_size = strlen($entry); $this->realtime_log_wrap = true; } fputs($this->realtime_log_file, $entry); } } function _send_channel_packet($client_channel, $data) { while (strlen($data)) { if (!$this->window_size_client_to_server[$client_channel]) { $this->bitmap^= NET_SSH2_MASK_WINDOW_ADJUST; $this->_get_channel_packet(-1); $this->bitmap^= NET_SSH2_MASK_WINDOW_ADJUST; } $max_size = min( $this->packet_size_client_to_server[$client_channel], $this->window_size_client_to_server[$client_channel] ); $temp = $this->_string_shift($data, $max_size); $packet = pack( 'CN2a*', NET_SSH2_MSG_CHANNEL_DATA, $this->server_channels[$client_channel], strlen($temp), $temp ); $this->window_size_client_to_server[$client_channel]-= strlen($temp); if (!$this->_send_binary_packet($packet)) { return false; } } return true; } function _close_channel($client_channel, $want_reply = false) { $this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_EOF, $this->server_channels[$client_channel])); if (!$want_reply) { $this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$client_channel])); } $this->channel_status[$client_channel] = NET_SSH2_MSG_CHANNEL_CLOSE; $this->curTimeout = 0; while (!is_bool($this->_get_channel_packet($client_channel))) { } if ($want_reply) { $this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$client_channel])); } if ($this->bitmap & NET_SSH2_MASK_SHELL) { $this->bitmap&= ~NET_SSH2_MASK_SHELL; } } function _disconnect($reason) { if ($this->bitmap & NET_SSH2_MASK_CONNECTED) { $data = pack('CNNa*Na*', NET_SSH2_MSG_DISCONNECT, $reason, 0, '', 0, ''); $this->_send_binary_packet($data); $this->bitmap = 0; fclose($this->fsock); return false; } } function _string_shift(&$string, $index = 1) { $substr = substr($string, 0, $index); $string = substr($string, $index); return $substr; } function _define_array() { $args = func_get_args(); foreach ($args as $arg) { foreach ($arg as $key => $value) { if (!defined($value)) { define($value, $key); } else { break 2; } } } } function getLog() { if (!defined('NET_SSH2_LOGGING')) { return false; } switch (NET_SSH2_LOGGING) { case NET_SSH2_LOG_SIMPLE: return $this->message_number_log; case NET_SSH2_LOG_COMPLEX: $log = $this->_format_log($this->message_log, $this->message_number_log); return PHP_SAPI == 'cli' ? $log : '<pre>' . $log . '</pre>'; default: return false; } } function _format_log($message_log, $message_number_log) { $output = ''; for ($i = 0; $i < count($message_log); $i++) { $output.= $message_number_log[$i] . "\r\n"; $current_log = $message_log[$i]; $j = 0; do { if (strlen($current_log)) { $output.= str_pad(dechex($j), 7, '0', STR_PAD_LEFT) . '0  '; } $fragment = $this->_string_shift($current_log, $this->log_short_width); $hex = substr(preg_replace_callback('#.#s', array($this, '_format_log_helper'), $fragment), strlen($this->log_boundary)); $raw = preg_replace('#[^\x20-\x7E]|<#', '.', $fragment); $output.= str_pad($hex, $this->log_long_width - $this->log_short_width, ' ') . $raw . "\r\n"; $j++; } while (strlen($current_log)); $output.= "\r\n"; } return $output; } function _format_log_helper($matches) { return $this->log_boundary . str_pad(dechex(ord($matches[0])), 2, '0', STR_PAD_LEFT); } function _on_channel_open() { if (isset($this->agent)) { $this->agent->_on_channel_open($this); } } function _array_intersect_first($array1, $array2) { foreach ($array1 as $value) { if (in_array($value, $array2)) { return $value; } } return false; } function getErrors() { return $this->errors; } function getLastError() { $count = count($this->errors); if ($count > 0) { return $this->errors[$count - 1]; } } function getServerIdentification() { $this->_connect(); return $this->server_identifier; } function getKexAlgorithms() { $this->_connect(); return $this->kex_algorithms; } function getServerHostKeyAlgorithms() { $this->_connect(); return $this->server_host_key_algorithms; } function getEncryptionAlgorithmsClient2Server() { $this->_connect(); return $this->encryption_algorithms_client_to_server; } function getEncryptionAlgorithmsServer2Client() { $this->_connect(); return $this->encryption_algorithms_server_to_client; } function getMACAlgorithmsClient2Server() { $this->_connect(); return $this->mac_algorithms_client_to_server; } function getMACAlgorithmsServer2Client() { $this->_connect(); return $this->mac_algorithms_server_to_client; } function getCompressionAlgorithmsClient2Server() { $this->_connect(); return $this->compression_algorithms_client_to_server; } function getCompressionAlgorithmsServer2Client() { $this->_connect(); return $this->compression_algorithms_server_to_client; } function getLanguagesServer2Client() { $this->_connect(); return $this->languages_server_to_client; } function getLanguagesClient2Server() { $this->_connect(); return $this->languages_client_to_server; } function getBannerMessage() { return $this->banner_message; } function getServerPublicHostKey() { if (!($this->bitmap & NET_SSH2_MASK_CONSTRUCTOR)) { if (!$this->_connect()) { return false; } } $signature = $this->signature; $server_public_host_key = $this->server_public_host_key; if (strlen($server_public_host_key) < 4) { return false; } extract(unpack('Nlength', $this->_string_shift($server_public_host_key, 4))); $this->_string_shift($server_public_host_key, $length); if ($this->signature_validated) { return $this->bitmap ? $this->signature_format . ' ' . base64_encode($this->server_public_host_key) : false; } $this->signature_validated = true; switch ($this->signature_format) { case 'ssh-dss': $zero = new Math_BigInteger(); if (strlen($server_public_host_key) < 4) { return false; } $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4)); $p = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256); if (strlen($server_public_host_key) < 4) { return false; } $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4)); $q = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256); if (strlen($server_public_host_key) < 4) { return false; } $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4)); $g = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256); if (strlen($server_public_host_key) < 4) { return false; } $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4)); $y = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256); $temp = unpack('Nlength', $this->_string_shift($signature, 4)); if ($temp['length'] != 40) { user_error('Invalid signature'); return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); } $r = new Math_BigInteger($this->_string_shift($signature, 20), 256); $s = new Math_BigInteger($this->_string_shift($signature, 20), 256); switch (true) { case $r->equals($zero): case $r->compare($q) >= 0: case $s->equals($zero): case $s->compare($q) >= 0: user_error('Invalid signature'); return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); } $w = $s->modInverse($q); $u1 = $w->multiply(new Math_BigInteger(sha1($this->exchange_hash), 16)); list(, $u1) = $u1->divide($q); $u2 = $w->multiply($r); list(, $u2) = $u2->divide($q); $g = $g->modPow($u1, $p); $y = $y->modPow($u2, $p); $v = $g->multiply($y); list(, $v) = $v->divide($p); list(, $v) = $v->divide($q); if (!$v->equals($r)) { user_error('Bad server signature'); return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE); } break; case 'ssh-rsa': if (strlen($server_public_host_key) < 4) { return false; } $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4)); $e = new Math_BigInteger($this->_string_shift($server_public_host_key, $temp['length']), -256); if (strlen($server_public_host_key) < 4) { return false; } $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4)); $rawN = $this->_string_shift($server_public_host_key, $temp['length']); $n = new Math_BigInteger($rawN, -256); $nLength = strlen(ltrim($rawN, "\0")); if (strlen($signature) < 4) { return false; } $temp = unpack('Nlength', $this->_string_shift($signature, 4)); $s = new Math_BigInteger($this->_string_shift($signature, $temp['length']), 256); if ($s->compare(new Math_BigInteger()) < 0 || $s->compare($n->subtract(new Math_BigInteger(1))) > 0) { user_error('Invalid signature'); return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); } $s = $s->modPow($e, $n); $s = $s->toBytes(); $h = pack('N4H*', 0x00302130, 0x0906052B, 0x0E03021A, 0x05000414, sha1($this->exchange_hash)); $h = chr(0x01) . str_repeat(chr(0xFF), $nLength - 2 - strlen($h)) . $h; if ($s != $h) { user_error('Bad server signature'); return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE); } break; default: user_error('Unsupported signature format'); return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE); } return $this->signature_format . ' ' . base64_encode($this->server_public_host_key); } function getExitStatus() { if (is_null($this->exit_status)) { return false; } return $this->exit_status; } function getWindowColumns() { return $this->windowColumns; } function getWindowRows() { return $this->windowRows; } function setWindowColumns($value) { $this->windowColumns = $value; } function setWindowRows($value) { $this->windowRows = $value; } function setWindowSize($columns = 80, $rows = 24) { $this->windowColumns = $columns; $this->windowRows = $rows; } } } if (!class_exists('Net_SFTP')) { if (!class_exists('Net_SSH2')) { include_once 'SSH2.php'; } define('NET_SFTP_LOG_SIMPLE', NET_SSH2_LOG_SIMPLE); define('NET_SFTP_LOG_COMPLEX', NET_SSH2_LOG_COMPLEX); define('NET_SFTP_LOG_REALTIME', 3); define('NET_SFTP_CHANNEL', 0x100); define('NET_SFTP_LOCAL_FILE', 1); define('NET_SFTP_STRING', 2); define('NET_SFTP_CALLBACK', 16); define('NET_SFTP_RESUME', 4); define('NET_SFTP_RESUME_START', 8); class Net_SFTP extends Net_SSH2 { var $packet_types = array(); var $status_codes = array(); var $request_id = false; var $packet_type = -1; var $packet_buffer = ''; var $extensions = array(); var $version; var $pwd = false; var $packet_type_log = array(); var $packet_log = array(); var $sftp_errors = array(); var $stat_cache = array(); var $max_sftp_packet; var $use_stat_cache = true; var $sortOptions = array(); function __construct($host, $port = 22, $timeout = 10) { parent::__construct($host, $port, $timeout); $this->max_sftp_packet = 1 << 15; $this->packet_types = array( 1 => 'NET_SFTP_INIT', 2 => 'NET_SFTP_VERSION', 3 => 'NET_SFTP_OPEN', 4 => 'NET_SFTP_CLOSE', 5 => 'NET_SFTP_READ', 6 => 'NET_SFTP_WRITE', 7 => 'NET_SFTP_LSTAT', 9 => 'NET_SFTP_SETSTAT', 11 => 'NET_SFTP_OPENDIR', 12 => 'NET_SFTP_READDIR', 13 => 'NET_SFTP_REMOVE', 14 => 'NET_SFTP_MKDIR', 15 => 'NET_SFTP_RMDIR', 16 => 'NET_SFTP_REALPATH', 17 => 'NET_SFTP_STAT', 18 => 'NET_SFTP_RENAME', 19 => 'NET_SFTP_READLINK', 20 => 'NET_SFTP_SYMLINK', 101=> 'NET_SFTP_STATUS', 102=> 'NET_SFTP_HANDLE', 103=> 'NET_SFTP_DATA', 104=> 'NET_SFTP_NAME', 105=> 'NET_SFTP_ATTRS', 200=> 'NET_SFTP_EXTENDED' ); $this->status_codes = array( 0 => 'NET_SFTP_STATUS_OK', 1 => 'NET_SFTP_STATUS_EOF', 2 => 'NET_SFTP_STATUS_NO_SUCH_FILE', 3 => 'NET_SFTP_STATUS_PERMISSION_DENIED', 4 => 'NET_SFTP_STATUS_FAILURE', 5 => 'NET_SFTP_STATUS_BAD_MESSAGE', 6 => 'NET_SFTP_STATUS_NO_CONNECTION', 7 => 'NET_SFTP_STATUS_CONNECTION_LOST', 8 => 'NET_SFTP_STATUS_OP_UNSUPPORTED', 9 => 'NET_SFTP_STATUS_INVALID_HANDLE', 10 => 'NET_SFTP_STATUS_NO_SUCH_PATH', 11 => 'NET_SFTP_STATUS_FILE_ALREADY_EXISTS', 12 => 'NET_SFTP_STATUS_WRITE_PROTECT', 13 => 'NET_SFTP_STATUS_NO_MEDIA', 14 => 'NET_SFTP_STATUS_NO_SPACE_ON_FILESYSTEM', 15 => 'NET_SFTP_STATUS_QUOTA_EXCEEDED', 16 => 'NET_SFTP_STATUS_UNKNOWN_PRINCIPAL', 17 => 'NET_SFTP_STATUS_LOCK_CONFLICT', 18 => 'NET_SFTP_STATUS_DIR_NOT_EMPTY', 19 => 'NET_SFTP_STATUS_NOT_A_DIRECTORY', 20 => 'NET_SFTP_STATUS_INVALID_FILENAME', 21 => 'NET_SFTP_STATUS_LINK_LOOP', 22 => 'NET_SFTP_STATUS_CANNOT_DELETE', 23 => 'NET_SFTP_STATUS_INVALID_PARAMETER', 24 => 'NET_SFTP_STATUS_FILE_IS_A_DIRECTORY', 25 => 'NET_SFTP_STATUS_BYTE_RANGE_LOCK_CONFLICT', 26 => 'NET_SFTP_STATUS_BYTE_RANGE_LOCK_REFUSED', 27 => 'NET_SFTP_STATUS_DELETE_PENDING', 28 => 'NET_SFTP_STATUS_FILE_CORRUPT', 29 => 'NET_SFTP_STATUS_OWNER_INVALID', 30 => 'NET_SFTP_STATUS_GROUP_INVALID', 31 => 'NET_SFTP_STATUS_NO_MATCHING_BYTE_RANGE_LOCK' ); $this->attributes = array( 0x00000001 => 'NET_SFTP_ATTR_SIZE', 0x00000002 => 'NET_SFTP_ATTR_UIDGID', 0x00000004 => 'NET_SFTP_ATTR_PERMISSIONS', 0x00000008 => 'NET_SFTP_ATTR_ACCESSTIME', -1 << 31 => 'NET_SFTP_ATTR_EXTENDED' ); $this->open_flags = array( 0x00000001 => 'NET_SFTP_OPEN_READ', 0x00000002 => 'NET_SFTP_OPEN_WRITE', 0x00000004 => 'NET_SFTP_OPEN_APPEND', 0x00000008 => 'NET_SFTP_OPEN_CREATE', 0x00000010 => 'NET_SFTP_OPEN_TRUNCATE', 0x00000020 => 'NET_SFTP_OPEN_EXCL' ); $this->file_types = array( 1 => 'NET_SFTP_TYPE_REGULAR', 2 => 'NET_SFTP_TYPE_DIRECTORY', 3 => 'NET_SFTP_TYPE_SYMLINK', 4 => 'NET_SFTP_TYPE_SPECIAL', 5 => 'NET_SFTP_TYPE_UNKNOWN', 6 => 'NET_SFTP_TYPE_SOCKET', 7 => 'NET_SFTP_TYPE_CHAR_DEVICE', 8 => 'NET_SFTP_TYPE_BLOCK_DEVICE', 9 => 'NET_SFTP_TYPE_FIFO' ); $this->_define_array( $this->packet_types, $this->status_codes, $this->attributes, $this->open_flags, $this->file_types ); if (!defined('NET_SFTP_QUEUE_SIZE')) { define('NET_SFTP_QUEUE_SIZE', 32); } } function Net_SFTP($host, $port = 22, $timeout = 10) { $this->__construct($host, $port, $timeout); } function login($username) { $args = func_get_args(); if (!call_user_func_array(array(&$this, '_login'), $args)) { return false; } $this->window_size_server_to_client[NET_SFTP_CHANNEL] = $this->window_size; $packet = pack( 'CNa*N3', NET_SSH2_MSG_CHANNEL_OPEN, strlen('session'), 'session', NET_SFTP_CHANNEL, $this->window_size, 0x4000 ); if (!$this->_send_binary_packet($packet)) { return false; } $this->channel_status[NET_SFTP_CHANNEL] = NET_SSH2_MSG_CHANNEL_OPEN; $response = $this->_get_channel_packet(NET_SFTP_CHANNEL); if ($response === false) { return false; } $packet = pack( 'CNNa*CNa*', NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[NET_SFTP_CHANNEL], strlen('subsystem'), 'subsystem', 1, strlen('sftp'), 'sftp' ); if (!$this->_send_binary_packet($packet)) { return false; } $this->channel_status[NET_SFTP_CHANNEL] = NET_SSH2_MSG_CHANNEL_REQUEST; $response = $this->_get_channel_packet(NET_SFTP_CHANNEL); if ($response === false) { $command = "test -x /usr/lib/sftp-server && exec /usr/lib/sftp-server\n" . "test -x /usr/local/lib/sftp-server && exec /usr/local/lib/sftp-server\n" . "exec sftp-server"; $packet = pack( 'CNNa*CNa*', NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[NET_SFTP_CHANNEL], strlen('exec'), 'exec', 1, strlen($command), $command ); if (!$this->_send_binary_packet($packet)) { return false; } $this->channel_status[NET_SFTP_CHANNEL] = NET_SSH2_MSG_CHANNEL_REQUEST; $response = $this->_get_channel_packet(NET_SFTP_CHANNEL); if ($response === false) { return false; } } $this->channel_status[NET_SFTP_CHANNEL] = NET_SSH2_MSG_CHANNEL_DATA; if (!$this->_send_sftp_packet(NET_SFTP_INIT, "\0\0\0\3")) { return false; } $response = $this->_get_sftp_packet(); if ($this->packet_type != NET_SFTP_VERSION) { user_error('Expected SSH_FXP_VERSION'); return false; } if (strlen($response) < 4) { return false; } extract(unpack('Nversion', $this->_string_shift($response, 4))); $this->version = $version; while (!empty($response)) { if (strlen($response) < 4) { return false; } extract(unpack('Nlength', $this->_string_shift($response, 4))); $key = $this->_string_shift($response, $length); if (strlen($response) < 4) { return false; } extract(unpack('Nlength', $this->_string_shift($response, 4))); $value = $this->_string_shift($response, $length); $this->extensions[$key] = $value; } $this->request_id = 1; switch ($this->version) { case 2: case 3: break; default: return false; } $this->pwd = $this->_realpath('.'); $this->_update_stat_cache($this->pwd, array()); return true; } function disableStatCache() { $this->use_stat_cache = false; } function enableStatCache() { $this->use_stat_cache = true; } function clearStatCache() { $this->stat_cache = array(); } function pwd() { return $this->pwd; } function _logError($response, $status = -1) { if ($status == -1) { if (strlen($response) < 4) { return; } extract(unpack('Nstatus', $this->_string_shift($response, 4))); } $error = $this->status_codes[$status]; if ($this->version > 2 || strlen($response) < 4) { extract(unpack('Nlength', $this->_string_shift($response, 4))); $this->sftp_errors[] = $error . ': ' . $this->_string_shift($response, $length); } else { $this->sftp_errors[] = $error; } } function realpath($path) { return $this->_realpath($path); } function _realpath($path) { if ($this->pwd === false) { if (!$this->_send_sftp_packet(NET_SFTP_REALPATH, pack('Na*', strlen($path), $path))) { return false; } $response = $this->_get_sftp_packet(); switch ($this->packet_type) { case NET_SFTP_NAME: $this->_string_shift($response, 4); if (strlen($response) < 4) { return false; } extract(unpack('Nlength', $this->_string_shift($response, 4))); return $this->_string_shift($response, $length); case NET_SFTP_STATUS: $this->_logError($response); return false; default: user_error('Expected SSH_FXP_NAME or SSH_FXP_STATUS'); return false; } } if ($path[0] != '/') { $path = $this->pwd . '/' . $path; } $path = explode('/', $path); $new = array(); foreach ($path as $dir) { if (!strlen($dir)) { continue; } switch ($dir) { case '..': array_pop($new); case '.': break; default: $new[] = $dir; } } return '/' . implode('/', $new); } function chdir($dir) { if (!($this->bitmap & NET_SSH2_MASK_LOGIN)) { return false; } if ($dir === '') { $dir = './'; } elseif ($dir[strlen($dir) - 1] != '/') { $dir.= '/'; } $dir = $this->_realpath($dir); if ($this->use_stat_cache && is_array($this->_query_stat_cache($dir))) { $this->pwd = $dir; return true; } if (!$this->_send_sftp_pack