Changeset 8356


Ignore:
Timestamp:
May 8, 2009, 2:35:02 PM (12 years ago)
Author:
charles
Message:

(trunk) revert r8351; it's not a sufficient fix

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/daemon/remote.c

    r8351 r8356  
    133133static char * auth = NULL;
    134134static char * netrc = NULL;
    135 static char * cookies = NULL;
    136135
    137136static char*
     
    12751274}
    12761275
    1277 /* very basic handling of cookies: when we get Set-Cookie, throw out all
    1278  * the previous cookies...  T only uses one cookie (session_id) */
    1279 static size_t
    1280 parseResponseHeader( void *ptr, size_t size, size_t nmemb, void * stream UNUSED )
    1281 {
    1282     const char * line = ptr;
    1283     const size_t linelen = size * nmemb;
    1284     const char * lineend = line + linelen;
    1285     const char * key = "Set-Cookie: ";
    1286     const size_t keylen = strlen( key );
    1287     if( ( linelen >= keylen ) && !memcmp( line, key, keylen ) ) {
    1288         const char * begin = line + keylen;
    1289         const char * end = begin;
    1290         while(( end!=lineend ) && !strchr("\r\n",*end))
    1291             ++end;
    1292         tr_free( cookies );
    1293         cookies = tr_strndup( begin, end-begin );
    1294     }
    1295 
    1296     return linelen;
    1297 }
    1298 
    1299 static CURL*
    1300 tr_curl_easy_init( struct evbuffer * writebuf )
    1301 {
    1302     CURL * curl = curl_easy_init( );
    1303     curl_easy_setopt( curl, CURLOPT_USERAGENT, MY_NAME "/" LONG_VERSION_STRING );
    1304     curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, writeFunc );
    1305     curl_easy_setopt( curl, CURLOPT_WRITEDATA, writebuf );
    1306     curl_easy_setopt( curl, CURLOPT_HEADERFUNCTION, parseResponseHeader );
    1307     curl_easy_setopt( curl, CURLOPT_POST, 1 );
    1308     curl_easy_setopt( curl, CURLOPT_NETRC, CURL_NETRC_OPTIONAL );
    1309     curl_easy_setopt( curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY );
    1310     curl_easy_setopt( curl, CURLOPT_TIMEOUT, 60L );
    1311     curl_easy_setopt( curl, CURLOPT_VERBOSE, debug );
    1312 #ifdef HAVE_ZLIB
    1313     curl_easy_setopt( curl, CURLOPT_ENCODING, "deflate" );
    1314 #endif
    1315     if( cookies )
    1316         curl_easy_setopt( curl, CURLOPT_COOKIE, cookies );
    1317     if( netrc )
    1318         curl_easy_setopt( curl, CURLOPT_NETRC_FILE, netrc );
    1319     if( auth )
    1320         curl_easy_setopt( curl, CURLOPT_USERPWD, auth );
    1321     return curl;
    1322 }
    1323    
    1324 
    13251276static void
    13261277processRequests( const char *  host,
     
    13291280                 int           reqCount )
    13301281{
    1331     int i;
    1332     CURL * curl = NULL;
     1282    int               i;
     1283    CURL *            curl;
    13331284    struct evbuffer * buf = evbuffer_new( );
    1334     char * url = tr_strdup_printf( "http://%s:%d/transmission/rpc", host, port );
    1335 
    1336     for( i=0; i<reqCount; ++i )
     1285    char *            url = tr_strdup_printf(
     1286        "http://%s:%d/transmission/rpc", host, port );
     1287
     1288    curl = curl_easy_init( );
     1289    curl_easy_setopt( curl, CURLOPT_VERBOSE, debug );
     1290#ifdef HAVE_ZLIB
     1291    curl_easy_setopt( curl, CURLOPT_ENCODING, "deflate" );
     1292#endif
     1293    curl_easy_setopt( curl, CURLOPT_USERAGENT, MY_NAME "/" LONG_VERSION_STRING );
     1294    curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, writeFunc );
     1295    curl_easy_setopt( curl, CURLOPT_WRITEDATA, buf );
     1296    curl_easy_setopt( curl, CURLOPT_POST, 1 );
     1297    curl_easy_setopt( curl, CURLOPT_URL, url );
     1298    curl_easy_setopt( curl, CURLOPT_NETRC, CURL_NETRC_OPTIONAL );
     1299    curl_easy_setopt( curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY );
     1300    curl_easy_setopt( curl, CURLOPT_TIMEOUT, 60L );
     1301    if( netrc )
     1302        curl_easy_setopt( curl, CURLOPT_NETRC_FILE, netrc );
     1303    if( auth )
     1304        curl_easy_setopt( curl, CURLOPT_USERPWD, auth );
     1305
     1306    for( i = 0; i < reqCount; ++i )
    13371307    {
    13381308        CURLcode res;
    1339         evbuffer_drain( buf, EVBUFFER_LENGTH( buf ) );
    1340 
    1341         if( curl == NULL )
    1342         {
    1343             curl = tr_curl_easy_init( buf );
    1344             curl_easy_setopt( curl, CURLOPT_URL, url );
    1345         }
    1346 
    13471309        curl_easy_setopt( curl, CURLOPT_POSTFIELDS, reqs[i] );
    1348 
    13491310        if( debug )
    13501311            fprintf( stderr, "posting:\n--------\n%s\n--------\n", reqs[i] );
    13511312        if( ( res = curl_easy_perform( curl ) ) )
    1352             tr_nerr( MY_NAME, "(%s:%d) %s", host, port, curl_easy_strerror( res ) );
    1353         else {
    1354             long response;
    1355             curl_easy_getinfo( curl, CURLINFO_RESPONSE_CODE, &response );
    1356             switch( response ) {
    1357                 case 200:
    1358                     processResponse( host, port, EVBUFFER_DATA(buf), EVBUFFER_LENGTH(buf) );
    1359                     break;
    1360                 case 409:
    1361                     /* session_id cookie expired.  by the time we reach line this our
    1362                      * curl header func has already found the new session_id, so make
    1363                      * a new CURL* and try again... */
    1364                     curl_easy_cleanup( curl );
    1365                     curl = NULL;
    1366                     --i;
    1367                     break;
    1368                 default:
    1369                     fprintf( stderr, "Unexpected response: %s\n", (char*)EVBUFFER_DATA(buf) );
    1370                     break;
    1371             }
    1372         }
     1313            tr_nerr( MY_NAME, "(%s:%d) %s", host, port,
     1314                    curl_easy_strerror( res ) );
     1315        else
     1316            processResponse( host, port, EVBUFFER_DATA(
     1317                                buf ), EVBUFFER_LENGTH( buf ) );
     1318
     1319        evbuffer_drain( buf, EVBUFFER_LENGTH( buf ) );
    13731320    }
    13741321
     
    13761323    tr_free( url );
    13771324    evbuffer_free( buf );
    1378     if( curl != NULL )
    1379         curl_easy_cleanup( curl );
     1325    curl_easy_cleanup( curl );
    13801326}
    13811327
  • trunk/libtransmission/rpc-server.c

    r8351 r8356  
    5757    struct evhttp *    httpd;
    5858    tr_session *       session;
    59     char *             sessionId;
    6059    char *             username;
    6160    char *             password;
     
    452451}
    453452
    454 static char*
    455 session_id_new( void )
    456 {
    457     int i;
    458     const int n = 48;
    459     const char * pool = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    460     const size_t pool_size = strlen( pool );
    461     char * buf = tr_new( char, n+1 );
    462     for( i=0; i<n; ++i )
    463         buf[i] = pool[ tr_cryptoRandInt( pool_size ) ];
    464     buf[n] = '\0';
    465     return buf;
    466 }
    467 
    468 static tr_bool
    469 test_session_id( struct tr_rpc_server * server, struct evhttp_request * req )
    470 {
    471     char * needle = tr_strdup_printf( "session_id=%s", server->sessionId );
    472     const char * haystack = evhttp_find_header( req->input_headers, "Cookie" );
    473     const tr_bool success = (haystack!=NULL) && (strstr(haystack,needle)!=NULL);
    474     tr_free( needle );
    475     return success;
    476 }
    477 
    478 static void
    479 handle_request( struct evhttp_request * req, void * arg )
     453static void
     454handle_request( struct evhttp_request * req,
     455                void *                  arg )
    480456{
    481457    struct tr_rpc_server * server = arg;
     
    484460    {
    485461        const char * auth;
    486         char * user = NULL;
    487         char * pass = NULL;
    488         char * cookie;
     462        char *       user = NULL;
     463        char *       pass = NULL;
    489464
    490465        evhttp_add_header( req->output_headers, "Server", MY_REALM );
    491         cookie = tr_strdup_printf( "session_id=%s;Path=/;Discard", server->sessionId );
    492         evhttp_add_header( req->output_headers, "Set-Cookie", cookie );
    493         tr_free( cookie );
    494466
    495467        auth = evhttp_find_header( req->input_headers, "Authorization" );
     468
    496469        if( auth && !strncasecmp( auth, "basic ", 6 ) )
    497470        {
     
    507480        if( !isAddressAllowed( server, req->remote_host ) )
    508481        {
    509             send_simple_response( req, 403,
     482            send_simple_response( req, 401,
    510483                "<p>Unauthorized IP Address.</p>"
    511484                "<p>Either disable the IP address whitelist or add your address to it.</p>"
     
    538511        {
    539512            handle_clutch( req, server );
    540         }
    541         else if( !test_session_id( server, req ) )
    542         {
    543             send_simple_response( req, 409, "<p>Invalid session_id cookie.</p>" );
    544513        }
    545514        else if( !strncmp( req->uri, "/transmission/rpc", 17 ) )
     
    798767    s = tr_new0( tr_rpc_server, 1 );
    799768    s->session = session;
    800     s->sessionId = session_id_new( );
    801769
    802770    found = tr_bencDictFindBool( settings, TR_PREFS_KEY_RPC_ENABLED, &boolVal );
  • trunk/qt/session.cc

    r8355 r8356  
    542542        header.setValue( "User-Agent", QCoreApplication::instance()->applicationName() + "/" + LONG_VERSION_STRING );
    543543        header.setValue( "Content-Type", "application/json; charset=UTF-8" );
    544         if( !myCookies.isEmpty( ) )
    545             header.setValue( "Cookie", myCookies );
    546         QBuffer * buf = new QBuffer;
    547         buf->setData( data );
    548         myHttp.request( header, buf, &myBuffer );
     544        myHttp.request( header, data, &myBuffer );
    549545#ifdef DEBUG_HTTP
    550546        std::cerr << "sending " << qPrintable(header.toString()) << "\nBody:\n" << request << std::endl;
     
    565561{
    566562    Q_UNUSED( id );
    567 
    568     QHttpResponseHeader response = myHttp.lastResponse();
    569     QIODevice * sourceDevice = myHttp.currentSourceDevice( );
    570563
    571564#ifdef DEBUG_HTTP
     
    577570#endif
    578571
    579     // very basic handling of cookies: when we get Set-Cookie, throw out all
    580     // the previous cookies...  T only uses one cookie (session_id)
    581     const QString responseCookies = response.value( "Set-Cookie" );
    582     if( !responseCookies.isEmpty( ) )
    583         myCookies = responseCookies;
    584        
    585     if( response.statusCode() == 409 )
    586     {
    587         // we got a 409 telling us our session cookie has expired.
    588         // now that we've updated our cookie, try again.
    589         exec( qobject_cast<QBuffer*>(sourceDevice)->buffer().constData( ) );
    590     }
    591     else if( error )
    592     {
     572    if( error )
    593573        std::cerr << "http error: " << qPrintable(myHttp.errorString()) << std::endl;
    594     }
    595     else
    596     {
     574    else {
    597575        const QByteArray& response( myBuffer.buffer( ) );
    598576        const char * json( response.constData( ) );
    599577        int jsonLength( response.size( ) );
    600578        if( jsonLength>0 && json[jsonLength-1] == '\n' ) --jsonLength;
     579
    601580        parseResponse( json, jsonLength );
    602581    }
    603582
    604     delete sourceDevice;
    605583    myBuffer.buffer( ).clear( );
    606584    myBuffer.reset( );
  • trunk/qt/session.h

    r8351 r8356  
    133133        tr_session * mySession;
    134134        QString myConfigDir;
    135         QString myCookies;
    136135        QUrl myUrl;
    137136        QBuffer myBuffer;
Note: See TracChangeset for help on using the changeset viewer.