ACL: add full rights copy for tickets to resolve connection counting, fixes #2349
This commit is contained in:
parent
5b3f64834a
commit
a510248efc
5 changed files with 74 additions and 40 deletions
39
src/access.c
39
src/access.c
|
@ -57,6 +57,7 @@ access_ticket_destroy(access_ticket_t *at)
|
|||
free(at->at_id);
|
||||
free(at->at_resource);
|
||||
TAILQ_REMOVE(&access_tickets, at, at_link);
|
||||
access_destroy(at->at_access);
|
||||
free(at);
|
||||
}
|
||||
|
||||
|
@ -92,7 +93,7 @@ access_ticket_timout(void *aux)
|
|||
* Create a new ticket for the requested resource and generate a id for it
|
||||
*/
|
||||
const char *
|
||||
access_ticket_create(const char *resource)
|
||||
access_ticket_create(const char *resource, access_t *a)
|
||||
{
|
||||
uint8_t buf[20];
|
||||
char id[41];
|
||||
|
@ -100,6 +101,8 @@ access_ticket_create(const char *resource)
|
|||
access_ticket_t *at;
|
||||
static const char hex_string[16] = "0123456789ABCDEF";
|
||||
|
||||
assert(a);
|
||||
|
||||
at = calloc(1, sizeof(access_ticket_t));
|
||||
|
||||
RAND_bytes(buf, 20);
|
||||
|
@ -114,6 +117,8 @@ access_ticket_create(const char *resource)
|
|||
at->at_id = strdup(id);
|
||||
at->at_resource = strdup(resource);
|
||||
|
||||
at->at_access = access_copy(a);
|
||||
|
||||
TAILQ_INSERT_TAIL(&access_tickets, at, at_link);
|
||||
gtimer_arm(&at->at_timer, access_ticket_timout, at, 60*5);
|
||||
|
||||
|
@ -140,18 +145,37 @@ access_ticket_delete(const char *id)
|
|||
/**
|
||||
*
|
||||
*/
|
||||
int
|
||||
access_ticket_verify(const char *id, const char *resource)
|
||||
access_t *
|
||||
access_ticket_verify2(const char *id, const char *resource)
|
||||
{
|
||||
access_ticket_t *at;
|
||||
|
||||
if((at = access_ticket_find(id)) == NULL)
|
||||
return -1;
|
||||
return NULL;
|
||||
|
||||
if(strcmp(at->at_resource, resource))
|
||||
return -1;
|
||||
return NULL;
|
||||
|
||||
return 0;
|
||||
return access_copy(at->at_access);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
access_t *
|
||||
access_copy(access_t *src)
|
||||
{
|
||||
access_t *dst = malloc(sizeof(*dst));
|
||||
*dst = *src;
|
||||
if (src->aa_username)
|
||||
dst->aa_username = strdup(src->aa_username);
|
||||
if (src->aa_representative)
|
||||
dst->aa_representative = strdup(src->aa_representative);
|
||||
if (src->aa_dvrcfgs)
|
||||
dst->aa_dvrcfgs = htsmsg_copy(src->aa_dvrcfgs);
|
||||
if (src->aa_chtags)
|
||||
dst->aa_chtags = htsmsg_copy(src->aa_chtags);
|
||||
return dst;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1207,10 +1231,13 @@ void
|
|||
access_done(void)
|
||||
{
|
||||
access_entry_t *ae;
|
||||
access_ticket_t *at;
|
||||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
while ((ae = TAILQ_FIRST(&access_entries)) != NULL)
|
||||
access_entry_destroy(ae);
|
||||
while ((at = TAILQ_FIRST(&access_tickets)) != NULL)
|
||||
access_ticket_destroy(at);
|
||||
free((void *)superuser_username);
|
||||
superuser_username = NULL;
|
||||
free((void *)superuser_password);
|
||||
|
|
36
src/access.h
36
src/access.h
|
@ -79,19 +79,6 @@ typedef struct access_entry {
|
|||
|
||||
extern const idclass_t access_entry_class;
|
||||
|
||||
TAILQ_HEAD(access_ticket_queue, access_ticket);
|
||||
|
||||
extern struct access_ticket_queue access_tickets;
|
||||
|
||||
typedef struct access_ticket {
|
||||
char *at_id;
|
||||
|
||||
TAILQ_ENTRY(access_ticket) at_link;
|
||||
|
||||
gtimer_t at_timer;
|
||||
char *at_resource;
|
||||
} access_ticket_t;
|
||||
|
||||
typedef struct access {
|
||||
char *aa_username;
|
||||
char *aa_representative;
|
||||
|
@ -104,6 +91,20 @@ typedef struct access {
|
|||
uint32_t aa_conn_limit;
|
||||
} access_t;
|
||||
|
||||
TAILQ_HEAD(access_ticket_queue, access_ticket);
|
||||
|
||||
extern struct access_ticket_queue access_tickets;
|
||||
|
||||
typedef struct access_ticket {
|
||||
char *at_id;
|
||||
|
||||
TAILQ_ENTRY(access_ticket) at_link;
|
||||
|
||||
gtimer_t at_timer;
|
||||
char *at_resource;
|
||||
access_t *at_access;
|
||||
} access_ticket_t;
|
||||
|
||||
#define ACCESS_ANONYMOUS 0
|
||||
#define ACCESS_STREAMING (1<<0)
|
||||
#define ACCESS_ADVANCED_STREAMING (1<<1)
|
||||
|
@ -118,12 +119,12 @@ typedef struct access {
|
|||
/**
|
||||
* Create a new ticket for the requested resource and generate a id for it
|
||||
*/
|
||||
const char* access_ticket_create(const char *resource);
|
||||
const char* access_ticket_create(const char *resource, access_t *a);
|
||||
|
||||
/**
|
||||
* Verifies that a given ticket id matches a resource
|
||||
*/
|
||||
int access_ticket_verify(const char *id, const char *resource);
|
||||
access_t *access_ticket_verify2(const char *id, const char *resource);
|
||||
|
||||
int access_ticket_delete(const char *ticket_id);
|
||||
|
||||
|
@ -132,6 +133,11 @@ int access_ticket_delete(const char *ticket_id);
|
|||
*/
|
||||
void access_destroy(access_t *a);
|
||||
|
||||
/**
|
||||
* Copy the access structure
|
||||
*/
|
||||
access_t *access_copy(access_t *src);
|
||||
|
||||
/**
|
||||
* Verifies that the given user in combination with the source ip
|
||||
* complies with the requested mask
|
||||
|
|
|
@ -1653,7 +1653,7 @@ htsp_method_getTicket(htsp_connection_t *htsp, htsmsg_t *in)
|
|||
return htsp_error("User does not have access");
|
||||
|
||||
snprintf(path, sizeof(path), "/stream/channelid/%d", id);
|
||||
ticket = access_ticket_create(path);
|
||||
ticket = access_ticket_create(path, htsp->htsp_granted_access);
|
||||
} else if(!htsmsg_get_u32(in, "dvrId", &id)) {
|
||||
if (!(de = dvr_entry_find_by_id(id)))
|
||||
return htsp_error("DVR entry does not exist");
|
||||
|
@ -1661,7 +1661,7 @@ htsp_method_getTicket(htsp_connection_t *htsp, htsmsg_t *in)
|
|||
return htsp_error("User does not have access");
|
||||
|
||||
snprintf(path, sizeof(path), "/dvrfile/%d", id);
|
||||
ticket = access_ticket_create(path);
|
||||
ticket = access_ticket_create(path, htsp->htsp_granted_access);
|
||||
} else {
|
||||
return htsp_error("Missing argument 'channelId' or 'dvrId'");
|
||||
}
|
||||
|
|
23
src/http.c
23
src/http.c
|
@ -410,19 +410,20 @@ http_redirect(http_connection_t *hc, const char *location,
|
|||
*/
|
||||
static int http_access_verify_ticket(http_connection_t *hc)
|
||||
{
|
||||
const char *ticket_id = http_arg_get(&hc->hc_req_args, "ticket");
|
||||
const char *ticket_id;
|
||||
|
||||
if (hc->hc_ticket)
|
||||
if (hc->hc_ticket || hc->hc_access)
|
||||
return 0;
|
||||
if(!access_ticket_verify(ticket_id, hc->hc_url)) {
|
||||
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;
|
||||
}
|
||||
return -1;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -450,7 +450,7 @@ http_channel_playlist(http_connection_t *hc, channel_t *channel)
|
|||
htsbuf_qprintf(hq, "#EXTM3U\n");
|
||||
htsbuf_qprintf(hq, "#EXTINF:-1,%s\n", channel_get_name(channel));
|
||||
htsbuf_qprintf(hq, "http://%s%s?ticket=%s", host, buf,
|
||||
access_ticket_create(buf));
|
||||
access_ticket_create(buf, hc->hc_access));
|
||||
|
||||
#if ENABLE_LIBAV
|
||||
transcoder_props_t props;
|
||||
|
@ -506,7 +506,7 @@ http_tag_playlist(http_connection_t *hc, channel_tag_t *tag)
|
|||
snprintf(buf, sizeof(buf), "/stream/channelid/%d", channel_get_id(ctm->ctm_channel));
|
||||
htsbuf_qprintf(hq, "#EXTINF:-1,%s\n", channel_get_name(ctm->ctm_channel));
|
||||
htsbuf_qprintf(hq, "http://%s%s?ticket=%s", host, buf,
|
||||
access_ticket_create(buf));
|
||||
access_ticket_create(buf, hc->hc_access));
|
||||
htsbuf_qprintf(hq, "&mux=%s\n", muxer_container_type2txt(mc));
|
||||
}
|
||||
|
||||
|
@ -543,7 +543,7 @@ http_tag_list_playlist(http_connection_t *hc)
|
|||
snprintf(buf, sizeof(buf), "/playlist/tagid/%d", idnode_get_short_uuid(&ct->ct_id));
|
||||
htsbuf_qprintf(hq, "#EXTINF:-1,%s\n", ct->ct_name);
|
||||
htsbuf_qprintf(hq, "http://%s%s?ticket=%s", host, buf,
|
||||
access_ticket_create(buf));
|
||||
access_ticket_create(buf, hc->hc_access));
|
||||
htsbuf_qprintf(hq, "&mux=%s\n", muxer_container_type2txt(mc));
|
||||
}
|
||||
|
||||
|
@ -607,7 +607,7 @@ http_channel_list_playlist(http_connection_t *hc)
|
|||
|
||||
htsbuf_qprintf(hq, "#EXTINF:-1,%s\n", channel_get_name(ch));
|
||||
htsbuf_qprintf(hq, "http://%s%s?ticket=%s", host, buf,
|
||||
access_ticket_create(buf));
|
||||
access_ticket_create(buf, hc->hc_access));
|
||||
htsbuf_qprintf(hq, "&mux=%s\n", muxer_container_type2txt(mc));
|
||||
}
|
||||
|
||||
|
@ -662,7 +662,7 @@ http_dvr_list_playlist(http_connection_t *hc)
|
|||
|
||||
snprintf(buf, sizeof(buf), "/dvrfile/%s", uuid);
|
||||
htsbuf_qprintf(hq, "http://%s%s?ticket=%s\n", host, buf,
|
||||
access_ticket_create(buf));
|
||||
access_ticket_create(buf, hc->hc_access));
|
||||
}
|
||||
|
||||
http_output_content(hc, "audio/x-mpegurl");
|
||||
|
@ -702,7 +702,7 @@ http_dvr_playlist(http_connection_t *hc, dvr_entry_t *de)
|
|||
htsbuf_qprintf(hq, "#EXT-X-PROGRAM-DATE-TIME:%s\n", buf);
|
||||
|
||||
snprintf(buf, sizeof(buf), "/dvrfile/%s", uuid);
|
||||
ticket_id = access_ticket_create(buf);
|
||||
ticket_id = access_ticket_create(buf, hc->hc_access);
|
||||
htsbuf_qprintf(hq, "http://%s%s?ticket=%s\n", host, buf, ticket_id);
|
||||
|
||||
http_output_content(hc, "application/x-mpegURL");
|
||||
|
|
Loading…
Add table
Reference in a new issue