]> git.sesse.net Git - vlc/commitdiff
Better ACL API (full rewrite)
authorRémi Denis-Courmont <rem@videolan.org>
Tue, 12 Jul 2005 16:00:43 +0000 (16:00 +0000)
committerRémi Denis-Courmont <rem@videolan.org>
Tue, 12 Jul 2005 16:00:43 +0000 (16:00 +0000)
14 files changed:
Makefile.am
include/network.h
include/vlc_acl.h [new file with mode: 0644]
include/vlc_common.h
include/vlc_httpd.h
include/vlc_symbols.h
modules/access_output/http.c
modules/control/http.c
modules/misc/rtsp.c
modules/stream_out/rtp.c
src/misc/httpd.c
src/misc/modules.c
src/misc/net.c
src/stream_output/acl.c [new file with mode: 0644]

index 38fd1faf533abe93ae53ebf89870b68d7296a2d8..fb349c8a66e3b1c644412f93914b1bbd47571c54 100644 (file)
@@ -88,6 +88,7 @@ HEADERS_include = \
        include/variables.h \
        include/video_output.h \
        include/vlc_access.h \
+       include/vlc_acl.h \
        include/vlc_bits.h \
        include/vlc_block.h \
        include/vlc_block_helper.h \
@@ -374,6 +375,7 @@ SOURCES_libvlc_common = \
        src/stream_output/stream_output.c \
        src/stream_output/announce.c \
        src/stream_output/sap.c \
+       src/stream_output/acl.c \
        src/misc/charset.c \
        src/misc/httpd.c \
        src/misc/tls.c \
index bbada0f4a02d96bc5ad5206ccc11dc754f2d0292..4fcf4a741f348eeac0e8f25f2f89d95054f0d74d 100644 (file)
@@ -371,9 +371,6 @@ VLC_EXPORT( int, __net_vaPrintf, ( vlc_object_t *p_this, int fd, v_socket_t *, c
 # define net_StopRecv( fd ) (void)0
 #endif
 
-#define net_CheckIP(a,b,c,d) __net_CheckIP(VLC_OBJECT(a),b,c,d)
-VLC_EXPORT( int, __net_CheckIP, ( vlc_object_t *p_this, char *psz_ip, char **ppsz_hosts, int i_hosts ) );
-
 /* Portable network names/addresses resolution layer */
 
 /* GAI error codes */
diff --git a/include/vlc_acl.h b/include/vlc_acl.h
new file mode 100644 (file)
index 0000000..be4d42f
--- /dev/null
@@ -0,0 +1,39 @@
+/*****************************************************************************
+ * vlc_acl.h: interface to the network Access Control List internal API
+ *****************************************************************************
+ * Copyright (C) 2005 Rémi Denis-Courmont
+ * $Id$
+ *
+ * Authors: Rémi Denis-Courmont <rem # videolan.org>
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef __VLC_ACL_H
+# define __VLC_ACL_H
+
+#define ACL_Create(a, b) __ACL_Create(VLC_OBJECT(a), b)
+#define ACL_Duplicate(a,b) __ACL_Duplicate(VLC_OBJECT(a),b)
+
+VLC_EXPORT( int, ACL_Check, ( vlc_acl_t *p_acl, const char *psz_ip ) );
+VLC_EXPORT( vlc_acl_t *, __ACL_Create, ( vlc_object_t *p_this, vlc_bool_t b_allow ) );
+VLC_EXPORT( vlc_acl_t *, __ACL_Duplicate, ( vlc_object_t *p_this, const vlc_acl_t *p_acl ) );
+VLC_EXPORT( void, ACL_Destroy, ( vlc_acl_t *p_acl ) );
+
+#define ACL_AddHost(a,b,c) ACL_AddNet(a,b,-1,c)
+VLC_EXPORT( int, ACL_AddNet, ( vlc_acl_t *p_acl, const char *psz_ip, int i_len, vlc_bool_t b_allow ) );
+VLC_EXPORT( int, ACL_LoadFile, ( vlc_acl_t *p_acl, const char *path ) );
+
+#endif
index 8186b9e9a3ffd29e818f6ad23e44ad9a5059af34..8d2ac57f87d3246059562669d7977e313d46fa12 100644 (file)
@@ -362,6 +362,7 @@ typedef struct virtual_socket_t v_socket_t;
 typedef struct iso639_lang_t iso639_lang_t;
 typedef struct sockaddr sockaddr;
 typedef struct addrinfo addrinfo;
+typedef struct vlc_acl_t vlc_acl_t;
 
 /* block */
 typedef struct block_t      block_t;
index d716fbe40d7a99f2744f31265524cfcebdcc9d37..7947d679cf55f2fb3c54458c6cb5a5b1a2883d85 100644 (file)
@@ -121,8 +121,8 @@ VLC_EXPORT( httpd_host_t *, httpd_TLSHostNew, ( vlc_object_t *, const char *, in
 VLC_EXPORT( void,           httpd_HostDelete, ( httpd_host_t * ) );
 
 /* register a new url */
-VLC_EXPORT( httpd_url_t *,  httpd_UrlNew, ( httpd_host_t *, char *psz_url, char *psz_user, char *psz_password, char **ppsz_hosts, int i_hosts ) );
-VLC_EXPORT( httpd_url_t *,  httpd_UrlNewUnique, ( httpd_host_t *, char *psz_url, char *psz_user, char *psz_password, char **ppsz_hosts, int i_hosts ) );
+VLC_EXPORT( httpd_url_t *,  httpd_UrlNew, ( httpd_host_t *, char *psz_url, char *psz_user, char *psz_password, const vlc_acl_t *p_acl ) );
+VLC_EXPORT( httpd_url_t *,  httpd_UrlNewUnique, ( httpd_host_t *, char *psz_url, char *psz_user, char *psz_password, const vlc_acl_t *p_acl ) );
 /* register callback on a url */
 VLC_EXPORT( int,            httpd_UrlCatch, ( httpd_url_t *, int i_msg, httpd_callback_t, httpd_callback_sys_t * ) );
 /* delete an url */
@@ -135,7 +135,7 @@ VLC_EXPORT( char*,          httpd_ClientIP, ( httpd_client_t *cl ) );
 
 /* High level */
 
-VLC_EXPORT( httpd_file_t *, httpd_FileNew, ( httpd_host_t *, char *psz_url, char *psz_mime, char *psz_user, char *psz_password, char **ppsz_hosts, int i_hosts, httpd_file_callback_t pf_fill, httpd_file_sys_t * ) );
+VLC_EXPORT( httpd_file_t *, httpd_FileNew, ( httpd_host_t *, char *psz_url, char *psz_mime, char *psz_user, char *psz_password, const vlc_acl_t *p_acl, httpd_file_callback_t pf_fill, httpd_file_sys_t * ) );
 VLC_EXPORT( void,           httpd_FileDelete, ( httpd_file_t * ) );
 
 
@@ -143,7 +143,7 @@ VLC_EXPORT( httpd_redirect_t *, httpd_RedirectNew, ( httpd_host_t *, char *psz_u
 VLC_EXPORT( void,               httpd_RedirectDelete, ( httpd_redirect_t * ) );
 
 
-VLC_EXPORT( httpd_stream_t *, httpd_StreamNew,    ( httpd_host_t *, char *psz_url, char *psz_mime, char *psz_user, char *psz_password, char **ppsz_hosts, int i_hosts ) );
+VLC_EXPORT( httpd_stream_t *, httpd_StreamNew,    ( httpd_host_t *, char *psz_url, char *psz_mime, char *psz_user, char *psz_password, const vlc_acl_t *p_acl ) );
 VLC_EXPORT( void,             httpd_StreamDelete, ( httpd_stream_t * ) );
 VLC_EXPORT( int,              httpd_StreamHeader, ( httpd_stream_t *, uint8_t *p_data, int i_data ) );
 VLC_EXPORT( int,              httpd_StreamSend,   ( httpd_stream_t *, uint8_t *p_data, int i_data ) );
index 4af77d556d8199a951ac7a421c4004284b3e067a..f144cc7ae248e81acaeffb734c2dd6a5556b1105 100644 (file)
@@ -195,18 +195,18 @@ struct module_symbols_t
     httpd_host_t * (*httpd_HostNew_inner) (vlc_object_t *, const char *psz_host, int i_port);
     httpd_host_t * (*httpd_TLSHostNew_inner) (vlc_object_t *, const char *, int, const char *, const char *, const char *, const char *);
     void (*httpd_HostDelete_inner) (httpd_host_t *);
-    httpd_url_t * (*httpd_UrlNew_inner) (httpd_host_t *, char *psz_url, char *psz_user, char *psz_password, char **ppsz_hosts, int i_hosts);
-    httpd_url_t * (*httpd_UrlNewUnique_inner) (httpd_host_t *, char *psz_url, char *psz_user, char *psz_password, char **ppsz_hosts, int i_hosts);
+    httpd_url_t * (*httpd_UrlNew_inner) (httpd_host_t *, char *psz_url, char *psz_user, char *psz_password, const vlc_acl_t *p_acl);
+    httpd_url_t * (*httpd_UrlNewUnique_inner) (httpd_host_t *, char *psz_url, char *psz_user, char *psz_password, const vlc_acl_t *p_acl);
     int (*httpd_UrlCatch_inner) (httpd_url_t *, int i_msg, httpd_callback_t, httpd_callback_sys_t *);
     void (*httpd_UrlDelete_inner) (httpd_url_t *);
     void (*httpd_ClientModeStream_inner) (httpd_client_t *cl);
     void (*httpd_ClientModeBidir_inner) (httpd_client_t *cl);
     char* (*httpd_ClientIP_inner) (httpd_client_t *cl);
-    httpd_file_t * (*httpd_FileNew_inner) (httpd_host_t *, char *psz_url, char *psz_mime, char *psz_user, char *psz_password, char **ppsz_hosts, int i_hosts, httpd_file_callback_t pf_fill, httpd_file_sys_t *);
+    httpd_file_t * (*httpd_FileNew_inner) (httpd_host_t *, char *psz_url, char *psz_mime, char *psz_user, char *psz_password, const vlc_acl_t *p_acl, httpd_file_callback_t pf_fill, httpd_file_sys_t *);
     void (*httpd_FileDelete_inner) (httpd_file_t *);
     httpd_redirect_t * (*httpd_RedirectNew_inner) (httpd_host_t *, char *psz_url_dst, char *psz_url_src);
     void (*httpd_RedirectDelete_inner) (httpd_redirect_t *);
-    httpd_stream_t * (*httpd_StreamNew_inner) (httpd_host_t *, char *psz_url, char *psz_mime, char *psz_user, char *psz_password, char **ppsz_hosts, int i_hosts);
+    httpd_stream_t * (*httpd_StreamNew_inner) (httpd_host_t *, char *psz_url, char *psz_mime, char *psz_user, char *psz_password, const vlc_acl_t *p_acl);
     void (*httpd_StreamDelete_inner) (httpd_stream_t *);
     int (*httpd_StreamHeader_inner) (httpd_stream_t *, uint8_t *p_data, int i_data);
     int (*httpd_StreamSend_inner) (httpd_stream_t *, uint8_t *p_data, int i_data);
@@ -375,8 +375,13 @@ struct module_symbols_t
     const char * (*vlc_gai_strerror_inner) (int);
     void (*net_ListenClose_inner) (int *fd);
     void (*DigestMD5_inner) (struct md5_s *, uint32_t *);
-    int (*__net_CheckIP_inner) (vlc_object_t *p_this, char *psz_ip, char **ppsz_hosts, int i_hosts);
+    int (*ACL_Check_inner) (vlc_acl_t *p_acl, const char *psz_ip);
     int (*playlist_NodeRemoveParent_inner) (playlist_t *,playlist_item_t*,playlist_item_t *);
+    vlc_acl_t * (*__ACL_Duplicate_inner) (vlc_object_t *p_this, const vlc_acl_t *p_acl);
+    vlc_acl_t * (*__ACL_Create_inner) (vlc_object_t *p_this, vlc_bool_t b_allow);
+    int (*ACL_LoadFile_inner) (vlc_acl_t *p_acl, const char *path);
+    int (*ACL_AddNet_inner) (vlc_acl_t *p_acl, const char *psz_ip, int i_len, vlc_bool_t b_allow);
+    void (*ACL_Destroy_inner) (vlc_acl_t *p_acl);
 };
 # if defined (__PLUGIN__)
 #  define aout_FiltersCreatePipeline (p_symbols)->aout_FiltersCreatePipeline_inner
@@ -737,8 +742,13 @@ struct module_symbols_t
 #  define vlc_gai_strerror (p_symbols)->vlc_gai_strerror_inner
 #  define net_ListenClose (p_symbols)->net_ListenClose_inner
 #  define DigestMD5 (p_symbols)->DigestMD5_inner
-#  define __net_CheckIP (p_symbols)->__net_CheckIP_inner
+#  define ACL_Check (p_symbols)->ACL_Check_inner
 #  define playlist_NodeRemoveParent (p_symbols)->playlist_NodeRemoveParent_inner
+#  define __ACL_Duplicate (p_symbols)->__ACL_Duplicate_inner
+#  define __ACL_Create (p_symbols)->__ACL_Create_inner
+#  define ACL_LoadFile (p_symbols)->ACL_LoadFile_inner
+#  define ACL_AddNet (p_symbols)->ACL_AddNet_inner
+#  define ACL_Destroy (p_symbols)->ACL_Destroy_inner
 # elif defined (HAVE_DYNAMIC_PLUGINS) && !defined (__BUILTIN__)
 /******************************************************************
  * STORE_SYMBOLS: store VLC APIs into p_symbols for plugin access.
@@ -1102,8 +1112,13 @@ struct module_symbols_t
     ((p_symbols)->vlc_gai_strerror_inner) = vlc_gai_strerror; \
     ((p_symbols)->net_ListenClose_inner) = net_ListenClose; \
     ((p_symbols)->DigestMD5_inner) = DigestMD5; \
-    ((p_symbols)->__net_CheckIP_inner) = __net_CheckIP; \
+    ((p_symbols)->ACL_Check_inner) = ACL_Check; \
     ((p_symbols)->playlist_NodeRemoveParent_inner) = playlist_NodeRemoveParent; \
+    ((p_symbols)->__ACL_Duplicate_inner) = __ACL_Duplicate; \
+    ((p_symbols)->__ACL_Create_inner) = __ACL_Create; \
+    ((p_symbols)->ACL_LoadFile_inner) = ACL_LoadFile; \
+    ((p_symbols)->ACL_AddNet_inner) = ACL_AddNet; \
+    ((p_symbols)->ACL_Destroy_inner) = ACL_Destroy; \
     (p_symbols)->net_ConvertIPv4_deprecated = NULL; \
 
 # endif /* __PLUGIN__ */
index b411dd843ad2a6daecbe1b6740b5d34b8ec71f19..32ba5c1b22b6b178ba0e2e6e22fc5eaef314e006 100644 (file)
@@ -255,7 +255,7 @@ static int Open( vlc_object_t *p_this )
 
     p_sys->p_httpd_stream =
         httpd_StreamNew( p_sys->p_httpd_host, psz_file_name, psz_mime,
-                         psz_user, psz_pwd, NULL, 0 );
+                         psz_user, psz_pwd, NULL );
     if( psz_user ) free( psz_user );
     if( psz_pwd ) free( psz_pwd );
     if( psz_mime ) free( psz_mime );
index a923d1140f1a22637f897eceb381fe0787f1e1e4..ffca4b82301547e461a1e613edc2c3cefd5c08b1 100644 (file)
@@ -40,6 +40,7 @@
 #include "vlc_httpd.h"
 #include "vlc_vlm.h"
 #include "vlc_tls.h"
+#include "vlc_acl.h"
 #include "charset.h"
 
 #ifdef HAVE_SYS_STAT_H
@@ -518,14 +519,13 @@ static int ParseDirectory( intf_thread_t *p_intf, char *psz_root,
 #endif
     DIR           *p_dir;
     struct dirent *p_dir_content;
+    vlc_acl_t     *p_acl;
     FILE          *file;
 
     char          *user = NULL;
     char          *password = NULL;
-    char          **ppsz_hosts = NULL;
-    int           i_hosts = 0;
 
-    int           i, i_dirlen;
+    int           i_dirlen;
 
 #ifdef HAVE_SYS_STAT_H
     if( stat( psz_dir, &stat_info ) == -1 || !S_ISDIR( stat_info.st_mode ) )
@@ -584,41 +584,9 @@ static int ParseDirectory( intf_thread_t *p_intf, char *psz_root,
     }
 
     sprintf( dir, "%s/.hosts", psz_dir );
-    if( ( file = fopen( dir, "r" ) ) != NULL )
-    {
-        char line[1024];
-        int  i_size;
-
-        msg_Dbg( p_intf, "find .hosts in dir=%s", psz_dir );
-
-        while( !feof( file ) )
-        {
-            fgets( line, 1023, file );
-            i_size = strlen(line);
-            if( i_size > 0 && line[0] != '#' )
-            {
-                while( i_size > 0 && ( line[i_size-1] == '\n' ||
-                       line[i_size-1] == '\r' ) )
-                {
-                    i_size--;
-                }
-                if( !i_size ) continue;
-
-                line[i_size] = '\0';
-
-                msg_Dbg( p_intf, "restricted to %s (read=%d)",
-                         line, i_size );
-                TAB_APPEND( i_hosts, ppsz_hosts, strdup( line ) );
-            }
-        }
-
-        fclose( file );
-
-        if( net_CheckIP( p_intf, "0.0.0.0", ppsz_hosts, i_hosts ) < 0 )
-        {
-            msg_Err( p_intf, ".hosts file is invalid in dir=%s", psz_dir );
-        }
-    }
+    p_acl = ACL_Create( p_intf, VLC_FALSE );
+    ACL_LoadFile( p_acl, dir );
+    
 
     for( ;; )
     {
@@ -659,7 +627,7 @@ static int ParseDirectory( intf_thread_t *p_intf, char *psz_root,
             f->p_file = httpd_FileNew( p_sys->p_httpd_host,
                                        f->name,
                                        f->b_html ? p_sys->psz_html_type : NULL,
-                                       user, password, ppsz_hosts, i_hosts,
+                                       user, password, p_acl,
                                        HttpCallback, f );
 
             if( f->p_file )
@@ -701,11 +669,8 @@ static int ParseDirectory( intf_thread_t *p_intf, char *psz_root,
     {
         free( password );
     }
-    for( i = 0; i < i_hosts; i++ )
-    {
-        TAB_REMOVE( i_hosts, ppsz_hosts, ppsz_hosts[0] );
-    }
 
+    ACL_Destroy( p_acl );
     closedir( p_dir );
 
     return VLC_SUCCESS;
index 54950c3aece2745a864e1080f0ac124e06f3191d..fe2e8b49021d2014d4d6734aefd347333697e5b4 100644 (file)
@@ -276,8 +276,8 @@ static vod_media_t *MediaNew( vod_t *p_vod, char *psz_name,
 
     asprintf( &p_media->psz_rtsp_path, "%s%s", p_sys->psz_path, psz_name );
     p_media->p_rtsp_url =
-        httpd_UrlNewUnique( p_sys->p_rtsp_host, p_media->psz_rtsp_path, 0, 0,
-                            NULL, 0 );
+        httpd_UrlNewUnique( p_sys->p_rtsp_host, p_media->psz_rtsp_path, NULL,
+                            NULL, NULL );
 
     if( !p_media->p_rtsp_url )
     {
@@ -465,8 +465,8 @@ static int MediaAddES( vod_t *p_vod, vod_media_t *p_media, es_format_t *p_fmt )
     }
 
     p_es->p_rtsp_url =
-        httpd_UrlNewUnique( p_vod->p_sys->p_rtsp_host, psz_urlc, 0, 0, NULL,
-                            0 );
+        httpd_UrlNewUnique( p_vod->p_sys->p_rtsp_host, psz_urlc, NULL, NULL,
+                            NULL );
 
     if( !p_es->p_rtsp_url )
     {
@@ -637,7 +637,7 @@ static int RtspCallback( httpd_callback_sys_t *p_args, httpd_client_t *cl,
             answer->psz_status = strdup( "OK" );
             httpd_MsgAdd( answer, "Content-type",  "%s", "application/sdp" );
 
-            answer->p_body = psz_sdp;
+            answer->p_body = (uint8_t *)psz_sdp;
             answer->i_body = strlen( psz_sdp );
             break;
         }
index a93c832b751cafb3d072877e31d9690ae98aad93..19ed74197d9aa4da8611d561b8509ff3b34c6146 100644 (file)
@@ -1049,7 +1049,7 @@ static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt )
 
         sprintf( psz_urlc, "%s/trackid=%d", p_sys->psz_rtsp_path, p_sys->i_es );
         fprintf( stderr, "rtsp: adding %s\n", psz_urlc );
-        id->p_rtsp_url = httpd_UrlNewUnique( p_sys->p_rtsp_host, psz_urlc, NULL, NULL, NULL, 0 );
+        id->p_rtsp_url = httpd_UrlNewUnique( p_sys->p_rtsp_host, psz_urlc, NULL, NULL, NULL );
 
         if( id->p_rtsp_url )
         {
@@ -1313,7 +1313,7 @@ static int HttpSetup( sout_stream_t *p_stream, vlc_url_t *url)
         p_sys->p_httpd_file = httpd_FileNew( p_sys->p_httpd_host,
                                              url->psz_path ? url->psz_path : "/",
                                              "application/sdp",
-                                             NULL, NULL, NULL, 0,
+                                             NULL, NULL, NULL,
                                              HttpCallback, (void*)p_sys );
     }
     if( p_sys->p_httpd_file == NULL )
@@ -1411,7 +1411,7 @@ static int RtspSetup( sout_stream_t *p_stream, vlc_url_t *url )
     sprintf( p_sys->psz_rtsp_control, "rtsp://%s:%d%s",
              url->psz_host,  url->i_port > 0 ? url->i_port : 554, p_sys->psz_rtsp_path );
 
-    p_sys->p_rtsp_url = httpd_UrlNewUnique( p_sys->p_rtsp_host, p_sys->psz_rtsp_path, NULL, NULL, NULL, 0 );
+    p_sys->p_rtsp_url = httpd_UrlNewUnique( p_sys->p_rtsp_host, p_sys->psz_rtsp_path, NULL, NULL, NULL );
     if( p_sys->p_rtsp_url == 0 )
     {
         return VLC_EGENERIC;
index 54955ec53e432f13354001fc17bc5d7cdf439c7a..b3e4d001be33b38018f4e027e1513460ca8feb3c 100644 (file)
@@ -30,6 +30,7 @@
 #include "vlc_httpd.h"
 #include "network.h"
 #include "vlc_tls.h"
+#include "vlc_acl.h"
 
 #include <string.h>
 #include <errno.h>
@@ -234,11 +235,10 @@ struct httpd_url_t
 
     vlc_mutex_t lock;
 
-    char    *psz_url;
-    char    *psz_user;
-    char    *psz_password;
-    char    **ppsz_hosts;
-    int     i_hosts;
+    char      *psz_url;
+    char      *psz_user;
+    char      *psz_password;
+    vlc_acl_t *p_acl;
 
     struct
     {
@@ -491,14 +491,13 @@ static int httpd_FileCallBack( httpd_callback_sys_t *p_sys, httpd_client_t *cl,
 httpd_file_t *httpd_FileNew( httpd_host_t *host,
                              char *psz_url, char *psz_mime,
                              char *psz_user, char *psz_password,
-                             char **ppsz_hosts, int i_hosts,
-                             httpd_file_callback_t pf_fill,
+                             const vlc_acl_t *p_acl, httpd_file_callback_t pf_fill,
                              httpd_file_sys_t *p_sys )
 {
     httpd_file_t *file = malloc( sizeof( httpd_file_t ) );
 
     if( ( file->url = httpd_UrlNewUnique( host, psz_url, psz_user,
-                                          psz_password, ppsz_hosts, i_hosts )
+                                          psz_password, p_acl )
         ) == NULL )
     {
         free( file );
@@ -596,8 +595,7 @@ httpd_redirect_t *httpd_RedirectNew( httpd_host_t *host, char *psz_url_dst,
 {
     httpd_redirect_t *rdir = malloc( sizeof( httpd_redirect_t ) );
 
-    if( !( rdir->url = httpd_UrlNewUnique( host, psz_url_src, NULL, NULL,
-                                           NULL, 0 ) ) )
+    if( !( rdir->url = httpd_UrlNewUnique( host, psz_url_src, NULL, NULL, NULL ) ) )
     {
         free( rdir );
         return NULL;
@@ -773,12 +771,12 @@ static int httpd_StreamCallBack( httpd_callback_sys_t *p_sys,
 httpd_stream_t *httpd_StreamNew( httpd_host_t *host,
                                  char *psz_url, char *psz_mime,
                                  char *psz_user, char *psz_password,
-                                 char **ppsz_hosts, int i_hosts )
+                                 const vlc_acl_t *p_acl )
 {
     httpd_stream_t *stream = malloc( sizeof( httpd_stream_t ) );
 
     if( ( stream->url = httpd_UrlNewUnique( host, psz_url, psz_user,
-                                            psz_password, ppsz_hosts, i_hosts )
+                                            psz_password, p_acl )
         ) == NULL )
     {
         free( stream );
@@ -1103,8 +1101,7 @@ void httpd_HostDelete( httpd_host_t *host )
 /* register a new url */
 static httpd_url_t *httpd_UrlNewPrivate( httpd_host_t *host, char *psz_url,
                                          char *psz_user, char *psz_password,
-                                         char **ppsz_hosts, int i_hosts,
-                                         vlc_bool_t b_check )
+                                         const vlc_acl_t *p_acl, vlc_bool_t b_check )
 {
     httpd_url_t *url;
     int         i;
@@ -1131,12 +1128,7 @@ static httpd_url_t *httpd_UrlNewPrivate( httpd_host_t *host, char *psz_url,
     url->psz_url = strdup( psz_url );
     url->psz_user = strdup( psz_user ? psz_user : "" );
     url->psz_password = strdup( psz_password ? psz_password : "" );
-    url->i_hosts = 0;
-    url->ppsz_hosts = NULL;
-    for( i = 0; i < i_hosts; i++ )
-    {
-        TAB_APPEND( url->i_hosts, url->ppsz_hosts, strdup(ppsz_hosts[i]) );
-    }
+    url->p_acl = ACL_Duplicate( host, p_acl );
     for( i = 0; i < HTTPD_MSG_MAX; i++ )
     {
         url->catch[i].cb = NULL;
@@ -1151,18 +1143,18 @@ static httpd_url_t *httpd_UrlNewPrivate( httpd_host_t *host, char *psz_url,
 
 httpd_url_t *httpd_UrlNew( httpd_host_t *host, char *psz_url,
                            char *psz_user, char *psz_password,
-                           char **ppsz_hosts, int i_hosts )
+                           const vlc_acl_t *p_acl )
 {
     return httpd_UrlNewPrivate( host, psz_url, psz_user,
-                                psz_password, ppsz_hosts, i_hosts, VLC_FALSE );
+                                psz_password, p_acl, VLC_FALSE );
 }
 
 httpd_url_t *httpd_UrlNewUnique( httpd_host_t *host, char *psz_url,
                                  char *psz_user, char *psz_password,
-                                 char **ppsz_hosts, int i_hosts )
+                                 const vlc_acl_t *p_acl )
 {
     return httpd_UrlNewPrivate( host, psz_url, psz_user,
-                                psz_password, ppsz_hosts, i_hosts, VLC_TRUE );
+                                psz_password, p_acl, VLC_TRUE );
 }
 
 /* register callback on a url */
@@ -1191,10 +1183,7 @@ void httpd_UrlDelete( httpd_url_t *url )
     free( url->psz_url );
     free( url->psz_user );
     free( url->psz_password );
-    for( i = 0; i < url->i_hosts; i++ )
-    {
-        TAB_REMOVE( url->i_hosts, url->ppsz_hosts, url->ppsz_hosts[0] );
-    }
+    ACL_Destroy( url->p_acl );
 
     for( i = 0; i < host->i_client; i++ )
     {
@@ -2085,14 +2074,12 @@ static void httpd_HostThread( httpd_host_t *host )
                         {
                             if( url->catch[i_msg].cb )
                             {
-                                if( answer && url->i_hosts )
+                                if( answer && ( url->p_acl != NULL ) )
                                 {
                                     char *ip = httpd_ClientIP( cl );
                                     if( ip != NULL )
                                     {
-                                        if( net_CheckIP( host, ip,
-                                                         url->ppsz_hosts,
-                                                         url->i_hosts ) <= 0 )
+                                        if( ACL_Check( url->p_acl, ip ) )
                                         {
                                             b_hosts_failed = VLC_TRUE;
                                             free( ip );
@@ -2454,10 +2441,21 @@ httpd_host_t *httpd_HostNew( vlc_object_t *a, char *b, int c )
     msg_Err( a, "HTTP daemon support is disabled" );
     return 0;
 }
-void httpd_HostDelete( httpd_host_t *a ){}
-httpd_url_t *httpd_UrlNew( httpd_host_t *a, char *b ){ return 0; }
-httpd_url_t *httpd_UrlNewUnique( httpd_host_t *a, char *b, char *c,
-                                 char *d ){ return 0; }
+void httpd_HostDelete( httpd_host_t *a )
+{
+}
+httpd_url_t *httpd_UrlNew( httpd_host_t *host, char *psz_url,
+                           char *psz_user, char *psz_password,
+                           const vlc_acl_t *p_acl )
+{
+    return NULL;
+}
+httpd_url_t *httpd_UrlNewUnique( httpd_host_t *host, char *psz_url,
+                                 char *psz_user, char *psz_password,
+                                 const vlc_acl_t *p_acl )
+{
+    return NULL;
+}
 int httpd_UrlCatch( httpd_url_t *a, int b, httpd_callback_t c,
                     httpd_callback_sys_t *d ){ return 0; }
 void httpd_UrlDelete( httpd_url_t *a ){}
index bea7566a48c74939be88a99ca858d58ff2ec690c..443d88526e36a7967868589de6d866662b7d10c4 100644 (file)
@@ -94,6 +94,7 @@
 #include "stream_output.h"
 #include "osd.h"
 #include "vlc_httpd.h"
+#include "vlc_acl.h"
 #include "vlc_tls.h"
 #include "vlc_md5.h"
 #include "vlc_xml.h"
index 6735748724ef05038f569f9b5510a937b3b33c72..a34877d02747e3d84c0c7e9ce7937212bffedcd2 100644 (file)
@@ -1156,58 +1156,3 @@ static int SocksHandshakeTCP( vlc_object_t *p_obj,
     return VLC_SUCCESS;
 }
 
-/*****************************************************************************
- * __net_CheckIP
- *****************************************************************************
- * Check that a given IP is within a set of IP/netmask.
- *****************************************************************************/
-int __net_CheckIP( vlc_object_t *p_this, char *psz_ip, char **ppsz_hosts,
-                   int i_hosts )
-{
-    struct in_addr ip;
-    int i;
-
-    if( (ip.s_addr = inet_addr( psz_ip )) == INADDR_NONE )
-    {
-        return VLC_EGENERIC;
-    }
-
-    for( i = 0; i < i_hosts; i++ )
-    {
-        struct in_addr base, mask;
-        char *psz_host = strdup( ppsz_hosts[i] );
-        char *p = strchr( psz_host, '/' );
-
-        if( p != NULL )
-        {
-            int i_mask;
-            *p++ = '\0';
-            i_mask = atoi(p);
-            if( i_mask < 0 || i_mask > 32 )
-            {
-                msg_Err( p_this, "invalid netmask %s", p );
-                mask.s_addr = INADDR_NONE;
-            }
-            else if( i_mask == 0 )
-                mask.s_addr = INADDR_ANY;
-            else
-                mask.s_addr = htonl( ntohl(INADDR_NONE) << (32 - i_mask) );
-        }
-        else
-            mask.s_addr = INADDR_NONE;
-
-        if( (base.s_addr = inet_addr( psz_host )) == INADDR_NONE )
-        {
-            msg_Err( p_this, "invalid base address %s", psz_host );
-            free( psz_host );
-            continue;
-        }
-        free( psz_host );
-
-        if( !((ip.s_addr ^ base.s_addr) & mask.s_addr) )
-            return VLC_TRUE;
-    }
-
-    return VLC_FALSE;
-}
-
diff --git a/src/stream_output/acl.c b/src/stream_output/acl.c
new file mode 100644 (file)
index 0000000..386071b
--- /dev/null
@@ -0,0 +1,346 @@
+/*****************************************************************************
+ * acl.c:
+ *****************************************************************************
+ * Copyright (C) 2005 Rémi Denis-Courmont
+ * $Id$
+ *
+ * Authors: Rémi Denis-Courmont <rem # videolan.org>
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h>
+#include <string.h>
+#include <vlc/vlc.h>
+
+#include "vlc_acl.h"
+
+#if defined( WIN32 ) || defined( UNDER_CE )
+#   include <winsock2.h>
+#   include <ws2tcpip.h>
+#else
+#   include <sys/socket.h>
+#   include <netinet/in.h>
+#   include <netdb.h>
+#endif
+
+#include "network.h"
+
+/* FIXME: rwlock on acl, but libvlc doesn't implement rwlock */
+/* FIXME: move to src/stream_output/whatever */
+typedef struct vlc_acl_entry_t
+{
+    uint8_t    host[17];
+    uint8_t    i_bytes_match;
+    uint8_t    i_bits_mask;
+    vlc_bool_t b_allow;
+} vlc_acl_entry_t;
+
+struct vlc_acl_t
+{
+    vlc_object_t    *p_owner;
+    unsigned         i_size;
+    vlc_acl_entry_t *p_entries;
+    vlc_bool_t       b_allow_default;
+};
+
+static int ACL_Resolve( vlc_object_t *p_this, uint8_t *p_bytes,
+                        const char *psz_ip )
+{
+    struct addrinfo hints = { }, *res;
+    int i_family;
+
+    hints.ai_socktype = SOCK_STREAM; /* doesn't matter */
+    hints.ai_flags = AI_NUMERICHOST;
+
+    if( vlc_getaddrinfo( p_this, psz_ip, 0, &hints, &res ) )
+    {
+        msg_Err( p_this, "invalid IP address %s", psz_ip );
+        return -1;
+    }
+    
+    p_bytes[16] = 0; /* avoids overflowing when i_bytes_match = 16 */
+
+    i_family = res->ai_addr->sa_family;
+    switch( i_family )
+    {
+        case AF_INET:
+        {
+            struct sockaddr_in *addr;
+                
+            addr = (struct sockaddr_in *)res->ai_addr;
+            memset( p_bytes, 0, 12 );
+            memcpy( p_bytes + 12, &addr->sin_addr, 4 );
+            break;
+        }
+
+#if defined (HAVE_GETADDRINFO) || defined (WIN32)
+        /* unfortunately many people define AF_INET6
+           though they don't have struct sockaddr_in6 */
+        case AF_INET6:
+        {
+            struct sockaddr_in6 *addr;
+
+            addr = (struct sockaddr_in6 *)res->ai_addr;
+            memcpy( p_bytes, &addr->sin6_addr, 16 );
+            break;
+        }
+#endif
+
+        default:
+            msg_Err( p_this, "IMPOSSIBLE: unknown address family!" );
+            vlc_freeaddrinfo( res );
+            return -1;
+    }
+
+    vlc_freeaddrinfo( res );
+    return i_family;
+}
+
+
+/*
+ * Returns 0 if allowed, 1 if not, -1 on error.
+ */
+int ACL_Check( vlc_acl_t *p_acl, const char *psz_ip )
+{
+    const vlc_acl_entry_t *p_cur, *p_end;
+    uint8_t host[17];
+
+    if( p_acl == NULL )
+        return -1;
+
+    p_cur = p_acl->p_entries;
+    p_end = p_cur + p_acl->i_size;
+
+    if( ACL_Resolve( p_acl->p_owner, host, psz_ip ) < 0 )
+        return -1;
+
+    while (p_cur < p_end)
+    {
+        unsigned i;
+
+        i = p_cur->i_bytes_match;
+        if( (memcmp( p_cur->host, host, i ) == 0)
+         && (((p_cur->host[i] ^ host[i]) & p_cur->i_bits_mask) == 0) )
+            return !p_cur->b_allow;
+
+        p_cur++;
+    }
+
+    return !p_acl->b_allow_default;
+}
+
+int ACL_AddNet( vlc_acl_t *p_acl, const char *psz_ip, int i_len,
+                vlc_bool_t b_allow )
+{
+    vlc_acl_entry_t *p_ent;
+    unsigned i_size;
+    div_t d;
+    int i_family;
+
+    i_size = p_acl->i_size;
+    p_ent = (vlc_acl_entry_t *)realloc( p_acl->p_entries,
+                                        ++p_acl->i_size * sizeof( *p_ent ) );
+
+    if( p_ent == NULL )
+        return -1;
+
+    i_family = ACL_Resolve( p_acl->p_owner, p_ent->host, psz_ip );
+    if( i_family < 0 )
+    {
+        /*
+         * I'm lazy : memory space will be re-used in the next ACL_Add call...
+         * or not.
+         */
+        p_acl->i_size--;
+        return -1;
+    }
+
+    if( i_len >= 0 )
+    {
+        if( i_family == AF_INET )
+            i_len += 96;
+
+        p_acl->p_entries = p_ent;
+        p_ent += i_size;
+
+        if( i_len > 128 )
+            i_len = 128;
+        else
+        if( i_len < 0 )
+            i_len = 0;
+    }
+    else
+        i_len = 128; /* ACL_AddHost */
+
+    d = div( i_len, 8 );
+    p_ent->i_bytes_match = d.quot;
+    p_ent->i_bits_mask = 0xff << (8 - d.rem);
+
+    p_ent->b_allow = b_allow;
+    return 0;
+}
+
+
+vlc_acl_t *__ACL_Create( vlc_object_t *p_this, vlc_bool_t b_allow )
+{
+    vlc_acl_t *p_acl;
+
+    p_acl = (vlc_acl_t *)malloc( sizeof( *p_acl ) );
+    if( p_acl == NULL )
+        return NULL;
+
+    vlc_object_yield( p_this );
+    p_acl->p_owner = p_this;
+    p_acl->i_size = 0;
+    p_acl->p_entries = NULL;
+    p_acl->b_allow_default = b_allow;
+    
+    return p_acl;
+}
+
+
+vlc_acl_t *__ACL_Duplicate( vlc_object_t *p_this, const vlc_acl_t *p_acl )
+{
+    vlc_acl_t *p_dupacl;
+
+    if( p_acl == NULL )
+        return NULL;
+
+    p_dupacl = (vlc_acl_t *)malloc( sizeof( *p_dupacl ) );
+    if( p_dupacl == NULL )
+        return NULL;
+
+    p_dupacl->p_entries = (vlc_acl_entry_t *)
+        malloc( p_acl->i_size * sizeof( vlc_acl_entry_t ) );
+    if( p_dupacl->p_entries == NULL )
+    {
+        free( p_dupacl );
+        return NULL;
+    }   
+
+    vlc_object_yield( p_this );
+    p_dupacl->p_owner = p_this;
+    p_dupacl->i_size = p_acl->i_size;
+    memcpy( p_dupacl->p_entries, p_acl->p_entries,
+            p_dupacl->i_size * sizeof( vlc_acl_entry_t ) );
+    
+    return p_dupacl;
+}
+
+
+void ACL_Destroy( vlc_acl_t *p_acl )
+{
+    if( p_acl != NULL )
+    {
+        if( p_acl->p_entries != NULL )
+            free( p_acl->p_entries );
+
+        vlc_object_release( p_acl->p_owner );
+        free( p_acl );
+    }
+}
+
+
+int ACL_LoadFile( vlc_acl_t *p_acl, const char *psz_path )
+{
+    FILE *file;
+    
+    if( p_acl == NULL )
+        return -1;
+
+    file = fopen( psz_path, "r" );
+    if( file == NULL )
+        return -1;
+
+    msg_Dbg( p_acl->p_owner, "find .hosts in dir=%s", psz_path );
+
+    while( !feof( file ) )
+    {
+        char line[1024], *psz_ip, *ptr;
+
+        if( fgets( line, sizeof( line ) - 1, file ) == NULL )
+        {
+            if( ferror( file ) )
+            {
+                msg_Err( p_acl->p_owner, "Error reading %s : %s\n", psz_path,
+                        strerror( errno ) );
+                goto error;
+            }
+            continue;
+        }
+
+        psz_ip = line;
+
+        /* skips blanks */
+        while( isblank( *psz_ip ) )
+            psz_ip++;
+
+        ptr = strchr( psz_ip, '\n' );
+        if( ptr == NULL )
+        {
+            msg_Warn( p_acl->p_owner, "Skipping overly long line in %s\n",
+                      psz_path);
+            do
+            {
+                fgets( line, sizeof( line ) - 1, file );
+                if( ferror( file ) || feof( file ) )
+                {
+                    msg_Err( p_acl->p_owner, "Error reading %s : %s\n",
+                             psz_path, strerror( errno ) );
+                    goto error;
+                }
+            }
+            while( strchr( line, '\n' ) == NULL);
+
+            continue; /* skip unusable line */
+        }
+
+        /* skips comment-only line */
+        if( *psz_ip == '#' )
+            continue;
+
+        /* looks for first space, CR, LF, etc. or end-of-line comment */
+        /* (there is at least a linefeed) */
+        for( ptr = psz_ip; ( *ptr != '#' ) && !isspace( *ptr ); ptr++ );
+
+        *ptr = '\0';
+
+        msg_Dbg( p_acl->p_owner, "restricted to %s", psz_ip );
+
+        ptr = strchr( psz_ip, '/' );
+        if( ptr != NULL )
+            *ptr++ = '\0'; /* separate address from mask length */
+
+        if( (ptr != NULL)
+            ? ACL_AddNet( p_acl, psz_ip, atoi( ptr ), VLC_TRUE ) 
+            : ACL_AddHost( p_acl, psz_ip, VLC_TRUE ) )
+        {
+            msg_Err( p_acl->p_owner, "cannot add ACL from %s", psz_path );
+            goto error;
+        }
+    }
+
+    fclose( file );
+    return 0;
+
+error:
+    fclose( file );
+    return -1;
+}
+