push_notifications: Validate APNS token format in bouncer.

This prevents a buggy old Zulip server from forwarding invalid-format
push notification tokens to the push notification bouncer service.

As part of this change, we switch the token from Text to str to match
the rest of the code path.
This commit is contained in:
Tim Abbott 2017-07-07 09:23:36 -07:00
parent eaa33cce73
commit 40425044c4
1 changed files with 8 additions and 8 deletions

View File

@ -14,6 +14,7 @@ from zerver.lib.request import JsonableError
from zerver.lib.response import json_error, json_success from zerver.lib.response import json_error, json_success
from zerver.lib.validator import check_dict from zerver.lib.validator import check_dict
from zerver.models import UserProfile, PushDeviceToken, Realm from zerver.models import UserProfile, PushDeviceToken, Realm
from zerver.views.push_notifications import validate_token
from typing import Any, Dict, Optional, Union, Text, cast from typing import Any, Dict, Optional, Union, Text, cast
@ -22,11 +23,10 @@ def validate_entity(entity):
if not isinstance(entity, RemoteZulipServer): if not isinstance(entity, RemoteZulipServer):
raise JsonableError(_("Must validate with valid Zulip server API key")) raise JsonableError(_("Must validate with valid Zulip server API key"))
def validate_bouncer_token_request(entity, token): def validate_bouncer_token_request(entity, token, kind):
# type: (Union[UserProfile, RemoteZulipServer], Text) -> None # type: (Union[UserProfile, RemoteZulipServer], str, int) -> None
validate_entity(entity) validate_entity(entity)
if token == '' or len(token) > 4096: validate_token(token, kind)
raise JsonableError(_("Empty or invalid length token"))
@has_request_variables @has_request_variables
def report_error(request, deployment, type=REQ(), report=REQ(validator=check_dict([]))): def report_error(request, deployment, type=REQ(), report=REQ(validator=check_dict([]))):
@ -36,8 +36,8 @@ def report_error(request, deployment, type=REQ(), report=REQ(validator=check_dic
@has_request_variables @has_request_variables
def remote_server_register_push(request, entity, user_id=REQ(), def remote_server_register_push(request, entity, user_id=REQ(),
token=REQ(), token_kind=REQ(), ios_app_id=None): token=REQ(), token_kind=REQ(), ios_app_id=None):
# type: (HttpRequest, Union[UserProfile, RemoteZulipServer], int, Text, int, Optional[Text]) -> HttpResponse # type: (HttpRequest, Union[UserProfile, RemoteZulipServer], int, str, int, Optional[Text]) -> HttpResponse
validate_bouncer_token_request(entity, token) validate_bouncer_token_request(entity, token, token_kind)
server = cast(RemoteZulipServer, entity) server = cast(RemoteZulipServer, entity)
# If a user logged out on a device and failed to unregister, # If a user logged out on a device and failed to unregister,
@ -61,8 +61,8 @@ def remote_server_register_push(request, entity, user_id=REQ(),
@has_request_variables @has_request_variables
def remote_server_unregister_push(request, entity, token=REQ(), def remote_server_unregister_push(request, entity, token=REQ(),
token_kind=REQ(), ios_app_id=None): token_kind=REQ(), ios_app_id=None):
# type: (HttpRequest, Union[UserProfile, RemoteZulipServer], Text, int, Optional[Text]) -> HttpResponse # type: (HttpRequest, Union[UserProfile, RemoteZulipServer], str, int, Optional[Text]) -> HttpResponse
validate_bouncer_token_request(entity, token) validate_bouncer_token_request(entity, token, token_kind)
server = cast(RemoteZulipServer, entity) server = cast(RemoteZulipServer, entity)
deleted = RemotePushDeviceToken.objects.filter(token=token, deleted = RemotePushDeviceToken.objects.filter(token=token,
kind=token_kind, kind=token_kind,