Commit 5f9a5f7c authored by Christophe Massiot's avatar Christophe Massiot

* modules/control/http.c: Added support for .hosts files detailing hosts

   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.
parent d026e61f
......@@ -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 */
......
......@@ -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 ) );
......
......@@ -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 );
......
......@@ -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 );
......
......@@ -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 )
{
......
......@@ -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;
......
......@@ -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 );
}
}
......
......@@ -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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment