Add optional PGP key verification on web server side.
This commit is contained in:
parent
bcebd12269
commit
e12f0f1d52
4 changed files with 133 additions and 0 deletions
|
@ -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
|
||||
//
|
||||
|
|
|
@ -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);
|
||||
|
|
85
gpg-mailgate-web/public_html/include/gpg.php
Normal file
85
gpg-mailgate-web/public_html/include/gpg.php
Normal 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;
|
||||
}
|
||||
|
||||
?>
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue