Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(169)

Side by Side Diff: net/tools/testserver/device_management.py

Issue 12183017: Verify the signature on user cloud policy downloads. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Comment Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 """A bare-bones test server for testing cloud policy support. 5 """A bare-bones test server for testing cloud policy support.
6 6
7 This implements a simple cloud policy test server that can be used to test 7 This implements a simple cloud policy test server that can be used to test
8 chrome's device management service client. The policy information is read from 8 chrome's device management service client. The policy information is read from
9 the file named device_management in the server's data directory. It contains 9 the file named device_management in the server's data directory. It contains
10 enforced and recommended policies for the device and user scope, and a list 10 enforced and recommended policies for the device and user scope, and a list
(...skipping 27 matching lines...) Expand all
38 }, 38 },
39 "google/chromeos/publicaccount/user@example.com" : { 39 "google/chromeos/publicaccount/user@example.com" : {
40 "mandatory" : { 40 "mandatory" : {
41 "HomepageLocation" : "http://www.chromium.org" 41 "HomepageLocation" : "http://www.chromium.org"
42 }, 42 },
43 "recommended" : { 43 "recommended" : {
44 } 44 }
45 }, 45 },
46 "managed_users" : [ 46 "managed_users" : [
47 "secret123456" 47 "secret123456"
48 ] 48 ],
49 "current_key_index": 0
49 } 50 }
50 51
51 """ 52 """
52 53
53 import cgi 54 import cgi
54 import hashlib 55 import hashlib
55 import logging 56 import logging
56 import os 57 import os
57 import random 58 import random
58 import re 59 import re
(...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after
448 if msg.policy_type in token_info['allowed_policy_types']: 449 if msg.policy_type in token_info['allowed_policy_types']:
449 if (msg.policy_type == 'google/chromeos/user' or 450 if (msg.policy_type == 'google/chromeos/user' or
450 msg.policy_type == 'google/chrome/user' or 451 msg.policy_type == 'google/chrome/user' or
451 msg.policy_type == 'google/chromeos/publicaccount'): 452 msg.policy_type == 'google/chromeos/publicaccount'):
452 settings = cp.CloudPolicySettings() 453 settings = cp.CloudPolicySettings()
453 self.GatherUserPolicySettings(settings, policy.get(policy_key, {})) 454 self.GatherUserPolicySettings(settings, policy.get(policy_key, {}))
454 elif msg.policy_type == 'google/chromeos/device': 455 elif msg.policy_type == 'google/chromeos/device':
455 settings = dp.ChromeDeviceSettingsProto() 456 settings = dp.ChromeDeviceSettingsProto()
456 self.GatherDevicePolicySettings(settings, policy.get(policy_key, {})) 457 self.GatherDevicePolicySettings(settings, policy.get(policy_key, {}))
457 458
458 # Figure out the key we want to use. If multiple keys are configured, the 459 # Sign with 'current_key_index', defaulting to key 0.
459 # server will rotate through them in a round-robin fashion.
460 signing_key = None 460 signing_key = None
461 req_key = None 461 req_key = None
462 key_version = 1 462 current_key_index = policy.get('current_key_index', 0)
463 nkeys = len(self._server.keys) 463 nkeys = len(self._server.keys)
464 if msg.signature_type == dm.PolicyFetchRequest.SHA1_RSA and nkeys > 0: 464 if (msg.signature_type == dm.PolicyFetchRequest.SHA1_RSA and
465 current_key_index in range(nkeys)):
466 signing_key = self._server.keys[current_key_index]
465 if msg.public_key_version in range(1, nkeys + 1): 467 if msg.public_key_version in range(1, nkeys + 1):
466 # requested key exists, use for signing and rotate. 468 # requested key exists, use for signing and rotate.
467 req_key = self._server.keys[msg.public_key_version - 1]['private_key'] 469 req_key = self._server.keys[msg.public_key_version - 1]['private_key']
468 key_version = (msg.public_key_version % nkeys) + 1
469 signing_key = self._server.keys[key_version - 1]
470 470
471 # Fill the policy data protobuf. 471 # Fill the policy data protobuf.
472 policy_data = dm.PolicyData() 472 policy_data = dm.PolicyData()
473 policy_data.policy_type = msg.policy_type 473 policy_data.policy_type = msg.policy_type
474 policy_data.timestamp = int(time.time() * 1000) 474 policy_data.timestamp = int(time.time() * 1000)
475 policy_data.request_token = token_info['device_token'] 475 policy_data.request_token = token_info['device_token']
476 policy_data.policy_value = settings.SerializeToString() 476 policy_data.policy_value = settings.SerializeToString()
477 policy_data.machine_name = token_info['machine_name'] 477 policy_data.machine_name = token_info['machine_name']
478 policy_data.valid_serial_number_missing = ( 478 policy_data.valid_serial_number_missing = (
479 token_info['machine_id'] in BAD_MACHINE_IDS) 479 token_info['machine_id'] in BAD_MACHINE_IDS)
480 policy_data.settings_entity_id = msg.settings_entity_id 480 policy_data.settings_entity_id = msg.settings_entity_id
481 481
482 if signing_key: 482 if signing_key:
483 policy_data.public_key_version = key_version 483 policy_data.public_key_version = current_key_index + 1
484 if msg.policy_type == 'google/chromeos/publicaccount': 484 if msg.policy_type == 'google/chromeos/publicaccount':
485 policy_data.username = msg.settings_entity_id 485 policy_data.username = msg.settings_entity_id
486 else: 486 else:
487 # For regular user/device policy, there is no way for the testserver to 487 # For regular user/device policy, there is no way for the testserver to
488 # know the user name belonging to the GAIA auth token we received (short 488 # know the user name belonging to the GAIA auth token we received (short
489 # of actually talking to GAIA). To address this, we read the username from 489 # of actually talking to GAIA). To address this, we read the username from
490 # the policy configuration dictionary, or use a default. 490 # the policy configuration dictionary, or use a default.
491 policy_data.username = policy.get('policy_user', 'user@example.com') 491 policy_data.username = policy.get('policy_user', 'user@example.com')
492 policy_data.device_id = token_info['device_id'] 492 policy_data.device_id = token_info['device_id']
493 signed_data = policy_data.SerializeToString() 493 signed_data = policy_data.SerializeToString()
494 494
495 response = dm.DeviceManagementResponse() 495 response = dm.DeviceManagementResponse()
496 fetch_response = response.policy_response.response.add() 496 fetch_response = response.policy_response.response.add()
497 fetch_response.policy_data = signed_data 497 fetch_response.policy_data = signed_data
498 if signing_key: 498 if signing_key:
499 fetch_response.policy_data_signature = ( 499 fetch_response.policy_data_signature = (
500 signing_key['private_key'].hashAndSign(signed_data).tostring()) 500 signing_key['private_key'].hashAndSign(signed_data).tostring())
501 if msg.public_key_version != key_version: 501 if msg.public_key_version != current_key_index + 1:
502 fetch_response.new_public_key = signing_key['public_key'] 502 fetch_response.new_public_key = signing_key['public_key']
503 if req_key: 503 if req_key:
504 fetch_response.new_public_key_signature = ( 504 fetch_response.new_public_key_signature = (
505 req_key.hashAndSign(fetch_response.new_public_key).tostring()) 505 req_key.hashAndSign(fetch_response.new_public_key).tostring())
506 506
507 self.DumpMessage('Response', response) 507 self.DumpMessage('Response', response)
508 508
509 return (200, response.SerializeToString()) 509 return (200, response.SerializeToString())
510 510
511 def CheckToken(self): 511 def CheckToken(self):
(...skipping 30 matching lines...) Expand all
542 542
543 return (None, (error, 'Server error %d' % error)) 543 return (None, (error, 'Server error %d' % error))
544 544
545 def DumpMessage(self, label, msg): 545 def DumpMessage(self, label, msg):
546 """Helper for logging an ASCII dump of a protobuf message.""" 546 """Helper for logging an ASCII dump of a protobuf message."""
547 logging.debug('%s\n%s' % (label, str(msg))) 547 logging.debug('%s\n%s' % (label, str(msg)))
548 548
549 class TestServer(object): 549 class TestServer(object):
550 """Handles requests and keeps global service state.""" 550 """Handles requests and keeps global service state."""
551 551
552 def __init__(self, policy_path, private_key_paths): 552 def __init__(self, policy_path):
553 """Initializes the server. 553 """Initializes the server.
554 554
555 Args: 555 Args:
556 policy_path: Names the file to read JSON-formatted policy from. 556 policy_path: Names the file to read JSON-formatted policy from.
557 private_key_paths: List of paths to read private keys from.
558 """ 557 """
559 self._registered_tokens = {} 558 self._registered_tokens = {}
560 self.policy_path = policy_path 559 self.policy_path = policy_path
561 560
561 # Generate 2 private keys.
562 self.keys = [] 562 self.keys = []
563 if private_key_paths: 563 for i in range(2):
564 # Load specified keys from the filesystem. 564 key = tlslite.api.generateRSAKey(512)
Mattias Nissler (ping if slow) 2013/02/07 14:12:07 I'd hate to loose the ability to use keys passed o
Joao da Silva 2013/02/07 16:32:00 Reverted.
565 for key_path in private_key_paths:
566 try:
567 key = tlslite.api.parsePEMKey(open(key_path).read(), private=True)
568 except IOError:
569 print 'Failed to load private key from %s' % key_path
570 continue
571
572 assert key is not None
573 self.keys.append({ 'private_key' : key })
574 else:
575 # Generate a key if none were specified.
576 key = tlslite.api.generateRSAKey(1024)
577 assert key is not None 565 assert key is not None
578 self.keys.append({ 'private_key' : key }) 566 self.keys.append({ 'private_key' : key })
579 567
580 # Derive the public keys from the loaded private keys. 568 # Derive the public keys from the generated private keys.
581 for entry in self.keys: 569 for entry in self.keys:
582 key = entry['private_key'] 570 key = entry['private_key']
583 571
584 algorithm = asn1der.Sequence( 572 algorithm = asn1der.Sequence(
585 [ asn1der.Data(asn1der.OBJECT_IDENTIFIER, PKCS1_RSA_OID), 573 [ asn1der.Data(asn1der.OBJECT_IDENTIFIER, PKCS1_RSA_OID),
586 asn1der.Data(asn1der.NULL, '') ]) 574 asn1der.Data(asn1der.NULL, '') ])
587 rsa_pubkey = asn1der.Sequence([ asn1der.Integer(key.n), 575 rsa_pubkey = asn1der.Sequence([ asn1der.Integer(key.n),
588 asn1der.Integer(key.e) ]) 576 asn1der.Integer(key.e) ])
589 pubkey = asn1der.Sequence([ algorithm, asn1der.Bitstring(rsa_pubkey) ]) 577 pubkey = asn1der.Sequence([ algorithm, asn1der.Bitstring(rsa_pubkey) ])
590 entry['public_key'] = pubkey; 578 entry['public_key'] = pubkey;
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
676 return self._registered_tokens.get(dmtoken, None) 664 return self._registered_tokens.get(dmtoken, None)
677 665
678 def UnregisterDevice(self, dmtoken): 666 def UnregisterDevice(self, dmtoken):
679 """Unregisters a device identified by the given DM token. 667 """Unregisters a device identified by the given DM token.
680 668
681 Args: 669 Args:
682 dmtoken: The device management token provided by the client. 670 dmtoken: The device management token provided by the client.
683 """ 671 """
684 if dmtoken in self._registered_tokens.keys(): 672 if dmtoken in self._registered_tokens.keys():
685 del self._registered_tokens[dmtoken] 673 del self._registered_tokens[dmtoken]
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698