]> git.mjollnir.org Git - moodle.git/commitdiff
Mnet: Key rotation: A more robust changeover for fresh keys
authordonal72 <donal72>
Mon, 15 Jan 2007 09:03:39 +0000 (09:03 +0000)
committerdonal72 <donal72>
Mon, 15 Jan 2007 09:03:39 +0000 (09:03 +0000)
mnet/remote_client.php
mnet/xmlrpc/client.php
mnet/xmlrpc/server.php

index 2cfcfcffc4233c77690fdc1d45adea087fb1c91e..649e7de657c19d6ee2b86e00b5ac7d3b9862fae8 100644 (file)
@@ -46,5 +46,27 @@ class mnet_remote_client extends mnet_peer {
 
         return false;
     }
+
+    function refresh_key() {
+        // set up an RPC request
+        $mnetrequest = new mnet_xmlrpc_client();
+        // Use any method - listServices is pretty lightweight.
+        $mnetrequest->set_method('system/listServices');
+
+        // Do RPC call and store response
+        if ($mnetrequest->send($this) === true) {
+            // Ok - we actually don't care about the result
+            $temp = new mnet_peer();
+            $temp->set_id($this->id);
+            if($this->public_key != $temp->public_key) {
+                $newkey = param_clean($temp->public_key, PARAM_PEM);
+                if(!empty($newkey)) {
+                    $this->public_key = $newkey;
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
 }
 ?>
\ No newline at end of file
index 663a7d3e6f8dc659db7cbaf0afb25a874a2ec2e3..96e5f0d897e964745593b1f9f3aa5ff2b3c38094 100644 (file)
@@ -203,6 +203,25 @@ class mnet_xmlrpc_client {
             $isOpen = openssl_open(base64_decode($data), $payload, base64_decode($key), $MNET->get_private_key());
 
             if (!$isOpen) {
+                // Decryption failed... let's try our archived keys
+                $result = get_config('mnet', 'openssl_history');
+                if(empty($result)) {
+                    set_config('openssl_history', serialize(array()), 'mnet');
+                    $result = get_config('mnet', 'openssl_history');
+                }
+                $openssl_history = unserialize($result->value);
+                foreach($openssl_history as $keyset) {
+                    $keyresource = openssl_pkey_get_private($keyset['keypair_PEM']);
+                    $isOpen      = openssl_open(base64_decode($data), $payload, base64_decode($key), $keyresource);
+                    if ($isOpen) {
+                        // It's an older code, sir, but it checks out
+                        break;
+                    }
+                }
+            }
+
+            if (!$isOpen) {
+                trigger_error("None of our keys could open the payload from host {$mnet_peer->wwwroot} with id {$mnet_peer->id}.");
                 return false;
             }
 
@@ -256,14 +275,22 @@ class mnet_xmlrpc_client {
             if($this->response['faultCode'] == 7025 && empty($mnet_peer->re_key)) {
                 $record                     = new stdClass();
                 $record->id                 = $mnet_peer->id;
-                $record->public_key         = $this->response['faultString'];
-                $details                    = openssl_x509_parse($record->public_key);
-                $record->public_key_expires = $details['validTo_time_t'];
-                update_record('mnet_host', $record);
-                $mnet_peer2 = new mnet_peer();
-                $mnet_peer2->set_id($record->id);
-                $mnet_peer2->re_key = true;
-                $this->send($mnet_peer2);
+                if($this->response['faultString'] == clean_param($this->response['faultString'], PARAM_PEM)) {
+                    $record->public_key         = $this->response['faultString'];
+                    $details                    = openssl_x509_parse($record->public_key);
+                    if(is_array($details) && isset($details['validTo_time_t'])) {
+                        $record->public_key_expires = $details['validTo_time_t'];
+                        update_record('mnet_host', $record);
+                        $mnet_peer2 = new mnet_peer();
+                        $mnet_peer2->set_id($record->id);
+                        $mnet_peer2->re_key = true;
+                        $this->send($mnet_peer2);
+                    } else {
+                        $this->error[] = $this->response['faultCode'] . " : " . $this->response['faultString'];
+                    }
+                } else {
+                    $this->error[] = $this->response['faultCode'] . " : " . $this->response['faultString'];
+                }
             } else {
                 $this->error[] = $this->response['faultCode'] . " : " . $this->response['faultString'];
             }
index b097586b9044863929f714b200f308b1db34baa6..ad36654b01207bc4c13bb0314a72c3c7c15a039f 100644 (file)
@@ -121,6 +121,15 @@ function mnet_server_strip_wrappers($HTTP_RAW_POST_DATA) {
         $crypt_parser = new mnet_encxml_parser();
         $crypt_parser->parse($HTTP_RAW_POST_DATA);
 
+        // Make sure we know who we're talking to
+        $host_record_exists = $MNET_REMOTE_CLIENT->set_wwwroot($crypt_parser->remote_wwwroot);
+
+        if (false == $host_record_exists) {
+            exit(mnet_server_fault(7020, 'wrong-wwwroot', $crypt_parser->remote_wwwroot));
+        } elseif (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] != $MNET_REMOTE_CLIENT->ip_address) {
+            exit(mnet_server_fault(7017, 'wrong-ip'));
+        }
+
         if ($crypt_parser->payload_encrypted) {
 
             $key  = array_pop($crypt_parser->cipher);  // This key is Symmetric
@@ -128,8 +137,8 @@ function mnet_server_strip_wrappers($HTTP_RAW_POST_DATA) {
 
             $crypt_parser->free_resource();
 
-            // Initialize payload var
-            $payload = '';
+            $payload          = '';    // Initialize payload var
+            $push_current_key = false; // True if we need to push a fresh key to the peer
 
             //                                          &$payload
             $isOpen = openssl_open(base64_decode($data), $payload, base64_decode($key), $MNET->get_private_key());
@@ -147,7 +156,7 @@ function mnet_server_strip_wrappers($HTTP_RAW_POST_DATA) {
                     $isOpen      = openssl_open(base64_decode($data), $payload, base64_decode($key), $keyresource);
                     if ($isOpen) {
                         // It's an older code, sir, but it checks out
-                        exit(mnet_server_fault(7025, $MNET->public_key));
+                        $push_current_key = true;
                     }
                 }
             }
@@ -170,12 +179,12 @@ function mnet_server_strip_wrappers($HTTP_RAW_POST_DATA) {
 
         unset($payload);
 
-        $host_record_exists = $MNET_REMOTE_CLIENT->set_wwwroot($sig_parser->remote_wwwroot);
-
-        if (false == $host_record_exists) {
-            exit(mnet_server_fault(7020, 'wrong-wwwroot', $sig_parser->remote_wwwroot));
-        } elseif (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] != $MNET_REMOTE_CLIENT->ip_address) {
-            exit(mnet_server_fault(7017, 'wrong-ip'));
+        // if the peer used one of our public keys that have expired, we will
+        // return a signed/encrypted error message with our new public key 
+        if($push_current_key) {
+            // NOTE: Here, we use the 'mnet_server_fault_xml' to avoid
+            // get_string being called on our public_key
+            exit(mnet_server_fault_xml(7025, $MNET->public_key));
         }
 
         /**
@@ -194,7 +203,16 @@ function mnet_server_strip_wrappers($HTTP_RAW_POST_DATA) {
         if ($signature_verified == 1) {
             // Parse the XML
         } elseif ($signature_verified == 0) {
-            exit(mnet_server_fault(710, 'verifysignature-invalid'));
+            $currkey = mnet_get_public_key($MNET_REMOTE_CLIENT->wwwroot);
+            if($currkey != $certificate) {
+                // Has the server updated its certificate since our last 
+                // handshake?
+                if(!$MNET_REMOTE_CLIENT->refresh_key()) {
+                    exit(mnet_server_fault(7026, 'verifysignature-invalid'));
+                }
+            } else {
+                exit(mnet_server_fault(710, 'verifysignature-invalid'));
+            }
         } else {
             exit(mnet_server_fault(711, 'verifysignature-error'));
         }