]> www.vanbest.org Git - motioneye-debian/commitdiff
add support for HTTP basic auth
authorCalin Crisan <ccrisan@gmail.com>
Sat, 5 Aug 2017 14:17:15 +0000 (17:17 +0300)
committerCalin Crisan <ccrisan@gmail.com>
Sat, 5 Aug 2017 14:17:15 +0000 (17:17 +0300)
extra/motioneye.conf.sample
motioneye/handlers.py
motioneye/settings.py
motioneye/utils.py

index a274d5a7540f8a1b9f8981b03ec8ceb1b794391e..5a90428c90f497043c57facf6f5d2994287b2e8c 100644 (file)
@@ -89,3 +89,6 @@ timelapse_timeout 500
 
 # enable adding and removing cameras from UI
 add_remove_cameras true
+
+# enables HTTP basic authentication scheme (in addition to, not instead of the signature mechanism)
+http_basic_auth false
index bee0959221a6c1daeed290714d51e476eb3f7b5a..0baab08288e1148e2447671161777808f56200aa 100644 (file)
@@ -115,28 +115,49 @@ class BaseHandler(RequestHandler):
         username = self.get_argument('_username', None)
         signature = self.get_argument('_signature', None)
         login = self.get_argument('_login', None) == 'true'
-        if (username == main_config.get('@admin_username') and
+
+        admin_username = main_config.get('@admin_username')
+        normal_username = main_config.get('@normal_username')
+
+        admin_password = main_config.get('@admin_password')
+        normal_password = main_config.get('@normal_password')
+
+        admin_hash = hashlib.sha1(main_config['@admin_password']).hexdigest()
+        normal_hash = hashlib.sha1(main_config['@normal_password']).hexdigest()
+
+        if settings.HTTP_BASIC_AUTH and 'Authorization' in self.request.headers:
+            up = utils.parse_basic_header(self.request.headers['Authorization'])
+            if up:
+                if (up['username'] == admin_username and
+                    admin_password in (up['password'], hashlib.sha1(up['password']).hexdigest())):
+
+                    return 'admin'
+
+                if (up['username'] == normal_username and
+                    normal_password in (up['password'], hashlib.sha1(up['password']).hexdigest())):
+
+                    return 'normal'
+
+        if (username == admin_username and
             (signature == utils.compute_signature(self.request.method, self.request.uri,
-                                                  self.request.body, main_config['@admin_password']) or
+                                                  self.request.body, admin_password) or
              signature == utils.compute_signature(self.request.method, self.request.uri,
-                                                  self.request.body,
-                                                  hashlib.sha1(main_config['@admin_password']).hexdigest()))):
+                                                  self.request.body, admin_hash))):
 
             return 'admin'
         
-        elif not username and not main_config.get('@normal_password'):  # no authentication required for normal user
+        if not username and not normal_password:  # no authentication required for normal user
             return 'normal'
-        
-        elif (username == main_config.get('@normal_username') and
-              (signature == utils.compute_signature(self.request.method, self.request.uri,
-                                                    self.request.body, main_config.get('@normal_password')) or
-               signature == utils.compute_signature(self.request.method, self.request.uri,
-                                                    self.request.body,
-                                                    hashlib.sha1(main_config['@normal_password']).hexdigest()))):
+
+        if (username == normal_username and
+            (signature == utils.compute_signature(self.request.method, self.request.uri,
+                                                  self.request.body, normal_password) or
+             signature == utils.compute_signature(self.request.method, self.request.uri,
+                                                  self.request.body, normal_hash))):
 
             return 'normal'
 
-        elif username and username != '_' and login:
+        if username and username != '_' and login:
             logging.error('authentication failed for user %(user)s' % {'user': username})
 
         return None
index 10d32f45c9f23c8f679c2deab6f38b297d94d97c..999c6b8fba71243fdcf06b587d624551b9d2d492 100644 (file)
@@ -128,3 +128,6 @@ VALIDATE_CERTS = True
 # an external program to be executed whenever a password changes;
 # the program will be invoked with environment variables MEYE_USERNAME and MEYE_PASSWORD
 PASSWORD_HOOK = None
+
+# enables HTTP basic authentication scheme (in addition to, not instead of the signature mechanism)
+HTTP_BASIC_AUTH = False
index d8456e2d07064cae317902be1c3892fafcd87663..e00b3d65a444caee9b9f06f363d2f0a09164e146 100644 (file)
@@ -683,6 +683,32 @@ def build_basic_header(username, password):
     return 'Basic ' + base64.encodestring('%s:%s' % (username, password)).replace('\n', '')
 
 
+def parse_basic_header(header):
+    parts = header.split(' ', 1)
+    if len(parts) < 2:
+        return None
+
+    if parts[0].lower() != 'basic':
+        return None
+
+    encoded = parts[1]
+
+    try:
+        decoded = base64.decodestring(encoded)
+
+    except:
+        return None
+
+    parts = decoded.split(':', 1)
+    if len(parts) < 2:
+        return None
+
+    return {
+        'username': parts[0],
+        'password': parts[1]
+    }
+
+
 def build_digest_header(method, url, username, password, state):
     realm = state['realm']
     nonce = state['nonce']