| OLD | NEW |
| 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 Loading... |
| 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 | |
| 50 } | 49 } |
| 51 | 50 |
| 52 """ | 51 """ |
| 53 | 52 |
| 54 import cgi | 53 import cgi |
| 55 import hashlib | 54 import hashlib |
| 56 import logging | 55 import logging |
| 57 import os | 56 import os |
| 58 import random | 57 import random |
| 59 import re | 58 import re |
| (...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 449 if msg.policy_type in token_info['allowed_policy_types']: | 448 if msg.policy_type in token_info['allowed_policy_types']: |
| 450 if (msg.policy_type == 'google/chromeos/user' or | 449 if (msg.policy_type == 'google/chromeos/user' or |
| 451 msg.policy_type == 'google/chrome/user' or | 450 msg.policy_type == 'google/chrome/user' or |
| 452 msg.policy_type == 'google/chromeos/publicaccount'): | 451 msg.policy_type == 'google/chromeos/publicaccount'): |
| 453 settings = cp.CloudPolicySettings() | 452 settings = cp.CloudPolicySettings() |
| 454 self.GatherUserPolicySettings(settings, policy.get(policy_key, {})) | 453 self.GatherUserPolicySettings(settings, policy.get(policy_key, {})) |
| 455 elif msg.policy_type == 'google/chromeos/device': | 454 elif msg.policy_type == 'google/chromeos/device': |
| 456 settings = dp.ChromeDeviceSettingsProto() | 455 settings = dp.ChromeDeviceSettingsProto() |
| 457 self.GatherDevicePolicySettings(settings, policy.get(policy_key, {})) | 456 self.GatherDevicePolicySettings(settings, policy.get(policy_key, {})) |
| 458 | 457 |
| 459 # Sign with 'current_key_index', defaulting to key 0. | 458 # Figure out the key we want to use. If multiple keys are configured, the |
| 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 current_key_index = policy.get('current_key_index', 0) | 462 key_version = 1 |
| 463 nkeys = len(self._server.keys) | 463 nkeys = len(self._server.keys) |
| 464 if (msg.signature_type == dm.PolicyFetchRequest.SHA1_RSA and | 464 if msg.signature_type == dm.PolicyFetchRequest.SHA1_RSA and nkeys > 0: |
| 465 current_key_index in range(nkeys)): | |
| 466 signing_key = self._server.keys[current_key_index] | |
| 467 if msg.public_key_version in range(1, nkeys + 1): | 465 if msg.public_key_version in range(1, nkeys + 1): |
| 468 # requested key exists, use for signing and rotate. | 466 # requested key exists, use for signing and rotate. |
| 469 req_key = self._server.keys[msg.public_key_version - 1]['private_key'] | 467 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 = current_key_index + 1 | 483 policy_data.public_key_version = key_version |
| 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 != current_key_index + 1: | 501 if msg.public_key_version != key_version: |
| 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 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 565 for key_path in private_key_paths: | 565 for key_path in private_key_paths: |
| 566 try: | 566 try: |
| 567 key = tlslite.api.parsePEMKey(open(key_path).read(), private=True) | 567 key = tlslite.api.parsePEMKey(open(key_path).read(), private=True) |
| 568 except IOError: | 568 except IOError: |
| 569 print 'Failed to load private key from %s' % key_path | 569 print 'Failed to load private key from %s' % key_path |
| 570 continue | 570 continue |
| 571 | 571 |
| 572 assert key is not None | 572 assert key is not None |
| 573 self.keys.append({ 'private_key' : key }) | 573 self.keys.append({ 'private_key' : key }) |
| 574 else: | 574 else: |
| 575 # Generate 2 private keys if none were passed from the command line. | 575 # Generate a key if none were specified. |
| 576 for i in range(2): | 576 key = tlslite.api.generateRSAKey(1024) |
| 577 key = tlslite.api.generateRSAKey(512) | 577 assert key is not None |
| 578 assert key is not None | 578 self.keys.append({ 'private_key' : key }) |
| 579 self.keys.append({ 'private_key' : key }) | |
| 580 | 579 |
| 581 # Derive the public keys from the private keys. | 580 # Derive the public keys from the loaded private keys. |
| 582 for entry in self.keys: | 581 for entry in self.keys: |
| 583 key = entry['private_key'] | 582 key = entry['private_key'] |
| 584 | 583 |
| 585 algorithm = asn1der.Sequence( | 584 algorithm = asn1der.Sequence( |
| 586 [ asn1der.Data(asn1der.OBJECT_IDENTIFIER, PKCS1_RSA_OID), | 585 [ asn1der.Data(asn1der.OBJECT_IDENTIFIER, PKCS1_RSA_OID), |
| 587 asn1der.Data(asn1der.NULL, '') ]) | 586 asn1der.Data(asn1der.NULL, '') ]) |
| 588 rsa_pubkey = asn1der.Sequence([ asn1der.Integer(key.n), | 587 rsa_pubkey = asn1der.Sequence([ asn1der.Integer(key.n), |
| 589 asn1der.Integer(key.e) ]) | 588 asn1der.Integer(key.e) ]) |
| 590 pubkey = asn1der.Sequence([ algorithm, asn1der.Bitstring(rsa_pubkey) ]) | 589 pubkey = asn1der.Sequence([ algorithm, asn1der.Bitstring(rsa_pubkey) ]) |
| 591 entry['public_key'] = pubkey; | 590 entry['public_key'] = pubkey; |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 677 return self._registered_tokens.get(dmtoken, None) | 676 return self._registered_tokens.get(dmtoken, None) |
| 678 | 677 |
| 679 def UnregisterDevice(self, dmtoken): | 678 def UnregisterDevice(self, dmtoken): |
| 680 """Unregisters a device identified by the given DM token. | 679 """Unregisters a device identified by the given DM token. |
| 681 | 680 |
| 682 Args: | 681 Args: |
| 683 dmtoken: The device management token provided by the client. | 682 dmtoken: The device management token provided by the client. |
| 684 """ | 683 """ |
| 685 if dmtoken in self._registered_tokens.keys(): | 684 if dmtoken in self._registered_tokens.keys(): |
| 686 del self._registered_tokens[dmtoken] | 685 del self._registered_tokens[dmtoken] |
| OLD | NEW |