6

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.

Hyen
  • 67
  • 2
  • 6
  • I made a little Java function a while ago to compute and show the Header part (just a little test). I tested the result using SoapUI and a Hikvision camera and worked perfectly; I hope it helps: http://pastebin.com/x16Prr2J – pparescasellas Sep 05 '14 at 09:52

2 Answers2

4

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.

Aliaksandr Belik
  • 12,725
  • 6
  • 64
  • 90
andrey.ko
  • 852
  • 1
  • 7
  • 17
  • 1
    Hi, thx for respond. About namespaces, you're right. I corrected it some time ago. But it wasn't real problem. It sends ws-usernametoken right. But I've just slightly changed code and it's generate hash like that program that I mentioned above, so correct. I'm right now busy, but when I will be free, I will find that catch and I will write it here what was problem. – Hyen Apr 22 '12 at 22:08
0

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.

Aliaksandr Belik
  • 12,725
  • 6
  • 64
  • 90
Shloim
  • 5,281
  • 21
  • 36
  • What do you mean by "use the dif between the two" calls when sending future requests?? Aren't they supposed to be both using UTC?? I know I'm late, but I'd really like an answer! (: Thanks again for your time! – LoukMouk May 11 '18 at 19:27
  • 1
    Hi, I mean that since this is a camera, it is most likely that its clock is not adjusted correctly. So in order to authenticate, you need to first read its clock using `getSystemDateAndTime`, then you compare it with your clock, and calculate the time difference. The next queries you send the camera should take into account this time difference. So you should call `currentTimeMillis` (I'm assuming Java here) and offset the result by the above time difference. – Shloim May 13 '18 at 11:06
  • 1
    Look at this example (see what I do with clientTime and serverTime) https://stackoverflow.com/questions/8798419/build-soap-web-service-client-using-wsdl-documents-in-eclipse/10394687#10394687 – Shloim May 13 '18 at 11:10