2008-04-29 06:53:21 +00:00
|
|
|
|
/*
|
|
|
|
|
* tvheadend, access control
|
|
|
|
|
* Copyright (C) 2008 Andreas <EFBFBD>man
|
|
|
|
|
*
|
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
* (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <pthread.h>
|
|
|
|
|
#include <ctype.h>
|
|
|
|
|
#include <assert.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
#include <netinet/in.h>
|
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
|
|
2010-12-30 09:17:14 +00:00
|
|
|
|
#include <openssl/sha.h>
|
2011-02-02 19:11:37 +01:00
|
|
|
|
#include <openssl/rand.h>
|
2010-12-30 09:17:14 +00:00
|
|
|
|
|
2010-11-29 19:25:24 +00:00
|
|
|
|
#include "tvheadend.h"
|
2008-04-29 06:53:21 +00:00
|
|
|
|
#include "access.h"
|
2008-08-25 16:22:50 +00:00
|
|
|
|
#include "dtable.h"
|
2009-05-28 21:12:44 +00:00
|
|
|
|
#include "settings.h"
|
2009-02-28 15:06:57 +00:00
|
|
|
|
|
2008-04-29 06:53:21 +00:00
|
|
|
|
struct access_entry_queue access_entries;
|
2011-02-01 22:43:22 +01:00
|
|
|
|
struct access_ticket_queue access_tickets;
|
2008-08-25 16:22:50 +00:00
|
|
|
|
|
2009-05-28 21:12:44 +00:00
|
|
|
|
const char *superuser_username;
|
|
|
|
|
const char *superuser_password;
|
2008-04-29 06:53:21 +00:00
|
|
|
|
|
2011-02-01 22:43:22 +01:00
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
access_ticket_destroy(access_ticket_t *at)
|
|
|
|
|
{
|
|
|
|
|
free(at->at_id);
|
|
|
|
|
free(at->at_resource);
|
|
|
|
|
TAILQ_REMOVE(&access_tickets, at, at_link);
|
|
|
|
|
free(at);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
static access_ticket_t *
|
|
|
|
|
access_ticket_find(const char *id)
|
|
|
|
|
{
|
|
|
|
|
access_ticket_t *at = NULL;
|
|
|
|
|
|
|
|
|
|
if(id != NULL) {
|
|
|
|
|
TAILQ_FOREACH(at, &access_tickets, at_link)
|
|
|
|
|
if(!strcmp(at->at_id, id))
|
|
|
|
|
return at;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
access_ticket_timout(void *aux)
|
|
|
|
|
{
|
|
|
|
|
access_ticket_t *at = aux;
|
|
|
|
|
|
|
|
|
|
access_ticket_destroy(at);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Create a new ticket for the requested resource and generate a id for it
|
|
|
|
|
*/
|
|
|
|
|
const char *
|
|
|
|
|
access_ticket_create(const char *resource)
|
|
|
|
|
{
|
|
|
|
|
uint8_t buf[20];
|
|
|
|
|
char id[41];
|
2011-02-02 19:11:37 +01:00
|
|
|
|
unsigned int i;
|
2011-02-01 22:43:22 +01:00
|
|
|
|
access_ticket_t *at;
|
|
|
|
|
static const char hex_string[16] = "0123456789ABCDEF";
|
|
|
|
|
|
|
|
|
|
at = calloc(1, sizeof(access_ticket_t));
|
2011-02-02 19:11:37 +01:00
|
|
|
|
|
|
|
|
|
RAND_bytes(buf, 20);
|
2011-02-01 22:43:22 +01:00
|
|
|
|
|
|
|
|
|
//convert to hexstring
|
|
|
|
|
for(i=0; i<sizeof(buf); i++){
|
|
|
|
|
id[i*2] = hex_string[((buf[i] >> 4) & 0xF)];
|
|
|
|
|
id[(i*2)+1] = hex_string[(buf[i]) & 0x0F];
|
|
|
|
|
}
|
|
|
|
|
id[40] = '\0';
|
|
|
|
|
|
|
|
|
|
at->at_id = strdup(id);
|
|
|
|
|
at->at_resource = strdup(resource);
|
|
|
|
|
|
|
|
|
|
TAILQ_INSERT_TAIL(&access_tickets, at, at_link);
|
|
|
|
|
gtimer_arm(&at->at_timer, access_ticket_timout, at, 60*5);
|
|
|
|
|
|
|
|
|
|
return at->at_id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
int
|
|
|
|
|
access_ticket_delete(const char *id)
|
|
|
|
|
{
|
|
|
|
|
access_ticket_t *at;
|
|
|
|
|
|
2011-02-02 18:48:14 +01:00
|
|
|
|
if((at = access_ticket_find(id)) == NULL)
|
2011-02-01 22:43:22 +01:00
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
gtimer_disarm(&at->at_timer);
|
|
|
|
|
access_ticket_destroy(at);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
int
|
|
|
|
|
access_ticket_verify(const char *id, const char *resource)
|
|
|
|
|
{
|
|
|
|
|
access_ticket_t *at;
|
|
|
|
|
|
2011-02-02 18:48:14 +01:00
|
|
|
|
if((at = access_ticket_find(id)) == NULL)
|
2011-02-01 22:43:22 +01:00
|
|
|
|
return -1;
|
|
|
|
|
|
2011-02-02 18:48:14 +01:00
|
|
|
|
if(strcmp(at->at_resource, resource))
|
2011-02-01 22:43:22 +01:00
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2008-04-29 06:53:21 +00:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
*/
|
2008-08-25 16:22:50 +00:00
|
|
|
|
int
|
|
|
|
|
access_verify(const char *username, const char *password,
|
|
|
|
|
struct sockaddr *src, uint32_t mask)
|
2008-04-29 06:53:21 +00:00
|
|
|
|
{
|
2008-08-25 16:22:50 +00:00
|
|
|
|
uint32_t bits = 0;
|
|
|
|
|
struct sockaddr_in *si = (struct sockaddr_in *)src;
|
|
|
|
|
uint32_t b = ntohl(si->sin_addr.s_addr);
|
|
|
|
|
access_entry_t *ae;
|
|
|
|
|
|
2009-05-28 21:12:44 +00:00
|
|
|
|
if(username != NULL && superuser_username != NULL &&
|
|
|
|
|
password != NULL && superuser_password != NULL &&
|
|
|
|
|
!strcmp(username, superuser_username) &&
|
|
|
|
|
!strcmp(password, superuser_password))
|
|
|
|
|
return 0;
|
|
|
|
|
|
2008-08-25 16:22:50 +00:00
|
|
|
|
TAILQ_FOREACH(ae, &access_entries, ae_link) {
|
|
|
|
|
|
2009-05-28 21:12:44 +00:00
|
|
|
|
if(!ae->ae_enabled)
|
|
|
|
|
continue;
|
|
|
|
|
|
2008-08-25 16:22:50 +00:00
|
|
|
|
if(ae->ae_username[0] != '*') {
|
|
|
|
|
/* acl entry requires username to match */
|
|
|
|
|
if(username == NULL)
|
|
|
|
|
continue; /* Didn't get one */
|
|
|
|
|
|
|
|
|
|
if(strcmp(ae->ae_username, username) ||
|
|
|
|
|
strcmp(ae->ae_password, password))
|
|
|
|
|
continue; /* username/password mismatch */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if((b & ae->ae_netmask) != ae->ae_network)
|
|
|
|
|
continue; /* IP based access mismatches */
|
|
|
|
|
|
|
|
|
|
bits |= ae->ae_rights;
|
|
|
|
|
}
|
|
|
|
|
return (mask & bits) == mask ? 0 : -1;
|
2008-04-29 06:53:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
2009-02-28 15:06:57 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
uint32_t
|
|
|
|
|
access_get_hashed(const char *username, const uint8_t digest[20],
|
2009-03-03 22:41:32 +00:00
|
|
|
|
const uint8_t *challenge, struct sockaddr *src,
|
|
|
|
|
int *entrymatch)
|
2009-02-28 15:06:57 +00:00
|
|
|
|
{
|
|
|
|
|
struct sockaddr_in *si = (struct sockaddr_in *)src;
|
|
|
|
|
uint32_t b = ntohl(si->sin_addr.s_addr);
|
|
|
|
|
access_entry_t *ae;
|
2010-12-30 09:17:14 +00:00
|
|
|
|
SHA_CTX shactx;
|
2009-02-28 15:06:57 +00:00
|
|
|
|
uint8_t d[20];
|
|
|
|
|
uint32_t r = 0;
|
2009-03-03 22:41:32 +00:00
|
|
|
|
int match = 0;
|
2009-02-28 15:06:57 +00:00
|
|
|
|
|
2009-05-28 21:12:44 +00:00
|
|
|
|
if(superuser_username != NULL && superuser_password != NULL) {
|
|
|
|
|
|
2010-12-30 09:17:14 +00:00
|
|
|
|
SHA_Init(&shactx);
|
|
|
|
|
SHA_Update(&shactx, (const uint8_t *)superuser_password,
|
|
|
|
|
strlen(superuser_password));
|
|
|
|
|
SHA_Update(&shactx, challenge, 32);
|
|
|
|
|
SHA_Final(d, &shactx);
|
2009-05-28 21:12:44 +00:00
|
|
|
|
|
|
|
|
|
if(!strcmp(superuser_username, username) && !memcmp(d, digest, 20))
|
|
|
|
|
return 0xffffffff;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2009-02-28 15:06:57 +00:00
|
|
|
|
TAILQ_FOREACH(ae, &access_entries, ae_link) {
|
|
|
|
|
|
2009-05-28 21:12:44 +00:00
|
|
|
|
if(!ae->ae_enabled)
|
|
|
|
|
continue;
|
|
|
|
|
|
2009-02-28 15:06:57 +00:00
|
|
|
|
if((b & ae->ae_netmask) != ae->ae_network)
|
|
|
|
|
continue; /* IP based access mismatches */
|
|
|
|
|
|
2010-12-30 09:17:14 +00:00
|
|
|
|
SHA_Init(&shactx);
|
|
|
|
|
SHA_Update(&shactx, (const uint8_t *)ae->ae_password,
|
2010-06-23 21:54:29 +00:00
|
|
|
|
strlen(ae->ae_password));
|
2010-12-30 09:17:14 +00:00
|
|
|
|
SHA1_Update(&shactx, challenge, 32);
|
|
|
|
|
SHA1_Final(d, &shactx);
|
2010-06-23 21:54:29 +00:00
|
|
|
|
|
2009-05-28 21:12:44 +00:00
|
|
|
|
if(strcmp(ae->ae_username, username) || memcmp(d, digest, 20))
|
2009-02-28 15:06:57 +00:00
|
|
|
|
continue;
|
2009-03-03 22:41:32 +00:00
|
|
|
|
match = 1;
|
2009-02-28 15:06:57 +00:00
|
|
|
|
r |= ae->ae_rights;
|
|
|
|
|
}
|
2009-03-03 22:41:32 +00:00
|
|
|
|
if(entrymatch != NULL)
|
|
|
|
|
*entrymatch = match;
|
2009-02-28 15:06:57 +00:00
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
uint32_t
|
|
|
|
|
access_get_by_addr(struct sockaddr *src)
|
|
|
|
|
{
|
|
|
|
|
struct sockaddr_in *si = (struct sockaddr_in *)src;
|
|
|
|
|
uint32_t b = ntohl(si->sin_addr.s_addr);
|
|
|
|
|
access_entry_t *ae;
|
|
|
|
|
uint32_t r = 0;
|
|
|
|
|
|
|
|
|
|
TAILQ_FOREACH(ae, &access_entries, ae_link) {
|
|
|
|
|
|
|
|
|
|
if(ae->ae_username[0] != '*')
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if((b & ae->ae_netmask) != ae->ae_network)
|
|
|
|
|
continue; /* IP based access mismatches */
|
|
|
|
|
|
|
|
|
|
r |= ae->ae_rights;
|
|
|
|
|
}
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2008-04-29 06:53:21 +00:00
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
*/
|
2008-08-25 16:22:50 +00:00
|
|
|
|
static void
|
|
|
|
|
access_update_flag(access_entry_t *ae, int flag, int bo)
|
2008-04-29 06:53:21 +00:00
|
|
|
|
{
|
2008-08-25 16:22:50 +00:00
|
|
|
|
if(bo)
|
|
|
|
|
ae->ae_rights |= flag;
|
|
|
|
|
else
|
|
|
|
|
ae->ae_rights &= ~flag;
|
2008-04-29 06:53:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
*/
|
2008-08-25 16:22:50 +00:00
|
|
|
|
static void
|
|
|
|
|
access_set_prefix(access_entry_t *ae, const char *prefix)
|
2008-04-29 06:53:21 +00:00
|
|
|
|
{
|
|
|
|
|
char buf[100];
|
|
|
|
|
int prefixlen;
|
|
|
|
|
char *p;
|
|
|
|
|
|
|
|
|
|
if(strlen(prefix) > 90)
|
2008-08-25 16:22:50 +00:00
|
|
|
|
return;
|
2008-04-29 06:53:21 +00:00
|
|
|
|
|
|
|
|
|
strcpy(buf, prefix);
|
|
|
|
|
p = strchr(buf, '/');
|
|
|
|
|
if(p) {
|
|
|
|
|
*p++ = 0;
|
|
|
|
|
prefixlen = atoi(p);
|
|
|
|
|
if(prefixlen > 32)
|
2008-08-25 16:22:50 +00:00
|
|
|
|
return;
|
2008-04-29 06:53:21 +00:00
|
|
|
|
} else {
|
|
|
|
|
prefixlen = 32;
|
|
|
|
|
}
|
|
|
|
|
|
2008-08-25 16:22:50 +00:00
|
|
|
|
ae->ae_ip.s_addr = inet_addr(buf);
|
2008-04-29 06:53:21 +00:00
|
|
|
|
ae->ae_prefixlen = prefixlen;
|
|
|
|
|
|
2008-08-25 16:22:50 +00:00
|
|
|
|
ae->ae_netmask = prefixlen ? 0xffffffff << (32 - prefixlen) : 0;
|
|
|
|
|
ae->ae_network = ntohl(ae->ae_ip.s_addr) & ae->ae_netmask;
|
2008-04-29 06:53:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
2008-08-25 16:22:50 +00:00
|
|
|
|
|
2008-04-29 06:53:21 +00:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
*/
|
2008-05-02 19:37:23 +00:00
|
|
|
|
static access_entry_t *
|
2008-08-25 16:22:50 +00:00
|
|
|
|
access_entry_find(const char *id, int create)
|
2008-04-29 06:53:21 +00:00
|
|
|
|
{
|
|
|
|
|
access_entry_t *ae;
|
2008-08-25 16:22:50 +00:00
|
|
|
|
char buf[20];
|
2008-09-07 08:57:02 +00:00
|
|
|
|
static int tally;
|
2008-08-25 16:22:50 +00:00
|
|
|
|
|
|
|
|
|
if(id != NULL) {
|
|
|
|
|
TAILQ_FOREACH(ae, &access_entries, ae_link)
|
|
|
|
|
if(!strcmp(ae->ae_id, id))
|
|
|
|
|
return ae;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(create == 0)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
ae = calloc(1, sizeof(access_entry_t));
|
|
|
|
|
if(id == NULL) {
|
2008-09-07 08:57:02 +00:00
|
|
|
|
tally++;
|
|
|
|
|
snprintf(buf, sizeof(buf), "%d", tally);
|
2008-08-25 16:22:50 +00:00
|
|
|
|
id = buf;
|
|
|
|
|
} else {
|
2008-09-07 08:57:02 +00:00
|
|
|
|
tally = MAX(atoi(id), tally);
|
2008-08-25 16:22:50 +00:00
|
|
|
|
}
|
2008-04-29 06:53:21 +00:00
|
|
|
|
|
2008-08-25 16:22:50 +00:00
|
|
|
|
ae->ae_id = strdup(id);
|
|
|
|
|
ae->ae_username = strdup("*");
|
|
|
|
|
ae->ae_password = strdup("*");
|
|
|
|
|
ae->ae_comment = strdup("New entry");
|
|
|
|
|
TAILQ_INSERT_TAIL(&access_entries, ae, ae_link);
|
2008-04-29 06:53:21 +00:00
|
|
|
|
return ae;
|
|
|
|
|
}
|
|
|
|
|
|
2008-08-25 16:22:50 +00:00
|
|
|
|
|
|
|
|
|
|
2008-04-29 06:53:21 +00:00
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
*/
|
2008-08-25 16:22:50 +00:00
|
|
|
|
static void
|
|
|
|
|
access_entry_destroy(access_entry_t *ae)
|
2008-04-29 06:53:21 +00:00
|
|
|
|
{
|
2008-08-25 16:22:50 +00:00
|
|
|
|
free(ae->ae_id);
|
|
|
|
|
free(ae->ae_username);
|
|
|
|
|
free(ae->ae_password);
|
|
|
|
|
TAILQ_REMOVE(&access_entries, ae, ae_link);
|
|
|
|
|
free(ae);
|
2008-04-29 06:53:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
*/
|
2008-08-25 16:22:50 +00:00
|
|
|
|
static htsmsg_t *
|
|
|
|
|
access_record_build(access_entry_t *ae)
|
2008-04-29 06:53:21 +00:00
|
|
|
|
{
|
2009-03-01 16:51:30 +00:00
|
|
|
|
htsmsg_t *e = htsmsg_create_map();
|
2008-08-25 16:22:50 +00:00
|
|
|
|
char buf[100];
|
2008-04-29 06:53:21 +00:00
|
|
|
|
|
2008-08-25 16:22:50 +00:00
|
|
|
|
htsmsg_add_u32(e, "enabled", !!ae->ae_enabled);
|
2008-04-29 06:53:21 +00:00
|
|
|
|
|
2008-08-25 16:22:50 +00:00
|
|
|
|
htsmsg_add_str(e, "username", ae->ae_username);
|
|
|
|
|
htsmsg_add_str(e, "password", ae->ae_password);
|
|
|
|
|
htsmsg_add_str(e, "comment", ae->ae_comment);
|
2008-04-29 06:53:21 +00:00
|
|
|
|
|
2008-08-25 16:22:50 +00:00
|
|
|
|
snprintf(buf, sizeof(buf), "%s/%d", inet_ntoa(ae->ae_ip), ae->ae_prefixlen);
|
|
|
|
|
htsmsg_add_str(e, "prefix", buf);
|
2008-04-29 06:53:21 +00:00
|
|
|
|
|
2008-08-25 16:22:50 +00:00
|
|
|
|
htsmsg_add_u32(e, "streaming", ae->ae_rights & ACCESS_STREAMING ? 1 : 0);
|
2008-09-23 19:32:57 +00:00
|
|
|
|
htsmsg_add_u32(e, "dvr" , ae->ae_rights & ACCESS_RECORDER ? 1 : 0);
|
2008-08-25 16:22:50 +00:00
|
|
|
|
htsmsg_add_u32(e, "webui" , ae->ae_rights & ACCESS_WEB_INTERFACE ? 1 : 0);
|
|
|
|
|
htsmsg_add_u32(e, "admin" , ae->ae_rights & ACCESS_ADMIN ? 1 : 0);
|
2008-04-29 06:53:21 +00:00
|
|
|
|
|
|
|
|
|
|
2008-08-25 16:22:50 +00:00
|
|
|
|
htsmsg_add_str(e, "id", ae->ae_id);
|
|
|
|
|
|
|
|
|
|
return e;
|
|
|
|
|
}
|
2008-04-29 06:53:21 +00:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
*/
|
2008-08-25 16:22:50 +00:00
|
|
|
|
static htsmsg_t *
|
|
|
|
|
access_record_get_all(void *opaque)
|
2008-04-29 06:53:21 +00:00
|
|
|
|
{
|
2009-03-01 16:51:30 +00:00
|
|
|
|
htsmsg_t *r = htsmsg_create_list();
|
2008-04-29 06:53:21 +00:00
|
|
|
|
access_entry_t *ae;
|
|
|
|
|
|
2008-08-25 16:22:50 +00:00
|
|
|
|
TAILQ_FOREACH(ae, &access_entries, ae_link)
|
|
|
|
|
htsmsg_add_msg(r, NULL, access_record_build(ae));
|
|
|
|
|
|
|
|
|
|
return r;
|
2008-04-29 06:53:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
*/
|
2008-08-25 16:22:50 +00:00
|
|
|
|
static htsmsg_t *
|
|
|
|
|
access_record_get(void *opaque, const char *id)
|
2008-04-29 06:53:21 +00:00
|
|
|
|
{
|
2008-08-25 16:22:50 +00:00
|
|
|
|
access_entry_t *ae;
|
|
|
|
|
|
|
|
|
|
if((ae = access_entry_find(id, 0)) == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
return access_record_build(ae);
|
2008-04-29 06:53:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
*/
|
2008-08-25 16:22:50 +00:00
|
|
|
|
static htsmsg_t *
|
|
|
|
|
access_record_create(void *opaque)
|
2008-04-29 06:53:21 +00:00
|
|
|
|
{
|
2008-08-25 16:22:50 +00:00
|
|
|
|
return access_record_build(access_entry_find(NULL, 1));
|
2008-04-29 06:53:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
*/
|
2008-08-25 16:22:50 +00:00
|
|
|
|
static htsmsg_t *
|
|
|
|
|
access_record_update(void *opaque, const char *id, htsmsg_t *values,
|
|
|
|
|
int maycreate)
|
2008-04-29 06:53:21 +00:00
|
|
|
|
{
|
|
|
|
|
access_entry_t *ae;
|
2008-08-25 16:22:50 +00:00
|
|
|
|
const char *s;
|
|
|
|
|
uint32_t u32;
|
2008-04-29 06:53:21 +00:00
|
|
|
|
|
2008-08-25 16:22:50 +00:00
|
|
|
|
if((ae = access_entry_find(id, maycreate)) == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
if((s = htsmsg_get_str(values, "username")) != NULL) {
|
|
|
|
|
free(ae->ae_username);
|
|
|
|
|
ae->ae_username = strdup(s);
|
|
|
|
|
}
|
2008-04-29 06:53:21 +00:00
|
|
|
|
|
2008-08-25 16:22:50 +00:00
|
|
|
|
if((s = htsmsg_get_str(values, "comment")) != NULL) {
|
|
|
|
|
free(ae->ae_comment);
|
|
|
|
|
ae->ae_comment = strdup(s);
|
|
|
|
|
}
|
2008-04-29 06:53:21 +00:00
|
|
|
|
|
2008-08-25 16:22:50 +00:00
|
|
|
|
if((s = htsmsg_get_str(values, "password")) != NULL) {
|
|
|
|
|
free(ae->ae_password);
|
|
|
|
|
ae->ae_password = strdup(s);
|
2008-04-29 06:53:21 +00:00
|
|
|
|
}
|
2008-08-25 16:22:50 +00:00
|
|
|
|
|
|
|
|
|
if((s = htsmsg_get_str(values, "prefix")) != NULL)
|
|
|
|
|
access_set_prefix(ae, s);
|
|
|
|
|
|
|
|
|
|
if(!htsmsg_get_u32(values, "enabled", &u32))
|
|
|
|
|
ae->ae_enabled = u32;
|
|
|
|
|
|
|
|
|
|
if(!htsmsg_get_u32(values, "streaming", &u32))
|
|
|
|
|
access_update_flag(ae, ACCESS_STREAMING, u32);
|
|
|
|
|
|
2008-09-23 19:32:57 +00:00
|
|
|
|
if(!htsmsg_get_u32(values, "dvr", &u32))
|
2008-08-25 16:22:50 +00:00
|
|
|
|
access_update_flag(ae, ACCESS_RECORDER, u32);
|
|
|
|
|
|
|
|
|
|
if(!htsmsg_get_u32(values, "admin", &u32))
|
|
|
|
|
access_update_flag(ae, ACCESS_ADMIN, u32);
|
|
|
|
|
|
|
|
|
|
if(!htsmsg_get_u32(values, "webui", &u32))
|
|
|
|
|
access_update_flag(ae, ACCESS_WEB_INTERFACE, u32);
|
|
|
|
|
|
|
|
|
|
return access_record_build(ae);
|
2008-04-29 06:53:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
2008-08-25 16:22:50 +00:00
|
|
|
|
|
2008-04-29 06:53:21 +00:00
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
*/
|
2008-08-25 16:22:50 +00:00
|
|
|
|
static int
|
|
|
|
|
access_record_delete(void *opaque, const char *id)
|
2008-04-29 06:53:21 +00:00
|
|
|
|
{
|
|
|
|
|
access_entry_t *ae;
|
|
|
|
|
|
2008-08-25 16:22:50 +00:00
|
|
|
|
if((ae = access_entry_find(id, 0)) == NULL)
|
|
|
|
|
return -1;
|
|
|
|
|
access_entry_destroy(ae);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2008-04-29 06:53:21 +00:00
|
|
|
|
|
|
|
|
|
|
2008-08-25 16:22:50 +00:00
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
static const dtable_class_t access_dtc = {
|
|
|
|
|
.dtc_record_get = access_record_get,
|
|
|
|
|
.dtc_record_get_all = access_record_get_all,
|
|
|
|
|
.dtc_record_create = access_record_create,
|
|
|
|
|
.dtc_record_update = access_record_update,
|
|
|
|
|
.dtc_record_delete = access_record_delete,
|
2008-09-25 16:38:55 +00:00
|
|
|
|
.dtc_read_access = ACCESS_ADMIN,
|
|
|
|
|
.dtc_write_access = ACCESS_ADMIN,
|
2011-01-25 22:48:01 +01:00
|
|
|
|
.dtc_mutex = &global_lock,
|
2008-08-25 16:22:50 +00:00
|
|
|
|
};
|
2008-04-29 06:53:21 +00:00
|
|
|
|
|
2008-08-25 16:22:50 +00:00
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
void
|
2009-05-28 21:12:44 +00:00
|
|
|
|
access_init(int createdefault)
|
2008-08-25 16:22:50 +00:00
|
|
|
|
{
|
|
|
|
|
dtable_t *dt;
|
2009-05-28 21:12:44 +00:00
|
|
|
|
htsmsg_t *r, *m;
|
2008-08-25 16:22:50 +00:00
|
|
|
|
access_entry_t *ae;
|
2009-06-10 05:54:48 +00:00
|
|
|
|
const char *s;
|
|
|
|
|
|
2011-02-02 19:11:37 +01:00
|
|
|
|
static struct {
|
|
|
|
|
pid_t pid;
|
|
|
|
|
struct timeval tv;
|
|
|
|
|
} randseed;
|
|
|
|
|
|
|
|
|
|
randseed.pid = getpid();
|
|
|
|
|
gettimeofday(&randseed.tv, NULL);
|
|
|
|
|
RAND_seed(&randseed, sizeof(randseed));
|
|
|
|
|
|
2008-08-25 16:22:50 +00:00
|
|
|
|
TAILQ_INIT(&access_entries);
|
2011-02-01 22:43:22 +01:00
|
|
|
|
TAILQ_INIT(&access_tickets);
|
|
|
|
|
|
2008-08-25 16:22:50 +00:00
|
|
|
|
dt = dtable_create(&access_dtc, "accesscontrol", NULL);
|
2008-04-29 06:53:21 +00:00
|
|
|
|
|
2009-05-28 21:12:44 +00:00
|
|
|
|
if(dtable_load(dt) == 0 && createdefault) {
|
2008-08-25 16:22:50 +00:00
|
|
|
|
/* No records available */
|
|
|
|
|
ae = access_entry_find(NULL, 1);
|
2008-04-29 06:53:21 +00:00
|
|
|
|
|
2008-08-25 16:22:50 +00:00
|
|
|
|
free(ae->ae_comment);
|
|
|
|
|
ae->ae_comment = strdup("Default access entry");
|
2008-04-29 06:53:21 +00:00
|
|
|
|
|
2008-08-25 16:22:50 +00:00
|
|
|
|
ae->ae_enabled = 1;
|
|
|
|
|
ae->ae_rights = 0xffffffff;
|
2008-04-29 06:53:21 +00:00
|
|
|
|
|
2008-08-25 16:22:50 +00:00
|
|
|
|
r = access_record_build(ae);
|
|
|
|
|
dtable_record_store(dt, ae->ae_id, r);
|
|
|
|
|
htsmsg_destroy(r);
|
2008-04-29 06:53:21 +00:00
|
|
|
|
|
2009-07-18 15:50:10 +00:00
|
|
|
|
tvhlog(LOG_WARNING, "accesscontrol",
|
|
|
|
|
"Created default wide open access controle entry");
|
2008-04-29 06:53:21 +00:00
|
|
|
|
}
|
2009-05-28 21:12:44 +00:00
|
|
|
|
|
|
|
|
|
/* Load superuser account */
|
|
|
|
|
|
|
|
|
|
if((m = hts_settings_load("superuser")) != NULL) {
|
2009-06-10 05:54:48 +00:00
|
|
|
|
s = htsmsg_get_str(m, "username");
|
|
|
|
|
superuser_username = s ? strdup(s) : NULL;
|
|
|
|
|
s = htsmsg_get_str(m, "password");
|
|
|
|
|
superuser_password =s ? strdup(s) : NULL;
|
|
|
|
|
htsmsg_destroy(m);
|
2009-05-28 21:12:44 +00:00
|
|
|
|
}
|
2008-04-29 06:53:21 +00:00
|
|
|
|
}
|