#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 */
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 */
/* 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 * ) );
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 ) );
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 );
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 ) )
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 */
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 )
{
free( password );
}
+ for( i = 0; i < i_hosts; i++ )
+ {
+ TAB_REMOVE( i_hosts, ppsz_hosts, ppsz_hosts[0] );
+ }
closedir( p_dir );
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 )
{
}
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 )
{
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 )
{
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 )
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;
char *psz_url;
char *psz_user;
char *psz_password;
+ char **ppsz_hosts;
+ int i_hosts;
struct
{
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;
{
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;
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;
/* 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;
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;
}
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 */
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++ )
{
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 */
{
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 */
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" );
ip = httpd_ClientIP( cl );
msg_Dbg( host, "new connection (%s)",
ip != NULL ? ip : "unknown" );
- if( ip != NULL)
+ if( ip != NULL )
free( ip );
}
}
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;
+}
+