3 * status-srv/sks.inc.php
4 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Kristian Fiskerstrand
6 * This file is part of SKS Keyserver Pool (http://sks-keyservers.net)
8 * The Author can be reached by electronic mail at kf@sumptuouscapital.com
9 * Communication using OpenPGP is preferred - a copy of the public key 0x0B7F8B60E3EDFAE3
10 * is available in all the common keyservers or in hkp://pool.sks-keyservers.net
12 * This program is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation, either version 3 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25 error_reporting(E_ALL
);
27 date_default_timezone_set("UTC");
28 function event_serverreturn($fd, $flag, $arg)
35 while(($buf = fgets($fd, 1024)) !== false)
42 echo "Error: popen never ended\n";
45 $sadd = new sks_peer($serverobj, null, $json);
46 $serverobj->add_server($sadd);
51 unset($serverobj->fh
[$sadd->get_hostname()]);
55 function gethostbyname6($host, $try_a = false) {
56 // get AAAA record for $host
57 // if $try_a is true, if AAAA fails, it tries for A
58 // the first match found is returned
59 // otherwise returns false
61 $dns = gethostbynamel6($host, $try_a);
62 if ($dns == false) { return false; }
63 else { return $dns[0]; }
66 function gethostbynamel6($host, $try_a = false) {
67 // get AAAA records for $host,
68 // if $try_a is true, if AAAA fails, it tries for A
69 // results are returned in an array of ips found matching type
70 // otherwise returns false
72 $dns6 = dns_get_record($host, DNS_AAAA
);
74 $dns4 = dns_get_record($host, DNS_A
);
75 $dns = array_merge($dns4, $dns6);
77 else { $dns = $dns6; }
80 foreach ($dns as $record) {
81 if ($record["type"] == "A") {
82 $ip4[] = $record["ip"];
84 if ($record["type"] == "AAAA") {
85 $ip6[] = $record["ipv6"];
88 if (count($ip6) < 1) {
90 if (count($ip4) < 1) {
106 class sks_servercollection
108 private $servers = array();
109 private $servers_queue = array();
111 private $events = array();
113 public $fh = array();
115 public function sks_servercollection()
117 $this->created
= time();
118 $this->event_base
= event_base_new();
123 public function add_server_to_queue($server)
125 if($this->do_add($server) && !isset($this->events
[$server]))
127 $this->servers_queue
[$server] = true;
129 $this->events
[$server] = event_new();
130 $this->fh
[$server] = popen("/usr/bin/php -f /webs/sks-keyservers.net/status/sks_get_peer_data.php {$server}", "r");
131 event_set($this->events
[$server], $this->fh
[$server], EV_TIMEOUT | EV_READ | EV_WRITE | EV_PERSIST
, "event_serverreturn", array($this->events
[$server], $this->event_base
, &$this, $this->created
));
132 event_base_set($this->events
[$server], $this->event_base
);
133 event_add($this->events
[$server], 70000);
137 public function get_queue_count()
139 return count($this->fh
);
142 public function add_server($obj)
144 if($obj != null && $obj->get_hostname() != "")
146 if(!isset($this->servers
[$obj->get_hostname()]))
147 $this->servers
[$obj->get_hostname()] = $obj;
151 public function get_servers()
153 return $this->servers
;
156 public function include_ipv6()
158 $should_include_ipv6 = true;
160 $kfwebs_included = false;
162 foreach($this->servers
as $server)
164 if($server->get_ipv6())
167 if($server->get_hostname() == "keys.kfwebs.net")
168 $kfwebs_included = true;
171 if($kfwebs_included && $count_ipv6 == 1)
177 public function get_server_by_name($name)
179 foreach($this->servers
as $id=>$server)
181 if($server->get_hostname() == $name ||
$server->get_called_hostname() == $name)
182 return $this->servers
[$id];
187 public function get_time()
189 return $this->created
;
192 public function do_add($n)
194 if(isset($this->servers
[$n]) ||
isset($this->servers_queue
[$n]))
204 private $called_hostname;
205 private $server_contact;
211 private $statusok = true;
212 private $statusipv6ok = false;
213 private $port80 = false;
214 private $has_hkps = false;
215 private $hkps_port = 0;
216 private $statusfaultreason;
217 private $peers = array();
219 private $responsetime = -1;
220 private $http_response_server;
221 private $http_response_via;
222 private $http_post_expect_error = false;
223 private $affected_cve2014_3207 = true;
224 private $tor_addresse = "";
226 public function get_numkeys() { return $this->numkeys
; }
227 public function get_software() { return $this->software
; }
228 public function get_version() { return $this->version
; }
229 public function get_hostname() { return $this->hostname
; }
230 public function get_server_contact() {
231 return strtr(strtoupper($this->server_contact
), array("X" => "x", " " => ""));
233 public function get_called_hostname() { return $this->called_hostname
; }
234 public function get_port() { return $this->port
; }
235 public function get_recon_port() { return $this->recon_port
; }
236 public function get_peers() {return $this->peers
;}
237 public function get_statusok() {return $this->statusok
;}
238 public function get_serversarr() {return $this->servers
;}
239 public function get_ipv6() {return $this->statusipv6ok
;}
240 public function get_has_hkps() {return ($this->has_hkps
&& $this->get_is_loadbalanced());}
241 public function get_hkps_port() {return $this->hkps_port
;}
242 public function get_port80() {return $this->port80
;}
243 public function get_responsetime() {return $this->responsetime
;}
244 public function get_http_response_server(){return $this->http_response_server
;}
245 public function get_has_http_response_via(){return $this->http_response_via
;}
246 public function get_is_loadbalanced(){return $this->is_loadbalanced();}
247 public function get_is_reverse_proxy() {return $this->is_accepted_server_response();}
248 public function get_http_post_error(){return $this->http_post_expect_error
;}
249 public function get_affected_cve2014_3207(){return $this->affected_cve2014_3207
;}
250 public function get_tor_addresse(){return $this->tor_addresse
;}
251 public function version_satisfy_min($min_version, $development = 0)
254 * Convert version string into array with
255 * (major, minor, release)
257 $min_version_tuple = preg_split("/\./", $min_version);
258 preg_match("/(\d+\.\d+\.\d+)/", $this->version
, $matches);
259 if(isset($matches[1]))
260 $version_tuple = preg_split("/\./", $matches[1]);
262 $version_tuple = preg_split("/\./", $this->version
);
265 if((int)($version_tuple[0]) > (int)($min_version_tuple[0]))
270 ((int)($version_tuple[0]) == (int)($min_version_tuple[0]))
271 && ((int)($version_tuple[1]) > (int)($min_version_tuple[1]))
277 ((int)($version_tuple[0]) == (int)($min_version_tuple[0]))
278 && ((int)($version_tuple[1]) == (int)($min_version_tuple[1]))
279 && ((int)($version_tuple[2]) >= (int)($min_version_tuple[2]))
280 && ($development ?
substr($this->version
, -1) == "+" : true)
284 // If not true by now, return false
288 public function sks_get_peer_data()
291 $fp = popen("/usr/bin/php -f /webs/sks-keyservers.net/status/sks_get_peer_data.php {$this->hostname}", "r");
296 while(($buf = fgets($fp, 1024)) !== false)
305 public function sks_peer(&$servers, $hostname=false, $jinp=false)
309 $this->hostname
= $hostname;
310 $jinp = $this->sks_get_peer_data();
313 // Convert back from json
314 $fp_rb_dec = json_decode($jinp, true);
316 $this->hostname
= strtolower($fp_rb_dec['hostname']);
317 $this->called_hostname
= strtolower($fp_rb_dec['called_hostname']);
319 $this->port
= $fp_rb_dec['port'];
321 $this->statusok
= $fp_rb_dec['statusok'];
324 echo "Server: {$this->hostname} has status: ".($this->statusok ?
"OK" : "Not OK")."\n";
328 $this->responsetime
= $fp_rb_dec['responsetime'];
329 $this->http_response_server
= $fp_rb_dec['http_response_server'];
330 $this->http_response_via
= $fp_rb_dec['http_response_via'];
331 $this->numkeys
= $fp_rb_dec['numkeys'];
332 $this->software
= $fp_rb_dec['software'];
333 $this->version
= $fp_rb_dec['version'];
334 $this->server_contact
= $fp_rb_dec['server_contact'];
336 if(isset($fp_rb_dec['recon_port']))
337 $this->recon_port
= $fp_rb_dec['recon_port'];
339 $this->http_post_expect_error
= $fp_rb_dec['postExpect'];
341 if(isset($fp_rb_dec['peers']) && is_array($fp_rb_dec['peers']))
342 $this->peers
= $fp_rb_dec['peers'];
344 $this->peers
= array();
346 $this->statusipv6ok
= $fp_rb_dec['statusipv6ok'];
347 $this->port80
= $fp_rb_dec['port80'];
348 $this->has_hkps
= $fp_rb_dec['has_hkps'];
349 $this->hkps_port
= $fp_rb_dec['hkps_port'];
350 $this->tor_addresse
= $fp_rb_dec['tor_addresse'];
351 $this->affected_cve2014_3207
= $fp_rb_dec['cve-2014-3207'];
354 if(is_array($this->peers
) && count($this->peers
) > 0)
356 foreach($this->peers
as $peer)
358 $servers->add_server_to_queue($peer);
362 } // End function sks_peer
364 private function is_loadbalanced()
366 $loadbalanced = array(
370 "keyserver.searchy.nl",
371 "keyserver.codinginfinity.com",
379 return $this->is_accepted_server_response() && in_array($this->hostname
, $loadbalanced);
382 private function is_accepted_server_response()
384 $is_accepted_server = false;
386 // Check if Server: header contain a valid response
387 $accepted_http_server_list = array("nginx", "apache");
388 foreach($accepted_http_server_list as $revprox)
390 if(strstr(strtolower($this->http_response_server
), $revprox) !== false)
391 $is_accepted_server = true;
394 // Check if Via: header is set, presume proxy if it is
395 if($this->http_response_via
)
396 $is_accepted_server = true;
398 return $is_accepted_server;
399 } // end is_accepted_server_response
405 public function sks_stats()
407 $servers = new sks_servercollection
;
409 $initial_servers = array("keys2.kfwebs.net", "zimmermann.mayfirst.org", "keyserver.kim-minh.com", "pgp.circl.lu", "keys.niif.hu", "sks.b4ckbone.de", "keyserver.opensuse.org");
411 foreach($initial_servers as $s)
413 $sadd = new sks_peer($servers, $s);
414 $servers->add_server($sadd);
415 echo "Adding: {$s}\n";
418 echo "Done adding primaries\n";
419 event_base_loop($servers->event_base
);
421 echo "Done looping\n";
424 if(!file_exists(dirname(__FILE__
)."/sks_cache_status_collection.serialized"))
425 $status_collection = new sks_status_collection();
427 $status_collection = unserialize(file_get_contents(dirname(__FILE__
)."/sks_cache_status_collection.serialized"));
429 $status_collection->run($servers);
430 $nk = $status_collection->get_statistics_data();
431 echo "Numkey set to:\t".$nk['numkeys'];
433 file_put_contents(dirname(__FILE__
)."/sks_cache.serialized",serialize($servers));
434 file_put_contents(dirname(__FILE__
)."/sks_cache_status_collection.serialized",serialize($status_collection));