Fix problems with validating pre-supplied header checksum and length
authorJonathan Dieter <jdieter@gmail.com>
Thu, 31 May 2018 07:05:36 +0000 (10:05 +0300)
committerJonathan Dieter <jdieter@gmail.com>
Thu, 31 May 2018 07:05:36 +0000 (10:05 +0300)
Signed-off-by: Jonathan Dieter <jdieter@gmail.com>
include/zck.h
src/lib/header.c
src/lib/zck.c

index 24811e3acacdfba5e26a5ab0f18a610460485b67..14b0d913421d6b0d12293c1774114eb0dfb112af 100644 (file)
@@ -111,7 +111,7 @@ void zck_free(zckCtx **zck);
  * Options
  *******************************************************************/
 /* Set string option */
-int zck_set_soption(zckCtx *zck, zck_soption option, const void *value,
+int zck_set_soption(zckCtx *zck, zck_soption option, const char *value,
                     size_t length)
     __attribute__ ((warn_unused_result));
 /* Set integer option */
index b727b976e20da727e390008a82727d43c7f310ac..372ae4dda87cff3e73f0a0548c7a6a4db8d5a01c 100644 (file)
@@ -113,12 +113,6 @@ int read_lead_1(zckCtx *zck) {
     size_t header_length = 0;
     if(!compint_to_size(&header_length, header+length, &length, lead))
         return False;
-    if(zck->prep_hdr_size > -1 && (size_t)zck->prep_hdr_size != header_length) {
-        zck_log(ZCK_LOG_ERROR,
-                "Header length (%lu) doesn't match requested header length "
-                "(%lu)\n", header_length, zck->prep_hdr_size);
-        return False;
-    }
     zck->header_length = header_length;
 
     zck->header = header;
@@ -145,6 +139,8 @@ int read_lead_2(zckCtx *zck) {
     /* Read header digest */
     zck_log(ZCK_LOG_DEBUG, "Reading header digest\n");
     header = realloc(header, length + zck->hash_type.digest_size);
+    zck->lead_string = header;
+    zck->header = header;
     if(header == NULL) {
         zck_log(ZCK_LOG_ERROR, "Unable to re-allocate %lu bytes\n",
                 length + zck->hash_type.digest_size);
@@ -160,7 +156,10 @@ int read_lead_2(zckCtx *zck) {
     if(zck->prep_digest &&
        memcmp(zck->prep_digest, header + length, zck->hash_type.digest_size) != 0) {
         zck_log(ZCK_LOG_ERROR,
-                "Header digest doesn't match requested header digest\n");
+                "Header digest doesn't match requested header digest\n"
+                "Expected: %s\nActual: %s\n",
+                get_digest_string(zck->prep_digest, zck->hash_type.digest_size),
+                get_digest_string(header + length, zck->hash_type.digest_size));
         return False;
     }
     zck->header_digest = zmalloc(zck->hash_type.digest_size);
@@ -172,6 +171,15 @@ int read_lead_2(zckCtx *zck) {
     memcpy(zck->header_digest, header + length, zck->hash_type.digest_size);
     length += zck->hash_type.digest_size;
 
+    /* Check whether full header length matches specified header length */
+    if(zck->prep_hdr_size > -1 &&
+       (size_t)zck->prep_hdr_size != zck->header_length + length) {
+        zck_log(ZCK_LOG_ERROR,
+                "Header length (%lu) doesn't match requested header length "
+                "(%lu)\n", zck->header_length + length,
+                zck->prep_hdr_size);
+        return False;
+    }
     /* Store pre-header */
     zck->header = header;
     zck->header_size = lead;
index 4279f3bad60ee4f6bccf3f38ec4f859aa91493ce..8e7eaea143da6d4f608d15149440d8e046068b88 100644 (file)
@@ -110,37 +110,78 @@ int PUBLIC zck_set_ioption(zckCtx *zck, zck_ioption option, ssize_t value) {
     return True;
 }
 
-int PUBLIC zck_set_soption(zckCtx *zck, zck_soption option, const void *value,
+int hex_to_int (char c) {
+    if (c >= 97)
+        c = c - 32;
+    int result = (c / 16 - 3) * 10 + (c % 16);
+    if (result > 9)
+        result--;
+    return result;
+}
+
+char *ascii_checksum_to_bin (char *checksum) {
+    int cl = strlen(checksum);
+    char *raw_checksum = zmalloc(cl/2);
+    if(raw_checksum == NULL) {
+        zck_log(ZCK_LOG_ERROR, "Unable to allocate %lu bytes\n", cl/2);
+        return NULL;
+    }
+    char *rp = raw_checksum;
+    int buf = 0;
+    for (int i=0; i<cl; i++) {
+        if (i % 2 == 0)
+            buf = hex_to_int(checksum[i]);
+        else {
+            rp[0] = buf*16 + hex_to_int(checksum[i]);
+            rp++;
+        }
+    }
+    return raw_checksum;
+}
+
+int PUBLIC zck_set_soption(zckCtx *zck, zck_soption option, const char *value,
                            size_t length) {
+    char *data = zmalloc(length);
+    if(data == NULL) {
+        zck_log(ZCK_LOG_ERROR, "Unable to allocate %lu bytes\n", length);
+        return False;
+    }
+    memcpy(data, value, length);
+
     /* Validation options */
     if(option == ZCK_VAL_HEADER_DIGEST) {
         VALIDATE_READ(zck);
         zckHashType chk_type = {0};
         if(zck->prep_hash_type < 0) {
+            free(data);
             zck_log(ZCK_LOG_ERROR,
                     "For validation, you must set the header hash type "
                     "*before* the header digest itself\n");
             return False;
         }
-        if(!zck_hash_setup(&chk_type, zck->prep_hash_type))
+        if(!zck_hash_setup(&chk_type, zck->prep_hash_type)) {
+            free(data);
             return False;
-        if(chk_type.digest_size != length) {
+        }
+        if(chk_type.digest_size != length/2) {
+            free(data);
             zck_log(ZCK_LOG_ERROR, "Hash digest size mismatch for header "
                     "validation\n"
                     "Expected: %lu\nProvided: %lu\n", chk_type.digest_size,
-                    length);
+                    length/2);
             return False;
         }
-        zck->prep_digest = zmalloc(length);
-        memcpy(zck->prep_digest, value, length);
+        zck->prep_digest = ascii_checksum_to_bin(data);
+        free(data);
 
     /* Compression options */
     } else if(option < 2000) {
         VALIDATE_WRITE(zck);
-        return comp_soption(zck, option, value, length);
+        return comp_soption(zck, option, data, length);
 
     /* Unknown options */
     } else {
+        free(data);
         zck_log(ZCK_LOG_ERROR, "Unknown string option %i\n", option);
         return False;
     }
@@ -406,9 +447,9 @@ int zck_import_dict(zckCtx *zck) {
     zck_log(ZCK_LOG_DEBUG, "Setting dict\n");
     if(!comp_soption(zck, ZCK_COMP_DICT, data, size))
         return False;
-    free(data);
     if(!zck_comp_init(zck))
         return False;
+    free(data);
 
     return True;
 }