Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2011 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 26 matching lines...) Expand all Loading... | |
| 37 } | 37 } |
| 38 }, | 38 }, |
| 39 "managed_users" : [ | 39 "managed_users" : [ |
| 40 "secret123456" | 40 "secret123456" |
| 41 ] | 41 ] |
| 42 } | 42 } |
| 43 | 43 |
| 44 """ | 44 """ |
| 45 | 45 |
| 46 import cgi | 46 import cgi |
| 47 import hashlib | |
| 47 import logging | 48 import logging |
| 48 import os | 49 import os |
| 49 import random | 50 import random |
| 50 import re | 51 import re |
| 51 import sys | 52 import sys |
| 52 import time | 53 import time |
| 53 import tlslite | 54 import tlslite |
| 54 import tlslite.api | 55 import tlslite.api |
| 55 import tlslite.utils | 56 import tlslite.utils |
| 56 | 57 |
| 57 # The name and availability of the json module varies in python versions. | 58 # The name and availability of the json module varies in python versions. |
| 58 try: | 59 try: |
| 59 import simplejson as json | 60 import simplejson as json |
| 60 except ImportError: | 61 except ImportError: |
| 61 try: | 62 try: |
| 62 import json | 63 import json |
| 63 except ImportError: | 64 except ImportError: |
| 64 json = None | 65 json = None |
| 65 | 66 |
| 66 import asn1der | 67 import asn1der |
| 67 import device_management_backend_pb2 as dm | 68 import device_management_backend_pb2 as dm |
| 68 import cloud_policy_pb2 as cp | 69 import cloud_policy_pb2 as cp |
| 69 import chrome_device_policy_pb2 as dp | 70 import chrome_device_policy_pb2 as dp |
| 70 | 71 |
| 71 # ASN.1 object identifier for PKCS#1/RSA. | 72 # ASN.1 object identifier for PKCS#1/RSA. |
| 72 PKCS1_RSA_OID = '\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01' | 73 PKCS1_RSA_OID = '\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01' |
| 73 | 74 |
| 75 # SHA256 sum of "0". | |
| 76 SHA256_0 = hashlib.sha256('0').digest() | |
|
pastarmovj
2011/12/01 09:30:04
If you only use haslib for this call why don't you
Joao da Silva
2011/12/01 09:42:07
I prefer this format since it's less magical, and
pastarmovj
2011/12/01 09:49:03
Ok I am fine with that.
| |
| 77 | |
| 74 class RequestHandler(object): | 78 class RequestHandler(object): |
| 75 """Decodes and handles device management requests from clients. | 79 """Decodes and handles device management requests from clients. |
| 76 | 80 |
| 77 The handler implements all the request parsing and protobuf message decoding | 81 The handler implements all the request parsing and protobuf message decoding |
| 78 and encoding. It calls back into the server to lookup, register, and | 82 and encoding. It calls back into the server to lookup, register, and |
| 79 unregister clients. | 83 unregister clients. |
| 80 """ | 84 """ |
| 81 | 85 |
| 82 def __init__(self, server, path, headers, request): | 86 def __init__(self, server, path, headers, request): |
| 83 """Initialize the handler. | 87 """Initialize the handler. |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 137 (request_type != 'ping' and | 141 (request_type != 'ping' and |
| 138 len(self.GetUniqueParam('deviceid')) >= 64) or | 142 len(self.GetUniqueParam('deviceid')) >= 64) or |
| 139 len(self.GetUniqueParam('agent')) >= 64): | 143 len(self.GetUniqueParam('agent')) >= 64): |
| 140 return (400, 'Invalid request parameter') | 144 return (400, 'Invalid request parameter') |
| 141 if request_type == 'register': | 145 if request_type == 'register': |
| 142 return self.ProcessRegister(rmsg.register_request) | 146 return self.ProcessRegister(rmsg.register_request) |
| 143 elif request_type == 'unregister': | 147 elif request_type == 'unregister': |
| 144 return self.ProcessUnregister(rmsg.unregister_request) | 148 return self.ProcessUnregister(rmsg.unregister_request) |
| 145 elif request_type == 'policy' or request_type == 'ping': | 149 elif request_type == 'policy' or request_type == 'ping': |
| 146 return self.ProcessPolicy(rmsg.policy_request, request_type) | 150 return self.ProcessPolicy(rmsg.policy_request, request_type) |
| 151 elif request_type == 'enterprise_check': | |
| 152 return self.ProcessAutoEnrollment(rmsg.auto_enrollment_request) | |
| 147 else: | 153 else: |
| 148 return (400, 'Invalid request parameter') | 154 return (400, 'Invalid request parameter') |
| 149 | 155 |
| 150 def CheckGoogleLogin(self): | 156 def CheckGoogleLogin(self): |
| 151 """Extracts the auth token from the request and returns it. The token may | 157 """Extracts the auth token from the request and returns it. The token may |
| 152 either be a GoogleLogin token from an Authorization header, or an OAuth V2 | 158 either be a GoogleLogin token from an Authorization header, or an OAuth V2 |
| 153 token from the oauth_token query parameter. Returns None if no token is | 159 token from the oauth_token query parameter. Returns None if no token is |
| 154 present. | 160 present. |
| 155 """ | 161 """ |
| 156 oauth_token = self.GetUniqueParam('oauth_token') | 162 oauth_token = self.GetUniqueParam('oauth_token') |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 247 for request in msg.request: | 253 for request in msg.request: |
| 248 if (request.policy_type in | 254 if (request.policy_type in |
| 249 ('google/chromeos/user', 'google/chromeos/device')): | 255 ('google/chromeos/user', 'google/chromeos/device')): |
| 250 if request_type != 'policy': | 256 if request_type != 'policy': |
| 251 return (400, 'Invalid request type') | 257 return (400, 'Invalid request type') |
| 252 else: | 258 else: |
| 253 return self.ProcessCloudPolicy(request) | 259 return self.ProcessCloudPolicy(request) |
| 254 else: | 260 else: |
| 255 return (400, 'Invalid policy_type') | 261 return (400, 'Invalid policy_type') |
| 256 | 262 |
| 263 def ProcessAutoEnrollment(self, msg): | |
| 264 """Handles an auto-enrollment check request. | |
| 265 | |
| 266 The reply depends on the value of the modulus: | |
| 267 1: replies with no new modulus and the sha256 hash of "0" | |
| 268 2: replies with a new modulus, 4. | |
| 269 4: replies with a new modulus, 2. | |
| 270 8: fails with error 400. | |
| 271 anything else: replies with no new modulus and an empty list of hashes | |
| 272 | |
| 273 These allow the client to pick the testing scenario its wants to simulate. | |
| 274 | |
| 275 Args: | |
| 276 msg: The DeviceAutoEnrollmentRequest message received from the client. | |
| 277 | |
| 278 Returns: | |
| 279 A tuple of HTTP status code and response data to send to the client. | |
| 280 """ | |
| 281 auto_enrollment_response = dm.DeviceAutoEnrollmentResponse() | |
| 282 | |
| 283 if msg.modulus == 1: | |
| 284 auto_enrollment_response.hashes.append(SHA256_0) | |
| 285 elif msg.modulus == 2: | |
| 286 auto_enrollment_response.modulus = 4 | |
| 287 elif msg.modulus == 4: | |
| 288 auto_enrollment_response.modulus = 2 | |
| 289 elif msg.modulus == 8: | |
| 290 return (400, 'Server error') | |
| 291 | |
| 292 response = dm.DeviceManagementResponse() | |
| 293 response.auto_enrollment_response.CopyFrom(auto_enrollment_response) | |
| 294 return (200, response.SerializeToString()) | |
| 295 | |
| 257 def SetProtobufMessageField(self, group_message, field, field_value): | 296 def SetProtobufMessageField(self, group_message, field, field_value): |
| 258 '''Sets a field in a protobuf message. | 297 '''Sets a field in a protobuf message. |
| 259 | 298 |
| 260 Args: | 299 Args: |
| 261 group_message: The protobuf message. | 300 group_message: The protobuf message. |
| 262 field: The field of the message to set, it should be a member of | 301 field: The field of the message to set, it should be a member of |
| 263 group_message.DESCRIPTOR.fields. | 302 group_message.DESCRIPTOR.fields. |
| 264 field_value: The value to set. | 303 field_value: The value to set. |
| 265 ''' | 304 ''' |
| 266 if field.label == field.LABEL_REPEATED: | 305 if field.label == field.LABEL_REPEATED: |
| (...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 572 return self._registered_tokens.get(dmtoken, None) | 611 return self._registered_tokens.get(dmtoken, None) |
| 573 | 612 |
| 574 def UnregisterDevice(self, dmtoken): | 613 def UnregisterDevice(self, dmtoken): |
| 575 """Unregisters a device identified by the given DM token. | 614 """Unregisters a device identified by the given DM token. |
| 576 | 615 |
| 577 Args: | 616 Args: |
| 578 dmtoken: The device management token provided by the client. | 617 dmtoken: The device management token provided by the client. |
| 579 """ | 618 """ |
| 580 if dmtoken in self._registered_tokens.keys(): | 619 if dmtoken in self._registered_tokens.keys(): |
| 581 del self._registered_tokens[dmtoken] | 620 del self._registered_tokens[dmtoken] |
| OLD | NEW |