Changeset 8352
- Timestamp:
- May 8, 2009, 2:38:08 AM (14 years ago)
- Location:
- branches/1.5x
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/1.5x/daemon/remote.c
r8275 r8352 127 127 static char * auth = NULL; 128 128 static char * netrc = NULL; 129 static char * cookies = NULL; 129 130 130 131 static char* … … 1223 1224 } 1224 1225 1226 /* very basic handling of cookies: when we get Set-Cookie, throw out all 1227 * the previous cookies... T only uses one cookie (session_id) */ 1228 static size_t 1229 parseResponseHeader( void *ptr, size_t size, size_t nmemb, void * stream UNUSED ) 1230 { 1231 const char * line = ptr; 1232 const size_t linelen = size * nmemb; 1233 const char * lineend = line + linelen; 1234 const char * key = "Set-Cookie: "; 1235 const size_t keylen = strlen( key ); 1236 if( ( linelen >= keylen ) && !memcmp( line, key, keylen ) ) { 1237 const char * begin = line + keylen; 1238 const char * end = begin; 1239 while(( end!=lineend ) && !strchr("\r\n",*end)) 1240 ++end; 1241 tr_free( cookies ); 1242 cookies = tr_strndup( begin, end-begin ); 1243 } 1244 1245 return linelen; 1246 } 1247 1248 static CURL* 1249 tr_curl_easy_init( struct evbuffer * writebuf ) 1250 { 1251 CURL * curl = curl_easy_init( ); 1252 curl_easy_setopt( curl, CURLOPT_USERAGENT, MY_NAME "/" LONG_VERSION_STRING ); 1253 curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, writeFunc ); 1254 curl_easy_setopt( curl, CURLOPT_WRITEDATA, writebuf ); 1255 curl_easy_setopt( curl, CURLOPT_HEADERFUNCTION, parseResponseHeader ); 1256 curl_easy_setopt( curl, CURLOPT_POST, 1 ); 1257 curl_easy_setopt( curl, CURLOPT_NETRC, CURL_NETRC_OPTIONAL ); 1258 curl_easy_setopt( curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY ); 1259 curl_easy_setopt( curl, CURLOPT_TIMEOUT, 60L ); 1260 curl_easy_setopt( curl, CURLOPT_VERBOSE, debug ); 1261 #ifdef HAVE_ZLIB 1262 curl_easy_setopt( curl, CURLOPT_ENCODING, "deflate" ); 1263 #endif 1264 if( cookies ) 1265 curl_easy_setopt( curl, CURLOPT_COOKIE, cookies ); 1266 if( netrc ) 1267 curl_easy_setopt( curl, CURLOPT_NETRC_FILE, netrc ); 1268 if( auth ) 1269 curl_easy_setopt( curl, CURLOPT_USERPWD, auth ); 1270 return curl; 1271 } 1272 1225 1273 static void 1226 1274 processRequests( const char * host, … … 1229 1277 int reqCount ) 1230 1278 { 1231 int 1232 CURL * curl;1279 int i; 1280 CURL * curl = NULL; 1233 1281 struct evbuffer * buf = evbuffer_new( ); 1234 char * url = tr_strdup_printf( 1235 "http://%s:%d/transmission/rpc", host, port ); 1236 1237 curl = curl_easy_init( ); 1238 curl_easy_setopt( curl, CURLOPT_VERBOSE, debug ); 1239 #ifdef HAVE_LIBZ 1240 curl_easy_setopt( curl, CURLOPT_ENCODING, "deflate" ); 1241 #endif 1242 curl_easy_setopt( curl, CURLOPT_USERAGENT, MY_NAME "/" LONG_VERSION_STRING ); 1243 curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, writeFunc ); 1244 curl_easy_setopt( curl, CURLOPT_WRITEDATA, buf ); 1245 curl_easy_setopt( curl, CURLOPT_POST, 1 ); 1246 curl_easy_setopt( curl, CURLOPT_URL, url ); 1247 curl_easy_setopt( curl, CURLOPT_NETRC, CURL_NETRC_OPTIONAL ); 1248 curl_easy_setopt( curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY ); 1249 curl_easy_setopt( curl, CURLOPT_TIMEOUT, 60L ); 1250 if( netrc ) 1251 curl_easy_setopt( curl, CURLOPT_NETRC_FILE, netrc ); 1252 if( auth ) 1253 curl_easy_setopt( curl, CURLOPT_USERPWD, auth ); 1254 1255 for( i = 0; i < reqCount; ++i ) 1282 char * url = tr_strdup_printf( "http://%s:%d/transmission/rpc", host, port ); 1283 1284 for( i=0; i<reqCount; ++i ) 1256 1285 { 1257 1286 CURLcode res; 1287 evbuffer_drain( buf, EVBUFFER_LENGTH( buf ) ); 1288 1289 if( curl == NULL ) 1290 { 1291 curl = tr_curl_easy_init( buf ); 1292 curl_easy_setopt( curl, CURLOPT_URL, url ); 1293 } 1294 1258 1295 curl_easy_setopt( curl, CURLOPT_POSTFIELDS, reqs[i] ); 1296 1259 1297 if( debug ) 1260 1298 fprintf( stderr, "posting:\n--------\n%s\n--------\n", reqs[i] ); 1261 1299 if( ( res = curl_easy_perform( curl ) ) ) 1262 tr_nerr( MY_NAME, "(%s:%d) %s", host, port, 1263 curl_easy_strerror( res ) ); 1264 else 1265 processResponse( host, port, EVBUFFER_DATA( 1266 buf ), EVBUFFER_LENGTH( buf ) ); 1267 1268 evbuffer_drain( buf, EVBUFFER_LENGTH( buf ) ); 1300 tr_nerr( MY_NAME, "(%s:%d) %s", host, port, curl_easy_strerror( res ) ); 1301 else { 1302 long response; 1303 curl_easy_getinfo( curl, CURLINFO_RESPONSE_CODE, &response ); 1304 switch( response ) { 1305 case 200: 1306 processResponse( host, port, EVBUFFER_DATA(buf), EVBUFFER_LENGTH(buf) ); 1307 break; 1308 case 409: 1309 /* session_id cookie expired. by the time we reach line this our 1310 * curl header func has already found the new session_id, so make 1311 * a new CURL* and try again... */ 1312 curl_easy_cleanup( curl ); 1313 curl = NULL; 1314 --i; 1315 break; 1316 default: 1317 fprintf( stderr, "Unexpected response: %s\n", (char*)EVBUFFER_DATA(buf) ); 1318 break; 1319 } 1320 } 1269 1321 } 1270 1322 … … 1272 1324 tr_free( url ); 1273 1325 evbuffer_free( buf ); 1274 curl_easy_cleanup( curl ); 1326 if( curl != NULL ) 1327 curl_easy_cleanup( curl ); 1275 1328 } 1276 1329 -
branches/1.5x/libtransmission/rpc-server.c
r8204 r8352 30 30 #include "transmission.h" 31 31 #include "bencode.h" 32 #include "crypto.h" 32 33 #include "list.h" 33 34 #include "platform.h" … … 54 55 struct evhttp * httpd; 55 56 tr_session * session; 57 char * sessionId; 56 58 char * username; 57 59 char * password; … … 446 448 } 447 449 448 static void 449 handle_request( struct evhttp_request * req, 450 void * arg ) 450 static char* 451 session_id_new( void ) 452 { 453 int i; 454 const int n = 48; 455 const char * pool = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; 456 const size_t pool_size = strlen( pool ); 457 char * buf = tr_new( char, n+1 ); 458 for( i=0; i<n; ++i ) 459 buf[i] = pool[ tr_cryptoRandInt( pool_size ) ]; 460 buf[n] = '\0'; 461 return buf; 462 } 463 464 static tr_bool 465 test_session_id( struct tr_rpc_server * server, struct evhttp_request * req ) 466 { 467 char * needle = tr_strdup_printf( "session_id=%s", server->sessionId ); 468 const char * haystack = evhttp_find_header( req->input_headers, "Cookie" ); 469 const tr_bool success = (haystack!=NULL) && (strstr(haystack,needle)!=NULL); 470 tr_free( needle ); 471 return success; 472 } 473 474 static void 475 handle_request( struct evhttp_request * req, void * arg ) 451 476 { 452 477 struct tr_rpc_server * server = arg; … … 455 480 { 456 481 const char * auth; 457 char * user = NULL; 458 char * pass = NULL; 482 char * user = NULL; 483 char * pass = NULL; 484 char * cookie; 459 485 460 486 evhttp_add_header( req->output_headers, "Server", MY_REALM ); 487 cookie = tr_strdup_printf( "session_id=%s;Path=/;Discard", server->sessionId ); 488 evhttp_add_header( req->output_headers, "Set-Cookie", cookie ); 489 tr_free( cookie ); 461 490 462 491 auth = evhttp_find_header( req->input_headers, "Authorization" ); 463 464 492 if( auth && !strncasecmp( auth, "basic ", 6 ) ) 465 493 { … … 475 503 if( !isAddressAllowed( server, req->remote_host ) ) 476 504 { 477 send_simple_response( req, 40 1,505 send_simple_response( req, 403, 478 506 "<p>Unauthorized IP Address.</p>" 479 507 "<p>Either disable the IP address whitelist or add your address to it.</p>" … … 505 533 { 506 534 handle_clutch( req, server ); 535 } 536 else if( !test_session_id( server, req ) ) 537 { 538 send_simple_response( req, 409, "<p>Invalid session_id cookie.</p>" ); 507 539 } 508 540 else if( !strncmp( req->uri, "/transmission/rpc", 17 ) ) … … 742 774 s = tr_new0( tr_rpc_server, 1 ); 743 775 s->session = session; 776 s->sessionId = session_id_new( ); 744 777 745 778 found = tr_bencDictFindInt( settings, TR_PREFS_KEY_RPC_ENABLED, &i );
Note: See TracChangeset
for help on using the changeset viewer.