]> granicus.if.org Git - transmission/commitdiff
(trunk libT) #1276 - hash rpc password with sha1
authorErick Turnquist <jhujhiti@adjectivism.org>
Tue, 24 Mar 2009 01:39:06 +0000 (01:39 +0000)
committerErick Turnquist <jhujhiti@adjectivism.org>
Tue, 24 Mar 2009 01:39:06 +0000 (01:39 +0000)
libtransmission/crypto.c
libtransmission/crypto.h
libtransmission/rpc-server.c

index 3bb2ba6e59a06d09502283cf7393c299d2b8fa67..e12e843d2fa7e743500eaea1cd587eb833acb144 100644 (file)
@@ -355,21 +355,59 @@ tr_cryptoRandBuf( unsigned char *buf,
 ***/
 
 char*
-tr_crypt( const void * plaintext )
+tr_ssha1( const void * plaintext )
 {
     static const char * salter = "0123456789"
                                  "abcdefghijklmnopqrstuvwxyz"
                                  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                                  "./";
     static const size_t salter_len = 64;
+    static const size_t saltval_len = 8;
 
     int i;
-    char salt[12];
+    char salt[saltval_len];
+    char sha[SHA_DIGEST_LENGTH];
+    char buf[2*SHA_DIGEST_LENGTH + saltval_len + 2];
 
-    memcpy( salt, "$1$", 3 );
-    for( i=0; i<8; ++i )
-        salt[3+i] = salter[ tr_cryptoRandInt( salter_len ) ];
-    salt[11] = '\0';
+    for( i=0; i<=saltval_len; ++i )
+        salt[i] = salter[ tr_cryptoRandInt( salter_len ) ];
 
-    return tr_strdup( DES_crypt( plaintext, salt ) );
+    tr_sha1( sha, plaintext, strlen( plaintext ), salt, saltval_len, NULL );
+    tr_sha1_to_hex( &buf[1], &sha );
+    memcpy( &buf[1+2*SHA_DIGEST_LENGTH], &salt, saltval_len );
+    buf[1+2*SHA_DIGEST_LENGTH + saltval_len] = '\0';
+    buf[0] = '{'; /* signal that this is a hash. this makes saving/restoring
+                     easier */
+
+    return tr_strdup( &buf );
+}
+
+tr_bool
+tr_ssha1_matches( const char * source, const char * pass )
+{
+    char * salt;
+    size_t saltlen;
+    char * hashed;
+    char buf[SHA_DIGEST_LENGTH];
+    tr_bool result;
+
+    /* extract the salt */
+    saltlen = strlen( source ) - 2*SHA_DIGEST_LENGTH-1;
+    salt = tr_malloc( saltlen );
+    memcpy( salt, source + 2*SHA_DIGEST_LENGTH+1, saltlen );
+
+    /* hash pass + salt */
+    hashed = tr_malloc( 2*SHA_DIGEST_LENGTH + saltlen + 2 );
+    tr_sha1( &buf, pass, strlen( pass ), salt, saltlen, NULL );
+    tr_sha1_to_hex( &hashed[1], &buf );
+    memcpy( hashed + 1+2*SHA_DIGEST_LENGTH, salt, saltlen );
+    hashed[1+2*SHA_DIGEST_LENGTH + saltlen] = '\0';
+    hashed[0] = '{';
+
+    result = strcmp( source, hashed ) == 0 ? TRUE : FALSE;
+
+    tr_free( hashed );
+    tr_free( salt );
+    
+    return result;
 }
index ef41c41037960b0574d3504c39e7f7e924827ae6..48a39e7ab8fc11a4f193cba9dac86ac1ee641bb3 100644 (file)
@@ -95,7 +95,8 @@ int            tr_cryptoWeakRandInt( int n );
 void           tr_cryptoRandBuf( unsigned char *buf,
                                  size_t         len );
 
-char*          tr_crypt( const void * plaintext );
+char*          tr_ssha1( const void * plaintext );
 
+tr_bool        tr_ssha1_matches( const char * source, const char * pass );
 
 #endif
index ef0ecc46460400f2ed40c69718b8595c42e27249..33edac71769ceee9a1e677dbc808bd3be29e82ae 100644 (file)
@@ -465,7 +465,6 @@ handle_request( struct evhttp_request * req,
             {
                 user = p;
                 *pass++ = '\0';
-                pass = tr_crypt( pass );
             }
         }
 
@@ -479,7 +478,8 @@ handle_request( struct evhttp_request * req,
         }
         else if( server->isPasswordEnabled
                  && ( !pass || !user || strcmp( server->username, user )
-                                     || strcmp( server->password, pass ) ) )
+                                     || !tr_ssha1_matches( server->password,
+                                                           pass ) ) )
         {
             evhttp_add_header( req->output_headers,
                                "WWW-Authenticate",
@@ -511,7 +511,6 @@ handle_request( struct evhttp_request * req,
             send_simple_response( req, HTTP_NOTFOUND, req->uri );
         }
 
-        tr_free( pass );
         tr_free( user );
     }
 }
@@ -671,7 +670,10 @@ tr_rpcSetPassword( tr_rpc_server * server,
                    const char *    password )
 {
     tr_free( server->password );
-    server->password = tr_crypt( password );
+    if( *password != '{' )
+        server->password = tr_ssha1( password );
+    else
+        server->password = strdup( password );
     dbgmsg( "setting our Password to [%s]", server->password );
 }
 
@@ -762,7 +764,10 @@ tr_rpcInit( tr_session  * session,
 
     found = tr_bencDictFindStr( settings, TR_PREFS_KEY_RPC_PASSWORD, &str );
     assert( found );
-    s->password = tr_strdup( str );
+    if( *str != '{' )
+        s->password = tr_ssha1( str );
+    else
+        s->password = strdup( str );
 
 #ifdef HAVE_ZLIB
     s->stream.zalloc = (alloc_func) Z_NULL;