mirror of
https://projects.vdr-developer.org/git/vdr-plugin-streamdev.git
synced 2023-10-10 19:16:51 +02:00
- added HTTP authentication (#475)
Modified Files: HISTORY README streamdev-server.c server/connection.h server/connectionHTTP.c server/connectionHTTP.h server/server.c server/server.h
This commit is contained in:
parent
992444cb67
commit
86c82c1381
1
HISTORY
1
HISTORY
@ -1,6 +1,7 @@
|
|||||||
VDR Plugin 'streamdev' Revision History
|
VDR Plugin 'streamdev' Revision History
|
||||||
---------------------------------------
|
---------------------------------------
|
||||||
|
|
||||||
|
- added HTTP authentication
|
||||||
- compatibility for VDR 1.7.1 (thanks to Udo Richter)
|
- compatibility for VDR 1.7.1 (thanks to Udo Richter)
|
||||||
- added vdr-1.6.0-intcamdevices.patch (thanks to Anssi Hannula)
|
- added vdr-1.6.0-intcamdevices.patch (thanks to Anssi Hannula)
|
||||||
- fixed problem when switching from one encrypted channel to an other
|
- fixed problem when switching from one encrypted channel to an other
|
||||||
|
24
README
24
README
@ -118,16 +118,20 @@ make [options, if necessary] plugins
|
|||||||
----------------------------------
|
----------------------------------
|
||||||
|
|
||||||
Starting with streamdev 0.4.0, all additional files are kept in a directory
|
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
|
called "streamdev" inside VDR's plugin config directory. It is the new default
|
||||||
particular the file "streamdevhosts.conf". You will have to move it to its
|
location of externremux.sh and the new place where streamdev-server expects the
|
||||||
new location:
|
file "streamdevhosts.conf". You will have to move this file to its new location:
|
||||||
|
|
||||||
mv VDRCONFDIR/plugins/streamdevhosts.conf VDRCONFDIR/plugins/streamdev/
|
mv VDRCONFDIR/plugins/streamdevhosts.conf VDRCONFDIR/plugins/streamdev/
|
||||||
|
|
||||||
(Directory VDRCONFDIR/plugins/streamdev already exists, as you copied the
|
(Directory VDRCONFDIR/plugins/streamdev already exists, as you copied the
|
||||||
whole folder from the sources directory as suggested above, right?)
|
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:
|
3. Usage:
|
||||||
@ -205,6 +209,18 @@ externremux script.
|
|||||||
|
|
||||||
http://hostname:3000/EXTERN;some_parameter/3
|
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:
|
3.2 Usage VDR-to-VDR server:
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
|
@ -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
|
#ifndef VDR_STREAMDEV_SERVER_CONNECTION_H
|
||||||
@ -47,6 +47,9 @@ public:
|
|||||||
cServerConnection(const char *Protocol);
|
cServerConnection(const char *Protocol);
|
||||||
virtual ~cServerConnection();
|
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 */
|
/* Gets called if the client has been accepted by the core */
|
||||||
virtual void Welcome(void) { }
|
virtual void Welcome(void) { }
|
||||||
|
|
||||||
|
@ -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 <ctype.h>
|
||||||
|
|
||||||
#include "server/connectionHTTP.h"
|
#include "server/connectionHTTP.h"
|
||||||
#include "server/menuHTTP.h"
|
#include "server/menuHTTP.h"
|
||||||
|
#include "server/server.h"
|
||||||
#include "server/setup.h"
|
#include "server/setup.h"
|
||||||
|
|
||||||
cConnectionHTTP::cConnectionHTTP(void):
|
cConnectionHTTP::cConnectionHTTP(void):
|
||||||
@ -26,6 +27,11 @@ cConnectionHTTP::~cConnectionHTTP()
|
|||||||
delete m_LiveStreamer;
|
delete m_LiveStreamer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool cConnectionHTTP::CanAuthenticate(void)
|
||||||
|
{
|
||||||
|
return opt_auth != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
bool cConnectionHTTP::Command(char *Cmd)
|
bool cConnectionHTTP::Command(char *Cmd)
|
||||||
{
|
{
|
||||||
Dprintf("command %s\n", Cmd);
|
Dprintf("command %s\n", Cmd);
|
||||||
@ -44,6 +50,15 @@ bool cConnectionHTTP::Command(char *Cmd)
|
|||||||
if (strncasecmp(Cmd, "Host:", 5) == 0) {
|
if (strncasecmp(Cmd, "Host:", 5) == 0) {
|
||||||
Dprintf("Host-Header\n");
|
Dprintf("Host-Header\n");
|
||||||
m_Host = (std::string) skipspace(Cmd + 5);
|
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");
|
Dprintf("header\n");
|
||||||
return true;
|
return true;
|
||||||
@ -56,6 +71,16 @@ bool cConnectionHTTP::Command(char *Cmd)
|
|||||||
bool cConnectionHTTP::ProcessRequest(void)
|
bool cConnectionHTTP::ProcessRequest(void)
|
||||||
{
|
{
|
||||||
Dprintf("process\n");
|
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))) {
|
if (m_Request.substr(0, 4) == "GET " && CmdGET(m_Request.substr(4))) {
|
||||||
switch (m_Job) {
|
switch (m_Job) {
|
||||||
case hjListing:
|
case hjListing:
|
||||||
|
@ -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
|
#ifndef VDR_STREAMDEV_SERVERS_CONNECTIONHTTP_H
|
||||||
@ -30,6 +30,7 @@ private:
|
|||||||
|
|
||||||
std::string m_Request;
|
std::string m_Request;
|
||||||
std::string m_Host;
|
std::string m_Host;
|
||||||
|
std::string m_Authorization;
|
||||||
//std::map<std::string,std::string> m_Headers; TODO: later?
|
//std::map<std::string,std::string> m_Headers; TODO: later?
|
||||||
eHTTPStatus m_Status;
|
eHTTPStatus m_Status;
|
||||||
eHTTPJob m_Job;
|
eHTTPJob m_Job;
|
||||||
@ -52,6 +53,8 @@ public:
|
|||||||
virtual void Attach(void) { if (m_LiveStreamer != NULL) m_LiveStreamer->Attach(); }
|
virtual void Attach(void) { if (m_LiveStreamer != NULL) m_LiveStreamer->Attach(); }
|
||||||
virtual void Detach(void) { if (m_LiveStreamer != NULL) m_LiveStreamer->Detach(); }
|
virtual void Detach(void) { if (m_LiveStreamer != NULL) m_LiveStreamer->Detach(); }
|
||||||
|
|
||||||
|
virtual bool CanAuthenticate(void);
|
||||||
|
|
||||||
virtual bool Command(char *Cmd);
|
virtual bool Command(char *Cmd);
|
||||||
bool CmdGET(const std::string &Opts);
|
bool CmdGET(const std::string &Opts);
|
||||||
|
|
||||||
|
@ -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"
|
#include "server/server.h"
|
||||||
@ -13,6 +13,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
cSVDRPhosts StreamdevHosts;
|
cSVDRPhosts StreamdevHosts;
|
||||||
|
char *opt_auth = NULL;
|
||||||
char *opt_remux = NULL;
|
char *opt_remux = NULL;
|
||||||
|
|
||||||
cStreamdevServer *cStreamdevServer::m_Instance = NULL;
|
cStreamdevServer *cStreamdevServer::m_Instance = NULL;
|
||||||
@ -122,7 +123,7 @@ void cStreamdevServer::Action(void)
|
|||||||
esyslog("streamdev: too many clients, rejecting %s:%d",
|
esyslog("streamdev: too many clients, rejecting %s:%d",
|
||||||
client->RemoteIp().c_str(), client->RemotePort());
|
client->RemoteIp().c_str(), client->RemotePort());
|
||||||
client->Reject();
|
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",
|
esyslog("streamdev: client %s:%d not allowed to connect",
|
||||||
client->RemoteIp().c_str(), client->RemotePort());
|
client->RemoteIp().c_str(), client->RemotePort());
|
||||||
client->Reject();
|
client->Reject();
|
||||||
|
@ -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
|
#ifndef VDR_STREAMDEV_SERVER_H
|
||||||
@ -13,6 +13,7 @@
|
|||||||
#define DEFAULT_EXTERNREMUX (*AddDirectory(cPlugin::ConfigDirectory(PLUGIN_NAME_I18N), "externremux.sh"))
|
#define DEFAULT_EXTERNREMUX (*AddDirectory(cPlugin::ConfigDirectory(PLUGIN_NAME_I18N), "externremux.sh"))
|
||||||
#define STREAMDEVHOSTSPATH (*AddDirectory(cPlugin::ConfigDirectory(PLUGIN_NAME_I18N), "streamdevhosts.conf"))
|
#define STREAMDEVHOSTSPATH (*AddDirectory(cPlugin::ConfigDirectory(PLUGIN_NAME_I18N), "streamdevhosts.conf"))
|
||||||
|
|
||||||
|
extern char *opt_auth;
|
||||||
extern char *opt_remux;
|
extern char *opt_remux;
|
||||||
|
|
||||||
class cStreamdevServer: public cThread {
|
class cStreamdevServer: public cThread {
|
||||||
|
@ -3,10 +3,11 @@
|
|||||||
*
|
*
|
||||||
* See the README file for copyright information and how to reach the author.
|
* 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 <getopt.h>
|
||||||
|
#include <vdr/tools.h>
|
||||||
#include "remux/extern.h"
|
#include "remux/extern.h"
|
||||||
#include "streamdev-server.h"
|
#include "streamdev-server.h"
|
||||||
#include "server/setup.h"
|
#include "server/setup.h"
|
||||||
@ -25,6 +26,7 @@ cPluginStreamdevServer::cPluginStreamdevServer(void)
|
|||||||
|
|
||||||
cPluginStreamdevServer::~cPluginStreamdevServer()
|
cPluginStreamdevServer::~cPluginStreamdevServer()
|
||||||
{
|
{
|
||||||
|
free(opt_auth);
|
||||||
free(opt_remux);
|
free(opt_remux);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,20 +38,35 @@ const char *cPluginStreamdevServer::Description(void)
|
|||||||
const char *cPluginStreamdevServer::CommandLineHelp(void)
|
const char *cPluginStreamdevServer::CommandLineHelp(void)
|
||||||
{
|
{
|
||||||
// return a string that describes all known command line options.
|
// 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[])
|
bool cPluginStreamdevServer::ProcessArgs(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
// implement command line argument processing here if applicable.
|
// implement command line argument processing here if applicable.
|
||||||
static const struct option long_options[] = {
|
static const struct option long_options[] = {
|
||||||
|
{ "auth", required_argument, NULL, 'a' },
|
||||||
{ "remux", required_argument, NULL, 'r' },
|
{ "remux", required_argument, NULL, 'r' },
|
||||||
{ NULL, 0, NULL, 0 }
|
{ NULL, 0, NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
int c;
|
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) {
|
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':
|
case 'r':
|
||||||
if (opt_remux)
|
if (opt_remux)
|
||||||
free(opt_remux);
|
free(opt_remux);
|
||||||
|
Loading…
Reference in New Issue
Block a user