diff options
| author | Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> | 2012-06-16 22:58:06 +0900 | 
|---|---|---|
| committer | Yang Tse <yangsita@gmail.com> | 2012-06-21 03:34:37 +0200 | 
| commit | 424bb3587748eb59c0d56613e88ef4511ad4dcbf (patch) | |
| tree | 8e8c1d21f4c985a92fabd5ec92b293fadc55e20f | |
| parent | 08e0ad7b3974811127f7d61c016fee540f91d343 (diff) | |
curl: Refactored metalink_checksum
When creating metalink_checksum from metalink_checksum_t, first
check hex digest is valid for the given hash function.  We do
this check in the order of digest_aliases so that first good
match will be chosen (strongest hash function available).  As a
result, the metalinkfile now only contains at most one
metalink_checksum because other entries are just redundant.
| -rw-r--r-- | src/tool_metalink.c | 105 | ||||
| -rw-r--r-- | src/tool_metalink.h | 77 | 
2 files changed, 89 insertions, 93 deletions
| diff --git a/src/tool_metalink.c b/src/tool_metalink.c index 8909397b7..8f6a1f870 100644 --- a/src/tool_metalink.c +++ b/src/tool_metalink.c @@ -325,13 +325,12 @@ static unsigned char hex_to_uint(const char *s)   */  static int check_hash(const char *filename,                        const metalink_digest_def *digest_def, -                      const char *hex_hash, FILE *error) +                      const unsigned char *digest, FILE *error)  {    unsigned char *result;    digest_context *dctx;    int check_ok;    int fd; -  size_t i;    fprintf(error, "Checking %s checksum of file %s\n", digest_def->hash_name,            filename);    fd = open(filename, O_RDONLY); @@ -357,13 +356,8 @@ static int check_hash(const char *filename,      Curl_digest_update(dctx, buf, (unsigned int)len);    }    Curl_digest_final(dctx, result); -  check_ok = 1; -  for(i = 0; i < digest_def->dparams->digest_resultlen; ++i) { -    if(hex_to_uint(&hex_hash[i*2]) != result[i]) { -      check_ok = 0; -      break; -    } -  } +  check_ok = memcmp(result, digest, +                    digest_def->dparams->digest_resultlen) == 0;    free(result);    close(fd);    return check_ok; @@ -373,31 +367,12 @@ int metalink_check_hash(struct Configurable *config,                          metalinkfile *mlfile,                          const char *filename)  { -  metalink_checksum *chksum; -  const metalink_digest_alias *digest_alias;    int rv;    if(mlfile->checksum == NULL) {      return -2;    } -  for(digest_alias = digest_aliases; digest_alias->alias_name; -      ++digest_alias) { -    for(chksum = mlfile->checksum; chksum; chksum = chksum->next) { -      if(Curl_raw_equal(digest_alias->alias_name, chksum->hash_name) && -         strlen(chksum->hash_value) == -         digest_alias->digest_def->dparams->digest_resultlen*2) { -        break; -      } -    } -    if(chksum) { -      break; -    } -  } -  if(!digest_alias->alias_name) { -    fprintf(config->errors, "No supported checksum in Metalink file\n"); -    return -2; -  } -  rv = check_hash(filename, digest_alias->digest_def, -                  chksum->hash_value, config->errors); +  rv = check_hash(filename, mlfile->checksum->digest_def, +                  mlfile->checksum->digest, config->errors);    if(rv == 1) {      fprintf(config->errors, "Checksum matched\n");    } @@ -407,14 +382,20 @@ int metalink_check_hash(struct Configurable *config,    return rv;  } -static metalink_checksum *new_metalink_checksum(const char *hash_name, -                                                const char *hash_value) +static metalink_checksum *new_metalink_checksum_from_hex_digest +(const metalink_digest_def *digest_def, const char *hex_digest)  {    metalink_checksum *chksum; +  unsigned char *digest; +  size_t i; +  size_t len = strlen(hex_digest); +  digest = malloc(len/2); +  for(i = 0; i < len; i += 2) { +    digest[i/2] = hex_to_uint(hex_digest+i); +  }    chksum = malloc(sizeof(metalink_checksum)); -  chksum->next = NULL; -  chksum->hash_name = strdup(hash_name); -  chksum->hash_value = strdup(hash_value); +  chksum->digest_def = digest_def; +  chksum->digest = digest;    return chksum;  } @@ -427,6 +408,23 @@ static metalink_resource *new_metalink_resource(const char *url)    return res;  } +/* Returns nonzero if hex_digest is properly formatted; that is each +   letter is in [0-9A-Za-z] and the length of the string equals to the +   result length of digest * 2. */ +static int check_hex_digest(const char *hex_digest, +                            const metalink_digest_def *digest_def) +{ +  size_t i; +  for(i = 0; hex_digest[i]; ++i) { +    char c = hex_digest[i]; +    if(!(('0' <= c && c <= '9') || ('a' <= c && c <= 'z') || +         ('A' <= c && c <= 'Z'))) { +      return 0; +    } +  } +  return digest_def->dparams->digest_resultlen * 2 == i; +} +  static metalinkfile *new_metalinkfile(metalink_file_t *fileinfo)  {    metalinkfile *f; @@ -436,17 +434,23 @@ static metalinkfile *new_metalinkfile(metalink_file_t *fileinfo)    f->checksum = NULL;    f->resource = NULL;    if(fileinfo->checksums) { -    metalink_checksum_t **p; -    metalink_checksum root, *tail; -    root.next = NULL; -    tail = &root; -    for(p = fileinfo->checksums; *p; ++p) { -      metalink_checksum *chksum; -      chksum = new_metalink_checksum((*p)->type, (*p)->hash); -      tail->next = chksum; -      tail = chksum; +    const metalink_digest_alias *digest_alias; +    for(digest_alias = digest_aliases; digest_alias->alias_name; +        ++digest_alias) { +      metalink_checksum_t **p; +      for(p = fileinfo->checksums; *p; ++p) { +        if(Curl_raw_equal(digest_alias->alias_name, (*p)->type) && +           check_hex_digest((*p)->hash, digest_alias->digest_def)) { +          f->checksum = +            new_metalink_checksum_from_hex_digest(digest_alias->digest_def, +                                                  (*p)->hash); +          break; +        } +      } +      if(f->checksum) { +        break; +      }      } -    f->checksum = root.next;    }    if(fileinfo->resources) {      metalink_resource_t **p; @@ -561,8 +565,7 @@ static void delete_metalink_checksum(metalink_checksum *chksum)    if(chksum == NULL) {      return;    } -  Curl_safefree(chksum->hash_value); -  Curl_safefree(chksum->hash_name); +  Curl_safefree(chksum->digest);    Curl_safefree(chksum);  } @@ -577,18 +580,12 @@ static void delete_metalink_resource(metalink_resource *res)  static void delete_metalinkfile(metalinkfile *mlfile)  { -  metalink_checksum *mc;    metalink_resource *res;    if(mlfile == NULL) {      return;    }    Curl_safefree(mlfile->filename); -  for(mc = mlfile->checksum; mc;) { -    metalink_checksum *next; -    next = mc->next; -    delete_metalink_checksum(mc); -    mc = next; -  } +  delete_metalink_checksum(mlfile->checksum);    for(res = mlfile->resource; res;) {      metalink_resource *next;      next = res->next; diff --git a/src/tool_metalink.h b/src/tool_metalink.h index 3ce1fe2f9..36b4b02c7 100644 --- a/src/tool_metalink.h +++ b/src/tool_metalink.h @@ -23,41 +23,6 @@   ***************************************************************************/  #include "tool_setup.h" -typedef struct metalink_checksum { -  struct metalink_checksum *next; -  char *hash_name; -  /* Hex-encoded hash value */ -  char *hash_value; -} metalink_checksum; - -typedef struct metalink_resource { -  struct metalink_resource *next; -  char *url; -} metalink_resource; - -typedef struct metalinkfile { -  struct metalinkfile *next; -  char *filename; -  metalink_checksum *checksum; -  metalink_resource *resource; -} metalinkfile; - -#ifdef USE_METALINK - -/* - * Counts the resource in the metalinkfile. - */ -int count_next_metalink_resource(metalinkfile *mlfile); -void clean_metalink(struct Configurable *config); - -int parse_metalink(struct Configurable *config, const char *infile); - -/* - * Returns nonzero if content_type includes "application/metalink+xml" - * media-type. The check is done in case-insensitive manner. - */ -int check_metalink_content_type(const char *content_type); -  typedef void (* Curl_digest_init_func)(void *context);  typedef void (* Curl_digest_update_func)(void *context,                                           const unsigned char *data, @@ -77,10 +42,6 @@ typedef struct {    void                  *digest_hashctx;   /* Hash function context */  } digest_context; -extern const digest_params MD5_DIGEST_PARAMS[1]; -extern const digest_params SHA1_DIGEST_PARAMS[1]; -extern const digest_params SHA256_DIGEST_PARAMS[1]; -  digest_context * Curl_digest_init(const digest_params *dparams);  int Curl_digest_update(digest_context *context,                         const unsigned char *data, @@ -97,6 +58,44 @@ typedef struct {    const metalink_digest_def *digest_def;  } metalink_digest_alias; +typedef struct metalink_checksum { +  const metalink_digest_def *digest_def; +  /* raw digest value, not ascii hex digest */ +  unsigned char *digest; +} metalink_checksum; + +typedef struct metalink_resource { +  struct metalink_resource *next; +  char *url; +} metalink_resource; + +typedef struct metalinkfile { +  struct metalinkfile *next; +  char *filename; +  metalink_checksum *checksum; +  metalink_resource *resource; +} metalinkfile; + +#ifdef USE_METALINK + +extern const digest_params MD5_DIGEST_PARAMS[1]; +extern const digest_params SHA1_DIGEST_PARAMS[1]; +extern const digest_params SHA256_DIGEST_PARAMS[1]; + +/* + * Counts the resource in the metalinkfile. + */ +int count_next_metalink_resource(metalinkfile *mlfile); +void clean_metalink(struct Configurable *config); + +int parse_metalink(struct Configurable *config, const char *infile); + +/* + * Returns nonzero if content_type includes "application/metalink+xml" + * media-type. The check is done in case-insensitive manner. + */ +int check_metalink_content_type(const char *content_type); +  /*   * Check checksum of file denoted by filename.   * | 
