Skip to content

Instantly share code, notes, and snippets.

@ralphbean
Created July 2, 2013 00:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ralphbean/5905893 to your computer and use it in GitHub Desktop.
Save ralphbean/5905893 to your computer and use it in GitHub Desktop.
A test script to see if we can send a message signed consistently.
<?php
// globals
$config = 0;
$queue = 0;
// A utility function, taken from the comments at
// http://php.net/manual/en/language.types.boolean.php
function to_bool ($_val) {
$_trueValues = array('yes', 'y', 'true');
$_forceLowercase = true;
if (is_string($_val)) {
return (in_array(
($_forceLowercase?strtolower($_val):$_val),
$_trueValues
));
} else {
return (boolean) $_val;
}
}
// A utility function to recursively sort an associative
// array by key. Kind of like ordereddict from Python.
// Used for encoding and signing messages.
function deep_ksort(&$arr) {
ksort($arr);
foreach ($arr as &$a) {
if (is_array($a) && !empty($a)) {
deep_ksort($a);
}
}
}
function initialize() {
global $config, $queue;
/* Load the config. Create a publishing socket. */
// Danger! Danger!
$json = shell_exec("fedmsg-config");
$config = json_decode($json, true);
/* Just make sure everything is sane with the fedmsg config */
if (!array_key_exists('relay_inbound', $config)) {
echo("fedmsg-config has no 'relay_inbound'");
return false;
}
$context = new ZMQContext(1, true);
$queue = $context->getSocket(ZMQ::SOCKET_PUB, "pub-a-dub-dub");
$queue->setSockOpt(ZMQ::SOCKOPT_LINGER, $config['zmq_linger']);
if (is_array($config['relay_inbound'])) {
// API for fedmsg >= 0.5.2
// TODO - be more robust here and if connecting to the first one fails, try
// the next, and the next, and etc...
$queue->connect($config['relay_inbound'][0]);
} else {
// API for fedmsg <= 0.5.1
$queue->connect($config['relay_inbound']);
}
# Go to sleep for a brief moment.. just long enough to let our zmq socket
# initialize.
if (array_key_exists('post_init_sleep', $config)) {
usleep($config['post_init_sleep'] * 1000000);
}
return true;
}
# This is a reimplementation of the python code in fedmsg/crypto.py
# That file is authoritative. Changes there should be reflected here.
function sign_message($message_obj) {
global $config;
# This is required so that the string we sign is identical in python and in
# php. Ordereddict is used there; ksort here.
deep_ksort($message_obj);
# It would be best to pass JSON_UNESCAPE_SLASHES as an option here, but it is
# not available until php-5.4
$message = json_encode($message_obj);
# In the meantime, we'll remove escaped slashes ourselves. This is
# necessary in order to produce the exact same encoding as python (so that our
# signatures match for validation).
$message = stripcslashes($message);
# Step 0) - Find our cert.
$fqdn = gethostname();
$tokens = explode('.', $fqdn);
$hostname = $tokens[0];
$ssldir = $config['ssldir'];
$certname = $config['certnames']['mediawiki.'.$hostname];
# Step 1) - Load and encode the X509 cert
$cert_obj = openssl_x509_read(file_get_contents(
$ssldir.'/'.$certname.".crt"
));
$cert = "";
openssl_x509_export($cert_obj, $cert);
$cert = base64_encode($cert);
# Step 2) - Load and sign the jsonified message with the RSA private key
$rsa_private = openssl_get_privatekey(file_get_contents(
$ssldir.'/'.$certname.".key"
));
$signature = "";
openssl_sign($message, $signature, $rsa_private);
$signature = base64_encode($signature);
# Step 3) - Stuff it back in the message and return
$message_obj['signature'] = $signature;
$message_obj['certificate'] = $cert;
return $message_obj;
}
function emit_message($subtopic, $message) {
global $config, $queue;
# Re-implement some of the logc from fedmsg/core.py
# We'll have to be careful to keep this up to date.
$prefix = "org.fedoraproject." . $config['environment'] . ".wiki.";
$topic = $prefix . $subtopic;
$message_obj = array(
"topic" => $topic,
"msg" => $message,
"timestamp" => time(),
# TODO -> we don't have a good way to increment this counter from php yet.
"i" => 1,
);
if (array_key_exists('sign_messages', $config) and to_bool($config['sign_messages'])) {
$message_obj = sign_message($message_obj);
}
$envelope = json_encode($message_obj);
$queue->send($topic, ZMQ::MODE_SNDMORE);
$queue->send($envelope);
}
function test_message() {
initialize();
emit_message("php.test", array("content"=>"something"));
}
echo("Hello.");
test_message();
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment