summaryrefslogtreecommitdiffstats
path: root/net/tools/testserver/device_management.py
diff options
context:
space:
mode:
authormnissler@chromium.org <mnissler@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-11 12:13:05 +0000
committermnissler@chromium.org <mnissler@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-11 12:13:05 +0000
commitcff5dadeb1be4c526a1b3875c9acf422cbaf834d (patch)
treeda0c0f9f6ff4fd3ede6e5f9a694c13bf8ed8c036 /net/tools/testserver/device_management.py
parent589344c079be45268437f11e55f73fa9ca031d17 (diff)
downloadchromium_src-cff5dadeb1be4c526a1b3875c9acf422cbaf834d.zip
chromium_src-cff5dadeb1be4c526a1b3875c9acf422cbaf834d.tar.gz
chromium_src-cff5dadeb1be4c526a1b3875c9acf422cbaf834d.tar.bz2
Support signatures in the policy test server.
Remove the old certificate-handling code and make the test server read a private key file instead. Public key is sent to the client in PKCS#1/DER format as required by the protocol. BUG=None TEST=manual Review URL: http://codereview.chromium.org/6823004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@81090 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/tools/testserver/device_management.py')
-rw-r--r--net/tools/testserver/device_management.py82
1 files changed, 60 insertions, 22 deletions
diff --git a/net/tools/testserver/device_management.py b/net/tools/testserver/device_management.py
index efd6694..57579b5 100644
--- a/net/tools/testserver/device_management.py
+++ b/net/tools/testserver/device_management.py
@@ -48,6 +48,7 @@ import sys
import time
import tlslite
import tlslite.api
+import tlslite.utils
# The name and availability of the json module varies in python versions.
try:
@@ -58,9 +59,12 @@ except ImportError:
except ImportError:
json = None
+import asn1der
import device_management_backend_pb2 as dm
import cloud_policy_pb2 as cp
+# ASN.1 object identifier for PKCS#1/RSA.
+PKCS1_RSA_OID = '\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01'
class RequestHandler(object):
"""Decodes and handles device management requests from clients.
@@ -419,23 +423,35 @@ class RequestHandler(object):
self.GatherPolicySettings(settings,
self._server.policy[msg.policy_type])
+ # Figure out the key we want to use.
+ key = None
+ if (msg.signature_type == dm.PolicyFetchRequest.SHA1_RSA and
+ len(self._server.keys)):
+ key_version = min(max(1, msg.public_key_version), len(self._server.keys))
+ key = self._server.keys[key_version - 1]
+
+ # Fill the policy data protobuf.
policy_data = dm.PolicyData()
- policy_data.policy_value = settings.SerializeToString()
policy_data.policy_type = msg.policy_type
policy_data.timestamp = int(time.time() * 1000)
policy_data.request_token = token_info['device_token'];
+ policy_data.policy_value = settings.SerializeToString()
policy_data.machine_name = token_info['machine_name']
+ if key:
+ policy_data.public_key_version = key_version
+ policy_data.username = self._server.username
+ policy_data.device_id = token_info['device_id']
signed_data = policy_data.SerializeToString()
response = dm.DeviceManagementResponse()
response.error = dm.DeviceManagementResponse.SUCCESS
fetch_response = response.policy_response.response.add()
fetch_response.policy_data = signed_data
- fetch_response.policy_data_signature = (
- self._server.private_key.hashAndSign(signed_data).tostring())
- for certificate in self._server.cert_chain:
- fetch_response.certificate_chain.append(
- certificate.writeBytes().tostring())
+ if key:
+ fetch_response.policy_data_signature = (
+ key['private_key'].hashAndSign(signed_data).tostring())
+ if msg.public_key_version != key_version:
+ fetch_response.new_public_key = key['public_key']
self.DumpMessage('Response', response)
@@ -485,16 +501,22 @@ class RequestHandler(object):
class TestServer(object):
"""Handles requests and keeps global service state."""
- def __init__(self, policy_path, policy_cert_chain):
+ def __init__(self, policy_path, private_key_paths, policy_user):
"""Initializes the server.
Args:
policy_path: Names the file to read JSON-formatted policy from.
- policy_cert_chain: List of paths to X.509 certificate files of the
- certificate chain used for signing responses.
+ private_key_paths: List of paths to read private keys from.
"""
self._registered_tokens = {}
self.policy = {}
+
+ # There is no way to for the testserver to know the user name belonging to
+ # the GAIA auth token we received (short of actually talking to GAIA). To
+ # address this, we have a command line parameter to set the username that
+ # the server should report to the client.
+ self.username = policy_user
+
if json is None:
print 'No JSON module, cannot parse policy information'
else :
@@ -503,19 +525,35 @@ class TestServer(object):
except IOError:
print 'Failed to load policy from %s' % policy_path
- self.private_key = None
- self.cert_chain = []
- for cert_path in policy_cert_chain:
- try:
- cert_text = open(cert_path).read()
- except IOError:
- print 'Failed to load certificate from %s' % cert_path
- certificate = tlslite.api.X509()
- certificate.parse(cert_text)
- self.cert_chain.append(certificate)
- if self.private_key is None:
- self.private_key = tlslite.api.parsePEMKey(cert_text, private=True)
- assert self.private_key != None
+ self.keys = []
+ if private_key_paths:
+ # Load specified keys from the filesystem.
+ for key_path in private_key_paths:
+ try:
+ key = tlslite.api.parsePEMKey(open(key_path).read(), private=True)
+ except IOError:
+ print 'Failed to load private key from %s' % key_path
+ continue
+
+ assert key != None
+ self.keys.append({ 'private_key' : key })
+ else:
+ # Generate a key if none were specified.
+ key = tlslite.api.generateRSAKey(1024)
+ assert key != None
+ self.keys.append({ 'private_key' : key })
+
+ # Derive the public keys from the loaded private keys.
+ for entry in self.keys:
+ key = entry['private_key']
+
+ algorithm = asn1der.Sequence(
+ [ asn1der.Data(asn1der.OBJECT_IDENTIFIER, PKCS1_RSA_OID),
+ asn1der.Data(asn1der.NULL, '') ])
+ rsa_pubkey = asn1der.Sequence([ asn1der.Integer(key.n),
+ asn1der.Integer(key.e) ])
+ pubkey = asn1der.Sequence([ algorithm, asn1der.Bitstring(rsa_pubkey) ])
+ entry['public_key'] = pubkey;
def HandleRequest(self, path, headers, request):
"""Handles a request.