本文整理汇总了Python中swift.common.utils.streq_const_time函数的典型用法代码示例。如果您正苦于以下问题:Python streq_const_time函数的具体用法?Python streq_const_time怎么用?Python streq_const_time使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了streq_const_time函数的12个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的Python代码示例。
示例1: _perform_subrequest
def _perform_subrequest(self, env, start_response, attributes, fp, key):
"""
Performs the subrequest and returns a new response.
:param env: The WSGI environment dict.
:param start_response: The WSGI start_response hook.
:param attributes: dict of the attributes of the form so far.
:param fp: The file-like object containing the request body.
:param key: The account key to validate the signature with.
:returns: Response as per WSGI.
"""
if not key:
return '401 Unauthorized', 'invalid signature'
try:
max_file_size = int(attributes.get('max_file_size') or 0)
except ValueError:
raise FormInvalid('max_file_size not an integer')
subenv = {'REQUEST_METHOD': 'PUT',
'SCRIPT_NAME': '',
'SERVER_NAME': env['SERVER_NAME'],
'SERVER_PORT': env['SERVER_PORT'],
'SERVER_PROTOCOL': env['SERVER_PROTOCOL'],
'HTTP_TRANSFER_ENCODING': 'chunked',
'wsgi.input': _CappedFileLikeObject(fp, max_file_size),
'swift.cache': env['swift.cache']}
subenv['PATH_INFO'] = env['PATH_INFO']
if subenv['PATH_INFO'][-1] != '/' and \
subenv['PATH_INFO'].count('/') < 4:
subenv['PATH_INFO'] += '/'
subenv['PATH_INFO'] += attributes['filename'] or 'filename'
if 'content-type' in attributes:
subenv['CONTENT_TYPE'] = \
attributes['content-type'] or 'application/octet-stream'
try:
if int(attributes.get('expires') or 0) < time():
return '401 Unauthorized', 'form expired'
except ValueError:
raise FormInvalid('expired not an integer')
hmac_body = '%s\n%s\n%s\n%s\n%s' % (
env['PATH_INFO'],
attributes.get('redirect') or '',
attributes.get('max_file_size') or '0',
attributes.get('max_file_count') or '0',
attributes.get('expires') or '0'
)
sig = hmac.new(key, hmac_body, sha1).hexdigest()
if not streq_const_time(sig, (attributes.get('signature') or
'invalid')):
return '401 Unauthorized', 'invalid signature'
subenv['swift.authorize'] = lambda req: None
subenv['swift.authorize_override'] = True
subenv['REMOTE_USER'] = '.wsgi.formpost'
substatus = [None]
def _start_response(status, headers, exc_info=None):
substatus[0] = status
self.app(subenv, _start_response)
return substatus[0], ''
示例2: _perform_subrequest
def _perform_subrequest(self, orig_env, attributes, fp, key):
"""
Performs the subrequest and returns the response.
:param orig_env: The WSGI environment dict; will only be used
to form a new env for the subrequest.
:param attributes: dict of the attributes of the form so far.
:param fp: The file-like object containing the request body.
:param key: The account key to validate the signature with.
:returns: (status_line, message)
"""
if not key:
return '401 Unauthorized', 'invalid signature'
try:
max_file_size = int(attributes.get('max_file_size') or 0)
except ValueError:
raise FormInvalid('max_file_size not an integer')
subenv = make_pre_authed_env(orig_env, 'PUT', agent=None,
swift_source='FP')
if 'QUERY_STRING' in subenv:
del subenv['QUERY_STRING']
subenv['HTTP_TRANSFER_ENCODING'] = 'chunked'
subenv['wsgi.input'] = _CappedFileLikeObject(fp, max_file_size)
if subenv['PATH_INFO'][-1] != '/' and \
subenv['PATH_INFO'].count('/') < 4:
subenv['PATH_INFO'] += '/'
subenv['PATH_INFO'] += attributes['filename'] or 'filename'
if 'content-type' in attributes:
subenv['CONTENT_TYPE'] = \
attributes['content-type'] or 'application/octet-stream'
elif 'CONTENT_TYPE' in subenv:
del subenv['CONTENT_TYPE']
try:
if int(attributes.get('expires') or 0) < time():
return '401 Unauthorized', 'form expired'
except ValueError:
raise FormInvalid('expired not an integer')
hmac_body = '%s\n%s\n%s\n%s\n%s' % (
orig_env['PATH_INFO'],
attributes.get('redirect') or '',
attributes.get('max_file_size') or '0',
attributes.get('max_file_count') or '0',
attributes.get('expires') or '0')
sig = hmac.new(key, hmac_body, sha1).hexdigest()
if not streq_const_time(sig, (attributes.get('signature') or
'invalid')):
return '401 Unauthorized', 'invalid signature'
substatus = [None]
def _start_response(status, headers, exc_info=None):
substatus[0] = status
i = iter(self.app(subenv, _start_response))
try:
i.next()
except StopIteration:
pass
return substatus[0], ''
示例3: GETorHEAD
def GETorHEAD(self, req):
"""Handler for HTTP GET/HEAD requests."""
"""
Handles requests to /info
Should return a WSGI-style callable (such as swob.Response).
:param req: swob.Request object
"""
if not self.expose_info:
return HTTPForbidden(request=req)
admin_request = False
sig = req.params.get('swiftinfo_sig', '')
expires = req.params.get('swiftinfo_expires', '')
if sig != '' or expires != '':
admin_request = True
if not self.admin_key:
return HTTPForbidden(request=req)
try:
expires = int(expires)
except ValueError:
return HTTPUnauthorized(request=req)
if expires < time():
return HTTPUnauthorized(request=req)
valid_sigs = []
for method in self.allowed_hmac_methods[req.method]:
valid_sigs.append(get_hmac(method,
'/info',
expires,
self.admin_key))
# While it's true that any() will short-circuit, this doesn't
# affect the timing-attack resistance since the only way this will
# short-circuit is when a valid signature is passed in.
is_valid_hmac = any(streq_const_time(valid_sig, sig)
for valid_sig in valid_sigs)
if not is_valid_hmac:
return HTTPUnauthorized(request=req)
headers = {}
if 'Origin' in req.headers:
headers['Access-Control-Allow-Origin'] = req.headers['Origin']
headers['Access-Control-Expose-Headers'] = ', '.join(
['x-trans-id'])
#json.dumps(dict)可以将字典形式的dict对象转换为json格式的对象
info = json.dumps(get_swift_info(
admin=admin_request, disallowed_sections=self.disallowed_sections))
return HTTPOk(request=req,
headers=headers,
body=info,
content_type='application/json; charset=UTF-8')
示例4: test_streq_const_time
def test_streq_const_time(self):
self.assertTrue(utils.streq_const_time('abc123', 'abc123'))
self.assertFalse(utils.streq_const_time('a', 'aaaaa'))
self.assertFalse(utils.streq_const_time('ABC123', 'abc123'))
示例5: __call__
def __call__(self, env, start_response):
"""
Main hook into the WSGI paste.deploy filter/app pipeline.
:param env: The WSGI environment dict.
:param start_response: The WSGI start_response hook.
:returns: Response as per WSGI.
"""
if env['REQUEST_METHOD'] == 'OPTIONS':
return self.app(env, start_response)
info = self._get_temp_url_info(env)
temp_url_sig, temp_url_expires, temp_url_prefix, filename,\
inline_disposition = info
if temp_url_sig is None and temp_url_expires is None:
return self.app(env, start_response)
if not temp_url_sig or not temp_url_expires:
return self._invalid(env, start_response)
account, container, obj = self._get_path_parts(env)
if not account:
return self._invalid(env, start_response)
keys = self._get_keys(env)
if not keys:
return self._invalid(env, start_response)
if temp_url_prefix is None:
path = '/v1/%s/%s/%s' % (account, container, obj)
else:
if not obj.startswith(temp_url_prefix):
return self._invalid(env, start_response)
path = 'prefix:/v1/%s/%s/%s' % (account, container,
temp_url_prefix)
if env['REQUEST_METHOD'] == 'HEAD':
hmac_vals = (
self._get_hmacs(env, temp_url_expires, path, keys) +
self._get_hmacs(env, temp_url_expires, path, keys,
request_method='GET') +
self._get_hmacs(env, temp_url_expires, path, keys,
request_method='POST') +
self._get_hmacs(env, temp_url_expires, path, keys,
request_method='PUT'))
else:
hmac_vals = self._get_hmacs(env, temp_url_expires, path, keys)
is_valid_hmac = False
hmac_scope = None
for hmac, scope in hmac_vals:
# While it's true that we short-circuit, this doesn't affect the
# timing-attack resistance since the only way this will
# short-circuit is when a valid signature is passed in.
if streq_const_time(temp_url_sig, hmac):
is_valid_hmac = True
hmac_scope = scope
break
if not is_valid_hmac:
return self._invalid(env, start_response)
# disallowed headers prevent accidentally allowing upload of a pointer
# to data that the PUT tempurl would not otherwise allow access for.
# It should be safe to provide a GET tempurl for data that an
# untrusted client just uploaded with a PUT tempurl.
resp = self._clean_disallowed_headers(env, start_response)
if resp:
return resp
self._clean_incoming_headers(env)
if hmac_scope == ACCOUNT_SCOPE:
env['swift.authorize'] = authorize_same_account(account)
else:
env['swift.authorize'] = authorize_same_container(account,
container)
env['swift.authorize_override'] = True
env['REMOTE_USER'] = '.wsgi.tempurl'
qs = {'temp_url_sig': temp_url_sig,
'temp_url_expires': temp_url_expires}
if temp_url_prefix is not None:
qs['temp_url_prefix'] = temp_url_prefix
if filename:
qs['filename'] = filename
env['QUERY_STRING'] = urlencode(qs)
def _start_response(status, headers, exc_info=None):
headers = self._clean_outgoing_headers(headers)
if env['REQUEST_METHOD'] in ('GET', 'HEAD') and status[0] == '2':
# figure out the right value for content-disposition
# 1) use the value from the query string
# 2) use the value from the object metadata
# 3) use the object name (default)
out_headers = []
existing_disposition = None
for h, v in headers:
if h.lower() != 'content-disposition':
out_headers.append((h, v))
else:
existing_disposition = v
if inline_disposition:
if filename:
disposition_value = disposition_format('inline',
filename)
else:
disposition_value = 'inline'
elif filename:
disposition_value = disposition_format('attachment',
#.........这里部分代码省略.........
示例6: __call__
def __call__(self, req):
if not self.allow_full_urls:
sync_to = req.headers.get('x-container-sync-to')
if sync_to and not sync_to.startswith('//'):
raise HTTPBadRequest(
body='Full URLs are not allowed for X-Container-Sync-To '
'values. Only realm values of the format '
'//realm/cluster/account/container are allowed.\n',
request=req)
auth = req.headers.get('x-container-sync-auth')
if auth:
valid = False
auth = auth.split()
if len(auth) != 3:
req.environ.setdefault('swift.log_info', []).append(
'cs:not-3-args')
else:
realm, nonce, sig = auth
realm_key = self.realms_conf.key(realm)
realm_key2 = self.realms_conf.key2(realm)
if not realm_key:
req.environ.setdefault('swift.log_info', []).append(
'cs:no-local-realm-key')
else:
info = get_container_info(
req.environ, self.app, swift_source='CS')
user_key = info.get('sync_key')
if not user_key:
req.environ.setdefault('swift.log_info', []).append(
'cs:no-local-user-key')
else:
expected = self.realms_conf.get_sig(
req.method, req.path,
req.headers.get('x-timestamp', '0'), nonce,
realm_key, user_key)
expected2 = self.realms_conf.get_sig(
req.method, req.path,
req.headers.get('x-timestamp', '0'), nonce,
realm_key2, user_key) if realm_key2 else expected
if not streq_const_time(sig, expected) and \
not streq_const_time(sig, expected2):
req.environ.setdefault(
'swift.log_info', []).append('cs:invalid-sig')
else:
req.environ.setdefault(
'swift.log_info', []).append('cs:valid')
valid = True
if not valid:
exc = HTTPUnauthorized(
body='X-Container-Sync-Auth header not valid; '
'contact cluster operator for support.',
headers={'content-type': 'text/plain'},
request=req)
exc.headers['www-authenticate'] = ' '.join([
'SwiftContainerSync',
exc.www_authenticate().split(None, 1)[1]])
raise exc
else:
req.environ['swift.authorize_override'] = True
if req.path == '/info':
# Ensure /info requests get the freshest results
dct = {}
for realm in self.realms_conf.realms():
clusters = self.realms_conf.clusters(realm)
if clusters:
dct[realm] = {'clusters': dict((c, {}) for c in clusters)}
register_swift_info('container_sync', realms=dct)
return self.app
示例7: _perform_subrequest
def _perform_subrequest(self, orig_env, attributes, fp, keys):
"""
Performs the subrequest and returns the response.
:param orig_env: The WSGI environment dict; will only be used
to form a new env for the subrequest.
:param attributes: dict of the attributes of the form so far.
:param fp: The file-like object containing the request body.
:param keys: The account keys to validate the signature with.
:returns: (status_line, headers_list, message)
"""
if not keys:
raise FormUnauthorized("invalid signature")
try:
max_file_size = int(attributes.get("max_file_size") or 0)
except ValueError:
raise FormInvalid("max_file_size not an integer")
subenv = make_pre_authed_env(orig_env, "PUT", agent=None, swift_source="FP")
if "QUERY_STRING" in subenv:
del subenv["QUERY_STRING"]
subenv["HTTP_TRANSFER_ENCODING"] = "chunked"
subenv["wsgi.input"] = _CappedFileLikeObject(fp, max_file_size)
if subenv["PATH_INFO"][-1] != "/" and subenv["PATH_INFO"].count("/") < 4:
subenv["PATH_INFO"] += "/"
subenv["PATH_INFO"] += attributes["filename"] or "filename"
if "x_delete_at" in attributes:
try:
subenv["HTTP_X_DELETE_AT"] = int(attributes["x_delete_at"])
except ValueError:
raise FormInvalid("x_delete_at not an integer: " "Unix timestamp required.")
if "x_delete_after" in attributes:
try:
subenv["HTTP_X_DELETE_AFTER"] = int(attributes["x_delete_after"])
except ValueError:
raise FormInvalid("x_delete_after not an integer: " "Number of seconds required.")
if "content-type" in attributes:
subenv["CONTENT_TYPE"] = attributes["content-type"] or "application/octet-stream"
elif "CONTENT_TYPE" in subenv:
del subenv["CONTENT_TYPE"]
try:
if int(attributes.get("expires") or 0) < time():
raise FormUnauthorized("form expired")
except ValueError:
raise FormInvalid("expired not an integer")
hmac_body = "%s\n%s\n%s\n%s\n%s" % (
orig_env["PATH_INFO"],
attributes.get("redirect") or "",
attributes.get("max_file_size") or "0",
attributes.get("max_file_count") or "0",
attributes.get("expires") or "0",
)
has_valid_sig = False
for key in keys:
sig = hmac.new(key, hmac_body, sha1).hexdigest()
if streq_const_time(sig, (attributes.get("signature") or "invalid")):
has_valid_sig = True
if not has_valid_sig:
raise FormUnauthorized("invalid signature")
substatus = [None]
subheaders = [None]
wsgi_input = subenv["wsgi.input"]
def _start_response(status, headers, exc_info=None):
if wsgi_input.file_size_exceeded:
raise EOFError("max_file_size exceeded")
substatus[0] = status
subheaders[0] = headers
i = iter(self.app(subenv, _start_response))
try:
i.next()
except StopIteration:
pass
return substatus[0], subheaders[0], ""
示例8: _perform_subrequest
def _perform_subrequest(self, orig_env, attributes, fp, keys):
"""
Performs the subrequest and returns the response.
:param orig_env: The WSGI environment dict; will only be used
to form a new env for the subrequest.
:param attributes: dict of the attributes of the form so far.
:param fp: The file-like object containing the request body.
:param keys: The account keys to validate the signature with.
:returns: (status_line, headers_list)
"""
if not keys:
raise FormUnauthorized('invalid signature')
try:
max_file_size = int(attributes.get('max_file_size') or 0)
except ValueError:
raise FormInvalid('max_file_size not an integer')
subenv = make_pre_authed_env(orig_env, 'PUT', agent=None,
swift_source='FP')
if 'QUERY_STRING' in subenv:
del subenv['QUERY_STRING']
subenv['HTTP_TRANSFER_ENCODING'] = 'chunked'
subenv['wsgi.input'] = _CappedFileLikeObject(fp, max_file_size)
if not subenv['PATH_INFO'].endswith('/') and \
subenv['PATH_INFO'].count('/') < 4:
subenv['PATH_INFO'] += '/'
subenv['PATH_INFO'] += attributes['filename'] or 'filename'
if 'x_delete_at' in attributes:
try:
subenv['HTTP_X_DELETE_AT'] = int(attributes['x_delete_at'])
except ValueError:
raise FormInvalid('x_delete_at not an integer: '
'Unix timestamp required.')
if 'x_delete_after' in attributes:
try:
subenv['HTTP_X_DELETE_AFTER'] = int(
attributes['x_delete_after'])
except ValueError:
raise FormInvalid('x_delete_after not an integer: '
'Number of seconds required.')
if 'content-type' in attributes:
subenv['CONTENT_TYPE'] = \
attributes['content-type'] or 'application/octet-stream'
if 'content-encoding' in attributes:
subenv['HTTP_CONTENT_ENCODING'] = attributes['content-encoding']
try:
if int(attributes.get('expires') or 0) < time():
raise FormUnauthorized('form expired')
except ValueError:
raise FormInvalid('expired not an integer')
hmac_body = '%s\n%s\n%s\n%s\n%s' % (
orig_env['PATH_INFO'],
attributes.get('redirect') or '',
attributes.get('max_file_size') or '0',
attributes.get('max_file_count') or '0',
attributes.get('expires') or '0')
if six.PY3:
hmac_body = hmac_body.encode('utf-8')
has_valid_sig = False
for key in keys:
sig = hmac.new(key, hmac_body, sha1).hexdigest()
if streq_const_time(sig, (attributes.get('signature') or
'invalid')):
has_valid_sig = True
if not has_valid_sig:
raise FormUnauthorized('invalid signature')
substatus = [None]
subheaders = [None]
wsgi_input = subenv['wsgi.input']
def _start_response(status, headers, exc_info=None):
if wsgi_input.file_size_exceeded:
raise EOFError("max_file_size exceeded")
substatus[0] = status
subheaders[0] = headers
# reiterate to ensure the response started,
# but drop any data on the floor
close_if_possible(reiterate(self.app(subenv, _start_response)))
return substatus[0], subheaders[0]
示例9: __call__
def __call__(self, env, start_response):
"""
Main hook into the WSGI paste.deploy filter/app pipeline.
:param env: The WSGI environment dict.
:param start_response: The WSGI start_response hook.
:returns: Response as per WSGI.
"""
if env['REQUEST_METHOD'] == 'OPTIONS':
return self.app(env, start_response)
temp_url_sig, temp_url_expires, filename = self._get_temp_url_info(env)
if temp_url_sig is None and temp_url_expires is None:
return self.app(env, start_response)
if not temp_url_sig or not temp_url_expires:
return self._invalid(env, start_response)
account = self._get_account(env)
if not account:
return self._invalid(env, start_response)
keys = self._get_keys(env, account)
if not keys:
return self._invalid(env, start_response)
if env['REQUEST_METHOD'] == 'HEAD':
hmac_vals = (self._get_hmacs(env, temp_url_expires, keys,
request_method='GET') +
self._get_hmacs(env, temp_url_expires, keys,
request_method='PUT'))
else:
hmac_vals = self._get_hmacs(env, temp_url_expires, keys)
# While it's true that any() will short-circuit, this doesn't affect
# the timing-attack resistance since the only way this will
# short-circuit is when a valid signature is passed in.
is_valid_hmac = any(streq_const_time(temp_url_sig, h)
for h in hmac_vals)
if not is_valid_hmac:
return self._invalid(env, start_response)
self._clean_incoming_headers(env)
env['swift.authorize'] = lambda req: None
env['swift.authorize_override'] = True
env['REMOTE_USER'] = '.wsgi.tempurl'
qs = {'temp_url_sig': temp_url_sig,
'temp_url_expires': temp_url_expires}
if filename:
qs['filename'] = filename
env['QUERY_STRING'] = urlencode(qs)
def _start_response(status, headers, exc_info=None):
headers = self._clean_outgoing_headers(headers)
if env['REQUEST_METHOD'] == 'GET' and status[0] == '2':
already = False
for h, v in headers:
if h.lower() == 'content-disposition':
already = True
break
if already and filename:
headers = list((h, v) for h, v in headers
if h.lower() != 'content-disposition')
already = False
if not already:
name = filename or basename(env['PATH_INFO'].rstrip('/'))
headers.append((
'Content-Disposition',
'attachment; filename="%s"' % (
name.replace('"', '\\"'))))
return start_response(status, headers, exc_info)
return self.app(env, _start_response)
示例10: __call__
def __call__(self, env, start_response):
"""
Main hook into the WSGI paste.deploy filter/app pipeline.
:param env: The WSGI environment dict.
:param start_response: The WSGI start_response hook.
:returns: Response as per WSGI.
"""
if env['REQUEST_METHOD'] == 'OPTIONS':
return self.app(env, start_response)
info = self._get_temp_url_info(env)
temp_url_sig, temp_url_expires, filename, inline_disposition = info
if temp_url_sig is None and temp_url_expires is None:
return self.app(env, start_response)
if not temp_url_sig or not temp_url_expires:
return self._invalid(env, start_response)
account = self._get_account(env)
if not account:
return self._invalid(env, start_response)
keys = self._get_keys(env, account)
if not keys:
return self._invalid(env, start_response)
if env['REQUEST_METHOD'] == 'HEAD':
hmac_vals = (
self._get_hmacs(env, temp_url_expires, keys) +
self._get_hmacs(env, temp_url_expires, keys,
request_method='GET') +
self._get_hmacs(env, temp_url_expires, keys,
request_method='POST') +
self._get_hmacs(env, temp_url_expires, keys,
request_method='PUT'))
else:
hmac_vals = self._get_hmacs(env, temp_url_expires, keys)
# While it's true that any() will short-circuit, this doesn't affect
# the timing-attack resistance since the only way this will
# short-circuit is when a valid signature is passed in.
is_valid_hmac = any(streq_const_time(temp_url_sig, hmac)
for hmac in hmac_vals)
if not is_valid_hmac:
return self._invalid(env, start_response)
self._clean_incoming_headers(env)
env['swift.authorize'] = lambda req: None
env['swift.authorize_override'] = True
env['REMOTE_USER'] = '.wsgi.tempurl'
qs = {'temp_url_sig': temp_url_sig,
'temp_url_expires': temp_url_expires}
if filename:
qs['filename'] = filename
env['QUERY_STRING'] = urlencode(qs)
def _start_response(status, headers, exc_info=None):
headers = self._clean_outgoing_headers(headers)
if env['REQUEST_METHOD'] == 'GET' and status[0] == '2':
# figure out the right value for content-disposition
# 1) use the value from the query string
# 2) use the value from the object metadata
# 3) use the object name (default)
out_headers = []
existing_disposition = None
for h, v in headers:
if h.lower() != 'content-disposition':
out_headers.append((h, v))
else:
existing_disposition = v
if inline_disposition:
disposition_value = 'inline'
elif filename:
disposition_value = disposition_format(filename)
elif existing_disposition:
disposition_value = existing_disposition
else:
name = basename(env['PATH_INFO'].rstrip('/'))
disposition_value = disposition_format(name)
# this is probably just paranoia, I couldn't actually get a
# newline into existing_disposition
value = disposition_value.replace('\n', '%0A')
out_headers.append(('Content-Disposition', value))
headers = out_headers
return start_response(status, headers, exc_info)
return self.app(env, _start_response)
示例11: __call__
def __call__(self, req):
if not self.allow_full_urls:
sync_to = req.headers.get('x-container-sync-to')
if sync_to and not sync_to.startswith('//'):
raise HTTPBadRequest(
body='Full URLs are not allowed for X-Container-Sync-To '
'values. Only realm values of the format '
'//realm/cluster/account/container are allowed.\n',
request=req)
auth = req.headers.get('x-container-sync-auth')
if auth:
valid = False
auth = auth.split()
if len(auth) != 3:
req.environ.setdefault('swift.log_info', []).append(
'cs:not-3-args')
else:
realm, nonce, sig = auth
realm_key = self.realms_conf.key(realm)
realm_key2 = self.realms_conf.key2(realm)
if not realm_key:
req.environ.setdefault('swift.log_info', []).append(
'cs:no-local-realm-key')
else:
info = get_container_info(
req.environ, self.app, swift_source='CS')
user_key = info.get('sync_key')
if not user_key:
req.environ.setdefault('swift.log_info', []).append(
'cs:no-local-user-key')
else:
# x-timestamp headers get shunted by gatekeeper
if 'x-backend-inbound-x-timestamp' in req.headers:
req.headers['x-timestamp'] = req.headers.pop(
'x-backend-inbound-x-timestamp')
expected = self.realms_conf.get_sig(
req.method, req.path,
req.headers.get('x-timestamp', '0'), nonce,
realm_key, user_key)
expected2 = self.realms_conf.get_sig(
req.method, req.path,
req.headers.get('x-timestamp', '0'), nonce,
realm_key2, user_key) if realm_key2 else expected
if not streq_const_time(sig, expected) and \
not streq_const_time(sig, expected2):
req.environ.setdefault(
'swift.log_info', []).append('cs:invalid-sig')
else:
req.environ.setdefault(
'swift.log_info', []).append('cs:valid')
valid = True
if not valid:
exc = HTTPUnauthorized(
body='X-Container-Sync-Auth header not valid; '
'contact cluster operator for support.',
headers={'content-type': 'text/plain'},
request=req)
exc.headers['www-authenticate'] = ' '.join([
'SwiftContainerSync',
exc.www_authenticate().split(None, 1)[1]])
raise exc
else:
req.environ['swift.authorize_override'] = True
# An SLO manifest will already be in the internal manifest
# syntax and might be synced before its segments, so stop SLO
# middleware from performing the usual manifest validation.
req.environ['swift.slo_override'] = True
if req.path == '/info':
# Ensure /info requests get the freshest results
self.register_info()
return self.app
示例12: __call__
def __call__(self, env, start_response):
"""
Main hook into the WSGI paste.deploy filter/app pipeline.
:param env: The WSGI environment dict.
:param start_response: The WSGI start_response hook.
:returns: Response as per WSGI.
"""
if env["REQUEST_METHOD"] == "OPTIONS":
return self.app(env, start_response)
info = self._get_temp_url_info(env)
temp_url_sig, temp_url_expires, filename, inline_disposition = info
if temp_url_sig is None and temp_url_expires is None:
return self.app(env, start_response)
if not temp_url_sig or not temp_url_expires:
return self._invalid(env, start_response)
account, container = self._get_account_and_container(env)
if not account:
return self._invalid(env, start_response)
keys = self._get_keys(env)
if not keys:
return self._invalid(env, start_response)
if env["REQUEST_METHOD"] == "HEAD":
hmac_vals = (
self._get_hmacs(env, temp_url_expires, keys)
+ self._get_hmacs(env, temp_url_expires, keys, request_method="GET")
+ self._get_hmacs(env, temp_url_expires, keys, request_method="POST")
+ self._get_hmacs(env, temp_url_expires, keys, request_method="PUT")
)
else:
hmac_vals = self._get_hmacs(env, temp_url_expires, keys)
is_valid_hmac = False
hmac_scope = None
for hmac, scope in hmac_vals:
# While it's true that we short-circuit, this doesn't affect the
# timing-attack resistance since the only way this will
# short-circuit is when a valid signature is passed in.
if streq_const_time(temp_url_sig, hmac):
is_valid_hmac = True
hmac_scope = scope
break
if not is_valid_hmac:
return self._invalid(env, start_response)
# disallowed headers prevent accidently allowing upload of a pointer
# to data that the PUT tempurl would not otherwise allow access for.
# It should be safe to provide a GET tempurl for data that an
# untrusted client just uploaded with a PUT tempurl.
resp = self._clean_disallowed_headers(env, start_response)
if resp:
return resp
self._clean_incoming_headers(env)
if hmac_scope == ACCOUNT_SCOPE:
env["swift.authorize"] = authorize_same_account(account)
else:
env["swift.authorize"] = authorize_same_container(account, container)
env["swift.authorize_override"] = True
env["REMOTE_USER"] = ".wsgi.tempurl"
qs = {"temp_url_sig": temp_url_sig, "temp_url_expires": temp_url_expires}
if filename:
qs["filename"] = filename
env["QUERY_STRING"] = urlencode(qs)
def _start_response(status, headers, exc_info=None):
headers = self._clean_outgoing_headers(headers)
if env["REQUEST_METHOD"] == "GET" and status[0] == "2":
# figure out the right value for content-disposition
# 1) use the value from the query string
# 2) use the value from the object metadata
# 3) use the object name (default)
out_headers = []
existing_disposition = None
for h, v in headers:
if h.lower() != "content-disposition":
out_headers.append((h, v))
else:
existing_disposition = v
if inline_disposition:
disposition_value = "inline"
elif filename:
disposition_value = disposition_format(filename)
elif existing_disposition:
disposition_value = existing_disposition
else:
name = basename(env["PATH_INFO"].rstrip("/"))
disposition_value = disposition_format(name)
# this is probably just paranoia, I couldn't actually get a
# newline into existing_disposition
value = disposition_value.replace("\n", "%0A")
out_headers.append(("Content-Disposition", value))
headers = out_headers
return start_response(status, headers, exc_info)
return self.app(env, _start_response)