1
0
Fork 0
mirror of https://github.com/transmission/transmission synced 2024-12-26 01:27:28 +00:00

RPC ACL: (1) add a new call for testing ACLs (2) add wildcard notation support (3) add regression tests for the ACL tester and wildcard handler

This commit is contained in:
Charles Kerr 2008-06-04 17:14:58 +00:00
parent a3324fbeea
commit c724a73fb4
6 changed files with 195 additions and 16 deletions

View file

@ -91,6 +91,7 @@ TESTS = \
bencode-test \
clients-test \
json-test \
rpc-test \
test-fastset \
test-peer-id \
utils-test
@ -117,6 +118,8 @@ clients_test_SOURCES = clients-test.c
clients_test_LDADD = $(APPS_LDADD)
json_test_SOURCES = json-test.c
json_test_LDADD = $(APPS_LDADD)
rpc_test_SOURCES = rpc-test.c
rpc_test_LDADD = $(APPS_LDADD)
test_fastset_SOURCES = test-fastset.c
test_fastset_LDADD = $(APPS_LDADD)
test_peer_id_SOURCES = test-peer-id.c

View file

@ -11,6 +11,9 @@
*/
#include <assert.h>
#include <ctype.h> /* isdigit */
#include <errno.h>
#include <stdlib.h> /* strtol */
#include <string.h>
#include <libevent/event.h>
@ -218,13 +221,61 @@ testACL( const char * s )
return NULL;
}
int
tr_rpcSetACL( tr_rpc_server * server, const char * acl, char ** setme_errmsg )
/* 192.*.*.* --> 192.0.0.0/8
192.64.*.* --> 192.64.0.0/16
192.64.1.* --> 192.64.1.0/24
192.64.1.2 --> 192.64.1.2/32 */
static void
cidrizeOne( const char * in, int len, struct evbuffer * out )
{
const int isRunning = server->ctx != NULL;
int ret = 0;
char * errmsg = testACL( acl );
int stars = 0;
const char * pch;
const char * end;
char zero = '0';
char huh = '?';
for( pch=in, end=pch+len; pch!=end; ++pch ) {
if( stars && isdigit(*pch) )
evbuffer_add( out, &huh, 1 );
else if( *pch!='*' )
evbuffer_add( out, pch, 1 );
else {
evbuffer_add( out, &zero, 1 );
++stars;
}
}
evbuffer_add_printf( out, "/%d", (32-(stars*8)));
}
char*
cidrize( const char * acl )
{
int len;
const char * walk = acl;
char * ret;
struct evbuffer * out = evbuffer_new( );
FOR_EACH_WORD_IN_LIST( walk, len )
{
cidrizeOne( walk, len, out );
evbuffer_add_printf( out, ", " );
}
/* the -2 is to eat the final ", " */
ret = tr_strndup( (char*) EVBUFFER_DATA(out), EVBUFFER_LENGTH(out)-2 );
evbuffer_free( out );
return ret;
}
int
tr_rpcTestACL( const tr_rpc_server * server UNUSED,
const char * acl,
char ** setme_errmsg )
{
int ret = 0;
char * cidr = cidrize( acl );
char * errmsg = testACL( cidr );
if( errmsg )
{
if( setme_errmsg )
@ -233,13 +284,27 @@ tr_rpcSetACL( tr_rpc_server * server, const char * acl, char ** setme_errmsg )
tr_free( errmsg );
ret = -1;
}
else
tr_free( cidr );
return ret;
}
int
tr_rpcSetACL( tr_rpc_server * server,
const char * acl,
char ** setme_errmsg )
{
char * cidr = cidrize( acl );
const int ret = tr_rpcTestACL( server, cidr, setme_errmsg );
if( ret )
{
const int isRunning = server->ctx != NULL;
if( isRunning )
stopServer( server );
tr_free( server->acl );
server->acl = tr_strdup( acl );
server->acl = tr_strdup( cidr );
if( isRunning )
startServer( server );

View file

@ -32,6 +32,10 @@ void tr_rpcSetPort ( tr_rpc_server * server,
int tr_rpcGetPort ( const tr_rpc_server * server );
int tr_rpcSetTest ( const tr_rpc_server * server,
const char * acl,
char ** allocme_errmsg );
int tr_rpcSetACL ( tr_rpc_server * server,
const char * acl,
char ** allocme_errmsg );

View file

@ -0,0 +1,75 @@
#include <stdio.h> /* fprintf */
#include <string.h> /* strcmp */
#include "transmission.h"
#include "utils.h"
#define VERBOSE 0
int test = 0;
#define check(A) { \
++test; \
if (A) { \
if( VERBOSE ) \
fprintf( stderr, "PASS test #%d (%s, %d)\n", test, __FILE__, __LINE__ ); \
} else { \
if( VERBOSE ) \
fprintf( stderr, "FAIL test #%d (%s, %d)\n", test, __FILE__, __LINE__ ); \
return test; \
} \
}
extern char* cidrize( const char * in );
extern int tr_rpcTestACL( const void * unused,
const char * acl,
char ** setme_errmsg );
static int
testWildcard( const char * in, const char * expected )
{
int ok;
char * str = cidrize( in );
/*fprintf( stderr, "in [%s] out [%s] should be [%s]\n", in, str, expected );*/
ok = expected ? !strcmp( expected, str ) : !str;
tr_free( str );
return ok;
}
static int
test_acl( void )
{
int err;
char * errmsg = NULL;
check( testWildcard( "192.*.*.*", "192.0.0.0/8" ) );
check( testWildcard( "192.64.*.*", "192.64.0.0/16" ) );
check( testWildcard( "192.64.0.*", "192.64.0.0/24" ) );
check( testWildcard( "192.64.0.1", "192.64.0.1/32" ) );
check( testWildcard( "+192.*.*.*, -192.64.*.*", "+192.0.0.0/8, -192.64.0.0/16" ) );
err = tr_rpcTestACL( NULL, "+192.*.*.*", &errmsg );
check( !err );
check( !errmsg );
err = tr_rpcTestACL( NULL, "+192.*.8.*", &errmsg );
check( err );
check( errmsg );
tr_free( errmsg );
errmsg = NULL;
err = tr_rpcTestACL( NULL, "+192.*.*.*, -192.168.*.*", &errmsg );
check( !err );
check( !errmsg );
return 0;
}
int
main( void )
{
int i;
if(( i = test_acl( )))
return i;
return 0;
}

View file

@ -775,6 +775,14 @@ tr_sessionSetRPCCallback( tr_handle * session,
session->rpc_func_user_data = user_data;
}
int
tr_sessionTestRPCACL( const tr_handle * session,
const char * acl,
char ** allocme_errmsg )
{
return tr_rpcTestACL( session->rpcServer, acl, allocme_errmsg );
}
int
tr_sessionSetRPCACL( tr_handle * session,
const char * acl,

View file

@ -292,21 +292,45 @@ void tr_sessionSetRPCPort( tr_handle *, int port );
int tr_sessionGetRPCPort( const tr_handle * );
/**
* Specify access control list (ACL). ACL is a comma separated list
* of IP subnets, each subnet is prepended by a '-' or '+' sign.
* Plus means allow, minus means deny. If the subnet mask is omitted,
* like * "-1.2.3.4", it means a single IP address. The mask may vary
* from 0 to 32 inclusive.
* @brief test an ACL's syntax without modifying the RPC settings.
*
* ACL is a comma separated list of IP subnets, each subnet is prepended
* by a '+' or '-' sign to denote 'allow' or 'deny'. If the subnet mask
* is omitted, like "-1.2.3.4", it means a single IP address. The mask
* may vary from 0 to 32 inclusive. A simple primer on x.x.x.x/n notation
* can be found at <http://25yearsofprogramming.com/blog/20070803.htm>.
*
* The default string is "+127.0.0.1"
*
* @param acl the new ACL to use.
* Since wildcards are more familiar to most users than netmasks,
* libtransmission supports a wildcard notation that it
* converts into cidr required by the embedded http server.
* So, notation like "+192.168.*.*" is accepted by libtransmission and is
* converted to "+192.168.0.0/16" before it reaches the server.
* @param acl the ACL to test
* @param allocme_errmsg If the ACL can't be parsed, this is set to a
* newly-allocated error string describing the problem.
* The client should tr_free() this string when done.
*
* @return 0 on success, -1 on failure due to an unparseable ACL.
*/
int tr_sessionTestRPCACL( const tr_handle * session,
const char * acl,
char ** allocme_errmsg );
/**
* @brief Specify access control list (ACL).
ACL is a comma separated list
* of IP subnets, each subnet is prepended by a '-' or '+' sign.
* Plus means allow, minus means deny. If the subnet mask is omitted,
* like "-1.2.3.4", it means a single IP address. The mask may vary
* from 0 to 32 inclusive.
*
* http://25yearsofprogramming.com/blog/20070803.htm has a simple
* primer on x.x.x.x/n notation for those interested.
*
* The parameters and return value follow the same behavior as
* tr_sessionTestRPCACL().
*
* @see tr_sessionTestRPCACL
* @see tr_sessionInitFull
* @see tr_sessionGetRPCACL
*/