]> granicus.if.org Git - transmission/commitdiff
#4400, #5462: Move BASE64 helpers to crypto-utils
authorMike Gelfand <mikedld@mikedld.com>
Thu, 4 Dec 2014 19:58:34 +0000 (19:58 +0000)
committerMike Gelfand <mikedld@mikedld.com>
Thu, 4 Dec 2014 19:58:34 +0000 (19:58 +0000)
On a way to factoring out OpenSSL support to a standalone file to ease
addition of other crypto libraries support in the future, move helpers
providing BASE64 encoding and decoding to crypto-utils.{c,h}. OpenSSL-
related functionality is moved to crypto-utils-openssl.c.

Add new functions to be implemented by crypto backends:
* tr_base64_encode_impl - encode from binary to BASE64,
* tr_base64_decode_impl - decode from BASE64 to binary.

Change `tr_base64_encode` and `tr_base64_decode` functions to expect
non-negative input data length which is considered real and never adjusted.
To process null-terminated strings (which was achieved before by passing 0
or -1 as input data length), add new `tr_base64_encode_str` and
`tr_base64_decode_str` functions which do not accept input data length as
an argument but calculate it on their own.

13 files changed:
daemon/remote.c
libtransmission/crypto-test.c
libtransmission/crypto-utils-openssl.c
libtransmission/crypto-utils.c
libtransmission/crypto-utils.h
libtransmission/libtransmission-test.c
libtransmission/rename-test.c
libtransmission/rpc-server.c
libtransmission/rpcimpl.c
libtransmission/utils-test.c
libtransmission/utils.c
libtransmission/utils.h
qt/add-data.cc

index 4f8cfffc3022a7fb2ac36539edd1a12308ef2eea..91b5b691252a1cd617d65c0194fd820bb8712591 100644 (file)
@@ -20,6 +20,7 @@
 #include <curl/curl.h>
 
 #include <libtransmission/transmission.h>
+#include <libtransmission/crypto-utils.h>
 #include <libtransmission/error.h>
 #include <libtransmission/file.h>
 #include <libtransmission/log.h>
@@ -1191,9 +1192,9 @@ printPeers (tr_variant * top)
 }
 
 static void
-printPiecesImpl (const uint8_t * raw, size_t rawlen, int64_t j)
+printPiecesImpl (const uint8_t * raw, size_t rawlen, size_t j)
 {
-    int i, k, len;
+    size_t i, k, len;
     char * str = tr_base64_decode (raw, rawlen, &len);
     printf ("  ");
     for (i=k=0; k<len; ++k) {
@@ -1225,7 +1226,8 @@ printPieces (tr_variant * top)
             tr_variant * torrent = tr_variantListChild (torrents, i);
             if (tr_variantDictFindRaw (torrent, TR_KEY_pieces, &raw, &rawlen) &&
                 tr_variantDictFindInt (torrent, TR_KEY_pieceCount, &j)) {
-                printPiecesImpl (raw, rawlen, j);
+                assert (j >= 0);
+                printPiecesImpl (raw, rawlen, (size_t) j);
                 if (i+1<n)
                     printf ("\n");
             }
index 697686897704f9ac81c704afc221134f238aaa16..26b06867f9e2e54c2c173292984b22e1103c9cc3 100644 (file)
@@ -183,6 +183,72 @@ test_random (void)
   return 0;
 }
 
+static int
+test_base64 (void)
+{
+  size_t len;
+  char * in, * out;
+  int i;
+
+  out = tr_base64_encode_str ("YOYO!", &len);
+  check_int_eq (8, len);
+  check_streq ("WU9ZTyE=", out);
+  in = tr_base64_decode_str (out, &len);
+  check_int_eq (5, len);
+  check_streq ("YOYO!", in);
+  tr_free (in);
+  tr_free (out);
+
+  out = tr_base64_encode ("", 0, &len);
+  check_int_eq (0, len);
+  check_streq ("", out);
+  out = tr_base64_decode ("", 0, &len);
+  check_int_eq (0, len);
+  check_streq ("", out);
+
+  out = tr_base64_encode (NULL, 0, &len);
+  check_int_eq (0, len);
+  check (out == NULL);
+  out = tr_base64_decode (NULL, 0, &len);
+  check_int_eq (0, len);
+  check (out == NULL);
+
+#define MAX_BUF_SIZE 1024
+
+  for (i = 1; i <= MAX_BUF_SIZE; ++i)
+    {
+      int j;
+      char buf[MAX_BUF_SIZE + 1];
+
+      for (j = 0; j < i; ++j)
+        buf[j] = tr_rand_int_weak (256);
+
+      out = tr_base64_encode (buf, j, &len);
+      check_int_eq ((j + 2) / 3 * 4, len);
+      in = tr_base64_decode (out, len, &len);
+      check_int_eq (j, len);
+      check (memcmp (in, buf, len) == 0);
+      tr_free (in);
+      tr_free (out);
+
+      for (j = 0; j < i; ++j)
+        buf[j] = 1 + tr_rand_int_weak (255);
+      buf[j] = '\0';
+
+      out = tr_base64_encode_str (buf, &len);
+      check_int_eq ((j + 2) / 3 * 4, len);
+      in = tr_base64_decode_str (out, &len);
+      check_int_eq (j, len);
+      check_streq (in, buf);
+      tr_free (in);
+      tr_free (out);
+    }
+
+#undef MAX_BUF_SIZE
+
+  return 0;
+}
+
 int
 main (void)
 {
@@ -190,7 +256,8 @@ main (void)
                              test_encrypt_decrypt,
                              test_sha1,
                              test_ssha1,
-                             test_random };
+                             test_random,
+                             test_base64 };
 
   return runTests (tests, NUM_TESTS (tests));
 }
index 2245f153f3764bbed4b150b29d07fe2fd9167a84..580071ef8f030d41593b272f959de091e3cb3dad 100644 (file)
@@ -9,7 +9,9 @@
 
 #include <assert.h>
 
+#include <openssl/bio.h>
 #include <openssl/bn.h>
+#include <openssl/buffer.h>
 #include <openssl/dh.h>
 #include <openssl/err.h>
 #include <openssl/evp.h>
@@ -301,3 +303,92 @@ tr_rand_buffer (void   * buffer,
 
   return check_result (RAND_bytes (buffer, (int) length));
 }
+
+/***
+****
+***/
+
+void *
+tr_base64_encode_impl (const void * input,
+                       size_t       input_length,
+                       size_t     * output_length)
+{
+  char * ret = NULL;
+  int ret_length = 0;
+  BIO * bmem;
+  BIO * b64;
+
+  assert (input != NULL);
+  assert (input_length > 0);
+
+  bmem = BIO_new (BIO_s_mem ());
+  b64 = BIO_new (BIO_f_base64 ());
+
+  BIO_set_flags (b64, BIO_FLAGS_BASE64_NO_NL);
+  b64 = BIO_push (b64, bmem);
+
+  if (check_result_eq (BIO_write (b64, input, input_length), (int) input_length) &&
+      check_result (BIO_flush (b64)))
+    {
+      BUF_MEM * bptr;
+
+      BIO_get_mem_ptr (b64, &bptr);
+      ret = tr_strndup (bptr->data, bptr->length);
+      ret_length = bptr->length;
+    }
+
+  BIO_free_all (b64);
+
+  if (output_length != NULL)
+    *output_length = (size_t) ret_length;
+
+  return ret;
+}
+
+void *
+tr_base64_decode_impl (const void * input,
+                       size_t       input_length,
+                       size_t     * output_length)
+{
+  char * ret;
+  int ret_length;
+  int i;
+
+  assert (input != NULL);
+  assert (input_length > 0);
+
+  ret = tr_new (char, input_length + 1);
+
+  /* try two times, without and with BIO_FLAGS_BASE64_NO_NL flag */
+  for (i = 0; i < 2; ++i)
+    {
+      BIO * bmem = BIO_new_mem_buf ((void *) input, (int) input_length);
+      BIO * b64 = BIO_new (BIO_f_base64 ());
+
+      BIO_set_flags (b64, i == 1 ? BIO_FLAGS_BASE64_NO_NL : 0);
+      bmem = BIO_push (b64, bmem);
+
+      ret_length = BIO_read (bmem, ret, (int) input_length);
+      if (ret_length < 0 && i == 1)
+        log_error ();
+
+      BIO_free_all (bmem);
+
+      /* < 0 - fatal error, > 0 - success*/
+      if (ret_length != 0)
+        break;
+    }
+
+  if (ret_length < 0)
+    {
+      tr_free (ret);
+      return NULL;
+    }
+
+  ret[ret_length] = '\0';
+
+  if (output_length != NULL)
+    *output_length = (size_t) ret_length;
+
+  return ret;
+}
index a11cdee531a42af374e202aefa7210cee91d74f8..b91c268cb07d40ab30ecae0cf9103f4f406cf3ed 100644 (file)
@@ -10,7 +10,7 @@
 #include <assert.h>
 #include <stdarg.h>
 #include <stdlib.h> /* abs (), srand (), rand () */
-#include <string.h> /* memmove (), memset () */
+#include <string.h> /* memmove (), memset (), strlen () */
 
 #include "transmission.h"
 #include "crypto-utils.h"
@@ -115,3 +115,77 @@ tr_rand_int_weak (int upper_bound)
 
   return rand () % upper_bound;
 }
+
+/***
+****
+***/
+
+void *
+tr_base64_encode (const void * input,
+                  size_t       input_length,
+                  size_t     * output_length)
+{
+  char * ret;
+
+  if (input != NULL)
+    {
+      if (input_length != 0)
+        {
+          if ((ret = tr_base64_encode_impl (input, input_length, output_length)) != NULL)
+            return ret;
+        }
+      else
+        ret = tr_strdup ("");
+    }
+  else
+    {
+      ret = NULL;
+    }
+
+  if (output_length != NULL)
+    *output_length = 0;
+
+  return ret;
+}
+
+void *
+tr_base64_encode_str (const char * input,
+                      size_t     * output_length)
+{
+  return tr_base64_encode (input, input == NULL ? 0 : strlen (input), output_length);
+}
+
+void *
+tr_base64_decode (const void * input,
+                  size_t       input_length,
+                  size_t     * output_length)
+{
+  char * ret;
+
+  if (input != NULL)
+    {
+      if (input_length != 0)
+        {
+          if ((ret = tr_base64_decode_impl (input, input_length, output_length)) != NULL)
+            return ret;
+        }
+      else
+        ret = tr_strdup ("");
+    }
+  else
+    {
+      ret = NULL;
+    }
+
+  if (output_length != NULL)
+    *output_length = 0;
+
+  return ret;
+}
+
+void *
+tr_base64_decode_str (const char * input,
+                      size_t     * output_length)
+{
+  return tr_base64_decode (input, input == NULL ? 0 : strlen (input), output_length);
+}
index 3091443b61c251c1ef81e591fae89a472ccd80e9..de8e34075d037e8a6ae69ded6f22f07426e9974a 100644 (file)
 #include <inttypes.h>
 #include <stddef.h>
 
-#include "utils.h" /* TR_GNUC_NULL_TERMINATED */
+#include "utils.h" /* TR_GNUC_MALLOC, TR_GNUC_NULL_TERMINATED */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 /**
 *** @addtogroup utils Utilities
@@ -150,6 +154,56 @@ int              tr_rand_int_weak      (int              upper_bound);
 bool             tr_rand_buffer        (void           * buffer,
                                         size_t           length);
 
+/**
+ * @brief Translate a block of bytes into base64.
+ * @return a newly-allocated null-terminated string that can be freed with tr_free ()
+ */
+void           * tr_base64_encode      (const void     * input,
+                                        size_t           input_length,
+                                        size_t         * output_length) TR_GNUC_MALLOC;
+
+/**
+ * @brief Translate null-terminated string into base64.
+ * @return a newly-allocated null-terminated string that can be freed with tr_free ()
+ */
+void           * tr_base64_encode_str  (const char     * input,
+                                        size_t         * output_length) TR_GNUC_MALLOC;
+
+/**
+ * @brief Translate a block of bytes into base64 (internal, do not use).
+ * @return a newly-allocated null-terminated string that can be freed with tr_free ()
+ */
+void           * tr_base64_encode_impl (const void     * input,
+                                        size_t           input_length,
+                                        size_t         * output_length) TR_GNUC_MALLOC;
+
+/**
+ * @brief Translate a block of bytes from base64 into raw form.
+ * @return a newly-allocated null-terminated string that can be freed with tr_free ()
+ */
+void           * tr_base64_decode      (const void     * input,
+                                        size_t           input_length,
+                                        size_t         * output_length) TR_GNUC_MALLOC;
+
+/**
+ * @brief Translate null-terminated string from base64 into raw form.
+ * @return a newly-allocated null-terminated string that can be freed with tr_free ()
+ */
+void           * tr_base64_decode_str  (const char     * input,
+                                        size_t         * output_length) TR_GNUC_MALLOC;
+
+/**
+ * @brief Translate null-terminated string from base64 into raw form (internal, do not use).
+ * @return a newly-allocated null-terminated string that can be freed with tr_free ()
+ */
+void           * tr_base64_decode_impl (const void     * input,
+                                        size_t           input_length,
+                                        size_t         * output_length) TR_GNUC_MALLOC;
+
 /** @} */
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* TR_CRYPTO_UTILS_H */
index 032f3e2e2fcf70e1afc6a030f58dbf2362500796..83ceadbfd025719c294e470fdde87c40deb236c7 100644 (file)
@@ -14,6 +14,7 @@
 #include <unistd.h>
 
 #include "transmission.h"
+#include "crypto-utils.h"
 #include "error.h"
 #include "file.h"
 #include "platform.h" /* TR_PATH_DELIMETER */
@@ -310,7 +311,7 @@ tr_torrent *
 libttest_zero_torrent_init (tr_session * session)
 {
   int err;
-  int metainfo_len;
+  size_t metainfo_len;
   char * metainfo;
   const char * metainfo_base64;
   tr_torrent * tor;
@@ -342,7 +343,7 @@ libttest_zero_torrent_init (tr_session * session)
     "OnByaXZhdGVpMGVlZQ==";
 
   /* create the torrent ctor */
-  metainfo = tr_base64_decode (metainfo_base64, -1, &metainfo_len);
+  metainfo = tr_base64_decode_str (metainfo_base64, &metainfo_len);
   assert (metainfo != NULL);
   assert (metainfo_len > 0);
   assert (session != NULL);
index a48fcac75fa23b137ee231163a61e1caa80608e6..aad099689f2948e6e5976ac527437d1eba5ccbf6 100644 (file)
@@ -15,6 +15,7 @@
 #include <unistd.h> /* sync() */
 
 #include "transmission.h"
+#include "crypto-utils.h"
 #include "file.h"
 #include "resume.h"
 #include "torrent.h" /* tr_isTorrent() */
@@ -101,12 +102,12 @@ static tr_torrent *
 create_torrent_from_base64_metainfo (tr_ctor * ctor, const char * metainfo_base64)
 {
   int err;
-  int metainfo_len;
+  size_t metainfo_len;
   char * metainfo;
   tr_torrent * tor;
 
   /* create the torrent ctor */
-  metainfo = tr_base64_decode (metainfo_base64, -1, &metainfo_len);
+  metainfo = tr_base64_decode_str (metainfo_base64, &metainfo_len);
   assert (metainfo != NULL);
   assert (metainfo_len > 0);
   tr_ctorSetMetainfo (ctor, (uint8_t*)metainfo, metainfo_len);
index 367819493d6b6df2c8a1c3021a12644b824584d4..505408ace45090b9f8ef492701c8b346aeaf766b 100644 (file)
@@ -611,8 +611,8 @@ handle_request (struct evhttp_request * req, void * arg)
       auth = evhttp_find_header (req->input_headers, "Authorization");
       if (auth && !evutil_ascii_strncasecmp (auth, "basic ", 6))
         {
-          int plen;
-          char * p = tr_base64_decode (auth + 6, 0, &plen);
+          size_t plen;
+          char * p = tr_base64_decode_str (auth + 6, &plen);
           if (p && plen && ((pass = strchr (p, ':'))))
             {
               user = p;
index fab0a207f9d9228065c2867d5e21a3a6a8abe25a..33621e93fe676d6fdf1704a4651019418ace3a3d 100644 (file)
@@ -19,6 +19,7 @@
 
 #include "transmission.h"
 #include "completion.h"
+#include "crypto-utils.h"
 #include "error.h"
 #include "fdlimit.h"
 #include "file.h"
@@ -1796,8 +1797,8 @@ torrentAdd (tr_session               * session,
 
           if (fname == NULL)
             {
-              int len;
-              char * metainfo = tr_base64_decode (metainfo_base64, -1, &len);
+              size_t len;
+              char * metainfo = tr_base64_decode_str (metainfo_base64, &len);
               tr_ctorSetMetainfo (ctor, (uint8_t*)metainfo, len);
               tr_free (metainfo);
             }
index 2ff9b8b7f5727fd9ceb2485803eeea9158288e45..d9fb9309157b7af279d82c501bc00a773ee54781 100644 (file)
 
 #include "libtransmission-test.h"
 
-static int
-test_base64 (void)
-{
-  int len;
-  char *in, *out;
-
-  /* base64 */
-  out = tr_base64_encode ("YOYO!", -1, &len);
-  check_streq ("WU9ZTyE=", out);
-  check_int_eq (8, len);
-  in = tr_base64_decode (out, -1, &len);
-  check_streq ("YOYO!", in);
-  check_int_eq (5, len);
-  tr_free (in);
-  tr_free (out);
-  out = tr_base64_encode (NULL, 0, &len);
-  check (out == NULL);
-  check_int_eq (0, len);
-
-  return 0;
-}
-
 static int
 test_strip_positional_args (void)
 {
@@ -518,7 +496,6 @@ int
 main (void)
 {
   const testFunc tests[] = { test_array,
-                             test_base64,
                              test_buildpath,
                              test_hex,
                              test_lowerbound,
index 4c0792d3eb2c30ecf237d51062ba2aa193eab43f..d1f98729a2d389e05d69d85b083f442e47b2c7c4 100644 (file)
@@ -812,82 +812,6 @@ tr_urlParse (const char * url_in,
   return err;
 }
 
-#include <string.h>
-#include <openssl/sha.h>
-#include <openssl/hmac.h>
-#include <openssl/evp.h>
-#include <openssl/bio.h>
-#include <openssl/buffer.h>
-
-char *
-tr_base64_encode (const void * input, int length, int * setme_len)
-{
-  int retlen = 0;
-  char * ret = NULL;
-
-  if (input != NULL)
-    {
-      BIO * b64;
-      BIO * bmem;
-      BUF_MEM * bptr;
-
-      if (length < 1)
-        length = (int)strlen (input);
-
-      bmem = BIO_new (BIO_s_mem ());
-      b64 = BIO_new (BIO_f_base64 ());
-      BIO_set_flags (b64, BIO_FLAGS_BASE64_NO_NL);
-      b64 = BIO_push (b64, bmem);
-      BIO_write (b64, input, length);
-      (void) BIO_flush (b64);
-      BIO_get_mem_ptr (b64, &bptr);
-      ret = tr_strndup (bptr->data, bptr->length);
-      retlen = bptr->length;
-      BIO_free_all (b64);
-    }
-
-  if (setme_len)
-    *setme_len = retlen;
-
-  return ret;
-}
-
-char *
-tr_base64_decode (const void * input,
-                  int          length,
-                  int *        setme_len)
-{
-  char * ret;
-  BIO * b64;
-  BIO * bmem;
-  int retlen;
-
-  if (length < 1)
-    length = strlen (input);
-
-  ret = tr_new0 (char, length);
-  b64 = BIO_new (BIO_f_base64 ());
-  bmem = BIO_new_mem_buf ((unsigned char*)input, length);
-  bmem = BIO_push (b64, bmem);
-  retlen = BIO_read (bmem, ret, length);
-  if (!retlen)
-    {
-      /* try again, but with the BIO_FLAGS_BASE64_NO_NL flag */
-      BIO_free_all (bmem);
-      b64 = BIO_new (BIO_f_base64 ());
-      BIO_set_flags (b64, BIO_FLAGS_BASE64_NO_NL);
-      bmem = BIO_new_mem_buf ((unsigned char*)input, length);
-      bmem = BIO_push (b64, bmem);
-      retlen = BIO_read (bmem, ret, length);
-    }
-
-  if (setme_len)
-    *setme_len = retlen;
-
-  BIO_free_all (bmem);
-  return ret;
-}
-
 /***
 ****
 ***/
index 8cda66f8cb21488140a4eff21116fc161b44f04f..3e6f2d88f2b0654a10f0029abf0cde34e312de45 100644 (file)
@@ -287,22 +287,6 @@ char* tr_strdup_printf (const char * fmt, ...) TR_GNUC_PRINTF (1, 2)
 char * tr_strdup_vprintf (const char * fmt,
                           va_list      args) TR_GNUC_MALLOC;
 
-/**
- * @brief Translate a block of bytes into base64
- * @return a newly-allocated string that can be freed with tr_free ()
- */
-char* tr_base64_encode (const void * input,
-                        int          inlen,
-                        int        * outlen) TR_GNUC_MALLOC;
-
-/**
- * @brief Translate a block of bytes from base64 into raw form
- * @return a newly-allocated string that can be freed with tr_free ()
- */
-char* tr_base64_decode (const void * input,
-                        int          inlen,
-                        int        * outlen) TR_GNUC_MALLOC;
-
 /** @brief Portability wrapper for strlcpy () that uses the system implementation if available */
 size_t tr_strlcpy (char * dst, const void * src, size_t siz);
 
index 3ce5b36ef75606f1f6d2f6f30820dfd3079a213d..b9f4979ad878adc1dde164d6632a1349238b08de 100644 (file)
@@ -11,7 +11,7 @@
 #include <QDir>
 
 #include <libtransmission/transmission.h>
-#include <libtransmission/utils.h> // tr_base64_encode()
+#include <libtransmission/crypto-utils.h> // tr_base64_encode()
 
 #include "add-data.h"
 #include "utils.h"
@@ -46,11 +46,11 @@ AddData :: set (const QString& key)
     }
   else
     {
-      int len;
-      char * raw = tr_base64_decode (key.toUtf8().constData(), key.toUtf8().size(), &len);
+      size_t len;
+      void * raw = tr_base64_decode (key.toUtf8().constData(), key.toUtf8().size(), &len);
       if (raw)
         {
-          metainfo.append (raw, len);
+          metainfo.append (static_cast<const char*> (raw), (int) len);
           tr_free (raw);
           type = METAINFO;
         }
@@ -70,9 +70,9 @@ AddData :: toBase64 () const
 
   if (!metainfo.isEmpty ())
     {
-      int len = 0;
-      char * b64 = tr_base64_encode (metainfo.constData(), metainfo.size(), &len);
-      ret = QByteArray (b64, len);
+      size_t len;
+      void * b64 = tr_base64_encode (metainfo.constData(), metainfo.size(), &len);
+      ret = QByteArray (static_cast<const char*> (b64), (int) len);
       tr_free (b64);
     }