diff --git a/src/calibre/srv/auth.py b/src/calibre/srv/auth.py index 2b6dc9a0fb..ad4f649b4d 100644 --- a/src/calibre/srv/auth.py +++ b/src/calibre/srv/auth.py @@ -200,15 +200,16 @@ class AuthController(object): return pw and self.user_credentials.get(un) == pw def __call__(self, data, endpoint): - http_auth_needed = not (endpoint.android_workaround and self.validate_android_cookie(data.cookies.get(self.ANDROID_COOKIE))) + path = encode_path(*data.path) + http_auth_needed = not (endpoint.android_workaround and self.validate_android_cookie(path, data.cookies.get(self.ANDROID_COOKIE))) if http_auth_needed: self.do_http_auth(data, endpoint) if endpoint.android_workaround: - data.outcookie[self.ANDROID_COOKIE] = synthesize_nonce(self.key_order, self.realm, self.secret) - data.outcookie[self.ANDROID_COOKIE]['path'] = encode_path(*data.path) + data.outcookie[self.ANDROID_COOKIE] = synthesize_nonce(self.key_order, path, self.secret) + data.outcookie[self.ANDROID_COOKIE]['path'] = path - def validate_android_cookie(self, cookie): - return cookie and validate_nonce(self.key_order, cookie, self.realm, self.secret) and not is_nonce_stale(cookie, self.max_age_seconds) + def validate_android_cookie(self, path, cookie): + return cookie and validate_nonce(self.key_order, cookie, path, self.secret) and not is_nonce_stale(cookie, self.max_age_seconds) def do_http_auth(self, data, endpoint): auth = data.inheaders.get('Authorization') diff --git a/src/calibre/srv/tests/auth.py b/src/calibre/srv/tests/auth.py index cc1a659f2b..f309b04172 100644 --- a/src/calibre/srv/tests/auth.py +++ b/src/calibre/srv/tests/auth.py @@ -26,6 +26,10 @@ def auth(ctx, data): def android(ctx, data): return 'android' +@endpoint('/android2', auth_required=True, android_workaround=True) +def android2(ctx, data): + return 'android2' + def router(prefer_basic_auth=False): from calibre.srv.auth import AuthController return Router(globals().itervalues(), auth_controller=AuthController( @@ -199,4 +203,11 @@ class TestAuth(BaseTest): r = urllib2.build_opener(cookie_handler).open(url) self.ae(r.getcode(), httplib.OK) self.ae(r.read(), b'android') + # Test that a replay attack against a different URL does not work + try: + urllib2.build_opener(cookie_handler).open(url+'2') + assert ('Replay attack succeeded') + except urllib2.HTTPError as e: + self.ae(e.code, httplib.UNAUTHORIZED) + # }}}