forked from extern/egroupware
dkim signature for posts using mailDomainSigner class, plus some code to generate and store a key-pair
This commit is contained in:
parent
49f1d43ad1
commit
33510a2f4d
@ -55,6 +55,34 @@ class ischedule_client
|
||||
{
|
||||
$this->url = $url;
|
||||
}
|
||||
|
||||
$this->dkim_private_key = $GLOBALS['egw_info']['server']['dkim_private_key'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate private/public key pair
|
||||
*
|
||||
* Private and public key are stored in api config as dkim_private_key / dkim_public_key and loaded automatic by constructor.
|
||||
*
|
||||
* @return string public key
|
||||
*/
|
||||
public static function generateKeyPair()
|
||||
{
|
||||
// Create the keypair
|
||||
$res = openssl_pkey_new();
|
||||
|
||||
// Get private key
|
||||
openssl_pkey_export($res, $dkim_private_key);
|
||||
|
||||
// Get public key
|
||||
$details = openssl_pkey_get_details($res);
|
||||
$dkim_public_key = $details['key'];
|
||||
|
||||
// store both in config
|
||||
config::save_value('dkim_private_key', $dkim_private_key, 'phpgwapi');
|
||||
config::save_value('dkim_public_key', $dkim_public_key, 'phpgwapi');
|
||||
|
||||
return $dkim_public_key;
|
||||
}
|
||||
|
||||
const EMAIL_PREG = '/^([a-z0-9][a-z0-9._-]*)?[a-z0-9]@([a-z0-9](|[a-z0-9_-]*[a-z0-9])\.)+[a-z]{2,6}$/i';
|
||||
@ -131,11 +159,16 @@ class ischedule_client
|
||||
*
|
||||
* @param string $content
|
||||
* @param string $content_type
|
||||
* @param boolean $debug=false true echo request before posting
|
||||
* @return string
|
||||
* @throws Exception with http status code and message, if server responds other then 2xx
|
||||
*/
|
||||
public function post_msg($content, $content_type)
|
||||
public function post_msg($content, $content_type, $debug=false)
|
||||
{
|
||||
if (empty($this->dkim_private_key))
|
||||
{
|
||||
throw new Exception('You need to generate a key pair first!');
|
||||
}
|
||||
$url_parts = parse_url($this->url);
|
||||
$headers = array(
|
||||
'Host' => $url_parts['host'].($url_parts['port'] ? ':'.$url_parts['port'] : ''),
|
||||
@ -145,12 +178,13 @@ class ischedule_client
|
||||
'Recipient' => $this->recipient,
|
||||
'Content-Length' => bytes($content),
|
||||
);
|
||||
$headers['DKIM-Signature'] = $this->dkim_sign($headers, $content);
|
||||
$header_string = '';
|
||||
foreach($headers as $name => $value)
|
||||
{
|
||||
$header_string .= $name.': '.$value."\r\n";
|
||||
}
|
||||
$header_string .= $this->dkim_sign($headers, $content)."\r\n";
|
||||
|
||||
$opts = array('http' =>
|
||||
array(
|
||||
'method' => 'POST',
|
||||
@ -160,6 +194,8 @@ class ischedule_client
|
||||
)
|
||||
);
|
||||
|
||||
if ($debug) echo "POST $this->url HTTP/1.1\n$header_string\n$content\n";
|
||||
|
||||
// need to suppress warning, if http-status not 2xx
|
||||
if (($response = @file_get_contents($this->url, false, stream_context_create($opts))) === false)
|
||||
{
|
||||
@ -172,13 +208,29 @@ class ischedule_client
|
||||
/**
|
||||
* Calculate DKIM signature for headers and body using originators domains private key
|
||||
*
|
||||
* @param array $headers
|
||||
* @param array $headers name => value pairs, names as in $sign_headers
|
||||
* @param string $body
|
||||
* @param string $type dkim-type
|
||||
* @param string $selector='calendar'
|
||||
* @param string $sign_headers='Content-Type:Host:Originator:Recipient'
|
||||
* @return string DKIM-Signature: ...
|
||||
*/
|
||||
public function dkim_sign(array $headers, $body, $type='calendar')
|
||||
public function dkim_sign(array $headers, $body, $selector='calendar', $sign_headers='Content-Type:Host:Originator:Recipient')
|
||||
{
|
||||
return 'dummy';
|
||||
include_once EGW_API_INC.'/php-mail-domain-signer/lib/class.mailDomainSigner.php';
|
||||
list(,$domain) = explode('@', $this->originator);
|
||||
$mds = new mailDomainSigner($this->dkim_private_key, $domain, $selector);
|
||||
|
||||
$dkim_headers = array();
|
||||
foreach(explode(':', $sign_headers) as $header)
|
||||
{
|
||||
$dkim_headers[] = $header.': '.$headers[$header];
|
||||
}
|
||||
$dkim = $mds->getDKIM(strtolower($sign_headers), $dkim_headers, $body);
|
||||
|
||||
// as we do http, no need to fold dkim, in fact recommendation is not to
|
||||
$dkim = str_replace(array(";\r\n\t", "\r\n\t"), array('; ', ''), $dkim);
|
||||
|
||||
return $dkim;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -21,7 +21,15 @@ if (isset($_SERVER['HTTP_HOST'])) die("This is a commandline ONLY tool!\n");
|
||||
*/
|
||||
function usage($err=null)
|
||||
{
|
||||
echo basename(__FILE__).": [--url ischedule-url] [--component (VEVENT|VFREEBUSY|VTODO) (-|ical-filename)] [--method (REQUEST(default)|RESPONSE)] recipient-email [originator-email]\n\n";
|
||||
echo "\nUsage: ".basename(__FILE__).": [options] recipient-email [originator-email]\n\n";
|
||||
echo "available options:\n\n";
|
||||
echo "\t--url ischedule-url\n";
|
||||
echo "\t--component (VEVENT|VFREEBUSY|VTODO) (-|ical-filename)\n";
|
||||
echo "\t--method (REQUEST(default)|REPLY|CANCEL|ADD)\n";
|
||||
echo "\t--generate-key-pair : generates and stores a new key pair\n";
|
||||
echo "\t--public-key : outputs public key\n";
|
||||
echo "\t-v|--verbose output posted message too\n";
|
||||
echo "\n";
|
||||
if ($err) echo "$err\n\n";
|
||||
exit;
|
||||
}
|
||||
@ -42,10 +50,10 @@ $method = 'REQUEST';
|
||||
while($args[0][0] == '-')
|
||||
{
|
||||
$option = array_shift($args);
|
||||
if (count($args) < 2) usage("Missing arguments for '$option'!".array2string($args));
|
||||
switch($option)
|
||||
{
|
||||
case '--url':
|
||||
if (count($args) < 2) usage("Missing arguments for '$option'!");
|
||||
$url = array_shift($args);
|
||||
break;
|
||||
|
||||
@ -64,6 +72,7 @@ while($args[0][0] == '-')
|
||||
break;
|
||||
|
||||
case '--method':
|
||||
if (count($args) < 2) usage("Missing arguments for '$option'!");
|
||||
$method = strtoupper(array_shift($args));
|
||||
if (!in_array($method, array('REQUEST','REPLY','CANCEL','ADD')))
|
||||
{
|
||||
@ -71,23 +80,41 @@ while($args[0][0] == '-')
|
||||
}
|
||||
break;
|
||||
|
||||
case '-v':
|
||||
case '--verbose':
|
||||
$verbose = true;
|
||||
break;
|
||||
|
||||
case '--generate-key-pair':
|
||||
$GLOBALS['egw_info']['server']['dkim_public_key'] = ischedule_client::generateKeyPair();
|
||||
echo "\nKey pair generated\n";
|
||||
// fall through
|
||||
case '--public-key':
|
||||
if (empty($GLOBALS['egw_info']['server']['dkim_public_key'])) die("\nYou need to generate a key pair first!\n\n");
|
||||
echo "\nYou need following DNS record:\n";
|
||||
$public_key = preg_replace('/([-]+(BEGIN|END) PUBLIC KEY[-]+|\s*)/m', '', $GLOBALS['egw_info']['server']['dkim_public_key']);
|
||||
echo "\ncalendar._domainkey IN TXT \"v=DKIM1;k=rsa;h=sha1;s=calendar;t=s;p=$public_key\"\n\n";
|
||||
exit;
|
||||
|
||||
default:
|
||||
usage("Unknown option '$option'!");
|
||||
}
|
||||
}
|
||||
if (!count($args)) usage();
|
||||
if (!count($args) && !($public_key || $generate_key_pair)) usage();
|
||||
|
||||
$recipient = array_shift($args);
|
||||
if ($args) $originator = array_shift($args);
|
||||
|
||||
try {
|
||||
$client = new ischedule_client($recipient, $url);
|
||||
|
||||
echo "\nUsing iSchedule URL: $client->url\n\n";
|
||||
if ($originator) $client->setOriginator($originator);
|
||||
if ($component)
|
||||
{
|
||||
$content_type = 'text/calendar; component='.$component.'; method='.$method;
|
||||
echo $client->post_msg($content, $content_type);
|
||||
$response = $client->post_msg($content, $content_type, $verbose);
|
||||
echo $response;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user