]> git.sesse.net Git - vlc/commitdiff
* modules/control/http.c: Added support for .hosts files detailing hosts
authorChristophe Massiot <massiot@videolan.org>
Fri, 17 Jun 2005 12:43:46 +0000 (12:43 +0000)
committerChristophe Massiot <massiot@videolan.org>
Fri, 17 Jun 2005 12:43:46 +0000 (12:43 +0000)
   allowed to connect. The format is :
   192.168.0.0/24
   172.16.12.42/32
 * src/misc/net.c: New function net_CheckIP to check that an IP is in a
   given range.
 * OTHERS: Changed prototypes to allow for two new arguments for the
   hosts list.

include/network.h
include/vlc_httpd.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/net.c

index 4661d0f7aec5028f9c771deade5cd1a460082878..f4b363d9f6fbbb0e9ce95f9fa8195d9fbe1b08f5 100644 (file)
@@ -314,6 +314,9 @@ VLC_EXPORT( int, net_Printf, ( vlc_object_t *p_this, int fd, v_socket_t *, const
 #define net_vaPrintf(a,b,c,d,e) __net_vaPrintf(VLC_OBJECT(a),b,c,d,e)
 VLC_EXPORT( int, __net_vaPrintf, ( vlc_object_t *p_this, int fd, v_socket_t *, const char *psz_fmt, va_list args ) );
 
+#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 */
index aa04c76a1334567bc41d1c8ff5133666c2a3d753..c1ea92d0f07dfab685c62c58b5e0dbd8d5575e2d 100644 (file)
@@ -119,8 +119,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 ) );
-VLC_EXPORT( httpd_url_t *,  httpd_UrlNewUnique, ( httpd_host_t *, char *psz_url, char *psz_user, char *psz_password ) );
+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 ) );
 /* 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 */
@@ -133,7 +133,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, 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, char **ppsz_hosts, int i_hosts, httpd_file_callback_t pf_fill, httpd_file_sys_t * ) );
 VLC_EXPORT( void,           httpd_FileDelete, ( httpd_file_t * ) );
 
 
@@ -141,7 +141,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 ) );
+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( 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 8555030d511ee53fd6932b716429210cf949ad49..3d2bfbb8e8137a8186991fdc749809e275977cd1 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 );
+                         psz_user, psz_pwd, NULL, 0 );
     if( psz_user ) free( psz_user );
     if( psz_pwd ) free( psz_pwd );
     if( psz_mime ) free( psz_mime );
index e4ce72a570fe978ed2ed9e4c60c3aaf2f5518364..f5f83a6047a1d16682c38e171e764bb9bf8eeacd 100644 (file)
@@ -522,6 +522,10 @@ static int ParseDirectory( intf_thread_t *p_intf, char *psz_root,
 
     char          *user = NULL;
     char          *password = NULL;
+    char          **ppsz_hosts = NULL;
+    int           i_hosts = 0;
+
+    int           i;
 
 #ifdef HAVE_SYS_STAT_H
     if( stat( psz_dir, &stat_info ) == -1 || !S_ISDIR( stat_info.st_mode ) )
@@ -572,6 +576,43 @@ static int ParseDirectory( intf_thread_t *p_intf, char *psz_root,
         fclose( file );
     }
 
+    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 );
+        }
+    }
+
     for( ;; )
     {
         /* parse psz_src dir */
@@ -611,7 +652,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,
+                                       user, password, ppsz_hosts, i_hosts,
                                        HttpCallback, f );
 
             if( f->p_file )
@@ -653,6 +694,10 @@ 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] );
+    }
 
     closedir( p_dir );
 
index 403d4807ae7fea4694d407821d8c8262d2abe21f..9b048cef35458732d3725b3ced6a1520188b45b8 100644 (file)
@@ -276,7 +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 );
+        httpd_UrlNewUnique( p_sys->p_rtsp_host, p_media->psz_rtsp_path, 0, 0,
+                            NULL, 0 );
 
     if( !p_media->p_rtsp_url )
     {
@@ -452,7 +453,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 );
+        httpd_UrlNewUnique( p_vod->p_sys->p_rtsp_host, psz_urlc, 0, 0, NULL,
+                            0 );
 
     if( !p_es->p_rtsp_url )
     {
index 5563c28576fb1b8a69bdf1be8406af62df910626..1dec3642dcfd3067eade199ae7a6b284f03e3a34 100644 (file)
@@ -1032,7 +1032,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 );
+        id->p_rtsp_url = httpd_UrlNewUnique( p_sys->p_rtsp_host, psz_urlc, NULL, NULL, NULL, 0 );
 
         if( id->p_rtsp_url )
         {
@@ -1296,7 +1296,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, NULL, NULL, 0,
                                              HttpCallback, (void*)p_sys );
     }
     if( p_sys->p_httpd_file == NULL )
@@ -1394,7 +1394,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 );
+    p_sys->p_rtsp_url = httpd_UrlNewUnique( p_sys->p_rtsp_host, p_sys->psz_rtsp_path, NULL, NULL, NULL, 0 );
     if( p_sys->p_rtsp_url == 0 )
     {
         return VLC_EGENERIC;
index c06d3651edcc39fbd87e9b2e8ce48e63f5b655d7..230808c9a712d23f83e13f89dfe1650e0ee86faa 100644 (file)
@@ -237,6 +237,8 @@ struct httpd_url_t
     char    *psz_url;
     char    *psz_user;
     char    *psz_password;
+    char    **ppsz_hosts;
+    int     i_hosts;
 
     struct
     {
@@ -489,13 +491,15 @@ 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,
                              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 ) ) == NULL )
+                                          psz_password, ppsz_hosts, i_hosts )
+        ) == NULL )
     {
         free( file );
         return NULL;
@@ -586,7 +590,8 @@ 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 ) ) )
+    if( !( rdir->url = httpd_UrlNewUnique( host, psz_url_src, NULL, NULL,
+                                           NULL, 0 ) ) )
     {
         free( rdir );
         return NULL;
@@ -761,12 +766,14 @@ 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 *psz_user, char *psz_password,
+                                 char **ppsz_hosts, int i_hosts )
 {
     httpd_stream_t *stream = malloc( sizeof( httpd_stream_t ) );
 
     if( ( stream->url = httpd_UrlNewUnique( host, psz_url, psz_user,
-                                            psz_password ) ) == NULL )
+                                            psz_password, ppsz_hosts, i_hosts )
+        ) == NULL )
     {
         free( stream );
         return NULL;
@@ -1090,6 +1097,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 )
 {
     httpd_url_t *url;
@@ -1117,6 +1125,12 @@ 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]) );
+    }
     for( i = 0; i < HTTPD_MSG_MAX; i++ )
     {
         url->catch[i].cb = NULL;
@@ -1130,17 +1144,19 @@ 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 *psz_user, char *psz_password,
+                           char **ppsz_hosts, int i_hosts )
 {
     return httpd_UrlNewPrivate( host, psz_url, psz_user,
-                                psz_password, VLC_FALSE );
+                                psz_password, ppsz_hosts, i_hosts, VLC_FALSE );
 }
 
 httpd_url_t *httpd_UrlNewUnique( httpd_host_t *host, char *psz_url,
-                                 char *psz_user, char *psz_password )
+                                 char *psz_user, char *psz_password,
+                                 char **ppsz_hosts, int i_hosts )
 {
     return httpd_UrlNewPrivate( host, psz_url, psz_user,
-                                psz_password, VLC_TRUE );
+                                psz_password, ppsz_hosts, i_hosts, VLC_TRUE );
 }
 
 /* register callback on a url */
@@ -1169,6 +1185,10 @@ 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] );
+    }
 
     for( i = 0; i < host->i_client; i++ )
     {
@@ -2073,6 +2093,7 @@ static void httpd_HostThread( httpd_host_t *host )
                 else
                 {
                     vlc_bool_t b_auth_failed = VLC_FALSE;
+                    vlc_bool_t b_hosts_failed = VLC_FALSE;
                     int i;
 
                     /* Search the url and trigger callbacks */
@@ -2084,6 +2105,23 @@ static void httpd_HostThread( httpd_host_t *host )
                         {
                             if( url->catch[i_msg].cb )
                             {
+                                if( answer && url->i_hosts )
+                                {
+                                    char *ip = httpd_ClientIP( cl );
+                                    if( ip != NULL )
+                                    {
+                                        if( net_CheckIP( host, ip,
+                                                         url->ppsz_hosts,
+                                                         url->i_hosts ) <= 0 )
+                                        {
+                                            b_hosts_failed = VLC_TRUE;
+                                            free( ip );
+                                            break;
+                                        }
+                                        free( ip );
+                                    }
+                                }
+
                                 if( answer && ( *url->psz_user || *url->psz_password ) )
                                 {
                                     /* create the headers */
@@ -2142,7 +2180,23 @@ static void httpd_HostThread( httpd_host_t *host )
                         answer->i_version= 0;
                         p = answer->p_body = malloc( 1000 + strlen(query->psz_url) );
 
-                        if( b_auth_failed )
+                        if( b_hosts_failed )
+                        {
+                            answer->i_status = 403;
+                            answer->psz_status = strdup( "Forbidden" );
+
+                            p += sprintf( p, "<html>\n" );
+                            p += sprintf( p, "<head>\n" );
+                            p += sprintf( p, "<title>Error 403</title>\n" );
+                            p += sprintf( p, "</head>\n" );
+                            p += sprintf( p, "<body>\n" );
+                            p += sprintf( p, "<h1><center> 403 Forbidden (%s)</center></h1>\n", query->psz_url );
+                            p += sprintf( p, "<hr />\n" );
+                            p += sprintf( p, "<a href=\"http://www.videolan.org\">VideoLAN</a>\n" );
+                            p += sprintf( p, "</body>\n" );
+                            p += sprintf( p, "</html>\n" );
+                        }
+                        else if( b_auth_failed )
                         {
                             answer->i_status = 401;
                             answer->psz_status = strdup( "Authorization Required" );
@@ -2354,7 +2408,7 @@ static void httpd_HostThread( httpd_host_t *host )
                         ip = httpd_ClientIP( cl );
                         msg_Dbg( host, "new connection (%s)",
                                 ip != NULL ? ip : "unknown" );
-                        if( ip != NULL)
+                        if( ip != NULL )
                             free( ip );
                     }
                 }
index 95d76d39402da181be18106892aa8233147d42c7..a090d5d9ec36fa8c768bbf5ae9f171fdc77606b8 100644 (file)
@@ -1171,3 +1171,59 @@ 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( !inet_aton( psz_ip, &ip ) )
+    {
+        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 = htons( ntohs(INADDR_NONE) << (32 - i_mask) );
+        }
+        else
+            mask.s_addr = INADDR_NONE;
+
+        if( !inet_aton( psz_host, &base ) )
+        {
+            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;
+}
+