Use constant time comparison for http authentication (#1804)
In order to prevent a potential timing attack, it's important to make sure the password check takes the same amount of time, regardless of how many characters in the candidate password match the real password. This commit does increase the verbosity of the authentication check. Generally it is a good idea for authentication logic to be very clear, even if that requires some extra verbosity.
This commit is contained in:
parent
0018d2b3f5
commit
80d6e9f08f
1 changed files with 17 additions and 6 deletions
|
@ -5,6 +5,7 @@ For more details about the RESTful API, please refer to the documentation at
|
||||||
https://home-assistant.io/developers/api/
|
https://home-assistant.io/developers/api/
|
||||||
"""
|
"""
|
||||||
import gzip
|
import gzip
|
||||||
|
import hmac
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import ssl
|
import ssl
|
||||||
|
@ -200,12 +201,22 @@ class RequestHandler(SimpleHTTPRequestHandler):
|
||||||
"Error parsing JSON", HTTP_UNPROCESSABLE_ENTITY)
|
"Error parsing JSON", HTTP_UNPROCESSABLE_ENTITY)
|
||||||
return
|
return
|
||||||
|
|
||||||
self.authenticated = (self.server.api_password is None or
|
if self.verify_session():
|
||||||
self.headers.get(HTTP_HEADER_HA_AUTH) ==
|
# The user has a valid session already
|
||||||
self.server.api_password or
|
self.authenticated = True
|
||||||
data.get(DATA_API_PASSWORD) ==
|
elif self.server.api_password is None:
|
||||||
self.server.api_password or
|
# No password is set, so everyone is authenticated
|
||||||
self.verify_session())
|
self.authenticated = True
|
||||||
|
elif hmac.compare_digest(self.headers.get(HTTP_HEADER_HA_AUTH, ''),
|
||||||
|
self.server.api_password):
|
||||||
|
# A valid auth header has been set
|
||||||
|
self.authenticated = True
|
||||||
|
elif hmac.compare_digest(data.get(DATA_API_PASSWORD, ''),
|
||||||
|
self.server.api_password):
|
||||||
|
# A valid password has been specified
|
||||||
|
self.authenticated = True
|
||||||
|
else:
|
||||||
|
self.authenticated = False
|
||||||
|
|
||||||
if '_METHOD' in data:
|
if '_METHOD' in data:
|
||||||
method = data.pop('_METHOD')
|
method = data.pop('_METHOD')
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue