motioneye-project / motioneye

A web frontend for the motion daemon.
GNU General Public License v3.0
3.87k stars 652 forks source link

RTSP Authentication - Password requires url encoding upon entering in UI #2972

Open gitteric opened 3 months ago

gitteric commented 3 months ago

Issue: When password for RTSP authentication contains special characters, motion throws errors not connecting to camera. "[ERR] [NET] netcam_rtsp_open_context: norm: Unable to open camera(Camera1): Invalid argument"

Solution: Password has to be entered url encoded in GUI. i.e. "#somepass#" -> "%23somepass%23"

All clients I've come across so far did url encode implictly, i suppose also for usernames. Only stumbled on this when fiddling with motioneye. Not sure tho how credentials are passed to motion in the background, maybe this needs to be addressed there. For now it just seems kinda odd to do that upon entering it into a ui box with asterisks...

MichaIng commented 3 months ago

Interesting. Just to be sure, you used the pre release of motionEye v0.43.1b1?

Could you check the respective motion camera config in /etc/motioneye whether the password is stored there somehow in a falsely decoded way? motion is just started with these config files, so credentials are not passed via HTTP requests or such, where encoding would be usually required. Hence it is either already stored unintentionally decoded, or it is not encoded by motion when it does its request.

Checking our code, indeed we seem to get the credentials at some point via POST request:

So I wonder whether this JSON data needs to be URL-encoded.

gitteric commented 3 months ago

Fresh install with pre version from pip, so should 0.43.1b1.

Yesterday I did check the config files. Password had no url encoding there. It is stored exactly like entered in ui. I replaced it with url encoded string which fixed my problem. Just double checked afterwards to find it also works when I enter an url encoded string in ui.

Strange was the fact motion did not throw an "authentication failed" but an "invalid argument" error. My pass contained "#"... maybe other characters behave different.

I think only urls should require url encoding X)

Since its basic auth I was thinking credentials end up base64 encoded in http headers at some point. But maybe motion passes it in url style (rtsp://user:pass@host/stream) to some underlying (ffmeg?) component

MichaIng commented 2 months ago

Indeed motion generates an URL with embedded credentials here: https://github.com/Motion-Project/motion/blob/1ff5dd6/src/netcam_rtsp.c#L1573-L1579

But I did not check whether it is URL-encoded somewhere earlier.

Strange was the fact motion did not throw an "authentication failed" but an "invalid argument" error. My pass contained "#"... maybe other characters behave different.

Would be interesting to test other characters, which do cause issues in URLs. # is used for comments, and while it do not see any inline comments in samples/templates, it is quite possible that a # without leading space renders the netcam_userpass value invalid. The issues would then not be missing URL-encoding but missing escape or special characters in motion configs. While leading # and ; are treated as comments, I do not find any explicit documentation about this, possible inline comments or other special characters, in motion docs/man pages.

What does not fit is that URL-encoding solves it, since, if the config syntax was the issue, while encoding is done, where needed, this would lead to double encoding. Or the encoding done motion-internally is clever enough to skip %-encoding pattern and double-encoding.

@Mr-Dave I hope you can clarify things for us, i.e. whether generally URL-encoding for netcam_userpass is required, or only encoding (or different escaping) of # and probably ;, which would start inline comments in motion config files. So we can fix this, escaping or encoding respective characters or the whole username and password strings.

Mr-Dave commented 2 months ago

I reviewed the code and performed some tests. Motion does not do any URL encoding of either the path (e.g. 'netcam_url') or username or password. The values entered into the configuration (including any embedded #, ;, %, spaces, etc ) are passed directly into the FFmpeg libraries.

As such, URL encoding must be done by the user. (Having it done by Motion or Motioneye would/could result in the double encoding problem referenced above)

MichaIng commented 2 months ago

It is all a question of documentation/info. In case of motionEye, the inputbox could have a clear info that no URL-encoding must be done, as it is done by motionEye internally. I see it from an end user friendliness perspective: Most users won't know about URL-encoding, which characters do need encoding, and how to do so. So I prefer telling them to not encode anything, then the other way round + expecting them to know about it or use an extra online encoder step. But when we start doing this, we must also either do a migration step (which never 100% reliable as we cannot know for sure which string is encoded or not) or inform users, that network camera passwords may need to be re-entered.

In case of motion with a CLI, where one cannot prompt info into users faces, and where other scripts/programs/frontends (like motionEye) may now rely on the behaviour, I agree that it is better to leave it as it is. But I suggest to add this info to the motion documentation 🙂.