Merge branch 'bug-1393' into testserver-stable
[cacert-devel.git] / includes / general.php
1 <? /*
2 LibreSSL - CAcert web application
3 Copyright (C) 2004-2008 CAcert Inc.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; version 2 of the License.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 require_once(dirname(__FILE__)."/lib/general.php");
20 require_once(dirname(__FILE__)."/notary.inc.php");
21
22 session_name("cacert");
23 session_start();
24
25 // session_register("_config");
26 // session_register("profile");
27 // session_register("signup");
28 // session_register("lostpw");
29 // if($_SESSION['profile']['id'] > 0)
30 // session_regenerate_id();
31
32 //cf. http://stackoverflow.com/a/14532168
33 if(!defined('ENT_HTML401')) define('ENT_HTML401', 0);
34 if(!defined('ENT_XML1')) define('ENT_XML1', 16);
35 if(!defined('ENT_XHTML')) define('ENT_XHTML', 32);
36 if(!defined('ENT_HTML5')) define('ENT_HTML5', (32|16));
37
38 $pageLoadTime_Start = microtime(true);
39
40 $junk = array(_("Face to Face Meeting"), _("Trusted Third Parties"), _("Thawte Points Transfer"), _("Administrative Increase"),
41 _("CT Magazine - Germany"), _("Temporary Increase"), _("Unknown"));
42
43 $_SESSION['_config']['errmsg']="";
44
45 $id = 0; if(array_key_exists("id",$_REQUEST)) $id=intval($_REQUEST['id']);
46 $oldid = 0; if(array_key_exists("oldid",$_REQUEST)) $oldid=intval($_REQUEST['oldid']);
47
48 $_SESSION['_config']['filepath'] = "/www";
49
50 require_once($_SESSION['_config']['filepath']."/includes/mysql.php");
51 require_once($_SESSION['_config']['filepath'].'/includes/lib/account.php');
52 require_once($_SESSION['_config']['filepath'].'/includes/lib/l10n.php');
53
54 if(array_key_exists('HTTP_HOST',$_SERVER) &&
55 $_SERVER['HTTP_HOST'] != $_SESSION['_config']['normalhostname'] &&
56 $_SERVER['HTTP_HOST'] != $_SESSION['_config']['securehostname'])
57 {
58 if(array_key_exists('HTTPS',$_SERVER) && $_SERVER['HTTPS'] == "on")
59 header("location: https://".$_SESSION['_config']['normalhostname']);
60 else
61 header("location: http://".$_SESSION['_config']['normalhostname']);
62 exit;
63 }
64
65 if(array_key_exists('HTTP_HOST',$_SERVER) &&
66 ($_SERVER['HTTP_HOST'] == $_SESSION['_config']['securehostname']))
67 {
68 if(array_key_exists('HTTPS',$_SERVER) && $_SERVER['HTTPS'] == "on")
69 {
70 }
71 else
72 {
73 if($_SERVER['HTTP_HOST'] == $_SESSION['_config']['securehostname']){
74 header("location: https://". $_SESSION['_config']['securehostname']);
75 }
76 exit;
77
78 }
79 }
80
81 L10n::detect_language();
82 L10n::init_gettext();
83
84 if(array_key_exists('profile',$_SESSION) && is_array($_SESSION['profile']) && array_key_exists('id',$_SESSION['profile']) && $_SESSION['profile']['id'] > 0)
85 {
86 $locked = mysql_fetch_assoc(mysql_query("select `locked` from `users` where `id`='".intval($_SESSION['profile']['id'])."'"));
87 if($locked['locked'] == 0)
88 {
89 update_points_in_profile();
90 } else {
91 $_SESSION['profile'] = "";
92 unset($_SESSION['profile']);
93 }
94 }
95
96 function loadem($section = "index")
97 {
98 if($section != "index" && $section != "account")
99 {
100 $section = "index";
101 }
102
103 if($section == "account"){
104 include_once($_SESSION['_config']['filepath']."/includes/account_stuff.php");
105 }
106
107 if($section == "index"){
108 include_once($_SESSION['_config']['filepath']."/includes/general_stuff.php");
109 }
110 }
111
112 function includeit($id = "0", $section = "index")
113 {
114 $id = intval($id);
115 if($section != "index" && $section != "account" && $section != "wot" && $section != "help" && $section != "gpg" && $section != "disputes" && $section != "advertising")
116 {
117 $section = "index";
118 }
119
120 if(file_exists($_SESSION['_config']['filepath']."/pages/$section/$id.php")){
121 include_once($_SESSION['_config']['filepath']."/pages/$section/$id.php");
122 }
123 else {
124 $id = "0";
125
126 if(file_exists($_SESSION['_config']['filepath']."/pages/$section/$id.php")){
127 include_once($_SESSION['_config']['filepath']."/pages/$section/$id.php");
128 } else {
129
130 $section = "index";
131 $id = "0";
132
133 if(file_exists($_SESSION['_config']['filepath']."/pages/$section/$id.php")){
134 include_once($_SESSION['_config']['filepath']."/pages/$section/$id.php");
135 } else {
136 include_once($_SESSION['_config']['filepath']."/www/error404.php");
137 }
138 }
139 }
140 }
141
142 function checkpwlight($pwd) {
143 $points = 0;
144
145 if(strlen($pwd) > 15)
146 $points++;
147 if(strlen($pwd) > 20)
148 $points++;
149 if(strlen($pwd) > 25)
150 $points++;
151 if(strlen($pwd) > 30)
152 $points++;
153
154 //echo "Points due to length: $points<br/>";
155
156 if(preg_match("/\d/", $pwd))
157 $points++;
158
159 if(preg_match("/[a-z]/", $pwd))
160 $points++;
161
162 if(preg_match("/[A-Z]/", $pwd))
163 $points++;
164
165 if(preg_match("/\W/", $pwd))
166 $points++;
167
168 if(preg_match("/\s/", $pwd))
169 $points++;
170
171 //echo "Points due to length and charset: $points<br/>";
172
173 // check for historical password proposal
174 if ($pwd === "Fr3d Sm|7h") {
175 return 0;
176 }
177
178 return $points;
179 }
180
181 function checkpw($pwd, $email, $fname, $mname, $lname, $suffix)
182 {
183 $points = checkpwlight($pwd);
184
185 if(@strstr(strtolower($pwd), strtolower($email)))
186 $points--;
187
188 if(@strstr(strtolower($email), strtolower($pwd)))
189 $points--;
190
191 if(@strstr(strtolower($pwd), strtolower($fname)))
192 $points--;
193
194 if(@strstr(strtolower($fname), strtolower($pwd)))
195 $points--;
196
197 if($mname)
198 if(@strstr(strtolower($pwd), strtolower($mname)))
199 $points--;
200
201 if($mname)
202 if(@strstr(strtolower($mname), strtolower($pwd)))
203 $points--;
204
205 if(@strstr(strtolower($pwd), strtolower($lname)))
206 $points--;
207
208 if(@strstr(strtolower($lname), strtolower($pwd)))
209 $points--;
210
211 if($suffix)
212 if(@strstr(strtolower($pwd), strtolower($suffix)))
213 $points--;
214
215 if($suffix)
216 if(@strstr(strtolower($suffix), strtolower($pwd)))
217 $points--;
218
219 //echo "Points due to name matches: $points<br/>";
220
221 $shellpwd = escapeshellarg($pwd);
222 $do = shell_exec("grep -F -- $shellpwd /usr/share/dict/american-english");
223 if($do)
224 $points--;
225
226 //echo "Points due to wordlist: $points<br/>";
227
228 return($points);
229 }
230
231 function extractit()
232 {
233 $bits = explode(": ", $_SESSION['_config']['subject'], 2);
234 $bits = str_replace(", ", "|", str_replace("/", "|", array_key_exists('1',$bits)?$bits['1']:""));
235 $bits = explode("|", $bits);
236
237 $_SESSION['_config']['cnc'] = $_SESSION['_config']['subaltc'] = 0;
238 $_SESSION['_config']['OU'] = "";
239
240 if(is_array($bits))
241 foreach($bits as $val)
242 {
243 if(!strstr($val, "="))
244 continue;
245
246 $split = explode("=", $val);
247
248 $k = $split[0];
249 $split['1'] = trim($split['1']);
250 if($k == "CN" && $split['1'])
251 {
252 $k = $_SESSION['_config']['cnc'].".".$k;
253 $_SESSION['_config']['cnc']++;
254 $_SESSION['_config'][$k] = $split['1'];
255 }
256 if($k == "OU" && $split['1'] && $_SESSION['_config']['OU'] == "")
257 {
258 $_SESSION['_config']['OU'] = $split['1'];
259 }
260 if($k == "subjectAltName" && $split['1'])
261 {
262 $k = $_SESSION['_config']['subaltc'].".".$k;
263 $_SESSION['_config']['subaltc']++;
264 $_SESSION['_config'][$k] = $split['1'];
265 }
266 }
267 }
268
269 function isValidWildcard($name){
270 if(substr($name,0,2) == "*."){
271 $name = substr($name, 2);
272 }
273 if(!preg_match('/^(\\.(?!-)[a-z0-9_-]*[a-z0-9])+$/i','.'.$name)){
274 return false;
275 }
276 return strpos($name, "*") === false;
277 }
278
279 function getcn()
280 {
281 unset($_SESSION['_config']['rows']);
282 unset($_SESSION['_config']['rowid']);
283 unset($_SESSION['_config']['rejected']);
284 $rows=array();
285 $rowid=array();
286 for($cnc = 0; $cnc < $_SESSION['_config']['cnc']; $cnc++)
287 {
288 $CN = $_SESSION['_config']["$cnc.CN"];
289 $bits = explode(".", $CN);
290 $dom = "";
291 $cnok = 0;
292
293 if(!isValidWildcard($CN)){
294 $_SESSION['_config']['rejected'][] = $CN;
295 continue;
296 }
297
298 for($i = count($bits) - 1; $i >= 0; $i--)
299 {
300 if($dom)
301 $dom = $bits[$i].".".$dom;
302 else
303 $dom = $bits[$i];
304 $_SESSION['_config']['row'] = "";
305 $dom = mysql_real_escape_string($dom);
306 $query = "select * from domains where `memid`='".intval($_SESSION['profile']['id'])."' and `domain` = '$dom' and `deleted`=0 and `hash`=''";
307 $res = mysql_query($query);
308 if(mysql_num_rows($res) > 0)
309 {
310 $cnok = 1;
311 $_SESSION['_config']['row'] = mysql_fetch_assoc($res);
312 $rowid[] = $_SESSION['_config']['row']['id'];
313 break;
314 }
315 }
316
317 if(!preg_match("/(?=^.{4,253}$)(^(?:\\*\\.)?((?!-)[a-zA-Z0-9_-]{1,63}(?<!-)\\.)+[a-zA-Z]{2,63}$)/i", $CN)) {
318 $cnok = 0;
319 }
320
321 if($cnok == 0) {
322 $_SESSION['_config']['rejected'][] = $CN;
323 continue;
324 }
325
326 if($_SESSION['_config']['row'] != "")
327 $rows[] = $CN;
328 }
329 // if(count($rows) <= 0)
330 // {
331 // echo _("There were no valid CommonName fields on the CSR, or I was unable to match any of these against your account. Please review your CSR, or add and verify domains contained in it to your account before trying again.");
332 // exit;
333 // }
334
335 $_SESSION['_config']['rows'] = $rows;
336 $_SESSION['_config']['rowid'] = $rowid;
337 }
338
339 function getalt()
340 {
341 unset($_SESSION['_config']['altrows']);
342 unset($_SESSION['_config']['altid']);
343 $altrows=array();
344 $altid=array();
345 for($altc = 0; $altc < $_SESSION['_config']['subaltc']; $altc++)
346 {
347 $subalt = $_SESSION['_config']["$altc.subjectAltName"];
348 if(substr($subalt, 0, 4) == "DNS:")
349 $alt = substr($subalt, 4);
350 else
351 continue;
352
353 if(!isValidWildcard($alt)){
354 $_SESSION['_config']['rejected'][] = $alt;
355 continue;
356 }
357
358 $bits = explode(".", $alt);
359 $dom = "";
360 $altok = 0;
361 for($i = count($bits) - 1; $i >= 0; $i--)
362 {
363 if($dom)
364 $dom = $bits[$i].".".$dom;
365 else
366 $dom = $bits[$i];
367 $_SESSION['_config']['altrow'] = "";
368 $dom = mysql_real_escape_string($dom);
369 $query = "select * from domains where `memid`='".intval($_SESSION['profile']['id'])."' and `domain` = '$dom' and `deleted`=0 and `hash`=''";
370 $res = mysql_query($query);
371 if(mysql_num_rows($res) > 0)
372 {
373 $altok = 1;
374 $_SESSION['_config']['altrow'] = mysql_fetch_assoc($res);
375 $altid[] = $_SESSION['_config']['altrow']['id'];
376 break;
377 }
378 }
379
380 if(!preg_match("/(?=^.{4,253}$)(^(?:\\*\\.)?((?!-)[a-zA-Z0-9_-]{1,63}(?<!-)\\.)+[a-zA-Z]{2,63}$)/i", $alt)) {
381 $altok = 0;
382 }
383
384 if($altok == 0) {
385 $_SESSION['_config']['rejected'][] = $alt;
386 continue;
387 }
388
389 if($_SESSION['_config']['altrow'] != "")
390 $altrows[] = $subalt;
391 }
392 $_SESSION['_config']['altrows'] = $altrows;
393 $_SESSION['_config']['altid'] = $altid;
394 }
395
396 function getcn2()
397 {
398 $rows=array();
399 $rowid=array();
400 for($cnc = 0; $cnc < $_SESSION['_config']['cnc']; $cnc++)
401 {
402 $CN = $_SESSION['_config']["$cnc.CN"];
403 $bits = explode(".", $CN);
404 $dom = "";
405
406 if(!isValidWildcard($CN)){
407 $_SESSION['_config']['rejected'][] = $CN;
408 continue;
409 }
410
411 for($i = count($bits) - 1; $i >= 0; $i--)
412 {
413 if($dom)
414 $dom = $bits[$i].".".$dom;
415 else
416 $dom = $bits[$i];
417 $_SESSION['_config']['row'] = "";
418 $dom = mysql_real_escape_string($dom);
419 $query = "select *, `orginfo`.`id` as `id` from `orginfo`,`orgdomains`,`org` where
420 `org`.`memid`='".intval($_SESSION['profile']['id'])."' and
421 `org`.`orgid`=`orginfo`.`id` and
422 `orgdomains`.`orgid`=`orginfo`.`id` and
423 `orgdomains`.`domain`='$dom'";
424 $res = mysql_query($query);
425 if(mysql_num_rows($res) > 0)
426 {
427 $_SESSION['_config']['row'] = mysql_fetch_assoc($res);
428 $rowid[] = $_SESSION['_config']['row']['id'];
429 break;
430 }
431 }
432
433 if(!preg_match("/(?=^.{4,253}$)(^(?:\\*\\.)?((?!-)[a-zA-Z0-9_-]{1,63}(?<!-)\\.)+[a-zA-Z]{2,63}$)/i", $CN)) {
434 continue;
435 }
436
437 if($_SESSION['_config']['row'] != "")
438 $rows[] = $CN;
439 }
440 // if(count($rows) <= 0)
441 // {
442 // echo _("There were no valid CommonName fields on the CSR, or I was unable to match any of these against your account. Please review your CSR, or add and verify domains contained in it to your account before trying again.");
443 // exit;
444 // }
445 $_SESSION['_config']['rows'] = $rows;
446 $_SESSION['_config']['rowid'] = $rowid;
447 }
448
449 function getalt2()
450 {
451 $altrows=array();
452 $altid=array();
453 for($altc = 0; $altc < $_SESSION['_config']['subaltc']; $altc++)
454 {
455 $subalt = $_SESSION['_config']["$altc.subjectAltName"];
456 if(substr($subalt, 0, 4) == "DNS:")
457 $alt = substr($subalt, 4);
458 else
459 continue;
460
461 if(!isValidWildcard($alt)){
462 $_SESSION['_config']['rejected'][] = $alt;
463 continue;
464 }
465
466 $bits = explode(".", $alt);
467 $dom = "";
468 for($i = count($bits) - 1; $i >= 0; $i--)
469 {
470 if($dom)
471 $dom = $bits[$i].".".$dom;
472 else
473 $dom = $bits[$i];
474 $_SESSION['_config']['altrow'] = "";
475 $dom = mysql_real_escape_string($dom);
476 $query = "select * from `orginfo`,`orgdomains`,`org` where
477 `org`.`memid`='".intval($_SESSION['profile']['id'])."' and
478 `org`.`orgid`=`orginfo`.`id` and
479 `orgdomains`.`orgid`=`orginfo`.`id` and
480 `orgdomains`.`domain`='$dom'";
481 $res = mysql_query($query);
482 if(mysql_num_rows($res) > 0)
483 {
484 $_SESSION['_config']['altrow'] = mysql_fetch_assoc($res);
485 $altid[] = $_SESSION['_config']['altrow']['id'];
486 break;
487 }
488 }
489
490 if(!preg_match("/(?=^.{4,253}$)(^(?:\\*\\.)?((?!-)[a-zA-Z0-9_-]{1,63}(?<!-)\\.)+[a-zA-Z]{2,63}$)/i", $alt)) {
491 continue;
492 }
493
494 if($_SESSION['_config']['altrow'] != "")
495 $altrows[] = $subalt;
496 }
497 $_SESSION['_config']['altrows'] = $altrows;
498 $_SESSION['_config']['altid'] = $altid;
499 }
500
501 function checkownership($hostname)
502 {
503 $bits = explode(".", $hostname);
504 $dom = "";
505 for($i = count($bits) - 1; $i >= 0; $i--)
506 {
507 if($dom)
508 $dom = $bits[$i].".".$dom;
509 else
510 $dom = $bits[$i];
511 $dom = mysql_real_escape_string($dom);
512 $query = "select * from `org`,`orgdomains`,`orginfo`
513 where `org`.`memid`='".intval($_SESSION['profile']['id'])."'
514 and `orgdomains`.`orgid`=`org`.`orgid`
515 and `orginfo`.`id`=`org`.`orgid`
516 and `orgdomains`.`domain`='$dom'";
517 $res = mysql_query($query);
518 if(mysql_num_rows($res) > 0)
519 {
520 $_SESSION['_config']['row'] = mysql_fetch_assoc($res);
521 return(true);
522 }
523 }
524 return(false);
525 }
526
527 function maxpoints($id = 0)
528 {
529 if($id <= 0)
530 $id = $_SESSION['profile']['id'];
531
532 $points = get_received_total_points($id);
533
534 $dob = date("Y-m-d", mktime(0,0,0,date("m"),date("d"),date("Y")-18));
535 $query = "select * from `users` where `id`='".intval($_SESSION['profile']['id'])."' and `dob` < '$dob'";
536 if(mysql_num_rows(mysql_query($query)) < 1)
537 {
538 if($points >= 100)
539 return(10);
540 else
541 return(0);
542 }
543
544 if($points >= 150)
545 return(35);
546 if($points >= 140)
547 return(30);
548 if($points >= 130)
549 return(25);
550 if($points >= 120)
551 return(20);
552 if($points >= 110)
553 return(15);
554 if($points >= 100)
555 return(10);
556 return(0);
557 }
558
559 /**
560 * Decode UTF-8 byte sequences into HTML entities
561 *
562 * @see https://blog.benny-baumann.de/?p=332
563 */
564 function charset_decode_utf8_callback($match) {
565 $m = $match[0];
566
567 switch(strlen($m)) {
568 case 6:
569 // decode six byte unicode characters
570 return '&#'.((ord($m[0])-252)*1073741824+(ord($m[1])-200)*16777216+(ord($m[2])-200)*262144+(ord($m[3])-128)*4096+(ord($m[4])-128)*64+(ord($m[5])-128)).';';
571 case 5:
572 // decode five byte unicode characters
573 return '&#'.((ord($m[0])-248)*16777216+(ord($m[1])-200)*262144+(ord($m[2])-128)*4096+(ord($m[3])-128)*64+(ord($m[4])-128)).';';
574 case 4:
575 // decode four byte unicode characters
576 return '&#'.((ord($m[0])-240)*262144+(ord($m[1])-128)*4096+(ord($m[2])-128)*64+(ord($m[3])-128)).';';
577 case 3:
578 // decode three byte unicode characters
579 return '&#'.((ord($m[0])-224)*4096+(ord($m[1])-128)*64+(ord($m[2])-128)).';';
580 case 2:
581 // decode two byte unicode characters
582 return '&#'.((ord($m[0])-192)*64+(ord($m[1])-128)).';';
583 default:
584 return $m;
585 }
586 }
587
588 /**
589 * Decode utf-8 strings
590 * @param string $string Encoded string
591 * @return string Decoded string
592 * @see https://blog.benny-baumann.de/?p=332
593 */
594 function charset_decode_utf8 ($string) {
595 // decode 2-6 byte unicode characters
596 $string = preg_replace_callback("/[\374-\375][\200-\277][\200-\277][\200-\277][\200-\277][\200-\277]|".
597 "[\370-\373][\200-\277][\200-\277][\200-\277][\200-\277]|".
598 "[\360-\367][\200-\277][\200-\277][\200-\277]|".
599 "[\340-\357][\200-\277][\200-\277]|".
600 "[\300-\337][\200-\277]/",
601 'charset_decode_utf8_callback', $string);
602
603 // remove broken unicode
604 $string = preg_replace("/[\200-\237]|\240|[\241-\377]/",'?',$string);
605
606 return $string;
607 }
608
609 function gpg_hex2bin($data)
610 {
611 while(strstr($data, "\\x"))
612 {
613 $pos = strlen($data) - strlen(strstr($data, "\\x"));
614 $before = substr($data, 0, $pos);
615 $char = chr(hexdec(substr($data, $pos + 2, 2)));
616 $after = substr($data, $pos + 4);
617 $data = $before.$char.$after;
618 }
619
620 return htmlentities(charset_decode_utf8($data), ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8', false);
621 }
622
623 function signmail($to, $subject, $message, $from, $replyto = "")
624 {
625 if($replyto == "")
626 $replyto = $from;
627 $tmpfname = tempnam("/tmp", "CSR");
628 $fp = fopen($tmpfname, "w");
629 fputs($fp, $message);
630 fclose($fp);
631 $to_esc = escapeshellarg($to);
632 $do = shell_exec("/usr/bin/gpg --homedir /home/gpg --clearsign \"$tmpfname\"|/usr/sbin/sendmail ".$to_esc);
633 @unlink($tmpfname);
634 }
635
636 function checkEmail($email)
637 {
638 $myemail = mysql_real_escape_string($email);
639 $myuid = intval($_SESSION['profile']['id']);
640 if(!preg_match("/^([a-zA-Z0-9])+([a-zA-Z0-9\+\._-])*@([a-zA-Z0-9_-])+([a-zA-Z0-9\._-]+)+$/" , $email))
641 {
642 $query = "INSERT INTO `pinglog` SET `when` = NOW(), `uid` = '$myuid', `email` = '$myemail',
643 `result` = 'Format of email address not recognized'";
644 mysql_query($query);
645 return _("Format of email address not recognized");
646 }
647
648 // Start with a blank transcript which is filled with information in the course of this routine
649 $transcript = "";
650
651 list($username,$domain)=explode('@',$email,2);
652 $transcript .= "Processing email address:\n";
653 $transcript .= "- Domain Name: " . sanitizeHTML($domain) . "\n";
654 $transcript .= "- Mailbox Name: " . sanitizeHTML($username) . "\n";
655
656 $transcript .= "Determining MX records for mail delivery:\n";
657 $mxhostrr = array();
658 $mxweight = array();
659 if( !getmxrr($domain, $mxhostrr, $mxweight) ) {
660 $transcript .= "- DNS lookup for MX records failed\n";
661 $transcript .= "- Defaulting to MX = '".sanitizeHTML($domain)."' at priority 0\n";
662 $mxhostrr = array($domain);
663 $mxweight = array(0);
664 } else if ( empty($mxhostrr) ) {
665 $transcript .= "- DNS lookup for MX records returned empty result\n";
666 $transcript .= "- Defaulting to MX = '".sanitizeHTML($domain)."' at priority 0\n";
667 $mxhostrr = array($domain);
668 $mxweight = array(0);
669 } else {
670 $transcript .= "- DNS lookup for MX records successful\n";
671 $transcript .= "- Received ".count($mxhostrr)." records\n";
672 }
673
674 $transcript .= "Building priority queue for test of servers:\n";
675 $mxhostprio = array();
676 for($i = 0; $i < count($mxhostrr); $i++) {
677 $mx_host = trim($mxhostrr[$i], '.');
678 $mx_prio = $mxweight[$i];
679 if(empty($mxhostprio[$mx_prio])) {
680 $mxhostprio[$mx_prio] = array();
681 }
682 $mxhostprio[$mx_prio][] = $mx_host;
683 }
684
685 array_walk($mxhostprio, function(&$mx) { shuffle($mx); } );
686 ksort($mxhostprio);
687
688 $mxhosts = array();
689 foreach($mxhostprio as $mx_prio => $mxhostnames) {
690 foreach($mxhostnames as $mx_host) {
691 $transcript .= "- Will test server id ".count($mxhosts)." at host '".sanitizeHTML($mx_host)."' with priority ".intval($mx_prio)."\n";
692 $ipv6rr = dns_get_record($mx_host, DNS_AAAA);
693 if(!empty($ipv6rr)) {
694 $transcript .= "- Will prefer IPv6 for server id ".count($mxhosts)." for host '".sanitizeHTML($mx_host)."'\n";
695 }
696
697 $mxhosts[] = $mx_host;
698 }
699 }
700
701 foreach($mxhosts as $key => $domain) {
702 $transcript .= "\n";
703 $transcript .= "Starting test for id ".intval($key)." for host '".sanitizeHTML($domain)."'\n";
704
705 $transcript .= "- Trying to connect to 'tcp://".sanitizeHTML($domain).":25' ... ";
706 $fp_opt = array(
707 'ssl' => array(
708 'verify_peer' => false, // Opportunistic Encryption
709 )
710 );
711 $fp_ctx = stream_context_create($fp_opt);
712 $fp = @stream_socket_client("tcp://$domain:25",$errno,$errstr,5,STREAM_CLIENT_CONNECT,$fp_ctx);
713
714 $transcript .= $fp ? "OK\n" : "FAILED\n";
715 if(!$fp) {
716 $transcript .= "- Connection failed with code $errno: ".sanitizeHTML($errstr)."\n";
717 continue;
718 }
719
720 $transcript .= "- Settng up the socket for blocking operation\n";
721 stream_set_blocking($fp, true);
722
723 $has_starttls = false;
724
725 $transcript .= "- Connection set up, dialog follows:\n";
726
727 do {
728 $line = fgets($fp, 4096);
729 $transcript .= "! S-&gt;C: ".sanitizeHTML(rtrim($line,"\r\n\0"))."\n";
730 } while(substr($line, 0, 4) == "220-");
731 if(substr($line, 0, 3) != "220") {
732 $transcript .= "- Unexpected status code, expected code 220\n";
733 $transcript .= "- Closing connection and trying the next host\n";
734 fclose($fp);
735 continue;
736 }
737
738 $transcript .= "! C-&gt;S: EHLO www.cacert.org\n";
739 fputs($fp, "EHLO www.cacert.org\r\n");
740 do {
741 $line = fgets($fp, 4096);
742 $transcript .= "! S-&gt;C: ".sanitizeHTML(rtrim($line,"\r\n\0"))."\n";
743 $has_starttls |= substr(trim($line),4) == "STARTTLS";
744 } while(substr($line, 0, 4) == "250-");
745 if(substr($line, 0, 3) != "250") {
746 $transcript .= "- Unexpected status code, expected code 250\n";
747 $transcript .= "- Closing connection and trying the next host\n";
748 fclose($fp);
749 continue;
750 }
751
752 if($has_starttls) {
753 $transcript .= "- STARTTLS support detected; will use it!\n";
754 $transcript .= "! C-&gt;S: STARTTLS\n";
755 fputs($fp, "STARTTLS\r\n");
756 do {
757 $line = fgets($fp, 4096);
758 $transcript .= "! S-&gt;C: ".sanitizeHTML(rtrim($line,"\r\n\0"))."\n";
759 } while(substr($line, 0, 4) == "220-");
760 if(substr($line, 0, 3) != "220") {
761 $transcript .= "- Unexpected status code, expected code 220\n";
762 $transcript .= "- Closing connection and trying the next host\n";
763 fclose($fp);
764 continue;
765 }
766
767 $transcript .= "- Establishing encrypted connection\n";
768 stream_socket_enable_crypto($fp, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);
769
770 $transcript .= "! C-&gt;S: EHLO www.cacert.org\n";
771 fputs($fp, "EHLO www.cacert.org\r\n");
772 do {
773 $line = fgets($fp, 4096);
774 $transcript .= "! S-&gt;C: ".sanitizeHTML(rtrim($line,"\r\n\0"))."\n";
775 } while(substr($line, 0, 4) == "250-");
776 if(substr($line, 0, 3) != "250") {
777 $transcript .= "- Unexpected status code, expected code 250\n";
778 $transcript .= "- Closing connection and trying the next host\n";
779 fclose($fp);
780 continue;
781 }
782 }
783
784 $transcript .= "! C-&gt;S: MAIL FROM:&lt;returns@cacert.org&gt;\n";
785 fputs($fp, "MAIL FROM:<returns@cacert.org>\r\n");
786 do {
787 $line = fgets($fp, 4096);
788 $transcript .= "! S-&gt;C: ".sanitizeHTML(rtrim($line,"\r\n\0"))."\n";
789 } while(substr($line, 0, 4) == "250-");
790 if(substr($line, 0, 3) != "250") {
791 $transcript .= "- Unexpected status code, expected code 250\n";
792 $transcript .= "- Closing connection and trying the next host\n";
793 fclose($fp);
794 continue;
795 }
796
797 $transcript .= "! C-&gt;S: MAIL FROM:&lt;".sanitizeHTML($email)."&gt;\n";
798 fputs($fp, "RCPT TO:<$email>\r\n");
799 do {
800 $line = fgets($fp, 4096);
801 $transcript .= "! S-&gt;C: ".sanitizeHTML(rtrim($line,"\r\n\0"))."\n";
802 } while(substr($line, 0, 4) == "250-");
803 if(substr($line, 0, 3) != "250") {
804 $transcript .= "- Unexpected status code, expected code 250\n";
805 $transcript .= "- Closing connection and trying the next host\n";
806 fclose($fp);
807 continue;
808 }
809
810 $transcript .= "! C-&gt;S: QUIT\n";
811 fputs($fp, "QUIT\r\n");
812 fclose($fp);
813 $transcript .= "- Connection to host closed\n";
814
815 $line = mysql_real_escape_string(trim(strip_tags($line)));
816 $query = "INSERT INTO `pinglog` SET `when` = NOW(), `uid` = '$myuid', `email` = '$myemail', `result` = '$line'";
817 mysql_query($query);
818
819 if(substr($line, 0, 3) != "250") {
820 return "<pre>" . $transcript . "</pre>";
821 } else {
822 return "OK";
823 }
824 }
825
826 $query = "INSERT INTO `pinglog` SET `when` = NOW(), `uid` = '$myuid', `email`='$myemail',
827 `result` = 'None of the email servers could be reached'";
828 mysql_query($query);
829 $transcript .= _("None of the email servers could be reached");
830
831 return "<pre>" . $transcript . "</pre>";
832 }
833
834 function waitForResult($table, $certid, $id = 0, $show = 1)
835 {
836 $found = $trycount = 0;
837 if($certid<=0)
838 {
839 if($show) showheader(_("My CAcert.org Account!"));
840 echo _("ERROR: The new Certificate ID is wrong. Please contact support.\n");
841 if($show) showfooter();
842 if($show) exit;
843 return;
844 }
845 while($trycount++ <= 40)
846 {
847 if($table == "gpg")
848 $query = "select * from `$table` where `id`='".intval($certid)."' and `crt` != ''";
849 else
850 $query = "select * from `$table` where `id`='".intval($certid)."' and `crt_name` != ''";
851 $res = mysql_query($query);
852 if(mysql_num_rows($res) > 0)
853 {
854 $found = 1;
855 break;
856 }
857 sleep(3);
858 }
859
860 if(!$found)
861 {
862 if($show) showheader(_("My CAcert.org Account!"));
863 $query = "select * from `$table` where `id`='".intval($certid)."' ";
864 $res = mysql_query($query);
865 $body="";
866 $subject="";
867 if(mysql_num_rows($res) > 0)
868 {
869 printf('<p>' . _("Your certificate request is still queued and hasn't been processed yet. Please wait, and go to Certificates -> View to see it's status." . '</p>'));
870 $subject="[CAcert.org] Certificate TIMEOUT";
871 $body = "A certificate has timed out!\n\n";
872 }
873 else
874 {
875 printf('<p>' . _("Your certificate request has failed to be processed correctly, see %sthe WIKI page%s for reasons and solutions.") . " certid:$table:".intval($certid) . '</p>', "<a href='http://wiki.cacert.org/wiki/FAQ/CertificateRenewal'>", "</a>");
876 $subject="[CAcert.org] Certificate FAILURE";
877 $body = "A certificate has failed: $table $certid $id $show\n\n";
878 }
879
880 $body .= _("Best regards")."\n"._("CAcert.org Support!");
881
882 sendmail("sw-message@cacert.org", $subject, $body, "returns@cacert.org", "", "", "CAcert Support");
883
884 if($show) showfooter();
885 if($show) exit;
886 }
887 }
888
889
890
891 function generateTicket()
892 {
893 $query = "insert into tickets (timestamp) values (now()) ";
894 mysql_query($query);
895 $ticket = mysql_insert_id();
896 return $ticket;
897 }
898
899 function sanitizeHTML($input)
900 {
901 return htmlentities(strip_tags($input), ENT_QUOTES | ENT_SUBSTITUTE, 'ISO-8859-1', false);
902 //In case of problems, please use the following line again:
903 //return htmlentities(strip_tags(utf8_decode($input)), ENT_QUOTES);
904 //return htmlspecialchars(strip_tags($input));
905 }
906
907 function make_hash()
908 {
909 if(function_exists("dio_open"))
910 {
911 $rnd = dio_open("/dev/urandom",O_RDONLY);
912 $hash = md5(dio_read($rnd,64));
913 dio_close($rnd);
914 } else {
915 $rnd = fopen("/dev/urandom", "r");
916 $hash = md5(fgets($rnd, 64));
917 fclose($rnd);
918 }
919 return($hash);
920 }
921
922 function csrf_check($nam, $show=1)
923 {
924 if(!array_key_exists('csrf',$_REQUEST) || !array_key_exists('csrf_'.$nam,$_SESSION))
925 {
926 showheader(_("My CAcert.org Account!"));
927 echo _("CSRF Hash is missing. Please try again.")."\n";
928 showfooter();
929 exit();
930 }
931 if(strlen($_REQUEST['csrf'])!=32)
932 {
933 showheader(_("My CAcert.org Account!"));
934 echo _("CSRF Hash is wrong. Please try again.")."\n";
935 showfooter();
936 exit();
937 }
938 if(!array_key_exists($_REQUEST['csrf'],$_SESSION['csrf_'.$nam]))
939 {
940 showheader(_("My CAcert.org Account!"));
941 echo _("CSRF Hash is wrong. Please try again.")."\n";
942 showfooter();
943 exit();
944 }
945 }
946 function make_csrf($nam)
947 {
948 $hash=make_hash();
949 $_SESSION['csrf_'.$nam][$hash]=1;
950 return($hash);
951 }
952
953 function clean_csr($CSR)
954 {
955 $newcsr = str_replace("\r\n","\n",trim($CSR));
956 $newcsr = str_replace("\n\n","\n",$newcsr);
957 return(preg_replace("/[^A-Za-z0-9\n\r\-\:\=\+\/ ]/","",$newcsr));
958 }
959 function clean_gpgcsr($CSR)
960 {
961 return(preg_replace("/[^A-Za-z0-9\n\r\-\:\=\+\/ ]/","",trim($CSR)));
962 }
963
964 function sanitizeFilename($text)
965 {
966 $text=preg_replace("/[^\w-.@]/","",$text);
967 return($text);
968 }
969
970
971 // returns text message to be shown to the user given the result of is_no_assurer
972 function no_assurer_text($Status)
973 {
974 if ($Status == 0) {
975 $Result = _("You have passed the Assurer Challenge and collected at least 100 Assurance Points, you are an Assurer.");
976 } elseif ($Status == 3) {
977 $Result = _("You have passed the Assurer Challenge, but to become an Assurer you still have to reach 100 Assurance Points!");
978 } elseif ($Status == 5) {
979 $Result = _("You have at least 100 Assurance Points, if you want to become an assurer try the").' <a href="https://cats.cacert.org/">'._("Assurer Challenge").'</a>!';
980 } elseif ($Status == 7) {
981 $Result = _("To become an Assurer you have to collect 100 Assurance Points and pass the").' <a href="https://cats.cacert.org/">'._("Assurer Challenge").'</a>!';
982 } elseif ($Status & 8 > 0) {
983 $Result = _("Sorry, you are not allowed to be an Assurer. Please contact").' <a href="mailto:cacert-support@lists.cacert.org">cacert-support@lists.cacert.org</a>'._(" if you feel that this is not corect.");
984 } else {
985 $Result = _("You are not an Assurer, but the reason is not stored in the database. Please contact").' <a href="mailto:cacert-support@lists.cacert.org">cacert-support@lists.cacert.org</a>.';
986 }
987 return $Result;
988 }
989
990 function is_assurer($userID)
991 {
992 if (get_assurer_status($userID))
993 return 0;
994 else
995 return 1;
996 }
997
998 function get_assurer_reason($userID)
999 {
1000 return no_assurer_text(get_assurer_status($userID));
1001 }
1002
1003 function generatecertpath($type,$kind,$id)
1004 {
1005 $name="../$type/$kind-".intval($id).".$type";
1006 $newlayout=1;
1007 if($newlayout)
1008 {
1009 $name="../$type/$kind/".intval($id/1000)."/$kind-".intval($id).".$type";
1010 if (!is_dir("../csr")) { mkdir("../csr",0777); }
1011 if (!is_dir("../crt")) { mkdir("../crt",0777); }
1012
1013 if (!is_dir("../csr/$kind")) { mkdir("../csr/$kind",0777); }
1014 if (!is_dir("../crt/$kind")) { mkdir("../crt/$kind",0777); }
1015 if (!is_dir("../csr/$kind/".intval($id/1000))) { mkdir("../csr/$kind/".intval($id/1000)); }
1016 if (!is_dir("../crt/$kind/".intval($id/1000))) { mkdir("../crt/$kind/".intval($id/1000)); }
1017 }
1018 return $name;
1019 }
1020
1021 /**
1022 * Run the sql query given in $sql.
1023 * The resource returned by mysql_query is
1024 * returned by this function.
1025 *
1026 * It should be safe to replace every mysql_query
1027 * call by a mysql_extended_query call.
1028 */
1029 function mysql_timed_query($sql)
1030 {
1031 global $sql_data_log;
1032 $query_start = microtime(true);
1033 $res = mysql_query($sql);
1034 $query_end = microtime(true);
1035 $sql_data_log[] = array("sql" => $sql, "duration" => $query_end - $query_start);
1036 return $res;
1037 }
1038
1039 /**
1040 * Returns the given ip address truncated to /16 (ipv4) or to /48 (ipv6)
1041 */
1042 function anonymizeIP($ip){
1043 $bits = @inet_pton($ip);
1044 if($bits === false) {
1045 return false;
1046 }
1047
1048 if(strlen($bits) == 4) {
1049 $bits[2] = "\0";
1050 $bits[3] = "\0";
1051 $newIP = @inet_ntop($bits);
1052 if($newIP !== false) {
1053 $newIP .= "/16";
1054 }
1055 return $newIP;
1056 } else if(strlen($bits) == 16) {
1057 for($i=6;$i<16;$i++){
1058 $bits[$i]="\0";
1059 }
1060 $newIP = @inet_ntop($bits);
1061 if($newIP !== false) {
1062 $newIP .= "/48";
1063 }
1064 return $newIP;
1065 }
1066 return false;
1067 }