Commit eeeba149 authored by Yang Tse's avatar Yang Tse
Browse files

metalink: build fixes and adjustments II

Additionally, make hash checking ability mandatory in order to allow metalink
support in curl.

A command line option could be introduced to skip hash checking at runtime,
but the ability to check hashes should always be built-in when providing
metalink support.
parent 186b101d
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -39,11 +39,11 @@
#include "tool_help.h"
#include "tool_helpers.h"
#include "tool_libinfo.h"
#include "tool_metalink.h"
#include "tool_msgs.h"
#include "tool_paramhlp.h"
#include "tool_parsecfg.h"
#include "tool_version.h"
#include "tool_metalink.h"

#include "memdebug.h" /* keep this as LAST include */

+109 −132
Original line number Diff line number Diff line
@@ -21,26 +21,43 @@
 ***************************************************************************/
#include "tool_setup.h"

#ifdef HAVE_UNISTD_H
#  include <unistd.h>
#endif

#include <sys/stat.h>

#ifdef HAVE_FCNTL_H
#  include <fcntl.h>
#endif

#ifdef USE_METALINK

#include <metalink/metalink_parser.h>

#ifdef USE_SSLEAY
#  ifdef USE_OPENSSL
#    include <openssl/md5.h>
#    include <openssl/sha.h>
#  else
#    include <md5.h>
#    include <sha.h>
#  endif
#elif defined(USE_GNUTLS_NETTLE)
#  include <nettle/md5.h>
#  include <nettle/sha.h>
#  define MD5_CTX    struct md5_ctx
#  define SHA_CTX    struct sha1_ctx
#  define SHA256_CTX struct sha256_ctx
#elif defined(USE_GNUTLS)
#  include <gcrypt.h>
#  define MD5_CTX    gcry_md_hd_t
#  define SHA_CTX    gcry_md_hd_t
#  define SHA256_CTX gcry_md_hd_t
#else
#  error "Can't compile METALINK support without a crypto library."
#endif

#include "rawstr.h"

#include "tool_metalink.h"
#define ENABLE_CURLX_PRINTF
/* use our own printf() functions */
#include "curlx.h"

#include "tool_getparam.h"
#include "tool_paramhlp.h"
#include "tool_cfgable.h"
#include "tool_metalink.h"

#include "memdebug.h" /* keep this as LAST include */

@@ -56,12 +73,65 @@
    return PARAM_NO_MEM; \
} WHILE_FALSE

#ifdef USE_GNUTLS_NETTLE
const digest_params MD5_DIGEST_PARAMS[] = {
  {
    (Curl_digest_init_func) MD5_Init,
    (Curl_digest_update_func) MD5_Update,
    (Curl_digest_final_func) MD5_Final,
    sizeof(MD5_CTX),
    16
  }
};

#include <nettle/md5.h>
#include <nettle/sha.h>
const digest_params SHA1_DIGEST_PARAMS[] = {
  {
    (Curl_digest_init_func) SHA1_Init,
    (Curl_digest_update_func) SHA1_Update,
    (Curl_digest_final_func) SHA1_Final,
    sizeof(SHA_CTX),
    20
  }
};

typedef struct md5_ctx MD5_CTX;
const digest_params SHA256_DIGEST_PARAMS[] = {
  {
    (Curl_digest_init_func) SHA256_Init,
    (Curl_digest_update_func) SHA256_Update,
    (Curl_digest_final_func) SHA256_Final,
    sizeof(SHA256_CTX),
    32
  }
};

static const metalink_digest_def SHA256_DIGEST_DEF[] = {
  {"sha-256", SHA256_DIGEST_PARAMS}
};

static const metalink_digest_def SHA1_DIGEST_DEF[] = {
  {"sha-1", SHA1_DIGEST_PARAMS}
};

static const metalink_digest_def MD5_DIGEST_DEF[] = {
  {"md5", MD5_DIGEST_PARAMS}
};

/*
 * The alias of supported hash functions in the order by preference
 * (basically stronger hash comes first). We included "sha-256" and
 * "sha256". The former is the name defined in the IANA registry named
 * "Hash Function Textual Names". The latter is widely (and
 * historically) used in Metalink version 3.
 */
static const metalink_digest_alias digest_aliases[] = {
  {"sha-256", SHA256_DIGEST_DEF},
  {"sha256", SHA256_DIGEST_DEF},
  {"sha-1", SHA1_DIGEST_DEF},
  {"sha1", SHA1_DIGEST_DEF},
  {"md5", MD5_DIGEST_DEF},
  {NULL, NULL}
};

#ifdef USE_GNUTLS_NETTLE

static void MD5_Init(MD5_CTX *ctx)
{
@@ -80,8 +150,6 @@ static void MD5_Final(unsigned char digest[16], MD5_CTX * ctx)
  md5_digest(ctx, 16, digest);
}

typedef struct sha1_ctx SHA_CTX;

static void SHA1_Init(SHA_CTX *ctx)
{
  sha1_init(ctx);
@@ -99,8 +167,6 @@ static void SHA1_Final(unsigned char digest[20], SHA_CTX * ctx)
  sha1_digest(ctx, 20, digest);
}

typedef struct sha256_ctx SHA256_CTX;

static void SHA256_Init(SHA256_CTX *ctx)
{
  sha256_init(ctx);
@@ -118,13 +184,7 @@ static void SHA256_Final(unsigned char digest[32], SHA256_CTX * ctx)
  sha256_digest(ctx, 32, digest);
}

#else

#ifdef USE_GNUTLS

#include <gcrypt.h>

typedef gcry_md_hd_t MD5_CTX;
#elif defined(USE_GNUTLS)

static void MD5_Init(MD5_CTX *ctx)
{
@@ -144,8 +204,6 @@ static void MD5_Final(unsigned char digest[16], MD5_CTX * ctx)
  gcry_md_close(*ctx);
}

typedef gcry_md_hd_t SHA_CTX;

static void SHA1_Init(SHA_CTX *ctx)
{
  gcry_md_open(ctx, GCRY_MD_SHA1, 0);
@@ -164,8 +222,6 @@ static void SHA1_Final(unsigned char digest[20], SHA_CTX * ctx)
  gcry_md_close(*ctx);
}

typedef gcry_md_hd_t SHA256_CTX;

static void SHA256_Init(SHA256_CTX *ctx)
{
  gcry_md_open(ctx, GCRY_MD_SHA256, 0);
@@ -184,52 +240,7 @@ static void SHA256_Final(unsigned char digest[32], SHA256_CTX * ctx)
  gcry_md_close(*ctx);
}

#else

#ifdef USE_OPENSSL
#  include <openssl/md5.h>
#  include <openssl/sha.h>
#else /* USE_OPENSSL */

/* TODO hash functions for other libraries here */

#endif /* USE_OPENSSL */

#endif /* USE_GNUTLS */

#endif /* USE_GNUTLS_NETTLE */

#ifdef METALINK_HASH_CHECK

const digest_params MD5_DIGEST_PARAMS[] = {
  {
    (Curl_digest_init_func) MD5_Init,
    (Curl_digest_update_func) MD5_Update,
    (Curl_digest_final_func) MD5_Final,
    sizeof(MD5_CTX),
    16
  }
};

const digest_params SHA1_DIGEST_PARAMS[] = {
  {
    (Curl_digest_init_func) SHA1_Init,
    (Curl_digest_update_func) SHA1_Update,
    (Curl_digest_final_func) SHA1_Final,
    sizeof(SHA_CTX),
    20
  }
};

const digest_params SHA256_DIGEST_PARAMS[] = {
  {
    (Curl_digest_init_func) SHA256_Init,
    (Curl_digest_update_func) SHA256_Update,
    (Curl_digest_final_func) SHA256_Final,
    sizeof(SHA256_CTX),
    32
  }
};
#endif /* CRYPTO LIBS */

digest_context *Curl_digest_init(const digest_params *dparams)
{
@@ -274,34 +285,6 @@ int Curl_digest_final(digest_context *context, unsigned char *result)
  return 0;
}

static const metalink_digest_def SHA256_DIGEST_DEF[] = {
  {"sha-256", SHA256_DIGEST_PARAMS}
};

static const metalink_digest_def SHA1_DIGEST_DEF[] = {
  {"sha-1", SHA1_DIGEST_PARAMS}
};

static const metalink_digest_def MD5_DIGEST_DEF[] = {
  {"md5", MD5_DIGEST_PARAMS}
};

/*
 * The alias of supported hash functions in the order by preference
 * (basically stronger hash comes first). We included "sha-256" and
 * "sha256". The former is the name defined in the IANA registry named
 * "Hash Function Textual Names". The latter is widely (and
 * historically) used in Metalink version 3.
 */
static const metalink_digest_alias digest_aliases[] = {
  {"sha-256", SHA256_DIGEST_DEF},
  {"sha256", SHA256_DIGEST_DEF},
  {"sha-1", SHA1_DIGEST_DEF},
  {"sha1", SHA1_DIGEST_DEF},
  {"md5", MD5_DIGEST_DEF},
  {NULL, NULL}
};

static unsigned char hex_to_uint(const char *s)
{
  int v[2];
@@ -414,10 +397,6 @@ int metalink_check_hash(struct Configurable *config,
  return rv;
}

#endif /* METALINK_HASH_CHECK */

#ifdef USE_METALINK

static metalink_checksum *new_metalink_checksum(const char *hash_name,
                                                const char *hash_value)
{
@@ -538,8 +517,6 @@ int parse_metalink(struct Configurable *config, const char *infile)
  return 0;
}

#endif /* USE_METALINK */

/*
 * Returns nonzero if content_type includes mediatype.
 */
+9 −13
Original line number Diff line number Diff line
@@ -23,13 +23,6 @@
 ***************************************************************************/
#include "tool_setup.h"

struct Configurable;

#if defined(USE_OPENSSL) || defined(USE_GNUTLS)
/* Define 1 if hash check is enabled in Metalink transfer */
#  define METALINK_HASH_CHECK 1
#endif

typedef struct metalink_checksum {
  struct metalink_checksum *next;
  char *hash_name;
@@ -49,17 +42,13 @@ typedef struct metalinkfile {
  metalink_resource *resource;
} metalinkfile;

#ifdef USE_METALINK

/*
 * Counts the resource in the metalinkfile.
 */
#ifdef USE_METALINK
int count_next_metalink_resource(metalinkfile *mlfile);
void clean_metalink(struct Configurable *config);
#else
#define count_next_metalink_resource(x) 0
#define clean_metalink(x)
#endif


int parse_metalink(struct Configurable *config, const char *infile);

@@ -126,4 +115,11 @@ int metalink_check_hash(struct Configurable *config,
                        metalinkfile *mlfile,
                        const char *filename);

#else /* USE_METALINK */

#define count_next_metalink_resource(x)  0
#define clean_metalink(x)  Curl_nop_stmt

#endif /* USE_METALINK */

#endif /* HEADER_CURL_TOOL_METALINK_H */
+1 −2
Original line number Diff line number Diff line
@@ -65,6 +65,7 @@
#include "tool_homedir.h"
#include "tool_libinfo.h"
#include "tool_main.h"
#include "tool_metalink.h"
#include "tool_msgs.h"
#include "tool_operate.h"
#include "tool_operhlp.h"
@@ -1577,14 +1578,12 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[])
              fprintf(config->errors, "Could not parse Metalink file.\n");
          }
        }
#  ifdef METALINK_HASH_CHECK
        else if(metalink && res == CURLE_OK && !metalink_next_res) {
          int rv = metalink_check_hash(config, mlfile, outs.filename);
          if(rv == 0) {
            metalink_next_res = 1;
          }
        }
#  endif /* METALINK_HASH_CHECK */
#endif /* USE_METALINK */

        /* No more business with this output struct */