mirror of
https://github.com/transmission/transmission
synced 2024-12-27 01:57:52 +00:00
(libT): added an ACL tester to tr_sessionSetRPCACL() and return an error string if the ACL can't be parsed.
This commit is contained in:
parent
a4520742e5
commit
f8d40cdf00
5 changed files with 79 additions and 19 deletions
|
@ -175,19 +175,72 @@ tr_rpcGetPort( const tr_rpc_server * server )
|
||||||
return server->port;
|
return server->port;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
/*
|
||||||
tr_rpcSetACL( tr_rpc_server * server, const char * acl )
|
* DELIM_CHARS, FOR_EACH_WORD_IN_LIST, isbyte, and testACL are from, or modified from,
|
||||||
|
* shttpd, written by Sergey Lyubka under this license:
|
||||||
|
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||||
|
* Sergey Lyubka wrote this file. As long as you retain this notice you
|
||||||
|
* can do whatever you want with this stuff. If we meet some day, and you think
|
||||||
|
* this stuff is worth it, you can buy me a beer in return.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DELIM_CHARS " ," /* Separators for lists */
|
||||||
|
|
||||||
|
#define FOR_EACH_WORD_IN_LIST(s,len) \
|
||||||
|
for (; s != NULL && (len = strcspn(s, DELIM_CHARS)) != 0; \
|
||||||
|
s += len, s+= strspn(s, DELIM_CHARS))
|
||||||
|
|
||||||
|
static int isbyte(int n) { return (n >= 0 && n <= 255); }
|
||||||
|
|
||||||
|
static char*
|
||||||
|
testACL( const char * s )
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
|
||||||
|
FOR_EACH_WORD_IN_LIST(s, len)
|
||||||
|
{
|
||||||
|
|
||||||
|
char flag;
|
||||||
|
int a, b, c, d, n, mask;
|
||||||
|
|
||||||
|
if( sscanf(s, "%c%d.%d.%d.%d%n",&flag,&a,&b,&c,&d,&n) != 5 )
|
||||||
|
return tr_strdup_printf( _( "[%s]: subnet must be [+|-]x.x.x.x[/x]" ), s );
|
||||||
|
if( flag != '+' && flag != '-')
|
||||||
|
return tr_strdup_printf( _( "[%s]: flag must be + or -" ), s );
|
||||||
|
if( !isbyte(a) || !isbyte(b) || !isbyte(c) || !isbyte(d) )
|
||||||
|
return tr_strdup_printf( _( "[%s]: bad ip address" ), s );
|
||||||
|
if( sscanf(s + n, "/%d", &mask) == 1 && ( mask<0 || mask>32 ) )
|
||||||
|
return tr_strdup_printf( _( "[%s]: bad subnet mask %d" ), s, n );
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
tr_rpcSetACL( tr_rpc_server * server, const char * acl, char ** setme_errmsg )
|
||||||
{
|
{
|
||||||
const int isRunning = server->ctx != NULL;
|
const int isRunning = server->ctx != NULL;
|
||||||
|
int ret = 0;
|
||||||
|
char * errmsg = testACL( acl );
|
||||||
|
|
||||||
if( isRunning )
|
if( errmsg )
|
||||||
stopServer( server );
|
{
|
||||||
|
*setme_errmsg = errmsg;
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( isRunning )
|
||||||
|
stopServer( server );
|
||||||
|
|
||||||
tr_free( server->acl );
|
tr_free( server->acl );
|
||||||
server->acl = tr_strdup( acl );
|
server->acl = tr_strdup( acl );
|
||||||
|
|
||||||
if( isRunning )
|
if( isRunning )
|
||||||
startServer( server );
|
startServer( server );
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char*
|
const char*
|
||||||
|
|
|
@ -32,8 +32,9 @@ void tr_rpcSetPort ( tr_rpc_server * server,
|
||||||
|
|
||||||
int tr_rpcGetPort ( const tr_rpc_server * server );
|
int tr_rpcGetPort ( const tr_rpc_server * server );
|
||||||
|
|
||||||
void tr_rpcSetACL ( tr_rpc_server * server,
|
int tr_rpcSetACL ( tr_rpc_server * server,
|
||||||
const char * acl );
|
const char * acl,
|
||||||
|
char ** allocme_errmsg );
|
||||||
|
|
||||||
const char* tr_rpcGetACL ( const tr_rpc_server * server );
|
const char* tr_rpcGetACL ( const tr_rpc_server * server );
|
||||||
|
|
||||||
|
|
|
@ -775,10 +775,12 @@ tr_sessionSetRPCCallback( tr_handle * session,
|
||||||
session->rpc_func_user_data = user_data;
|
session->rpc_func_user_data = user_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int
|
||||||
tr_sessionSetRPCACL( tr_handle * session, const char * acl )
|
tr_sessionSetRPCACL( tr_handle * session,
|
||||||
|
const char * acl,
|
||||||
|
char ** allocme_errmsg )
|
||||||
{
|
{
|
||||||
tr_rpcSetACL( session->rpcServer, acl );
|
return tr_rpcSetACL( session->rpcServer, acl, allocme_errmsg );
|
||||||
}
|
}
|
||||||
|
|
||||||
const char*
|
const char*
|
||||||
|
|
|
@ -300,15 +300,19 @@ int tr_sessionGetRPCPort( const tr_handle * );
|
||||||
*
|
*
|
||||||
* The default string is "+127.0.0.1"
|
* The default string is "+127.0.0.1"
|
||||||
*
|
*
|
||||||
* IMPORTANT: a malformed ACL is likely to cause Transmission to crash.
|
* @param acl the new ACL to use.
|
||||||
* Client applications need to validate user input, or better yet
|
* @param allocme_errmsg If the ACL can't be parsed, this is set to a
|
||||||
* generate it from a higher-level interface that doesn't allow user error,
|
* newly-allocated error string describing the problem.
|
||||||
* before calling this function.
|
* The client should tr_free() this string when done.
|
||||||
|
*
|
||||||
|
* @return 0 on success, -1 on failure due to an unparseable ACL.
|
||||||
*
|
*
|
||||||
* @see tr_sessionInitFull
|
* @see tr_sessionInitFull
|
||||||
* @see tr_sessionGetRPCACL
|
* @see tr_sessionGetRPCACL
|
||||||
*/
|
*/
|
||||||
void tr_sessionSetRPCACL( tr_handle *, const char * acl );
|
int tr_sessionSetRPCACL( tr_handle * session,
|
||||||
|
const char * acl,
|
||||||
|
char ** allocme_errmsg );
|
||||||
|
|
||||||
/** Returns the Access Control List for allowing/denying RPC requests.
|
/** Returns the Access Control List for allowing/denying RPC requests.
|
||||||
@see tr_sessionInitFull
|
@see tr_sessionInitFull
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include "transmission.h"
|
#include "transmission.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
#define VERBOSE 1
|
#define VERBOSE 0
|
||||||
#define NUM_LOOPS 1
|
#define NUM_LOOPS 1
|
||||||
#define SPEED_TEST 0
|
#define SPEED_TEST 0
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue