[pulseaudio-commits] r1123 - in /trunk/src: ./ Makefile.am pulsecore/ipacl.c pulsecore/ipacl.h tests/ipacl-test.c

svnmailer-noreply at 0pointer.de svnmailer-noreply at 0pointer.de
Thu Jul 20 09:48:28 PDT 2006


Author: lennart
Date: Thu Jul 20 18:48:26 2006
New Revision: 1123

URL: http://0pointer.de/cgi-bin/viewcvs.cgi?rev=1123&root=pulseaudio&view=rev
Log:
add IP address ACL subsystem

Added:
    trunk/src/pulsecore/ipacl.c   (with props)
    trunk/src/pulsecore/ipacl.h   (with props)
    trunk/src/tests/ipacl-test.c   (with props)
Modified:
    trunk/src/   (props changed)
    trunk/src/Makefile.am

Propchange: trunk/src/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Thu Jul 20 18:48:26 2006
@@ -1,3 +1,4 @@
+ipacl-test
 interpol-test
 get-binary-name-test
 utf8-test

Modified: trunk/src/Makefile.am
URL: http://0pointer.de/cgi-bin/viewcvs.cgi/trunk/src/Makefile.am?rev=1123&root=pulseaudio&r1=1122&r2=1123&view=diff
==============================================================================
--- trunk/src/Makefile.am (original)
+++ trunk/src/Makefile.am Thu Jul 20 18:48:26 2006
@@ -194,7 +194,8 @@
 		channelmap-test \
 		thread-mainloop-test \
 		utf8-test \
-		get-binary-name-test
+		get-binary-name-test \
+		ipacl-test
 
 if HAVE_SIGXCPU
 noinst_PROGRAMS += \
@@ -226,6 +227,11 @@
 get_binary_name_test_CFLAGS = $(AM_CFLAGS)
 get_binary_name_test_LDADD = $(AM_LDADD) libpulse.la
 get_binary_name_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
+
+ipacl_test_SOURCES = tests/ipacl-test.c pulsecore/ipacl.c pulsecore/ipacl.h
+ipacl_test_CFLAGS = $(AM_CFLAGS)
+ipacl_test_LDADD = $(AM_LDADD) libpulsecore.la
+ipacl_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
 
 mcalign_test_SOURCES = tests/mcalign-test.c
 mcalign_test_CFLAGS = $(AM_CFLAGS)
@@ -586,6 +592,7 @@
 		pulsecore/socket-util.h \
 		pulsecore/iochannel.h \
 		pulsecore/socket-server.h \
+		pulsecore/ipacl.h \
 		pulsecore/socket-client.h \
 		pulsecore/parseaddr.h \
 		pulsecore/packet.h \
@@ -615,6 +622,7 @@
 		libsocket-util.la \
 		libiochannel.la \
 		libsocket-server.la \
+		libipacl.la \
 		libparseaddr.la \
 		libsocket-client.la \
 		libpacket.la \
@@ -667,6 +675,10 @@
 		pulsecore/socket-server.c pulsecore/socket-server.h
 libsocket_server_la_LDFLAGS = -avoid-version
 libsocket_server_la_LIBADD = $(AM_LIBADD) libpulsecore.la libiochannel.la libsocket-util.la $(LIBWRAP_LIBS) $(WINSOCK_LIBS)
+
+libipacl_la_SOURCES = pulsecore/ipacl.h pulsecore/ipacl.c
+libipacl_la_LDFLAGS = -avoid-version
+libipacl_la_LIBADD = $(AM_LIBADD) libpulsecore.la $(WINSOCK_LIBS)
 
 libsocket_client_la_SOURCES = pulsecore/socket-client.c pulsecore/socket-client.h
 libsocket_client_la_LDFLAGS = -avoid-version

Added: trunk/src/pulsecore/ipacl.c
URL: http://0pointer.de/cgi-bin/viewcvs.cgi/trunk/src/pulsecore/ipacl.c?rev=1123&root=pulseaudio&view=auto
==============================================================================
--- trunk/src/pulsecore/ipacl.c (added)
+++ trunk/src/pulsecore/ipacl.c Thu Jul 20 18:48:26 2006
@@ -1,0 +1,216 @@
+/* $Id$ */
+
+/***
+  This file is part of PulseAudio.
+ 
+  PulseAudio is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License as
+  published by the Free Software Foundation; either version 2.1 of the
+  License, or (at your option) any later version.
+ 
+  PulseAudio 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
+  Lesser General Public License for more details.
+ 
+  You should have received a copy of the GNU Lesser General Public
+  License along with PulseAudio; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+  USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <sys/types.h>
+#include <arpa/inet.h>
+#include <string.h>
+
+#include <pulsecore/core-util.h>
+#include <pulsecore/llist.h>
+#include <pulsecore/log.h>
+#include <pulse/xmalloc.h>
+
+#include "ipacl.h"
+
+struct acl_entry {
+    PA_LLIST_FIELDS(struct acl_entry);
+    int family;    
+    struct in_addr address_ipv4;
+    struct in6_addr address_ipv6;
+    int bits;
+};
+
+struct pa_ip_acl {
+    PA_LLIST_HEAD(struct acl_entry, entries);
+};
+
+pa_ip_acl* pa_ip_acl_new(const char *s) {
+    const char *state = NULL;
+    char *a;
+    pa_ip_acl *acl;
+
+    assert(s);
+    
+    acl = pa_xnew(pa_ip_acl, 1);
+    PA_LLIST_HEAD_INIT(struct acl_entry, acl->entries);
+    
+    while ((a = pa_split(s, ";", &state))) {
+        char *slash;
+        struct acl_entry e, *n;
+        uint32_t bits;
+
+        if ((slash = strchr(a, '/'))) {
+            *slash = 0;
+            slash++;
+            if (pa_atou(slash, &bits) < 0) {
+                pa_log(__FILE__": failed to parse number of bits: %s", slash);
+                goto fail;
+            }
+        } else
+            bits = (uint32_t) -1;
+
+        if (inet_pton(AF_INET, a, &e.address_ipv4) > 0) {
+
+            e.bits = bits == (uint32_t) -1 ? 32 : (int) bits;
+            
+            if (e.bits > 32) {
+                pa_log(__FILE__": number of bits out of range: %i", e.bits);
+                goto fail;
+            }
+
+            e.family = AF_INET;
+
+            if (e.bits < 32 && (uint32_t) (ntohl(e.address_ipv4.s_addr) << e.bits) != 0)
+                pa_log_warn(__FILE__": WARNING: Host part of ACL entry '%s/%u' is not zero!", a, e.bits);
+                
+        } else if (inet_pton(AF_INET6, a, &e.address_ipv6) > 0) {
+
+            e.bits = bits == (uint32_t) -1 ? 128 : (int) bits;
+
+            if (e.bits > 128) {
+                pa_log(__FILE__": number of bits out of range: %i", e.bits);
+                goto fail;
+            }
+            e.family = AF_INET6;
+
+            if (e.bits < 128) {
+                int t = 0, i;
+
+                for (i = 0, bits = e.bits; i < 16; i++) {
+
+                    if (bits >= 8) 
+                        bits -= 8;
+                    else {
+                        if ((uint8_t) ((e.address_ipv6.s6_addr[i]) << bits) != 0) {
+                            t = 1;
+                            break;
+                        }
+                        bits = 0;
+                    }
+                }
+
+                if (t)
+                    pa_log_warn(__FILE__": WARNING: Host part of ACL entry '%s/%u' is not zero!", a, e.bits);
+            }
+            
+        } else {
+            pa_log(__FILE__": failed to parse address: %s", a);
+            goto fail;
+        }
+
+        n = pa_xmemdup(&e, sizeof(struct acl_entry));
+        PA_LLIST_PREPEND(struct acl_entry, acl->entries, n);
+        
+        pa_xfree(a);
+    }
+
+    return acl;
+    
+fail:
+    pa_xfree(a);
+    pa_ip_acl_free(acl);
+    
+    return NULL;
+}
+
+void pa_ip_acl_free(pa_ip_acl *acl) {
+    assert(acl);
+
+    while (acl->entries) {
+        struct acl_entry *e = acl->entries;
+        PA_LLIST_REMOVE(struct acl_entry, acl->entries, e);
+        pa_xfree(e);
+    }
+    
+    pa_xfree(acl);
+}
+
+int pa_ip_acl_check(pa_ip_acl *acl, int fd) {
+    struct sockaddr_storage sa;
+    struct acl_entry *e;
+    socklen_t  salen;
+        
+    assert(acl);
+    assert(fd >= 0);
+
+    salen = sizeof(sa);
+    if (getpeername(fd, (struct sockaddr*) &sa, &salen) < 0)
+        return -1;
+
+    if (sa.ss_family != AF_INET && sa.ss_family != AF_INET6)
+        return -1;
+
+    if (sa.ss_family == AF_INET && salen != sizeof(struct sockaddr_in))
+        return -1;
+
+    if (sa.ss_family == AF_INET6 && salen != sizeof(struct sockaddr_in6))
+        return -1;
+    
+    for (e = acl->entries; e; e = e->next) {
+
+        if (e->family != sa.ss_family)
+            continue;
+
+        if (e->family == AF_INET) {
+            struct sockaddr_in *sai = (struct sockaddr_in*) &sa;
+            
+            if (e->bits == 0 || /* this needs special handling because >> takes the right-hand side modulo 32 */
+                (ntohl(sai->sin_addr.s_addr ^ e->address_ipv4.s_addr) >> (32 - e->bits)) == 0)
+                return 1;
+        } else if (e->family == AF_INET6) {
+            int i, bits ;
+            struct sockaddr_in6 *sai = (struct sockaddr_in6*) &sa;
+
+            if (e->bits == 128)
+                return memcmp(&sai->sin6_addr, &e->address_ipv6, 16) == 0;
+
+            if (e->bits == 0)
+                return 1;
+                
+            for (i = 0, bits = e->bits; i < 16; i++) {
+
+                if (bits >= 8) {
+                    if (sai->sin6_addr.s6_addr[i] != e->address_ipv6.s6_addr[i])
+                        break;
+
+                    bits -= 8;
+                } else {
+                    if ((sai->sin6_addr.s6_addr[i] ^ e->address_ipv6.s6_addr[i]) >> (8 - bits) != 0)
+                        break;
+
+                    bits = 0;
+                }
+
+                if (bits == 0)
+                    return 1;
+            }
+        }
+    }
+
+    return 0;
+}

Propchange: trunk/src/pulsecore/ipacl.c
------------------------------------------------------------------------------
    svn:keywords = Id

Added: trunk/src/pulsecore/ipacl.h
URL: http://0pointer.de/cgi-bin/viewcvs.cgi/trunk/src/pulsecore/ipacl.h?rev=1123&root=pulseaudio&view=auto
==============================================================================
--- trunk/src/pulsecore/ipacl.h (added)
+++ trunk/src/pulsecore/ipacl.h Thu Jul 20 18:48:26 2006
@@ -1,0 +1,31 @@
+#ifndef fooparseaddrhfoo
+#define fooparseaddrhfoo
+
+/* $Id$ */
+
+/***
+  This file is part of PulseAudio.
+ 
+  PulseAudio is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License as
+  published by the Free Software Foundation; either version 2.1 of the
+  License, or (at your option) any later version.
+ 
+  PulseAudio 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
+  Lesser General Public License for more details.
+ 
+  You should have received a copy of the GNU Lesser General Public
+  License along with PulseAudio; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+  USA.
+***/
+
+typedef struct pa_ip_acl pa_ip_acl;
+
+pa_ip_acl* pa_ip_acl_new(const char *s);
+void pa_ip_acl_free(pa_ip_acl *acl);
+int pa_ip_acl_check(pa_ip_acl *acl, int fd);
+
+#endif

Propchange: trunk/src/pulsecore/ipacl.h
------------------------------------------------------------------------------
    svn:keywords = Id

Added: trunk/src/tests/ipacl-test.c
URL: http://0pointer.de/cgi-bin/viewcvs.cgi/trunk/src/tests/ipacl-test.c?rev=1123&root=pulseaudio&view=auto
==============================================================================
--- trunk/src/tests/ipacl-test.c (added)
+++ trunk/src/tests/ipacl-test.c Thu Jul 20 18:48:26 2006
@@ -1,0 +1,117 @@
+/* $Id$ */
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include <assert.h>
+#include <string.h>
+
+#include <pulsecore/ipacl.h>
+
+int main(int argc, char *argv[]) {
+    struct sockaddr_in sa;
+    struct sockaddr_in6 sa6;
+    int fd;
+    int r;
+    pa_ip_acl *acl;
+
+    fd = socket(PF_INET, SOCK_STREAM, 0); 
+    assert(fd >= 0);
+    
+    sa.sin_family = AF_INET;
+    sa.sin_port = htons(22);
+    sa.sin_addr.s_addr = inet_addr("127.0.0.1");
+        
+    r = connect(fd, (struct sockaddr*) &sa, sizeof(sa));
+    assert(r >= 0);
+
+    acl = pa_ip_acl_new("127.0.0.1");
+    assert(acl);
+    printf("result=%u (should be 1)\n", pa_ip_acl_check(acl, fd));
+    pa_ip_acl_free(acl);
+
+    acl = pa_ip_acl_new("127.0.0.2/0");
+    assert(acl);
+    printf("result=%u (should be 1)\n", pa_ip_acl_check(acl, fd));
+    pa_ip_acl_free(acl);
+
+    acl = pa_ip_acl_new("127.0.0.1/32");
+    assert(acl);
+    printf("result=%u (should be 1)\n", pa_ip_acl_check(acl, fd));
+    pa_ip_acl_free(acl);
+
+    acl = pa_ip_acl_new("127.0.0.1/7");
+    assert(acl);
+    printf("result=%u (should be 1)\n", pa_ip_acl_check(acl, fd));
+    pa_ip_acl_free(acl);
+    
+    acl = pa_ip_acl_new("127.0.0.2");
+    assert(acl);
+    printf("result=%u (should be 0)\n", pa_ip_acl_check(acl, fd));
+    pa_ip_acl_free(acl);
+
+    acl = pa_ip_acl_new("127.0.0.0/8;0.0.0.0/32");
+    assert(acl);
+    printf("result=%u (should be 1)\n", pa_ip_acl_check(acl, fd));
+    pa_ip_acl_free(acl);
+
+    acl = pa_ip_acl_new("128.0.0.2/9");
+    assert(acl);
+    printf("result=%u (should be 0)\n", pa_ip_acl_check(acl, fd));
+    pa_ip_acl_free(acl);
+
+    acl = pa_ip_acl_new("::1/9");
+    assert(acl);
+    printf("result=%u (should be 0)\n", pa_ip_acl_check(acl, fd));
+    pa_ip_acl_free(acl);
+    
+    close(fd);
+
+    fd = socket(PF_INET6, SOCK_STREAM, 0);
+    assert(fd >= 0);
+
+    memset(&sa6, 0, sizeof(sa6));
+    sa6.sin6_family = AF_INET6;
+    sa6.sin6_port = htons(22);
+    inet_pton(AF_INET6, "::1", &sa6.sin6_addr);
+        
+    r = connect(fd, (struct sockaddr*) &sa6, sizeof(sa6));
+    assert(r >= 0);
+
+    acl = pa_ip_acl_new("::1");
+    assert(acl);
+    printf("result=%u (should be 1)\n", pa_ip_acl_check(acl, fd));
+    pa_ip_acl_free(acl);
+
+    acl = pa_ip_acl_new("::1/9");
+    assert(acl);
+    printf("result=%u (should be 1)\n", pa_ip_acl_check(acl, fd));
+    pa_ip_acl_free(acl);
+
+    acl = pa_ip_acl_new("::/0");
+    assert(acl);
+    printf("result=%u (should be 1)\n", pa_ip_acl_check(acl, fd));
+    pa_ip_acl_free(acl);
+
+    acl = pa_ip_acl_new("::2/128");
+    assert(acl);
+    printf("result=%u (should be 0)\n", pa_ip_acl_check(acl, fd));
+    pa_ip_acl_free(acl);
+
+    acl = pa_ip_acl_new("::2/127");
+    assert(acl);
+    printf("result=%u (should be 0)\n", pa_ip_acl_check(acl, fd));
+    pa_ip_acl_free(acl);
+
+    acl = pa_ip_acl_new("::2/126");
+    assert(acl);
+    printf("result=%u (should be 1)\n", pa_ip_acl_check(acl, fd));
+    pa_ip_acl_free(acl);
+
+    close(fd);
+    
+    return 0;
+}

Propchange: trunk/src/tests/ipacl-test.c
------------------------------------------------------------------------------
    svn:keywords = Id




More information about the pulseaudio-commits mailing list