To better understand this issue, I decided to find a way to capture the network traces from a smartphone or a tablet. To do so, I put my laptop's wireless card into hotspot mode and plugged the laptop into a wired Ethernet connection. It turns out that Android (including Jelly Bean) devices can't connect to wireless networks placed in this mode, but at least Apple devices can do so. I use an IPad to establish a WiFi connection to the laptop, allowing me to capture the network traces from the wireless Ethernet card.
By examining the Wireshark traces, it turns out that even though you specify RTSP port 4520, the IP Camera apps connects to port 4524 (+4 offset), which appears to accept authentication requests.
Capturing the network trace you see the following:
OPTIONS rtsp://myipcamera.example.com:4524/1 RTSP/1.0 CSeq: 1 User-Agent: IPCamViewer
When this request is given, the Samsung DVR responds with a 401 Unauthorized, a realm=, and a nonce= value:
RTSP/1.0 401 Unauthorized CSeq: 1 Date: Wed May 8 06:39:55 2013 GMT WWW-Authenticate: Digest realm="NET-i", nonce="0000000000000000000000002E923766"The next sequence includes the Authorization: Digest header. The realm value and nonce are replayed, and a response= hash is calculated.
OPTIONS rtsp://myipcamera.example.com:4524/1 RTSP/1.0 CSeq: 2 User-Agent: IPCamViewer Authorization: Digest username="johnsmith", realm="NET-i", nonce="0000000000000000000000007B719AE4", uri="rtsp://myipcamera.example.com:4524/1", response="758b43dd292609c5b6e80084aa688ac5"
How is the response= value calculated? Aparently it appears to follow the RFC2069 spec:
The documentation at the bottom of http://tools.ietf.org/html/rfc2617 shows how this digest can be calculated in the C language. The Python equivalent is shown below. Note that the OPTIONS: is used since the previous network packet uses it instead of the more typical GET/POST verb requests.
import hashlib username = "johnsmith" realm="NET-i" password="123456" uri="rtsp://myipcamera.example.com:4524/1" nonce="0000000000000000000000002E923766" ha1 = hashlib.md5("%s:%s:%s" % (username, realm, password)).hexdigest() ha2 = hashlib.md5("OPTIONS:%s" % uri).hexdigest() response = hashlib.md5("%s:%s:%s" % (ha1, nonce, ha2)).hexdigest() print responseI was able to confirm the hash value matched the one the Samsung device transmitted with this Python code. Therefore, it seems as if the Samsung device has both a proprietary way in its ActiveX control to authenticate and a more standards based to do so.