├── bin ├── index.php ├── php_root ├── start_suricata ├── suricata-update.cron ├── start_ips ├── suricataips.sh ├── suricata2mikrotik.sh ├── daemon_ips_clean.php ├── daemon_ips_hunter.php └── daemon_ips_process.php ├── share ├── index.php ├── ssh │ ├── openssl.cnf │ ├── Net │ │ ├── SCP.php │ │ └── SFTP │ │ │ └── Stream.php │ ├── Crypt │ │ ├── Random.php │ │ ├── RC4.php │ │ ├── AES.php │ │ └── Hash.php │ └── File │ │ └── ANSI.php ├── sshkey.pub ├── routeros_api.php └── functions.php ├── www ├── favicon.ico ├── sql.php └── a.css ├── index.php ├── README.md ├── config.php ├── schema.sql └── LICENSE /bin/index.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /share/index.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /www/favicon.ico: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /www/sql.php: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elmaxid/Suricata2MikroTik/HEAD/www/sql.php -------------------------------------------------------------------------------- /bin/php_root: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elmaxid/Suricata2MikroTik/HEAD/bin/php_root -------------------------------------------------------------------------------- /share/ssh/openssl.cnf: -------------------------------------------------------------------------------- 1 | # minimalist openssl.cnf file for use with phpseclib 2 | 3 | HOME = . 4 | RANDFILE = $ENV::HOME/.rnd 5 | 6 | [ v3_ca ] -------------------------------------------------------------------------------- /bin/start_suricata: -------------------------------------------------------------------------------- 1 | /usr/local/bin/trafr -s | /usr/bin/suricata -c /etc/suricata/suricata.yaml --pidfile /var/run/suricata.pid -r /dev/stdin & 2 | 3 | 4 | -------------------------------------------------------------------------------- /bin/suricata-update.cron: -------------------------------------------------------------------------------- 1 | #suricata-update --reload-command "service suricataips restart" -v -f 2 | suricata-update --reload-command "service suricataips restart" -v 3 | 4 | -------------------------------------------------------------------------------- /bin/start_ips: -------------------------------------------------------------------------------- 1 | cd /var/www/html/suricata2mikrotik/ 2 | php bin/daemon_ips_hunter.php & 3 | sleep 1; 4 | php bin/daemon_ips_process.php & 5 | sleep 1; 6 | php bin/daemon_ips_clean.php & 7 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | 21 | -------------------------------------------------------------------------------- /share/sshkey.pub: -------------------------------------------------------------------------------- 1 | ssh-dss AAAAB3NzaC1kc3MAAACBAMoArDGl13YOaykala8/zQoZzzTjpMK/+nQebfx/A9QGmNM1ug0Fnz3vl89Dt7CgQsqLJSk4OevRuHA+8IcOJqx2PeJF2eUyzNJlMIPFM1+NgPayhWxCLWfISuzPmpTHc6TSnrQnnUn48ef3c4gq8OzkdY4kq7ng8w+5Y3gFmvZTAAAAFQCyIRcsx/HtqvkWy9WeITopxyuPlwAAAIB36O6ltmqIDKYkoJdn/o0fwf5wId+uMRQxaRclfg6dSCM4AZHAT1tEtzQ1LjYWCCParU2nVCjZny0lfye9WbxeCIC7+8NL+3DyStXq/ES4NHmwmNnD6IUZ/xleUbIvEo4PwNRmQgAb2nCuQBvN77q/2aR5xmRhDB1LmOa9P79vOQAAAIAvkikNBNeHkimRk6XP3tydizh3wS2ikttowo+NXeVdhLbCZigIxZnhjkrXXoDehXiLs8leQqhFjR3K9ppmzvgoto9YHn3PE05HspH1/YYobEO+wKdnlx2G5gx1NAm8scpIoj56nTeKyNT++zPe/CrdhQNd15vi40g5FqMw7XNJAw== root@OraculoV2 2 | -------------------------------------------------------------------------------- /bin/suricataips.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | ### BEGIN INIT INFO 4 | # Provides: suricataips 5 | # Required-Start: $all 6 | # Required-Stop: $local_fs 7 | # Default-Start: 2 3 4 5 8 | # Default-Stop: 0 1 6 9 | # Short-Description: Suricata service 10 | # Description: Run Suricata service sudo -u Suricata-user 11 | ### END INIT INFO 12 | 13 | # Carry out specific functions when asked to by the system 14 | case "$1" in 15 | start) 16 | echo "Starting Suricata..." 17 | # bash -c 'cd /var/www/html/suricata2ips/bin/ && ./start-Suricata.sh' 18 | bash -c 'cd /usr/local/bin/ && start_suricata' 19 | ;; 20 | stop) 21 | echo "Stopping Suricata..." 22 | # bash -c 'cd /var/www/html/suricata2ips/bin/ && ./stop-Suricata.sh' 23 | bash -c 'pkill trafr' 24 | sleep 2 25 | ;; 26 | restart) 27 | $0 stop 28 | sleep 5 29 | $0 start 30 | ;; 31 | 32 | *) 33 | echo "Usage: /etc/init.d/suricataips {start|stop|restart}" 34 | exit 1 35 | ;; 36 | esac 37 | 38 | exit 0 -------------------------------------------------------------------------------- /bin/suricata2mikrotik.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | ### BEGIN INIT INFO 4 | # Provides: suricata2mikrotik 5 | # Required-Start: $remote_fs $syslog 6 | # Required-Stop: $local_fs 7 | # Default-Start: 2 3 4 5 8 | # Default-Stop: 0 1 6 9 | # Short-Description: Suricata service 10 | # Description: Run Suricata service sudo -u Suricata-user 11 | ### END INIT INFO 12 | 13 | # Carry out specific functions when asked to by the system 14 | case "$1" in 15 | start) 16 | echo "Starting Suricata2MikroTik..." 17 | # bash -c 'cd /var/www/html/suricata2ips/bin/ && ./start-Suricata.sh' 18 | bash -c 'cd /usr/local/bin/ && start_ips' 19 | ;; 20 | stop) 21 | echo "Stopping Suricata2MikroTik..." 22 | # bash -c 'cd /var/www/html/suricata2ips/bin/ && ./stop-Suricata.sh' 23 | bash -c 'rm /tmp/suricata2mikrotik.pid ' 24 | sleep 2 25 | ;; 26 | restart) 27 | $0 stop 28 | sleep 11 29 | $0 start 30 | ;; 31 | 32 | *) 33 | echo "Usage: /etc/init.d/suricata2mikrotik {start|stop|restart}" 34 | exit 1 35 | ;; 36 | esac 37 | 38 | exit 0 -------------------------------------------------------------------------------- /bin/daemon_ips_clean.php: -------------------------------------------------------------------------------- 1 | query( $SQL ) ) { 39 | die( 'There was an error running the query [' . $connect->error . ']' ); 40 | } //!$result = $connect->query( $SQL ) 41 | mysqli_free_result( $result ); 42 | sleep( 10 ); 43 | /* Sleep 10 seconds then do again */ 44 | mysqli_ping( $connect ); 45 | } //file_exists( $PID_app_file ) 46 | echo "Shutdown services Clean DB\n"; 47 | unlink( $cfg[PID_app_file] ); 48 | $connect->close(); 49 | ?> -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Suricata2MikroTik 2 | 3 | Module for Suricata to read eve.json file and looking for specified alerts. If found it, then connect to router MikroTik via API and block the Attack with Firewall. 4 | 5 | This is similar like ips-mikrotik-suricata but works with eve.json and not with barnyard2. https://github.com/elmaxid/ips-mikrotik-suricata 6 | 7 | 8 | Changelog: 9 | 18 February 19: v1.1: Add SSH Support 10 | 31 October 18: v1.0 11 | 12 | * Init version 13 | 14 | 15 | Requeriment: 16 | 17 | * Suricata 18 | * IP and login for router MikroTik RouterOS 19 | * GIT 20 | 21 | ** Features 22 | 23 | * Detect an Alert from Suricata and connect to RouterOS to block de Attack source IP Address 24 | * Notification: 25 | * Email 26 | * Telegram (API Bot) 27 | 28 | Instalation 29 | 30 | Once we have Suricata working and running on our network, the next step is the instalation of Suricata2MikroTik: 31 | 32 | To install, Clone the repository and copy to /var/www/html/suricata2mikrotik 33 | 34 | cd /var/www/html/ 35 | 36 | git clone https://github.com/elmaxid/Suricata2MikroTik 37 | 38 | cd suricata2mikrotik 39 | 40 | -- to Config 41 | 42 | * Edit the file config.php with DB and API Logins 43 | 44 | * Create the DB schema 45 | 46 | mysql -u username -p < schema.sql 47 | 48 | * Copy start_ips and start_suricata to /usr/local/bin 49 | 50 | * Give permisions 51 | chmod +x /usr/local/bin/start* 52 | 53 | 54 | ---- 55 | 56 | How work it 57 | 58 | For run Suricata, you need to redirect the traffic from MikroTik RouterOS to Suricata server, to do it just use Packet Sniffer or Mangle Send To TZSP Action. -------------------------------------------------------------------------------- /config.php: -------------------------------------------------------------------------------- 1 | 0=yes)', 23 | `json_raw` longtext COLLATE utf8_unicode_ci, 24 | PRIMARY KEY (`que_id`), 25 | KEY `que_added` (`que_added`) 26 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='Queue of ip addresses to block on firewall'; 27 | 28 | 29 | DROP TABLE IF EXISTS `sigs_to_block`; 30 | CREATE TABLE `sigs_to_block` ( 31 | `sig_name` text COLLATE utf8_unicode_ci NOT NULL, 32 | `src_or_dst` char(3) COLLATE utf8_unicode_ci NOT NULL DEFAULT 'src', 33 | `timeout` varchar(12) COLLATE utf8_unicode_ci NOT NULL DEFAULT '01:00:00', 34 | `active` int(1) NOT NULL DEFAULT '1', 35 | `id` int(1) NOT NULL AUTO_INCREMENT, 36 | PRIMARY KEY (`id`), 37 | UNIQUE KEY `sig_name_unique_index` (`sig_name`(64)) 38 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 39 | 40 | INSERT INTO `sigs_to_block` (`sig_name`, `src_or_dst`, `timeout`, `active`, `id`) VALUES 41 | ('ET COMPROMISED Known Compromised or Hostile Host Traffic', 'src', '01:00:00', 1, 1), 42 | ('ET POLICY Suspicious inbound to', 'src', '01:00:00', 1, 2), 43 | ('ET DROP Dshield Block Listed Source', 'src', '01:00:00', 1, 3), 44 | ('ET SCAN Sipvicious Scan', 'src', '01:00:00', 1, 4), 45 | ('ET SCAN Sipvicious User-Agent Detected (friendly-scanner)', 'src', '01:00:00', 1, 5), 46 | ('ET DROP Spamhaus DROP Listed Traffic Inbound', 'src', '01:00:00', 1, 6), 47 | ('ET POLICY Outgoing Basic Auth Base64 HTTP Password detected unencrypted', 'dst', '23:59:59', 1, 7), 48 | ('ET CINS Active Threat Intelligence Poor Reputation IP', 'src', '01:00:00', 1, 8), 49 | ('GPL SNMP public access udp', 'src', '01:00:00', 1, 9), 50 | ('ET TOR Known Tor Relay/Router (Not Exit) Node Traffic', 'src', '01:00:00', 1, 10), 51 | ('GPL DNS named version attempt', 'src', '01:00:00', 1, 11), 52 | ('ET VOIP Modified Sipvicious Asterisk PBX User-Agent', 'src', '01:00:00', 1, 12), 53 | ('GPL RPC xdmcp info query', 'src', '01:00:00', 1, 13), 54 | ('GPL RPC portmap listing UDP 111', 'src', '01:00:00', 1, 14), 55 | ('GPL ATTACK_RESPONSE id check returned root', 'src', '00:01:10', 1, 15), 56 | ('ET VOIP Multiple Unauthorized SIP Responses UDP', 'dst', '00:59:59', 1, 16), 57 | ('ET SCAN Behavioral Unusually fast Terminal Server Traffic, Potential Scan or Infection (Inbound)', 'src', '00:10:00', 1, 18), 58 | ('ET DOS Possible NTP DDoS Inbound Frequent', 'src', '00:10:00', 1, 19), 59 | ('ET SCAN SipCLI VOIP Scan', 'src', '01:00:00', 1, 20), 60 | ('ET POLICY GNU/Linux APT', 'src', '01:00:00', 1, 21), 61 | ('ATTACK [PTsecurity]', 'src', '01:00:00', 1, 22), 62 | ('ETN AGGRESSIVE IPs', 'src', '01:00:00', 1, 25); 63 | 64 | -- 2018-10-31 21:57:40 -------------------------------------------------------------------------------- /www/a.css: -------------------------------------------------------------------------------- 1 | .colorgraph { 2 | height: 5px; 3 | border-top: 0; 4 | background: #c4e17f; 5 | border-radius: 5px; 6 | background-image: -webkit-linear-gradient(left, #c4e17f, #c4e17f 12.5%, #f7fdca 12.5%, #f7fdca 25%, #fecf71 25%, #fecf71 37.5%, #f0776c 37.5%, #f0776c 50%, #db9dbe 50%, #db9dbe 62.5%, #c49cde 62.5%, #c49cde 75%, #669ae1 75%, #669ae1 87.5%, #62c2e4 87.5%, #62c2e4); 7 | background-image: -moz-linear-gradient(left, #c4e17f, #c4e17f 12.5%, #f7fdca 12.5%, #f7fdca 25%, #fecf71 25%, #fecf71 37.5%, #f0776c 37.5%, #f0776c 50%, #db9dbe 50%, #db9dbe 62.5%, #c49cde 62.5%, #c49cde 75%, #669ae1 75%, #669ae1 87.5%, #62c2e4 87.5%, #62c2e4); 8 | background-image: -o-linear-gradient(left, #c4e17f, #c4e17f 12.5%, #f7fdca 12.5%, #f7fdca 25%, #fecf71 25%, #fecf71 37.5%, #f0776c 37.5%, #f0776c 50%, #db9dbe 50%, #db9dbe 62.5%, #c49cde 62.5%, #c49cde 75%, #669ae1 75%, #669ae1 87.5%, #62c2e4 87.5%, #62c2e4); 9 | background-image: linear-gradient(to right, #c4e17f, #c4e17f 12.5%, #f7fdca 12.5%, #f7fdca 25%, #fecf71 25%, #fecf71 37.5%, #f0776c 37.5%, #f0776c 50%, #db9dbe 50%, #db9dbe 62.5%, #c49cde 62.5%, #c49cde 75%, #669ae1 75%, #669ae1 87.5%, #62c2e4 87.5%, #62c2e4); 10 | } 11 | 12 | body { 13 | background-color: #dedede; 14 | } 15 | 16 | .topbar { 17 | background: #2A3F54; 18 | border-color: #2A3F54; 19 | border-radius: 0px; 20 | } 21 | 22 | .topbar .navbar-header a { 23 | color: #ffffff; 24 | } 25 | 26 | .wrapper { 27 | padding-left: 0px; 28 | -webkit-transition: all 0.5s ease; 29 | -moz-transition: all 0.5s ease; 30 | -o-transition: all 0.5s ease; 31 | transition: all 0.5s ease; 32 | } 33 | 34 | .sidebar { 35 | z-index: 1000; 36 | position: fixed; 37 | top: 50px; 38 | left: -50px; 39 | width: 50px; 40 | height: 100%; 41 | overflow-y: auto; 42 | background: #2A3F54; 43 | color: #ffffff; 44 | -webkit-transition: all 0.5s ease; 45 | -moz-transition: all 0.5s ease; 46 | -o-transition: all 0.5s ease; 47 | transition: all 0.5s ease; 48 | } 49 | 50 | .main { 51 | width: 100%; 52 | position: relative; 53 | padding-bottom:20px; 54 | } 55 | 56 | .wrapper.toggled { 57 | padding-left: 50px; 58 | } 59 | 60 | .wrapper.toggled .sidebar { 61 | left: 0; 62 | } 63 | 64 | /* Sidebar Styles */ 65 | 66 | .sidebar-nav { 67 | position: absolute; 68 | top: 52px; 69 | width: 50px; 70 | margin: 0; 71 | padding: 0; 72 | list-style: none; 73 | } 74 | .sidebar-nav li { 75 | line-height: 40px; 76 | } 77 | .sidebar-nav li a { 78 | display: block; 79 | text-decoration: none; 80 | color: #e8e8e8; 81 | padding: 0; 82 | text-align:center; 83 | } 84 | 85 | .sidebar-nav li a:hover, .sidebar-nav li.active a { 86 | text-decoration: none; 87 | color: #fff; 88 | background: #fff; 89 | background: rgba(255,255,255,0.2); 90 | } 91 | 92 | .sidebar-nav li a:active, 93 | .sidebar-nav li a:focus { 94 | text-decoration: none; 95 | } 96 | 97 | .sidebar-nav li span, .subbar li span { 98 | display : none; 99 | } 100 | 101 | nav.subbar { 102 | position: relative; 103 | width: 100%; 104 | border-radius: 0px; 105 | background: #fff; 106 | margin: 50px 0 -50px 0; 107 | padding: 10px 0 0 0; 108 | z-index: 2; 109 | } 110 | nav.subbar > ul.nav.nav-tabs { 111 | padding: 0 5px; 112 | } 113 | 114 | nav.subbar > ul.nav.nav-tabs > li.active > a { 115 | background: #dedede; 116 | border-top: 1px solid #a6a6a6; 117 | border-left: 1px solid #a6a6a6; 118 | border-right: 1px solid #a6a6a6; 119 | border-radius: 0px; 120 | } 121 | 122 | .content { 123 | margin-top: 70px; 124 | padding: 0 30px; 125 | } 126 | 127 | @media(min-width:768px){ 128 | .subbar li span { 129 | display: inline; 130 | } 131 | } 132 | 133 | @media(min-width:992px) { 134 | .wrapper { 135 | padding-left: 50px; 136 | } 137 | 138 | .sidebar { 139 | left: 0; 140 | width: 50px; 141 | } 142 | 143 | .wrapper.toggled { 144 | padding-left: 200px; 145 | } 146 | 147 | .wrapper.toggled .sidebar, .wrapper.toggled .sidebar-nav { 148 | width: 200px; 149 | } 150 | 151 | .wrapper.toggled .sidebar-nav li a { 152 | text-align: left; 153 | padding: 0 0 0 10px; 154 | } 155 | 156 | .wrapper.toggled .sidebar-nav li span { 157 | display: inline; 158 | } 159 | 160 | } 161 | 162 | .navbar-btn { 163 | background: none; 164 | border: none; 165 | height: 35px; 166 | min-width: 35px; 167 | color: #fff; 168 | } 169 | .navbar-text { 170 | margin-top: 14px; 171 | margin-bottom: 14px; 172 | } 173 | @media (min-width: 768px) { 174 | .navbar-text { 175 | float: left; 176 | margin-left: 15px; 177 | margin-right: 15px; 178 | } 179 | } 180 | 181 | 182 | 183 | 184 | .animationload { 185 | background-color: #fff; 186 | height: 100%; 187 | left: 0; 188 | position: fixed; 189 | top: 0; 190 | width: 100%; 191 | z-index: 10000; 192 | } 193 | .osahanloading { 194 | animation: 1.5s linear 0s normal none infinite running osahanloading; 195 | background: #fed37f none repeat scroll 0 0; 196 | border-radius: 50px; 197 | height: 50px; 198 | left: 50%; 199 | margin-left: -25px; 200 | margin-top: -25px; 201 | position: absolute; 202 | top: 50%; 203 | width: 50px; 204 | } 205 | .osahanloading::after { 206 | animation: 1.5s linear 0s normal none infinite running osahanloading_after; 207 | border-color: #85d6de transparent; 208 | border-radius: 80px; 209 | border-style: solid; 210 | border-width: 10px; 211 | content: ""; 212 | height: 80px; 213 | left: -15px; 214 | position: absolute; 215 | top: -15px; 216 | width: 80px; 217 | } 218 | @keyframes osahanloading { 219 | 0% { 220 | transform: rotate(0deg); 221 | } 222 | 50% { 223 | background: #85d6de none repeat scroll 0 0; 224 | transform: rotate(180deg); 225 | } 226 | 100% { 227 | transform: rotate(360deg); 228 | } 229 | } 230 | -------------------------------------------------------------------------------- /bin/daemon_ips_hunter.php: -------------------------------------------------------------------------------- 1 | bloquear 37 | # 38 | # conectarse via API 39 | # conectarse via SSH 40 | # 41 | # TODO: Hacer que se quede la regla o se borre con el clean 42 | 43 | 44 | /* 45 | ALERTA 46 | 47 | 48 | {"timestamp":"2018-10-30T16:40:33.914426+0000","flow_id":1176372373961457,"pcap_cnt":1642642,"event_type":"alert","src_ip":"217.160.0.187","src_port":80,"dest_ip":"192.168.10.17","dest_port":50101,"proto":"TCP","alert":{"action":"allowed","gid":1,"signature_id":2100498,"rev":7,"signature":"GPL ATTACK_RESPONSE id check returned root","category":"Potentially Bad Traffic","severity":2},"http":{"hostname":"testmyids.com","url":"\/","http_user_agent":"curl\/7.43.0","http_content_type":"text\/html","http_method":"GET","protocol":"HTTP\/1.1","status":200,"length":39},"app_proto":"http","flow":{"pkts_toserver":12,"pkts_toclient":5,"bytes_toserver":953,"bytes_toclient":644,"start":"2018-10-30T16:40:25.998129+0000"}} 49 | 50 | 51 | HTTP 52 | 53 | {"timestamp":"2018-10-30T16:40:33.672909+0000","flow_id":1176372373961457,"pcap_cnt":1642193,"event_type":"http","src_ip":"192.168.10.17","src_port":50101,"dest_ip":"217.160.0.187","dest_port":80,"proto":"TCP","tx_id":0,"http":{"hostname":"testmyids.com","url":"\/","http_user_agent":"curl\/7.43.0","http_content_type":"text\/html","accept":"*\/*","connection":"keep-alive","content_length":"39","content_type":"text\/html","date":"Tue, 30 Oct 2018 16:40:33 GMT","last_modified":"Mon, 15 Jan 2007 23:11:55 GMT","server":"Apache","http_method":"GET","protocol":"HTTP\/1.1","status":200,"length":39}} 54 | 55 | 56 | */ 57 | 58 | touch( $cfg['PID_app_file'] ); 59 | 60 | 61 | $handle = popen("tail -f /var/log/suricata/eve.json 2>&1", 'r'); 62 | // $handle = popen("tail -n 200 /var/log/suricata/eve.json 2>&1", 'r'); 63 | while(!feof($handle)) { 64 | #Rule to block, from cache with 3 minutes to refresh 65 | $block_rules=get_cache_rules_to_block(); 66 | 67 | unset($datos_to_db); unset($need_block); 68 | 69 | $buffer = fgets($handle); 70 | // $line=json_decode($buffer,true); 71 | if (!file_exists( $cfg['PID_app_file'] )) { 72 | exit(0); 73 | } 74 | // echo "$buffer
\n"; 75 | $array = json_decode($buffer, true); 76 | $time = $array['timestamp']; 77 | $date = strtotime($time); 78 | $fixed = date('l, F d Y g:iA', $date); 79 | $date_db = date("Y-m-d H:i:s", $date); 80 | if (isset($array['alert']['signature']) && !empty($array['alert']['signature'])) { 81 | 82 | // echo var_dump($buffer)."
\n";; 83 | // $need_block= array_search_partial($block_rules, $array['alert']['signature']); 84 | #Busco si existe la firma en el array de las --firmas a bloquear--- 85 | $need_block= array_search_multiarray_strpos( $block_rules,'sig_name', $array['alert']['signature'] ); 86 | if ($need_block ) { 87 | 88 | // if ($block_rules) 89 | $datos_to_db[que_added]=get_now(); 90 | $datos_to_db[que_timeout]=$need_block[timeout]; 91 | ($need_block[src_or_dst]=='src') ? $datos_to_db[que_ip_adr]=ip2long($array['src_ip']):$datos_to_db[que_ip_adr]=ip2long($array['dest_ip']); 92 | $datos_to_db[que_sig_name]=$array['alert']['signature']; 93 | $datos_to_db[que_sig_sid]=$array['alert']['signature_id']; 94 | $datos_to_db[que_sig_gid]=$array['alert']['gid']; 95 | $datos_to_db[que_event_timestamp]=$date_db; 96 | $datos_to_db[json_raw]=serialize($array); 97 | insert_db( 'block_queue', $datos_to_db ); 98 | 99 | if ( $DEBUG ) _log("Alert Found: ". $datos_to_db[que_sig_name]. " FROM ".$array['src_ip']. " TO: ".$array['dest_ip']); 100 | 101 | 102 | 103 | // echo var_dump($datos_to_db)."BLOCK
\n";; 104 | 105 | // echo "BLOCKEDDD.......".$need_block." \n"; 106 | /* echo " 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 |
" . $fixed . "" . $array['src_ip'] . "" . $array['src_port'] . "" . $array['dest_ip'] . "" . $array['dest_port'] . "" . $array['alert']['signature'] . " - -
\n";*/ 117 | 118 | } 119 | 120 | } 121 | 122 | // ob_flush(); 123 | // flush(); 124 | usleep(400); 125 | } 126 | pclose($handle); 127 | unlink( $cfg['PID_app_file'] ); 128 | 129 | /** 130 | * [get_cache_rules_to_block get rules to block from cache and refresh it every 2 minutes] 131 | * @return [type] [description] 132 | */ 133 | function get_cache_rules_to_block(){ 134 | global $CACHE; 135 | $elapsed=minutos_transcurridos($CACHE[rules_block][time],get_now()); 136 | if ($elapsed>1) { 137 | _log("Reloading Rules to block. Getting from DB. ".$elapsed); 138 | $CACHE[rules_block][time]=get_now(); 139 | $CACHE[rules_block][rules]=get_rules2block_db(); 140 | return $CACHE[rules_block][rules]; 141 | 142 | }else { 143 | // _log("Rules to block. Getting from cache ".$elapsed); 144 | return $CACHE[rules_block][rules]; 145 | } 146 | 147 | } 148 | -------------------------------------------------------------------------------- /bin/daemon_ips_process.php: -------------------------------------------------------------------------------- 1 | query($SQL)) 66 | { 67 | die('There was an error running the query [' . $connect->error . ']'); 68 | } //!$result = $connect->query( $SQL ) 69 | 70 | // Reconnecting avoid timeout or API not responding (>v6.43) 71 | 72 | $elapsed = minutos_transcurridos($start_connection_api, get_now()); 73 | if ($elapsed > $router['restart_conn_time']) 74 | { 75 | $start_connection_api = get_now(); 76 | if ($router['conn'] == 'API') 77 | { 78 | if ($DEBUG) _log("Restarting API Connection. Time elapsed. " . $elapsed); 79 | 80 | // Reconexion 81 | 82 | $API->disconnect(); 83 | sleep(1); 84 | _api_connect_MikroTik($router); 85 | } 86 | 87 | if ($DEBUG) _log("OK ReConnected to " . $router['ip']); 88 | } 89 | 90 | $count = $result->num_rows; 91 | if ($count == 0) 92 | { 93 | if ($DEBUG) _log("Sleeping for new entry " . $elapsed); 94 | sleep(2); 95 | continue; 96 | } 97 | 98 | while ($row = $result->fetch_assoc()) 99 | { 100 | if (!check_ip_in_whilelist($row['ip'])) 101 | { 102 | /* Does not match local address... */ 103 | 104 | // Avoid process same last ip 105 | 106 | if ($last_ip == $row['ip']) 107 | { 108 | if ($DEBUG) _log("SAME Last IP."); 109 | usleep(500); 110 | break 1; 111 | } 112 | else 113 | { 114 | 115 | // Block IP 116 | 117 | /* Now add the address into the Blocked address-list group */ 118 | $comment_tmp = "From SuricataIPS, " . $row['que_sig_name'] . " => " . $row['que_sig_gid'] . ":" . $row['que_sig_sid'] . " => event timestamp: " . $row['que_event_timestamp']; 119 | if ($DEBUG) _log("Pushing to " . $router['ip']); 120 | if ($router['conn'] == 'API') 121 | { 122 | $API->comm("/ip/firewall/address-list/add", array( 123 | "list" => $router['address_list_block'], 124 | "address" => $row['ip'], 125 | "timeout" => $row['que_timeout'], 126 | "comment" => $comment_tmp 127 | )); 128 | } 129 | elseif ($router['conn'] == 'SSH') 130 | { 131 | unset($cmd); //clean last cmd 132 | $cmd = '/ip fi address-list add list="' . $router['address_list_block'] . '" address="' . $row['ip'] . '" comment="' . $comment_tmp . '" timeout="' . $row['que_timeout'] . '"'; 133 | $ssh_log = _ssh_connect_MikroTik($router, $cmd); 134 | if ($DEBUG) _log($ssh_log); 135 | } 136 | 137 | // si esta activo el api de telegram, avisar 138 | 139 | if ($active_api_telegram) 140 | { 141 | $comment_tmp.= " => IP: " . $row['ip'] . " => Timeout: " . $row['que_timeout']; 142 | send_to_telegram($comment_tmp); 143 | } 144 | 145 | // si esta activo el mail envio por correo el alerta 146 | 147 | if ($active_mail_report) 148 | { 149 | /* Send email indicating bad block attempt*/ 150 | $to = 'noreply@gmail.com'; 151 | $subject = 'Suricata on snort-host: attempted block on local address'; 152 | $message = 'A record in the block_queue indicated a block on a local IP Address (' . $row['ip'] . ")\r\n"; 153 | $message = $message . "\r\n"; 154 | $message = $message . "The signature ID is " . $row['que_sig_id'] . " named: " . $row['que_sig_name'] . "\r\n"; 155 | $message = $message . " with a que_id of " . $row['que_id'] . "\r\n\r\n"; 156 | $message = $message . "Check the src_or_dst field in events_to_block for the signature to make sure it is correct (src/dst).\r\n\r\n"; 157 | $message = $message . "The record was not processed but marked as completed.\r\n"; 158 | $headers = 'From: noreply@gmail.com' . "\r\n" . 'Reply-To: noreply@gmail.com' . "\r\n" . 'X-Mailer: PHP/' . phpversion(); 159 | 160 | // mail($to, $subject, $message, $headers); 161 | // 162 | 163 | } 164 | 165 | $last_ip = $row['ip']; //update last IP 166 | } //else 167 | if ($DEBUG) _log($comment_tmp); 168 | } // ! whilelist 169 | 170 | // # IP EN lista excepcion 171 | 172 | else 173 | { 174 | if ($DEBUG) _log("Exception IP " . $row['ip']); 175 | } 176 | 177 | // $SQL2 = "UPDATE block_queue set que_processed = 1 WHERE que_id = " . $row[ 'que_id' ] . ";"; 178 | // actualizo todos los que tengan el mismo ip 179 | 180 | $SQL2 = "UPDATE block_queue set que_processed = 1 WHERE que_ip_adr = " . ip2long($row['ip']) . ";"; 181 | if (!$result2 = $connect->query($SQL2)) 182 | { 183 | _log('There was an error running the query [' . $connect->error . ']'); 184 | die('There was an error running the query [' . $connect->error . ']'); 185 | } //!$result2 = $connect->query( $SQL2 ) 186 | mysqli_free_result($result2); 187 | } //eof while 188 | mysqli_free_result($result); 189 | usleep(5000); 190 | 191 | // sleep( 1 ); 192 | 193 | /* Sleep 2 seconds then do again */ 194 | mysqli_ping($connect); 195 | } //while grande 196 | 197 | // file_exists( $cfg[PID_app_file] ) 198 | 199 | if ($DEBUG) _log("Disconnect to " . $router['ip']); 200 | 201 | if ($router['conn'] == 'API') $API->disconnect(); 202 | echo "Shutdown services cron\n"; 203 | unlink($cfg['PID_app_file']); 204 | 205 | // db close 206 | 207 | $connect->close(); 208 | 209 | function _api_connect_MikroTik($router = NULL) 210 | { 211 | if (!$router) return false; 212 | global $DEBUG; 213 | global $API; 214 | global $start_connection_api; 215 | $API = new RouterosAPI(); 216 | try 217 | { 218 | if ($DEBUG) _log("Trying to connect to " . $router['ip']); 219 | $API->connect($router['ip'], $router['user'], $router['pass']); 220 | $start_connection_api = get_now(); //Define que se inicia ahora la conexion para reiniciarla cada 5 minutos. 221 | if ($DEBUG) _log("OK Connected to " . $router['ip']); 222 | return true; 223 | } 224 | 225 | catch(Exception $e) 226 | { 227 | _log("ERROR API CONNECTION " . $router['ip']); 228 | die('Unable to connect to RouterOS. Error:' . $e); 229 | } 230 | } 231 | 232 | // Ejecuta un comando ssh remoto 233 | 234 | function _ssh_connect_MikroTik($router = NULL, $cmd = NULL) 235 | { 236 | global $ssh; 237 | if (!$router) return false; 238 | if (!$cmd) return false; 239 | include_once ('Net/SSH2.php'); 240 | 241 | // define('NET_SSH2_LOGGING', NET_SSH2_LOG_COMPLEX); 242 | 243 | $ssh = new Net_SSH2($router['ip'], $router['port']); 244 | if (!$ssh->login($router['user'], $router['pass'])) 245 | { 246 | return ('ERR_LOGIN'); 247 | } 248 | 249 | return $ssh->exec($cmd . "\n"); // note the "\n" 250 | } 251 | 252 | ?> -------------------------------------------------------------------------------- /share/ssh/Net/SCP.php: -------------------------------------------------------------------------------- 1 | 13 | * login('username', 'password')) { 19 | * exit('bad login'); 20 | * } 21 | 22 | * $scp = new Net_SCP($ssh); 23 | * $scp->put('abcd', str_repeat('x', 1024*1024)); 24 | * ?> 25 | * 26 | * 27 | * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy 28 | * of this software and associated documentation files (the "Software"), to deal 29 | * in the Software without restriction, including without limitation the rights 30 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 31 | * copies of the Software, and to permit persons to whom the Software is 32 | * furnished to do so, subject to the following conditions: 33 | * 34 | * The above copyright notice and this permission notice shall be included in 35 | * all copies or substantial portions of the Software. 36 | * 37 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 38 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 39 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 40 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 41 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 42 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 43 | * THE SOFTWARE. 44 | * 45 | * @category Net 46 | * @package Net_SCP 47 | * @author Jim Wigginton 48 | * @copyright MMX Jim Wigginton 49 | * @license http://www.opensource.org/licenses/mit-license.html MIT License 50 | * @link http://phpseclib.sourceforge.net 51 | */ 52 | 53 | /**#@+ 54 | * @access public 55 | * @see Net_SCP::put() 56 | */ 57 | /** 58 | * Reads data from a local file. 59 | */ 60 | define('NET_SCP_LOCAL_FILE', 1); 61 | /** 62 | * Reads data from a string. 63 | */ 64 | define('NET_SCP_STRING', 2); 65 | /**#@-*/ 66 | 67 | /**#@+ 68 | * @access private 69 | * @see Net_SCP::_send() 70 | * @see Net_SCP::_receive() 71 | */ 72 | /** 73 | * SSH1 is being used. 74 | */ 75 | define('NET_SCP_SSH1', 1); 76 | /** 77 | * SSH2 is being used. 78 | */ 79 | define('NET_SCP_SSH2', 2); 80 | /**#@-*/ 81 | 82 | /** 83 | * Pure-PHP implementations of SCP. 84 | * 85 | * @author Jim Wigginton 86 | * @version 0.1.0 87 | * @access public 88 | * @package Net_SCP 89 | */ 90 | class Net_SCP { 91 | /** 92 | * SSH Object 93 | * 94 | * @var Object 95 | * @access private 96 | */ 97 | var $ssh; 98 | 99 | /** 100 | * Packet Size 101 | * 102 | * @var Integer 103 | * @access private 104 | */ 105 | var $packet_size; 106 | 107 | /** 108 | * Mode 109 | * 110 | * @var Integer 111 | * @access private 112 | */ 113 | var $mode; 114 | 115 | /** 116 | * Default Constructor. 117 | * 118 | * Connects to an SSH server 119 | * 120 | * @param String $host 121 | * @param optional Integer $port 122 | * @param optional Integer $timeout 123 | * @return Net_SCP 124 | * @access public 125 | */ 126 | function Net_SCP($ssh) 127 | { 128 | if (!is_object($ssh)) { 129 | return; 130 | } 131 | 132 | switch (strtolower(get_class($ssh))) { 133 | case'net_ssh2': 134 | $this->mode = NET_SCP_SSH2; 135 | break; 136 | case 'net_ssh1': 137 | $this->packet_size = 50000; 138 | $this->mode = NET_SCP_SSH1; 139 | break; 140 | default: 141 | return; 142 | } 143 | 144 | $this->ssh = $ssh; 145 | } 146 | 147 | /** 148 | * Uploads a file to the SCP server. 149 | * 150 | * By default, Net_SCP::put() does not read from the local filesystem. $data is dumped directly into $remote_file. 151 | * So, for example, if you set $data to 'filename.ext' and then do Net_SCP::get(), you will get a file, twelve bytes 152 | * long, containing 'filename.ext' as its contents. 153 | * 154 | * Setting $mode to NET_SFTP_LOCAL_FILE will change the above behavior. With NET_SFTP_LOCAL_FILE, $remote_file will 155 | * contain as many bytes as filename.ext does on your local filesystem. If your filename.ext is 1MB then that is how 156 | * large $remote_file will be, as well. 157 | * 158 | * Currently, only binary mode is supported. As such, if the line endings need to be adjusted, you will need to take 159 | * care of that, yourself. 160 | * 161 | * @param String $remote_file 162 | * @param String $data 163 | * @param optional Integer $mode 164 | * @return Boolean 165 | * @access public 166 | */ 167 | function put($remote_file, $data, $mode = NET_SCP_STRING) 168 | { 169 | if (!isset($this->ssh)) { 170 | return false; 171 | } 172 | 173 | $this->ssh->exec('scp -t ' . $remote_file, false); // -t = to 174 | 175 | $temp = $this->_receive(); 176 | if ($temp !== chr(0)) { 177 | return false; 178 | } 179 | 180 | if ($this->mode == NET_SCP_SSH2) { 181 | $this->packet_size = $this->ssh->packet_size_client_to_server[NET_SSH2_CHANNEL_EXEC]; 182 | } 183 | 184 | $remote_file = basename($remote_file); 185 | $this->_send('C0644 ' . strlen($data) . ' ' . $remote_file . "\n"); 186 | 187 | $temp = $this->_receive(); 188 | if ($temp !== chr(0)) { 189 | return false; 190 | } 191 | 192 | if ($mode == NET_SCP_STRING) { 193 | $this->_send($data); 194 | } else { 195 | if (!is_file($data)) { 196 | user_error("$data is not a valid file", E_USER_NOTICE); 197 | return false; 198 | } 199 | $fp = @fopen($data, 'rb'); 200 | if (!$fp) { 201 | return false; 202 | } 203 | $size = filesize($data); 204 | for ($i = 0; $i < $size; $i += $this->packet_size) { 205 | $this->_send(fgets($fp, $this->packet_size)); 206 | } 207 | fclose($fp); 208 | } 209 | $this->_close(); 210 | } 211 | 212 | /** 213 | * Downloads a file from the SCP server. 214 | * 215 | * Returns a string containing the contents of $remote_file if $local_file is left undefined or a boolean false if 216 | * the operation was unsuccessful. If $local_file is defined, returns true or false depending on the success of the 217 | * operation 218 | * 219 | * @param String $remote_file 220 | * @param optional String $local_file 221 | * @return Mixed 222 | * @access public 223 | */ 224 | function get($remote_file, $local_file = false) 225 | { 226 | if (!isset($this->ssh)) { 227 | return false; 228 | } 229 | 230 | $this->ssh->exec('scp -f ' . $remote_file, false); // -f = from 231 | 232 | $this->_send("\0"); 233 | 234 | if (!preg_match('#(?[^ ]+) (?\d+) (?.+)#', rtrim($this->_receive()), $info)) { 235 | return false; 236 | } 237 | 238 | $this->_send("\0"); 239 | 240 | $size = 0; 241 | 242 | if ($local_file !== false) { 243 | $fp = @fopen($local_file, 'wb'); 244 | if (!$fp) { 245 | return false; 246 | } 247 | } 248 | 249 | $content = ''; 250 | while ($size < $info['size']) { 251 | $data = $this->_receive(); 252 | // SCP usually seems to split stuff out into 16k chunks 253 | $size+= strlen($data); 254 | 255 | if ($local_file === false) { 256 | $content.= $data; 257 | } else { 258 | fputs($fp, $data); 259 | } 260 | } 261 | 262 | $this->_close(); 263 | 264 | if ($local_file !== false) { 265 | fclose($fp); 266 | return true; 267 | } 268 | 269 | return $content; 270 | } 271 | 272 | /** 273 | * Sends a packet to an SSH server 274 | * 275 | * @param String $data 276 | * @access private 277 | */ 278 | function _send($data) 279 | { 280 | switch ($this->mode) { 281 | case NET_SCP_SSH2: 282 | $this->ssh->_send_channel_packet(NET_SSH2_CHANNEL_EXEC, $data); 283 | break; 284 | case NET_SCP_SSH1: 285 | $data = pack('CNa*', NET_SSH1_CMSG_STDIN_DATA, strlen($data), $data); 286 | $this->ssh->_send_binary_packet($data); 287 | } 288 | } 289 | 290 | /** 291 | * Receives a packet from an SSH server 292 | * 293 | * @return String 294 | * @access private 295 | */ 296 | function _receive() 297 | { 298 | switch ($this->mode) { 299 | case NET_SCP_SSH2: 300 | return $this->ssh->_get_channel_packet(NET_SSH2_CHANNEL_EXEC, true); 301 | case NET_SCP_SSH1: 302 | if (!$this->ssh->bitmap) { 303 | return false; 304 | } 305 | while (true) { 306 | $response = $this->ssh->_get_binary_packet(); 307 | switch ($response[NET_SSH1_RESPONSE_TYPE]) { 308 | case NET_SSH1_SMSG_STDOUT_DATA: 309 | extract(unpack('Nlength', $response[NET_SSH1_RESPONSE_DATA])); 310 | return $this->ssh->_string_shift($response[NET_SSH1_RESPONSE_DATA], $length); 311 | case NET_SSH1_SMSG_STDERR_DATA: 312 | break; 313 | case NET_SSH1_SMSG_EXITSTATUS: 314 | $this->ssh->_send_binary_packet(chr(NET_SSH1_CMSG_EXIT_CONFIRMATION)); 315 | fclose($this->ssh->fsock); 316 | $this->ssh->bitmap = 0; 317 | return false; 318 | default: 319 | user_error('Unknown packet received', E_USER_NOTICE); 320 | return false; 321 | } 322 | } 323 | } 324 | } 325 | 326 | /** 327 | * Closes the connection to an SSH server 328 | * 329 | * @access private 330 | */ 331 | function _close() 332 | { 333 | switch ($this->mode) { 334 | case NET_SCP_SSH2: 335 | $this->ssh->_close_channel(NET_SSH2_CHANNEL_EXEC); 336 | break; 337 | case NET_SCP_SSH1: 338 | $this->ssh->disconnect(); 339 | } 340 | } 341 | } 342 | -------------------------------------------------------------------------------- /share/ssh/Crypt/Random.php: -------------------------------------------------------------------------------- 1 | 11 | * 16 | * 17 | * 18 | * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy 19 | * of this software and associated documentation files (the "Software"), to deal 20 | * in the Software without restriction, including without limitation the rights 21 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 22 | * copies of the Software, and to permit persons to whom the Software is 23 | * furnished to do so, subject to the following conditions: 24 | * 25 | * The above copyright notice and this permission notice shall be included in 26 | * all copies or substantial portions of the Software. 27 | * 28 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 29 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 30 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 31 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 32 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 33 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 34 | * THE SOFTWARE. 35 | * 36 | * @category Crypt 37 | * @package Crypt_Random 38 | * @author Jim Wigginton 39 | * @copyright MMVII Jim Wigginton 40 | * @license http://www.opensource.org/licenses/mit-license.html MIT License 41 | * @link http://phpseclib.sourceforge.net 42 | */ 43 | 44 | /** 45 | * "Is Windows" test 46 | * 47 | * @access private 48 | */ 49 | define('CRYPT_RANDOM_IS_WINDOWS', strtoupper(substr(PHP_OS, 0, 3)) === 'WIN'); 50 | 51 | /** 52 | * Generate a random string. 53 | * 54 | * Although microoptimizations are generally discouraged as they impair readability this function is ripe with 55 | * microoptimizations because this function has the potential of being called a huge number of times. 56 | * eg. for RSA key generation. 57 | * 58 | * @param Integer $length 59 | * @return String 60 | * @access public 61 | */ 62 | function crypt_random_string($length) 63 | { 64 | if (CRYPT_RANDOM_IS_WINDOWS) { 65 | // method 1. prior to PHP 5.3 this would call rand() on windows hence the function_exists('class_alias') call. 66 | // ie. class_alias is a function that was introduced in PHP 5.3 67 | if (function_exists('mcrypt_create_iv') && function_exists('class_alias')) { 68 | return mcrypt_create_iv($length); 69 | } 70 | // method 2. openssl_random_pseudo_bytes was introduced in PHP 5.3.0 but prior to PHP 5.3.4 there was, 71 | // to quote , "possible blocking behavior". as of 5.3.4 72 | // openssl_random_pseudo_bytes and mcrypt_create_iv do the exact same thing on Windows. ie. they both 73 | // call php_win32_get_random_bytes(): 74 | // 75 | // https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/openssl/openssl.c#L5008 76 | // https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/mcrypt/mcrypt.c#L1392 77 | // 78 | // php_win32_get_random_bytes() is defined thusly: 79 | // 80 | // https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/win32/winutil.c#L80 81 | // 82 | // we're calling it, all the same, in the off chance that the mcrypt extension is not available 83 | if (function_exists('openssl_random_pseudo_bytes') && version_compare(PHP_VERSION, '5.3.4', '>=')) { 84 | return openssl_random_pseudo_bytes($length); 85 | } 86 | } else { 87 | // method 1. the fastest 88 | if (function_exists('openssl_random_pseudo_bytes')) { 89 | return openssl_random_pseudo_bytes($length); 90 | } 91 | // method 2 92 | static $fp = true; 93 | if ($fp === true) { 94 | // warning's will be output unles the error suppression operator is used. errors such as 95 | // "open_basedir restriction in effect", "Permission denied", "No such file or directory", etc. 96 | $fp = @fopen('/dev/urandom', 'rb'); 97 | } 98 | if ($fp !== true && $fp !== false) { // surprisingly faster than !is_bool() or is_resource() 99 | return fread($fp, $length); 100 | } 101 | // method 3. pretty much does the same thing as method 2 per the following url: 102 | // https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/mcrypt/mcrypt.c#L1391 103 | // surprisingly slower than method 2. maybe that's because mcrypt_create_iv does a bunch of error checking that we're 104 | // not doing. regardless, this'll only be called if this PHP script couldn't open /dev/urandom due to open_basedir 105 | // restrictions or some such 106 | if (function_exists('mcrypt_create_iv')) { 107 | return mcrypt_create_iv($length, MCRYPT_DEV_URANDOM); 108 | } 109 | } 110 | // at this point we have no choice but to use a pure-PHP CSPRNG 111 | 112 | // cascade entropy across multiple PHP instances by fixing the session and collecting all 113 | // environmental variables, including the previous session data and the current session 114 | // data. 115 | // 116 | // mt_rand seeds itself by looking at the PID and the time, both of which are (relatively) 117 | // easy to guess at. linux uses mouse clicks, keyboard timings, etc, as entropy sources, but 118 | // PHP isn't low level to be able to use those as sources and on a web server there's not likely 119 | // going to be a ton of keyboard or mouse action. web servers do have one thing that we can use 120 | // however. a ton of people visiting the website. obviously you don't want to base your seeding 121 | // soley on parameters a potential attacker sends but (1) not everything in $_SERVER is controlled 122 | // by the user and (2) this isn't just looking at the data sent by the current user - it's based 123 | // on the data sent by all users. one user requests the page and a hash of their info is saved. 124 | // another user visits the page and the serialization of their data is utilized along with the 125 | // server envirnment stuff and a hash of the previous http request data (which itself utilizes 126 | // a hash of the session data before that). certainly an attacker should be assumed to have 127 | // full control over his own http requests. he, however, is not going to have control over 128 | // everyone's http requests. 129 | static $crypto = false, $v; 130 | if ($crypto === false) { 131 | // save old session data 132 | $old_session_id = session_id(); 133 | $old_use_cookies = ini_get('session.use_cookies'); 134 | $old_session_cache_limiter = session_cache_limiter(); 135 | if (isset($_SESSION)) { 136 | $_OLD_SESSION = $_SESSION; 137 | } 138 | if ($old_session_id != '') { 139 | session_write_close(); 140 | } 141 | 142 | session_id(1); 143 | ini_set('session.use_cookies', 0); 144 | session_cache_limiter(''); 145 | session_start(); 146 | 147 | $v = $seed = $_SESSION['seed'] = pack('H*', sha1( 148 | serialize($_SERVER) . 149 | serialize($_POST) . 150 | serialize($_GET) . 151 | serialize($_COOKIE) . 152 | serialize($GLOBALS) . 153 | serialize($_SESSION) . 154 | serialize($_OLD_SESSION) 155 | )); 156 | if (!isset($_SESSION['count'])) { 157 | $_SESSION['count'] = 0; 158 | } 159 | $_SESSION['count']++; 160 | 161 | session_write_close(); 162 | 163 | // restore old session data 164 | if ($old_session_id != '') { 165 | session_id($old_session_id); 166 | session_start(); 167 | ini_set('session.use_cookies', $old_use_cookies); 168 | session_cache_limiter($old_session_cache_limiter); 169 | } else { 170 | if (isset($_OLD_SESSION)) { 171 | $_SESSION = $_OLD_SESSION; 172 | unset($_OLD_SESSION); 173 | } else { 174 | unset($_SESSION); 175 | } 176 | } 177 | 178 | // in SSH2 a shared secret and an exchange hash are generated through the key exchange process. 179 | // the IV client to server is the hash of that "nonce" with the letter A and for the encryption key it's the letter C. 180 | // if the hash doesn't produce enough a key or an IV that's long enough concat successive hashes of the 181 | // original hash and the current hash. we'll be emulating that. for more info see the following URL: 182 | // 183 | // http://tools.ietf.org/html/rfc4253#section-7.2 184 | // 185 | // see the is_string($crypto) part for an example of how to expand the keys 186 | $key = pack('H*', sha1($seed . 'A')); 187 | $iv = pack('H*', sha1($seed . 'C')); 188 | 189 | // ciphers are used as per the nist.gov link below. also, see this link: 190 | // 191 | // http://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator#Designs_based_on_cryptographic_primitives 192 | switch (true) { 193 | case class_exists('Crypt_AES'): 194 | $crypto = new Crypt_AES(CRYPT_AES_MODE_CTR); 195 | break; 196 | case class_exists('Crypt_TripleDES'): 197 | $crypto = new Crypt_TripleDES(CRYPT_DES_MODE_CTR); 198 | break; 199 | case class_exists('Crypt_DES'): 200 | $crypto = new Crypt_DES(CRYPT_DES_MODE_CTR); 201 | break; 202 | case class_exists('Crypt_RC4'): 203 | $crypto = new Crypt_RC4(); 204 | break; 205 | default: 206 | $crypto = $seed; 207 | return crypt_random_string($length); 208 | } 209 | 210 | $crypto->setKey($key); 211 | $crypto->setIV($iv); 212 | $crypto->enableContinuousBuffer(); 213 | } 214 | 215 | if (is_string($crypto)) { 216 | // the following is based off of ANSI X9.31: 217 | // 218 | // http://csrc.nist.gov/groups/STM/cavp/documents/rng/931rngext.pdf 219 | // 220 | // OpenSSL uses that same standard for it's random numbers: 221 | // 222 | // http://www.opensource.apple.com/source/OpenSSL/OpenSSL-38/openssl/fips-1.0/rand/fips_rand.c 223 | // (do a search for "ANS X9.31 A.2.4") 224 | // 225 | // ANSI X9.31 recommends ciphers be used and phpseclib does use them if they're available (see 226 | // later on in the code) but if they're not we'll use sha1 227 | $result = ''; 228 | while (strlen($result) < $length) { // each loop adds 20 bytes 229 | // microtime() isn't packed as "densely" as it could be but then neither is that the idea. 230 | // the idea is simply to ensure that each "block" has a unique element to it. 231 | $i = pack('H*', sha1(microtime())); 232 | $r = pack('H*', sha1($i ^ $v)); 233 | $v = pack('H*', sha1($r ^ $i)); 234 | $result.= $r; 235 | } 236 | return substr($result, 0, $length); 237 | } 238 | 239 | //return $crypto->encrypt(str_repeat("\0", $length)); 240 | 241 | $result = ''; 242 | while (strlen($result) < $length) { 243 | $i = $crypto->encrypt(microtime()); 244 | $r = $crypto->encrypt($i ^ $v); 245 | $v = $crypto->encrypt($r ^ $i); 246 | $result.= $r; 247 | } 248 | return substr($result, 0, $length); 249 | } 250 | -------------------------------------------------------------------------------- /share/routeros_api.php: -------------------------------------------------------------------------------- 1 | debug) { 53 | echo $text . "\n"; 54 | } 55 | } 56 | 57 | 58 | /** 59 | * 60 | * 61 | * @param string $length 62 | * 63 | * @return void 64 | */ 65 | public function encodeLength($length) 66 | { 67 | if ($length < 0x80) { 68 | $length = chr($length); 69 | } elseif ($length < 0x4000) { 70 | $length |= 0x8000; 71 | $length = chr(($length >> 8) & 0xFF) . chr($length & 0xFF); 72 | } elseif ($length < 0x200000) { 73 | $length |= 0xC00000; 74 | $length = chr(($length >> 16) & 0xFF) . chr(($length >> 8) & 0xFF) . chr($length & 0xFF); 75 | } elseif ($length < 0x10000000) { 76 | $length |= 0xE0000000; 77 | $length = chr(($length >> 24) & 0xFF) . chr(($length >> 16) & 0xFF) . chr(($length >> 8) & 0xFF) . chr($length & 0xFF); 78 | } elseif ($length >= 0x10000000) { 79 | $length = chr(0xF0) . chr(($length >> 24) & 0xFF) . chr(($length >> 16) & 0xFF) . chr(($length >> 8) & 0xFF) . chr($length & 0xFF); 80 | } 81 | 82 | return $length; 83 | } 84 | 85 | 86 | /** 87 | * Login to RouterOS 88 | * 89 | * @param string $ip Hostname (IP or domain) of the RouterOS server 90 | * @param string $login The RouterOS username 91 | * @param string $password The RouterOS password 92 | * 93 | * @return boolean If we are connected or not 94 | */ 95 | public function connect($ip, $login, $password) 96 | { 97 | for ($ATTEMPT = 1; $ATTEMPT <= $this->attempts; $ATTEMPT++) { 98 | $this->connected = false; 99 | $PROTOCOL = ($this->ssl ? 'ssl://' : '' ); 100 | $context = stream_context_create(array('ssl' => array('ciphers' => 'ADH:ALL', 'verify_peer' => false, 'verify_peer_name' => false))); 101 | $this->debug('Connection attempt #' . $ATTEMPT . ' to ' . $PROTOCOL . $ip . ':' . $this->port . '...'); 102 | $this->socket = @stream_socket_client($PROTOCOL . $ip.':'. $this->port, $this->error_no, $this->error_str, $this->timeout, STREAM_CLIENT_CONNECT,$context); 103 | if ($this->socket) { 104 | socket_set_timeout($this->socket, $this->timeout); 105 | $this->write('/login', false); 106 | $this->write('=name=' . $login, false); 107 | $this->write('=password=' . $password); 108 | $RESPONSE = $this->read(false); 109 | if (isset($RESPONSE[0])) { 110 | if ($RESPONSE[0] == '!done') { 111 | if (!isset($RESPONSE[1])) { 112 | // Login method post-v6.43 113 | $this->connected = true; 114 | break; 115 | } else { 116 | // Login method pre-v6.43 117 | $MATCHES = array(); 118 | if (preg_match_all('/[^=]+/i', $RESPONSE[1], $MATCHES)) { 119 | if ($MATCHES[0][0] == 'ret' && strlen($MATCHES[0][1]) == 32) { 120 | $this->write('/login', false); 121 | $this->write('=name=' . $login, false); 122 | $this->write('=response=00' . md5(chr(0) . $password . pack('H*', $MATCHES[0][1]))); 123 | $RESPONSE = $this->read(false); 124 | if (isset($RESPONSE[0]) && $RESPONSE[0] == '!done') { 125 | $this->connected = true; 126 | break; 127 | } 128 | } 129 | } 130 | } 131 | } 132 | } 133 | fclose($this->socket); 134 | } 135 | sleep($this->delay); 136 | } 137 | 138 | if ($this->connected) { 139 | $this->debug('Connected...'); 140 | } else { 141 | $this->debug('Error...'); 142 | } 143 | return $this->connected; 144 | } 145 | 146 | 147 | /** 148 | * Disconnect from RouterOS 149 | * 150 | * @return void 151 | */ 152 | public function disconnect() 153 | { 154 | // let's make sure this socket is still valid. it may have been closed by something else 155 | if( is_resource($this->socket) ) { 156 | fclose($this->socket); 157 | } 158 | $this->connected = false; 159 | $this->debug('Disconnected...'); 160 | } 161 | 162 | 163 | /** 164 | * Parse response from Router OS 165 | * 166 | * @param array $response Response data 167 | * 168 | * @return array Array with parsed data 169 | */ 170 | public function parseResponse($response) 171 | { 172 | if (is_array($response)) { 173 | $PARSED = array(); 174 | $CURRENT = null; 175 | $singlevalue = null; 176 | foreach ($response as $x) { 177 | if (in_array($x, array('!fatal','!re','!trap'))) { 178 | if ($x == '!re') { 179 | $CURRENT =& $PARSED[]; 180 | } else { 181 | $CURRENT =& $PARSED[$x][]; 182 | } 183 | } elseif ($x != '!done') { 184 | $MATCHES = array(); 185 | if (preg_match_all('/[^=]+/i', $x, $MATCHES)) { 186 | if ($MATCHES[0][0] == 'ret') { 187 | $singlevalue = $MATCHES[0][1]; 188 | } 189 | $CURRENT[$MATCHES[0][0]] = (isset($MATCHES[0][1]) ? $MATCHES[0][1] : ''); 190 | } 191 | } 192 | } 193 | 194 | if (empty($PARSED) && !is_null($singlevalue)) { 195 | $PARSED = $singlevalue; 196 | } 197 | 198 | return $PARSED; 199 | } else { 200 | return array(); 201 | } 202 | } 203 | 204 | 205 | /** 206 | * Parse response from Router OS 207 | * 208 | * @param array $response Response data 209 | * 210 | * @return array Array with parsed data 211 | */ 212 | public function parseResponse4Smarty($response) 213 | { 214 | if (is_array($response)) { 215 | $PARSED = array(); 216 | $CURRENT = null; 217 | $singlevalue = null; 218 | foreach ($response as $x) { 219 | if (in_array($x, array('!fatal','!re','!trap'))) { 220 | if ($x == '!re') { 221 | $CURRENT =& $PARSED[]; 222 | } else { 223 | $CURRENT =& $PARSED[$x][]; 224 | } 225 | } elseif ($x != '!done') { 226 | $MATCHES = array(); 227 | if (preg_match_all('/[^=]+/i', $x, $MATCHES)) { 228 | if ($MATCHES[0][0] == 'ret') { 229 | $singlevalue = $MATCHES[0][1]; 230 | } 231 | $CURRENT[$MATCHES[0][0]] = (isset($MATCHES[0][1]) ? $MATCHES[0][1] : ''); 232 | } 233 | } 234 | } 235 | foreach ($PARSED as $key => $value) { 236 | $PARSED[$key] = $this->arrayChangeKeyName($value); 237 | } 238 | return $PARSED; 239 | if (empty($PARSED) && !is_null($singlevalue)) { 240 | $PARSED = $singlevalue; 241 | } 242 | } else { 243 | return array(); 244 | } 245 | } 246 | 247 | 248 | /** 249 | * Change "-" and "/" from array key to "_" 250 | * 251 | * @param array $array Input array 252 | * 253 | * @return array Array with changed key names 254 | */ 255 | public function arrayChangeKeyName(&$array) 256 | { 257 | if (is_array($array)) { 258 | foreach ($array as $k => $v) { 259 | $tmp = str_replace("-", "_", $k); 260 | $tmp = str_replace("/", "_", $tmp); 261 | if ($tmp) { 262 | $array_new[$tmp] = $v; 263 | } else { 264 | $array_new[$k] = $v; 265 | } 266 | } 267 | return $array_new; 268 | } else { 269 | return $array; 270 | } 271 | } 272 | 273 | 274 | /** 275 | * Read data from Router OS 276 | * 277 | * @param boolean $parse Parse the data? default: true 278 | * 279 | * @return array Array with parsed or unparsed data 280 | */ 281 | public function read($parse = true) 282 | { 283 | $RESPONSE = array(); 284 | $receiveddone = false; 285 | while (true) { 286 | // Read the first byte of input which gives us some or all of the length 287 | // of the remaining reply. 288 | $BYTE = ord(fread($this->socket, 1)); 289 | $LENGTH = 0; 290 | // If the first bit is set then we need to remove the first four bits, shift left 8 291 | // and then read another byte in. 292 | // We repeat this for the second and third bits. 293 | // If the fourth bit is set, we need to remove anything left in the first byte 294 | // and then read in yet another byte. 295 | if ($BYTE & 128) { 296 | if (($BYTE & 192) == 128) { 297 | $LENGTH = (($BYTE & 63) << 8) + ord(fread($this->socket, 1)); 298 | } else { 299 | if (($BYTE & 224) == 192) { 300 | $LENGTH = (($BYTE & 31) << 8) + ord(fread($this->socket, 1)); 301 | $LENGTH = ($LENGTH << 8) + ord(fread($this->socket, 1)); 302 | } else { 303 | if (($BYTE & 240) == 224) { 304 | $LENGTH = (($BYTE & 15) << 8) + ord(fread($this->socket, 1)); 305 | $LENGTH = ($LENGTH << 8) + ord(fread($this->socket, 1)); 306 | $LENGTH = ($LENGTH << 8) + ord(fread($this->socket, 1)); 307 | } else { 308 | $LENGTH = ord(fread($this->socket, 1)); 309 | $LENGTH = ($LENGTH << 8) + ord(fread($this->socket, 1)); 310 | $LENGTH = ($LENGTH << 8) + ord(fread($this->socket, 1)); 311 | $LENGTH = ($LENGTH << 8) + ord(fread($this->socket, 1)); 312 | } 313 | } 314 | } 315 | } else { 316 | $LENGTH = $BYTE; 317 | } 318 | 319 | $_ = ""; 320 | 321 | // If we have got more characters to read, read them in. 322 | if ($LENGTH > 0) { 323 | $_ = ""; 324 | $retlen = 0; 325 | while ($retlen < $LENGTH) { 326 | $toread = $LENGTH - $retlen; 327 | $_ .= fread($this->socket, $toread); 328 | $retlen = strlen($_); 329 | } 330 | $RESPONSE[] = $_; 331 | $this->debug('>>> [' . $retlen . '/' . $LENGTH . '] bytes read.'); 332 | } 333 | 334 | // If we get a !done, make a note of it. 335 | if ($_ == "!done") { 336 | $receiveddone = true; 337 | } 338 | 339 | $STATUS = socket_get_status($this->socket); 340 | if ($LENGTH > 0) { 341 | $this->debug('>>> [' . $LENGTH . ', ' . $STATUS['unread_bytes'] . ']' . $_); 342 | } 343 | 344 | if ((!$this->connected && !$STATUS['unread_bytes']) || ($this->connected && !$STATUS['unread_bytes'] && $receiveddone)) { 345 | break; 346 | } 347 | } 348 | 349 | if ($parse) { 350 | $RESPONSE = $this->parseResponse($RESPONSE); 351 | } 352 | 353 | return $RESPONSE; 354 | } 355 | 356 | 357 | /** 358 | * Write (send) data to Router OS 359 | * 360 | * @param string $command A string with the command to send 361 | * @param mixed $param2 If we set an integer, the command will send this data as a "tag" 362 | * If we set it to boolean true, the funcion will send the comand and finish 363 | * If we set it to boolean false, the funcion will send the comand and wait for next command 364 | * Default: true 365 | * 366 | * @return boolean Return false if no command especified 367 | */ 368 | public function write($command, $param2 = true) 369 | { 370 | if ($command) { 371 | $data = explode("\n", $command); 372 | foreach ($data as $com) { 373 | $com = trim($com); 374 | fwrite($this->socket, $this->encodeLength(strlen($com)) . $com); 375 | $this->debug('<<< [' . strlen($com) . '] ' . $com); 376 | } 377 | 378 | if (gettype($param2) == 'integer') { 379 | fwrite($this->socket, $this->encodeLength(strlen('.tag=' . $param2)) . '.tag=' . $param2 . chr(0)); 380 | $this->debug('<<< [' . strlen('.tag=' . $param2) . '] .tag=' . $param2); 381 | } elseif (gettype($param2) == 'boolean') { 382 | fwrite($this->socket, ($param2 ? chr(0) : '')); 383 | } 384 | 385 | return true; 386 | } else { 387 | return false; 388 | } 389 | } 390 | 391 | 392 | /** 393 | * Write (send) data to Router OS 394 | * 395 | * @param string $com A string with the command to send 396 | * @param array $arr An array with arguments or queries 397 | * 398 | * @return array Array with parsed 399 | */ 400 | public function comm($com, $arr = array()) 401 | { 402 | $count = count($arr); 403 | $this->write($com, !$arr); 404 | $i = 0; 405 | if ($this->isIterable($arr)) { 406 | foreach ($arr as $k => $v) { 407 | switch ($k[0]) { 408 | case "?": 409 | $el = "$k=$v"; 410 | break; 411 | case "~": 412 | $el = "$k~$v"; 413 | break; 414 | default: 415 | $el = "=$k=$v"; 416 | break; 417 | } 418 | 419 | $last = ($i++ == $count - 1); 420 | $this->write($el, $last); 421 | } 422 | } 423 | 424 | return $this->read(); 425 | } 426 | 427 | /** 428 | * Standard destructor 429 | * 430 | * @return void 431 | */ 432 | public function __destruct() 433 | { 434 | $this->disconnect(); 435 | } 436 | } 437 | -------------------------------------------------------------------------------- /share/functions.php: -------------------------------------------------------------------------------- 1 | query($SQL)) 68 | { 69 | die('There was an error running the query [' . $connect->error . ']'); 70 | } //!$result = $db_->query( $SQL ) 71 | $row = $result->fetch_assoc(); 72 | return $row; 73 | } 74 | 75 | /** 76 | * [insert_db agrega un nuevo registro en una db] 77 | * @param [type] $dbname [description] 78 | * @param [type] $datos [description] 79 | * @return [type] [description] 80 | */ 81 | 82 | function insert_db($dbname = NULL, $datos = NULL, $delayed = false) 83 | { 84 | global $connect; 85 | if (!$datos) return false; 86 | if (!$dbname) return false; 87 | $sql = "INSERT "; 88 | if ($delayed) $sql.= " delayed "; 89 | $sql.= " INTO $dbname "; 90 | foreach($datos as $key => $valor) 91 | 92 | { 93 | $sql_init.= "`" . $key . "`,"; 94 | $sql_final.= "'" . $valor . "',"; 95 | } //$datos as $key => $valor 96 | 97 | $sql_init = substr($sql_init, 0, -1); 98 | $sql_final = substr($sql_final, 0, -1); 99 | 100 | 101 | $sql.= " ( " . $sql_init . " ) VALUES (" . $sql_final . ") ;"; 102 | 103 | // echo $sql; 104 | 105 | $result = $connect->query($sql); 106 | 107 | if ($connect->error) 108 | { 109 | die('Error, insert query failed ' . $connect->error . $sql); 110 | } 111 | elseif ($result) 112 | { 113 | return (true); 114 | } //$result 115 | else 116 | { 117 | return (false); 118 | } 119 | } 120 | 121 | function mysql_con() 122 | { 123 | global $cfg; 124 | global $connect; 125 | $i = 0; 126 | while ($i < 100) 127 | { 128 | $connect = new mysqli($cfg['db_server'], $cfg['db_user_name'], $cfg['db_password'], $cfg['db_database']); 129 | if ($connect->connect_error > 0) 130 | { 131 | print ('Unable to connect to database [' . $connect->connect_error . ']'); 132 | sleep(10); 133 | $i = $i + 10; 134 | } //$connect->connect_errno > 0 135 | else 136 | { 137 | $i = 100; 138 | $connect_DB = true; 139 | } 140 | } //$i < 100+ 141 | return $connect; 142 | } 143 | 144 | /** 145 | * [array_search_partial busca un string en un valor de un array y devuelve el key] 146 | * @param [type] $arr [description] 147 | * @param [type] $keyword [description] 148 | * @return [type] [description] 149 | */ 150 | 151 | function array_search_partial($arr, $keyword) 152 | { 153 | foreach($arr as $index => $string) 154 | { 155 | if (strpos($keyword, $string) !== FALSE) return $index; 156 | } //$arr as $index => $string 157 | } 158 | 159 | /** 160 | * [partial_search_array Busca si existe parte de un string en un array] 161 | * @param [type] $haystack [description] 162 | * @param [type] $needle [description] 163 | * @return [type] [description] 164 | */ 165 | 166 | function partial_search_array($haystack, $needle) 167 | { 168 | foreach($haystack as $item) 169 | { 170 | if (strpos($item, $needle) !== false) 171 | { 172 | return true; 173 | } //strpos( $item, $needle ) !== false 174 | } //$haystack as $item 175 | return false; 176 | } 177 | 178 | /** 179 | * [array_search_multiarray_strpos busca en un array por un key y devuelve si encuentra el string ] 180 | * @param [type] $array [description] 181 | * @param [type] $field [description] 182 | * @param [type] $string_to_search [description] 183 | * @return [type] [description] 184 | */ 185 | 186 | function array_search_multiarray_strpos($array, $field, $string_to_search) 187 | { 188 | foreach($array as $key => $p) 189 | { 190 | 191 | // if ( $p[ $field ] === $value ) 192 | 193 | if (strpos($string_to_search, $p[$field]) !== FALSE) return $p; 194 | } //$array as $key => $product 195 | return false; 196 | } 197 | 198 | /** 199 | * [partial_search_array Busca si existe parte de un string en un array] 200 | * @param [type] $haystack [description] 201 | * @param [type] $needle [description] 202 | * @return [type] [description] 203 | */ 204 | 205 | function partial_search_array_special($haystack, $needle) 206 | { 207 | foreach($haystack as $item) 208 | { 209 | if (count($needle) > count($item)) 210 | { //busco item en needle 211 | if (strpos($item, $needle) !== false) 212 | { 213 | return true; 214 | } //strpos( $item, $needle ) !== false 215 | } //count( $needle ) > count( $item ) 216 | else 217 | { //busco needle en item 218 | if (strpos($needle, $item) !== false) 219 | { 220 | return true; 221 | } //strpos( $needle, $item ) !== false 222 | } 223 | } //$haystack as $item 224 | return false; 225 | } 226 | 227 | /** 228 | * [get_total_rules_active Get the total record of active rules] 229 | * @return [type] [description] 230 | */ 231 | 232 | function get_total_rules_active($status=false) 233 | { 234 | global $connect; 235 | $SQL = "SELECT count(*) as TOTAL FROM `block_queue` "; 236 | if (is_numeric($status)) $SQL.=" WHERE que_processed='".$status."' ;"; 237 | // echo $SQL; 238 | if (!$result = $connect->query($SQL)) 239 | { 240 | die('There was an error running the query [' . $connect->error . ']'); 241 | } //!$result = $connect->query( $SQL ) 242 | $row = $result->fetch_assoc(); 243 | return $row[TOTAL]; 244 | } 245 | 246 | /** 247 | * [get_rules_db Get array with rules on DB] 248 | * @return [type] [description] 249 | */ 250 | 251 | function get_rules2block_db() 252 | { 253 | global $connect; 254 | $SQL = "SELECT * FROM sigs_to_block order by sig_name ;"; 255 | if (!$result = $connect->query($SQL)) 256 | { 257 | die('There was an error running the query [' . $connect->error . ']'); 258 | } //!$result = $connect->query( $SQL ) 259 | while ($row = $result->fetch_assoc()) 260 | { 261 | $array_tmp[] = $row; 262 | } //$row = $result->fetch_assoc() 263 | return $array_tmp; 264 | } 265 | 266 | /** 267 | * [check_connect_router_API check API connection ] 268 | * @return [type] [description] 269 | */ 270 | 271 | function check_connect_router_API() 272 | { 273 | global $router; 274 | require ('routeros_api.php'); 275 | 276 | $API = new RouterosAPI(); 277 | if ($API->connect($router['ip'], $router['user'], $router['pass'])) return "OK"; 278 | else return ('Unable to connect to RouterOS. Error:' . $e); 279 | $API->disconnect(); 280 | } 281 | 282 | /** 283 | * [check_service_running check service running] 284 | * @param string $service [description] 285 | * @return [type] [description] 286 | */ 287 | 288 | function check_service_running($service = "ids") 289 | { 290 | global $cfg; 291 | if ($service == "ids") $cmd = "suricata -c /etc/suricata/suricata.yaml"; 292 | elseif ($service == "ips") 293 | if (file_exists($cfg['PID_app_file'])) return "OK"; 294 | else return "NO"; 295 | $cmd_exec = "ps ax | grep -v grep | grep '$cmd' | wc -l"; 296 | 297 | // echo $cmd_exec; 298 | 299 | $ret = exec($cmd_exec); 300 | 301 | // return $ret; 302 | 303 | if ($ret) return "OK"; 304 | else return "NO"; 305 | } 306 | 307 | function obtiene_server_status() 308 | { 309 | 310 | // UPTIME 311 | 312 | $res[uptime] = shell_exec("uptime | grep -ohe 'up .*' | sed 's/,//g' | awk '{ print $2\" \"$3 }'"); 313 | $res[server_uptime] = $res[uptime]; 314 | 315 | // MEMORY 316 | 317 | if (false === ($str = @file("/proc/meminfo"))) return false; 318 | $str = implode("", $str); 319 | preg_match_all("/MemTotal\s{0,}\:+\s{0,}([\d\.]+).+?MemFree\s{0,}\:+\s{0,}([\d\.]+).+?Cached\s{0,}\:+\s{0,}([\d\.]+).+?SwapTotal\s{0,}\:+\s{0,}([\d\.]+).+?SwapFree\s{0,}\:+\s{0,}([\d\.]+)/s", $str, $buf); 320 | $res['memTotal'] = round($buf[1][0], 2); 321 | $res['memFree'] = round($buf[2][0], 2); 322 | $res['memCached'] = round($buf[3][0], 2); 323 | $res['memUsed'] = ($res['memTotal'] - $res['memFree']); 324 | $res['memPercent'] = (floatval($res['memTotal']) != 0) ? round($res['memUsed'] / $res['memTotal'] * 100, 2) : 0; 325 | $res['memRealUsed'] = ($res['memTotal'] - $res['memFree'] - $res['memCached']); 326 | $res['memRealPercent'] = (floatval($res['memTotal']) != 0) ? round($res['memRealUsed'] / $res['memTotal'] * 100, 2) : 0; 327 | $res['swapTotal'] = round($buf[4][0], 2); 328 | $res['swapFree'] = round($buf[5][0], 2); 329 | $res['swapUsed'] = ($res['swapTotal'] - $res['swapFree']); 330 | $res['swapPercent'] = (floatval($res['swapTotal']) != 0) ? round($res['swapUsed'] / $res['swapTotal'] * 100, 2) : 0; 331 | 332 | // LOAD AVG 333 | 334 | if (false === ($str = @file("/proc/loadavg"))) return false; 335 | $str = explode(" ", implode("", $str)); 336 | $str = array_chunk($str, 4); 337 | $res['loadAvg'] = implode(" ", $str[0]); 338 | $res['memTotal'] = filesize_format($res['memTotal'] * 1024); 339 | $res['memUsed'] = filesize_format($res['memUsed'] * 1024); 340 | $res['memCached'] = filesize_format($res['memCached'] * 1024); 341 | $res['swapTotal'] = filesize_format($res['swapTotal'] * 1024, '', 'GB'); 342 | $res['swapFree'] = filesize_format($res['swapFree'] * 1024); 343 | $res['swapUsed'] = filesize_format($res['swapUsed'] * 1024); 344 | return $res; 345 | } 346 | 347 | // * Format a number of bytes into a human readable format. 348 | // * Optionally choose the output format and/or force a particular unit 349 | 350 | function filesize_format($size, $level = 0, $precision = 2, $base = 1024) 351 | { 352 | $unit = array( 353 | 'B', 354 | 'kB', 355 | 'MB', 356 | 'GB', 357 | 'TB', 358 | 'PB', 359 | 'EB', 360 | 'ZB', 361 | 'YB' 362 | ); 363 | $times = floor(log($size, $base)); 364 | return sprintf("%." . $precision . "f", $size / pow($base, ($times + $level))) . " " . $unit[$times + $level]; 365 | } 366 | 367 | // Facebook like 368 | 369 | function format_fecha($time) 370 | { 371 | if ($time !== intval($time)) 372 | { 373 | $time = strtotime($time); 374 | } //$time !== intval( $time ) 375 | $d = time() - $time; 376 | if ($time < strtotime(date('Y-m-d 00:00:00')) - 60 * 60 * 24 * 3) 377 | { 378 | $format = 'F j'; 379 | if (date('Y') !== date('Y', $time)) 380 | { 381 | $format.= ", Y"; 382 | } //date( 'Y' ) !== date( 'Y', $time ) 383 | return date($format, $time); 384 | } //$time < strtotime( date( 'Y-m-d 00:00:00' ) ) - 60 * 60 * 24 * 3 385 | if ($d >= 60 * 60 * 24) 386 | { 387 | $day = 'Ayer'; 388 | if (date('l', time() - 60 * 60 * 24) !== date('l', $time)) 389 | { 390 | $day = date('l', $time); 391 | } //date( 'l', time() - 60 * 60 * 24 ) !== date( 'l', $time ) 392 | return $day . " a las " . date('g:ia', $time); 393 | } //$d >= 60 * 60 * 24 394 | if ($d >= 60 * 60 * 2) 395 | { 396 | return intval($d / (60 * 60)) . " hours ago"; 397 | } //$d >= 60 * 60 * 2 398 | if ($d >= 60 * 60) 399 | { 400 | return "1 hour ago"; 401 | } //$d >= 60 * 60 402 | if ($d >= 60 * 2) 403 | { 404 | return intval($d / 60) . " minutes ago"; 405 | } //$d >= 60 * 2 406 | if ($d >= 60) 407 | { 408 | return "a minute ago"; 409 | } //$d >= 60 410 | if ($d >= 2) 411 | { 412 | return intval($d) . " seconds"; 413 | } //$d >= 2 414 | return "a few seconds ago"; 415 | } 416 | 417 | function get_server_uptime() 418 | { 419 | $exec_uptime = preg_split("/[\s]+/", trim(shell_exec('uptime'))); 420 | $uptime = $exec_uptime[2] . ' Days'; 421 | return $uptime; 422 | } 423 | 424 | /** 425 | * [is_IPv4_IPv6 chequea si es un ipv4 o ipv6] 426 | * @param [type] $ip [description] 427 | * @return boolean [description] 428 | */ 429 | 430 | function is_IPv4_IPv6($ip = NULL) 431 | { 432 | if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) 433 | { 434 | 435 | // echo "Valid IPv4"; 436 | 437 | return 4; 438 | } 439 | elseif (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) 440 | { 441 | 442 | // echo "Valid IPv6"; 443 | 444 | return 6; 445 | } 446 | 447 | return false; 448 | } 449 | 450 | /** 451 | * [check_ip_in_whilelist check if ip is in whilelist] 452 | * @param [type] $ip [description] 453 | * @return [type] [description] 454 | */ 455 | 456 | function check_ip_in_whilelist($ip = NULL) 457 | { 458 | global $cfg; 459 | foreach($cfg['whitelist'] as $range) 460 | { 461 | if (ip_in_range($ip, $range)) return true; 462 | } 463 | 464 | return false; 465 | } 466 | 467 | /** 468 | * Check if a given ip is in a network 469 | * @param string $ip IP to check in IPV4 format eg. 127.0.0.1 470 | * @param string $range IP/CIDR netmask eg. 127.0.0.0/24, also 127.0.0.1 is accepted and /32 assumed 471 | * @return boolean true if the ip is in this range / false if not. 472 | */ 473 | 474 | function ip_in_range($ip, $range) 475 | { 476 | if (strpos($range, '/') == false) 477 | { 478 | $range.= '/32'; 479 | } 480 | 481 | // $range is in IP/CIDR format eg 127.0.0.1/24 482 | 483 | list($range, $netmask) = explode('/', $range, 2); 484 | $range_decimal = ip2long($range); 485 | $ip_decimal = ip2long($ip); 486 | $wildcard_decimal = pow(2, (32 - $netmask)) - 1; 487 | $netmask_decimal = ~ $wildcard_decimal; 488 | return (($ip_decimal & $netmask_decimal) == ($range_decimal & $netmask_decimal)); 489 | } 490 | 491 | /** 492 | * [json_object_to_html show json on html] 493 | * @param [type] $json_object_string [description] 494 | * @return [type] [description] 495 | */ 496 | 497 | function json_object_to_html($json_object_string) 498 | { 499 | $json_object = json_decode($json_object_string); 500 | if (!is_object($json_object)) 501 | { 502 | if (is_array($json_object)) 503 | { 504 | $result = "[
"; 505 | foreach($json_object as $json_obj) 506 | { 507 | $result.= "
" . json_object_to_html(json_encode($json_obj)) . "
"; 508 | if (end($json_object) != $json_obj) $result.= ","; 509 | } 510 | 511 | return $result . " ]
"; 512 | } 513 | else return json_decode($json_object_string); 514 | } 515 | 516 | $result = ""; 517 | foreach($json_object as $key => $value) 518 | { 519 | $str_value = json_object_to_html(json_encode($value)); 520 | $result.= "$key : $str_value
"; 521 | } 522 | 523 | return $result; 524 | } 525 | /** 526 | * [show_credits credits] 527 | * @return [type] [description] 528 | */ 529 | function show_credits() 530 | { 531 | return '
532 |
533 | MKE Solutions 534 |
535 |
536 |

Suricata2Mikrotik CE -Community Edition- '.VERSION.'

537 |

Designed by Maximiliano Dobladez

538 |
539 |
'; 540 | } -------------------------------------------------------------------------------- /share/ssh/Crypt/RC4.php: -------------------------------------------------------------------------------- 1 | 21 | * setKey('abcdefgh'); 27 | * 28 | * $size = 10 * 1024; 29 | * $plaintext = ''; 30 | * for ($i = 0; $i < $size; $i++) { 31 | * $plaintext.= 'a'; 32 | * } 33 | * 34 | * echo $rc4->decrypt($rc4->encrypt($plaintext)); 35 | * ?> 36 | * 37 | * 38 | * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy 39 | * of this software and associated documentation files (the "Software"), to deal 40 | * in the Software without restriction, including without limitation the rights 41 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 42 | * copies of the Software, and to permit persons to whom the Software is 43 | * furnished to do so, subject to the following conditions: 44 | * 45 | * The above copyright notice and this permission notice shall be included in 46 | * all copies or substantial portions of the Software. 47 | * 48 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 49 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 50 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 51 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 52 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 53 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 54 | * THE SOFTWARE. 55 | * 56 | * @category Crypt 57 | * @package Crypt_RC4 58 | * @author Jim Wigginton 59 | * @copyright MMVII Jim Wigginton 60 | * @license http://www.opensource.org/licenses/mit-license.html MIT License 61 | * @link http://phpseclib.sourceforge.net 62 | */ 63 | 64 | /**#@+ 65 | * @access private 66 | * @see Crypt_RC4::Crypt_RC4() 67 | */ 68 | /** 69 | * Toggles the internal implementation 70 | */ 71 | define('CRYPT_RC4_MODE_INTERNAL', 1); 72 | /** 73 | * Toggles the mcrypt implementation 74 | */ 75 | define('CRYPT_RC4_MODE_MCRYPT', 2); 76 | /**#@-*/ 77 | 78 | /**#@+ 79 | * @access private 80 | * @see Crypt_RC4::_crypt() 81 | */ 82 | define('CRYPT_RC4_ENCRYPT', 0); 83 | define('CRYPT_RC4_DECRYPT', 1); 84 | /**#@-*/ 85 | 86 | /** 87 | * Pure-PHP implementation of RC4. 88 | * 89 | * @author Jim Wigginton 90 | * @version 0.1.0 91 | * @access public 92 | * @package Crypt_RC4 93 | */ 94 | class Crypt_RC4 { 95 | /** 96 | * The Key 97 | * 98 | * @see Crypt_RC4::setKey() 99 | * @var String 100 | * @access private 101 | */ 102 | var $key = "\0"; 103 | 104 | /** 105 | * The Key Stream for encryption 106 | * 107 | * If CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT, this will be equal to the mcrypt object 108 | * 109 | * @see Crypt_RC4::setKey() 110 | * @var Array 111 | * @access private 112 | */ 113 | var $encryptStream = false; 114 | 115 | /** 116 | * The Key Stream for decryption 117 | * 118 | * If CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT, this will be equal to the mcrypt object 119 | * 120 | * @see Crypt_RC4::setKey() 121 | * @var Array 122 | * @access private 123 | */ 124 | var $decryptStream = false; 125 | 126 | /** 127 | * The $i and $j indexes for encryption 128 | * 129 | * @see Crypt_RC4::_crypt() 130 | * @var Integer 131 | * @access private 132 | */ 133 | var $encryptIndex = 0; 134 | 135 | /** 136 | * The $i and $j indexes for decryption 137 | * 138 | * @see Crypt_RC4::_crypt() 139 | * @var Integer 140 | * @access private 141 | */ 142 | var $decryptIndex = 0; 143 | 144 | /** 145 | * The Encryption Algorithm 146 | * 147 | * Only used if CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT. Only possible values are MCRYPT_RC4 or MCRYPT_ARCFOUR. 148 | * 149 | * @see Crypt_RC4::Crypt_RC4() 150 | * @var Integer 151 | * @access private 152 | */ 153 | var $mode; 154 | 155 | /** 156 | * Continuous Buffer status 157 | * 158 | * @see Crypt_RC4::enableContinuousBuffer() 159 | * @var Boolean 160 | * @access private 161 | */ 162 | var $continuousBuffer = false; 163 | 164 | /** 165 | * Default Constructor. 166 | * 167 | * Determines whether or not the mcrypt extension should be used. 168 | * 169 | * @return Crypt_RC4 170 | * @access public 171 | */ 172 | function Crypt_RC4() 173 | { 174 | if ( !defined('CRYPT_RC4_MODE') ) { 175 | switch (true) { 176 | case extension_loaded('mcrypt') && (defined('MCRYPT_ARCFOUR') || defined('MCRYPT_RC4')) && in_array('arcfour', mcrypt_list_algorithms()): 177 | define('CRYPT_RC4_MODE', CRYPT_RC4_MODE_MCRYPT); 178 | break; 179 | default: 180 | define('CRYPT_RC4_MODE', CRYPT_RC4_MODE_INTERNAL); 181 | } 182 | } 183 | 184 | switch ( CRYPT_RC4_MODE ) { 185 | case CRYPT_RC4_MODE_MCRYPT: 186 | switch (true) { 187 | case defined('MCRYPT_ARCFOUR'): 188 | $this->mode = MCRYPT_ARCFOUR; 189 | break; 190 | case defined('MCRYPT_RC4'); 191 | $this->mode = MCRYPT_RC4; 192 | } 193 | $this->encryptStream = mcrypt_module_open($this->mode, '', MCRYPT_MODE_STREAM, ''); 194 | $this->decryptStream = mcrypt_module_open($this->mode, '', MCRYPT_MODE_STREAM, ''); 195 | 196 | } 197 | } 198 | 199 | /** 200 | * Sets the key. 201 | * 202 | * Keys can be between 1 and 256 bytes long. If they are longer then 256 bytes, the first 256 bytes will 203 | * be used. If no key is explicitly set, it'll be assumed to be a single null byte. 204 | * 205 | * @access public 206 | * @param String $key 207 | */ 208 | function setKey($key) 209 | { 210 | $this->key = $key; 211 | 212 | if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT ) { 213 | mcrypt_generic_init($this->encryptStream, $this->key, ''); 214 | mcrypt_generic_init($this->decryptStream, $this->key, ''); 215 | return; 216 | } 217 | 218 | $keyLength = strlen($key); 219 | $keyStream = array(); 220 | for ($i = 0; $i < 256; $i++) { 221 | $keyStream[$i] = $i; 222 | } 223 | $j = 0; 224 | for ($i = 0; $i < 256; $i++) { 225 | $j = ($j + $keyStream[$i] + ord($key[$i % $keyLength])) & 255; 226 | $temp = $keyStream[$i]; 227 | $keyStream[$i] = $keyStream[$j]; 228 | $keyStream[$j] = $temp; 229 | } 230 | 231 | $this->encryptIndex = $this->decryptIndex = array(0, 0); 232 | $this->encryptStream = $this->decryptStream = $keyStream; 233 | } 234 | 235 | /** 236 | * Sets the password. 237 | * 238 | * Depending on what $method is set to, setPassword()'s (optional) parameters are as follows: 239 | * {@link http://en.wikipedia.org/wiki/PBKDF2 pbkdf2}: 240 | * $hash, $salt, $count, $dkLen 241 | * 242 | * @param String $password 243 | * @param optional String $method 244 | * @access public 245 | */ 246 | function setPassword($password, $method = 'pbkdf2') 247 | { 248 | $key = ''; 249 | 250 | switch ($method) { 251 | default: // 'pbkdf2' 252 | list(, , $hash, $salt, $count) = func_get_args(); 253 | if (!isset($hash)) { 254 | $hash = 'sha1'; 255 | } 256 | // WPA and WPA2 use the SSID as the salt 257 | if (!isset($salt)) { 258 | $salt = 'phpseclib/salt'; 259 | } 260 | // RFC2898#section-4.2 uses 1,000 iterations by default 261 | // WPA and WPA2 use 4,096. 262 | if (!isset($count)) { 263 | $count = 1000; 264 | } 265 | if (!isset($dkLen)) { 266 | $dkLen = 128; 267 | } 268 | 269 | if (!class_exists('Crypt_Hash')) { 270 | require_once('Crypt/Hash.php'); 271 | } 272 | 273 | $i = 1; 274 | while (strlen($key) < $dkLen) { 275 | //$dk.= $this->_pbkdf($password, $salt, $count, $i++); 276 | $hmac = new Crypt_Hash(); 277 | $hmac->setHash($hash); 278 | $hmac->setKey($password); 279 | $f = $u = $hmac->hash($salt . pack('N', $i++)); 280 | for ($j = 2; $j <= $count; $j++) { 281 | $u = $hmac->hash($u); 282 | $f^= $u; 283 | } 284 | $key.= $f; 285 | } 286 | } 287 | 288 | $this->setKey(substr($key, 0, $dkLen)); 289 | } 290 | 291 | /** 292 | * Dummy function. 293 | * 294 | * Some protocols, such as WEP, prepend an "initialization vector" to the key, effectively creating a new key [1]. 295 | * If you need to use an initialization vector in this manner, feel free to prepend it to the key, yourself, before 296 | * calling setKey(). 297 | * 298 | * [1] WEP's initialization vectors (IV's) are used in a somewhat insecure way. Since, in that protocol, 299 | * the IV's are relatively easy to predict, an attack described by 300 | * {@link http://www.drizzle.com/~aboba/IEEE/rc4_ksaproc.pdf Scott Fluhrer, Itsik Mantin, and Adi Shamir} 301 | * can be used to quickly guess at the rest of the key. The following links elaborate: 302 | * 303 | * {@link http://www.rsa.com/rsalabs/node.asp?id=2009 http://www.rsa.com/rsalabs/node.asp?id=2009} 304 | * {@link http://en.wikipedia.org/wiki/Related_key_attack http://en.wikipedia.org/wiki/Related_key_attack} 305 | * 306 | * @param String $iv 307 | * @see Crypt_RC4::setKey() 308 | * @access public 309 | */ 310 | function setIV($iv) 311 | { 312 | } 313 | 314 | /** 315 | * Encrypts a message. 316 | * 317 | * @see Crypt_RC4::_crypt() 318 | * @access public 319 | * @param String $plaintext 320 | */ 321 | function encrypt($plaintext) 322 | { 323 | return $this->_crypt($plaintext, CRYPT_RC4_ENCRYPT); 324 | } 325 | 326 | /** 327 | * Decrypts a message. 328 | * 329 | * $this->decrypt($this->encrypt($plaintext)) == $this->encrypt($this->encrypt($plaintext)). 330 | * Atleast if the continuous buffer is disabled. 331 | * 332 | * @see Crypt_RC4::_crypt() 333 | * @access public 334 | * @param String $ciphertext 335 | */ 336 | function decrypt($ciphertext) 337 | { 338 | return $this->_crypt($ciphertext, CRYPT_RC4_DECRYPT); 339 | } 340 | 341 | /** 342 | * Encrypts or decrypts a message. 343 | * 344 | * @see Crypt_RC4::encrypt() 345 | * @see Crypt_RC4::decrypt() 346 | * @access private 347 | * @param String $text 348 | * @param Integer $mode 349 | */ 350 | function _crypt($text, $mode) 351 | { 352 | if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT ) { 353 | $keyStream = $mode == CRYPT_RC4_ENCRYPT ? 'encryptStream' : 'decryptStream'; 354 | 355 | if (!$this->continuousBuffer) { 356 | mcrypt_generic_init($this->$keyStream, $this->key, ''); 357 | } 358 | 359 | return mcrypt_generic($this->$keyStream, $text); 360 | } 361 | 362 | if ($this->encryptStream === false) { 363 | $this->setKey($this->key); 364 | } 365 | 366 | switch ($mode) { 367 | case CRYPT_RC4_ENCRYPT: 368 | $keyStream = $this->encryptStream; 369 | list($i, $j) = $this->encryptIndex; 370 | break; 371 | case CRYPT_RC4_DECRYPT: 372 | $keyStream = $this->decryptStream; 373 | list($i, $j) = $this->decryptIndex; 374 | } 375 | 376 | $newText = ''; 377 | for ($k = 0; $k < strlen($text); $k++) { 378 | $i = ($i + 1) & 255; 379 | $j = ($j + $keyStream[$i]) & 255; 380 | $temp = $keyStream[$i]; 381 | $keyStream[$i] = $keyStream[$j]; 382 | $keyStream[$j] = $temp; 383 | $temp = $keyStream[($keyStream[$i] + $keyStream[$j]) & 255]; 384 | $newText.= chr(ord($text[$k]) ^ $temp); 385 | } 386 | 387 | if ($this->continuousBuffer) { 388 | switch ($mode) { 389 | case CRYPT_RC4_ENCRYPT: 390 | $this->encryptStream = $keyStream; 391 | $this->encryptIndex = array($i, $j); 392 | break; 393 | case CRYPT_RC4_DECRYPT: 394 | $this->decryptStream = $keyStream; 395 | $this->decryptIndex = array($i, $j); 396 | } 397 | } 398 | 399 | return $newText; 400 | } 401 | 402 | /** 403 | * Treat consecutive "packets" as if they are a continuous buffer. 404 | * 405 | * Say you have a 16-byte plaintext $plaintext. Using the default behavior, the two following code snippets 406 | * will yield different outputs: 407 | * 408 | * 409 | * echo $rc4->encrypt(substr($plaintext, 0, 8)); 410 | * echo $rc4->encrypt(substr($plaintext, 8, 8)); 411 | * 412 | * 413 | * echo $rc4->encrypt($plaintext); 414 | * 415 | * 416 | * The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates 417 | * another, as demonstrated with the following: 418 | * 419 | * 420 | * $rc4->encrypt(substr($plaintext, 0, 8)); 421 | * echo $rc4->decrypt($des->encrypt(substr($plaintext, 8, 8))); 422 | * 423 | * 424 | * echo $rc4->decrypt($des->encrypt(substr($plaintext, 8, 8))); 425 | * 426 | * 427 | * With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different 428 | * outputs. The reason is due to the fact that the initialization vector's change after every encryption / 429 | * decryption round when the continuous buffer is enabled. When it's disabled, they remain constant. 430 | * 431 | * Put another way, when the continuous buffer is enabled, the state of the Crypt_DES() object changes after each 432 | * encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that 433 | * continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them), 434 | * however, they are also less intuitive and more likely to cause you problems. 435 | * 436 | * @see Crypt_RC4::disableContinuousBuffer() 437 | * @access public 438 | */ 439 | function enableContinuousBuffer() 440 | { 441 | if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT ) { 442 | mcrypt_generic_init($this->encryptStream, $this->key, ''); 443 | mcrypt_generic_init($this->decryptStream, $this->key, ''); 444 | } 445 | 446 | $this->continuousBuffer = true; 447 | } 448 | 449 | /** 450 | * Treat consecutive packets as if they are a discontinuous buffer. 451 | * 452 | * The default behavior. 453 | * 454 | * @see Crypt_RC4::enableContinuousBuffer() 455 | * @access public 456 | */ 457 | function disableContinuousBuffer() 458 | { 459 | if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_INTERNAL ) { 460 | $this->encryptIndex = $this->decryptIndex = array(0, 0); 461 | $this->encryptStream = $this->decryptStream = false; 462 | } 463 | 464 | $this->continuousBuffer = false; 465 | } 466 | 467 | /** 468 | * Dummy function. 469 | * 470 | * Since RC4 is a stream cipher and not a block cipher, no padding is necessary. The only reason this function is 471 | * included is so that you can switch between a block cipher and a stream cipher transparently. 472 | * 473 | * @see Crypt_RC4::disablePadding() 474 | * @access public 475 | */ 476 | function enablePadding() 477 | { 478 | } 479 | 480 | /** 481 | * Dummy function. 482 | * 483 | * @see Crypt_RC4::enablePadding() 484 | * @access public 485 | */ 486 | function disablePadding() 487 | { 488 | } 489 | } 490 | 491 | // vim: ts=4:sw=4:et: 492 | // vim6: fdl=1: 493 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /share/ssh/Crypt/AES.php: -------------------------------------------------------------------------------- 1 | 22 | * setKey('abcdefghijklmnop'); 28 | * 29 | * $size = 10 * 1024; 30 | * $plaintext = ''; 31 | * for ($i = 0; $i < $size; $i++) { 32 | * $plaintext.= 'a'; 33 | * } 34 | * 35 | * echo $aes->decrypt($aes->encrypt($plaintext)); 36 | * ?> 37 | * 38 | * 39 | * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy 40 | * of this software and associated documentation files (the "Software"), to deal 41 | * in the Software without restriction, including without limitation the rights 42 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 43 | * copies of the Software, and to permit persons to whom the Software is 44 | * furnished to do so, subject to the following conditions: 45 | * 46 | * The above copyright notice and this permission notice shall be included in 47 | * all copies or substantial portions of the Software. 48 | * 49 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 50 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 51 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 52 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 53 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 54 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 55 | * THE SOFTWARE. 56 | * 57 | * @category Crypt 58 | * @package Crypt_AES 59 | * @author Jim Wigginton 60 | * @copyright MMVIII Jim Wigginton 61 | * @license http://www.opensource.org/licenses/mit-license.html MIT License 62 | * @link http://phpseclib.sourceforge.net 63 | */ 64 | 65 | /** 66 | * Include Crypt_Rijndael 67 | */ 68 | if (!class_exists('Crypt_Rijndael')) { 69 | require_once 'Rijndael.php'; 70 | } 71 | 72 | /**#@+ 73 | * @access public 74 | * @see Crypt_AES::encrypt() 75 | * @see Crypt_AES::decrypt() 76 | */ 77 | /** 78 | * Encrypt / decrypt using the Counter mode. 79 | * 80 | * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode. 81 | * 82 | * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29 83 | */ 84 | define('CRYPT_AES_MODE_CTR', -1); 85 | /** 86 | * Encrypt / decrypt using the Electronic Code Book mode. 87 | * 88 | * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29 89 | */ 90 | define('CRYPT_AES_MODE_ECB', 1); 91 | /** 92 | * Encrypt / decrypt using the Code Book Chaining mode. 93 | * 94 | * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29 95 | */ 96 | define('CRYPT_AES_MODE_CBC', 2); 97 | /** 98 | * Encrypt / decrypt using the Cipher Feedback mode. 99 | * 100 | * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29 101 | */ 102 | define('CRYPT_AES_MODE_CFB', 3); 103 | /** 104 | * Encrypt / decrypt using the Cipher Feedback mode. 105 | * 106 | * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29 107 | */ 108 | define('CRYPT_AES_MODE_OFB', 4); 109 | /**#@-*/ 110 | 111 | /**#@+ 112 | * @access private 113 | * @see Crypt_AES::Crypt_AES() 114 | */ 115 | /** 116 | * Toggles the internal implementation 117 | */ 118 | define('CRYPT_AES_MODE_INTERNAL', 1); 119 | /** 120 | * Toggles the mcrypt implementation 121 | */ 122 | define('CRYPT_AES_MODE_MCRYPT', 2); 123 | /**#@-*/ 124 | 125 | /** 126 | * Pure-PHP implementation of AES. 127 | * 128 | * @author Jim Wigginton 129 | * @version 0.1.0 130 | * @access public 131 | * @package Crypt_AES 132 | */ 133 | class Crypt_AES extends Crypt_Rijndael { 134 | /** 135 | * mcrypt resource for encryption 136 | * 137 | * The mcrypt resource can be recreated every time something needs to be created or it can be created just once. 138 | * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode. 139 | * 140 | * @see Crypt_AES::encrypt() 141 | * @var String 142 | * @access private 143 | */ 144 | var $enmcrypt; 145 | 146 | /** 147 | * mcrypt resource for decryption 148 | * 149 | * The mcrypt resource can be recreated every time something needs to be created or it can be created just once. 150 | * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode. 151 | * 152 | * @see Crypt_AES::decrypt() 153 | * @var String 154 | * @access private 155 | */ 156 | var $demcrypt; 157 | 158 | /** 159 | * mcrypt resource for CFB mode 160 | * 161 | * @see Crypt_AES::encrypt() 162 | * @see Crypt_AES::decrypt() 163 | * @var String 164 | * @access private 165 | */ 166 | var $ecb; 167 | 168 | /** 169 | * Default Constructor. 170 | * 171 | * Determines whether or not the mcrypt extension should be used. $mode should only, at present, be 172 | * CRYPT_AES_MODE_ECB or CRYPT_AES_MODE_CBC. If not explictly set, CRYPT_AES_MODE_CBC will be used. 173 | * 174 | * @param optional Integer $mode 175 | * @return Crypt_AES 176 | * @access public 177 | */ 178 | function Crypt_AES($mode = CRYPT_AES_MODE_CBC) 179 | { 180 | if ( !defined('CRYPT_AES_MODE') ) { 181 | switch (true) { 182 | case extension_loaded('mcrypt') && in_array('rijndael-128', mcrypt_list_algorithms()): 183 | define('CRYPT_AES_MODE', CRYPT_AES_MODE_MCRYPT); 184 | break; 185 | default: 186 | define('CRYPT_AES_MODE', CRYPT_AES_MODE_INTERNAL); 187 | } 188 | } 189 | 190 | switch ( CRYPT_AES_MODE ) { 191 | case CRYPT_AES_MODE_MCRYPT: 192 | switch ($mode) { 193 | case CRYPT_AES_MODE_ECB: 194 | $this->paddable = true; 195 | $this->mode = MCRYPT_MODE_ECB; 196 | break; 197 | case CRYPT_AES_MODE_CTR: 198 | // ctr doesn't have a constant associated with it even though it appears to be fairly widely 199 | // supported. in lieu of knowing just how widely supported it is, i've, for now, opted not to 200 | // include a compatibility layer. the layer has been implemented but, for now, is commented out. 201 | $this->mode = 'ctr'; 202 | //$this->mode = in_array('ctr', mcrypt_list_modes()) ? 'ctr' : CRYPT_AES_MODE_CTR; 203 | break; 204 | case CRYPT_AES_MODE_CFB: 205 | $this->mode = 'ncfb'; 206 | break; 207 | case CRYPT_AES_MODE_OFB: 208 | $this->mode = MCRYPT_MODE_NOFB; 209 | break; 210 | case CRYPT_AES_MODE_CBC: 211 | default: 212 | $this->paddable = true; 213 | $this->mode = MCRYPT_MODE_CBC; 214 | } 215 | 216 | break; 217 | default: 218 | switch ($mode) { 219 | case CRYPT_AES_MODE_ECB: 220 | $this->paddable = true; 221 | $this->mode = CRYPT_RIJNDAEL_MODE_ECB; 222 | break; 223 | case CRYPT_AES_MODE_CTR: 224 | $this->mode = CRYPT_RIJNDAEL_MODE_CTR; 225 | break; 226 | case CRYPT_AES_MODE_CFB: 227 | $this->mode = CRYPT_RIJNDAEL_MODE_CFB; 228 | break; 229 | case CRYPT_AES_MODE_OFB: 230 | $this->mode = CRYPT_RIJNDAEL_MODE_OFB; 231 | break; 232 | case CRYPT_AES_MODE_CBC: 233 | default: 234 | $this->paddable = true; 235 | $this->mode = CRYPT_RIJNDAEL_MODE_CBC; 236 | } 237 | } 238 | 239 | if (CRYPT_AES_MODE == CRYPT_AES_MODE_INTERNAL) { 240 | parent::Crypt_Rijndael($this->mode); 241 | } 242 | 243 | } 244 | 245 | /** 246 | * Dummy function 247 | * 248 | * Since Crypt_AES extends Crypt_Rijndael, this function is, technically, available, but it doesn't do anything. 249 | * 250 | * @access public 251 | * @param Integer $length 252 | */ 253 | function setBlockLength($length) 254 | { 255 | return; 256 | } 257 | 258 | /** 259 | * Sets the initialization vector. (optional) 260 | * 261 | * SetIV is not required when CRYPT_RIJNDAEL_MODE_ECB is being used. If not explictly set, it'll be assumed 262 | * to be all zero's. 263 | * 264 | * @access public 265 | * @param String $iv 266 | */ 267 | function setIV($iv) 268 | { 269 | parent::setIV($iv); 270 | if ( CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT ) { 271 | $this->changed = true; 272 | } 273 | } 274 | 275 | /** 276 | * Encrypts a message. 277 | * 278 | * $plaintext will be padded with up to 16 additional bytes. Other AES implementations may or may not pad in the 279 | * same manner. Other common approaches to padding and the reasons why it's necessary are discussed in the following 280 | * URL: 281 | * 282 | * {@link http://www.di-mgt.com.au/cryptopad.html http://www.di-mgt.com.au/cryptopad.html} 283 | * 284 | * An alternative to padding is to, separately, send the length of the file. This is what SSH, in fact, does. 285 | * strlen($plaintext) will still need to be a multiple of 16, however, arbitrary values can be added to make it that 286 | * length. 287 | * 288 | * @see Crypt_AES::decrypt() 289 | * @access public 290 | * @param String $plaintext 291 | */ 292 | function encrypt($plaintext) 293 | { 294 | if ( CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT ) { 295 | $this->_mcryptSetup(); 296 | 297 | // re: http://phpseclib.sourceforge.net/cfb-demo.phps 298 | // using mcrypt's default handing of CFB the above would output two different things. using phpseclib's 299 | // rewritten CFB implementation the above outputs the same thing twice. 300 | if ($this->mode == 'ncfb' && $this->continuousBuffer) { 301 | $iv = &$this->encryptIV; 302 | $pos = &$this->enbuffer['pos']; 303 | $len = strlen($plaintext); 304 | $ciphertext = ''; 305 | $i = 0; 306 | if ($pos) { 307 | $orig_pos = $pos; 308 | $max = 16 - $pos; 309 | if ($len >= $max) { 310 | $i = $max; 311 | $len-= $max; 312 | $pos = 0; 313 | } else { 314 | $i = $len; 315 | $pos+= $len; 316 | $len = 0; 317 | } 318 | $ciphertext = substr($iv, $orig_pos) ^ $plaintext; 319 | $iv = substr_replace($iv, $ciphertext, $orig_pos, $i); 320 | $this->enbuffer['enmcrypt_init'] = true; 321 | } 322 | if ($len >= 16) { 323 | if ($this->enbuffer['enmcrypt_init'] === false || $len > 280) { 324 | if ($this->enbuffer['enmcrypt_init'] === true) { 325 | mcrypt_generic_init($this->enmcrypt, $this->key, $iv); 326 | $this->enbuffer['enmcrypt_init'] = false; 327 | } 328 | $ciphertext.= mcrypt_generic($this->enmcrypt, substr($plaintext, $i, $len - $len % 16)); 329 | $iv = substr($ciphertext, -16); 330 | $len%= 16; 331 | } else { 332 | while ($len >= 16) { 333 | $iv = mcrypt_generic($this->ecb, $iv) ^ substr($plaintext, $i, 16); 334 | $ciphertext.= $iv; 335 | $len-= 16; 336 | $i+= 16; 337 | } 338 | } 339 | } 340 | 341 | if ($len) { 342 | $iv = mcrypt_generic($this->ecb, $iv); 343 | $block = $iv ^ substr($plaintext, -$len); 344 | $iv = substr_replace($iv, $block, 0, $len); 345 | $ciphertext.= $block; 346 | $pos = $len; 347 | } 348 | 349 | return $ciphertext; 350 | } 351 | 352 | if ($this->paddable) { 353 | $plaintext = $this->_pad($plaintext); 354 | } 355 | 356 | $ciphertext = mcrypt_generic($this->enmcrypt, $plaintext); 357 | 358 | if (!$this->continuousBuffer) { 359 | mcrypt_generic_init($this->enmcrypt, $this->key, $this->iv); 360 | } 361 | 362 | return $ciphertext; 363 | } 364 | 365 | return parent::encrypt($plaintext); 366 | } 367 | 368 | /** 369 | * Decrypts a message. 370 | * 371 | * If strlen($ciphertext) is not a multiple of 16, null bytes will be added to the end of the string until it is. 372 | * 373 | * @see Crypt_AES::encrypt() 374 | * @access public 375 | * @param String $ciphertext 376 | */ 377 | function decrypt($ciphertext) 378 | { 379 | if ( CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT ) { 380 | $this->_mcryptSetup(); 381 | 382 | if ($this->mode == 'ncfb' && $this->continuousBuffer) { 383 | $iv = &$this->decryptIV; 384 | $pos = &$this->debuffer['pos']; 385 | $len = strlen($ciphertext); 386 | $plaintext = ''; 387 | $i = 0; 388 | if ($pos) { 389 | $orig_pos = $pos; 390 | $max = 16 - $pos; 391 | if ($len >= $max) { 392 | $i = $max; 393 | $len-= $max; 394 | $pos = 0; 395 | } else { 396 | $i = $len; 397 | $pos+= $len; 398 | $len = 0; 399 | } 400 | // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize 401 | $plaintext = substr($iv, $orig_pos) ^ $ciphertext; 402 | $iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i); 403 | } 404 | if ($len >= 16) { 405 | $cb = substr($ciphertext, $i, $len - $len % 16); 406 | $plaintext.= mcrypt_generic($this->ecb, $iv . $cb) ^ $cb; 407 | $iv = substr($cb, -16); 408 | $len%= 16; 409 | } 410 | if ($len) { 411 | $iv = mcrypt_generic($this->ecb, $iv); 412 | $plaintext.= $iv ^ substr($ciphertext, -$len); 413 | $iv = substr_replace($iv, substr($ciphertext, -$len), 0, $len); 414 | $pos = $len; 415 | } 416 | 417 | return $plaintext; 418 | } 419 | 420 | if ($this->paddable) { 421 | // we pad with chr(0) since that's what mcrypt_generic does. to quote from http://php.net/function.mcrypt-generic : 422 | // "The data is padded with "\0" to make sure the length of the data is n * blocksize." 423 | $ciphertext = str_pad($ciphertext, (strlen($ciphertext) + 15) & 0xFFFFFFF0, chr(0)); 424 | } 425 | 426 | $plaintext = mdecrypt_generic($this->demcrypt, $ciphertext); 427 | 428 | if (!$this->continuousBuffer) { 429 | mcrypt_generic_init($this->demcrypt, $this->key, $this->iv); 430 | } 431 | 432 | return $this->paddable ? $this->_unpad($plaintext) : $plaintext; 433 | } 434 | 435 | return parent::decrypt($ciphertext); 436 | } 437 | 438 | /** 439 | * Setup mcrypt 440 | * 441 | * Validates all the variables. 442 | * 443 | * @access private 444 | */ 445 | function _mcryptSetup() 446 | { 447 | if (!$this->changed) { 448 | return; 449 | } 450 | 451 | if (!$this->explicit_key_length) { 452 | // this just copied from Crypt_Rijndael::_setup() 453 | $length = strlen($this->key) >> 2; 454 | if ($length > 8) { 455 | $length = 8; 456 | } else if ($length < 4) { 457 | $length = 4; 458 | } 459 | $this->Nk = $length; 460 | $this->key_size = $length << 2; 461 | } 462 | 463 | switch ($this->Nk) { 464 | case 4: // 128 465 | $this->key_size = 16; 466 | break; 467 | case 5: // 160 468 | case 6: // 192 469 | $this->key_size = 24; 470 | break; 471 | case 7: // 224 472 | case 8: // 256 473 | $this->key_size = 32; 474 | } 475 | 476 | $this->key = str_pad(substr($this->key, 0, $this->key_size), $this->key_size, chr(0)); 477 | $this->encryptIV = $this->decryptIV = $this->iv = str_pad(substr($this->iv, 0, 16), 16, chr(0)); 478 | 479 | if (!isset($this->enmcrypt)) { 480 | $mode = $this->mode; 481 | //$mode = $this->mode == CRYPT_AES_MODE_CTR ? MCRYPT_MODE_ECB : $this->mode; 482 | 483 | $this->demcrypt = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', $mode, ''); 484 | $this->enmcrypt = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', $mode, ''); 485 | 486 | if ($mode == 'ncfb') { 487 | $this->ecb = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_ECB, ''); 488 | } 489 | 490 | } // else should mcrypt_generic_deinit be called? 491 | 492 | mcrypt_generic_init($this->demcrypt, $this->key, $this->iv); 493 | mcrypt_generic_init($this->enmcrypt, $this->key, $this->iv); 494 | 495 | if ($this->mode == 'ncfb') { 496 | mcrypt_generic_init($this->ecb, $this->key, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"); 497 | } 498 | 499 | $this->changed = false; 500 | } 501 | 502 | /** 503 | * Treat consecutive "packets" as if they are a continuous buffer. 504 | * 505 | * The default behavior. 506 | * 507 | * @see Crypt_Rijndael::disableContinuousBuffer() 508 | * @access public 509 | */ 510 | function enableContinuousBuffer() 511 | { 512 | parent::enableContinuousBuffer(); 513 | 514 | if (CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT) { 515 | $this->enbuffer['enmcrypt_init'] = true; 516 | $this->debuffer['demcrypt_init'] = true; 517 | } 518 | } 519 | 520 | /** 521 | * Treat consecutive packets as if they are a discontinuous buffer. 522 | * 523 | * The default behavior. 524 | * 525 | * @see Crypt_Rijndael::enableContinuousBuffer() 526 | * @access public 527 | */ 528 | function disableContinuousBuffer() 529 | { 530 | parent::disableContinuousBuffer(); 531 | 532 | if (CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT) { 533 | mcrypt_generic_init($this->enmcrypt, $this->key, $this->iv); 534 | mcrypt_generic_init($this->demcrypt, $this->key, $this->iv); 535 | } 536 | } 537 | } 538 | 539 | // vim: ts=4:sw=4:et: 540 | // vim6: fdl=1: 541 | -------------------------------------------------------------------------------- /share/ssh/File/ANSI.php: -------------------------------------------------------------------------------- 1 | 35 | * @copyright MMXII Jim Wigginton 36 | * @license http://www.opensource.org/licenses/mit-license.html MIT License 37 | * @link http://phpseclib.sourceforge.net 38 | */ 39 | 40 | /** 41 | * Pure-PHP ANSI Decoder 42 | * 43 | * @author Jim Wigginton 44 | * @version 0.3.0 45 | * @access public 46 | * @package File_ANSI 47 | */ 48 | class File_ANSI { 49 | /** 50 | * Max Width 51 | * 52 | * @var Integer 53 | * @access private 54 | */ 55 | var $max_x; 56 | 57 | /** 58 | * Max Height 59 | * 60 | * @var Integer 61 | * @access private 62 | */ 63 | var $max_y; 64 | 65 | /** 66 | * Max History 67 | * 68 | * @var Integer 69 | * @access private 70 | */ 71 | var $max_history; 72 | 73 | /** 74 | * History 75 | * 76 | * @var Array 77 | * @access private 78 | */ 79 | var $history; 80 | 81 | /** 82 | * History Attributes 83 | * 84 | * @var Array 85 | * @access private 86 | */ 87 | var $history_attrs; 88 | 89 | /** 90 | * Current Column 91 | * 92 | * @var Integer 93 | * @access private 94 | */ 95 | var $x; 96 | 97 | /** 98 | * Current Row 99 | * 100 | * @var Integer 101 | * @access private 102 | */ 103 | var $y; 104 | 105 | /** 106 | * Old Column 107 | * 108 | * @var Integer 109 | * @access private 110 | */ 111 | var $old_x; 112 | 113 | /** 114 | * Old Row 115 | * 116 | * @var Integer 117 | * @access private 118 | */ 119 | var $old_y; 120 | 121 | /** 122 | * An empty attribute row 123 | * 124 | * @var Array 125 | * @access private 126 | */ 127 | var $attr_row; 128 | 129 | /** 130 | * The current screen text 131 | * 132 | * @var Array 133 | * @access private 134 | */ 135 | var $screen; 136 | 137 | /** 138 | * The current screen attributes 139 | * 140 | * @var Array 141 | * @access private 142 | */ 143 | var $attrs; 144 | 145 | /** 146 | * The current foreground color 147 | * 148 | * @var String 149 | * @access private 150 | */ 151 | var $foreground; 152 | 153 | /** 154 | * The current background color 155 | * 156 | * @var String 157 | * @access private 158 | */ 159 | var $background; 160 | 161 | /** 162 | * Bold flag 163 | * 164 | * @var Boolean 165 | * @access private 166 | */ 167 | var $bold; 168 | 169 | /** 170 | * Underline flag 171 | * 172 | * @var Boolean 173 | * @access private 174 | */ 175 | var $underline; 176 | 177 | /** 178 | * Blink flag 179 | * 180 | * @var Boolean 181 | * @access private 182 | */ 183 | var $blink; 184 | 185 | /** 186 | * Reverse flag 187 | * 188 | * @var Boolean 189 | * @access private 190 | */ 191 | var $reverse; 192 | 193 | /** 194 | * Color flag 195 | * 196 | * @var Boolean 197 | * @access private 198 | */ 199 | var $color; 200 | 201 | /** 202 | * Current ANSI code 203 | * 204 | * @var String 205 | * @access private 206 | */ 207 | var $ansi; 208 | 209 | /** 210 | * Default Constructor. 211 | * 212 | * @return File_ANSI 213 | * @access public 214 | */ 215 | function File_ANSI() 216 | { 217 | $this->setHistory(200); 218 | $this->setDimensions(80, 24); 219 | } 220 | 221 | /** 222 | * Set terminal width and height 223 | * 224 | * Resets the screen as well 225 | * 226 | * @param Integer $x 227 | * @param Integer $y 228 | * @access public 229 | */ 230 | function setDimensions($x, $y) 231 | { 232 | $this->max_x = $x - 1; 233 | $this->max_y = $y - 1; 234 | $this->x = $this->y = 0; 235 | $this->history = $this->history_attrs = array(); 236 | $this->attr_row = array_fill(0, $this->max_x + 1, ''); 237 | $this->screen = array_fill(0, $this->max_y + 1, ''); 238 | $this->attrs = array_fill(0, $this->max_y + 1, $this->attr_row); 239 | $this->foreground = 'white'; 240 | $this->background = 'black'; 241 | $this->bold = false; 242 | $this->underline = false; 243 | $this->blink = false; 244 | $this->reverse = false; 245 | $this->color = false; 246 | 247 | $this->ansi = ''; 248 | } 249 | 250 | /** 251 | * Set the number of lines that should be logged past the terminal height 252 | * 253 | * @param Integer $x 254 | * @param Integer $y 255 | * @access public 256 | */ 257 | function setHistory($history) 258 | { 259 | $this->max_history = $history; 260 | } 261 | 262 | /** 263 | * Load a string 264 | * 265 | * @param String $source 266 | * @access public 267 | */ 268 | function loadString($source) 269 | { 270 | $this->setDimensions($this->max_x + 1, $this->max_y + 1); 271 | $this->appendString($source); 272 | } 273 | 274 | /** 275 | * Appdend a string 276 | * 277 | * @param String $source 278 | * @access public 279 | */ 280 | function appendString($source) 281 | { 282 | for ($i = 0; $i < strlen($source); $i++) { 283 | if (strlen($this->ansi)) { 284 | $this->ansi.= $source[$i]; 285 | $chr = ord($source[$i]); 286 | // http://en.wikipedia.org/wiki/ANSI_escape_code#Sequence_elements 287 | // single character CSI's not currently supported 288 | switch (true) { 289 | case $this->ansi == "\x1B=": 290 | $this->ansi = ''; 291 | continue 2; 292 | case strlen($this->ansi) == 2 && $chr >= 64 && $chr <= 95 && $chr != ord('['): 293 | case strlen($this->ansi) > 2 && $chr >= 64 && $chr <= 126: 294 | break; 295 | default: 296 | continue 2; 297 | } 298 | // http://ascii-table.com/ansi-escape-sequences-vt-100.php 299 | switch ($this->ansi) { 300 | case "\x1B[H": // Move cursor to upper left corner 301 | $this->old_x = $this->x; 302 | $this->old_y = $this->y; 303 | $this->x = $this->y = 0; 304 | break; 305 | case "\x1B[J": // Clear screen from cursor down 306 | $this->history = array_merge($this->history, array_slice(array_splice($this->screen, $this->y + 1), 0, $this->old_y)); 307 | $this->screen = array_merge($this->screen, array_fill($this->y, $this->max_y, '')); 308 | 309 | $this->history_attrs = array_merge($this->history_attrs, array_slice(array_splice($this->attrs, $this->y + 1), 0, $this->old_y)); 310 | $this->attrs = array_merge($this->attrs, array_fill($this->y, $this->max_y, $this->attr_row)); 311 | 312 | if (count($this->history) == $this->max_history) { 313 | array_shift($this->history); 314 | array_shift($this->history_attrs); 315 | } 316 | case "\x1B[K": // Clear screen from cursor right 317 | $this->screen[$this->y] = substr($this->screen[$this->y], 0, $this->x); 318 | 319 | array_splice($this->attrs[$this->y], $this->x + 1); 320 | break; 321 | case "\x1B[2K": // Clear entire line 322 | $this->screen[$this->y] = str_repeat(' ', $this->x); 323 | $this->attrs[$this->y] = $this->attr_row; 324 | break; 325 | case "\x1B[?1h": // set cursor key to application 326 | case "\x1B[?25h": // show the cursor 327 | break; 328 | case "\x1BE": // Move to next line 329 | $this->_newLine(); 330 | $this->x = 0; 331 | break; 332 | default: 333 | switch (true) { 334 | case preg_match('#\x1B\[(\d+);(\d+)H#', $this->ansi, $match): // Move cursor to screen location v,h 335 | $this->old_x = $this->x; 336 | $this->old_y = $this->y; 337 | $this->x = $match[2] - 1; 338 | $this->y = $match[1] - 1; 339 | break; 340 | case preg_match('#\x1B\[(\d+)C#', $this->ansi, $match): // Move cursor right n lines 341 | $this->old_x = $this->x; 342 | $x = $match[1] - 1; 343 | break; 344 | case preg_match('#\x1B\[(\d+);(\d+)r#', $this->ansi, $match): // Set top and bottom lines of a window 345 | break; 346 | case preg_match('#\x1B\[(\d*(?:;\d*)*)m#', $this->ansi, $match): // character attributes 347 | $mods = explode(';', $match[1]); 348 | foreach ($mods as $mod) { 349 | switch ($mod) { 350 | case 0: // Turn off character attributes 351 | $this->attrs[$this->y][$this->x] = ''; 352 | 353 | if ($this->bold) $this->attrs[$this->y][$this->x].= ''; 354 | if ($this->underline) $this->attrs[$this->y][$this->x].= ''; 355 | if ($this->blink) $this->attrs[$this->y][$this->x].= ''; 356 | if ($this->color) $this->attrs[$this->y][$this->x].= ''; 357 | 358 | if ($this->reverse) { 359 | $temp = $this->background; 360 | $this->background = $this->foreground; 361 | $this->foreground = $temp; 362 | } 363 | 364 | $this->bold = $this->underline = $this->blink = $this->color = $this->reverse = false; 365 | break; 366 | case 1: // Turn bold mode on 367 | if (!$this->bold) { 368 | $this->attrs[$this->y][$this->x] = ''; 369 | $this->bold = true; 370 | } 371 | break; 372 | case 4: // Turn underline mode on 373 | if (!$this->underline) { 374 | $this->attrs[$this->y][$this->x] = ''; 375 | $this->underline = true; 376 | } 377 | break; 378 | case 5: // Turn blinking mode on 379 | if (!$this->blink) { 380 | $this->attrs[$this->y][$this->x] = ''; 381 | $this->blink = true; 382 | } 383 | break; 384 | case 7: // Turn reverse video on 385 | $this->reverse = !$this->reverse; 386 | $temp = $this->background; 387 | $this->background = $this->foreground; 388 | $this->foreground = $temp; 389 | $this->attrs[$this->y][$this->x] = ''; 390 | if ($this->color) { 391 | $this->attrs[$this->y][$this->x] = '' . $this->attrs[$this->y][$this->x]; 392 | } 393 | $this->color = true; 394 | break; 395 | default: // set colors 396 | //$front = $this->reverse ? &$this->background : &$this->foreground; 397 | $front = &$this->{ $this->reverse ? 'background' : 'foreground' }; 398 | //$back = $this->reverse ? &$this->foreground : &$this->background; 399 | $back = &$this->{ $this->reverse ? 'foreground' : 'background' }; 400 | switch ($mod) { 401 | case 30: $front = 'black'; break; 402 | case 31: $front = 'red'; break; 403 | case 32: $front = 'green'; break; 404 | case 33: $front = 'yellow'; break; 405 | case 34: $front = 'blue'; break; 406 | case 35: $front = 'magenta'; break; 407 | case 36: $front = 'cyan'; break; 408 | case 37: $front = 'white'; break; 409 | 410 | case 40: $back = 'black'; break; 411 | case 41: $back = 'red'; break; 412 | case 42: $back = 'green'; break; 413 | case 43: $back = 'yellow'; break; 414 | case 44: $back = 'blue'; break; 415 | case 45: $back = 'magenta'; break; 416 | case 46: $back = 'cyan'; break; 417 | case 47: $back = 'white'; break; 418 | 419 | default: 420 | user_error('Unsupported attribute: ' . $mod); 421 | $this->ansi = ''; 422 | break 2; 423 | } 424 | 425 | unset($temp); 426 | $this->attrs[$this->y][$this->x] = ''; 427 | if ($this->color) { 428 | $this->attrs[$this->y][$this->x] = '' . $this->attrs[$this->y][$this->x]; 429 | } 430 | $this->color = true; 431 | } 432 | } 433 | break; 434 | default: 435 | user_error("{$this->ansi} unsupported\r\n"); 436 | } 437 | } 438 | $this->ansi = ''; 439 | continue; 440 | } 441 | 442 | switch ($source[$i]) { 443 | case "\r": 444 | $this->x = 0; 445 | break; 446 | case "\n": 447 | $this->_newLine(); 448 | break; 449 | case "\x0F": // shift 450 | break; 451 | case "\x1B": // start ANSI escape code 452 | $this->ansi.= "\x1B"; 453 | break; 454 | default: 455 | $this->screen[$this->y] = substr_replace( 456 | $this->screen[$this->y], 457 | $source[$i], 458 | $this->x, 459 | 1 460 | ); 461 | 462 | if ($this->x > $this->max_x) { 463 | $this->x = 0; 464 | $this->y++; 465 | } else { 466 | $this->x++; 467 | } 468 | } 469 | } 470 | } 471 | 472 | /** 473 | * Add a new line 474 | * 475 | * Also update the $this->screen and $this->history buffers 476 | * 477 | * @access private 478 | */ 479 | function _newLine() 480 | { 481 | //if ($this->y < $this->max_y) { 482 | // $this->y++; 483 | //} 484 | 485 | while ($this->y >= $this->max_y) { 486 | $this->history = array_merge($this->history, array(array_shift($this->screen))); 487 | $this->screen[] = ''; 488 | 489 | $this->history_attrs = array_merge($this->history_attrs, array(array_shift($this->attrs))); 490 | $this->attrs[] = $this->attr_row; 491 | 492 | if (count($this->history) >= $this->max_history) { 493 | array_shift($this->history); 494 | array_shift($this->history_attrs); 495 | } 496 | 497 | $this->y--; 498 | } 499 | $this->y++; 500 | } 501 | 502 | /** 503 | * Returns the current screen without preformating 504 | * 505 | * @access private 506 | * @return String 507 | */ 508 | function _getScreen() 509 | { 510 | $output = ''; 511 | for ($i = 0; $i <= $this->max_y; $i++) { 512 | for ($j = 0; $j <= $this->max_x + 1; $j++) { 513 | if (isset($this->attrs[$i][$j])) { 514 | $output.= $this->attrs[$i][$j]; 515 | } 516 | if (isset($this->screen[$i][$j])) { 517 | $output.= htmlspecialchars($this->screen[$i][$j]); 518 | } 519 | } 520 | $output.= "\r\n"; 521 | } 522 | return rtrim($output); 523 | } 524 | 525 | /** 526 | * Returns the current screen 527 | * 528 | * @access public 529 | * @return String 530 | */ 531 | function getScreen() 532 | { 533 | return '
' . $this->_getScreen() . '
'; 534 | } 535 | 536 | /** 537 | * Returns the current screen and the x previous lines 538 | * 539 | * @access public 540 | * @return String 541 | */ 542 | function getHistory() 543 | { 544 | $scrollback = ''; 545 | for ($i = 0; $i < count($this->history); $i++) { 546 | for ($j = 0; $j <= $this->max_x + 1; $j++) { 547 | if (isset($this->history_attrs[$i][$j])) { 548 | $scrollback.= $this->history_attrs[$i][$j]; 549 | } 550 | if (isset($this->history[$i][$j])) { 551 | $scrollback.= htmlspecialchars($this->history[$i][$j]); 552 | } 553 | } 554 | $scrollback.= "\r\n"; 555 | } 556 | $scrollback.= $this->_getScreen(); 557 | 558 | return '
' . $scrollback . '
'; 559 | } 560 | } -------------------------------------------------------------------------------- /share/ssh/Net/SFTP/Stream.php: -------------------------------------------------------------------------------- 1 | 32 | * @copyright MMXIII Jim Wigginton 33 | * @license http://www.opensource.org/licenses/mit-license.html MIT License 34 | * @link http://phpseclib.sourceforge.net 35 | */ 36 | 37 | /** 38 | * SFTP Stream Wrapper 39 | * 40 | * @author Jim Wigginton 41 | * @version 0.3.2 42 | * @access public 43 | * @package Net_SFTP_Stream 44 | */ 45 | class Net_SFTP_Stream { 46 | /** 47 | * SFTP instances 48 | * 49 | * Rather than re-create the connection we re-use instances if possible 50 | * 51 | * @var Array 52 | * @access static 53 | */ 54 | static $instances; 55 | 56 | /** 57 | * SFTP instance 58 | * 59 | * @var Object 60 | * @access private 61 | */ 62 | var $sftp; 63 | 64 | /** 65 | * Path 66 | * 67 | * @var String 68 | * @access private 69 | */ 70 | var $path; 71 | 72 | /** 73 | * Mode 74 | * 75 | * @var String 76 | * @access private 77 | */ 78 | var $mode; 79 | 80 | /** 81 | * Position 82 | * 83 | * @var Integer 84 | * @access private 85 | */ 86 | var $pos; 87 | 88 | /** 89 | * Size 90 | * 91 | * @var Integer 92 | * @access private 93 | */ 94 | var $size; 95 | 96 | /** 97 | * Directory entries 98 | * 99 | * @var Array 100 | * @access private 101 | */ 102 | var $entries; 103 | 104 | /** 105 | * EOF flag 106 | * 107 | * @var Boolean 108 | * @access private 109 | */ 110 | var $eof; 111 | 112 | /** 113 | * Context resource 114 | * 115 | * Technically this needs to be publically accessible so PHP can set it directly 116 | * 117 | * @var Resource 118 | * @access public 119 | */ 120 | var $context; 121 | 122 | /** 123 | * Notification callback function 124 | * 125 | * @var Callable 126 | * @access public 127 | */ 128 | var $notification; 129 | 130 | /** 131 | * The Constructor 132 | * 133 | * @access public 134 | */ 135 | function Net_SFTP_Stream() 136 | { 137 | if (!class_exists('Net_SFTP')) { 138 | require_once('Net/SFTP.php'); 139 | } 140 | } 141 | 142 | /** 143 | * Path Parser 144 | * 145 | * Extract a path from a URI and actually connect to an SSH server if appropriate 146 | * 147 | * If "notification" is set as a context parameter the message code for successful login is 148 | * NET_SSH2_MSG_USERAUTH_SUCCESS. For a failed login it's NET_SSH2_MSG_USERAUTH_FAILURE. 149 | * 150 | * @param String $path 151 | * @return String 152 | * @access private 153 | */ 154 | function _parse_path($path) 155 | { 156 | extract(parse_url($path)); 157 | 158 | if (!isset($host)) { 159 | return false; 160 | } 161 | 162 | $context = stream_context_get_params($this->context); 163 | if (isset($context['notification'])) { 164 | $this->notification = $context['notification']; 165 | } 166 | 167 | if ($host[0] == '$') { 168 | $host = substr($host, 1); 169 | global $$host; 170 | if (!is_object($$host) || get_class($$host) != 'Net_sFTP') { 171 | return false; 172 | } 173 | $this->sftp = $$host; 174 | } else { 175 | $context = stream_context_get_options($this->context); 176 | if (isset($context['sftp']['session'])) { 177 | $sftp = $context['sftp']['session']; 178 | } 179 | if (isset($context['sftp']['sftp'])) { 180 | $sftp = $context['sftp']['sftp']; 181 | } 182 | if (isset($sftp) && is_object($sftp) && get_class($sftp) == 'Net_SFTP') { 183 | $this->sftp = $sftp; 184 | return $path; 185 | } 186 | if (isset($context['sftp']['username'])) { 187 | $user = $context['sftp']['username']; 188 | } 189 | if (isset($context['sftp']['password'])) { 190 | $pass = $context['sftp']['password']; 191 | } 192 | if (isset($context['sftp']['privkey']) && is_object($context['sftp']['privkey']) && get_Class($context['sftp']['privkey']) == 'Crypt_RSA') { 193 | $pass = $context['sftp']['privkey']; 194 | } 195 | 196 | if (!isset($user) || !isset($pass)) { 197 | return false; 198 | } 199 | 200 | // casting $pass to a string is necessary in the event that it's a Crypt_RSA object 201 | if (isset(self::$instances[$host][$port][$user][(string) $pass])) { 202 | $this->sftp = self::$instances[$host][$port][$user][(string) $pass]; 203 | } else { 204 | $this->sftp = new Net_SFTP($host, isset($port) ? $port : 22); 205 | if (isset($this->notification) && is_callable($this->notification)) { 206 | /* if !is_callable($this->notification) we could do this: 207 | 208 | user_error('fopen(): failed to call user notifier', E_USER_WARNING); 209 | 210 | the ftp wrapper gives errors like that when the notifier isn't callable. 211 | i've opted not to do that, however, since the ftp wrapper gives the line 212 | on which the fopen occurred as the line number - not the line that the 213 | user_error is on. 214 | */ 215 | call_user_func($this->notification, STREAM_NOTIFY_CONNECT, STREAM_NOTIFY_SEVERITY_INFO, '', 0, 0, 0); 216 | call_user_func($this->notification, STREAM_NOTIFY_AUTH_REQUIRED, STREAM_NOTIFY_SEVERITY_INFO, '', 0, 0, 0); 217 | if (!$this->sftp->login($user, $pass)) { 218 | call_user_func($this->notification, STREAM_NOTIFY_AUTH_RESULT, STREAM_NOTIFY_SEVERITY_ERR, 'Login Failure', NET_SSH2_MSG_USERAUTH_FAILURE, 0, 0); 219 | return false; 220 | } 221 | call_user_func($this->notification, STREAM_NOTIFY_AUTH_RESULT, STREAM_NOTIFY_SEVERITY_INFO, 'Login Success', NET_SSH2_MSG_USERAUTH_SUCCESS, 0, 0); 222 | } else { 223 | if (!$this->sftp->login($user, $pass)) { 224 | return false; 225 | } 226 | } 227 | self::$instances[$host][$port][$user][(string) $pass] = $this->sftp; 228 | } 229 | } 230 | 231 | return $path; 232 | } 233 | 234 | /** 235 | * Opens file or URL 236 | * 237 | * @param String $path 238 | * @param String $mode 239 | * @param Integer $options 240 | * @param String $opened_path 241 | * @return Boolean 242 | * @access public 243 | */ 244 | function _stream_open($path, $mode, $options, &$opened_path) 245 | { 246 | $path = $this->_parse_path($path); 247 | 248 | if ($path === false) { 249 | return false; 250 | } 251 | $this->path = $path; 252 | 253 | $this->size = $this->sftp->size($path); 254 | $this->mode = preg_replace('#[bt]$#', '', $mode); 255 | 256 | if ($this->size === false) { 257 | if ($this->mode[0] == 'r') { 258 | return false; 259 | } 260 | } else { 261 | switch ($this->mode[0]) { 262 | case 'x': 263 | return false; 264 | case 'w': 265 | case 'c': 266 | $this->sftp->truncate($path, 0); 267 | } 268 | } 269 | 270 | $this->pos = $this->mode[0] != 'a' ? 0 : $this->size; 271 | 272 | return true; 273 | } 274 | 275 | /** 276 | * Read from stream 277 | * 278 | * @param Integer $count 279 | * @return Mixed 280 | * @access public 281 | */ 282 | function _stream_read($count) 283 | { 284 | switch ($this->mode) { 285 | case 'w': 286 | case 'a': 287 | case 'x': 288 | case 'c': 289 | return false; 290 | } 291 | 292 | // commented out because some files - eg. /dev/urandom - will say their size is 0 when in fact it's kinda infinite 293 | //if ($this->pos >= $this->size) { 294 | // $this->eof = true; 295 | // return false; 296 | //} 297 | 298 | $result = $this->sftp->get($this->path, false, $this->pos, $count); 299 | if (isset($this->notification) && is_callable($this->notification)) { 300 | if ($result === false) { 301 | call_user_func($this->notification, STREAM_NOTIFY_FAILURE, STREAM_NOTIFY_SEVERITY_ERR, $this->sftp->getLastSFTPError(), NET_SFTP_OPEN, 0, 0); 302 | return 0; 303 | } 304 | // seems that PHP calls stream_read in 8k chunks 305 | call_user_func($this->notification, STREAM_NOTIFY_PROGRESS, STREAM_NOTIFY_SEVERITY_INFO, '', 0, strlen($result), $this->size); 306 | } 307 | 308 | if (empty($result)) { // ie. false or empty string 309 | $this->eof = true; 310 | return false; 311 | } 312 | $this->pos+= strlen($result); 313 | 314 | return $result; 315 | } 316 | 317 | /** 318 | * Write to stream 319 | * 320 | * @param String $data 321 | * @return Mixed 322 | * @access public 323 | */ 324 | function _stream_write($data) 325 | { 326 | switch ($this->mode) { 327 | case 'r': 328 | return false; 329 | } 330 | 331 | $result = $this->sftp->put($this->path, $data, NET_SFTP_STRING, $this->pos); 332 | if (isset($this->notification) && is_callable($this->notification)) { 333 | if (!$result) { 334 | call_user_func($this->notification, STREAM_NOTIFY_FAILURE, STREAM_NOTIFY_SEVERITY_ERR, $this->sftp->getLastSFTPError(), NET_SFTP_OPEN, 0, 0); 335 | return 0; 336 | } 337 | // seems that PHP splits up strings into 8k blocks before calling stream_write 338 | call_user_func($this->notification, STREAM_NOTIFY_PROGRESS, STREAM_NOTIFY_SEVERITY_INFO, '', 0, strlen($data), strlen($data)); 339 | } 340 | 341 | if ($result === false) { 342 | return false; 343 | } 344 | $this->pos+= strlen($data); 345 | if ($this->pos > $this->size) { 346 | $this->size = $this->pos; 347 | } 348 | $this->eof = false; 349 | return strlen($data); 350 | } 351 | 352 | /** 353 | * Retrieve the current position of a stream 354 | * 355 | * @return Integer 356 | * @access public 357 | */ 358 | function _stream_tell() 359 | { 360 | return $this->pos; 361 | } 362 | 363 | /** 364 | * Tests for end-of-file on a file pointer 365 | * 366 | * In my testing there are four classes functions that normally effect the pointer: 367 | * fseek, fputs / fwrite, fgets / fread and ftruncate. 368 | * 369 | * Only fgets / fread, however, results in feof() returning true. do fputs($fp, 'aaa') on a blank file and feof() 370 | * will return false. do fread($fp, 1) and feof() will then return true. do fseek($fp, 10) on ablank file and feof() 371 | * will return false. do fread($fp, 1) and feof() will then return true. 372 | * 373 | * @return Boolean 374 | * @access public 375 | */ 376 | function _stream_eof() 377 | { 378 | return $this->eof; 379 | } 380 | 381 | /** 382 | * Seeks to specific location in a stream 383 | * 384 | * @param Integer $offset 385 | * @param Integer $whence 386 | * @return Boolean 387 | * @access public 388 | */ 389 | function _stream_seek($offset, $whence) 390 | { 391 | switch ($whence) { 392 | case SEEK_SET: 393 | if ($offset >= $this->size || $offset < 0) { 394 | return false; 395 | } 396 | break; 397 | case SEEK_CUR: 398 | $offset+= $this->pos; 399 | break; 400 | case SEEK_END: 401 | $offset+= $this->size; 402 | } 403 | 404 | $this->pos = $offset; 405 | $this->eof = false; 406 | return true; 407 | } 408 | 409 | /** 410 | * Change stream options 411 | * 412 | * @param String $path 413 | * @param Integer $option 414 | * @param Mixed $var 415 | * @return Boolean 416 | * @access public 417 | */ 418 | function _stream_metadata($path, $option, $var) 419 | { 420 | $path = $this->_parse_path($path); 421 | if ($path === false) { 422 | return false; 423 | } 424 | 425 | // stream_metadata was introduced in PHP 5.4.0 but as of 5.4.11 the constants haven't been defined 426 | // see http://www.php.net/streamwrapper.stream-metadata and https://bugs.php.net/64246 427 | // and https://github.com/php/php-src/blob/master/main/php_streams.h#L592 428 | switch ($option) { 429 | case 1: // PHP_STREAM_META_TOUCH 430 | return $this->sftp->touch($path, $var[0], $var[1]); 431 | case 2: // PHP_STREAM_OWNER_NAME 432 | case 3: // PHP_STREAM_GROUP_NAME 433 | return false; 434 | case 4: // PHP_STREAM_META_OWNER 435 | return $this->sftp->chown($path, $var); 436 | case 5: // PHP_STREAM_META_GROUP 437 | return $this->sftp->chgrp($path, $var); 438 | case 6: // PHP_STREAM_META_ACCESS 439 | return $this->sftp->chmod($path, $var) !== false; 440 | } 441 | } 442 | 443 | /** 444 | * Retrieve the underlaying resource 445 | * 446 | * @param Integer $cast_as 447 | * @return Resource 448 | * @access public 449 | */ 450 | function _stream_cast($cast_as) 451 | { 452 | return $this->sftp->fsock; 453 | } 454 | 455 | /** 456 | * Advisory file locking 457 | * 458 | * @param Integer $operation 459 | * @return Boolean 460 | * @access public 461 | */ 462 | function _stream_lock($operation) 463 | { 464 | return false; 465 | } 466 | 467 | /** 468 | * Renames a file or directory 469 | * 470 | * Attempts to rename oldname to newname, moving it between directories if necessary. 471 | * If newname exists, it will be overwritten. This is a departure from what Net_SFTP 472 | * does. 473 | * 474 | * @param String $path_from 475 | * @param String $path_to 476 | * @return Boolean 477 | * @access public 478 | */ 479 | function _rename($path_from, $path_to) 480 | { 481 | $path1 = parse_url($path_from); 482 | $path2 = parse_url($path_to); 483 | unset($path1['path'], $path2['path']); 484 | if ($path1 != $path2) { 485 | return false; 486 | } 487 | 488 | $path_from = $this->_parse_path($path_from); 489 | $path_to = parse_url($path_to); 490 | if ($path_from == false) { 491 | return false; 492 | } 493 | 494 | $path_to = $path_to['path']; // the $component part of parse_url() was added in PHP 5.1.2 495 | // "It is an error if there already exists a file with the name specified by newpath." 496 | // -- http://tools.ietf.org/html/draft-ietf-secsh-filexfer-02#section-6.5 497 | if (!$this->sftp->rename($path_from, $path_to)) { 498 | if ($this->sftp->stat($path_to)) { 499 | return $this->sftp->delete($path_to, true) && $this->sftp->rename($path_from, $path_to); 500 | } 501 | return false; 502 | } 503 | 504 | return true; 505 | } 506 | 507 | /** 508 | * Open directory handle 509 | * 510 | * The only $options is "whether or not to enforce safe_mode (0x04)". Since safe mode was deprecated in 5.3 and 511 | * removed in 5.4 I'm just going to ignore it 512 | * 513 | * @param String $path 514 | * @param Integer $options 515 | * @return Boolean 516 | * @access public 517 | */ 518 | function _dir_opendir($path, $options) 519 | { 520 | $path = $this->_parse_path($path); 521 | if ($path === false) { 522 | return false; 523 | } 524 | $this->pos = 0; 525 | $this->entries = $this->sftp->nlist($path); 526 | return $this->entries !== false; 527 | } 528 | 529 | /** 530 | * Read entry from directory handle 531 | * 532 | * @return Mixed 533 | * @access public 534 | */ 535 | function _dir_readdir() 536 | { 537 | if (isset($this->entries[$this->pos])) { 538 | return $this->entries[$this->pos++]; 539 | } 540 | return false; 541 | } 542 | 543 | /** 544 | * Rewind directory handle 545 | * 546 | * @return Boolean 547 | * @access public 548 | */ 549 | function _dir_rewinddir() 550 | { 551 | $this->pos = 0; 552 | return true; 553 | } 554 | 555 | /** 556 | * Close directory handle 557 | * 558 | * @return Boolean 559 | * @access public 560 | */ 561 | function _dir_closedir() 562 | { 563 | return true; 564 | } 565 | 566 | /** 567 | * Create a directory 568 | * 569 | * Only valid $options is STREAM_MKDIR_RECURSIVE 570 | * 571 | * @param String $path 572 | * @param Integer $mode 573 | * @param Integer $options 574 | * @return Boolean 575 | * @access public 576 | */ 577 | function _mkdir($path, $mode, $options) 578 | { 579 | $path = $this->_parse_path($path); 580 | if ($path === false) { 581 | return false; 582 | } 583 | 584 | return $this->sftp->mkdir($path, $mode, $options & STREAM_MKDIR_RECURSIVE); 585 | } 586 | 587 | /** 588 | * Removes a directory 589 | * 590 | * Only valid $options is STREAM_MKDIR_RECURSIVE per , however, 591 | * does not have a $recursive parameter as mkdir() does so I don't know how 592 | * STREAM_MKDIR_RECURSIVE is supposed to be set. Also, when I try it out with rmdir() I get 8 as 593 | * $options. What does 8 correspond to? 594 | * 595 | * @param String $path 596 | * @param Integer $mode 597 | * @param Integer $options 598 | * @return Boolean 599 | * @access public 600 | */ 601 | function _rmdir($path, $options) 602 | { 603 | $path = $this->_parse_path($path); 604 | if ($path === false) { 605 | return false; 606 | } 607 | 608 | return $this->sftp->rmdir($path); 609 | } 610 | 611 | /** 612 | * Flushes the output 613 | * 614 | * See . Always returns true because Net_SFTP doesn't cache stuff before writing 615 | * 616 | * @return Boolean 617 | * @access public 618 | */ 619 | function _stream_flush() 620 | { 621 | return true; 622 | } 623 | 624 | /** 625 | * Retrieve information about a file resource 626 | * 627 | * @return Mixed 628 | * @access public 629 | */ 630 | function _stream_stat() 631 | { 632 | $results = $this->sftp->stat($this->path); 633 | if ($results === false) { 634 | return false; 635 | } 636 | return $results; 637 | } 638 | 639 | /** 640 | * Delete a file 641 | * 642 | * @param String $path 643 | * @return Boolean 644 | * @access public 645 | */ 646 | function _unlink($path) 647 | { 648 | $path = $this->_parse_path($path); 649 | if ($path === false) { 650 | return false; 651 | } 652 | 653 | return $this->sftp->delete($path, false); 654 | } 655 | 656 | /** 657 | * Retrieve information about a file 658 | * 659 | * Ignores the STREAM_URL_STAT_QUIET flag because the entirety of Net_SFTP_Stream is quiet by default 660 | * might be worthwhile to reconstruct bits 12-16 (ie. the file type) if mode doesn't have them but we'll 661 | * cross that bridge when and if it's reached 662 | * 663 | * @param String $path 664 | * @param Integer $flags 665 | * @return Mixed 666 | * @access public 667 | */ 668 | function _url_stat($path, $flags) 669 | { 670 | $path = $this->_parse_path($path); 671 | if ($path === false) { 672 | return false; 673 | } 674 | 675 | $results = $flags & STREAM_URL_STAT_LINK ? $this->sftp->lstat($path) : $this->sftp->stat($path); 676 | if ($results === false) { 677 | return false; 678 | } 679 | 680 | return $results; 681 | } 682 | 683 | /** 684 | * Truncate stream 685 | * 686 | * @param Integer $new_size 687 | * @return Boolean 688 | * @access public 689 | */ 690 | function _stream_truncate($new_size) 691 | { 692 | if (!$this->sftp->truncate($this->path, $new_size)) { 693 | return false; 694 | } 695 | 696 | $this->eof = false; 697 | $this->size = $new_size; 698 | 699 | return true; 700 | } 701 | 702 | /** 703 | * Change stream options 704 | * 705 | * STREAM_OPTION_WRITE_BUFFER isn't supported for the same reason stream_flush isn't. 706 | * The other two aren't supported because of limitations in Net_SFTP. 707 | * 708 | * @param Integer $option 709 | * @param Integer $arg1 710 | * @param Integer $arg2 711 | * @return Boolean 712 | * @access public 713 | */ 714 | function _stream_set_option($option, $arg1, $arg2) 715 | { 716 | return false; 717 | } 718 | 719 | /** 720 | * Close an resource 721 | * 722 | * @access public 723 | */ 724 | function _stream_close() 725 | { 726 | } 727 | 728 | /** 729 | * __call Magic Method 730 | * 731 | * When you're utilizing an SFTP stream you're not calling the methods in this class directly - PHP is calling them for you. 732 | * Which kinda begs the question... what methods is PHP calling and what parameters is it passing to them? This function 733 | * lets you figure that out. 734 | * 735 | * If NET_SFTP_STREAM_LOGGING is defined all calls will be output on the screen and then (regardless of whether or not 736 | * NET_SFTP_STREAM_LOGGING is enabled) the parameters will be passed through to the appropriate method. 737 | * 738 | * @param String 739 | * @param Array 740 | * @return Mixed 741 | * @access public 742 | */ 743 | function __call($name, $arguments) 744 | { 745 | if (defined('NET_SFTP_STREAM_LOGGING')) { 746 | echo $name . '('; 747 | $last = count($arguments) - 1; 748 | foreach ($arguments as $i => $argument) { 749 | var_export($argument); 750 | if ($i != $last) { 751 | echo ','; 752 | } 753 | } 754 | echo ")\r\n"; 755 | } 756 | $name = '_' . $name; 757 | if (!method_exists($this, $name)) { 758 | return false; 759 | } 760 | return call_user_func_array(array($this, $name), $arguments); 761 | } 762 | } 763 | 764 | if (function_exists('stream_wrapper_register')) { 765 | stream_wrapper_register('sftp', 'Net_SFTP_Stream'); 766 | } 767 | -------------------------------------------------------------------------------- /share/ssh/Crypt/Hash.php: -------------------------------------------------------------------------------- 1 | 21 | * setKey('abcdefg'); 27 | * 28 | * echo base64_encode($hash->hash('abcdefg')); 29 | * ?> 30 | * 31 | * 32 | * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy 33 | * of this software and associated documentation files (the "Software"), to deal 34 | * in the Software without restriction, including without limitation the rights 35 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 36 | * copies of the Software, and to permit persons to whom the Software is 37 | * furnished to do so, subject to the following conditions: 38 | * 39 | * The above copyright notice and this permission notice shall be included in 40 | * all copies or substantial portions of the Software. 41 | * 42 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 43 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 44 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 45 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 46 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 47 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 48 | * THE SOFTWARE. 49 | * 50 | * @category Crypt 51 | * @package Crypt_Hash 52 | * @author Jim Wigginton 53 | * @copyright MMVII Jim Wigginton 54 | * @license http://www.opensource.org/licenses/mit-license.html MIT License 55 | * @link http://phpseclib.sourceforge.net 56 | */ 57 | 58 | /**#@+ 59 | * @access private 60 | * @see Crypt_Hash::Crypt_Hash() 61 | */ 62 | /** 63 | * Toggles the internal implementation 64 | */ 65 | define('CRYPT_HASH_MODE_INTERNAL', 1); 66 | /** 67 | * Toggles the mhash() implementation, which has been deprecated on PHP 5.3.0+. 68 | */ 69 | define('CRYPT_HASH_MODE_MHASH', 2); 70 | /** 71 | * Toggles the hash() implementation, which works on PHP 5.1.2+. 72 | */ 73 | define('CRYPT_HASH_MODE_HASH', 3); 74 | /**#@-*/ 75 | 76 | /** 77 | * Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions. 78 | * 79 | * @author Jim Wigginton 80 | * @version 0.1.0 81 | * @access public 82 | * @package Crypt_Hash 83 | */ 84 | class Crypt_Hash { 85 | /** 86 | * Byte-length of compression blocks / key (Internal HMAC) 87 | * 88 | * @see Crypt_Hash::setAlgorithm() 89 | * @var Integer 90 | * @access private 91 | */ 92 | var $b; 93 | 94 | /** 95 | * Byte-length of hash output (Internal HMAC) 96 | * 97 | * @see Crypt_Hash::setHash() 98 | * @var Integer 99 | * @access private 100 | */ 101 | var $l = false; 102 | 103 | /** 104 | * Hash Algorithm 105 | * 106 | * @see Crypt_Hash::setHash() 107 | * @var String 108 | * @access private 109 | */ 110 | var $hash; 111 | 112 | /** 113 | * Key 114 | * 115 | * @see Crypt_Hash::setKey() 116 | * @var String 117 | * @access private 118 | */ 119 | var $key = false; 120 | 121 | /** 122 | * Outer XOR (Internal HMAC) 123 | * 124 | * @see Crypt_Hash::setKey() 125 | * @var String 126 | * @access private 127 | */ 128 | var $opad; 129 | 130 | /** 131 | * Inner XOR (Internal HMAC) 132 | * 133 | * @see Crypt_Hash::setKey() 134 | * @var String 135 | * @access private 136 | */ 137 | var $ipad; 138 | 139 | /** 140 | * Default Constructor. 141 | * 142 | * @param optional String $hash 143 | * @return Crypt_Hash 144 | * @access public 145 | */ 146 | function Crypt_Hash($hash = 'sha1') 147 | { 148 | if ( !defined('CRYPT_HASH_MODE') ) { 149 | switch (true) { 150 | case extension_loaded('hash'): 151 | define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_HASH); 152 | break; 153 | case extension_loaded('mhash'): 154 | define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_MHASH); 155 | break; 156 | default: 157 | define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_INTERNAL); 158 | } 159 | } 160 | 161 | $this->setHash($hash); 162 | } 163 | 164 | /** 165 | * Sets the key for HMACs 166 | * 167 | * Keys can be of any length. 168 | * 169 | * @access public 170 | * @param optional String $key 171 | */ 172 | function setKey($key = false) 173 | { 174 | $this->key = $key; 175 | } 176 | 177 | /** 178 | * Sets the hash function. 179 | * 180 | * @access public 181 | * @param String $hash 182 | */ 183 | function setHash($hash) 184 | { 185 | $hash = strtolower($hash); 186 | switch ($hash) { 187 | case 'md5-96': 188 | case 'sha1-96': 189 | $this->l = 12; // 96 / 8 = 12 190 | break; 191 | case 'md2': 192 | case 'md5': 193 | $this->l = 16; 194 | break; 195 | case 'sha1': 196 | $this->l = 20; 197 | break; 198 | case 'sha256': 199 | $this->l = 32; 200 | break; 201 | case 'sha384': 202 | $this->l = 48; 203 | break; 204 | case 'sha512': 205 | $this->l = 64; 206 | } 207 | 208 | switch ($hash) { 209 | case 'md2': 210 | $mode = CRYPT_HASH_MODE == CRYPT_HASH_MODE_HASH && in_array('md2', hash_algos()) ? 211 | CRYPT_HASH_MODE_HASH : CRYPT_HASH_MODE_INTERNAL; 212 | break; 213 | case 'sha384': 214 | case 'sha512': 215 | $mode = CRYPT_HASH_MODE == CRYPT_HASH_MODE_MHASH ? CRYPT_HASH_MODE_INTERNAL : CRYPT_HASH_MODE; 216 | break; 217 | default: 218 | $mode = CRYPT_HASH_MODE; 219 | } 220 | 221 | switch ( $mode ) { 222 | case CRYPT_HASH_MODE_MHASH: 223 | switch ($hash) { 224 | case 'md5': 225 | case 'md5-96': 226 | $this->hash = MHASH_MD5; 227 | break; 228 | case 'sha256': 229 | $this->hash = MHASH_SHA256; 230 | break; 231 | case 'sha1': 232 | case 'sha1-96': 233 | default: 234 | $this->hash = MHASH_SHA1; 235 | } 236 | return; 237 | case CRYPT_HASH_MODE_HASH: 238 | switch ($hash) { 239 | case 'md5': 240 | case 'md5-96': 241 | $this->hash = 'md5'; 242 | return; 243 | case 'md2': 244 | case 'sha256': 245 | case 'sha384': 246 | case 'sha512': 247 | $this->hash = $hash; 248 | return; 249 | case 'sha1': 250 | case 'sha1-96': 251 | default: 252 | $this->hash = 'sha1'; 253 | } 254 | return; 255 | } 256 | 257 | switch ($hash) { 258 | case 'md2': 259 | $this->b = 16; 260 | $this->hash = array($this, '_md2'); 261 | break; 262 | case 'md5': 263 | case 'md5-96': 264 | $this->b = 64; 265 | $this->hash = array($this, '_md5'); 266 | break; 267 | case 'sha256': 268 | $this->b = 64; 269 | $this->hash = array($this, '_sha256'); 270 | break; 271 | case 'sha384': 272 | case 'sha512': 273 | $this->b = 128; 274 | $this->hash = array($this, '_sha512'); 275 | break; 276 | case 'sha1': 277 | case 'sha1-96': 278 | default: 279 | $this->b = 64; 280 | $this->hash = array($this, '_sha1'); 281 | } 282 | 283 | $this->ipad = str_repeat(chr(0x36), $this->b); 284 | $this->opad = str_repeat(chr(0x5C), $this->b); 285 | } 286 | 287 | /** 288 | * Compute the HMAC. 289 | * 290 | * @access public 291 | * @param String $text 292 | * @return String 293 | */ 294 | function hash($text) 295 | { 296 | $mode = is_array($this->hash) ? CRYPT_HASH_MODE_INTERNAL : CRYPT_HASH_MODE; 297 | 298 | if (!empty($this->key) || is_string($this->key)) { 299 | switch ( $mode ) { 300 | case CRYPT_HASH_MODE_MHASH: 301 | $output = mhash($this->hash, $text, $this->key); 302 | break; 303 | case CRYPT_HASH_MODE_HASH: 304 | $output = hash_hmac($this->hash, $text, $this->key, true); 305 | break; 306 | case CRYPT_HASH_MODE_INTERNAL: 307 | /* "Applications that use keys longer than B bytes will first hash the key using H and then use the 308 | resultant L byte string as the actual key to HMAC." 309 | 310 | -- http://tools.ietf.org/html/rfc2104#section-2 */ 311 | $key = strlen($this->key) > $this->b ? call_user_func($this->hash, $this->key) : $this->key; 312 | 313 | $key = str_pad($key, $this->b, chr(0)); // step 1 314 | $temp = $this->ipad ^ $key; // step 2 315 | $temp .= $text; // step 3 316 | $temp = call_user_func($this->hash, $temp); // step 4 317 | $output = $this->opad ^ $key; // step 5 318 | $output.= $temp; // step 6 319 | $output = call_user_func($this->hash, $output); // step 7 320 | } 321 | } else { 322 | switch ( $mode ) { 323 | case CRYPT_HASH_MODE_MHASH: 324 | $output = mhash($this->hash, $text); 325 | break; 326 | case CRYPT_HASH_MODE_HASH: 327 | $output = hash($this->hash, $text, true); 328 | break; 329 | case CRYPT_HASH_MODE_INTERNAL: 330 | $output = call_user_func($this->hash, $text); 331 | } 332 | } 333 | 334 | return substr($output, 0, $this->l); 335 | } 336 | 337 | /** 338 | * Returns the hash length (in bytes) 339 | * 340 | * @access public 341 | * @return Integer 342 | */ 343 | function getLength() 344 | { 345 | return $this->l; 346 | } 347 | 348 | /** 349 | * Wrapper for MD5 350 | * 351 | * @access private 352 | * @param String $m 353 | */ 354 | function _md5($m) 355 | { 356 | return pack('H*', md5($m)); 357 | } 358 | 359 | /** 360 | * Wrapper for SHA1 361 | * 362 | * @access private 363 | * @param String $m 364 | */ 365 | function _sha1($m) 366 | { 367 | return pack('H*', sha1($m)); 368 | } 369 | 370 | /** 371 | * Pure-PHP implementation of MD2 372 | * 373 | * See {@link http://tools.ietf.org/html/rfc1319 RFC1319}. 374 | * 375 | * @access private 376 | * @param String $m 377 | */ 378 | function _md2($m) 379 | { 380 | static $s = array( 381 | 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6, 382 | 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188, 383 | 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24, 384 | 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251, 385 | 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63, 386 | 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50, 387 | 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165, 388 | 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210, 389 | 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157, 390 | 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27, 391 | 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15, 392 | 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197, 393 | 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65, 394 | 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123, 395 | 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233, 396 | 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228, 397 | 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237, 398 | 31, 26, 219, 153, 141, 51, 159, 17, 131, 20 399 | ); 400 | 401 | // Step 1. Append Padding Bytes 402 | $pad = 16 - (strlen($m) & 0xF); 403 | $m.= str_repeat(chr($pad), $pad); 404 | 405 | $length = strlen($m); 406 | 407 | // Step 2. Append Checksum 408 | $c = str_repeat(chr(0), 16); 409 | $l = chr(0); 410 | for ($i = 0; $i < $length; $i+= 16) { 411 | for ($j = 0; $j < 16; $j++) { 412 | // RFC1319 incorrectly states that C[j] should be set to S[c xor L] 413 | //$c[$j] = chr($s[ord($m[$i + $j] ^ $l)]); 414 | // per , however, C[j] should be set to S[c xor L] xor C[j] 415 | $c[$j] = chr($s[ord($m[$i + $j] ^ $l)] ^ ord($c[$j])); 416 | $l = $c[$j]; 417 | } 418 | } 419 | $m.= $c; 420 | 421 | $length+= 16; 422 | 423 | // Step 3. Initialize MD Buffer 424 | $x = str_repeat(chr(0), 48); 425 | 426 | // Step 4. Process Message in 16-Byte Blocks 427 | for ($i = 0; $i < $length; $i+= 16) { 428 | for ($j = 0; $j < 16; $j++) { 429 | $x[$j + 16] = $m[$i + $j]; 430 | $x[$j + 32] = $x[$j + 16] ^ $x[$j]; 431 | } 432 | $t = chr(0); 433 | for ($j = 0; $j < 18; $j++) { 434 | for ($k = 0; $k < 48; $k++) { 435 | $x[$k] = $t = $x[$k] ^ chr($s[ord($t)]); 436 | //$t = $x[$k] = $x[$k] ^ chr($s[ord($t)]); 437 | } 438 | $t = chr(ord($t) + $j); 439 | } 440 | } 441 | 442 | // Step 5. Output 443 | return substr($x, 0, 16); 444 | } 445 | 446 | /** 447 | * Pure-PHP implementation of SHA256 448 | * 449 | * See {@link http://en.wikipedia.org/wiki/SHA_hash_functions#SHA-256_.28a_SHA-2_variant.29_pseudocode SHA-256 (a SHA-2 variant) pseudocode - Wikipedia}. 450 | * 451 | * @access private 452 | * @param String $m 453 | */ 454 | function _sha256($m) 455 | { 456 | if (extension_loaded('suhosin')) { 457 | return pack('H*', sha256($m)); 458 | } 459 | 460 | // Initialize variables 461 | $hash = array( 462 | 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 463 | ); 464 | // Initialize table of round constants 465 | // (first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311) 466 | static $k = array( 467 | 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 468 | 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 469 | 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 470 | 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 471 | 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 472 | 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 473 | 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 474 | 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 475 | ); 476 | 477 | // Pre-processing 478 | $length = strlen($m); 479 | // to round to nearest 56 mod 64, we'll add 64 - (length + (64 - 56)) % 64 480 | $m.= str_repeat(chr(0), 64 - (($length + 8) & 0x3F)); 481 | $m[$length] = chr(0x80); 482 | // we don't support hashing strings 512MB long 483 | $m.= pack('N2', 0, $length << 3); 484 | 485 | // Process the message in successive 512-bit chunks 486 | $chunks = str_split($m, 64); 487 | foreach ($chunks as $chunk) { 488 | $w = array(); 489 | for ($i = 0; $i < 16; $i++) { 490 | extract(unpack('Ntemp', $this->_string_shift($chunk, 4))); 491 | $w[] = $temp; 492 | } 493 | 494 | // Extend the sixteen 32-bit words into sixty-four 32-bit words 495 | for ($i = 16; $i < 64; $i++) { 496 | $s0 = $this->_rightRotate($w[$i - 15], 7) ^ 497 | $this->_rightRotate($w[$i - 15], 18) ^ 498 | $this->_rightShift( $w[$i - 15], 3); 499 | $s1 = $this->_rightRotate($w[$i - 2], 17) ^ 500 | $this->_rightRotate($w[$i - 2], 19) ^ 501 | $this->_rightShift( $w[$i - 2], 10); 502 | $w[$i] = $this->_add($w[$i - 16], $s0, $w[$i - 7], $s1); 503 | 504 | } 505 | 506 | // Initialize hash value for this chunk 507 | list($a, $b, $c, $d, $e, $f, $g, $h) = $hash; 508 | 509 | // Main loop 510 | for ($i = 0; $i < 64; $i++) { 511 | $s0 = $this->_rightRotate($a, 2) ^ 512 | $this->_rightRotate($a, 13) ^ 513 | $this->_rightRotate($a, 22); 514 | $maj = ($a & $b) ^ 515 | ($a & $c) ^ 516 | ($b & $c); 517 | $t2 = $this->_add($s0, $maj); 518 | 519 | $s1 = $this->_rightRotate($e, 6) ^ 520 | $this->_rightRotate($e, 11) ^ 521 | $this->_rightRotate($e, 25); 522 | $ch = ($e & $f) ^ 523 | ($this->_not($e) & $g); 524 | $t1 = $this->_add($h, $s1, $ch, $k[$i], $w[$i]); 525 | 526 | $h = $g; 527 | $g = $f; 528 | $f = $e; 529 | $e = $this->_add($d, $t1); 530 | $d = $c; 531 | $c = $b; 532 | $b = $a; 533 | $a = $this->_add($t1, $t2); 534 | } 535 | 536 | // Add this chunk's hash to result so far 537 | $hash = array( 538 | $this->_add($hash[0], $a), 539 | $this->_add($hash[1], $b), 540 | $this->_add($hash[2], $c), 541 | $this->_add($hash[3], $d), 542 | $this->_add($hash[4], $e), 543 | $this->_add($hash[5], $f), 544 | $this->_add($hash[6], $g), 545 | $this->_add($hash[7], $h) 546 | ); 547 | } 548 | 549 | // Produce the final hash value (big-endian) 550 | return pack('N8', $hash[0], $hash[1], $hash[2], $hash[3], $hash[4], $hash[5], $hash[6], $hash[7]); 551 | } 552 | 553 | /** 554 | * Pure-PHP implementation of SHA384 and SHA512 555 | * 556 | * @access private 557 | * @param String $m 558 | */ 559 | function _sha512($m) 560 | { 561 | if (!class_exists('Math_BigInteger')) { 562 | require_once('Math/BigInteger.php'); 563 | } 564 | 565 | static $init384, $init512, $k; 566 | 567 | if (!isset($k)) { 568 | // Initialize variables 569 | $init384 = array( // initial values for SHA384 570 | 'cbbb9d5dc1059ed8', '629a292a367cd507', '9159015a3070dd17', '152fecd8f70e5939', 571 | '67332667ffc00b31', '8eb44a8768581511', 'db0c2e0d64f98fa7', '47b5481dbefa4fa4' 572 | ); 573 | $init512 = array( // initial values for SHA512 574 | '6a09e667f3bcc908', 'bb67ae8584caa73b', '3c6ef372fe94f82b', 'a54ff53a5f1d36f1', 575 | '510e527fade682d1', '9b05688c2b3e6c1f', '1f83d9abfb41bd6b', '5be0cd19137e2179' 576 | ); 577 | 578 | for ($i = 0; $i < 8; $i++) { 579 | $init384[$i] = new Math_BigInteger($init384[$i], 16); 580 | $init384[$i]->setPrecision(64); 581 | $init512[$i] = new Math_BigInteger($init512[$i], 16); 582 | $init512[$i]->setPrecision(64); 583 | } 584 | 585 | // Initialize table of round constants 586 | // (first 64 bits of the fractional parts of the cube roots of the first 80 primes 2..409) 587 | $k = array( 588 | '428a2f98d728ae22', '7137449123ef65cd', 'b5c0fbcfec4d3b2f', 'e9b5dba58189dbbc', 589 | '3956c25bf348b538', '59f111f1b605d019', '923f82a4af194f9b', 'ab1c5ed5da6d8118', 590 | 'd807aa98a3030242', '12835b0145706fbe', '243185be4ee4b28c', '550c7dc3d5ffb4e2', 591 | '72be5d74f27b896f', '80deb1fe3b1696b1', '9bdc06a725c71235', 'c19bf174cf692694', 592 | 'e49b69c19ef14ad2', 'efbe4786384f25e3', '0fc19dc68b8cd5b5', '240ca1cc77ac9c65', 593 | '2de92c6f592b0275', '4a7484aa6ea6e483', '5cb0a9dcbd41fbd4', '76f988da831153b5', 594 | '983e5152ee66dfab', 'a831c66d2db43210', 'b00327c898fb213f', 'bf597fc7beef0ee4', 595 | 'c6e00bf33da88fc2', 'd5a79147930aa725', '06ca6351e003826f', '142929670a0e6e70', 596 | '27b70a8546d22ffc', '2e1b21385c26c926', '4d2c6dfc5ac42aed', '53380d139d95b3df', 597 | '650a73548baf63de', '766a0abb3c77b2a8', '81c2c92e47edaee6', '92722c851482353b', 598 | 'a2bfe8a14cf10364', 'a81a664bbc423001', 'c24b8b70d0f89791', 'c76c51a30654be30', 599 | 'd192e819d6ef5218', 'd69906245565a910', 'f40e35855771202a', '106aa07032bbd1b8', 600 | '19a4c116b8d2d0c8', '1e376c085141ab53', '2748774cdf8eeb99', '34b0bcb5e19b48a8', 601 | '391c0cb3c5c95a63', '4ed8aa4ae3418acb', '5b9cca4f7763e373', '682e6ff3d6b2b8a3', 602 | '748f82ee5defb2fc', '78a5636f43172f60', '84c87814a1f0ab72', '8cc702081a6439ec', 603 | '90befffa23631e28', 'a4506cebde82bde9', 'bef9a3f7b2c67915', 'c67178f2e372532b', 604 | 'ca273eceea26619c', 'd186b8c721c0c207', 'eada7dd6cde0eb1e', 'f57d4f7fee6ed178', 605 | '06f067aa72176fba', '0a637dc5a2c898a6', '113f9804bef90dae', '1b710b35131c471b', 606 | '28db77f523047d84', '32caab7b40c72493', '3c9ebe0a15c9bebc', '431d67c49c100d4c', 607 | '4cc5d4becb3e42b6', '597f299cfc657e2a', '5fcb6fab3ad6faec', '6c44198c4a475817' 608 | ); 609 | 610 | for ($i = 0; $i < 80; $i++) { 611 | $k[$i] = new Math_BigInteger($k[$i], 16); 612 | } 613 | } 614 | 615 | $hash = $this->l == 48 ? $init384 : $init512; 616 | 617 | // Pre-processing 618 | $length = strlen($m); 619 | // to round to nearest 112 mod 128, we'll add 128 - (length + (128 - 112)) % 128 620 | $m.= str_repeat(chr(0), 128 - (($length + 16) & 0x7F)); 621 | $m[$length] = chr(0x80); 622 | // we don't support hashing strings 512MB long 623 | $m.= pack('N4', 0, 0, 0, $length << 3); 624 | 625 | // Process the message in successive 1024-bit chunks 626 | $chunks = str_split($m, 128); 627 | foreach ($chunks as $chunk) { 628 | $w = array(); 629 | for ($i = 0; $i < 16; $i++) { 630 | $temp = new Math_BigInteger($this->_string_shift($chunk, 8), 256); 631 | $temp->setPrecision(64); 632 | $w[] = $temp; 633 | } 634 | 635 | // Extend the sixteen 32-bit words into eighty 32-bit words 636 | for ($i = 16; $i < 80; $i++) { 637 | $temp = array( 638 | $w[$i - 15]->bitwise_rightRotate(1), 639 | $w[$i - 15]->bitwise_rightRotate(8), 640 | $w[$i - 15]->bitwise_rightShift(7) 641 | ); 642 | $s0 = $temp[0]->bitwise_xor($temp[1]); 643 | $s0 = $s0->bitwise_xor($temp[2]); 644 | $temp = array( 645 | $w[$i - 2]->bitwise_rightRotate(19), 646 | $w[$i - 2]->bitwise_rightRotate(61), 647 | $w[$i - 2]->bitwise_rightShift(6) 648 | ); 649 | $s1 = $temp[0]->bitwise_xor($temp[1]); 650 | $s1 = $s1->bitwise_xor($temp[2]); 651 | $w[$i] = $w[$i - 16]->copy(); 652 | $w[$i] = $w[$i]->add($s0); 653 | $w[$i] = $w[$i]->add($w[$i - 7]); 654 | $w[$i] = $w[$i]->add($s1); 655 | } 656 | 657 | // Initialize hash value for this chunk 658 | $a = $hash[0]->copy(); 659 | $b = $hash[1]->copy(); 660 | $c = $hash[2]->copy(); 661 | $d = $hash[3]->copy(); 662 | $e = $hash[4]->copy(); 663 | $f = $hash[5]->copy(); 664 | $g = $hash[6]->copy(); 665 | $h = $hash[7]->copy(); 666 | 667 | // Main loop 668 | for ($i = 0; $i < 80; $i++) { 669 | $temp = array( 670 | $a->bitwise_rightRotate(28), 671 | $a->bitwise_rightRotate(34), 672 | $a->bitwise_rightRotate(39) 673 | ); 674 | $s0 = $temp[0]->bitwise_xor($temp[1]); 675 | $s0 = $s0->bitwise_xor($temp[2]); 676 | $temp = array( 677 | $a->bitwise_and($b), 678 | $a->bitwise_and($c), 679 | $b->bitwise_and($c) 680 | ); 681 | $maj = $temp[0]->bitwise_xor($temp[1]); 682 | $maj = $maj->bitwise_xor($temp[2]); 683 | $t2 = $s0->add($maj); 684 | 685 | $temp = array( 686 | $e->bitwise_rightRotate(14), 687 | $e->bitwise_rightRotate(18), 688 | $e->bitwise_rightRotate(41) 689 | ); 690 | $s1 = $temp[0]->bitwise_xor($temp[1]); 691 | $s1 = $s1->bitwise_xor($temp[2]); 692 | $temp = array( 693 | $e->bitwise_and($f), 694 | $g->bitwise_and($e->bitwise_not()) 695 | ); 696 | $ch = $temp[0]->bitwise_xor($temp[1]); 697 | $t1 = $h->add($s1); 698 | $t1 = $t1->add($ch); 699 | $t1 = $t1->add($k[$i]); 700 | $t1 = $t1->add($w[$i]); 701 | 702 | $h = $g->copy(); 703 | $g = $f->copy(); 704 | $f = $e->copy(); 705 | $e = $d->add($t1); 706 | $d = $c->copy(); 707 | $c = $b->copy(); 708 | $b = $a->copy(); 709 | $a = $t1->add($t2); 710 | } 711 | 712 | // Add this chunk's hash to result so far 713 | $hash = array( 714 | $hash[0]->add($a), 715 | $hash[1]->add($b), 716 | $hash[2]->add($c), 717 | $hash[3]->add($d), 718 | $hash[4]->add($e), 719 | $hash[5]->add($f), 720 | $hash[6]->add($g), 721 | $hash[7]->add($h) 722 | ); 723 | } 724 | 725 | // Produce the final hash value (big-endian) 726 | // (Crypt_Hash::hash() trims the output for hashes but not for HMACs. as such, we trim the output here) 727 | $temp = $hash[0]->toBytes() . $hash[1]->toBytes() . $hash[2]->toBytes() . $hash[3]->toBytes() . 728 | $hash[4]->toBytes() . $hash[5]->toBytes(); 729 | if ($this->l != 48) { 730 | $temp.= $hash[6]->toBytes() . $hash[7]->toBytes(); 731 | } 732 | 733 | return $temp; 734 | } 735 | 736 | /** 737 | * Right Rotate 738 | * 739 | * @access private 740 | * @param Integer $int 741 | * @param Integer $amt 742 | * @see _sha256() 743 | * @return Integer 744 | */ 745 | function _rightRotate($int, $amt) 746 | { 747 | $invamt = 32 - $amt; 748 | $mask = (1 << $invamt) - 1; 749 | return (($int << $invamt) & 0xFFFFFFFF) | (($int >> $amt) & $mask); 750 | } 751 | 752 | /** 753 | * Right Shift 754 | * 755 | * @access private 756 | * @param Integer $int 757 | * @param Integer $amt 758 | * @see _sha256() 759 | * @return Integer 760 | */ 761 | function _rightShift($int, $amt) 762 | { 763 | $mask = (1 << (32 - $amt)) - 1; 764 | return ($int >> $amt) & $mask; 765 | } 766 | 767 | /** 768 | * Not 769 | * 770 | * @access private 771 | * @param Integer $int 772 | * @see _sha256() 773 | * @return Integer 774 | */ 775 | function _not($int) 776 | { 777 | return ~$int & 0xFFFFFFFF; 778 | } 779 | 780 | /** 781 | * Add 782 | * 783 | * _sha256() adds multiple unsigned 32-bit integers. Since PHP doesn't support unsigned integers and since the 784 | * possibility of overflow exists, care has to be taken. Math_BigInteger() could be used but this should be faster. 785 | * 786 | * @param Integer $... 787 | * @return Integer 788 | * @see _sha256() 789 | * @access private 790 | */ 791 | function _add() 792 | { 793 | static $mod; 794 | if (!isset($mod)) { 795 | $mod = pow(2, 32); 796 | } 797 | 798 | $result = 0; 799 | $arguments = func_get_args(); 800 | foreach ($arguments as $argument) { 801 | $result+= $argument < 0 ? ($argument & 0x7FFFFFFF) + 0x80000000 : $argument; 802 | } 803 | 804 | return fmod($result, $mod); 805 | } 806 | 807 | /** 808 | * String Shift 809 | * 810 | * Inspired by array_shift 811 | * 812 | * @param String $string 813 | * @param optional Integer $index 814 | * @return String 815 | * @access private 816 | */ 817 | function _string_shift(&$string, $index = 1) 818 | { 819 | $substr = substr($string, 0, $index); 820 | $string = substr($string, $index); 821 | return $substr; 822 | } 823 | } 824 | --------------------------------------------------------------------------------