Convert prefix to a , seperated list of multiple prefixes
This commit is contained in:
parent
3b758e5ce7
commit
89c3271368
2 changed files with 163 additions and 104 deletions
246
src/access.c
246
src/access.c
|
@ -155,6 +155,7 @@ access_ticket_verify(const char *id, const char *resource)
|
|||
static int
|
||||
netmask_verify(access_entry_t *ae, struct sockaddr *src)
|
||||
{
|
||||
access_ipmask_t *ai;
|
||||
int isv4v6 = 0;
|
||||
uint32_t v4v6 = 0;
|
||||
|
||||
|
@ -169,45 +170,48 @@ netmask_verify(access_entry_t *ae, struct sockaddr *src)
|
|||
}
|
||||
}
|
||||
|
||||
if(ae->ae_ipv6 == 0 && src->sa_family == AF_INET)
|
||||
LIST_FOREACH(ai, &ae->ae_ipmasks, ai_link)
|
||||
{
|
||||
struct sockaddr_in *in4 = (struct sockaddr_in *)src;
|
||||
uint32_t b = ntohl(in4->sin_addr.s_addr);
|
||||
return (b & ae->ae_netmask) == ae->ae_network;
|
||||
}
|
||||
else if(ae->ae_ipv6 == 0 && isv4v6)
|
||||
{
|
||||
return (v4v6 & ae->ae_netmask) == ae->ae_network;
|
||||
}
|
||||
else if(ae->ae_ipv6 && isv4v6)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if(ae->ae_ipv6 && src->sa_family == AF_INET6)
|
||||
{
|
||||
struct in6_addr *in6 = &(((struct sockaddr_in6 *)src)->sin6_addr);
|
||||
uint8_t *a8 = (uint8_t*)in6->s6_addr;
|
||||
uint8_t *m8 = (uint8_t*)ae->ae_ip6.s6_addr;
|
||||
int slen = ae->ae_prefixlen;
|
||||
uint32_t apos = 0;
|
||||
uint8_t lastMask = (0xFFu << (8 - (slen % 8)));
|
||||
|
||||
if(slen < 0 || slen > 128)
|
||||
return 0;
|
||||
|
||||
while(slen >= 8)
|
||||
if(ai->ai_ipv6 == 0 && src->sa_family == AF_INET)
|
||||
{
|
||||
if(a8[apos] != m8[apos])
|
||||
return 0;
|
||||
|
||||
apos += 1;
|
||||
slen -= 8;
|
||||
struct sockaddr_in *in4 = (struct sockaddr_in *)src;
|
||||
uint32_t b = ntohl(in4->sin_addr.s_addr);
|
||||
if((b & ai->ai_netmask) == ai->ai_network)
|
||||
return 1;
|
||||
}
|
||||
else if(ai->ai_ipv6 == 0 && isv4v6)
|
||||
{
|
||||
if((v4v6 & ai->ai_netmask) == ai->ai_network)
|
||||
return 1;
|
||||
}
|
||||
else if(ai->ai_ipv6 && isv4v6)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if(ai->ai_ipv6 && src->sa_family == AF_INET6)
|
||||
{
|
||||
struct in6_addr *in6 = &(((struct sockaddr_in6 *)src)->sin6_addr);
|
||||
uint8_t *a8 = (uint8_t*)in6->s6_addr;
|
||||
uint8_t *m8 = (uint8_t*)ai->ai_ip6.s6_addr;
|
||||
int slen = ai->ai_prefixlen;
|
||||
uint32_t apos = 0;
|
||||
uint8_t lastMask = (0xFFu << (8 - (slen % 8)));
|
||||
|
||||
if(slen == 0)
|
||||
return 1;
|
||||
if(slen < 0 || slen > 128)
|
||||
continue;
|
||||
|
||||
return (a8[apos] & lastMask) == (m8[apos] & lastMask);
|
||||
while(slen >= 8)
|
||||
{
|
||||
if(a8[apos] != m8[apos])
|
||||
continue;
|
||||
|
||||
apos += 1;
|
||||
slen -= 8;
|
||||
}
|
||||
|
||||
if(slen == 0 || (a8[apos] & lastMask) == (m8[apos] & lastMask))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -351,56 +355,89 @@ static void
|
|||
access_set_prefix(access_entry_t *ae, const char *prefix)
|
||||
{
|
||||
char buf[100];
|
||||
char tokbuf[4096];
|
||||
int prefixlen;
|
||||
char *p;
|
||||
char *p, *tok, *saveptr;
|
||||
access_ipmask_t *ai;
|
||||
|
||||
if(strlen(prefix) > 90)
|
||||
return;
|
||||
|
||||
strcpy(buf, prefix);
|
||||
|
||||
if(strchr(buf, ':') != NULL)
|
||||
ae->ae_ipv6 = 1;
|
||||
else
|
||||
ae->ae_ipv6 = 0;
|
||||
|
||||
if(ae->ae_ipv6)
|
||||
while((ai = LIST_FIRST(&ae->ae_ipmasks)) != NULL)
|
||||
{
|
||||
p = strchr(buf, '/');
|
||||
if(p)
|
||||
{
|
||||
*p++ = 0;
|
||||
prefixlen = atoi(p);
|
||||
if(prefixlen > 128)
|
||||
return;
|
||||
} else {
|
||||
prefixlen = 128;
|
||||
}
|
||||
|
||||
ae->ae_prefixlen = prefixlen;
|
||||
inet_pton(AF_INET6, buf, &ae->ae_ip6);
|
||||
|
||||
ae->ae_netmask = 0xffffffff;
|
||||
ae->ae_network = 0x00000000;
|
||||
LIST_REMOVE(ai, ai_link);
|
||||
free(ai);
|
||||
}
|
||||
else
|
||||
|
||||
strncpy(tokbuf, prefix, 4095);
|
||||
tokbuf[4095] = 0;
|
||||
tok = strtok_r(tokbuf, ",;| ", &saveptr);
|
||||
|
||||
while(tok != NULL)
|
||||
{
|
||||
p = strchr(buf, '/');
|
||||
if(p)
|
||||
ai = calloc(1, sizeof(access_ipmask_t));
|
||||
|
||||
if(strlen(tok) > 90 || strlen(tok) == 0)
|
||||
{
|
||||
*p++ = 0;
|
||||
prefixlen = atoi(p);
|
||||
if(prefixlen > 32)
|
||||
return;
|
||||
} else {
|
||||
prefixlen = 32;
|
||||
free(ai);
|
||||
tok = strtok_r(NULL, ",;| ", &saveptr);
|
||||
continue;
|
||||
}
|
||||
|
||||
ae->ae_ip.s_addr = inet_addr(buf);
|
||||
ae->ae_prefixlen = prefixlen;
|
||||
strcpy(buf, tok);
|
||||
|
||||
ae->ae_netmask = prefixlen ? 0xffffffff << (32 - prefixlen) : 0;
|
||||
ae->ae_network = ntohl(ae->ae_ip.s_addr) & ae->ae_netmask;
|
||||
if(strchr(buf, ':') != NULL)
|
||||
ai->ai_ipv6 = 1;
|
||||
else
|
||||
ai->ai_ipv6 = 0;
|
||||
|
||||
if(ai->ai_ipv6)
|
||||
{
|
||||
p = strchr(buf, '/');
|
||||
if(p)
|
||||
{
|
||||
*p++ = 0;
|
||||
prefixlen = atoi(p);
|
||||
if(prefixlen > 128)
|
||||
{
|
||||
free(ai);
|
||||
tok = strtok_r(NULL, ",;| ", &saveptr);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
prefixlen = 128;
|
||||
}
|
||||
|
||||
ai->ai_prefixlen = prefixlen;
|
||||
inet_pton(AF_INET6, buf, &ai->ai_ip6);
|
||||
|
||||
ai->ai_netmask = 0xffffffff;
|
||||
ai->ai_network = 0x00000000;
|
||||
}
|
||||
else
|
||||
{
|
||||
p = strchr(buf, '/');
|
||||
if(p)
|
||||
{
|
||||
*p++ = 0;
|
||||
prefixlen = atoi(p);
|
||||
if(prefixlen > 32)
|
||||
{
|
||||
free(ai);
|
||||
tok = strtok_r(NULL, ",;| ", &saveptr);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
prefixlen = 32;
|
||||
}
|
||||
|
||||
ai->ai_ip.s_addr = inet_addr(buf);
|
||||
ai->ai_prefixlen = prefixlen;
|
||||
|
||||
ai->ai_netmask = prefixlen ? 0xffffffff << (32 - prefixlen) : 0;
|
||||
ai->ai_network = ntohl(ai->ai_ip.s_addr) & ai->ai_netmask;
|
||||
}
|
||||
|
||||
LIST_INSERT_HEAD(&ae->ae_ipmasks, ai, ai_link);
|
||||
|
||||
tok = strtok_r(NULL, ",;| ", &saveptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -450,6 +487,14 @@ access_entry_find(const char *id, int create)
|
|||
static void
|
||||
access_entry_destroy(access_entry_t *ae)
|
||||
{
|
||||
access_ipmask_t *ai;
|
||||
|
||||
while((ai = LIST_FIRST(&ae->ae_ipmasks)) != NULL)
|
||||
{
|
||||
LIST_REMOVE(ai, ai_link);
|
||||
free(ai);
|
||||
}
|
||||
|
||||
free(ae->ae_id);
|
||||
free(ae->ae_username);
|
||||
free(ae->ae_password);
|
||||
|
@ -465,8 +510,12 @@ static htsmsg_t *
|
|||
access_record_build(access_entry_t *ae)
|
||||
{
|
||||
htsmsg_t *e = htsmsg_create_map();
|
||||
access_ipmask_t *ai;
|
||||
char addrbuf[50];
|
||||
char buf[100];
|
||||
char buf[4096];
|
||||
int pos = 0;
|
||||
|
||||
memset(buf, 0, 4096);
|
||||
|
||||
htsmsg_add_u32(e, "enabled", !!ae->ae_enabled);
|
||||
|
||||
|
@ -474,14 +523,22 @@ access_record_build(access_entry_t *ae)
|
|||
htsmsg_add_str(e, "password", ae->ae_password);
|
||||
htsmsg_add_str(e, "comment", ae->ae_comment);
|
||||
|
||||
if(ae->ae_ipv6)
|
||||
LIST_FOREACH(ai, &ae->ae_ipmasks, ai_link)
|
||||
{
|
||||
inet_ntop(AF_INET6, &ae->ae_ip6, addrbuf, 50);
|
||||
snprintf(buf, sizeof(buf), "%s/%d", addrbuf, ae->ae_prefixlen);
|
||||
if(sizeof(buf)-pos <= 0)
|
||||
break;
|
||||
|
||||
if(ai->ai_ipv6)
|
||||
{
|
||||
inet_ntop(AF_INET6, &ai->ai_ip6, addrbuf, 50);
|
||||
pos += snprintf(buf+pos, sizeof(buf)-pos, ",%s/%d", addrbuf, ai->ai_prefixlen);
|
||||
}
|
||||
else
|
||||
{
|
||||
pos += snprintf(buf+pos, sizeof(buf)-pos, ",%s/%d", inet_ntoa(ai->ai_ip), ai->ai_prefixlen);
|
||||
}
|
||||
}
|
||||
else
|
||||
snprintf(buf, sizeof(buf), "%s/%d", inet_ntoa(ae->ae_ip), ae->ae_prefixlen);
|
||||
htsmsg_add_str(e, "prefix", buf);
|
||||
htsmsg_add_str(e, "prefix", buf + 1);
|
||||
|
||||
htsmsg_add_u32(e, "streaming", ae->ae_rights & ACCESS_STREAMING ? 1 : 0);
|
||||
htsmsg_add_u32(e, "dvr" , ae->ae_rights & ACCESS_RECORDER ? 1 : 0);
|
||||
|
@ -631,6 +688,7 @@ access_init(int createdefault)
|
|||
dtable_t *dt;
|
||||
htsmsg_t *r, *m;
|
||||
access_entry_t *ae;
|
||||
access_ipmask_t *ai;
|
||||
const char *s;
|
||||
|
||||
static struct {
|
||||
|
@ -652,33 +710,25 @@ access_init(int createdefault)
|
|||
ae = access_entry_find(NULL, 1);
|
||||
|
||||
free(ae->ae_comment);
|
||||
ae->ae_comment = strdup("Default IPv6 access entry");
|
||||
ae->ae_comment = strdup("Default access entry");
|
||||
|
||||
ae->ae_enabled = 1;
|
||||
ae->ae_rights = 0xffffffff;
|
||||
|
||||
ae->ae_ipv6 = 1;
|
||||
ai = calloc(1, sizeof(access_ipmask_t));
|
||||
ai->ai_ipv6 = 0;
|
||||
LIST_INSERT_HEAD(&ae->ae_ipmasks, ai, ai_link);
|
||||
|
||||
r = access_record_build(ae);
|
||||
dtable_record_store(dt, ae->ae_id, r);
|
||||
htsmsg_destroy(r);
|
||||
|
||||
ae = access_entry_find(NULL, 1);
|
||||
|
||||
free(ae->ae_comment);
|
||||
ae->ae_comment = strdup("Default IPv4 access entry");
|
||||
|
||||
ae->ae_enabled = 1;
|
||||
ae->ae_rights = 0xffffffff;
|
||||
|
||||
ae->ae_ipv6 = 0;
|
||||
ai = calloc(1, sizeof(access_ipmask_t));
|
||||
ai->ai_ipv6 = 1;
|
||||
LIST_INSERT_HEAD(&ae->ae_ipmasks, ai, ai_link);
|
||||
|
||||
r = access_record_build(ae);
|
||||
dtable_record_store(dt, ae->ae_id, r);
|
||||
htsmsg_destroy(r);
|
||||
|
||||
tvhlog(LOG_WARNING, "accesscontrol",
|
||||
"Created default wide open access controle entrys");
|
||||
"Created default wide open access controle entry");
|
||||
}
|
||||
|
||||
/* Load superuser account */
|
||||
|
|
21
src/access.h
21
src/access.h
|
@ -20,6 +20,20 @@
|
|||
#define ACCESS_H_
|
||||
|
||||
|
||||
typedef struct access_ipmask {
|
||||
LIST_ENTRY(access_ipmask) ai_link;
|
||||
|
||||
int ai_ipv6;
|
||||
|
||||
struct in_addr ai_ip;
|
||||
struct in6_addr ai_ip6;
|
||||
|
||||
int ai_prefixlen;
|
||||
|
||||
uint32_t ai_network;
|
||||
uint32_t ai_netmask;
|
||||
} access_ipmask_t;
|
||||
|
||||
TAILQ_HEAD(access_entry_queue, access_entry);
|
||||
|
||||
extern struct access_entry_queue access_entries;
|
||||
|
@ -31,17 +45,12 @@ typedef struct access_entry {
|
|||
char *ae_username;
|
||||
char *ae_password;
|
||||
char *ae_comment;
|
||||
int ae_ipv6;
|
||||
struct in_addr ae_ip;
|
||||
struct in6_addr ae_ip6;
|
||||
int ae_prefixlen;
|
||||
int ae_enabled;
|
||||
|
||||
|
||||
uint32_t ae_rights;
|
||||
|
||||
uint32_t ae_network; /* derived from ae_ip */
|
||||
uint32_t ae_netmask; /* derived from ae_prefixlen */
|
||||
LIST_HEAD(, access_ipmask) ae_ipmasks;
|
||||
} access_entry_t;
|
||||
|
||||
TAILQ_HEAD(access_ticket_queue, access_ticket);
|
||||
|
|
Loading…
Add table
Reference in a new issue