Changeset 8378 for branches/1.5x/libtransmission/rpc-server.c
- Timestamp:
- May 11, 2009, 5:45:00 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/1.5x/libtransmission/rpc-server.c
r8357 r8378 30 30 #include "transmission.h" 31 31 #include "bencode.h" 32 #include "crypto.h" 32 33 #include "list.h" 33 34 #include "platform.h" … … 37 38 #include "utils.h" 38 39 #include "web.h" 40 41 /* session-id is used to make cross-site request forgery attacks difficult. 42 * Don't disable this feature unless you really know what you're doing! 43 * http://en.wikipedia.org/wiki/Cross-site_request_forgery 44 * http://shiflett.org/articles/cross-site-request-forgeries 45 * http://www.webappsec.org/lists/websecurity/archive/2008-04/msg00037.html */ 46 #define REQUIRE_SESSION_ID 39 47 40 48 #define MY_NAME "RPC Server" … … 58 66 char * whitelistStr; 59 67 tr_list * whitelist; 68 69 char * sessionId; 70 time_t sessionIdExpiresAt; 60 71 61 72 #ifdef HAVE_ZLIB … … 446 457 } 447 458 448 static void 449 handle_request( struct evhttp_request * req, 450 void * arg ) 459 static char* 460 get_current_session_id( struct tr_rpc_server * server ) 461 { 462 const time_t now = time( NULL ); 463 464 if( !server->sessionId || ( now >= server->sessionIdExpiresAt ) ) 465 { 466 int i; 467 const int n = 48; 468 const char * pool = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; 469 const size_t pool_size = strlen( pool ); 470 char * buf = tr_new( char, n+1 ); 471 472 for( i=0; i<n; ++i ) 473 buf[i] = pool[ tr_cryptoRandInt( pool_size ) ]; 474 buf[n] = '\0'; 475 476 tr_free( server->sessionId ); 477 server->sessionId = buf; 478 server->sessionIdExpiresAt = now + (60*60); /* expire in an hour */ 479 } 480 481 return server->sessionId; 482 } 483 484 485 static tr_bool 486 test_session_id( struct tr_rpc_server * server, struct evhttp_request * req ) 487 { 488 const char * ours = get_current_session_id( server ); 489 const char * theirs = evhttp_find_header( req->input_headers, TR_RPC_SESSION_ID_HEADER ); 490 const tr_bool success = theirs && !strcmp( theirs, ours ); 491 return success; 492 } 493 494 static void 495 handle_request( struct evhttp_request * req, void * arg ) 451 496 { 452 497 struct tr_rpc_server * server = arg; … … 455 500 { 456 501 const char * auth; 457 char * 458 char * 502 char * user = NULL; 503 char * pass = NULL; 459 504 460 505 evhttp_add_header( req->output_headers, "Server", MY_REALM ); 461 506 462 507 auth = evhttp_find_header( req->input_headers, "Authorization" ); 463 464 508 if( auth && !strncasecmp( auth, "basic ", 6 ) ) 465 509 { … … 475 519 if( !isAddressAllowed( server, req->remote_host ) ) 476 520 { 477 send_simple_response( req, 40 1,521 send_simple_response( req, 403, 478 522 "<p>Unauthorized IP Address.</p>" 479 523 "<p>Either disable the IP address whitelist or add your address to it.</p>" … … 506 550 handle_clutch( req, server ); 507 551 } 552 #ifdef REQUIRE_SESSION_ID 553 else if( !test_session_id( server, req ) ) 554 { 555 const char * sessionId = get_current_session_id( server ); 556 char * tmp = tr_strdup_printf( 557 "<p>Please add this header to your requests:</p>" 558 "<p><code>%s: %s</code></p>" 559 "<p>This requirement is to make " 560 "<a href=\"http://en.wikipedia.org/wiki/Cross-site_request_forgery\">CSRF</a>" 561 " attacks more difficult.</p>", 562 TR_RPC_SESSION_ID_HEADER, sessionId ); 563 evhttp_add_header( req->output_headers, TR_RPC_SESSION_ID_HEADER, sessionId ); 564 send_simple_response( req, 409, tmp ); 565 tr_free( tmp ); 566 } 567 #endif 508 568 else if( !strncmp( req->uri, "/transmission/rpc", 17 ) ) 509 569 {
Note: See TracChangeset
for help on using the changeset viewer.