Fixed printable fingerprint buffer overflow. RedHat bug 372021.
authorPekka Riikonen <priikone@silcnet.org>
Tue, 8 Jan 2008 07:49:48 +0000 (07:49 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Tue, 8 Jan 2008 07:49:48 +0000 (07:49 +0000)
CHANGES.RUNTIME
lib/silcutil/silcutil.c
lib/silcutil/silcutil.h

index b7b5e2f4796cd51689407d7112f8bcafe95bae5e..9ce124dd32587e722365e66230b108b3f5b97a81 100644 (file)
@@ -1,3 +1,8 @@
+Tue Jan  8 09:41:57 EET 2008  Pekka Riikonen <priikone@silcnet.org>
+
+        * Fixed printable fingerprint bufferoverlfow, RedHat bug 372021.
+          Affected file is lib/silcutil/silcutil.c.
+
 Sat Jan  5 20:19:28 EET 2008  Pekka Riikonen <priikone@silcnet.org>
 
        * Added SILC_STR_DELETE buffer format macro.  Added support for
index eb0d989e835791fd78d5e2514e1a2709cd8a3c47..07688e36c55ce90fa864ad9fa443662095e6a007 100644 (file)
@@ -332,28 +332,43 @@ SilcBool silc_hash_client_id_compare(void *key1, void *key2,
 
 char *silc_fingerprint(const unsigned char *data, SilcUInt32 data_len)
 {
-  char fingerprint[64], *cp;
-  int i;
+  unsigned char *fingerprint, *cp;
+  unsigned int len, blocks, i;
+
+  if (!data || !data_len) {
+    silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
+    return NULL;
+  }
+
+  if (data_len >= 256)
+    data_len = 255;
+
+  /* Align and calculate total length */
+  len = ((data_len + 19) / 20) * 20;
+  blocks = (len / 10);
+  len = (len * 2) + ((blocks - 1) * 2) + (4 * blocks) + 2 + 1;
+
+  cp = fingerprint = silc_calloc(len, sizeof(*fingerprint));
+  if (!cp)
+    return NULL;
 
-  memset(fingerprint, 0, sizeof(fingerprint));
-  cp = fingerprint;
   for (i = 0; i < data_len; i++) {
-    silc_snprintf(cp, sizeof(fingerprint), "%02X", data[i]);
+    silc_snprintf(cp, len, "%02X", data[i]);
     cp += 2;
+    len -= 2;
 
     if ((i + 1) % 2 == 0)
-      silc_snprintf(cp++, sizeof(fingerprint), " ");
-
+      silc_snprintf(cp++, len--, " ");
     if ((i + 1) % 10 == 0)
-      silc_snprintf(cp++, sizeof(fingerprint), " ");
+      silc_snprintf(cp++, len--, " ");
   }
   i--;
-  if ((i + 1) % 2 == 0)
-    cp[-2] = 0;
   if ((i + 1) % 10 == 0)
-    cp[-1] = 0;
+    *(--cp) = '\0';
+  if ((i + 1) % 2 == 0)
+    *(--cp) = '\0';
 
-  return silc_strdup(fingerprint);
+  return fingerprint;
 }
 
 /* Return TRUE if the `data' is ASCII string. */
index 7aa40a4f21f87f2e11f0588b97009cfee272287f..4524a80b0c6642237c0599e10c8fedc17ffb7603 100644 (file)
@@ -213,7 +213,9 @@ SilcBool silc_hash_client_id_compare(void *key1, void *key2,
  * DESCRIPTION
  *
  *    Return a textual representation of the fingerprint in *data, the
- *    caller must free the returned string.
+ *    caller must free the returned string.  Returns NULL on error.  If
+ *    the `data_len' is longer than 255 bytes, only the first 255 bytes are
+ *    used to create the fingerprint.
  *
  ***/
 char *silc_fingerprint(const unsigned char *data, SilcUInt32 data_len);