...
 
Commits (50)
2018-10-31 09:07 ph3-der-loewe
* Update: Changed set of default headers
* Improve compatibility with broken clients
2018-10-30 13:53 tbr
* Win32 clean up
* Removed all files related to the removed Windows UI
* Added files needed by NSIS
* Added batch file used to start icecast on Windows
* Include icecast.bat into Makefile
2018-10-28 10:42 ph3-der-loewe
* Fix: Worked around buffer overflows in URL auth's cURL interface
2018-10-27 17:42 ph3-der-loewe
* Security fix: Fixed buffer overflows in URL auth code.
* CVE-2018-18820
* Fix: Fixed a memory leak
* Fix: Removed integer overflows
2018-10-27 11:59 ph3-der-loewe
* Fix: Corrected possible bufferoverflows in format_prepare_headers()
2018-06-17 06:50 ph3-der-loewe
* Fix: Do not shut down fserve engine if not started up
* Fix: Corrected const for SSL_METHOD*.
2018-06-10 18:13 tbr
* Release preparation for Icecast 2.4.4
2018-05-26 06:15 ph3-der-loewe
* Fix: Fixed segfault in htpasswd auth if no filename is set
2018-05-08 07:24 ph3-der-loewe
* Fix: Do not report hashed user passworts in user list.
2018-05-05 07:23 Marvin Scholz
* Fix two mistakes in the default config's comments
2018-05-05 07:23 Marvin Scholz
* Add log message for succesful streamlist requests
2018-05-05 07:23 JRS
* Fix: update_from_master() for receiving HTTP/1.1
2018-05-05 07:23 tbr
* Fix: Spelling, thanks to Ukikie
2018-05-05 06:41 ph3-der-loewe
* Fix: Fixed a segfault when xsltApplyStylesheet() returns error
2018-04-21 10:30 ph3-der-loewe
* Fix: Do not segfaul on bad Opus streams
2018-04-21 10:29 ph3-der-loewe
* Fix: Corrected response and fixed TLS for 416 Request Range Not Satisfiable
responses
2018-04-21 10:13 ph3-der-loewe
* Fix: TLS for ICECAST_PROTOCOL_SHOUTCAST source clients
2018-04-16 13:42 Marvin Scholz
* Fix: global listener count could be negative under certain circumstances
Thanks a lot to Simeon Völkel (0xBD4E031CDB4043C9) for reporting
and investigating the bug.
2018-04-13 13:46 ph3-der-loewe
* Fix: Send "Content-Length: 0" on 100-continue
2018-04-13 11:18 ph3-der-loewe
* Fix: Do not send 100-continue in plain over TLS sockets
2016-12-27 11:49 ph3-der-loewe
* Fix: Added needed code to announce Opus streams as such to yp.
This fixes the situation at least for Opus. It should be checked
if the same problem applies to other codecs as well.
If so, maybe a better solution should be considered for 2.5.x.
2016-12-07 18:42 ph3-der-loewe
* Cleanup: Updated usage of global.running to be more clear
2016-12-07 18:38 ph3-der-loewe
* Fix: Avoid invalid locking in signal handlers.
2016-10-29 11:42 ph3-der-loewe
* Workaround: avoid libspeex printing warnings on Opus streams.
2016-08-15 11:51 ph3-der-loewe
* Fix: Fixed regression introduced by r19250.
This fixes the regression introduced by r19250
(461a537561580cb32dac327bae73f7e670188bd4).
The fix checks if the source client is actually
known before printing it's IP-Address.
2016-02-10 10:00 ph3-der-loewe
* Fix: do not allow unescaped strings in XML output.
2015-12-24 00:38 ph3-der-loewe
* RELEASE 2.4.3
* Windows security fix: remove trailing dots in URI
This addresses CVE-2005-0837 (sic!), which was sadly ignored after
ticket #635 got closed erroneously.
* Linux/Unix installations were never affected, Windows only release!
* Impact is low: most installations run default XSLT files and
there is nothing to be learned in such a case. Also a majority
of production Icecast servers don't run on Windows.
2015-04-08 10:07:42 dm8tbr
* RELEASE 2.4.2
* apply fix for documentation (needed by distro packaging)
2015-04-08 09:09:26 ph3-der-loewe
* Fix: Do not crash URL Auth is used with stream_auth
and no credentials are given.
This fixes a crash (NULL reference) in case URL Auth is used
and stream_auth is trigged with no credentials passed by the client.
Username and password is now set to empty strings and transmited to
the backend server this way.
See #2191 for more details and to keep track of the problem.
Closes: #2191, DEB#782120
2015-04-08 09:02:20 ph3-der-loewe
* Fix: Let util_url_escape() handle NULL parameter.
This lets util_url_escape() handle NULL passed as parameter.
In case the parameter is NULL it will also return NULL.
This patch also does some cleanup of the code such as migration
away from int and thus avoiding future failures.
2015-04-08 08:32:23 dm8tbr
* update version number to 2.4.2 in preparation for release
this will be a strict security release
2015-04-08 08:18:40 dm8tbr
* applying curl fix for win32 from master
2014-11-19 13:42:23 dm8tbr 2014-11-19 13:42:23 dm8tbr
* This is Spaaarrr^w Icecast 2.4.1! * This is Spaaarrr^w Icecast 2.4.1!
......
This diff is collapsed.
...@@ -87,9 +87,9 @@ ...@@ -87,9 +87,9 @@
</div> </div>
</xsl:for-each> </xsl:for-each>
<div id="footer"> <div id="footer">
Support icecast development at <a href="http://www.icecast.org">www.icecast.org</a> Support icecast development at <a href="https://www.icecast.org/">www.icecast.org</a>
</div> </div>
</body> </body>
</html> </html>
</xsl:template> </xsl:template>
</xsl:stylesheet> </xsl:stylesheet>
\ No newline at end of file
...@@ -53,9 +53,9 @@ ...@@ -53,9 +53,9 @@
</div> </div>
</xsl:for-each> </xsl:for-each>
<div id="footer"> <div id="footer">
Support icecast development at <a href="http://www.icecast.org">www.icecast.org</a> Support icecast development at <a href="https://www.icecast.org/">www.icecast.org</a>
</div> </div>
</body> </body>
</html> </html>
</xsl:template> </xsl:template>
</xsl:stylesheet> </xsl:stylesheet>
\ No newline at end of file
...@@ -83,9 +83,9 @@ ...@@ -83,9 +83,9 @@
</div> </div>
</xsl:for-each> </xsl:for-each>
<div id="footer"> <div id="footer">
Support icecast development at <a href="http://www.icecast.org">www.icecast.org</a> Support icecast development at <a href="https://www.icecast.org/">www.icecast.org</a>
</div> </div>
</body> </body>
</html> </html>
</xsl:template> </xsl:template>
</xsl:stylesheet> </xsl:stylesheet>
\ No newline at end of file
...@@ -31,9 +31,9 @@ ...@@ -31,9 +31,9 @@
</xsl:for-each> </xsl:for-each>
</div> </div>
<div id="footer"> <div id="footer">
Support icecast development at <a href="http://www.icecast.org">www.icecast.org</a> Support icecast development at <a href="https://www.icecast.org/">www.icecast.org</a>
</div> </div>
</body> </body>
</html> </html>
</xsl:template> </xsl:template>
</xsl:stylesheet> </xsl:stylesheet>
\ No newline at end of file
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
</div> </div>
</xsl:for-each> </xsl:for-each>
<div id="footer"> <div id="footer">
Support icecast development at <a href="http://www.icecast.org">www.icecast.org</a> Support icecast development at <a href="https://www.icecast.org/">www.icecast.org</a>
</div> </div>
</body> </body>
</html> </html>
......
...@@ -92,7 +92,7 @@ ...@@ -92,7 +92,7 @@
</xsl:for-each> </xsl:for-each>
<!--end mount point stats--> <!--end mount point stats-->
<div id="footer"> <div id="footer">
Support icecast development at <a href="http://www.icecast.org">www.icecast.org</a> Support icecast development at <a href="https://www.icecast.org/">www.icecast.org</a>
</div> </div>
</body> </body>
</html> </html>
......
...@@ -41,9 +41,9 @@ ...@@ -41,9 +41,9 @@
</div> </div>
</xsl:for-each> </xsl:for-each>
<div id="footer"> <div id="footer">
Support icecast development at <a href="http://www.icecast.org">www.icecast.org</a> Support icecast development at <a href="https://www.icecast.org/">www.icecast.org</a>
</div> </div>
</body> </body>
</html> </html>
</xsl:template> </xsl:template>
</xsl:stylesheet> </xsl:stylesheet>
\ No newline at end of file
...@@ -63,7 +63,7 @@ ...@@ -63,7 +63,7 @@
--> -->
<hostname>localhost</hostname> <hostname>localhost</hostname>
<!-- You may have multiple <listener> elements --> <!-- You may have multiple <listen-socket> elements -->
<listen-socket> <listen-socket>
<port>8000</port> <port>8000</port>
<!-- <bind-address>127.0.0.1</bind-address> --> <!-- <bind-address>127.0.0.1</bind-address> -->
...@@ -97,7 +97,7 @@ ...@@ -97,7 +97,7 @@
<!-- Relaying <!-- Relaying
You don't need this if you only have one server. You don't need this if you only have one server.
Please refer to the config for a detailed explanation. Please refer to the documentation for a detailed explanation.
--> -->
<!--<master-server>127.0.0.1</master-server>--> <!--<master-server>127.0.0.1</master-server>-->
<!--<master-server-port>8001</master-server-port>--> <!--<master-server-port>8001</master-server-port>-->
......
AC_INIT([Icecast], [2.4.1], [icecast@xiph.org]) AC_INIT([Icecast], [2.4.4], [icecast@xiph.org])
AC_PREREQ(2.54) AC_PREREQ(2.54)
AC_CONFIG_SRCDIR(src/main.c) AC_CONFIG_SRCDIR(src/main.c)
...@@ -156,6 +156,6 @@ AC_SUBST(KATE_LIBS) ...@@ -156,6 +156,6 @@ AC_SUBST(KATE_LIBS)
AC_OUTPUT([Makefile conf/Makefile src/Makefile src/avl/Makefile AC_OUTPUT([Makefile conf/Makefile src/Makefile src/avl/Makefile
src/httpp/Makefile src/thread/Makefile src/log/Makefile src/httpp/Makefile src/thread/Makefile src/log/Makefile
src/net/Makefile src/timing/Makefile doc/Makefile doc/img/Makefile src/net/Makefile src/timing/Makefile doc/Makefile doc/img/Makefile
doc/assets/Makefile doc/assets/css/Makefile doc/assets/font/Makefile doc/assets/Makefile doc/assets/css/Makefile doc/assets/font/Makefile
doc/assets/img/Makefile web/Makefile admin/Makefile win32/Makefile doc/assets/img/Makefile web/Makefile admin/Makefile win32/Makefile
win32/res/Makefile examples/Makefile]) examples/Makefile])
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
<div class="section"> <div class="section">
<h2>Icecast 2.4.1 Docs &mdash; Admin Interface</h2> <h2>Icecast 2.4.4 Docs &mdash; Admin Interface</h2>
<div class="article"> <div class="article">
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
AUTOMAKE_OPTIONS = foreign AUTOMAKE_OPTIONS = foreign
docdir = $(datadir)/doc/icecast/assets/css otherdocdir = $(docdir)/assets/css
doc_DATA = style.css otherdoc_DATA = style.css
EXTRA_DIST = $(doc_DATA) EXTRA_DIST = $(otherdoc_DATA)
...@@ -2,12 +2,12 @@ ...@@ -2,12 +2,12 @@
AUTOMAKE_OPTIONS = foreign AUTOMAKE_OPTIONS = foreign
docdir = $(datadir)/doc/icecast/assets/font otherdocdir = $(docdir)/assets/font
doc_DATA = FiraMono-Bold.eot FiraMono-Regular.eot \ otherdoc_DATA = FiraMono-Bold.eot FiraMono-Regular.eot \
FiraSans-Bold.eot FiraSans-BoldItalic.woff \ FiraSans-Bold.eot FiraSans-BoldItalic.woff \
FiraSans-Italic.eot FiraSans-Regular.eot \ FiraSans-Italic.eot FiraSans-Regular.eot \
FiraMono-Bold.woff FiraMono-Regular.woff \ FiraMono-Bold.woff FiraMono-Regular.woff \
FiraSans-BoldItalic.eot FiraSans-Bold.woff \ FiraSans-BoldItalic.eot FiraSans-Bold.woff \
FiraSans-Italic.woff FiraSans-Regular.woff FiraSans-Italic.woff FiraSans-Regular.woff
EXTRA_DIST = $(doc_DATA) EXTRA_DIST = $(otherdoc_DATA)
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
AUTOMAKE_OPTIONS = foreign AUTOMAKE_OPTIONS = foreign
docdir = $(datadir)/doc/icecast/assets/img otherdocdir = $(docdir)/assets/img
doc_DATA = xiph-community.svg otherdoc_DATA = xiph-community.svg
EXTRA_DIST = $(doc_DATA) EXTRA_DIST = $(otherdoc_DATA)
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
<div class="section"> <div class="section">
<h2>Icecast 2.4.1 Docs &mdash; Authentication</h2> <h2>Icecast 2.4.4 Docs &mdash; Authentication</h2>
<div class="article"> <div class="article">
<h3 id="listener-authentication">Listener Authentication</h3> <h3 id="listener-authentication">Listener Authentication</h3>
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
<div class="section"> <div class="section">
<h2>Icecast 2.4.1 Docs &mdash; Basic Setup</h2> <h2>Icecast 2.4.4 Docs &mdash; Basic Setup</h2>
<div class="article"> <div class="article">
<h3 id="basic-requirements">Basic Requirements</h3> <h3 id="basic-requirements">Basic Requirements</h3>
......
...@@ -16,8 +16,74 @@ ...@@ -16,8 +16,74 @@
<div class="section"> <div class="section">
<h2>Icecast 2.4.1 Docs &mdash; Changes</h2> <h2>Icecast 2.4.4 Docs &mdash; Changes</h2>
<div id="v2.4.4" class="article">
<h3 id="version-244">Version 2.4.4</h3>
<h4 id="fixes-4">Fixes</h4>
<ul>
<li><strong>Security fix</strong>: Buffer overflow in URL-auth <br />
<ul>
<li>A malicious client can send long HTTP headers, leading to a buffer overflow and potential remote code execution.</li>
<li>The issue has been assigned CVE-2018-18820.</li>
<li>An Icecast server (version &lt;2.4.4) is only vulnerable if a &lt;mount&gt; definition exists that enables URL authentication.</li>
<li>The problematic code exists since version 2.4.0 and was now brought to our attention by Nick Rolfe of <a href="https://lgtm.com/security">Semmle Security Research Team</a></li>
</ul>
<li>Fixed segfault in htpasswd auth, if no filename was set</li>
<li>Do not report hashed user passwords in user list</li>
<li>Fix two mistakes in the default config's comments</li>
<li>Add log message for succesful streamlist requests</li>
<li>Fix update_from_master() for receiving HTTP/1.1</li>
<li>Spelling fix, thanks to Ukikie</li>
<li>Fixed a segfault when xsltApplyStylesheet() returns error</li>
<li>Fixed segfault on bad Opus streams</li>
<li>Corrected response and fixed TLS for 416 Request Range Not Satisfiable responses</li>
</ul>
<h4 id="known-issues-3">Known issues</h4>
<ul>
<li>See <a href="#known-issues">2.4.1</a></li>
</ul>
</div>
<div id="v2.4.3" class="article">
<h3 id="version-243">Version 2.4.3</h3>
<h4 id="fixes-3">Fixes</h4>
<ul>
<li><strong>Security fix</strong>: Windows - remove trailing dots in URI. <br /> A quirk in the Windows API made it possible to request the raw stylesheet file from webroot. Only XSLT files are affected, no internal state data is available this way. <br /> This addresses CVE-2005-0837 (sic!), which was sadly ignored after the initial ticket got closed erroneously.</li>
<li><strong>Expected impact is low</strong>: most installations run with default XSLT files and there is nothing new to be learned in such a case. Also a majority of production Icecast servers don't run on Windows to start with.</li>
<li><strong>Linux/Unix installations were never affected, this is a Windows only release!</strong></li>
</li>
</ul>
<h4 id="known-issues-3">Known issues</h4>
<ul>
<li>See <a href="#known-issues">2.4.1</a></li>
</ul>
</div>
<div id="v2.4.2" class="article">
<h3 id="version-242">Version 2.4.2</h3>
<h4 id="fixes-2">Fixes</h4>
<ul>
<li><strong>Security fix</strong>: Do not crash if URL Auth is used with stream_auth.</li>
</ul>
<h4 id="known-issues-2">Known issues</h4>
<ul>
<li>See <a href="#known-issues">2.4.1</a></li>
</ul>
</div>
<div id="v2.4.1" class="article"> <div id="v2.4.1" class="article">
<h3 id="version-241">Version 2.4.1</h3> <h3 id="version-241">Version 2.4.1</h3>
...@@ -134,4 +200,4 @@ This allows you to define a global set of defaults for ALL mounts. This way you ...@@ -134,4 +200,4 @@ This allows you to define a global set of defaults for ALL mounts. This way you
</div> </div>
</body> </body>
</html> </html>
\ No newline at end of file
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
<div class="section"> <div class="section">
<h2>Icecast 2.4.1 Docs &mdash; Config File</h2> <h2>Icecast 2.4.4 Docs &mdash; Config File</h2>
<div class="article"> <div class="article">
<h3 id="overview">Overview</h3> <h3 id="overview">Overview</h3>
...@@ -168,7 +168,7 @@ The value for this setting is provided by the owner of the Directory server.</dd ...@@ -168,7 +168,7 @@ The value for this setting is provided by the owner of the Directory server.</dd
<span class="nt">&lt;location&gt;</span>earth<span class="nt">&lt;/location&gt;</span> <span class="nt">&lt;location&gt;</span>earth<span class="nt">&lt;/location&gt;</span>
<span class="nt">&lt;admin&gt;</span>icemaster@localhost<span class="nt">&lt;/admin&gt;</span> <span class="nt">&lt;admin&gt;</span>icemaster@localhost<span class="nt">&lt;/admin&gt;</span>
<span class="nt">&lt;fileserve&gt;</span>1<span class="nt">&lt;/fileserve&gt;</span> <span class="nt">&lt;fileserve&gt;</span>1<span class="nt">&lt;/fileserve&gt;</span>
<span class="nt">&lt;server-id&gt;</span>icecast 2.4.1<span class="nt">&lt;/server-id&gt;</span></code></pre></div> <span class="nt">&lt;server-id&gt;</span>icecast 2.4.4<span class="nt">&lt;/server-id&gt;</span></code></pre></div>
<dl> <dl>
<dt>hostname</dt> <dt>hostname</dt>
...@@ -488,7 +488,8 @@ There is also a <a href="auth.html#stream-auth">URL based authentication method< ...@@ -488,7 +488,8 @@ There is also a <a href="auth.html#stream-auth">URL based authentication method<
<dt>max-listeners</dt> <dt>max-listeners</dt>
<dd>An optional value which will set the maximum number of listeners that can be attached to this mountpoint.</dd> <dd>An optional value which will set the maximum number of listeners that can be attached to this mountpoint.</dd>
<dt>max-listener-duration</dt> <dt>max-listener-duration</dt>
<dd>An optional value which will set the length of time a listener will stay connected to the stream.<br /> <dd>An optional value which will set the length of time a listener will stay connected to the stream.
The time is given as integer of seconds. <br />
An auth component may override this.</dd> An auth component may override this.</dd>
<dt>dump-file</dt> <dt>dump-file</dt>
<dd>An optional value which will set the filename which will be a dump of the stream coming through <dd>An optional value which will set the filename which will be a dump of the stream coming through
...@@ -738,4 +739,4 @@ These need to be valid users on the system. Icecast must be started as root for ...@@ -738,4 +739,4 @@ These need to be valid users on the system. Icecast must be started as root for
</div> </div>
</body> </body>
</html> </html>
\ No newline at end of file
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
<div class="section"> <div class="section">
<h2>Icecast 2.4.1 Docs &mdash; FAQ</h2> <h2>Icecast 2.4.4 Docs &mdash; FAQ</h2>
<div class="article"> <div class="article">
<h3 id="general-questions">General Questions</h3> <h3 id="general-questions">General Questions</h3>
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
<div class="section"> <div class="section">
<h2>Icecast 2.4.1 Docs &mdash; Glossary</h2> <h2>Icecast 2.4.4 Docs &mdash; Glossary</h2>
<div class="article"> <div class="article">
<dl> <dl>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
AUTOMAKE_OPTIONS = foreign AUTOMAKE_OPTIONS = foreign
docdir = $(datadir)/doc/icecast/img otherdocdir = $(docdir)/img
doc_DATA = listener_auth1.png listener_auth2.png listener_auth3.png masterslave.png relay.png otherdoc_DATA = listener_auth1.png listener_auth2.png listener_auth3.png masterslave.png relay.png
EXTRA_DIST = $(doc_DATA) EXTRA_DIST = $(otherdoc_DATA)
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
<div class="section"> <div class="section">
<h2>Icecast 2.4.1 Docs &mdash; Table of Contents</h2> <h2>Icecast 2.4.4 Docs &mdash; Table of Contents</h2>
<div class="article"> <div class="article">
<h3 id="pages">Pages</h3> <h3 id="pages">Pages</h3>
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
</div> </div>
<div class="article"> <div class="article">
<h3 id="icecast-241-readme">Icecast 2.4.1 Readme</h3> <h3 id="icecast-241-readme">Icecast 2.4.4 Readme</h3>
<p>Icecast is a streaming media server which currently supports Ogg <p>Icecast is a streaming media server which currently supports Ogg
Vorbis and MP3 audio streams. It can be used to create an Internet Vorbis and MP3 audio streams. It can be used to create an Internet
radio station or a privately running jukebox and many things in radio station or a privately running jukebox and many things in
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
<div class="section"> <div class="section">
<h2>Icecast 2.4.1 Docs &mdash; Introduction</h2> <h2>Icecast 2.4.4 Docs &mdash; Introduction</h2>
<div class="article"> <div class="article">
<h3 id="what-is-icecast">What is Icecast?</h3> <h3 id="what-is-icecast">What is Icecast?</h3>
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
<div class="section"> <div class="section">
<h2>Icecast 2.4.1 Docs &mdash; Relaying</h2> <h2>Icecast 2.4.4 Docs &mdash; Relaying</h2>
<div class="article"> <div class="article">
<h3 id="overview">Overview</h3> <h3 id="overview">Overview</h3>
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
<div class="section"> <div class="section">
<h2>Icecast 2.4.1 Docs &mdash; Server Statistics</h2> <h2>Icecast 2.4.4 Docs &mdash; Server Statistics</h2>
<div class="article"> <div class="article">
<h3 id="overview">Overview</h3> <h3 id="overview">Overview</h3>
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
<div class="section"> <div class="section">
<h2>Icecast 2.4.1 Docs &mdash; Win32 Specifics</h2> <h2>Icecast 2.4.4 Docs &mdash; Win32 Specifics</h2>
<div class="article"> <div class="article">
<p>The Win32 port of Icecast 2 is a simple command line application, <p>The Win32 port of Icecast 2 is a simple command line application,
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
<div class="section"> <div class="section">
<h2>Icecast 2.4.1 Docs &mdash; YP Directories</h2> <h2>Icecast 2.4.4 Docs &mdash; YP Directories</h2>
<div class="article"> <div class="article">
<h3 id="overview">Overview</h3> <h3 id="overview">Overview</h3>
......
...@@ -58,7 +58,7 @@ int main() ...@@ -58,7 +58,7 @@ int main()
{ {
return 0; return 0;
} }
]),,[curl_ok="no"]) ]),,[curl_ok="no"],[curl_ok="yes"])
fi fi
if test "$curl_ok" = "yes"; then if test "$curl_ok" = "yes"; then
AC_MSG_RESULT(yes) AC_MSG_RESULT(yes)
......
...@@ -209,7 +209,7 @@ xmlDocPtr admin_build_sourcelist (const char *mount) ...@@ -209,7 +209,7 @@ xmlDocPtr admin_build_sourcelist (const char *mount)
xmlDocSetRootElement(doc, xmlnode); xmlDocSetRootElement(doc, xmlnode);
if (mount) { if (mount) {
xmlNewChild (xmlnode, NULL, XMLSTR("current_source"), XMLSTR(mount)); xmlNewTextChild (xmlnode, NULL, XMLSTR("current_source"), XMLSTR(mount));
} }
node = avl_get_first(global.source_tree); node = avl_get_first(global.source_tree);
...@@ -229,17 +229,17 @@ xmlDocPtr admin_build_sourcelist (const char *mount) ...@@ -229,17 +229,17 @@ xmlDocPtr admin_build_sourcelist (const char *mount)
srcnode = xmlNewChild(xmlnode, NULL, XMLSTR("source"), NULL); srcnode = xmlNewChild(xmlnode, NULL, XMLSTR("source"), NULL);
xmlSetProp(srcnode, XMLSTR("mount"), XMLSTR(source->mount)); xmlSetProp(srcnode, XMLSTR("mount"), XMLSTR(source->mount));
xmlNewChild(srcnode, NULL, XMLSTR("fallback"), xmlNewTextChild(srcnode, NULL, XMLSTR("fallback"),
(source->fallback_mount != NULL)? (source->fallback_mount != NULL)?
XMLSTR(source->fallback_mount):XMLSTR("")); XMLSTR(source->fallback_mount):XMLSTR(""));
snprintf (buf, sizeof(buf), "%lu", source->listeners); snprintf (buf, sizeof(buf), "%lu", source->listeners);
xmlNewChild(srcnode, NULL, XMLSTR("listeners"), XMLSTR(buf)); xmlNewTextChild(srcnode, NULL, XMLSTR("listeners"), XMLSTR(buf));
config = config_get_config(); config = config_get_config();
mountinfo = config_find_mount (config, source->mount, MOUNT_TYPE_NORMAL); mountinfo = config_find_mount (config, source->mount, MOUNT_TYPE_NORMAL);
if (mountinfo && mountinfo->auth) if (mountinfo && mountinfo->auth)
{ {
xmlNewChild(srcnode, NULL, XMLSTR("authenticator"), xmlNewTextChild(srcnode, NULL, XMLSTR("authenticator"),
XMLSTR(mountinfo->auth->type)); XMLSTR(mountinfo->auth->type));
} }
config_release_config(); config_release_config();
...@@ -250,9 +250,9 @@ xmlDocPtr admin_build_sourcelist (const char *mount) ...@@ -250,9 +250,9 @@ xmlDocPtr admin_build_sourcelist (const char *mount)
{ {
snprintf (buf, sizeof(buf), "%lu", snprintf (buf, sizeof(buf), "%lu",
(unsigned long)(now - source->con->con_time)); (unsigned long)(now - source->con->con_time));
xmlNewChild (srcnode, NULL, XMLSTR("Connected"), XMLSTR(buf)); xmlNewTextChild (srcnode, NULL, XMLSTR("Connected"), XMLSTR(buf));
} }
xmlNewChild (srcnode, NULL, XMLSTR("content-type"), xmlNewTextChild (srcnode, NULL, XMLSTR("content-type"),
XMLSTR(source->format->contenttype)); XMLSTR(source->format->contenttype));
} }
} }
...@@ -681,8 +681,8 @@ static void command_move_clients(client_t *client, source_t *source, ...@@ -681,8 +681,8 @@ static void command_move_clients(client_t *client, source_t *source,
memset(buf, '\000', sizeof(buf)); memset(buf, '\000', sizeof(buf));
snprintf (buf, sizeof(buf), "Clients moved from %s to %s", snprintf (buf, sizeof(buf), "Clients moved from %s to %s",
source->mount, dest_source); source->mount, dest_source);
xmlNewChild(node, NULL, XMLSTR("message"), XMLSTR(buf)); xmlNewTextChild(node, NULL, XMLSTR("message"), XMLSTR(buf));
xmlNewChild(node, NULL, XMLSTR("return"), XMLSTR("1")); xmlNewTextChild(node, NULL, XMLSTR("return"), XMLSTR("1"));
admin_send_response(doc, client, response, admin_send_response(doc, client, response,
ADMIN_XSL_RESPONSE); ADMIN_XSL_RESPONSE);
...@@ -708,7 +708,7 @@ static void command_show_listeners(client_t *client, source_t *source, ...@@ -708,7 +708,7 @@ static void command_show_listeners(client_t *client, source_t *source,
memset(buf, '\000', sizeof(buf)); memset(buf, '\000', sizeof(buf));
snprintf (buf, sizeof(buf), "%lu", source->listeners); snprintf (buf, sizeof(buf), "%lu", source->listeners);
xmlNewChild(srcnode, NULL, XMLSTR("Listeners"), XMLSTR(buf)); xmlNewTextChild(srcnode, NULL, XMLSTR("Listeners"), XMLSTR(buf));
avl_tree_rlock(source->client_tree); avl_tree_rlock(source->client_tree);
...@@ -716,22 +716,22 @@ static void command_show_listeners(client_t *client, source_t *source, ...@@ -716,22 +716,22 @@ static void command_show_listeners(client_t *client, source_t *source,
while(client_node) { while(client_node) {
current = (client_t *)client_node->key; current = (client_t *)client_node->key;
listenernode = xmlNewChild(srcnode, NULL, XMLSTR("listener"), NULL); listenernode = xmlNewChild(srcnode, NULL, XMLSTR("listener"), NULL);
xmlNewChild(listenernode, NULL, XMLSTR("IP"), XMLSTR(current->con->ip)); xmlNewTextChild(listenernode, NULL, XMLSTR("IP"), XMLSTR(current->con->ip));
userAgent = httpp_getvar(current->parser, "user-agent"); userAgent = httpp_getvar(current->parser, "user-agent");
if (userAgent) { if (userAgent) {
xmlNewChild(listenernode, NULL, XMLSTR("UserAgent"), XMLSTR(userAgent)); xmlNewTextChild(listenernode, NULL, XMLSTR("UserAgent"), XMLSTR(userAgent));
} }
else { else {
xmlNewChild(listenernode, NULL, XMLSTR("UserAgent"), XMLSTR("Unknown")); xmlNewTextChild(listenernode, NULL, XMLSTR("UserAgent"), XMLSTR("Unknown"));
} }
memset(buf, '\000', sizeof(buf)); memset(buf, '\000', sizeof(buf));
snprintf(buf, sizeof(buf), "%lu", (unsigned long)(now - current->con->con_time)); snprintf(buf, sizeof(buf), "%lu", (unsigned long)(now - current->con->con_time));
xmlNewChild(listenernode, NULL, XMLSTR("Connected"), XMLSTR(buf)); xmlNewTextChild(listenernode, NULL, XMLSTR("Connected"), XMLSTR(buf));
memset(buf, '\000', sizeof(buf)); memset(buf, '\000', sizeof(buf));
snprintf(buf, sizeof(buf)-1, "%lu", current->con->id); snprintf(buf, sizeof(buf)-1, "%lu", current->con->id);
xmlNewChild(listenernode, NULL, XMLSTR("ID"), XMLSTR(buf)); xmlNewTextChild(listenernode, NULL, XMLSTR("ID"), XMLSTR(buf));
if (current->username) { if (current->username) {
xmlNewChild(listenernode, NULL, XMLSTR("username"), XMLSTR(current->username)); xmlNewTextChild(listenernode, NULL, XMLSTR("username"), XMLSTR(current->username));
} }
client_node = avl_get_next(client_node); client_node = avl_get_next(client_node);
} }
...@@ -851,7 +851,7 @@ static void command_manageauth(client_t *client, source_t *source, ...@@ -851,7 +851,7 @@ static void command_manageauth(client_t *client, source_t *source,
if (message) { if (message) {
msgnode = xmlNewChild(node, NULL, XMLSTR("iceresponse"), NULL); msgnode = xmlNewChild(node, NULL, XMLSTR("iceresponse"), NULL);
xmlNewChild(msgnode, NULL, XMLSTR("message"), XMLSTR(message)); xmlNewTextChild(msgnode, NULL, XMLSTR("message"), XMLSTR(message));
} }
xmlDocSetRootElement(doc, node); xmlDocSetRootElement(doc, node);
...@@ -880,8 +880,8 @@ static void command_kill_source(client_t *client, source_t *source, ...@@ -880,8 +880,8 @@ static void command_kill_source(client_t *client, source_t *source,
doc = xmlNewDoc (XMLSTR("1.0")); doc = xmlNewDoc (XMLSTR("1.0"));
node = xmlNewDocNode(doc, NULL, XMLSTR("iceresponse"), NULL); node = xmlNewDocNode(doc, NULL, XMLSTR("iceresponse"), NULL);
xmlNewChild(node, NULL, XMLSTR("message"), XMLSTR("Source Removed")); xmlNewTextChild(node, NULL, XMLSTR("message"), XMLSTR("Source Removed"));
xmlNewChild(node, NULL, XMLSTR("return"), XMLSTR("1")); xmlNewTextChild(node, NULL, XMLSTR("return"), XMLSTR("1"));
xmlDocSetRootElement(doc, node); xmlDocSetRootElement(doc, node);
source->running = 0; source->running = 0;
...@@ -921,14 +921,14 @@ static void command_kill_client(client_t *client, source_t *source, ...@@ -921,14 +921,14 @@ static void command_kill_client(client_t *client, source_t *source,
listener->con->error = 1; listener->con->error = 1;
memset(buf, '\000', sizeof(buf)); memset(buf, '\000', sizeof(buf));
snprintf(buf, sizeof(buf)-1, "Client %d removed", id); snprintf(buf, sizeof(buf)-1, "Client %d removed", id);
xmlNewChild(node, NULL, XMLSTR("message"), XMLSTR(buf)); xmlNewTextChild(node, NULL, XMLSTR("message"), XMLSTR(buf));
xmlNewChild(node, NULL, XMLSTR("return"), XMLSTR("1")); xmlNewTextChild(node, NULL, XMLSTR("return"), XMLSTR("1"));
} }
else { else {
memset(buf, '\000', sizeof(buf)); memset(buf, '\000', sizeof(buf));
snprintf(buf, sizeof(buf)-1, "Client %d not found", id); snprintf(buf, sizeof(buf)-1, "Client %d not found", id);
xmlNewChild(node, NULL, XMLSTR("message"), XMLSTR(buf)); xmlNewTextChild(node, NULL, XMLSTR("message"), XMLSTR(buf));
xmlNewChild(node, NULL, XMLSTR("return"), XMLSTR("0")); xmlNewTextChild(node, NULL, XMLSTR("return"), XMLSTR("0"));
} }
admin_send_response(doc, client, response, admin_send_response(doc, client, response,
ADMIN_XSL_RESPONSE); ADMIN_XSL_RESPONSE);
...@@ -976,8 +976,8 @@ static void command_metadata(client_t *client, source_t *source, ...@@ -976,8 +976,8 @@ static void command_metadata(client_t *client, source_t *source,
if (strcmp (action, "updinfo") != 0) if (strcmp (action, "updinfo") != 0)
{ {
xmlNewChild(node, NULL, XMLSTR("message"), XMLSTR("No such action")); xmlNewTextChild(node, NULL, XMLSTR("message"), XMLSTR("No such action"));
xmlNewChild(node, NULL, XMLSTR("return"), XMLSTR("0")); xmlNewTextChild(node, NULL, XMLSTR("return"), XMLSTR("0"));
admin_send_response(doc, client, response, admin_send_response(doc, client, response,
ADMIN_XSL_RESPONSE); ADMIN_XSL_RESPONSE);
xmlFreeDoc(doc); xmlFreeDoc(doc);
...@@ -1011,17 +1011,17 @@ static void command_metadata(client_t *client, source_t *source, ...@@ -1011,17 +1011,17 @@ static void command_metadata(client_t *client, source_t *source,
} }
else else
{ {
xmlNewChild(node, NULL, XMLSTR("message"), xmlNewTextChild(node, NULL, XMLSTR("message"),
XMLSTR("Mountpoint will not accept URL updates")); XMLSTR("Mountpoint will not accept URL updates"));
xmlNewChild(node, NULL, XMLSTR("return"), XMLSTR("1")); xmlNewTextChild(node, NULL, XMLSTR("return"), XMLSTR("1"));
admin_send_response(doc, client, response, admin_send_response(doc, client, response,
ADMIN_XSL_RESPONSE); ADMIN_XSL_RESPONSE);
xmlFreeDoc(doc); xmlFreeDoc(doc);
return; return;
} }
xmlNewChild(node, NULL, XMLSTR("message"), XMLSTR("Metadata update successful")); xmlNewTextChild(node, NULL, XMLSTR("message"), XMLSTR("Metadata update successful"));
xmlNewChild(node, NULL, XMLSTR("return"), XMLSTR("1")); xmlNewTextChild(node, NULL, XMLSTR("return"), XMLSTR("1"));
admin_send_response(doc, client, response, admin_send_response(doc, client, response,
ADMIN_XSL_RESPONSE); ADMIN_XSL_RESPONSE);
xmlFreeDoc(doc); xmlFreeDoc(doc);
......
...@@ -194,6 +194,11 @@ static auth_result htpasswd_auth (auth_client *auth_user) ...@@ -194,6 +194,11 @@ static auth_result htpasswd_auth (auth_client *auth_user)
} }
htpasswd_recheckfile (htpasswd); htpasswd_recheckfile (htpasswd);
if (htpasswd->users == NULL) {
ICECAST_LOG_ERROR("No user list.");
return AUTH_FAILED;
}
thread_rwlock_rlock (&htpasswd->file_rwlock); thread_rwlock_rlock (&htpasswd->file_rwlock);
entry.name = client->username; entry.name = client->username;
if (avl_get_by_key (htpasswd->users, &entry, &result) == 0) if (avl_get_by_key (htpasswd->users, &entry, &result) == 0)
...@@ -262,8 +267,18 @@ static auth_result htpasswd_adduser (auth_t *auth, const char *username, const c ...@@ -262,8 +267,18 @@ static auth_result htpasswd_adduser (auth_t *auth, const char *username, const c
htpasswd_user entry; htpasswd_user entry;
void *result; void *result;
if (state->filename == NULL) {
ICECAST_LOG_ERROR("No filename given in options for authenticator.");
return AUTH_FAILED;
}
htpasswd_recheckfile (state); htpasswd_recheckfile (state);
if (state->filename == NULL) {
ICECAST_LOG_ERROR("No user list.");
return AUTH_FAILED;
}
thread_rwlock_wlock (&state->file_rwlock); thread_rwlock_wlock (&state->file_rwlock);
entry.name = (char*)username; entry.name = (char*)username;
...@@ -308,6 +323,17 @@ static auth_result htpasswd_deleteuser(auth_t *auth, const char *username) ...@@ -308,6 +323,17 @@ static auth_result htpasswd_deleteuser(auth_t *auth, const char *username)
struct stat file_info; struct stat file_info;
state = auth->state; state = auth->state;
if (state->filename == NULL) {
ICECAST_LOG_ERROR("No filename given in options for authenticator.");
return AUTH_FAILED;
}
if (state->users == NULL) {
ICECAST_LOG_ERROR("No user list.");
return AUTH_FAILED;
}
thread_rwlock_wlock (&state->file_rwlock); thread_rwlock_wlock (&state->file_rwlock);
passwdfile = fopen(state->filename, "rb"); passwdfile = fopen(state->filename, "rb");
...@@ -392,16 +418,25 @@ static auth_result htpasswd_userlist(auth_t *auth, xmlNodePtr srcnode) ...@@ -392,16 +418,25 @@ static auth_result htpasswd_userlist(auth_t *auth, xmlNodePtr srcnode)
state = auth->state; state = auth->state;
if (state->filename == NULL) {
ICECAST_LOG_ERROR("No filename given in options for authenticator.");
return AUTH_FAILED;
}
htpasswd_recheckfile (state); htpasswd_recheckfile (state);
if (state->users == NULL) {
ICECAST_LOG_ERROR("No user list.");
return AUTH_FAILED;
}
thread_rwlock_rlock (&state->file_rwlock); thread_rwlock_rlock (&state->file_rwlock);
node = avl_get_first (state->users); node = avl_get_first (state->users);
while (node) while (node)
{ {
htpasswd_user *user = (htpasswd_user *)node->key; htpasswd_user *user = (htpasswd_user *)node->key;
newnode = xmlNewChild (srcnode, NULL, XMLSTR("User"), NULL); newnode = xmlNewChild (srcnode, NULL, XMLSTR("User"), NULL);
xmlNewChild(newnode, NULL, XMLSTR("username"), XMLSTR(user->name)); xmlNewTextChild(newnode, NULL, XMLSTR("username"), XMLSTR(user->name));
xmlNewChild(newnode, NULL, XMLSTR("password"), XMLSTR(user->pass));
node = avl_get_next (node); node = avl_get_next (node);
} }
thread_rwlock_unlock (&state->file_rwlock); thread_rwlock_unlock (&state->file_rwlock);
......
...@@ -141,40 +141,58 @@ static int my_getpass(void *client, char *prompt, char *buffer, int buflen) ...@@ -141,40 +141,58 @@ static int my_getpass(void *client, char *prompt, char *buffer, int buflen)
static size_t handle_returned_header (void *ptr, size_t size, size_t nmemb, void *stream) static size_t handle_returned_header (void *ptr, size_t size, size_t nmemb, void *stream)
{ {
auth_client *auth_user = stream; auth_client *auth_user = stream;
unsigned bytes = size * nmemb; size_t len = size * nmemb;
client_t *client = auth_user->client; client_t *client = auth_user->client;
if (client) if (client) {
{
auth_t *auth = client->auth; auth_t *auth = client->auth;
auth_url *url = auth->state; auth_url *url = auth->state;
if (strncasecmp (ptr, url->auth_header, url->auth_header_len) == 0)
if (url->auth_header && len >= url->auth_header_len && strncasecmp(ptr, url->auth_header, url->auth_header_len) == 0)
client->authenticated = 1; client->authenticated = 1;
if (strncasecmp (ptr, url->timelimit_header, url->timelimit_header_len) == 0)
{ if (url->timelimit_header && len > url->timelimit_header_len && strncasecmp(ptr, url->timelimit_header, url->timelimit_header_len) == 0) {
const char *input = ptr;
unsigned int limit = 0; unsigned int limit = 0;
sscanf ((char *)ptr+url->timelimit_header_len, "%u\r\n", &limit);
client->con->discon_time = time(NULL) + limit; if (len >= 2 && input[len - 2] == '\r' && input[len - 1] == '\n') {
input += url->timelimit_header_len;
if (sscanf(input, "%u\r\n", &limit) == 1) {
client->con->discon_time = time(NULL) + limit;
} else {
ICECAST_LOG_ERROR("Auth backend returned invalid timeline header: Can not parse limit");
}
} else {
ICECAST_LOG_ERROR("Auth backend returned invalid timelimit header.");
}
} }
if (strncasecmp (ptr, "icecast-auth-message: ", 22) == 0)
{ if (len > 24 && strncasecmp(ptr, "icecast-auth-message: ", 22) == 0) {
char *eol; const char *input = ptr;
snprintf (url->errormsg, sizeof (url->errormsg), "%s", (char*)ptr+22); size_t copy_len = len - 24 + 1; /* length of string plus \0-termination */
eol = strchr (url->errormsg, '\r');
if (eol == NULL) if (copy_len > sizeof(url->errormsg)) {
eol = strchr (url->errormsg, '\n'); copy_len = sizeof(url->errormsg);
if (eol) }
*eol = '\0';
if (len >= 2 && input[len - 2] == '\r' && input[len - 1] == '\n') {
input += 22;
memcpy(url->errormsg, input, copy_len);
url->errormsg[copy_len-1] = 0;
} else {
ICECAST_LOG_ERROR("Auth backend returned invalid message header.");
}
} }
} }
return (int)bytes; return len;
} }
/* capture returned data, but don't do anything with it */ /* capture returned data, but don't do anything with it */
static size_t handle_returned_data (void *ptr, size_t size, size_t nmemb, void *stream) static size_t handle_returned_data (void *ptr, size_t size, size_t nmemb, void *stream)
{ {
return (int)(size*nmemb); return size * nmemb;
} }
...@@ -191,6 +209,7 @@ static auth_result url_remove_listener (auth_client *auth_user) ...@@ -191,6 +209,7 @@ static auth_result url_remove_listener (auth_client *auth_user)
char *userpwd = NULL, post [4096]; char *userpwd = NULL, post [4096];
const char *agent; const char *agent;
char *user_agent, *ipaddr; char *user_agent, *ipaddr;
int ret;
if (url->removeurl == NULL) if (url->removeurl == NULL)
return AUTH_OK; return AUTH_OK;
...@@ -223,11 +242,11 @@ static auth_result url_remove_listener (auth_client *auth_user) ...@@ -223,11 +242,11 @@ static auth_result url_remove_listener (auth_client *auth_user)
mount = util_url_escape (mountreq); mount = util_url_escape (mountreq);
ipaddr = util_url_escape (client->con->ip); ipaddr = util_url_escape (client->con->ip);
snprintf (post, sizeof (post), ret = snprintf(post, sizeof(post),
"action=listener_remove&server=%s&port=%d&client=%lu&mount=%s" "action=listener_remove&server=%s&port=%d&client=%lu&mount=%s"
"&user=%s&pass=%s&duration=%lu&ip=%s&agent=%s", "&user=%s&pass=%s&duration=%lu&ip=%s&agent=%s",
server, port, client->con->id, mount, username, server, port, client->con->id, mount, username,
password, (long unsigned)duration, ipaddr, user_agent); password, (long unsigned)duration, ipaddr, user_agent);
free (server); free (server);
free (mount); free (mount);
free (username); free (username);
...@@ -235,6 +254,11 @@ static auth_result url_remove_listener (auth_client *auth_user) ...@@ -235,6 +254,11 @@ static auth_result url_remove_listener (auth_client *auth_user)
free (ipaddr); free (ipaddr);
free (user_agent); free (user_agent);
if (ret <= 0 || ret >= sizeof(post)) {
ICECAST_LOG_ERROR("POST body too long for buffer on mount point \"%H\" client %p.", auth_user->mount, client);
return AUTH_FAILED;
}
if (strchr (url->removeurl, '@') == NULL) if (strchr (url->removeurl, '@') == NULL)
{ {
if (url->userpwd) if (url->userpwd)
...@@ -331,6 +355,11 @@ static auth_result url_add_listener (auth_client *auth_user) ...@@ -331,6 +355,11 @@ static auth_result url_add_listener (auth_client *auth_user)
free (password); free (password);
free (ipaddr); free (ipaddr);
if (post_offset <= 0 || post_offset >= sizeof(post)) {
ICECAST_LOG_ERROR("POST body too long for buffer on mount point \"%H\" client %p.", auth_user->mount, client);
return AUTH_FAILED;
}
pass_headers = NULL; pass_headers = NULL;
if (url->pass_headers) if (url->pass_headers)
pass_headers = strdup (url->pass_headers); pass_headers = strdup (url->pass_headers);
...@@ -349,15 +378,26 @@ static auth_result url_add_listener (auth_client *auth_user) ...@@ -349,15 +378,26 @@ static auth_result url_add_listener (auth_client *auth_user)
header_val = httpp_getvar (client->parser, cur_header); header_val = httpp_getvar (client->parser, cur_header);
if (header_val) if (header_val)
{ {
size_t left = sizeof(post) - post_offset;
int ret;
header_valesc = util_url_escape (header_val); header_valesc = util_url_escape (header_val);
post_offset += snprintf (post+post_offset, sizeof (post)-post_offset, "&%s%s=%s", ret = snprintf (post+post_offset, left, "&%s%s=%s",
url->prefix_headers ? url->prefix_headers : "", url->prefix_headers ? url->prefix_headers : "",
cur_header, header_valesc); cur_header, header_valesc);
free (header_valesc); free (header_valesc);
if (ret <= 0 || ret >= left) {
ICECAST_LOG_ERROR("POST body too long for buffer on mount point \"%H\" client %p.", auth_user->mount, client);
free(pass_headers);
return AUTH_FAILED;
} else {
post_offset += ret;
}
} }
cur_header = next_header; cur_header = next_header;
} }
free(pass_headers);
} }
if (strchr (url->addurl, '@') == NULL) if (strchr (url->addurl, '@') == NULL)
...@@ -418,6 +458,7 @@ static void url_stream_start (auth_client *auth_user) ...@@ -418,6 +458,7 @@ static void url_stream_start (auth_client *auth_user)
char *stream_start_url; char *stream_start_url;
int port; int port;
char post [4096]; char post [4096];
int ret;
if (url->stream_start == NULL) if (url->stream_start == NULL)
{ {
...@@ -433,11 +474,17 @@ static void url_stream_start (auth_client *auth_user) ...@@ -433,11 +474,17 @@ static void url_stream_start (auth_client *auth_user)
config_release_config (); config_release_config ();
mount = util_url_escape (auth_user->mount); mount = util_url_escape (auth_user->mount);
snprintf (post, sizeof (post), ret = snprintf(post, sizeof(post), "action=mount_add&mount=%s&server=%s&port=%d", mount, server, port);
"action=mount_add&mount=%s&server=%s&port=%d", mount, server, port);
free (server); free (server);
free (mount); free (mount);
if (ret <= 0 || ret >= sizeof(post)) {
ICECAST_LOG_ERROR("POST body too long for buffer on mount point \"%H\".", auth_user->mount);
auth_release(auth);
free(stream_start_url);
return;
}
if (strchr (url->stream_start, '@') == NULL) if (strchr (url->stream_start, '@') == NULL)
{ {
if (url->userpwd) if (url->userpwd)
...@@ -470,6 +517,7 @@ static void url_stream_end (auth_client *auth_user) ...@@ -470,6 +517,7 @@ static void url_stream_end (auth_client *auth_user)
char *stream_end_url; char *stream_end_url;
int port; int port;
char post [4096]; char post [4096];
int ret;
if (url->stream_end == NULL) if (url->stream_end == NULL)
{ {
...@@ -485,11 +533,17 @@ static void url_stream_end (auth_client *auth_user) ...@@ -485,11 +533,17 @@ static void url_stream_end (auth_client *auth_user)
config_release_config (); config_release_config ();
mount = util_url_escape (auth_user->mount); mount = util_url_escape (auth_user->mount);
snprintf (post, sizeof (post), ret = snprintf(post, sizeof(post), "action=mount_remove&mount=%s&server=%s&port=%d", mount, server, port);
"action=mount_remove&mount=%s&server=%s&port=%d", mount, server, port);
free (server); free (server);
free (mount); free (mount);
if (ret <= 0 || ret >= sizeof(post)) {
ICECAST_LOG_ERROR("POST body too long for buffer on mount point \"%H\".", auth_user->mount);
auth_release(auth);
free(stream_end_url);
return;
}
if (strchr (url->stream_end, '@') == NULL) if (strchr (url->stream_end, '@') == NULL)
{ {
if (url->userpwd) if (url->userpwd)
...@@ -519,6 +573,7 @@ static void url_stream_auth (auth_client *auth_user) ...@@ -519,6 +573,7 @@ static void url_stream_auth (auth_client *auth_user)
auth_url *url = client->auth->state; auth_url *url = client->auth->state;
char *mount, *host, *user, *pass, *ipaddr, *admin=""; char *mount, *host, *user, *pass, *ipaddr, *admin="";
char post [4096]; char post [4096];
int ret;
if (strchr (url->stream_auth, '@') == NULL) if (strchr (url->stream_auth, '@') == NULL)
{ {
...@@ -539,13 +594,23 @@ static void url_stream_auth (auth_client *auth_user) ...@@ -539,13 +594,23 @@ static void url_stream_auth (auth_client *auth_user)
host = util_url_escape (config->hostname); host = util_url_escape (config->hostname);
port = config->port; port = config->port;
config_release_config (); config_release_config ();
user = util_url_escape (client->username);
pass = util_url_escape (client->password);
ipaddr = util_url_escape (client->con->ip); ipaddr = util_url_escape (client->con->ip);
snprintf (post, sizeof (post), if (client->username) {
"action=stream_auth&mount=%s&ip=%s&server=%s&port=%d&user=%s&pass=%s%s", user = util_url_escape(client->username);
mount, ipaddr, host, port, user, pass, admin); } else {
user = strdup("");
}
if (client->password) {
pass = util_url_escape(client->password);
} else {
pass = strdup("");
}
ret = snprintf(post, sizeof(post),
"action=stream_auth&mount=%s&ip=%s&server=%s&port=%d&user=%s&pass=%s%s",
mount, ipaddr, host, port, user, pass, admin);
free (ipaddr); free (ipaddr);
free (user); free (user);
free (pass); free (pass);
...@@ -553,6 +618,12 @@ static void url_stream_auth (auth_client *auth_user) ...@@ -553,6 +618,12 @@ static void url_stream_auth (auth_client *auth_user)
free (host); free (host);
client->authenticated = 0; client->authenticated = 0;
if (ret <= 0 || ret >= sizeof(post)) {
ICECAST_LOG_ERROR("POST body too long for buffer on mount point \"%H\" client %p.", auth_user->mount, client);
return;
}
if (curl_easy_perform (url->handle)) if (curl_easy_perform (url->handle))
ICECAST_LOG_WARN("auth to server %s failed with %s", url->stream_auth, url->errormsg); ICECAST_LOG_WARN("auth to server %s failed with %s", url->stream_auth, url->errormsg);
} }
......
...@@ -183,7 +183,7 @@ int client_read_bytes (client_t *client, void *buf, unsigned len) ...@@ -183,7 +183,7 @@ int client_read_bytes (client_t *client, void *buf, unsigned len)
return bytes; return bytes;
} }
static void client_send_error(client_t *client, int status, int plain, const char *message) void client_send_error(client_t *client, int status, int plain, const char *message)
{ {
ssize_t ret; ssize_t ret;
...@@ -211,7 +211,9 @@ static void client_send_error(client_t *client, int status, int plain, const cha ...@@ -211,7 +211,9 @@ static void client_send_error(client_t *client, int status, int plain, const cha
void client_send_100(client_t *client) void client_send_100(client_t *client)
{ {
/* On demand inject a HTTP/1.1 100 Continue to make sure clients are happy */ /* On demand inject a HTTP/1.1 100 Continue to make sure clients are happy */
sock_write (client->con->sock, "HTTP/1.1 100 Continue\r\n\r\n"); static const char str[] = "HTTP/1.1 100 Continue\r\nContent-Length: 0\r\n\r\n";
const size_t len = strlen(str);
client_send_bytes(client, str, len);
} }
void client_send_400(client_t *client, const char *message) void client_send_400(client_t *client, const char *message)
......
...@@ -80,5 +80,6 @@ int client_send_bytes (client_t *client, const void *buf, unsigned len); ...@@ -80,5 +80,6 @@ int client_send_bytes (client_t *client, const void *buf, unsigned len);
int client_read_bytes (client_t *client, void *buf, unsigned len); int client_read_bytes (client_t *client, void *buf, unsigned len);
void client_set_queue (client_t *client, refbuf_t *refbuf); void client_set_queue (client_t *client, refbuf_t *refbuf);
int client_check_source_auth (client_t *client, const char *mount); int client_check_source_auth (client_t *client, const char *mount);
void client_send_error(client_t *client, int status, int plain, const char *message);
#endif /* __CLIENT_H__ */ #endif /* __CLIENT_H__ */
...@@ -194,7 +194,11 @@ static unsigned long _next_connection_id(void) ...@@ -194,7 +194,11 @@ static unsigned long _next_connection_id(void)
#ifdef HAVE_OPENSSL #ifdef HAVE_OPENSSL
static void get_ssl_certificate (ice_config_t *config) static void get_ssl_certificate (ice_config_t *config)
{ {
#if OPENSSL_VERSION_NUMBER < 0x1000114fL
SSL_METHOD *method; SSL_METHOD *method;
#else
const SSL_METHOD *method;
#endif
long ssl_opts; long ssl_opts;
ssl_ok = 0; ssl_ok = 0;
...@@ -249,7 +253,7 @@ static int connection_read_ssl (connection_t *con, void *buf, size_t len) ...@@ -249,7 +253,7 @@ static int connection_read_ssl (connection_t *con, void *buf, size_t len)
{ {
int bytes = SSL_read (con->ssl, buf, len); int bytes = SSL_read (con->ssl, buf, len);
if (bytes < 0) if (bytes <= 0)
{ {
switch (SSL_get_error (con->ssl, bytes)) switch (SSL_get_error (con->ssl, bytes))