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