Commit e6a2e27b authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

Better ACL API (full rewrite)

parent 9fad47dc
......@@ -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 \
......
......@@ -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 */
......
/*****************************************************************************
* 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
......@@ -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;
......
......@@ -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 ) );
......
......@@ -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__ */
......
......@@ -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 );
......
......@@ -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;
......
......@@ -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;
}
......
......@@ -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;
......
......@@ -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 ){}
......
......@@ -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"
......
......@@ -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;
}
/*****************************************************************************
* 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;
}
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