agsh / onvif

ONVIF node.js implementation
http://agsh.github.io/onvif/
MIT License
696 stars 237 forks source link

HikVision "Wrong ONVIF Soap Response" Error #294

Open kjlaw89 opened 1 year ago

kjlaw89 commented 1 year ago

Hey all,

I have a client that installed a bunch of HikVision cameras. Normally these connect without any issues, but we ran into some issues this time with most of the cameras. We were getting the error "Wrong ONVIF Soap Response". It seems this is an issue with the newer firmware. We seem to be able to connect fine to cameras with the 18.12 firmware, but cameras with 19.12 are unable to connect:

image image

I added a bit of extra logging and was able to get some extra details that I hop could be useful.

First, I logged out the data that was being parsed when that error message was loaded up and got this: image

(for searchability, this message is returning "Access Error: 401 - Unauthorized")

In our code, the "Unable to reach camera" error is triggered when we get an error after calling Camera.connect(). I tracked that a bit further and was able to get a trace in place to the spot that is complaining:

Trace
    at Cam.<anonymous> (/.../node_modules/onvif/lib/cam.js:176:17)
    at Cam.<anonymous> (/.../node_modules/onvif/lib/media.js:989:15)
    at /.../node_modules/onvif/lib/utils.js:74:6
    at Parser.<anonymous> (/.../node_modules/xml2js/lib/parser.js:304:18)
    at Parser.emit (events.js:400:28)
    at Parser.emit (domain.js:475:12)
    at SAXParser.onclosetag (/.../node_modules/xml2js/lib/parser.js:262:26)
    at emit (/.../node_modules/sax/lib/sax.js:624:35)
    at emitNode (/.../node_modules/sax/lib/sax.js:629:5)
    at closeTag (/.../node_modules/sax/lib/sax.js:889:7)

From my tracking it seems that getProfiles or getVideoSources now requires authentication but something isn't working correctly with that for the newer firmware - but I'm not sure how to go about debugging further.

Unfortunately I don't have direct access to the cameras themselves, but I do have access to the code & device that are actively attempting to connect to the cameras, so if any changes are needed to get extra information or to test changes let me know and I can make them directly to try.

RogerHardiman commented 1 year ago

can you try with the latest code from github please.

getProfiles and getVideoSources have always needed authentication, so nothing new there. But this library used to parse the error string (eg Not Authorized) and not the error code (eg 401) Hik have changed the formatting of the error string (ASCII Text) which messed up this library. So I did code changes to use the error code (eg 401).

As a result the library never re-tried the API with authentication.

The fixes should have all been merged in from the "roger" branch to the master branch

kjlaw89 commented 1 year ago

Hey Roger - I just pulled the latest changes from Github directly. It does take me up to the most recent commit (the version bump to 0.6.8). But I noticed your last line mentioned that it should have changes from the roger branch but it does not appear that those changes have been merged into master yet.

I'm going to try to check the changes for that branch out specifically and see if that resolves the problem. I'll follow-up here shortly.

kjlaw89 commented 1 year ago

@RogerHardiman that seemed to do it! Installing the onvif library set to the roger branch fixed the connection.

RogerHardiman commented 1 year ago

Thanks for testing and letting me know.

RogerHardiman commented 1 year ago

The change in the code that fixed this issue is in the Master Branch and has been there since January. In your project, were you pulling in a specific version of the library in your package.json?

kjlaw89 commented 1 year ago

There was a roger branch merged in Jan. 12th, but it's not the branch that contains the particular fix that I apparently needed. You made that change March 2nd https://github.com/agsh/onvif/commit/53b95001adf7e0927fc5d14011757c5916d442b6. This particular change doesn't exist in master: https://github.com/agsh/onvif/blob/7197b2df9245fd1486efc2d5f81171ff696ee4ea/lib/cam.js#L253

But for what it's worth, the first time I pulled master I did npm install git+https://github.com/agsh/onvif.git, the second time I did git+https://github.com/agsh/onvif.git#roger

RogerHardiman commented 1 year ago

thank you for the extra pair of eyes here and helping me with the commits.

RogerHardiman commented 1 year ago

The commit from March 2nd was to try and get a D-Link camera working and Media2 API (so I could use H265 streams). It was a bit of an experiment which I don't think worked, so in the end I gave up on the pile of junk from D-Link with numerous fireware bugs. But by good fortune the fix works for you.

So there are two authentication methods in ONVIF, (a) WS-Securiry and (b) Digest Authentication. So looping back to your original posts, looks like Hik don't like WS-Security and only Digest Authentication will do. ONVIF recommended everyone use Digest in about 2012, but require the older WS-Security standard for legacy systems so we never changed (making us legacy). So I'll have another look at the patch on March 2nd and what it doe (as it was a D-Link fix) and get something over to master soon-ish.

RogerHardiman commented 1 year ago

Could you goback to the camera with 19.12 firmware and tell me what the dropdown options are where it says "Digest", just below the 19.12 version string. Thanks

kjlaw89 commented 1 year ago

The commit from March 2nd was to try and get a D-Link camera working and Media2 API (so I could use H265 streams). It was a bit of an experiment which I don't think worked, so in the end I gave up on the pile of junk from D-Link with numerous fireware bugs. But by good fortune the fix works for you.

Good fortune indeed! I guess it was by luck that you still had the branch and it was named roger, or I probably wouldn't have tried it, haha!

Could you goback to the camera with 19.12 firmware and tell me what the dropdown options are where it says "Digest", just below the 19.12 version string.

I'll check with the client that has the camera and see if he can check this setting. I know he was traveling and may not be able to access the cameras remotely currently so it might be a bit before I have this answer but I'll follow-up when I get it.

kjlaw89 commented 1 year ago

The client got back and provided this:

image

Looks like the options are:

Digest is enabled for all of the devices currently.

RogerHardiman commented 1 year ago

Many thanks

If the camera is set to Digest&ws-username token then the existing ONVIF library would have worked.

For 10+ years the library has only supported WS-Username (also called WS-Security) which was in the original ONVIF standard. Digest Authentication was added by ONVIF about 2 years after the original standard. (so still a long time ago) But this library never caught up.

So at least we understand what is going on now. Either change the cameras to include ws-username, OR use my "roger" branch with some initial 'digest' authentication code in.

kjlaw89 commented 1 year ago

We're going to start slowly swapping the cameras over to the Digest&ws option. Once we've got everything swapped over we'll attempt to run on master (0.6.8) and hopefully all will go well. It may be a bit before we reach that point - not sure if you want to close this ticket out for now and I can re-open if switching doesn't work or just leave it open until we've swapped and tested. I'll leave that up to you, but I think either way we're good for the time being.

Thanks for your help!

RogerHardiman commented 1 year ago

Quick question, then the cameras is in Digest only mode, can ONVIF Device Manager talk to it? I thought ODM only supported WS-Security but was interested to see what ODM does. Thanks

chou-007 commented 1 year ago

海康18.12及其以前的相机支持普通的WSSE认证的方式,因此直接使用gsoap中的soap_wsse_add_UsernameTokenDigest就可以完成认证,但是之后新版本的相机只支持安全的WSSE认证方式和digest认证,WSSE需要客户端和服务端时间同步,因此在使用WSSE认证方式之前需要校时。但是digest不需要。

chou-007 commented 1 year ago

ODM抓包分析发现使用的是http digest认证的方式

yuxiaolejs commented 1 year ago

海康18.12及其以前的相机支持普通的WSSE认证的方式,因此直接使用gsoap中的soap_wsse_add_UsernameTokenDigest就可以完成认证,但是之后新版本的相机只支持安全的WSSE认证方式和digest认证,WSSE需要客户端和服务端时间同步,因此在使用WSSE认证方式之前需要校时。但是digest不需要。

感谢,解决了