ACL: add more restrictive permissions for all config urls, fix the http ticket issue, fixes #2383
This commit is contained in:
parent
8d71f8ed25
commit
4b7a674e7f
20 changed files with 111 additions and 98 deletions
|
@ -1030,6 +1030,7 @@ const idclass_t access_entry_class = {
|
|||
.ic_class = "access",
|
||||
.ic_caption = "Access",
|
||||
.ic_event = "access",
|
||||
.ic_perm_def = ACCESS_ADMIN,
|
||||
.ic_save = access_entry_class_save,
|
||||
.ic_get_title = access_entry_class_get_title,
|
||||
.ic_delete = access_entry_class_delete,
|
||||
|
|
|
@ -52,9 +52,9 @@ api_access_entry_create
|
|||
void api_access_init ( void )
|
||||
{
|
||||
static api_hook_t ah[] = {
|
||||
{ "access/entry/class", ACCESS_ANONYMOUS, api_idnode_class, (void*)&access_entry_class },
|
||||
{ "access/entry/grid", ACCESS_ANONYMOUS, api_idnode_grid, api_access_entry_grid },
|
||||
{ "access/entry/create", ACCESS_ADMIN, api_access_entry_create, NULL },
|
||||
{ "access/entry/class", ACCESS_ADMIN, api_idnode_class, (void*)&access_entry_class },
|
||||
{ "access/entry/grid", ACCESS_ADMIN, api_idnode_grid, api_access_entry_grid },
|
||||
{ "access/entry/create", ACCESS_ADMIN, api_access_entry_create, NULL },
|
||||
|
||||
{ NULL },
|
||||
};
|
||||
|
|
|
@ -347,22 +347,22 @@ api_mpegts_init ( void )
|
|||
extern const idclass_t mpegts_service_class;
|
||||
|
||||
static api_hook_t ah[] = {
|
||||
{ "mpegts/input/network_list", ACCESS_ANONYMOUS, api_mpegts_input_network_list, NULL },
|
||||
{ "mpegts/network/grid", ACCESS_ANONYMOUS, api_idnode_grid, api_mpegts_network_grid },
|
||||
{ "mpegts/network/class", ACCESS_ANONYMOUS, api_idnode_class, (void*)&mpegts_network_class },
|
||||
{ "mpegts/network/builders", ACCESS_ANONYMOUS, api_mpegts_network_builders, NULL },
|
||||
{ "mpegts/network/create", ACCESS_ANONYMOUS, api_mpegts_network_create, NULL },
|
||||
{ "mpegts/network/mux_class", ACCESS_ANONYMOUS, api_mpegts_network_muxclass, NULL },
|
||||
{ "mpegts/network/mux_create", ACCESS_ANONYMOUS, api_mpegts_network_muxcreate, NULL },
|
||||
{ "mpegts/mux/grid", ACCESS_ANONYMOUS, api_idnode_grid, api_mpegts_mux_grid },
|
||||
{ "mpegts/mux/class", ACCESS_ANONYMOUS, api_idnode_class, (void*)&mpegts_mux_class },
|
||||
{ "mpegts/service/grid", ACCESS_ANONYMOUS, api_idnode_grid, api_mpegts_service_grid },
|
||||
{ "mpegts/service/class", ACCESS_ANONYMOUS, api_idnode_class, (void*)&mpegts_service_class },
|
||||
{ "mpegts/mux_sched/class", ACCESS_ANONYMOUS, api_idnode_class, (void*)&mpegts_mux_sched_class },
|
||||
{ "mpegts/mux_sched/grid", ACCESS_ANONYMOUS, api_idnode_grid, api_mpegts_mux_sched_grid },
|
||||
{ "mpegts/mux_sched/create", ACCESS_ANONYMOUS, api_mpegts_mux_sched_create, NULL },
|
||||
{ "mpegts/input/network_list", ACCESS_ADMIN, api_mpegts_input_network_list, NULL },
|
||||
{ "mpegts/network/grid", ACCESS_ADMIN, api_idnode_grid, api_mpegts_network_grid },
|
||||
{ "mpegts/network/class", ACCESS_ADMIN, api_idnode_class, (void*)&mpegts_network_class },
|
||||
{ "mpegts/network/builders", ACCESS_ADMIN, api_mpegts_network_builders, NULL },
|
||||
{ "mpegts/network/create", ACCESS_ADMIN, api_mpegts_network_create, NULL },
|
||||
{ "mpegts/network/mux_class", ACCESS_ADMIN, api_mpegts_network_muxclass, NULL },
|
||||
{ "mpegts/network/mux_create", ACCESS_ADMIN, api_mpegts_network_muxcreate, NULL },
|
||||
{ "mpegts/mux/grid", ACCESS_ADMIN, api_idnode_grid, api_mpegts_mux_grid },
|
||||
{ "mpegts/mux/class", ACCESS_ADMIN, api_idnode_class, (void*)&mpegts_mux_class },
|
||||
{ "mpegts/service/grid", ACCESS_ADMIN, api_idnode_grid, api_mpegts_service_grid },
|
||||
{ "mpegts/service/class", ACCESS_ADMIN, api_idnode_class, (void*)&mpegts_service_class },
|
||||
{ "mpegts/mux_sched/class", ACCESS_ADMIN, api_idnode_class, (void*)&mpegts_mux_sched_class },
|
||||
{ "mpegts/mux_sched/grid", ACCESS_ADMIN, api_idnode_grid, api_mpegts_mux_sched_grid },
|
||||
{ "mpegts/mux_sched/create", ACCESS_ADMIN, api_mpegts_mux_sched_create, NULL },
|
||||
#if ENABLE_MPEGTS_DVB
|
||||
{ "dvb/scanfile/list", ACCESS_ANONYMOUS, api_dvb_scanfile_list, NULL },
|
||||
{ "dvb/scanfile/list", ACCESS_ADMIN, api_dvb_scanfile_list, NULL },
|
||||
#endif
|
||||
{ NULL },
|
||||
};
|
||||
|
|
|
@ -189,9 +189,9 @@ void api_service_init ( void )
|
|||
{ "service/mapper/start", ACCESS_ADMIN, api_mapper_start, NULL },
|
||||
{ "service/mapper/stop", ACCESS_ADMIN, api_mapper_stop, NULL },
|
||||
{ "service/mapper/status", ACCESS_ADMIN, api_mapper_status, NULL },
|
||||
{ "service/list", ACCESS_ANONYMOUS, api_idnode_load_by_class,
|
||||
{ "service/list", ACCESS_ADMIN, api_idnode_load_by_class,
|
||||
(void*)&service_class },
|
||||
{ "service/streams", ACCESS_ANONYMOUS, api_service_streams, NULL },
|
||||
{ "service/streams", ACCESS_ADMIN, api_service_streams, NULL },
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "settings.h"
|
||||
#include "lang_codes.h"
|
||||
#include "service.h"
|
||||
#include "access.h"
|
||||
#include "esfilter.h"
|
||||
|
||||
struct esfilter_entry_queue esfilters[ESF_CLASS_LAST + 1];
|
||||
|
@ -588,6 +589,7 @@ const idclass_t esfilter_class = {
|
|||
.ic_class = "esfilter",
|
||||
.ic_caption = "Elementary Stream Filter",
|
||||
.ic_event = "esfilter",
|
||||
.ic_perm_def = ACCESS_ADMIN,
|
||||
.ic_save = esfilter_class_save,
|
||||
.ic_get_title = esfilter_class_get_title,
|
||||
.ic_delete = esfilter_class_delete,
|
||||
|
|
19
src/http.c
19
src/http.c
|
@ -408,22 +408,21 @@ http_redirect(http_connection_t *hc, const char *location,
|
|||
/**
|
||||
*
|
||||
*/
|
||||
static int http_access_verify_ticket(http_connection_t *hc)
|
||||
static void
|
||||
http_access_verify_ticket(http_connection_t *hc)
|
||||
{
|
||||
const char *ticket_id;
|
||||
|
||||
if (hc->hc_ticket || hc->hc_access)
|
||||
return 0;
|
||||
if (hc->hc_access)
|
||||
return;
|
||||
ticket_id = http_arg_get(&hc->hc_req_args, "ticket");
|
||||
hc->hc_access = access_ticket_verify2(ticket_id, hc->hc_url);
|
||||
if (hc->hc_access == NULL)
|
||||
return -1;
|
||||
return;
|
||||
char addrstr[50];
|
||||
tcp_get_ip_str((struct sockaddr*)hc->hc_peer, addrstr, 50);
|
||||
tvhlog(LOG_INFO, "HTTP", "%s: using ticket %s for %s",
|
||||
addrstr, ticket_id, hc->hc_url);
|
||||
hc->hc_ticket = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -432,8 +431,7 @@ static int http_access_verify_ticket(http_connection_t *hc)
|
|||
int
|
||||
http_access_verify(http_connection_t *hc, int mask)
|
||||
{
|
||||
if (!http_access_verify_ticket(hc))
|
||||
return 0;
|
||||
http_access_verify_ticket(hc);
|
||||
|
||||
if (hc->hc_access == NULL) {
|
||||
hc->hc_access = access_get(hc->hc_username, hc->hc_password,
|
||||
|
@ -456,8 +454,8 @@ http_access_verify_channel(http_connection_t *hc, int mask,
|
|||
|
||||
assert(ch);
|
||||
|
||||
if (ticket && !http_access_verify_ticket(hc))
|
||||
return 0;
|
||||
if (ticket)
|
||||
http_access_verify_ticket(hc);
|
||||
|
||||
if (hc->hc_access == NULL) {
|
||||
hc->hc_access = access_get(hc->hc_username, hc->hc_password,
|
||||
|
@ -488,7 +486,6 @@ http_exec(http_connection_t *hc, http_path_t *hp, char *remain)
|
|||
err = hp->hp_callback(hc, remain, hp->hp_opaque);
|
||||
access_destroy(hc->hc_access);
|
||||
hc->hc_access = NULL;
|
||||
hc->hc_ticket = 0;
|
||||
|
||||
if(err == -1)
|
||||
return 1;
|
||||
|
|
|
@ -132,7 +132,6 @@ typedef struct http_connection {
|
|||
char *hc_username;
|
||||
char *hc_password;
|
||||
access_t *hc_access;
|
||||
int hc_ticket;
|
||||
|
||||
struct config_head *hc_user_config;
|
||||
|
||||
|
|
16
src/idnode.c
16
src/idnode.c
|
@ -29,6 +29,7 @@
|
|||
#include "notify.h"
|
||||
#include "settings.h"
|
||||
#include "uuid.h"
|
||||
#include "access.h"
|
||||
|
||||
static const idnodes_rb_t * idnode_domain ( const idclass_t *idc );
|
||||
static void idclass_root_register ( idnode_t *in );
|
||||
|
@ -548,6 +549,21 @@ idnode_get_time
|
|||
* Lookup
|
||||
* *************************************************************************/
|
||||
|
||||
int
|
||||
idnode_perm(idnode_t *self, struct access *a, htsmsg_t *msg_to_write)
|
||||
{
|
||||
const idclass_t *ic = self->in_class;
|
||||
|
||||
while (ic) {
|
||||
if (ic->ic_perm)
|
||||
return self->in_class->ic_perm(self, a, msg_to_write);
|
||||
if (ic->ic_perm_def)
|
||||
return access_verify2(a, self->in_class->ic_perm_def);
|
||||
ic = ic->ic_super;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
|
@ -62,6 +62,7 @@ struct idclass {
|
|||
const property_group_t *ic_groups; ///< Groups for visual representation
|
||||
const property_t *ic_properties; ///< Property list
|
||||
const char *ic_event; ///< Events to fire on add/delete/title
|
||||
uint32_t ic_perm_def; ///< Default permissions
|
||||
|
||||
/* Callbacks */
|
||||
idnode_set_t *(*ic_get_childs) (idnode_t *self);
|
||||
|
@ -175,13 +176,7 @@ int idnode_write0 (idnode_t *self, htsmsg_t *m, int optmask, int dosave);
|
|||
#define idnode_save(in, m) idnode_read0(in, m, NULL, PO_NOSAVE | PO_USERAW)
|
||||
#define idnode_update(in, m) idnode_write0(in, m, PO_RDONLY | PO_WRONCE, 1)
|
||||
|
||||
static inline int
|
||||
idnode_perm(idnode_t *self, struct access *a, htsmsg_t *msg_to_write)
|
||||
{
|
||||
if (self->in_class->ic_perm)
|
||||
return self->in_class->ic_perm(self, a, msg_to_write);
|
||||
return 0;
|
||||
}
|
||||
int idnode_perm(idnode_t *self, struct access *a, htsmsg_t *msg_to_write);
|
||||
|
||||
const char *idnode_get_str (idnode_t *self, const char *key );
|
||||
int idnode_get_u32 (idnode_t *self, const char *key, uint32_t *u32);
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "packet.h"
|
||||
#include "streaming.h"
|
||||
#include "subscriptions.h"
|
||||
#include "access.h"
|
||||
#include "atomic.h"
|
||||
#include "notify.h"
|
||||
#include "idnode.h"
|
||||
|
@ -143,6 +144,7 @@ const idclass_t mpegts_input_class =
|
|||
.ic_class = "mpegts_input",
|
||||
.ic_caption = "MPEGTS Input",
|
||||
.ic_event = "mpegts_input",
|
||||
.ic_perm_def = ACCESS_ADMIN,
|
||||
.ic_get_title = mpegts_input_class_get_title,
|
||||
.ic_properties = (const property_t[]){
|
||||
{
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "queue.h"
|
||||
#include "input.h"
|
||||
#include "subscriptions.h"
|
||||
#include "access.h"
|
||||
#include "dvb_charset.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
@ -37,6 +38,7 @@ const idclass_t mpegts_mux_instance_class =
|
|||
{
|
||||
.ic_class = "mpegts_mux_instance",
|
||||
.ic_caption = "MPEGTS Multiplex Phy",
|
||||
.ic_perm_def = ACCESS_ADMIN
|
||||
};
|
||||
|
||||
static void
|
||||
|
@ -319,6 +321,7 @@ const idclass_t mpegts_mux_class =
|
|||
.ic_class = "mpegts_mux",
|
||||
.ic_caption = "MPEGTS Multiplex",
|
||||
.ic_event = "mpegts_mux",
|
||||
.ic_perm_def = ACCESS_ADMIN,
|
||||
.ic_save = mpegts_mux_class_save,
|
||||
.ic_delete = mpegts_mux_class_delete,
|
||||
.ic_get_title = mpegts_mux_class_get_title,
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include "input.h"
|
||||
#include "subscriptions.h"
|
||||
#include "access.h"
|
||||
#include "dvb_charset.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
@ -109,8 +110,9 @@ const idclass_t mpegts_network_class =
|
|||
{
|
||||
.ic_class = "mpegts_network",
|
||||
.ic_caption = "MPEGTS Network",
|
||||
.ic_save = mpegts_network_class_save,
|
||||
.ic_event = "mpegts_network",
|
||||
.ic_perm_def = ACCESS_ADMIN,
|
||||
.ic_save = mpegts_network_class_save,
|
||||
.ic_get_title = mpegts_network_class_get_title,
|
||||
.ic_properties = (const property_t[]){
|
||||
{
|
||||
|
|
13
src/main.c
13
src/main.c
|
@ -137,17 +137,8 @@ const tvh_caps_t tvheadend_capabilities[] = {
|
|||
#if ENABLE_CWC || ENABLE_CAPMT || ENABLE_CONSTCW
|
||||
{ "caclient", NULL },
|
||||
#endif
|
||||
#if ENABLE_V4L
|
||||
{ "v4l", NULL },
|
||||
#endif
|
||||
#if ENABLE_LINUXDVB
|
||||
{ "linuxdvb", NULL },
|
||||
#endif
|
||||
#if ENABLE_SATIP_CLIENT
|
||||
{ "satip_client", NULL },
|
||||
#endif
|
||||
#if ENABLE_HDHOMERUN_CLIENT
|
||||
{ "tvhdhomerun_client", NULL },
|
||||
#if ENABLE_V4L || ENABLE_LINUXDVB || ENABLE_SATIP_CLIENT || ENABLE_HDHOMERUN_CLIENT
|
||||
{ "tvadapters", NULL },
|
||||
#endif
|
||||
#if ENABLE_IMAGECACHE
|
||||
{ "imagecache", (uint32_t*)&imagecache_conf.enabled },
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "settings.h"
|
||||
#include "profile.h"
|
||||
#include "streaming.h"
|
||||
#include "access.h"
|
||||
#include "plumbing/tsfix.h"
|
||||
#include "plumbing/globalheaders.h"
|
||||
#if ENABLE_LIBAV
|
||||
|
@ -218,8 +219,9 @@ const idclass_t profile_class =
|
|||
{
|
||||
.ic_class = "profile",
|
||||
.ic_caption = "Stream Profile",
|
||||
.ic_save = profile_class_save,
|
||||
.ic_event = "profile",
|
||||
.ic_perm_def = ACCESS_ADMIN,
|
||||
.ic_save = profile_class_save,
|
||||
.ic_get_title = profile_class_get_title,
|
||||
.ic_delete = profile_class_delete,
|
||||
.ic_properties = (const property_t[]){
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "lang_codes.h"
|
||||
#include "descrambler.h"
|
||||
#include "input.h"
|
||||
#include "access.h"
|
||||
#include "esfilter.h"
|
||||
|
||||
static void service_data_timeout(void *aux);
|
||||
|
@ -169,6 +170,7 @@ const idclass_t service_class = {
|
|||
.ic_class = "service",
|
||||
.ic_caption = "Service",
|
||||
.ic_event = "service",
|
||||
.ic_perm_def = ACCESS_ADMIN,
|
||||
.ic_save = service_class_save,
|
||||
.ic_get_title = service_class_get_title,
|
||||
.ic_properties = (const property_t[]){
|
||||
|
|
|
@ -14,7 +14,7 @@ tvheadend.acleditor = function(panel, index)
|
|||
titleP: 'Access Entries',
|
||||
iconCls: 'group',
|
||||
columns: {
|
||||
enabled: { width: 120 },
|
||||
enabled: { width: 120 },
|
||||
username: { width: 250 },
|
||||
password: { width: 250 },
|
||||
prefix: { width: 350 },
|
||||
|
|
|
@ -2,15 +2,18 @@
|
|||
* Conditional Access Client (cwc,capmt)
|
||||
*/
|
||||
|
||||
tvheadend.caclient_builders = new Ext.data.JsonStore({
|
||||
url: 'api/caclient/builders',
|
||||
root: 'entries',
|
||||
fields: ['class', 'caption', 'props'],
|
||||
id: 'class',
|
||||
autoLoad: true
|
||||
});
|
||||
|
||||
tvheadend.caclient = function(panel, index) {
|
||||
|
||||
if (!tvheadend.caclient_builders) {
|
||||
tvheadend.caclient_builders = new Ext.data.JsonStore({
|
||||
url: 'api/caclient/builders',
|
||||
root: 'entries',
|
||||
fields: ['class', 'caption', 'props'],
|
||||
id: 'class',
|
||||
autoLoad: true
|
||||
});
|
||||
}
|
||||
|
||||
var actions = new Ext.ux.grid.RowActions({
|
||||
id: 'status',
|
||||
header: '',
|
||||
|
|
|
@ -2,16 +2,18 @@
|
|||
* Stream Profiles, Elementary Stream Filters
|
||||
*/
|
||||
|
||||
tvheadend.profile_builders = new Ext.data.JsonStore({
|
||||
url: 'api/profile/builders',
|
||||
root: 'entries',
|
||||
fields: ['class', 'caption', 'props'],
|
||||
id: 'class',
|
||||
autoLoad: true
|
||||
});
|
||||
|
||||
tvheadend.esfilter_tab = function(panel)
|
||||
{
|
||||
if (!tvheadend.profile_builders) {
|
||||
tvheadend.profile_builders = new Ext.data.JsonStore({
|
||||
url: 'api/profile/builders',
|
||||
root: 'entries',
|
||||
fields: ['class', 'caption', 'props'],
|
||||
id: 'class',
|
||||
autoLoad: true
|
||||
});
|
||||
}
|
||||
|
||||
var list = '-class';
|
||||
|
||||
tvheadend.idnode_form_grid(panel, {
|
||||
|
|
|
@ -2,31 +2,31 @@
|
|||
* DVB network
|
||||
*/
|
||||
|
||||
tvheadend.network_builders = new Ext.data.JsonStore({
|
||||
url: 'api/mpegts/network/builders',
|
||||
root: 'entries',
|
||||
fields: ['class', 'caption', 'props'],
|
||||
id: 'class',
|
||||
autoLoad: true
|
||||
});
|
||||
|
||||
tvheadend.network_list = new Ext.data.JsonStore({
|
||||
url: 'api/idnode/load',
|
||||
baseParams: {class: 'mpegts_network', enum: 1},
|
||||
root: 'entries',
|
||||
fields: ['key', 'val'],
|
||||
id: 'key',
|
||||
autoLoad: true
|
||||
});
|
||||
|
||||
tvheadend.comet.on('mpegts_network', function() {
|
||||
// TODO: Might be a bit excessive
|
||||
tvheadend.network_builders.reload();
|
||||
tvheadend.network_list.reload();
|
||||
});
|
||||
|
||||
tvheadend.networks = function(panel, index)
|
||||
{
|
||||
if (!tvheadend.network_list) {
|
||||
tvheadend.network_list = new Ext.data.JsonStore({
|
||||
url: 'api/idnode/load',
|
||||
baseParams: {class: 'mpegts_network', enum: 1},
|
||||
root: 'entries',
|
||||
fields: ['key', 'val'],
|
||||
id: 'key',
|
||||
autoLoad: true
|
||||
});
|
||||
tvheadend.network_builders = new Ext.data.JsonStore({
|
||||
url: 'api/mpegts/network/builders',
|
||||
root: 'entries',
|
||||
fields: ['class', 'caption', 'props'],
|
||||
id: 'class',
|
||||
autoLoad: true
|
||||
});
|
||||
tvheadend.comet.on('mpegts_network', function() {
|
||||
// TODO: Might be a bit excessive
|
||||
tvheadend.network_builders.reload();
|
||||
tvheadend.network_list.reload();
|
||||
});
|
||||
}
|
||||
|
||||
tvheadend.idnode_grid(panel, {
|
||||
url: 'api/mpegts/network',
|
||||
titleS: 'Network',
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
tvheadend.dynamic = true;
|
||||
tvheadend.accessupdate = null;
|
||||
tvheadend.capabilties = null;
|
||||
tvheadend.dvrpanel = null;
|
||||
tvheadend.confpanel = null;
|
||||
tvheadend.capabilities = null;
|
||||
|
||||
/* State Provider */
|
||||
Ext.state.Manager.setProvider(new Ext.state.CookieProvider({
|
||||
|
@ -353,9 +351,7 @@ function accessUpdate(o) {
|
|||
|
||||
var idx = 0;
|
||||
|
||||
if (tvheadend.capabilities.indexOf('linuxdvb') !== -1 ||
|
||||
tvheadend.capabilities.indexOf('satip_client') !== -1 ||
|
||||
tvheadend.capabilities.indexOf('v4l') !== -1)
|
||||
if (tvheadend.capabilities.indexOf('tvadapters') !== -1)
|
||||
tvheadend.tvadapters(dvbin);
|
||||
tvheadend.networks(dvbin);
|
||||
tvheadend.muxes(dvbin);
|
||||
|
|
Loading…
Add table
Reference in a new issue