ACL: add more restrictive permissions for all config urls, fix the http ticket issue, fixes #2383

This commit is contained in:
Jaroslav Kysela 2014-10-16 11:03:22 +02:00
parent 8d71f8ed25
commit 4b7a674e7f
20 changed files with 111 additions and 98 deletions

View file

@ -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,

View file

@ -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 },
};

View file

@ -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 },
};

View file

@ -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 },
};

View file

@ -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,

View file

@ -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;

View file

@ -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;

View file

@ -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;
}
/**
*
*/

View file

@ -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);

View file

@ -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[]){
{

View file

@ -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,

View file

@ -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[]){
{

View file

@ -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 },

View file

@ -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[]){

View file

@ -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[]){

View file

@ -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 },

View file

@ -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: '',

View file

@ -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, {

View file

@ -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',

View file

@ -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);