X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fnetwork%2Facl.c;h=f10ec64152e87ec3a959825cd497a865a828d00a;hb=ac8243334cd14ffcf8f407cb5fbee89d4790d389;hp=b9cc0a63f7deff4a379fd82bb84c73d734d08732;hpb=1e6b04ccf9e6a172cf09d9116ab9d294ab0a7986;p=vlc diff --git a/src/network/acl.c b/src/network/acl.c index b9cc0a63f7..f10ec64152 100644 --- a/src/network/acl.c +++ b/src/network/acl.c @@ -1,7 +1,7 @@ /***************************************************************************** * acl.c: ***************************************************************************** - * Copyright (C) 2005 Rémi Denis-Courmont + * Copyright © 2005-2007 Rémi Denis-Courmont * $Id$ * * Authors: Rémi Denis-Courmont @@ -18,22 +18,23 @@ * * 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. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ /***************************************************************************** * Preamble *****************************************************************************/ -#include -#include -#include -#include +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif -#include "vlc_acl.h" +#include -#include +#include +#include -#include "network.h" +#include +#include /* FIXME: rwlock on acl, but libvlc doesn't implement rwlock */ typedef struct vlc_acl_entry_t @@ -41,7 +42,7 @@ 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; + bool b_allow; } vlc_acl_entry_t; struct vlc_acl_t @@ -49,15 +50,16 @@ struct vlc_acl_t vlc_object_t *p_owner; unsigned i_size; vlc_acl_entry_t *p_entries; - vlc_bool_t b_allow_default; + bool b_allow_default; }; static int ACL_Resolve( vlc_object_t *p_this, uint8_t *p_bytes, const char *psz_ip ) { - struct addrinfo hints = { 0 }, *res; + struct addrinfo hints, *res; int i_family; + memset (&hints, 0, sizeof (hints)); hints.ai_socktype = SOCK_STREAM; /* doesn't matter */ hints.ai_flags = AI_NUMERICHOST; @@ -96,7 +98,7 @@ static int ACL_Resolve( vlc_object_t *p_this, uint8_t *p_bytes, #endif default: - msg_Err( p_this, "IMPOSSIBLE: unknown address family!" ); + msg_Err( p_this, "unknown address family" ); vlc_freeaddrinfo( res ); return -1; } @@ -106,8 +108,15 @@ static int ACL_Resolve( vlc_object_t *p_this, uint8_t *p_bytes, } -/* - * Returns 0 if allowed, 1 if not, -1 on error. +/** + * Check if a given address passes an access control list. + * + * @param p_acl pre-existing ACL to match the address against + * @param psz_ip numeric IPv4/IPv6 address + * + * @return 0 if the first matching ACL entry is an access grant, + * 1 if the first matching ACL entry is a denial of access, + * -1 on error. */ int ACL_Check( vlc_acl_t *p_acl, const char *psz_ip ) { @@ -138,8 +147,12 @@ int ACL_Check( vlc_acl_t *p_acl, const char *psz_ip ) return !p_acl->b_allow_default; } +/** + * Adds an item to an ACL. + * Items are always matched in the same order as they are added. + */ int ACL_AddNet( vlc_acl_t *p_acl, const char *psz_ip, int i_len, - vlc_bool_t b_allow ) + bool b_allow ) { vlc_acl_entry_t *p_ent; unsigned i_size; @@ -174,9 +187,6 @@ int ACL_AddNet( vlc_acl_t *p_acl, const char *psz_ip, int i_len, if( i_len > 128 ) i_len = 128; - else - if( i_len < 0 ) - i_len = 0; } else i_len = 128; /* ACL_AddHost */ @@ -189,8 +199,16 @@ int ACL_AddNet( vlc_acl_t *p_acl, const char *psz_ip, int i_len, return 0; } - -vlc_acl_t *__ACL_Create( vlc_object_t *p_this, vlc_bool_t b_allow ) +#undef ACL_Create +/** + * Creates an empty ACL. + * + * @param b_allow whether to grant (true) or deny (false) access + * by default (ie if none of the ACL entries matched). + * + * @return an ACL object. NULL in case of error. + */ +vlc_acl_t *ACL_Create( vlc_object_t *p_this, bool b_allow ) { vlc_acl_t *p_acl; @@ -198,7 +216,7 @@ vlc_acl_t *__ACL_Create( vlc_object_t *p_this, vlc_bool_t b_allow ) if( p_acl == NULL ) return NULL; - vlc_object_yield( p_this ); + vlc_object_hold( p_this ); p_acl->p_owner = p_this; p_acl->i_size = 0; p_acl->p_entries = NULL; @@ -207,8 +225,16 @@ vlc_acl_t *__ACL_Create( vlc_object_t *p_this, vlc_bool_t b_allow ) return p_acl; } - -vlc_acl_t *__ACL_Duplicate( vlc_object_t *p_this, const vlc_acl_t *p_acl ) +#undef ACL_Duplicate +/** + * Perform a deep copy of an existing ACL. + * + * @param p_this object to attach the copy to. + * @param p_acl ACL object to be copied. + * + * @return a new ACL object, or NULL on error. + */ +vlc_acl_t *ACL_Duplicate( vlc_object_t *p_this, const vlc_acl_t *p_acl ) { vlc_acl_t *p_dupacl; @@ -236,7 +262,7 @@ vlc_acl_t *__ACL_Duplicate( vlc_object_t *p_this, const vlc_acl_t *p_acl ) else p_dupacl->p_entries = NULL; - vlc_object_yield( p_this ); + vlc_object_hold( p_this ); p_dupacl->p_owner = p_this; p_dupacl->i_size = p_acl->i_size; p_dupacl->b_allow_default = p_acl->b_allow_default; @@ -245,22 +271,28 @@ vlc_acl_t *__ACL_Duplicate( vlc_object_t *p_this, const vlc_acl_t *p_acl ) } +/** + * Releases all resources associated with an ACL object. + */ void ACL_Destroy( vlc_acl_t *p_acl ) { if( p_acl != NULL ) { - if( p_acl->p_entries != NULL ) - free( p_acl->p_entries ); - + free( p_acl->p_entries ); vlc_object_release( p_acl->p_owner ); free( p_acl ); } } -#ifndef isblank -# define isblank(c) ((c) == ' ' || (c) == '\t') -#endif +/** + * Reads ACL entries from a file. + * + * @param p_acl ACL object in which to insert parsed entries. + * @param psz_patch filename from which to parse entries. + * + * @return 0 on success, -1 on error. + */ int ACL_LoadFile( vlc_acl_t *p_acl, const char *psz_path ) { FILE *file; @@ -268,7 +300,7 @@ int ACL_LoadFile( vlc_acl_t *p_acl, const char *psz_path ) if( p_acl == NULL ) return -1; - file = fopen( psz_path, "r" ); + file = vlc_fopen( psz_path, "r" ); if( file == NULL ) return -1; @@ -282,8 +314,7 @@ int ACL_LoadFile( vlc_acl_t *p_acl, const char *psz_path ) { if( ferror( file ) ) { - msg_Err( p_acl->p_owner, "Error reading %s : %s\n", psz_path, - strerror( errno ) ); + msg_Err( p_acl->p_owner, "error reading %s : %m", psz_path ); goto error; } continue; @@ -300,18 +331,20 @@ int ACL_LoadFile( vlc_acl_t *p_acl, const char *psz_path ) continue; ptr = strchr( psz_ip, '\n' ); - if( ptr == NULL ) + if( ptr == NULL && !feof(file) ) { - msg_Warn( p_acl->p_owner, "Skipping overly long line in %s\n", + msg_Warn( p_acl->p_owner, "skipping overly long line in %s", psz_path); do { - fgets( line, sizeof( line ), file ); - if( ferror( file ) || feof( file ) ) + if( fgets( line, sizeof( line ), file ) == NULL ) { - msg_Err( p_acl->p_owner, "Error reading %s : %s\n", - psz_path, strerror( errno ) ); - goto error; + if( ferror( file ) ) + { + msg_Err( p_acl->p_owner, "error reading %s : %m", + psz_path ); + } + goto error; } } while( strchr( line, '\n' ) == NULL); @@ -319,16 +352,15 @@ int ACL_LoadFile( vlc_acl_t *p_acl, const char *psz_path ) 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++ ); + /* look for first space, CR, LF, etc. or comment character */ + for( ptr = psz_ip; ( *ptr!='#' ) && !isspace( *ptr ) && *ptr; ++ptr ); *ptr = '\0'; + /* skip lines without usable information */ + if( ptr == psz_ip ) + continue; + msg_Dbg( p_acl->p_owner, "restricted to %s", psz_ip ); ptr = strchr( psz_ip, '/' ); @@ -336,11 +368,11 @@ int ACL_LoadFile( vlc_acl_t *p_acl, const char *psz_path ) *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 ) ) + ? ACL_AddNet( p_acl, psz_ip, atoi( ptr ), true ) + : ACL_AddHost( p_acl, psz_ip, true ) ) { msg_Err( p_acl->p_owner, "cannot add ACL from %s", psz_path ); - goto error; + continue; } }