Hyen
Hyen

Reputation: 67

ONVIF: Authentication failure with SNC-CH110 using ONVIF protocol

I've camera SNC-CH110 from Sony. Default user is 'admin' and password is 'admin' too. My big problem is with authentication.

<SOAP-ENV:Fault>
    <SOAP-ENV:Code>
        <SOAP-ENV:Value>SOAP-ENV:Sender</SOAP-ENV:Value>
        <SOAP-ENV:Subcode>
            <SOAP-ENV:Value>ter:NotAuthorized</SOAP-ENV:Value>
        </SOAP-ENV:Subcode>
    </SOAP-ENV:Code>
    <SOAP-ENV:Reason>
        <SOAP-ENV:Text xml:lang="en">Sender not Authorized</SOAP-ENV:Text>
    </SOAP-ENV:Reason>
    <SOAP-ENV:Detail>
        <SOAP-ENV:Text xml:lang="en">The action requested requires authorization and the sender is not authorized
        </SOAP-ENV:Text>
    </SOAP-ENV:Detail>
</SOAP-ENV:Fault>

According to ONVIF specification 1.02, I use “user name token profile” for authentication which is described in specification http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0.pdf or in http://www.onvif.org/Portals/0/documents/WhitePapers/ONVIF_WG-APG-Application_Programmer%27s_Guide.pdf

Below is the Script that I use to form soap request:

<?xml version="1.0" encoding="utf-8"?>
<SOAP-ENV:Envelope 
    xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope"
    xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
    xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
    xmlns:tds="http://www.onvif.org/ver10/device/wsdl">
    <SOAP-ENV:Header> 
        <Security SOAP-ENV:mustUnderstand="1" xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
            <UsernameToken> 
                <Username>admin</Username>
                <wsse:Password Type=""http://docs.oasis-open.org/wss/2004/01/oasis-200401-wssusername-token-profile-1.0#PasswordDigest"">" + hashBase64 + @"</wsse:Password> 
                <wsse:Nonce >" + Convert.ToBase64String(_nonce) + @"</wsse:Nonce> 
                <Created>" + dt + @"</Created> 
            </UsernameToken> 
        </Security> 
    </SOAP-ENV:Header>
    <SOAP-ENV:Body> 
        <tds:GetCapabilities> 
            <tds:Category>All</tds:Category> 
        </tds:GetCapabilities> 
    </SOAP-ENV:Body> 
</SOAP-ENV:Envelope>"

Here is my code for sending request:

byte[] _nonce = new byte[16];
RandomNumberGenerator rndGenerator = new RNGCryptoServiceProvider();
rndGenerator.GetBytes(_nonce);

// get other operands to the right format
string dt = DateTime.UtcNow.ToString("yyyy-MM-ddThh:mm:ss.fffZ");
byte[] time = Encoding.UTF8.GetBytes(dt);
byte[] pwd = Encoding.UTF8.GetBytes("admin");
byte[] operand = new byte[_nonce.Length + time.Length + pwd.Length];
Array.Copy(_nonce, operand, _nonce.Length);
Array.Copy(time, 0, operand, _nonce.Length, time.Length);
Array.Copy(pwd, 0, operand, _nonce.Length + time.Length, pwd.Length);

// create the hash
SHA1 sha1 = SHA1.Create();
string hashBase64 = Convert.ToBase64String(sha1.ComputeHash(operand));

XmlDocument xml = new XmlDocument();
xml.Load("../../../xml/GetCapabilities.xml");
Communication.SendTcpXml(xml.InnerXml, new Uri("http://192.168.1.25/onvif/device_service"));

I'm really confused, because I can't find a mistake. It's very interesting that when I use date, password, nonce and username from program ONVIF Device Manager (I took it via Wireshark), I'm successful. BUT I don't understand how this program hash password, because I'm doing it exactly according the specification and when I use same date, nonce and password I can't get same hashed password like this program. I will be grateful for any help, thank.

Upvotes: 6

Views: 5352

Answers (2)

andrey.ko
andrey.ko

Reputation: 862

The hash computation looks like correctly, but I found that element "Created" has wrong namespace, it should be in wsu namespace.
It is also will be more correctly to define attribute EncodingType for Nonce element with value http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary in your case.

Upvotes: 4

Naomi
Naomi

Reputation: 5486

Did you synchronize clocks between you and the camera?
You should first call the getSystemDateAndTime, record your local time, and after that, use the diff between the two when sending further requests.

getSystemDateAndTime does not require authentication, so you're clear at that point.

Upvotes: 0

Related Questions