Source code taken from cacert-20140419.tar.bz2
[cacert-devel.git] / www / gpg.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("../includes/loggedin.php");
20 require_once("../includes/lib/general.php");
21 require_once('../includes/notary.inc.php');
22
23 $id = 0; if(array_key_exists('id',$_REQUEST)) $id=intval($_REQUEST['id']);
24 $oldid = $_REQUEST['oldid'] = array_key_exists('oldid',$_REQUEST) ? intval($_REQUEST['oldid']) : 0;
25
26 if($_SESSION['profile']['points'] < 50)
27 {
28 header("location: /account.php");
29 exit;
30 }
31
32 loadem("account");
33
34
35
36 $CSR=""; if(array_key_exists('CSR',$_REQUEST)) $CSR=stripslashes($_REQUEST['CSR']);
37
38
39 if($oldid == "0")
40 {
41 if(array_key_exists('process',$_REQUEST) && $_REQUEST['process'] != "" && $CSR == "")
42 {
43 $_SESSION['_config']['errmsg'] = _("You failed to paste a valid GPG/PGP key.");
44 $id = $oldid;
45 $oldid=0;
46 }
47 }
48
49 $keyid="";
50
51 if(0)
52 {
53 if($_SESSION["profile"]["id"] != 5897)
54 {
55 showheader(_("Welcome to CAcert.org"));
56 echo "The OpenPGP signing system is currently shutdown due to a maintenance. We hope to get it fixed within the next few hours. We are very sorry for the inconvenience.";
57
58 exit(0);
59 }
60 }
61
62
63 function verifyName($name)
64 {
65 if($name == "") return 0;
66 if($name == $_SESSION['profile']['fname']." ".$_SESSION['profile']['lname']) return 1;
67 if($name == $_SESSION['profile']['fname']." ".$_SESSION['profile']['mname']." ".$_SESSION['profile']['lname']) return 1;
68 if($name == $_SESSION['profile']['fname']." ".$_SESSION['profile']['lname']." ".$_SESSION['profile']['suffix']) return 1;
69 if($name == $_SESSION['profile']['fname']." ".$_SESSION['profile']['mname']." ".$_SESSION['profile']['lname']." ".$_SESSION['profile']['suffix']) return 1;
70 return 0;
71
72 }
73
74 function verifyEmail($email)
75 {
76 if($email == "") return 0;
77 if(mysql_num_rows(mysql_query("select * from `email` where `memid`='".$_SESSION['profile']['id']."' and `email`='".mysql_real_escape_string($email)."' and `deleted`=0 and `hash`=''")) > 0) return 1;
78 return 0;
79 }
80
81
82
83 $ToBeDeleted=array();
84 $state=0;
85 if($oldid == "0" && $CSR != "")
86 {
87 if(!array_key_exists('CCA',$_REQUEST))
88 {
89 showheader(_("My CAcert.org Account!"));
90 echo _("You did not accept the CAcert Community Agreement (CCA), hit the back button and try again.");
91 showfooter();
92 exit;
93 }
94
95 $err = runCommand('mktemp --directory /tmp/cacert_gpg.XXXXXXXXXX',
96 "",
97 $tmpdir);
98 if (!$tmpdir)
99 {
100 $err = true;
101 }
102
103 if (!$err)
104 {
105 $err = runCommand("gpg --with-colons --homedir $tmpdir 2>&1",
106 clean_gpgcsr($CSR),
107 $gpg);
108
109 `rm -r $tmpdir`;
110 }
111
112 if ($err)
113 {
114 showheader(_("Welcome to CAcert.org"));
115
116 echo "<p style='color:#ff0000'>"._("There was an error parsing your key.")."</p>";
117 unset($_REQUEST['process']);
118 $id = $oldid;
119 unset($oldid);
120 exit();
121 }
122
123 $lines = "";
124 $gpgarr = explode("\n", trim($gpg));
125 foreach($gpgarr as $line)
126 {
127 #echo "Line[]: $line <br/>\n";
128 if(substr($line, 0, 3) == "pub" || substr($line, 0, 3) == "uid")
129 {
130 if($lines != "")
131 $lines .= "\n";
132 $lines .= $line;
133 }
134 }
135 $gpg = $lines;
136 $expires = 0;
137 $nerr=0; $nok=0;
138 $multiple = 0;
139
140 $resulttable=_("The following UIDs were found in your key:")."<br/><table border='1'><tr><td>#</td><td>"._("Name")."</td><td>"._("Email")."</td><td>Result</td>";
141 $i=0;
142 $lastvalidemail="";
143 $npubs=0;
144 foreach(explode("\n", $gpg) as $line)
145 {
146 $bits = explode(":", $line);
147 $resulttable.="<tr><td>".++$i."</td>";
148 $name = $comment = "";
149 if($bits[0] == "pub")
150 {
151 $npubs++;
152 }
153 if($npubs>1)
154 {
155 showheader(_("Welcome to CAcert.org"));
156 echo "<font color='#ff0000'>"._("Please upload only one key at a time.")."</font>";
157 unset($_REQUEST['process']);
158 $id = $oldid;
159 unset($oldid);
160 exit();
161 }
162 if($bits[0] == "pub" && (!$keyid || !$when))
163 {
164 $keyid = $bits[4];
165 $when = $bits[5];
166 if($bits[6] != "")
167 $expires = 1;
168 }
169 $name="";
170 $comm="";
171 $mail="";
172 $uidformatwrong=0;
173
174 if(sizeof($bits)<10) $uidformatwrong=1;
175
176 if(preg_match("/\@.*\@/",$bits[9]))
177 {
178 showheader(_("Welcome to CAcert.org"));
179
180 echo "<font color='#ff0000'>"._("Multiple Email Adresses per UID are not allowed.")."</font>";
181 unset($_REQUEST['process']);
182 $id = $oldid;
183 unset($oldid);
184 exit();
185 }
186
187 // Name (Comment) <Email>
188 if(preg_match("/^([^\(\)\[@<>]+) \(([^\(\)@<>]*)\) <([\w=\/%.-]*\@[\w.-]*|[\w.-]*\![\w=\/%.-]*)>/",$bits[9],$matches))
189 {
190 $name=trim(gpg_hex2bin($matches[1]));
191 $nocomment=0;
192 $comm=trim(gpg_hex2bin($matches[2]));
193 $mail=trim(gpg_hex2bin($matches[3]));
194 }
195 // Name <EMail>
196 elseif(preg_match("/^([^\(\)\[@<>]+) <([\w=\/%.-]*\@[\w.-]*|[\w.-]*\![\w=\/%.-]*)>/",$bits[9],$matches))
197 {
198 $name=trim(gpg_hex2bin($matches[1]));
199 $nocomment=1;
200 $comm="";
201 $mail=trim(gpg_hex2bin($matches[2]));
202 }
203 // Unrecognized format
204 else
205 {
206 $nocomment=1;
207 $uidformatwrong=1;
208 }
209 $nameok=verifyName($name);
210 $emailok=verifyEmail($mail);
211
212
213 if($comm != "")
214 $comment[] = $comm;
215
216 $resulttable.="<td bgcolor='#".($nameok?"c0ffc0":"ffc0c0")."'>".sanitizeHTML($name)."</td>";
217 $resulttable.="<td bgcolor='#".($emailok?"c0ffc0":"ffc0c0")."'>".sanitizeHTML($mail)."</td>";
218
219 $uidok=0;
220 if($bits[1]=="r")
221 {
222 $rmessage=_("Error: UID is revoked");
223 }
224 elseif($uidformatwrong==1)
225 {
226 $rmessage=_("The format of the UID was not recognized. Please use 'Name (comment) &lt;email@domain>'");
227 }
228 elseif($mail=="" and $name=="")
229 {
230 $rmessage=_("Error: Both Name and Email address are empty");
231 }
232 elseif($emailok and $nameok)
233 {
234 $uidok=1;
235 $rmessage=_("Name and Email OK.");
236 }
237 elseif(!$emailok and !$nameok)
238 {
239 $rmessage=_("Name and Email both cannot be matched with your account.");
240 }
241 elseif($emailok and $name=="")
242 {
243 $uidok=1;
244 $rmessage=_("The email is OK. The name is empty.");
245 }
246 elseif($nameok and $mail=="")
247 {
248 $uidok=1;
249 $rmessage=_("The name is OK. The email is empty.");
250 }
251 elseif(!$emailok)
252 {
253 $rmessage=_("The email address has not been registered and verified in your account. Please add the email address to your account first.");
254 }
255 elseif(!$nameok)
256 {
257 $rmessage=_("The name in the UID does not match the name in your account. Please verify the name.");
258 }
259
260 else
261 {
262 $rmessage=_("Error");
263 }
264 if($uidok)
265 {
266 $nok++;
267 $resulttable.="<td>$rmessage</td>";
268 $lastvalidemail=$mail;
269 }
270 else
271 {
272 $nerr++;
273 //$ToBeDeleted[]=$i;
274 //echo "Adding UID $i\n";
275 $resulttable.="<td bgcolor='#ffc0c0'>$rmessage</td>";
276 }
277 $resulttable.="</tr>\n";
278
279 if($emailok) $multiple++;
280 }
281 $resulttable.="</table>";
282
283 if($nok==0)
284 {
285 showheader(_("Welcome to CAcert.org"));
286 echo $resulttable;
287
288 echo "<font color='#ff0000'>"._("No valid UIDs found on your key")."</font>";
289 unset($_REQUEST['process']);
290 $id = $oldid;
291 unset($oldid);
292 exit();
293 }
294 elseif($nerr)
295 {
296 $resulttable.=_("The unverified UIDs have been removed, the verified UIDs have been signed.");
297 }
298
299
300 }
301
302
303 if($oldid == "0" && $CSR != "")
304 {
305 write_user_agreement(intval($_SESSION['profile']['id']), "CCA", "certificate creation", "", 1);
306
307 //set variable for comment
308 if(trim($_REQUEST['description']) == ""){
309 $description= "";
310 }else{
311 $description= trim(mysql_real_escape_string(stripslashes($_REQUEST['description'])));
312 }
313
314 $query = "insert into `gpg` set `memid`='".intval($_SESSION['profile']['id'])."',
315 `email`='".mysql_real_escape_string($lastvalidemail)."',
316 `level`='1',
317 `expires`='".mysql_real_escape_string($expires)."',
318 `multiple`='".mysql_real_escape_string($multiple)."',
319 `keyid`='".mysql_real_escape_string($keyid)."',
320 `description`='".mysql_real_escape_string($description)."'";
321 mysql_query($query);
322 $insert_id = mysql_insert_id();
323
324
325 $cwd = '/tmp/gpgspace'.$insert_id;
326 mkdir($cwd,0755);
327
328 $fp = fopen("$cwd/gpg.csr", "w");
329 fputs($fp, clean_gpgcsr($CSR));
330 fclose($fp);
331
332
333 system("gpg --homedir $cwd --import $cwd/gpg.csr");
334
335
336 $cmd_keyid = escapeshellarg($keyid);
337 $gpg = trim(`gpg --homedir $cwd --with-colons --fixed-list-mode --list-keys $cmd_keyid 2>&1`);
338 $lines = "";
339 $gpgarr = explode("\n", $gpg);
340 foreach($gpgarr as $line)
341 {
342 //echo "Line[]: $line <br/>\n";
343 if(substr($line, 0, 4) == "uid:")
344 {
345 $name = $comment = "";
346 $bits = explode(":", $line);
347
348 $pos = strpos($bits[9], "(") - 1;
349 $nocomment = 0;
350 if($pos < 0)
351 {
352 $nocomment = 1;
353 $pos = strpos($bits[9], "<") - 1;
354 }
355 if($pos < 0)
356 {
357 $pos = strlen($bits[9]);
358 }
359
360 $name = trim(gpg_hex2bin(trim(substr($bits[9], 0, $pos))));
361 $nameok=verifyName($name);
362 if($nocomment == 0)
363 {
364 $pos += 2;
365 $pos2 = strpos($bits[9], ")");
366 $comm = trim(gpg_hex2bin(trim(substr($bits[9], $pos, $pos2 - $pos))));
367 if($comm != "")
368 $comment[] = $comm;
369 $pos = $pos2 + 3;
370 } else {
371 $pos = strpos($bits[9], "<") + 1;
372 }
373
374 $mail="";
375 if (preg_match("/<([\w.-]*\@[\w.-]*)>/", $bits[9],$match)) {
376 //echo "Found: ".$match[1];
377 $mail = trim(gpg_hex2bin($match[1]));
378 }
379 else
380 {
381 //echo "Not found!\n";
382 }
383
384 $emailok=verifyEmail($mail);
385
386 $uidid=$bits[7];
387
388 if($bits[1]=="r")
389 {
390 $ToBeDeleted[]=$uidid;
391 }
392 elseif($mail=="" and $name=="")
393 {
394 //echo "$uidid will be deleted\n";
395 $ToBeDeleted[]=$uidid;
396 }
397 elseif($emailok and $nameok)
398 {
399 }
400 elseif($emailok and $name=="")
401 {
402 }
403 elseif($nameok and $mail=="")
404 {
405 }
406 elseif(!$emailok and !$nameok)
407 {
408 //echo "$uidid will be deleted\n";
409 $ToBeDeleted[]=$uidid;
410 }
411 elseif(!$emailok)
412 {
413 //echo "$uidid will be deleted\n";
414 $ToBeDeleted[]=$uidid;
415 }
416 elseif(!$nameok)
417 {
418 //echo "$uidid will be deleted\n";
419 $ToBeDeleted[]=$uidid;
420 }
421
422 }
423 }
424
425 if(count($ToBeDeleted)>0)
426 {
427 $descriptorspec = array(
428 0 => array("pipe", "r"), // stdin is a pipe that the child will read from
429 1 => array("pipe", "w"), // stdout is a pipe that the child will write to
430 2 => array("pipe", "w") // stderr is a file to write to
431 );
432
433 $stderr = fopen('php://stderr', 'w');
434
435 //echo "Keyid: $keyid\n";
436
437 $cmd_keyid = escapeshellarg($keyid);
438 $process = proc_open("/usr/bin/gpg --homedir $cwd --no-tty --command-fd 0 --status-fd 1 --logger-fd 2 --edit-key $cmd_keyid", $descriptorspec, $pipes);
439
440 //echo "Process: $process\n";
441 //fputs($stderr,"Process: $process\n");
442
443 if (is_resource($process)) {
444 //echo("it is a resource\n");
445 // $pipes now looks like this:
446 // 0 => writeable handle connected to child stdin
447 // 1 => readable handle connected to child stdout
448 // Any error output will be appended to /tmp/error-output.txt
449 while (!feof($pipes[1]))
450 {
451 $buffer = fgets($pipes[1], 4096);
452 //echo $buffer;
453
454 if($buffer == "[GNUPG:] GET_BOOL keyedit.sign_all.okay\n")
455 {
456 fputs($pipes[0],"yes\n");
457 }
458 elseif($buffer == "[GNUPG:] GOT_IT\n")
459 {
460 }
461 elseif(ereg("^\[GNUPG:\] GET_BOOL keyedit\.remove\.uid\.okay\s*",$buffer))
462 {
463 fputs($pipes[0],"yes\n");
464 }
465 elseif(ereg("^\[GNUPG:\] GET_LINE keyedit\.prompt\s*",$buffer))
466 {
467 if(count($ToBeDeleted)>0)
468 {
469 $delthisuid=array_pop($ToBeDeleted);
470 //echo "Deleting an UID $delthisuid\n";
471 fputs($pipes[0],"uid ".$delthisuid."\n");
472 }
473 else
474 {
475 //echo "Saving\n";
476 fputs($pipes[0],$state?"save\n":"deluid\n");
477 $state++;
478 }
479 }
480 elseif($buffer == "[GNUPG:] GOOD_PASSPHRASE\n")
481 {
482 }
483 elseif(ereg("^\[GNUPG:\] KEYEXPIRED ",$buffer))
484 {
485 echo "Key expired!\n";
486 exit;
487 }
488 elseif($buffer == "")
489 {
490 //echo "Empty!\n";
491 }
492 else
493 {
494 echo "ERROR: UNKNOWN $buffer\n";
495 }
496
497
498 }
499 //echo "Fertig\n";
500 fclose($pipes[0]);
501
502 //echo stream_get_contents($pipes[1]);
503 fclose($pipes[1]);
504
505 // It is important that you close any pipes before calling
506 // proc_close in order to avoid a deadlock
507 $return_value = proc_close($process);
508
509 //echo "command returned $return_value\n";
510 }
511 else
512 {
513 echo "Keine ressource!\n";
514 }
515
516
517 }
518
519
520 $csrname=generatecertpath("csr","gpg",$insert_id);
521 $cmd_keyid = escapeshellarg($keyid);
522 $do=`gpg --homedir $cwd --batch --export-options export-minimal --export $cmd_keyid >$csrname`;
523
524 mysql_query("update `gpg` set `csr`='$csrname' where `id`='$insert_id'");
525 waitForResult('gpg', $insert_id);
526
527 showheader(_("Welcome to CAcert.org"));
528 echo $resulttable;
529 $query = "select * from `gpg` where `id`='$insert_id' and `crt`!=''";
530 $res = mysql_query($query);
531 if(mysql_num_rows($res) <= 0)
532 {
533 echo _("Your certificate request has failed to be processed correctly, please try submitting it again.")."<br>\n";
534 echo _("If this is a re-occuring problem, please send a copy of the key you are trying to signed to support@cacert.org. Thank you.");
535 } else {
536 echo "<pre>";
537 readfile(generatecertpath("crt","gpg",$insert_id));
538 echo "</pre>";
539 }
540
541 showfooter();
542 exit;
543 }
544
545 if($oldid == 2 && array_key_exists('change',$_REQUEST) && $_REQUEST['change'] != "")
546 {
547 showheader(_("My CAcert.org Account!"));
548 foreach($_REQUEST as $id => $val)
549 {
550 if(substr($id,0,14)=="check_comment_")
551 {
552 $cid = intval(substr($id,14));
553 $comment=trim(mysql_real_escape_string(stripslashes($_REQUEST['comment_'.$cid])));
554 mysql_query("update `gpg` set `description`='$comment' where `id`='$cid' and `memid`='".$_SESSION['profile']['id']."'");
555 }
556 }
557 echo(_("Certificate settings have been changed.")."<br/>\n");
558 showfooter();
559 exit;
560 }
561
562 $id = intval($id);
563
564 showheader(_("Welcome to CAcert.org"));
565 includeit($id, "gpg");
566 showfooter();
567 ?>