mirror of
https://github.com/videolan/vlc.git
synced 2024-11-24 18:33:38 +08:00
Better ACL API (full rewrite)
This commit is contained in:
parent
9fad47dcd8
commit
e6a2e27bbb
@ -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 */
|
||||
|
39
include/vlc_acl.h
Normal file
39
include/vlc_acl.h
Normal file
@ -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
|
@ -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;
|
||||
}
|
||||
|
||||
|
346
src/stream_output/acl.c
Normal file
346
src/stream_output/acl.c
Normal file
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user