xiph / Icecast-Server

Icecast streaming media server (Mirror) - Please report bugs at https://gitlab.xiph.org/xiph/icecast-server/issues
https://icecast.org
GNU General Public License v2.0
471 stars 130 forks source link

URL authentication not working #16

Open simahawk opened 6 years ago

simahawk commented 6 years ago

I have icecast compiled w/ all the required to support URL auth on mounts. I create mounts on the fly using liquidsoap and I configured auth in icecast.xml as follow:

<mount type="default">
    <authentication type="url">
        <!-- this url just give you back the proper auth header w/out any check -->
        <option name="listener_add" value="http://foo/listener_added"/>
    </authentication>
</mount>

This should work only on listeners but is actually called for everything but that. EVERY http request is passed to it and prevents also admin to login. This is a raw print of POST data from icecast:

{'ip': u'x.x.x.x', 'mount': u'/assets/css/style.css', 'agent': u'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36', 'server': u'foo.com', 'client': u'2566', 'user': u'', 'pass': u'', 'action': u'listener_add', 'port': u'8000'}
{'ip': u'x.x.x.x', 'mount': u'/assets/font/FiraSans-Regular.woff', 'agent': u'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36', 'server': u'foo.com', 'client': u'2567', 'user': u'', 'pass': u'', 'action': u'listener_add', 'port': u'8000'}
{'ip': u'x.x.x.x', 'mount': u'/assets/font/FiraSans-Bold.woff', 'agent': u'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36', 'server': u'foo.com', 'client': u'2568', 'user': u'', 'pass': u'', 'action': u'listener_add', 'port': u'8000'}
{'ip': u'x.x.x.x', 'mount': u'/assets/font/FiraMono-Regular.woff', 'agent': u'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36', 'server': u'foo.com', 'client': u'2569', 'user': u'', 'pass': u'', 'action': u'listener_add', 'port': u'8000'}
{'ip': u'x.x.x.x', 'mount': u'/favicon.ico', 'agent': u'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36', 'server': u'foo.com', 'client': u'2570', 'user': u'', 'pass': u'', 'action': u'listener_add', 'port': u'8000'}

which are clearly not a "listener" request. In the error log I see:

[2017-11-10  17:41:52] EROR connection/_handle_authed_client Client (role=anonymous, username=source) not allowed to use this request method on /mount_name

for each mount point. Whereas, if I deactivate auth=url I find:

[2017-11-10  17:54:53] INFO auth/auth_add_client adding client 0x1148df0 for authentication on 0x11277a0

meaning the source credentials are ok. Am I missing anything?

ePirat commented 6 years ago

This should work only on listeners but is actually called for everything but that. EVERY http request is passed to it and prevents also admin to login.

This is expected behavior. A mountpoint can be anything, actually. Even a static file.

simahawk commented 6 years ago

ok, what about the error then? not allowed to use this request method on /mount_name -> which request method? I authorized both POST (documented) and GET (just in case), and I'm returning always the right header (which works for static resources). What it's trying to say? :)

dm8tbr commented 6 years ago

Source connections are either PUT or SOURCE, not POST. I'd need to look at the source code if you need to specify both or if PUT is sufficient. It's been a long while.

simahawk commented 6 years ago

Well, beside a SOURCE method does not exists (I'll try PUT), here we are talking about "listeners" authentication not source authentication. This is what docs say:

Listener authentication is a feature of Icecast which allows you to secure a certain mountpoint such that in order to listen, a listener must pass some verification test. With this feature, a simple pay-for-play operation (eg. user/pass), or some filtering based on the listener connection can be performed. This section will show you the basics of setting up and maintaining this component.

And regarding sources' auth (which should be handled via stream_auth):

stream_auth

Technically this does not belong to listener authentication, but due to its similarity it is explained here too. When a source connects, before anything is sent back to them, this request is processed. The default action is to reject a source unless the auth server sends back a response header which may be stated in the header option.

So, by default source auth is handled in a really simple way: "source" user + pwd specified in icecast.xml. And this works fine here... until you enable URL auth :(

Ref:https://icecast.org/docs/icecast-2.4.1/auth.html

ePirat commented 6 years ago

@dm8tbr I think @simahawk is referring to the method that Icecast will use to request the script, which indeed should be POST.

@simahawk Your error looks like you are trying to authenticate with source client credentials, this is very confusing as you are doing listener auth. Which Icecast version are you using?

simahawk commented 6 years ago
# icecast --version
Icecast 2.4.99.1

I pulled it from github and compiled it myself.

The point is that sources' auth should not be altered by enabling URL auth, at least judging from what docs say. BUT in any case, even if this is supposed to work like that: it should work, as I'm supporting all known request method and returning always the right the header w/ no check (just to test).

Still, my endpoint is not even called by source-whatsoever-handler as I don't see any request landing on it. So I don't really know who is calling what and how.

ePirat commented 6 years ago

Can you try using URL Auth for a specific mountpoint first instead of setting it as default for all mounts?

simahawk commented 6 years ago

tried. Does not work anyway... you can stream but cannot listen to it.

If you play using pure html5 player it shows you a popup for authentication -> you cannot listen.

If you go to icecast web UI you see that the mount point is locked and you can get to it only by login.

Then once you are logged in you can download the m3u but when you open it (in Totem for instace) it bumps you saying "Authentication required".

Practically the auth works only for pure http request to icecast webserver and not at stream level which would allow you to protect a streaming straight and not its icecast interface. All in all this auth thing sounds a bit broken IMO.

A side note about the requests that were failing w/ bad method: I guess that is related to the fact that Liquidsoap does also GET request to fetch metadata

172.17.0.2 - source [13/Nov/2017:18:16:57 +0000] "GET /admin/metadata HTTP/1.0" 200 396 "-" "Liquidsoap/1.1.1 (Unix; OCaml 4.01.0)" 0

and sounds like those requests are locked beforehand.

simahawk commented 6 years ago

Forgot to add the logs. This is what happens when I open the m3u file:

application side

{'ip': u'xxx.xxx.xxx.xxx', 'mount': u'/mount-foo', 'agent': u'gvfs/1.28.2', 'server': u'foo.com', 'client': u'29', 'user': u'', 'pass': u'', 'action': u'listener_add', 'port': u'8000'} 
{'ip': u'xxx.xxx.xxx.xxx', 'mount': u'/mount-foo', 'agent': u'gvfs/1.28.2', 'server': u'foo.com', 'client': u'30', 'user': u'', 'pass': u'', 'action': u'listener_add', 'port': u'8000'} 
{'ip': u'xxx.xxx.xxx.xxx', 'mount': u'/mount-foo', 'agent': u'Videos/3.18.1', 'server': u'foo.com', 'client': u'31', 'user': u'', 'pass': u'', 'action': u'listener_add', 'port': u'8000'} 

Icecast side

xxx.xxx.xxx.xxx - - [13/Nov/2017:18:37:56 +0000] "GET /mount-foo HTTP/1.1" 401 393 "-" "gvfs/1.28.2" 1
xxx.xxx.xxx.xxx - - [13/Nov/2017:18:37:59 +0000] "HEAD /mount-foo HTTP/1.1" 401 393 "-" "gvfs/1.28.2" 3
xxx.xxx.xxx.xxx - - [13/Nov/2017:18:37:59 +0000] "GET /mount-foo HTTP/1.1" 401 393 "-" "Videos/3.18.1" 3
x.x.x.x - source [13/Nov/2017:18:38:16 +0000] "GET /admin/metadata HTTP/1.0" 200 396 "-" "Liquidsoap/1.1.1 (Unix; OCaml 4.01.0)" 0

as you see GET/HEAD request get unauthorized :(

ePirat commented 6 years ago

Sorry, I am not sure what you mean, everything works as expected.

ePirat commented 6 years ago

Of course if you require auth, your players will prompt you for authentication, that's the whole point of it…

Practically the auth works only for pure http request to icecast webserver and not at stream level which would allow you to protect a streaming straight and not its icecast interface.

The authentication will be applied to the actual stream, the "login" Icecast shows you is just an authentication helper, that generates a m3u with the username/password in it already. Some players handle this fine and will play the stream, others still require you to re-enter the username and password.

as you see GET/HEAD request get unauthorized :(

As expected.

ePirat commented 6 years ago

Or do you mean that you provide a username/password combination your auth script will accept but it still fails?

simahawk commented 6 years ago

well, no: the whole point is about letting a server side endpoint decide if you can listen to something... so NO, asking for password is not what you would expect :) Also, once again, my endpoint is giving back just the auth header always, for every request -> you are (should be) always authorized.

ePirat commented 6 years ago

Also, once again, my endpoint is giving back just the auth header, always, for every request.

Oh ok, in this case it is not supposed to ask for authentication but immediately work, afaik. (The web interface will show the lock/login-form regardless)

phschafft commented 2 years ago

Does this still apply? Do we have a ticket on the official ticket system at https://gitlab.xiph.org/xiph/icecast-server/-/issues ?

Generally this sounds more like a misunderstanding/misconfiguration to me.

If there is no reaction I would close this ticket.