summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--HISTORY1
-rw-r--r--README24
-rw-r--r--server/connection.h5
-rw-r--r--server/connectionHTTP.c27
-rw-r--r--server/connectionHTTP.h5
-rw-r--r--server/server.c5
-rw-r--r--server/server.h3
-rw-r--r--streamdev-server.c23
8 files changed, 80 insertions, 13 deletions
diff --git a/HISTORY b/HISTORY
index aea9d78..b601880 100644
--- a/HISTORY
+++ b/HISTORY
@@ -1,6 +1,7 @@
VDR Plugin 'streamdev' Revision History
---------------------------------------
+- added HTTP authentication
- compatibility for VDR 1.7.1 (thanks to Udo Richter)
- added vdr-1.6.0-intcamdevices.patch (thanks to Anssi Hannula)
- fixed problem when switching from one encrypted channel to an other
diff --git a/README b/README
index c113891..b49821d 100644
--- a/README
+++ b/README
@@ -118,16 +118,20 @@ make [options, if necessary] plugins
----------------------------------
Starting with streamdev 0.4.0, all additional files are kept in a directory
-called "streamdev" inside VDR's plugin config directory. This affects in
-particular the file "streamdevhosts.conf". You will have to move it to its
-new location:
+called "streamdev" inside VDR's plugin config directory. It is the new default
+location of externremux.sh and the new place where streamdev-server expects the
+file "streamdevhosts.conf". You will have to move this file to its new location:
mv VDRCONFDIR/plugins/streamdevhosts.conf VDRCONFDIR/plugins/streamdev/
(Directory VDRCONFDIR/plugins/streamdev already exists, as you copied the
whole folder from the sources directory as suggested above, right?)
-The new default location for externremux.sh is also in this directory.
+Now check the contents of streamdevhosts.conf. Does it contain a "0.0.0.0/0"
+entry? If your VDR machine is connected to the Internet, this line gives
+*anyone* full access to streamdev, unless you took some other measures to
+prevent this (e.g. firewall). You might want to remove this line and enable
+HTTP authentication instead.
3. Usage:
@@ -205,6 +209,18 @@ externremux script.
http://hostname:3000/EXTERN;some_parameter/3
+If you want to access streamdev's HTTP server from the Internet, do *not* grant
+access for anyone by allowing any IP in "streamdevhosts.conf". Instead, pass the
+"-a" commandline option to streamdev-server. It takes a username and a password
+as argument. Clients with an IP not accepted by "streamdevhosts.conf" will then
+have to login. The VDR commandline will have to look like this:
+
+vdr ... -P 'streamdev-server -a vdr:secret' ...
+
+Note the single quotes, as otherwise "-a" will be passed to VDR and not to
+streamdev-server. The login ("vdr" in the example above) doesn't have to exist
+as a system account.
+
3.2 Usage VDR-to-VDR server:
----------------------------
diff --git a/server/connection.h b/server/connection.h
index fe828d9..69c24fe 100644
--- a/server/connection.h
+++ b/server/connection.h
@@ -1,5 +1,5 @@
/*
- * $Id: connection.h,v 1.5 2007/04/16 11:01:02 schmirl Exp $
+ * $Id: connection.h,v 1.6 2008/10/14 11:05:47 schmirl Exp $
*/
#ifndef VDR_STREAMDEV_SERVER_CONNECTION_H
@@ -47,6 +47,9 @@ public:
cServerConnection(const char *Protocol);
virtual ~cServerConnection();
+ /* If true, any client IP will be accepted */
+ virtual bool CanAuthenticate(void) { return false; }
+
/* Gets called if the client has been accepted by the core */
virtual void Welcome(void) { }
diff --git a/server/connectionHTTP.c b/server/connectionHTTP.c
index 38a82a3..2e867cf 100644
--- a/server/connectionHTTP.c
+++ b/server/connectionHTTP.c
@@ -1,11 +1,12 @@
/*
- * $Id: connectionHTTP.c,v 1.13 2008/03/28 15:11:40 schmirl Exp $
+ * $Id: connectionHTTP.c,v 1.14 2008/10/14 11:05:47 schmirl Exp $
*/
#include <ctype.h>
#include "server/connectionHTTP.h"
#include "server/menuHTTP.h"
+#include "server/server.h"
#include "server/setup.h"
cConnectionHTTP::cConnectionHTTP(void):
@@ -26,6 +27,11 @@ cConnectionHTTP::~cConnectionHTTP()
delete m_LiveStreamer;
}
+bool cConnectionHTTP::CanAuthenticate(void)
+{
+ return opt_auth != NULL;
+}
+
bool cConnectionHTTP::Command(char *Cmd)
{
Dprintf("command %s\n", Cmd);
@@ -44,6 +50,15 @@ bool cConnectionHTTP::Command(char *Cmd)
if (strncasecmp(Cmd, "Host:", 5) == 0) {
Dprintf("Host-Header\n");
m_Host = (std::string) skipspace(Cmd + 5);
+ return true;
+ }
+ else if (strncasecmp(Cmd, "Authorization:", 14) == 0) {
+ Cmd = skipspace(Cmd + 14);
+ if (strncasecmp(Cmd, "Basic", 5) == 0) {
+ Dprintf("'Authorization Basic'-Header\n");
+ m_Authorization = (std::string) skipspace(Cmd + 5);
+ return true;
+ }
}
Dprintf("header\n");
return true;
@@ -56,6 +71,16 @@ bool cConnectionHTTP::Command(char *Cmd)
bool cConnectionHTTP::ProcessRequest(void)
{
Dprintf("process\n");
+ if (!StreamdevHosts.Acceptable(RemoteIpAddr()))
+ {
+ if (!opt_auth || m_Authorization.empty() || m_Authorization.compare(opt_auth) != 0) {
+ isyslog("streamdev-server: HTTP authorization required");
+ DeferClose();
+ return Respond("HTTP/1.0 401 Authorization Required")
+ && Respond("WWW-authenticate: basic Realm=\"Streamdev-Server\")")
+ && Respond("");
+ }
+ }
if (m_Request.substr(0, 4) == "GET " && CmdGET(m_Request.substr(4))) {
switch (m_Job) {
case hjListing:
diff --git a/server/connectionHTTP.h b/server/connectionHTTP.h
index a3558ad..0548959 100644
--- a/server/connectionHTTP.h
+++ b/server/connectionHTTP.h
@@ -1,5 +1,5 @@
/*
- * $Id: connectionHTTP.h,v 1.5 2008/03/28 15:11:40 schmirl Exp $
+ * $Id: connectionHTTP.h,v 1.6 2008/10/14 11:05:48 schmirl Exp $
*/
#ifndef VDR_STREAMDEV_SERVERS_CONNECTIONHTTP_H
@@ -30,6 +30,7 @@ private:
std::string m_Request;
std::string m_Host;
+ std::string m_Authorization;
//std::map<std::string,std::string> m_Headers; TODO: later?
eHTTPStatus m_Status;
eHTTPJob m_Job;
@@ -52,6 +53,8 @@ public:
virtual void Attach(void) { if (m_LiveStreamer != NULL) m_LiveStreamer->Attach(); }
virtual void Detach(void) { if (m_LiveStreamer != NULL) m_LiveStreamer->Detach(); }
+ virtual bool CanAuthenticate(void);
+
virtual bool Command(char *Cmd);
bool CmdGET(const std::string &Opts);
diff --git a/server/server.c b/server/server.c
index 481e041..9399e61 100644
--- a/server/server.c
+++ b/server/server.c
@@ -1,5 +1,5 @@
/*
- * $Id: server.c,v 1.6 2008/04/29 07:00:54 schmirl Exp $
+ * $Id: server.c,v 1.7 2008/10/14 11:05:48 schmirl Exp $
*/
#include "server/server.h"
@@ -13,6 +13,7 @@
#include <errno.h>
cSVDRPhosts StreamdevHosts;
+char *opt_auth = NULL;
char *opt_remux = NULL;
cStreamdevServer *cStreamdevServer::m_Instance = NULL;
@@ -122,7 +123,7 @@ void cStreamdevServer::Action(void)
esyslog("streamdev: too many clients, rejecting %s:%d",
client->RemoteIp().c_str(), client->RemotePort());
client->Reject();
- } else if (!StreamdevHosts.Acceptable(client->RemoteIpAddr())) {
+ } else if (!client->CanAuthenticate() && !StreamdevHosts.Acceptable(client->RemoteIpAddr())) {
esyslog("streamdev: client %s:%d not allowed to connect",
client->RemoteIp().c_str(), client->RemotePort());
client->Reject();
diff --git a/server/server.h b/server/server.h
index c32fe09..339a05d 100644
--- a/server/server.h
+++ b/server/server.h
@@ -1,5 +1,5 @@
/*
- * $Id: server.h,v 1.4 2008/04/29 07:00:54 schmirl Exp $
+ * $Id: server.h,v 1.5 2008/10/14 11:05:48 schmirl Exp $
*/
#ifndef VDR_STREAMDEV_SERVER_H
@@ -13,6 +13,7 @@
#define DEFAULT_EXTERNREMUX (*AddDirectory(cPlugin::ConfigDirectory(PLUGIN_NAME_I18N), "externremux.sh"))
#define STREAMDEVHOSTSPATH (*AddDirectory(cPlugin::ConfigDirectory(PLUGIN_NAME_I18N), "streamdevhosts.conf"))
+extern char *opt_auth;
extern char *opt_remux;
class cStreamdevServer: public cThread {
diff --git a/streamdev-server.c b/streamdev-server.c
index 9892cb2..6b4ff6f 100644
--- a/streamdev-server.c
+++ b/streamdev-server.c
@@ -3,10 +3,11 @@
*
* See the README file for copyright information and how to reach the author.
*
- * $Id: streamdev-server.c,v 1.10 2008/10/13 11:30:05 schmirl Exp $
+ * $Id: streamdev-server.c,v 1.11 2008/10/14 11:05:47 schmirl Exp $
*/
#include <getopt.h>
+#include <vdr/tools.h>
#include "remux/extern.h"
#include "streamdev-server.h"
#include "server/setup.h"
@@ -25,6 +26,7 @@ cPluginStreamdevServer::cPluginStreamdevServer(void)
cPluginStreamdevServer::~cPluginStreamdevServer()
{
+ free(opt_auth);
free(opt_remux);
}
@@ -36,20 +38,35 @@ const char *cPluginStreamdevServer::Description(void)
const char *cPluginStreamdevServer::CommandLineHelp(void)
{
// return a string that describes all known command line options.
- return " -r <CMD>, --remux=<CMD> Define an external command for remuxing.\n";
+ return
+ " -a <LOGIN:PASSWORD>, --auth=<LOGIN:PASSWORD> Credentials for HTTP authentication.\n"
+ " -r <CMD>, --remux=<CMD> Define an external command for remuxing.\n"
+ ;
}
bool cPluginStreamdevServer::ProcessArgs(int argc, char *argv[])
{
// implement command line argument processing here if applicable.
static const struct option long_options[] = {
+ { "auth", required_argument, NULL, 'a' },
{ "remux", required_argument, NULL, 'r' },
{ NULL, 0, NULL, 0 }
};
int c;
- while((c = getopt_long(argc, argv, "r:", long_options, NULL)) != -1) {
+ while((c = getopt_long(argc, argv, "a:r:", long_options, NULL)) != -1) {
switch (c) {
+ case 'a':
+ {
+ if (opt_auth)
+ free(opt_auth);
+ int l = strlen(optarg);
+ cBase64Encoder Base64((uchar*) optarg, l, l * 4 / 3 + 3);
+ const char *s = Base64.NextLine();
+ if (s)
+ opt_auth = strdup(s);
+ }
+ break;
case 'r':
if (opt_remux)
free(opt_remux);