def _validate_policy(self, retrieved_policy, username):
        import chrome_device_policy_pb2
        import device_management_backend_pb2

        response_proto = device_management_backend_pb2.PolicyFetchResponse()
        response_proto.ParseFromString(retrieved_policy)
        ownership.assert_has_policy_data(response_proto)

        poldata = device_management_backend_pb2.PolicyData()
        poldata.ParseFromString(response_proto.policy_data)
        ownership.assert_has_device_settings(poldata)
        ownership.assert_username(poldata, username)

        polval = chrome_device_policy_pb2.ChromeDeviceSettingsProto()
        polval.ParseFromString(poldata.policy_value)
        ownership.assert_new_users(polval, True)
        ownership.assert_users_on_whitelist(polval, (username,))
Beispiel #2
0
    def _GenerateDevicePolicyBlob(self, device_policy=None, owner=None):
        """Generates a signed device policy blob."""

        # Fill in the device settings protobuf.
        device_policy = device_policy or {}
        owner = owner or constants.CREDENTIALS['$mockowner'][0]
        settings = dp.ChromeDeviceSettingsProto()
        for group in settings.DESCRIPTOR.fields:
            # Create protobuf message for group.
            group_message = eval('dp.' + group.message_type.name + '()')
            # Indicates if at least one field was set in |group_message|.
            got_fields = False
            # Iterate over fields of the message and feed them from the policy dict.
            for field in group_message.DESCRIPTOR.fields:
                field_value = None
                if field.name in device_policy:
                    got_fields = True
                    field_value = device_policy[field.name]
                    self._SetProtobufMessageField(group_message, field,
                                                  field_value)
            if got_fields:
                settings.__getattribute__(group.name).CopyFrom(group_message)

        # Fill in the policy data protobuf.
        policy_data = dm.PolicyData()
        policy_data.policy_type = 'google/chromeos/device'
        policy_data.policy_value = settings.SerializeToString()
        policy_data.username = owner
        serialized_policy_data = policy_data.SerializeToString()

        # Fill in the device management response protobuf.
        response = dm.DeviceManagementResponse()
        fetch_response = response.policy_response.response.add()
        fetch_response.policy_data = serialized_policy_data
        fetch_response.policy_data_signature = (
            self._private_key.hashAndSign(serialized_policy_data).tostring())

        self._device_policy_blob = fetch_response.SerializeToString()
Beispiel #3
0
def compare_policy_response(policy_response, owner=None, guests=None,
                            new_users=None, roaming=None, whitelist=None):
    """Check the contents of |policy_response| against given args.

    Deserializes |policy_response| into a PolicyFetchResponse protobuf,
    with an embedded (serialized) PolicyData protobuf that embeds a
    (serialized) ChromeDeviceSettingsProto, and checks to see if this
    protobuf turducken contains the information passed in.

    @param policy_response: string serialization of a PolicyData protobuf.
    @param owner: string representing the owner's name/account.
    @param guests: boolean indicating whether guests should be allowed.
    @param new_users: boolean indicating if user pods are on login screen.
    @param roaming: boolean indicating whether data roaming is enabled.
    @param whitelist: list of accounts that are allowed to log in.

    @return True if |policy_response| has all the provided data, else False.
    """
    import chrome_device_policy_pb2
    import device_management_backend_pb2

    response_proto = device_management_backend_pb2.PolicyFetchResponse()
    response_proto.ParseFromString(policy_response)
    ownership.assert_has_policy_data(response_proto)

    data_proto = device_management_backend_pb2.PolicyData()
    data_proto.ParseFromString(response_proto.policy_data)
    ownership.assert_has_device_settings(data_proto)
    if owner: ownership.assert_username(data_proto, owner)

    settings = chrome_device_policy_pb2.ChromeDeviceSettingsProto()
    settings.ParseFromString(data_proto.policy_value)
    if guests: ownership.assert_guest_setting(settings, guests)
    if new_users: ownership.assert_show_users(settings, new_users)
    if roaming: ownership.assert_roaming(settings, roaming)
    if whitelist:
        ownership.assert_new_users(settings, False)
        ownership.assert_users_on_whitelist(settings, whitelist)
    def ProcessInitialPolicy(self, msg):
        """Handles a 'preregister policy' request.

    Queries the list of managed users and responds the client if their user
    is managed or not.

    Args:
      msg: The PolicyFetchRequest message received from the client.

    Returns:
      A tuple of HTTP status code and response data to send to the client.
    """
        # Check the GAIA token.
        auth = self.CheckGoogleLogin()
        if not auth:
            return (403, 'No authorization')

        chrome_initial_settings = dm.ChromeInitialSettingsProto()
        if ('*' in self._server.policy['managed_users']
                or auth in self._server.policy['managed_users']):
            chrome_initial_settings.enrollment_provision = (
                dm.ChromeInitialSettingsProto.MANAGED)
        else:
            chrome_initial_settings.enrollment_provision = (
                dm.ChromeInitialSettingsProto.UNMANAGED)

        policy_data = dm.PolicyData()
        policy_data.policy_type = msg.policy_type
        policy_data.policy_value = chrome_initial_settings.SerializeToString()

        # Prepare and send the response.
        response = dm.DeviceManagementResponse()
        fetch_response = response.policy_response.response.add()
        fetch_response.policy_data = (policy_data.SerializeToString())

        self.DumpMessage('Response', response)

        return (200, response.SerializeToString())
Beispiel #5
0
def build_policy_data(owner=None, guests=None, new_users=None, roaming=None,
                      whitelist=None):
    """Generate and serialize a populated device policy protobuffer.

    Creates a PolicyData protobuf, with an embedded
    ChromeDeviceSettingsProto, containing the information passed in.

    @param owner: string representing the owner's name/account.
    @param guests: boolean indicating whether guests should be allowed.
    @param new_users: boolean indicating if user pods are on login screen.
    @param roaming: boolean indicating whether data roaming is enabled.
    @param whitelist: list of accounts that are allowed to log in.

    @return serialization of the PolicyData proto that we build.
    """
    import chrome_device_policy_pb2
    import device_management_backend_pb2

    data_proto = device_management_backend_pb2.PolicyData()
    data_proto.policy_type = ownership.POLICY_TYPE
    if owner: data_proto.username = owner

    settings = chrome_device_policy_pb2.ChromeDeviceSettingsProto()
    if guests:
        settings.guest_mode_enabled.guest_mode_enabled = guests
    if new_users:
        settings.show_user_names.show_user_names = new_users
    if roaming:
        settings.data_roaming_enabled.data_roaming_enabled = roaming
    if whitelist:
        settings.allow_new_users.allow_new_users = False
        for user in whitelist:
            settings.user_whitelist.user_whitelist.append(user)

    data_proto.policy_value = settings.SerializeToString()
    return data_proto.SerializeToString()
    def ProcessCloudPolicy(self, msg, token_info, response):
        """Handles a cloud policy request. (New protocol for policy requests.)

    Encodes the policy into protobuf representation, signs it and constructs
    the response.

    Args:
      msg: The CloudPolicyRequest message received from the client.
      token_info: the token extracted from the request.
      response: A PolicyFetchResponse message that should be filled with the
                response data.
    """

        if msg.machine_id:
            self.server.UpdateMachineId(token_info['device_token'],
                                        msg.machine_id)

        # Response is only given if the scope is specified in the config file.
        # Normally 'google/chromeos/device', 'google/chromeos/user' and
        # 'google/chromeos/publicaccount' should be accepted.
        policy = self.server.GetPolicies()
        policy_value = ''
        policy_key = msg.policy_type
        if msg.settings_entity_id:
            policy_key += '/' + msg.settings_entity_id
        if msg.policy_type in token_info['allowed_policy_types']:
            if (msg.policy_type == 'google/chromeos/user'
                    or msg.policy_type == 'google/chrome/user'
                    or msg.policy_type == 'google/chromeos/publicaccount'):
                settings = cp.CloudPolicySettings()
                payload = self.server.ReadPolicyFromDataDir(
                    policy_key, settings)
                if payload is None:
                    self.GatherUserPolicySettings(settings,
                                                  policy.get(policy_key, {}))
                    payload = settings.SerializeToString()
            elif dp is not None and msg.policy_type == 'google/chromeos/device':
                settings = dp.ChromeDeviceSettingsProto()
                payload = self.server.ReadPolicyFromDataDir(
                    policy_key, settings)
                if payload is None:
                    self.GatherDevicePolicySettings(settings,
                                                    policy.get(policy_key, {}))
                    payload = settings.SerializeToString()
            elif msg.policy_type == 'google/chrome/extension':
                settings = ep.ExternalPolicyData()
                payload = self.server.ReadPolicyFromDataDir(
                    policy_key, settings)
                if payload is None:
                    payload = self.CreatePolicyForExternalPolicyData(
                        policy_key)
            else:
                response.error_code = 400
                response.error_message = 'Invalid policy type'
                return
        else:
            response.error_code = 400
            response.error_message = 'Request not allowed for the token used'
            return

        # Sign with 'current_key_index', defaulting to key 0.
        signing_key = None
        req_key = None
        current_key_index = policy.get('current_key_index', 0)
        nkeys = len(self.server.keys)
        if (msg.signature_type == dm.PolicyFetchRequest.SHA1_RSA
                and current_key_index in range(nkeys)):
            signing_key = self.server.keys[current_key_index]
            if msg.public_key_version in range(1, nkeys + 1):
                # requested key exists, use for signing and rotate.
                req_key = self.server.keys[msg.public_key_version -
                                           1]['private_key']

        # Fill the policy data protobuf.
        policy_data = dm.PolicyData()
        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 = payload
        policy_data.machine_name = token_info['machine_name']
        policy_data.valid_serial_number_missing = (token_info['machine_id']
                                                   in BAD_MACHINE_IDS)
        policy_data.settings_entity_id = msg.settings_entity_id
        policy_data.service_account_identity = policy.get(
            'service_account_identity',
            'policy_testserver.py-service_account_identity')
        invalidation_source = policy.get('invalidation_source')
        if invalidation_source is not None:
            policy_data.invalidation_source = invalidation_source
        # Since invalidation_name is type bytes in the proto, the Unicode name
        # provided needs to be encoded as ASCII to set the correct byte pattern.
        invalidation_name = policy.get('invalidation_name')
        if invalidation_name is not None:
            policy_data.invalidation_name = invalidation_name.encode('ascii')

        if signing_key:
            policy_data.public_key_version = current_key_index + 1
        if msg.policy_type == 'google/chromeos/publicaccount':
            policy_data.username = msg.settings_entity_id
        else:
            # For regular user/device policy, there is no way 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 read the username from
            # the policy configuration dictionary, or use a default.
            policy_data.username = policy.get('policy_user',
                                              '*****@*****.**')
        policy_data.device_id = token_info['device_id']
        signed_data = policy_data.SerializeToString()

        response.policy_data = signed_data
        if signing_key:
            response.policy_data_signature = (
                signing_key['private_key'].hashAndSign(signed_data).tostring())
            if msg.public_key_version != current_key_index + 1:
                response.new_public_key = signing_key['public_key']
                if req_key:
                    response.new_public_key_signature = (req_key.hashAndSign(
                        response.new_public_key).tostring())

        self.DumpMessage('Response', response)

        return (200, response.SerializeToString())
Beispiel #7
0
  def ProcessCloudPolicy(self, msg):
    """Handles a cloud policy request. (New protocol for policy requests.)

    Checks for authorization, encodes the policy into protobuf representation,
    signs it and constructs the repsonse.

    Args:
      msg: The CloudPolicyRequest message received from the client.

    Returns:
      A tuple of HTTP status code and response data to send to the client.
    """

    token_info, error = self.CheckToken()
    if not token_info:
      return error

    if msg.machine_id:
      self.server.UpdateMachineId(token_info['device_token'], msg.machine_id)

    # Response is only given if the scope is specified in the config file.
    # Normally 'google/chromeos/device', 'google/chromeos/user' and
    # 'google/chromeos/publicaccount' should be accepted.
    policy = self.server.GetPolicies()
    policy_value = ''
    policy_key = msg.policy_type
    if msg.settings_entity_id:
      policy_key += '/' + msg.settings_entity_id
    if msg.policy_type in token_info['allowed_policy_types']:
      if (msg.policy_type == 'google/chromeos/user' or
          msg.policy_type == 'google/chrome/user' or
          msg.policy_type == 'google/chromeos/publicaccount'):
        settings = cp.CloudPolicySettings()
        payload = self.server.ReadPolicyFromDataDir(policy_key, settings)
        if payload is None:
          self.GatherUserPolicySettings(settings, policy.get(policy_key, {}))
          payload = settings.SerializeToString()
      elif msg.policy_type == 'google/chromeos/device':
        settings = dp.ChromeDeviceSettingsProto()
        payload = self.server.ReadPolicyFromDataDir(policy_key, settings)
        if payload is None:
          self.GatherDevicePolicySettings(settings, policy.get(policy_key, {}))
          payload = settings.SerializeToString()

    # Sign with 'current_key_index', defaulting to key 0.
    signing_key = None
    req_key = None
    current_key_index = policy.get('current_key_index', 0)
    nkeys = len(self.server.keys)
    if (msg.signature_type == dm.PolicyFetchRequest.SHA1_RSA and
        current_key_index in range(nkeys)):
      signing_key = self.server.keys[current_key_index]
      if msg.public_key_version in range(1, nkeys + 1):
        # requested key exists, use for signing and rotate.
        req_key = self.server.keys[msg.public_key_version - 1]['private_key']

    # Fill the policy data protobuf.
    policy_data = dm.PolicyData()
    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 = payload
    policy_data.machine_name = token_info['machine_name']
    policy_data.valid_serial_number_missing = (
        token_info['machine_id'] in BAD_MACHINE_IDS)
    policy_data.settings_entity_id = msg.settings_entity_id

    if signing_key:
      policy_data.public_key_version = current_key_index + 1
    if msg.policy_type == 'google/chromeos/publicaccount':
      policy_data.username = msg.settings_entity_id
    else:
      # For regular user/device policy, there is no way 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 read the username from
      # the policy configuration dictionary, or use a default.
      policy_data.username = policy.get('policy_user', '*****@*****.**')
    policy_data.device_id = token_info['device_id']
    signed_data = policy_data.SerializeToString()

    response = dm.DeviceManagementResponse()
    fetch_response = response.policy_response.response.add()
    fetch_response.policy_data = signed_data
    if signing_key:
      fetch_response.policy_data_signature = (
          signing_key['private_key'].hashAndSign(signed_data).tostring())
      if msg.public_key_version != current_key_index + 1:
        fetch_response.new_public_key = signing_key['public_key']
        if req_key:
          fetch_response.new_public_key_signature = (
              req_key.hashAndSign(fetch_response.new_public_key).tostring())

    self.DumpMessage('Response', response)

    return (200, response.SerializeToString())
Beispiel #8
0
  def ProcessCloudPolicy(self, msg):
    """Handles a cloud policy request. (New protocol for policy requests.)

    Checks for authorization, encodes the policy into protobuf representation,
    signs it and constructs the repsonse.

    Args:
      msg: The CloudPolicyRequest message received from the client.

    Returns:
      A tuple of HTTP status code and response data to send to the client.
    """

    token_info, error = self.CheckToken()
    if not token_info:
      return error

    if msg.machine_id:
      self._server.UpdateMachineId(token_info['device_token'], msg.machine_id)

    # Response is only given if the scope is specified in the config file.
    # Normally 'google/chromeos/device' and 'google/chromeos/user' should be
    # accepted.
    policy = self._server.GetPolicies()
    policy_value = ''
    if (msg.policy_type in token_info['allowed_policy_types'] and
        msg.policy_type in policy):
      if msg.policy_type == 'google/chromeos/user':
        settings = cp.CloudPolicySettings()
        self.GatherUserPolicySettings(settings,
                                      policy[msg.policy_type])
        policy_value = settings.SerializeToString()
      elif msg.policy_type == 'google/chromeos/device':
        settings = dp.ChromeDeviceSettingsProto()
        self.GatherDevicePolicySettings(settings,
                                        policy[msg.policy_type])
        policy_value = settings.SerializeToString()

    # Figure out the key we want to use. If multiple keys are configured, the
    # server will rotate through them in a round-robin fashion.
    signing_key = None
    req_key = None
    key_version = 1
    nkeys = len(self._server.keys)
    if msg.signature_type == dm.PolicyFetchRequest.SHA1_RSA and nkeys > 0:
      if msg.public_key_version in range(1, nkeys + 1):
        # requested key exists, use for signing and rotate.
        req_key = self._server.keys[msg.public_key_version - 1]['private_key']
        key_version = (msg.public_key_version % nkeys) + 1
      signing_key = self._server.keys[key_version - 1]

    # Fill the policy data protobuf.
    policy_data = dm.PolicyData()
    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 = policy_value
    policy_data.machine_name = token_info['machine_name']
    policy_data.valid_serial_number_missing = (
        token_info['machine_id'] in BAD_MACHINE_IDS)

    if signing_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()
    fetch_response = response.policy_response.response.add()
    fetch_response.policy_data = signed_data
    if signing_key:
      fetch_response.policy_data_signature = (
          signing_key['private_key'].hashAndSign(signed_data).tostring())
      if msg.public_key_version != key_version:
        fetch_response.new_public_key = signing_key['public_key']
        if req_key:
          fetch_response.new_public_key_signature = (
              req_key.hashAndSign(fetch_response.new_public_key).tostring())

    self.DumpMessage('Response', response)

    return (200, response.SerializeToString())