#918: Reimplement openssl-vulnkey in PHP so we don't have to include
[cacert-devel.git] / includes / account_stuff.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 $id = 0; if(array_key_exists("id",$_REQUEST)) $id=intval($_REQUEST['id']);
20 $expand="";
21
22 function showheader($title = "CAcert.org", $title2 = "")
23 {
24 global $id, $PHP_SELF;
25 $expand="";
26 $tmpid = $id;
27 if($PHP_SELF == "/wot.php")
28 $tmpid = $id + 500;
29 if($PHP_SELF == "/gpg.php")
30 $tmpid = $id + 1000;
31 if($PHP_SELF == "/disputes.php")
32 $tmpid = $id + 1500;
33 if($PHP_SELF == "/advertising.php")
34 $tmpid = $id + 2000;
35
36 switch($tmpid)
37 {
38 case 1:
39 case 2: $expand = " explode('emailacc');"; break;
40 case 3:
41 case 4:
42 case 5:
43 case 6: $expand = " explode('clicerts');"; break;
44 case 7:
45 case 8:
46 case 9: $expand = " explode('domains');"; break;
47 case 10:
48 case 11:
49 case 12:
50 case 15: $expand = " explode('servercert');"; break;
51 case 13:
52 case 14:
53 case 36:
54 case 41:
55 case 507:
56 case 508:
57 case 513: $expand = " explode('mydetails');"; break;
58 case 16:
59 case 17:
60 case 18:
61 case 19: $expand = " explode('clientorg');"; break;
62 case 20:
63 case 21:
64 case 22:
65 case 23: $expand = " explode('serverorg');"; break;
66 case 24:
67 case 25:
68 case 26:
69 case 27:
70 case 28:
71 case 29:
72 case 30:
73 case 31:
74 case 32:
75 case 33:
76 case 34:
77 case 35: $expand = " explode('orgadmin');"; break;
78 case 42:
79 case 43:
80 case 44:
81 case 45:
82 case 46:
83 case 47:
84 case 48:
85 case 49:
86 case 50:
87 case 54:
88 case 53: $expand = " explode('sysadmin');"; break;
89 case 500:
90 case 501:
91 case 502:
92 case 503:
93 case 504:
94 case 505:
95 case 506:
96 case 509:
97 case 510:
98 case 511:
99 case 512: $expand = " explode('WoT');"; break;
100 case 1000:
101 case 1001:
102 case 1002:
103 case 1003:
104 case 1004:
105 case 1005:
106 case 1006:
107 case 1007:
108 case 1008:
109 case 1009:
110 case 1010: $expand = " explode('gpg');"; break;
111 case 1500:
112 case 1501:
113 case 1502:
114 case 1503:
115 case 1504:
116 case 1505:
117 case 1506:
118 case 1507:
119 case 1508:
120 case 1509:
121 case 1510: $expand = " explode('disputes');"; break;
122 case 2000:
123 case 2001:
124 case 2002:
125 case 2003:
126 case 2004:
127 case 2005:
128 case 2006:
129 case 2007:
130 case 2008:
131 case 2009: $expand = " explode('advertising');"; break;
132 }
133
134 ?><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
135 <html>
136 <head>
137 <title><?=$title?></title>
138 <? if(array_key_exists('header',$_SESSION) && $_SESSION['_config']['header'] != "") { ?><?=$_SESSION['_config']['header']?><? } ?>
139 <link rel="stylesheet" href="/styles/default.css" type="text/css" />
140 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
141 <script language="JavaScript" type="text/javascript">
142 function explode(e) {
143 if (document.getElementById(e).style.display == 'none') {
144 document.getElementById(e).style.display = 'block';
145 } else {
146 document.getElementById(e).style.display = 'none';
147 }
148 }
149
150 function hideall() {
151 var Nodes = document.getElementsByTagName('ul')
152 var max = Nodes.length
153 for(var i = 0;i < max;i++) {
154 var nodeObj = Nodes.item(i)
155 if (nodeObj.className == "menu") {
156 nodeObj.style.display = 'none';
157 }
158 }
159 }
160 </script>
161 </head>
162 <body onload="hideall(); explode('home');<?=$expand?>">
163 <div id="pagecell1">
164 <div id="pageName"><br>
165 <div id="pageLogo"><a href="http://<?=$_SESSION['_config']['normalhostname']?>"><img src="/images/cacert4.png" border="0" alt="CAcert.org logo"></a></div>
166 <div id="googlead"><h2><?=_("Free digital certificates!")?></h2></div>
167 </div>
168 <div id="pageNav">
169 <div class="relatedLinks">
170 <h3>CAcert.org</h3>
171 <ul class="menu" id="home"><li><a href="/index.php"><?=_("Go Home")?></a></li><li><a href="account.php?id=logout"><?=_("Logout")?></a></li></ul>
172 </div>
173 <div class="relatedLinks">
174 <h3 class="pointer" onclick="explode('mydetails')">+ <?=_("My Details")?></h3>
175 <ul class="menu" id="mydetails"><li><a href="account.php?id=13"><?=_("Edit")?></a></li><li><a href="account.php?id=14"><?=_("Change Password")?></a></li><li><a href="account.php?id=41"><?=_("Default Language")?></a></li><li><a href="wot.php?id=8"><?=_("My Listing")?></a></li><li><a href="wot.php?id=13"><?=_("My Location")?></a></li><li><a href="account.php?id=36"><?=_("My Alert Settings")?></a></li><li><a href="wot.php?id=10"><?=_("My Points")?></a></li><?
176 if($_SESSION['profile']['id'] == 1 || $_SESSION['profile']['id'] == 5897)
177 echo "<li><a href='sqldump.php'>SQL Dump</a></li>";
178 ?></ul>
179 </div>
180 <div class="relatedLinks">
181 <h3 class="pointer" onclick="explode('emailacc')">+ <?=_("Email Accounts")?></h3>
182 <ul class="menu" id="emailacc"><li><a href="account.php?id=1"><?=_("Add")?></a></li><li><a href="account.php?id=2"><?=_("View")?></a></li></ul>
183 </div>
184 <div class="relatedLinks">
185 <h3 class="pointer" onclick="explode('clicerts')">+ <?=_("Client Certificates")?></h3>
186 <ul class="menu" id="clicerts"><li><a href="account.php?id=3"><?=_("New")?></a></li><li><a href="account.php?id=5"><?=_("View")?></a></li></ul>
187 </div>
188 <? if($_SESSION['profile']['points'] >= 50) { ?>
189 <div class="relatedLinks">
190 <h3 class="pointer" onclick="explode('gpg')">+ <?=_("GPG/PGP Keys")?></h3>
191 <ul class="menu" id="gpg"><li><a href="gpg.php?id=0"><?=_("New")?></a></li><li><a href="gpg.php?id=2"><?=_("View")?></a></li></ul>
192 </div>
193 <? } ?>
194 <div class="relatedLinks">
195 <h3 class="pointer" onclick="explode('domains')">+ <?=_("Domains")?></h3>
196 <ul class="menu" id="domains"><li><a href="account.php?id=7"><?=_("Add")?></a></li><li><a href="account.php?id=9"><?=_("View")?></a></li></ul>
197 </div>
198 <div class="relatedLinks">
199 <h3 class="pointer" onclick="explode('servercert')">+ <?=_("Server Certificates")?></h3>
200 <ul class="menu" id="servercert"><li><a href="account.php?id=10"><?=_("New")?></a></li><li><a href="account.php?id=12"><?=_("View")?></a></li></ul>
201 </div>
202 <? if(mysql_num_rows(mysql_query("select * from `org` where `memid`='".intval($_SESSION['profile']['id'])."'")) > 0 || $_SESSION['profile']['orgadmin'] == 1) { ?>
203 <div class="relatedLinks">
204 <h3 class="pointer" onclick="explode('clientorg')">+ <?=_("Org Client Certs")?></h3>
205 <ul class="menu" id="clientorg"><li><a href="account.php?id=16"><?=_("New")?></a></li><li><a href="account.php?id=18"><?=_("View")?></a></li></ul>
206 </div>
207 <div class="relatedLinks">
208 <h3 class="pointer" onclick="explode('serverorg')">+ <?=_("Org Server Certs")?></h3>
209 <ul class="menu" id="serverorg"><li><a href="account.php?id=20"><?=_("New")?></a></li><li><a href="account.php?id=22"><?=_("View")?></a></li></ul>
210 </div>
211 <? } ?>
212 <? if(mysql_num_rows(mysql_query("select * from `org` where `memid`='".intval($_SESSION['profile']['id'])."' and `masteracc`='1'")) > 0 || $_SESSION['profile']['orgadmin'] == 1) { ?>
213 <div class="relatedLinks">
214 <h3 class="pointer" onclick="explode('orgadmin')">+ <?=_("Org Admin")?></h3>
215 <ul class="menu" id="orgadmin"><? if($_SESSION['profile']['orgadmin'] == 1) { ?><li><a href="account.php?id=24"><?=_("New Organisation")?></a></li><li><a href="account.php?id=25"><?=_("View Organisations")?></a></li><? } ?><li><a href="account.php?id=35"><?=_("View")?></a></li></ul>
216 </div>
217 <? } ?>
218 <div class="relatedLinks">
219 <h3 class="pointer" onclick="explode('WoT')">+ <?=_("CAcert Web of Trust")?></h3>
220 <ul class="menu" id="WoT"><li><a href="wot.php?id=0"><?=_("About")?></a></li><li><a href="wot.php?id=12"><?=_("Find an Assurer")?></a></li><li><a href="wot.php?id=3"><?=_("Rules")?></a></li><li><? if($_SESSION['profile']['assurer'] != 1) { ?><a href="wot.php?id=2"><?=_("Becoming an Assurer")?></a><? } else { ?><a href="wot.php?id=5"><?=_("Assure Someone")?></a><? } ?></li><li><a href="wot.php?id=4"><?=_("Trusted ThirdParties")?></a></li><? if($_SESSION['profile']['points'] >= 500) { ?><li><a href="wot.php?id=11"><div style="white-space:nowrap"><?=_("Organisation Assurance")?></div></a></li><? } ?><li><a href="account.php?id=55"><?=_("Training")?></a></li></ul>
221 </div>
222 <div class="relatedLinks">
223 <h3 class="pointer" onclick="explode('WoTForms')">+ <?=_("CAP Forms")?></h3><?
224 $name = $_SESSION['profile']['fname']." ".$_SESSION['profile']['mname']." ".$_SESSION['profile']['lname']." ".$_SESSION['profile']['suffix'];
225 while(strstr($name, " "))
226 $name = str_replace(" ", " ", $name);
227 $extra = "?name=".urlencode($name);
228 $extra .= "&amp;dob=".urlencode($_SESSION['profile']['dob']);
229 $extra .= "&amp;email=".urlencode($_SESSION['profile']['email']);
230
231 $extra2 = "?assurer=".urlencode($name)."&amp;date=now&amp;maxpoints=".maxpoints();
232 ?>
233 <ul class="menu" id="WoTForms">
234 <li><a href="/cap.php<?=$extra?>">A4 - <?=_("WoT Form")?></a></li>
235 <li><a href="/cap.php<?=$extra?>&amp;format=letter">US - <?=_("WoT Form")?></a></li>
236 <? /* <li><div style="white-space:nowrap"><a href="/ttp.php<?=$extra?>">A4 - <?=_("TTP Form")?></a></div></li>
237 <li><div style="white-space:nowrap"><a href="/ttp.php<?=$extra?>&amp;format=letter">US - <?=_("TTP Form")?></a></div></li> */
238 ?>
239 <? if($_SESSION['profile']['points'] > 100) { ?><li><div style="white-space:nowrap"><a href="/cap.php<?=$extra2?>">A4 - <?=_("Assurance Form")?></a></div></li>
240 <li><div style="white-space:nowrap"><a href="/cap.php<?=$extra2?>&amp;format=letter">US - <?=_("Assurance Form")?></a></div></li>
241 <? } ?>
242 <? /*
243 <li><div style="white-space:nowrap"><a href="/ttp.php">A4 - <?=_("Blank TTP Form")?></a></div></li>
244 <li><div style="white-space:nowrap"><a href="/ttp.php?&amp;format=letter">US - <?=_("Blank TTP Form")?></a></div></li>
245 */ ?>
246 <li><div style="white-space:nowrap"><a href="/cap.php">A4 - <?=_("Blank CAP Form")?></a></div></li>
247 <li><div style="white-space:nowrap"><a href="/cap.php?&amp;format=letter">US - <?=_("Blank CAP Form")?></a></div></li></ul>
248 </div>
249 <? if($_SESSION['profile']['admin'] == 1 || $_SESSION['profile']['locadmin'] == 1) { ?>
250 <div class="relatedLinks">
251 <h3 class="pointer" onclick="explode('sysadmin')">+ <?=_("System Admin")?></h3>
252 <ul class="menu" id="sysadmin"><? if($_SESSION['profile']['admin'] == 1) { ?><li><a href="account.php?id=42"><?=_("Find User")?></a></li><li><a href="account.php?id=48"><?=_("Find Domain")?></a></li><? } if($_SESSION['profile']['locadmin'] == 1) { ?><li><a href="account.php?id=53"><?=_("Location DB")?></a></li><? } ?></ul>
253 </div>
254 <? } ?>
255 <div class="relatedLinks">
256 <h3 class="pointer" onclick="explode('disputes')">+ <?=_("Disputes/Abuses")?></h3>
257 <ul class="menu" id="disputes"><li><a href="disputes.php?id=0"><?=_("More Information")?></a></li><li><a href="disputes.php?id=1"><?=_("Email Dispute")?></a></li><li><a href="disputes.php?id=2"><?=_("Domain Dispute")?></a></li><? if($_SESSION['profile']['admin'] == 1) { ?><li><a href="disputes.php?id=3"><?=_("Abuses")?></a></li><? } ?></ul>
258 </div>
259 <? if($_SESSION['profile']['adadmin'] >= 1) { ?>
260 <div class="relatedLinks">
261 <h3 class="pointer" onclick="explode('advertising')">+ <?=_("Advertising")?></h3>
262 <ul class="menu" id="advertising"><li><a href="advertising.php?id=1"><?=_("New Ad")?></a></li><li><a href="advertising.php?id=0"><?=_("View Ads")?></a></li></ul>
263 </div>
264 <? } ?>
265 </div>
266 <div id="content">
267 <div class="story">
268 <h3><?=$title2?></h3>
269 <? if($_SESSION['_config']['errmsg'] != "") { ?>
270 <p><font color="#ff0000" size="+2"><? echo $_SESSION['_config']['errmsg']; $_SESSION['_config']['errmsg'] = ""; ?> </font></p>
271 <? } ?>
272 <?
273 }
274
275 function showfooter()
276 {
277 ?>
278 </div>
279 </div>
280 <div id="siteInfo"><a href="account.php?id=37"><?=_("About Us")?></a> | <a href="account.php?id=38"><?=_("Donations")?></a> | <a href="http://wiki.cacert.org/wiki/CAcertIncorporated"><?=_("Association Membership")?></a> |
281 <a href="account.php?id=39"><?=_("Privacy Policy")?></a> | <a href="account.php?id=40"><?=_("Contact Us")?></a>
282 | &copy;2002-<?=date("Y")?> <?=_("by CAcert")?></div>
283 </div>
284 </body>
285 </html><?
286 }
287
288 /**
289 * Produces a log entry with the error message with log level E_USER_WARN
290 * and a random ID an returns a message that can be displayed to the user
291 * including the generated ID
292 *
293 * @param $errormessage string
294 * The error message that should be logged
295 * @return string containing the generated ID that can be displayed to the
296 * user
297 */
298 function failWithId($errormessage) {
299 $errorId = rand();
300 trigger_error("$errormessage. ID: $errorId", E_USER_WARNING);
301 return sprintf(_("Something went wrong when processing your request. ".
302 "Please contact %s for help and provide them with the ".
303 "following ID: %d"),
304 "<a href='mailto:support@cacert.org?subject=System%20Error%20-%20".
305 "ID%3A%20$errorId'>support@cacert.org</a>",
306 $errorId);
307 }
308
309 /**
310 * Checks whether the given CSR contains a vulnerable key
311 *
312 * @param $csr string
313 * The CSR to be checked
314 * @param $encoding string [optional]
315 * The encoding the CSR is in (for the "-inform" parameter of OpenSSL,
316 * currently only "PEM" (default) or "DER" allowed)
317 * @return string containing the reason if the key is considered weak,
318 * empty string otherwise
319 */
320 function checkWeakKeyCSR($csr, $encoding = "PEM")
321 {
322 // non-PEM-encodings may be binary so don't use echo
323 $descriptorspec = array(
324 0 => array("pipe", "r"), // STDIN for child
325 1 => array("pipe", "w"), // STDOUT for child
326 );
327 $encoding = escapeshellarg($encoding);
328 $proc = proc_open("openssl req -inform $encoding -text -noout",
329 $descriptorspec, $pipes);
330
331 if (is_resource($proc))
332 {
333 fwrite($pipes[0], $csr);
334 fclose($pipes[0]);
335
336 $csrText = "";
337 while (!feof($pipes[1]))
338 {
339 $csrText .= fread($pipes[1], 8192);
340 }
341 fclose($pipes[1]);
342
343 if (($status = proc_close($proc)) !== 0 || $csrText === "")
344 {
345 return _("I didn't receive a valid Certificate Request, hit ".
346 "the back button and try again.");
347 }
348 } else {
349 return failWithId("checkWeakKeyCSR(): Failed to start OpenSSL");
350 }
351
352
353 return checkWeakKeyText($csrText);
354 }
355
356 /**
357 * Checks whether the given SPKAC contains a vulnerable key
358 *
359 * @param $spkac string
360 * The SPKAC to be checked
361 * @param $spkacname string [optional]
362 * The name of the variable that contains the SPKAC. The default is
363 * "SPKAC"
364 * @return string containing the reason if the key is considered weak,
365 * empty string otherwise
366 */
367 function checkWeakKeySPKAC($spkac, $spkacname = "SPKAC")
368 {
369 /* Check for the debian OpenSSL vulnerability */
370
371 $spkac = escapeshellarg($spkac);
372 $spkacname = escapeshellarg($spkacname);
373 $spkacText = `echo $spkac | openssl spkac -spkac $spkacname`;
374 if ($spkacText === null) {
375 return _("I didn't receive a valid Certificate Request, hit the ".
376 "back button and try again.");
377 }
378
379 return checkWeakKeyText($spkacText);
380 }
381
382 /**
383 * Checks whether the given text representation of a CSR or a SPKAC contains
384 * a weak key
385 *
386 * @param $text string
387 * The text representation of a key as output by the
388 * "openssl <foo> -text -noout" commands
389 * @return string containing the reason if the key is considered weak,
390 * empty string otherwise
391 */
392 function checkWeakKeyText($text)
393 {
394 /* Which public key algorithm? */
395 if (!preg_match('/^\s*Public Key Algorithm: ([^\s]+)$/m', $text,
396 $algorithm))
397 {
398 return failWithId("checkWeakKeyText(): Couldn't extract the ".
399 "public key algorithm used");
400 } else {
401 $algorithm = $algorithm[1];
402 }
403
404
405 if ($algorithm === "rsaEncryption")
406 {
407 if (!preg_match('/^\s*RSA Public Key: \((\d+) bit\)$/m', $text,
408 $keysize))
409 {
410 return failWithId("checkWeakKeyText(): Couldn't parse the RSA ".
411 "key size");
412 } else {
413 $keysize = intval($keysize[1]);
414 }
415
416 if ($keysize < 1024)
417 {
418 return sprintf(_("The keys that you use are very small ".
419 "and therefore insecure. Please generate stronger ".
420 "keys. More information about this issue can be ".
421 "found in %sthe wiki%s"),
422 "<a href='//wiki.cacert.org/WeakKeys#SmallKey'>",
423 "</a>");
424 } elseif ($keysize < 2048) {
425 // not critical but log so we have some statistics about
426 // affected users
427 trigger_error("checkWeakKeyText(): Certificate for small ".
428 "key (< 2048 bit) requested", E_USER_NOTICE);
429 }
430
431
432 $debianVuln = checkDebianVulnerability($text, $keysize);
433 if ($debianVuln === true)
434 {
435 return sprintf(_("The keys you use have very likely been ".
436 "generated with a vulnerable version of OpenSSL which ".
437 "was distributed by debian. Please generate new keys. ".
438 "More information about this issue can be found in ".
439 "%sthe wiki%s"),
440 "<a href='//wiki.cacert.org/WeakKeys#DebianVulnerability'>",
441 "</a>");
442 } elseif ($debianVuln === false) {
443 // not vulnerable => do nothing
444 } else {
445 return failWithId("checkWeakKeyText(): Something went wrong in".
446 "checkDebianVulnerability()");
447 }
448
449 if (!preg_match('/^\s*Exponent: (\d+) \(0x[0-9a-fA-F]+\)$/m', $text,
450 $exponent))
451 {
452 return failWithId("checkWeakKeyText(): Couldn't parse the RSA ".
453 "exponent");
454 } else {
455 $exponent = $exponent[1]; // exponent might be very big =>
456 //handle as string using bc*()
457
458 if (bccomp($exponent, "3") === 0)
459 {
460 return sprintf(_("The keys you use might be insecure. ".
461 "Although there is currently no known attack for ".
462 "reasonable encryption schemes, we're being ".
463 "cautious and don't allow certificates for such ".
464 "keys. Please generate stronger keys. More ".
465 "information about this issue can be found in ".
466 "%sthe wiki%s"),
467 "<a href='//wiki.cacert.org/WeakKeys#SmallExponent'>",
468 "</a>");
469 } elseif (!(bccomp($exponent, "65537") >= 0 &&
470 (bccomp($exponent, "100000") === -1 ||
471 // speed things up if way smaller than 2^256
472 bccomp($exponent, bcpow("2", "256")) === -1) )) {
473 // 65537 <= exponent < 2^256 recommended by NIST
474 // not critical but log so we have some statistics about
475 // affected users
476 trigger_error("checkWeakKeyText(): Certificate for ".
477 "unsuitable exponent '$exponent' requested",
478 E_USER_NOTICE);
479 }
480 }
481 }
482
483 /* No weakness found */
484 return "";
485 }
486
487 /**
488 * Reimplement the functionality of the openssl-vulnkey tool
489 *
490 * @param $text string
491 * The text representation of a key as output by the
492 * "openssl <foo> -text -noout" commands
493 * @param $keysize int [optional]
494 * If the key size is already known it can be provided so it doesn't
495 * have to be parsed again. This also skips the check whether the key
496 * is an RSA key => use wisely
497 * @return TRUE if key is vulnerable, FALSE otherwise, NULL in case of error
498 */
499 function checkDebianVulnerability($text, $keysize = 0)
500 {
501 $keysize = intval($keysize);
502
503 if ($keysize === 0)
504 {
505 /* Which public key algorithm? */
506 if (!preg_match('/^\s*Public Key Algorithm: ([^\s]+)$/m', $text,
507 $algorithm))
508 {
509 trigger_error("checkDebianVulnerability(): Couldn't extract ".
510 "the public key algorithm used", E_USER_WARNING);
511 return null;
512 } else {
513 $algorithm = $algorithm[1];
514 }
515
516 if ($algorithm !== "rsaEncryption") return false;
517
518 /* Extract public key size */
519 if (!preg_match('/^\s*RSA Public Key: \((\d+) bit\)$/m', $text,
520 $keysize))
521 {
522 trigger_error("checkDebianVulnerability(): Couldn't parse the ".
523 "RSA key size", E_USER_WARNING);
524 return null;
525 } else {
526 $keysize = intval($keysize[1]);
527 }
528 }
529
530 // $keysize has been made sure to contain an int
531 $blacklist = "/usr/share/openssl-blacklist/blacklist.RSA-$keysize";
532 if (!(is_file($blacklist) && is_readable($blacklist)))
533 {
534 if (in_array($keysize, array(512, 1024, 2048, 4096)))
535 {
536 trigger_error("checkDebianVulnerability(): Blacklist for ".
537 "$keysize bit keys not accessible. Expected at ".
538 "$blacklist", E_USER_ERROR);
539 return null;
540 }
541
542 trigger_error("checkDebianVulnerability(): $blacklist is not ".
543 "readable. Unsupported key size?", E_USER_WARNING);
544 return false;
545 }
546
547
548 /* Extract RSA modulus */
549 if (!preg_match('/^\s*Modulus \(\d+ bit\):\n'.
550 '((?:\s*[0-9a-f][0-9a-f]:(?:\n)?)+[0-9a-f][0-9a-f])$/m',
551 $text, $modulus))
552 {
553 trigger_error("checkDebianVulnerability(): Couldn't extract the ".
554 "RSA modulus", E_USER_WARNING);
555 return null;
556 } else {
557 $modulus = $modulus[1];
558 // strip whitespace and colon leftovers
559 $modulus = str_replace(array(" ", "\t", "\n", ":"), "", $modulus);
560
561 // when using "openssl xxx -text" first byte was 00 in all my test
562 // cases but 00 not present in the "openssl xxx -modulus" output
563 if ($modulus[0] === "0" && $modulus[1] === "0")
564 {
565 $modulus = substr($modulus, 2);
566 } else {
567 trigger_error("checkDebianVulnerability(): First byte is not ".
568 "zero", E_USER_NOTICE);
569 }
570
571 $modulus = strtoupper($modulus);
572 }
573
574
575 /* calculate checksum and look it up in the blacklist */
576 $checksum = substr(sha1("Modulus=$modulus\n"), 20);
577
578 // $checksum and $blacklist should be safe, but just to make sure
579 $checksum = escapeshellarg($checksum);
580 $blacklist = escapeshellarg($blacklist);
581 exec("grep $checksum $blacklist", $dummy, $debianVuln);
582 if ($debianVuln === 0) // grep returned something => it is on the list
583 {
584 return true;
585 } elseif ($debianVuln === 1) { // grep returned nothing
586 return false;
587 } else {
588 trigger_error("checkDebianVulnerability(): Something went wrong ".
589 "when looking up the key with checksum $checksum in the ".
590 "blacklist $blacklist", E_USER_ERROR);
591 return null;
592 }
593
594 // Should not get here
595 return null;
596 }
597 ?>