static int
netmask_verify(access_entry_t *ae, struct sockaddr *src)
{
+ access_ipmask_t *ai;
int isv4v6 = 0;
uint32_t v4v6 = 0;
}
}
- 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 || slen > 128)
+ continue;
+
+ while(slen >= 8)
+ {
+ if(a8[apos] != m8[apos])
+ continue;
+
+ apos += 1;
+ slen -= 8;
+ }
+
+ if(slen == 0 || (a8[apos] & lastMask) == (m8[apos] & lastMask))
+ return 1;
}
-
- if(slen == 0)
- return 1;
-
- return (a8[apos] & lastMask) == (m8[apos] & lastMask);
}
return 0;
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);
+ while((ai = LIST_FIRST(&ae->ae_ipmasks)) != NULL)
+ {
+ LIST_REMOVE(ai, ai_link);
+ free(ai);
+ }
- if(strchr(buf, ':') != NULL)
- ae->ae_ipv6 = 1;
- else
- ae->ae_ipv6 = 0;
+ strncpy(tokbuf, prefix, 4095);
+ tokbuf[4095] = 0;
+ tok = strtok_r(tokbuf, ",;| ", &saveptr);
- if(ae->ae_ipv6)
+ 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 > 128)
- return;
- } else {
- prefixlen = 128;
+ free(ai);
+ tok = strtok_r(NULL, ",;| ", &saveptr);
+ continue;
}
- ae->ae_prefixlen = prefixlen;
- inet_pton(AF_INET6, buf, &ae->ae_ip6);
+ strcpy(buf, tok);
- ae->ae_netmask = 0xffffffff;
- ae->ae_network = 0x00000000;
- }
- else
- {
- p = strchr(buf, '/');
- if(p)
+ 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++ = 0;
- prefixlen = atoi(p);
- if(prefixlen > 32)
- return;
- } else {
- prefixlen = 32;
+ 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;
}
- ae->ae_ip.s_addr = inet_addr(buf);
- ae->ae_prefixlen = prefixlen;
+ LIST_INSERT_HEAD(&ae->ae_ipmasks, ai, ai_link);
- ae->ae_netmask = prefixlen ? 0xffffffff << (32 - prefixlen) : 0;
- ae->ae_network = ntohl(ae->ae_ip.s_addr) & ae->ae_netmask;
+ tok = strtok_r(NULL, ",;| ", &saveptr);
}
}
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);
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);
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);
dtable_t *dt;
htsmsg_t *r, *m;
access_entry_t *ae;
+ access_ipmask_t *ai;
const char *s;
static struct {
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;
-
- 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;
+ ai = calloc(1, sizeof(access_ipmask_t));
+ ai->ai_ipv6 = 0;
+ LIST_INSERT_HEAD(&ae->ae_ipmasks, ai, ai_link);
- 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 */