def get(self):
        params = collections.defaultdict(dict)

        search_perms = base_handler.VerifyAllPermissionTypes(
            permissions.SEARCH)

        for model_type in search_perms:
            if not search_perms[model_type]:
                continue
            model = model_util.TypeNameToModel(model_type)
            if not hasattr(model, 'SEARCH_FIELDS'):
                continue
            params[model_type]['fields'] = model.SEARCH_FIELDS

        can_retrieve_own = False
        retrieve_own_perms = base_handler.VerifyAllPermissionTypes(
            permissions.RETRIEVE_OWN)
        for volume_type in retrieve_own_perms:
            if retrieve_own_perms[volume_type]:
                params[volume_type][permissions.RETRIEVE_OWN] = True
                can_retrieve_own = True

        if can_retrieve_own:
            params['user'] = base.GetCurrentUser().user.nickname()

        self.response.out.write(util.ToSafeJson(params))
    def post(self, volume_key):
        """Handles POST requests."""
        try:
            db_key = db.Key(volume_key)
        except db.BadKeyError as e:
            logging.warning('Bad volume_key "%s" provided: %s', volume_key, e)
            return self.error(httplib.NOT_FOUND)

        self.entity = self.SECRET_MODEL.get(db_key)
        if not self.entity:
            return self.error(httplib.NOT_FOUND)
        if self.entity and not self.entity.active:
            return self.error(httplib.BAD_REQUEST)

        self.VerifyXsrfToken(base_settings.CHANGE_OWNER_ACTION)
        base_handler.VerifyPermissions(permissions.CHANGE_OWNER,
                                       base.GetCurrentUser(),
                                       self.PERMISSION_TYPE)
        new_entity = self.entity.Clone()
        new_entity.owner = self.request.get('new_owner')
        new_entity.put()
        self.AUDIT_LOG_MODEL.Log(
            entity=self.entity,
            request=self.request,
            message=('Owner changed from "%s" to "%s"' %
                     (self.entity.owner, new_entity.owner)))
Example #3
0
    def VerifyPermissions(self,
                          required_permission,
                          user=None,
                          permission_type=None):
        """Verifies a valid user is logged in.

    Args:
      required_permission: permission string from permissions.*.
      user: optional, base.User entity; default current user.
      permission_type: optional, string, one of permission.TYPE_* variables. if
          omitted, self.PERMISSION_TYPE is used.
    Returns:
      base.User object of the current user.
    Raises:
      base.AccessDeniedError: there was a permissions issue.
    """
        permission_type = permission_type or self.PERMISSION_TYPE

        if user is None:
            user = base.GetCurrentUser()

        base_handler.VerifyPermissions(required_permission, user,
                                       permission_type)

        return user
Example #4
0
  def CheckRetrieveAuthorizationAndNotifyOwner(self, entity):
    """Checks whether the user is authorised to retrieve the secret.

    Args:
      entity: base.BasePassPhrase instance of retrieved object.
    Raises:
      errors.AccessDeniedError: user lacks any retrieval permissions.
      errors.AccessError: user lacks a specific retrieval permission.
    """
    user = base.GetCurrentUser()

    try:
      self.VerifyPermissions(permissions.RETRIEVE, user=user)
    except errors.AccessDeniedError:
      try:
        self.VerifyPermissions(permissions.RETRIEVE_CREATED_BY, user=user)
        if str(entity.created_by) not in str(user.user.email()):
          raise
      except errors.AccessDeniedError:
        self.VerifyPermissions(permissions.RETRIEVE_OWN, user=user)
        if user.email not in entity.owners:
          raise

    if user.email not in entity.owners:
      SendRetrievalEmail(self.PERMISSION_TYPE, entity, user)
Example #5
0
  def get(self):
    """Handles GET requests."""
    log_type = self.request.get('log_type')
    base_handler.VerifyPermissions(
        permissions.MASTER, base.GetCurrentUser(), log_type)

    start = self.request.get('start_next', None)
    log_model = models_util.TypeNameToLogModel(log_type)
    logs_query = log_model.all()
    logs_query.order('-paginate_mtime')
    if start:
      logs_query.filter('paginate_mtime <', start)

    logs = logs_query.fetch(PER_PAGE + 1)
    more = len(logs) == PER_PAGE + 1
    start_next = None
    if more:
      start_next = logs[-1].paginate_mtime

    logs = [db.to_dict(log) for log in logs[:PER_PAGE]]
    for log in logs:
      log['user'] = str(log['user'])
      log['mtime'] = str(log['mtime'])
    params = {
        'logs': logs,
        'log_type': log_type,
        'more': more,
        'start': start,
        'start_next': start_next,
    }

    self.response.out.write(util.ToSafeJson(params))
Example #6
0
    def get(self):
        params = collections.defaultdict(dict)

        search_perms = handlers.VerifyAllPermissionTypes(permissions.SEARCH)
        if search_perms[permissions.TYPE_BITLOCKER]:
            params['bitlocker'][
                'fields'] = models.BitLockerVolume.SEARCH_FIELDS
        if search_perms[permissions.TYPE_FILEVAULT]:
            params['filevault'][
                'fields'] = models.FileVaultVolume.SEARCH_FIELDS
        if search_perms[permissions.TYPE_LUKS]:
            params['luks']['fields'] = models.LuksVolume.SEARCH_FIELDS
        if search_perms[permissions.TYPE_PROVISIONING]:
            provisioning_fields = models.ProvisioningVolume.SEARCH_FIELDS
            params['provisioning']['fields'] = provisioning_fields

        can_retrieve_own = False
        retrieve_own_perms = handlers.VerifyAllPermissionTypes(
            permissions.RETRIEVE_OWN)
        for volume_type in retrieve_own_perms:
            if retrieve_own_perms[volume_type]:
                params[volume_type][permissions.RETRIEVE_OWN] = True
                can_retrieve_own = True

        if can_retrieve_own:
            params['user'] = base.GetCurrentUser().user.nickname()

        self.response.out.write(util.ToSafeJson(params))
    def get(self, serials):
        base_handler.VerifyPermissions(permissions.RETRIEVE,
                                       base.GetCurrentUser(),
                                       permissions.TYPE_APPLE_FIRMWARE)

        inventory_service = service_factory.GetInventoryService()
        res = {
            'active': [],
            'retired': [],
        }
        for serial in serials.split(','):
            if not inventory_service.IsRetiredMac(serial):
                res['active'].append(serial)
                continue

            entity = firmware.AppleFirmwarePassword.GetLatestForTarget(serial)
            if entity:
                firmware.AppleFirmwarePasswordAccessLog.Log(
                    message='GET', entity=entity, request=self.request)

                res['retired'].append({
                    'serial': serial,
                    'password': entity.password
                })
            else:
                res['retired'].append({'serial': serial, 'password': '******'})

        self.response.write(util.ToSafeJson(res))
    def VerifyPermissions(self,
                          required_permission,
                          user=None,
                          permission_type=None):
        """Verifies a valid user is logged in.

    Args:
      required_permission: permission string from permissions.*.
      user: optional, base.User entity; default current user.
      permission_type: optional, string, one of permission.TYPE_* variables. if
          omitted, self.PERMISSION_TYPE is used.
    Returns:
      base.User object of the current user.
    Raises:
      base.AccessDeniedError: there was a permissions issue.
    """
        # TODO(user): Consider making the method accept a list of checks
        #    to be performed, making CheckRetrieveAuthorization simpler.
        permission_type = permission_type or self.PERMISSION_TYPE

        if user is None:
            user = base.GetCurrentUser()

        base_handler.VerifyPermissions(required_permission, user,
                                       permission_type)

        return user
Example #9
0
def XsrfTokenValidate(token, action, user=None, timestamp=None, time_=time):
    """Generate an XSRF token."""
    if not token:
        return False
    if not user:
        # TODO(user): drop the unused user arg, find a way to cache user.
        user = base.GetCurrentUser().email
    if not timestamp:
        try:
            # Request objects return Unicode encoded tokens.
            token = token.encode('utf-8')

            _, timestr = base64.urlsafe_b64decode(token).split(
                XSRF_DELIMITER, 1)
            timestamp = float(timestr)
        except ValueError:
            logging.exception('ValueError obtaining timestamp from token: %s',
                              token)
            return False

    if timestamp + XSRF_VALID_TIME < time_.time():
        return False
    if token != XsrfTokenGenerate(action, user, timestamp):
        return False
    return True
Example #10
0
 def _VerifyEscrowPermission(self):
   try:
     base.GetCurrentUser()
   except base.AccessDeniedError:
     pass
   else:
     return super(DellFirmwarePassword, self)._VerifyEscrowPermission()
   raise base.AccessDeniedError
    def RetrieveSecret(self, target_id):
        """Handles a GET request to retrieve a secret."""
        self.VerifyXsrfToken(base_settings.GET_PASSPHRASE_ACTION)

        if self.request.get('id'):
            try:
                entity = self.SECRET_MODEL.get(db.Key(self.request.get('id')))
            except datastore_errors.BadKeyError:
                raise base.AccessError('target_id is malformed')
        else:
            entity = self.SECRET_MODEL.GetLatestForTarget(target_id,
                                                          tag=self.request.get(
                                                              'tag',
                                                              'default'))

        if not entity:
            raise base.AccessError('Passphrase not found: target_id %s' %
                                   target_id)

        user = base.GetCurrentUser()

        self.CheckRetrieveAuthorization(entity=entity, user=user)

        self.AUDIT_LOG_MODEL.Log(message='GET',
                                 entity=entity,
                                 request=self.request)

        # Send retrieval email if user is not retrieving their own secret.
        if entity.owner != user.email:
            SendRetrievalEmail(self.PERMISSION_TYPE, entity, user)

        escrow_secret = str(entity.secret).strip()

        escrow_barcode_svg = None
        qr_img_url = None
        if self.QRCODE_DURING_PASSPHRASE_RETRIEVAL:
            if len(escrow_secret) <= 100:
                qr_img_url = (
                    'https://chart.googleapis.com/chart?chs=245x245&cht=qr&chl='
                    + cgi.escape(escrow_secret))

        recovery_str = self._PassphraseTypeName(entity)

        params = {
            'volume_type': self.SECRET_MODEL.ESCROW_TYPE_NAME,
            'volume_uuid': entity.target_id,
            'qr_img_url': qr_img_url,
            'escrow_secret': escrow_secret,
            'checksum': entity.checksum,
            'recovery_str': recovery_str,
        }

        params[self.JSON_SECRET_NAME] = escrow_secret

        if entity.active:
            entity.UpdateMutableProperty('force_rekeying', True)

        self.response.out.write(util.ToSafeJson(params))
 def _VerifyEscrowPermission(self):
     try:
         base.GetCurrentUser()
     except errors.AccessDeniedError:
         pass
     else:
         return super(FirmwarePasswordHandler,
                      self)._VerifyEscrowPermission()
     raise errors.AccessDeniedError
    def _CreateNewSecretEntity(self, owner, volume_uuid, secret):
        user = base.GetCurrentUser()
        platform = self.request.get('platform')
        # Set default platform to Mac
        if not platform:
            platform = 'Mac'

        return models.ProvisioningVolume(owner=owner,
                                         volume_uuid=volume_uuid,
                                         passphrase=str(secret))
Example #14
0
    def testGetCurrentUser(self):
        self.testbed.setup_env(user_email='*****@*****.**', overwrite=True)

        user = base.GetCurrentUser()

        self.assertEqual('*****@*****.**', user.user.email())
        self.assertEqual(0, len(user.bitlocker_perms))
        self.assertEqual(0, len(user.duplicity_perms))
        self.assertEqual(0, len(user.filevault_perms))
        self.assertEqual(0, len(user.luks_perms))
Example #15
0
def XsrfTokenGenerate(action, user=None, timestamp=None):
    """Generate an XSRF token."""
    if not user:
        user = base.GetCurrentUser().email
    if not timestamp:
        timestamp = time.time()
    timestr = str(timestamp)
    secret = crypto.ENCRYPTION_KEY_TYPES[settings.KEY_TYPE_DEFAULT_XSRF]()
    h = hmac.new(secret, XSRF_DELIMITER.join((user, action, timestr)))
    return base64.urlsafe_b64encode(''.join(
        (h.digest(), XSRF_DELIMITER, timestr)))
Example #16
0
    def get(self, action=None):
        """Handles GET requests."""
        if not action:
            self.error(httplib.NOT_FOUND)
            return

        try:
            email = base.GetCurrentUser().email
        except errors.AccessDeniedError:
            raise errors.AccessDeniedError
        self.response.headers['Content-Type'] = 'text/plain'
        self.response.out.write(util.XsrfTokenGenerate(action, user=email))
Example #17
0
    def get(self):
        """Handles GET requests."""

        base_handler.VerifyPermissions(permissions.RETRIEVE_CREATED_BY,
                                       base.GetCurrentUser(),
                                       permissions.TYPE_PROVISIONING)

        volumes = ProvisioningVolumesForUser(users.get_current_user(),
                                             PROVISIONING_FILTER_SECONDS)
        volumes = [volume.ToDict() for volume in volumes]

        self.response.out.write(util.ToSafeJson(volumes))
Example #18
0
 def post(self, volume_key):
   """Handles POST requests."""
   self.VerifyXsrfToken(base_settings.CHANGE_OWNER_ACTION)
   base_handler.VerifyPermissions(
       permissions.CHANGE_OWNER, base.GetCurrentUser(),
       permissions.TYPE_FILEVAULT)
   new_entity = self.entity.Clone()
   new_entity.owner = self.request.get('new_owner')
   new_entity.put()
   self.AUDIT_LOG_MODEL.Log(
       entity=self.entity, request=self.request, message=(
           'Owner changed from "%s" to "%s"' %
           (self.entity.owner, new_entity.owner)))
Example #19
0
    def get(self, action=None):
        """Handles GET requests."""
        if not action:
            self.error(httplib.NOT_FOUND)
            return

        try:
            base.GetCurrentUser()
        except base.AccessDeniedError:
            self.error(httplib.UNAUTHORIZED)
            return

        self.response.headers['Content-Type'] = 'text/plain'
        self.response.out.write(util.XsrfTokenGenerate(action))
Example #20
0
    def get(self, type_name, target_id):
        """Handles GET requests."""
        user = base.GetCurrentUser()
        tag = self.request.get('tag', 'default')

        entity = models_util.TypeNameToModel(type_name).GetLatestForTarget(
            target_id, tag)
        if not entity:
            # TODO(b/35954370) notify users about missing passphrases.
            self.response.write(util.ToSafeJson(False))
            return

        if entity.owner != user.email:
            logging.warning('owner mismatch %s %s', entity.owner, user.email)
            # Passphrase retrieval is necessary for rekeying so we abort.
            self.response.write(util.ToSafeJson(False))
            return

        self.response.write(util.ToSafeJson(bool(entity.force_rekeying)))
Example #21
0
  def get(self, type_name, target_id):
    """Handles GET requests."""
    user = base.GetCurrentUser()
    tag = self.request.get('tag', 'default')

    entity = models_util.TypeNameToModel(
        type_name).GetLatestForTarget(target_id, tag)
    if not entity:
      if memcache.Client().get(target_id, namespace='experimental_rekey'):
        logging.info('experimental_rekey %s', target_id)
        self.response.write(util.ToSafeJson('experimental'))
        return
      self.response.write(util.ToSafeJson(False))
      return

    if entity.owner != user.email:
      logging.warning(
          'owner mismatch %s %s', entity.owner, user.email)
      # Passphrase retrieval is necessary for rekeying so we abort.
      self.response.write(util.ToSafeJson(False))
      return

    self.response.write(util.ToSafeJson(bool(entity.force_rekeying)))
Example #22
0
def VerifyAllPermissionTypes(required_permission, user=None):
    """Verifies if a user has the required_permission for all permission types.

  Args:
    required_permission: permission string from permissions.*.
    user: optional, base.User entity; default current user.
  Returns:
    Dict. Keys are permissions.TYPES values, and value booleans, True when
    the user has the required_permission for the permission type, False
    otherwise.
  """
    if user is None:
        user = base.GetCurrentUser()

    perms = {}
    for permission_type in permissions.TYPES:
        try:
            VerifyPermissions(required_permission, user, permission_type)
            perms[permission_type] = True
        except base.AccessDeniedError:
            perms[permission_type] = False
    # TODO(user): if use of this method widens, consider returning a
    #    collections.namedtuple instead of a basic dict.
    return perms
Example #23
0
    def get(self):
        """Handles GET requests."""
        if self.request.get('json', '0') != '1':
            search_type = self.request.get('search_type')
            field1 = urllib.quote(self.request.get('field1'))
            value1 = urllib.quote(self.request.get('value1').strip())
            prefix_search = urllib.quote(self.request.get(
                'prefix_search', '0'))

            if search_type and field1 and value1:
                self.redirect('/ui/#/search/%s/%s/%s/%s' %
                              (search_type, field1, value1, prefix_search))
            else:
                self.redirect('/ui/', permanent=True)
            return

        tag = self.request.get('tag', 'default')
        search_type = self.request.get('search_type')
        field1 = self.request.get('field1')
        value1 = self.request.get('value1').strip()
        prefix_search = self.request.get('prefix_search', '0') == '1'

        try:
            model = models_util.TypeNameToModel(search_type)
        except ValueError:
            raise passphrase_handler.InvalidArgumentError(
                'Invalid search_type %s' % search_type)

        if not (field1 and value1):
            raise base_handler.InvalidArgumentError('Missing field1 or value1')

        # Get the user's search and retrieve permissions for all permission types.
        search_perms = base_handler.VerifyAllPermissionTypes(
            permissions.SEARCH)
        retrieve_perms = base_handler.VerifyAllPermissionTypes(
            permissions.RETRIEVE_OWN)
        retrieve_created = base_handler.VerifyAllPermissionTypes(
            permissions.RETRIEVE_CREATED_BY)

        # user is performing a search, ensure they have permissions.
        if (not search_perms.get(search_type)
                and not retrieve_perms.get(search_type)
                and not retrieve_created.get(search_type)):
            raise base.AccessDeniedError('User lacks %s permission' %
                                         search_type)

        try:
            passphrases = _PassphrasesForQuery(model, field1, value1,
                                               prefix_search)
        except ValueError:
            self.error(httplib.NOT_FOUND)
            return

        skipped = False
        if not search_perms.get(search_type):
            results_len = len(passphrases)
            email = base.GetCurrentUser().user.email()
            passphrases = [x for x in passphrases if x.owner == email]
            skipped = len(passphrases) != results_len
        too_many_results = len(passphrases) >= MAX_PASSPHRASES_PER_QUERY

        passphrases = [
            v.ToDict(skip_secret=True) for v in passphrases if v.tag == tag
        ]
        if model.ALLOW_OWNER_CHANGE:
            for passphrase in passphrases:
                if not passphrase['active']:
                    continue
                link = '/api/internal/change-owner/%s/%s/' % (search_type,
                                                              passphrase['id'])
                passphrase['change_owner_link'] = link

        self.response.out.write(
            util.ToSafeJson({
                'passphrases': passphrases,
                'too_many_results': too_many_results,
                'results_access_warning': skipped,
            }))
Example #24
0
    def get(self):  # pylint: disable=g-bad-name
        """Handles GET requests."""
        # TODO(user): Users with retrieve_own should not need to search to
        # retrieve their escrowed secrets.
        if self.request.get('json', '0') != '1':
            search_type = self.request.get('search_type')
            field1 = urllib.quote(self.request.get('field1'))
            value1 = urllib.quote(self.request.get('value1').strip())
            prefix_search = urllib.quote(self.request.get(
                'prefix_search', '0'))

            if search_type and field1 and value1:
                self.redirect('/ui/#/search/%s/%s/%s/%s' %
                              (search_type, field1, value1, prefix_search))
            else:
                self.redirect('/ui/', permanent=True)
            return

        tag = self.request.get('tag', 'default')
        search_type = self.request.get('search_type')
        field1 = self.request.get('field1')
        value1 = self.request.get('value1').strip()
        prefix_search = self.request.get('prefix_search', '0') == '1'

        try:
            model = volumes.TypeNameToModel(search_type)
        except ValueError:
            raise handlers.InvalidArgumentError('Invalid search_type %s' %
                                                search_type)

        if not (field1 and value1):
            raise handlers.InvalidArgumentError('Missing field1 or value1')

        # Get the user's search and retrieve permissions for all permission types.
        search_perms = handlers.VerifyAllPermissionTypes(permissions.SEARCH)
        retrieve_perms = handlers.VerifyAllPermissionTypes(
            permissions.RETRIEVE_OWN)
        retrieve_created = handlers.VerifyAllPermissionTypes(
            permissions.RETRIEVE_CREATED_BY)

        # user is performing a search, ensure they have permissions.
        if (not search_perms.get(search_type)
                and not retrieve_perms.get(search_type)
                and not retrieve_created.get(search_type)):
            raise base.AccessDeniedError('User lacks %s permission' %
                                         search_type)

        # TODO(user): implement multi-field search by building query here
        #   or better yet using JavaScript.
        q = '%s:%s' % (field1, value1)
        try:
            passphrases = _PassphrasesForQuery(model, q, prefix_search)
        except ValueError:
            self.error(httplib.NOT_FOUND)
            return

        if not search_perms.get(search_type):
            username = base.GetCurrentUser().user.nickname()
            passphrases = [x for x in passphrases if x.owner == username]

        passphrases = [
            v.ToDict(skip_secret=True) for v in passphrases if v.tag == tag
        ]
        if model.ALLOW_OWNER_CHANGE:
            for passphrase in passphrases:
                if not passphrase['active']:
                    continue
                link = '/api/internal/change-owner/%s/%s/' % (search_type,
                                                              passphrase['id'])
                passphrase['change_owner_link'] = link

        self.response.out.write(util.ToSafeJson(passphrases))