]> www.vanbest.org Git - motioneye-debian/commitdiff
allow adding digest auth rtsp cameras (no credentials check though)
authorCalin Crisan <ccrisan@gmail.com>
Sun, 14 Aug 2016 18:12:34 +0000 (21:12 +0300)
committerCalin Crisan <ccrisan@gmail.com>
Sun, 14 Aug 2016 18:12:34 +0000 (21:12 +0300)
motioneye/utils.py

index 923901bcc93518b653aa808f4ce28902b4318b1e..98a9dc59a68b90e97dedf3c581e9f2d1851481a0 100644 (file)
@@ -430,35 +430,39 @@ def test_mjpeg_url(data, auth_modes, allow_jpeg, callback):
 def test_rtsp_url(data, callback):
     import config
     
-    data = dict(data)
-    data.setdefault('scheme', 'rtsp')
-    data.setdefault('host', '127.0.0.1')
-    data['port'] = data.get('port') or '554'
-    data.setdefault('path', '')
-    data.setdefault('username', None)
-    data.setdefault('password', None)
+    scheme = data.get('scheme', 'rtsp')
+    host = data.get('host', '127.0.0.1')
+    port = data.get('port') or '554'
+    path = data.get('path') or ''
+    username = data.get('username')
+    password = data.get('password')
 
     url = '%(scheme)s://%(host)s%(port)s%(path)s' % {
-            'scheme': data['scheme'],
-            'host': data['host'],
-            'port': ':' + str(data['port']) if data['port'] else '',
-            'path': data['path'] or ''}
+            'scheme': scheme,
+            'host': host,
+            'port': (':' + port) if port else '',
+            'path': path}
     
     called = [False]
+    send_auth = [False]
     timeout = [None]
     stream = None
     
     io_loop = IOLoop.instance()
 
     def connect():
-        logging.debug('testing rtsp netcam at %s' % url)
+        if send_auth[0]:
+            logging.debug('testing rtsp netcam at %s (this time with credentials)' % url)
+            
+        else:
+            logging.debug('testing rtsp netcam at %s' % url)
 
         s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
         s.settimeout(settings.MJPG_CLIENT_TIMEOUT)
         stream = IOStream(s)
         stream.set_close_callback(on_close)
-        stream.connect((data['host'], int(data['port'])), on_connect)
-        
+        stream.connect((host, int(port)), on_connect)
+
         timeout[0] = io_loop.add_timeout(datetime.timedelta(seconds=settings.MJPG_CLIENT_TIMEOUT),
                 functools.partial(on_connect, _timeout=True))
         
@@ -481,8 +485,8 @@ def test_rtsp_url(data, callback):
             'User-Agent: motionEye'
         ]
         
-        if data['username']:
-            auth_header = 'Authorization: ' + build_basic_header(data['username'], data['password'])
+        if username and send_auth[0]:
+            auth_header = 'Authorization: ' + build_basic_header(username, password)
             lines.append(auth_header)
 
         lines += [
@@ -507,13 +511,18 @@ def test_rtsp_url(data, callback):
         if data:
             if data.endswith('200 '):
                 seek_server()
-    
+
             elif data.endswith('401 '):
-                handle_error('authentication failed')
+                if not username or send_auth[0]:
+                    # either credentials not supplied, or already sent
+                    handle_error('authentication failed')
+
+                else:
+                    seek_www_authenticate()
 
             else:
                 handle_error('rtsp netcam returned erroneous response: %s' % data)
-        
+
         else:
             handle_error('timeout waiting for rtsp netcam response')
 
@@ -537,6 +546,31 @@ def test_rtsp_url(data, callback):
 
         handle_success(identifier)
 
+    def seek_www_authenticate():
+        if check_error():
+            return
+
+        stream.read_until_regex('WWW-Authenticate: .*', on_www_authenticate)
+        timeout[0] = io_loop.add_timeout(datetime.timedelta(seconds=1), on_www_authenticate)
+
+    def on_www_authenticate(data=None):
+        io_loop.remove_timeout(timeout[0])
+
+        if data:
+            scheme = re.findall('WWW-Authenticate: ([^\s]+)', data)[0].strip()
+            logging.debug('rtsp netcam auth scheme: %s' % scheme)
+            if scheme.lower() == 'basic':
+                send_auth[0] = True
+                connect()
+                
+            else:
+                logging.debug('rtsp auth scheme digest not supported, considering credentials ok')
+                handle_success('(unknown) ')
+
+        else:
+            logging.error('timeout waiting for rtsp auth scheme')
+            handle_error('timeout waiting for rtsp netcam response')
+
     def on_close():
         if called[0]:
             return