Add optional PGP key verification on web server side.

This commit is contained in:
perennate 2013-09-27 21:57:07 -04:00
parent bcebd12269
commit e12f0f1d52
4 changed files with 133 additions and 0 deletions

View File

@ -42,6 +42,9 @@ $config['site_url'] = 'http://example.com/gpgmw';
//title of the website (displayed on home page)
$config['site_title'] = 'PGP key management';
//whether debug mode should be enabled
$config['debug'] = false;
//
// MAIL SETTINGS
//
@ -71,6 +74,27 @@ $config['db_username'] = 'gpgmw';
//database password
$config['db_password'] = '';
//
// PGP VERIFICATION SETTINGS
//
//whether to enable immediate verification of PGP keys
// keys will always be verified with the email address in our cron job
// but this will enable verification from the web interface before email confirmation
//for this to work, Crypt_GPG from http://pear.php.net/Crypt_GPG must be installed
// (as well as any of its dependencies), and pgpverify_tmpdir must be set
$config['pgpverify_enable'] = false;
//a temporary directory to use for PGP verification, without trailing slash
// gpgmw will create subdirectories from here to use as temporary gpg home directories
// these directories will (should) be deleted immediately after use
$config['pgpverify_tmpdir'] = '/tmp';
//whether to allow blank "keys"
// this is useful to allow users to delete their key from the keystore
// if they no longer want encryption
$config['pgpverify_allowblank'] = true;
//
// LOCK SETTINGS
//

View File

@ -99,6 +99,21 @@ function secure_random() {
return hexdec(bin2hex(secure_random_bytes(3)));
}
function recursiveDelete($dirPath) {
foreach(
new RecursiveIteratorIterator(
new RecursiveDirectoryIterator(
$dirPath, FilesystemIterator::SKIP_DOTS
),
RecursiveIteratorIterator::CHILD_FIRST
)
as $path) {
$path->isFile() ? unlink($path->getPathname()) : rmdir($path->getPathname());
}
rmdir($dirPath);
}
function gpgmw_mail($subject, $body, $to) { //returns true=ok, false=notok
$config = $GLOBALS['config'];
$from = filter_var($config['email_from'], FILTER_SANITIZE_EMAIL);

View File

@ -0,0 +1,85 @@
<?php
/*
gpg-mailgate
This file is part of the gpg-mailgate source code.
gpg-mailgate is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
gpg-mailgate source code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with gpg-mailgate source code. If not, see <http://www.gnu.org/licenses/>.
*/
//uses gpg to verify that a key belongs to a given email address
function verifyPGPKey($content, $email) {
global $config;
//allow blank "keys" if this is set
//this means that encryption for $email will be disabled by the cron if it
// was enabled originally
if($config['pgpverify_allowblank'] && trim($content) == '') {
return true;
}
require_once("Crypt/GPG.php");
//try to create a random subdirectory of $config['pgpverify_tmpdir']
do {
$path = $config['pgpverify_tmpdir'] . '/' . uid(16);
} while(file_exists($path));
$result = @mkdir($path);
if($result === false) {
if($config['debug']) {
die("Failed to create directory [" . $path . "] for PGP verification.");
} else {
return false;
}
}
$gpg = new Crypt_GPG(array('homedir' => $path));
//import the key to our GPG temp directory
try {
$gpg->importKey($content);
} catch(Crypt_GPG_NoDataException $e) {
//user supplied an invalid key!
recursiveDelete($path);
return false;
}
//verify the email address matches
$keys = $gpg->getKeys();
if(count($keys) != 1) {
if($config['debug']) {
die("Error in PGP verification: key count is " . count($keys) . "!");
} else {
recursiveDelete($path);
return false;
}
}
$userIds = $keys[0]->getUserIds();
if(count($userIds) != 1 || strtolower($userIds[0]->getEmail()) != strtolower($email)) {
recursiveDelete($path);
return false;
}
recursiveDelete($path);
return true;
}
?>

View File

@ -56,6 +56,15 @@ function requestPGP($email, $key) {
}
}
//if PGP key verification is enabled, do it
if($config['pgpverify_enable']) {
require_once(includePath() . "/gpg.php");
if(!verifyPGPKey($key, $email)) {
return "your key does not appear to be valid (ensure ASCII armor is enabled and that the email address entered matches the email address of the key)";
}
}
//well, it looks good, let's submit it
lockAction('requestpgp');
$confirm = uid(32);