1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at http://curl.haxx.se/docs/copyright.html.
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ***************************************************************************/
22 #include "tool_setup.h"
34 # include <openssl/md5.h>
35 # include <openssl/sha.h>
40 #elif defined(USE_GNUTLS_NETTLE)
41 # include <nettle/md5.h>
42 # include <nettle/sha.h>
43 # define MD5_CTX struct md5_ctx
44 # define SHA_CTX struct sha1_ctx
45 # define SHA256_CTX struct sha256_ctx
46 #elif defined(USE_GNUTLS)
48 # define MD5_CTX gcry_md_hd_t
49 # define SHA_CTX gcry_md_hd_t
50 # define SHA256_CTX gcry_md_hd_t
51 #elif defined(USE_NSS)
54 # define MD5_CTX void *
55 # define SHA_CTX void *
56 # define SHA256_CTX void *
57 # ifdef HAVE_NSS_INITCONTEXT
58 static NSSInitContext *nss_context;
60 #elif defined(__MAC_10_4) || defined(__IPHONE_5_0)
61 /* For Apple operating systems: CommonCrypto has the functions we need.
62 The library's headers are even backward-compatible with OpenSSL's
63 headers as long as we define COMMON_DIGEST_FOR_OPENSSL first.
65 These functions are available on Tiger and later, as well as iOS 5.0
66 and later. If you're building for an older cat, well, sorry. */
67 # define COMMON_DIGEST_FOR_OPENSSL
68 # include <CommonCrypto/CommonDigest.h>
70 /* For Windows: If no other crypto library is provided, we fallback
71 to the hash functions provided within the Microsoft Windows CryptoAPI */
72 # include <wincrypt.h>
73 /* Custom structure in order to store the required provider and hash handle */
74 struct win32_crypto_hash {
75 HCRYPTPROV hCryptProv;
78 /* Custom Microsoft AES Cryptographic Provider defines required for MinGW */
79 # ifndef ALG_SID_SHA_256
80 # define ALG_SID_SHA_256 12
83 # define CALG_SHA_256 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_256)
85 # define MD5_CTX struct win32_crypto_hash
86 # define SHA_CTX struct win32_crypto_hash
87 # define SHA256_CTX struct win32_crypto_hash
89 # error "Can't compile METALINK support without a crypto library."
94 #define ENABLE_CURLX_PRINTF
95 /* use our own printf() functions */
98 #include "tool_getparam.h"
99 #include "tool_paramhlp.h"
100 #include "tool_cfgable.h"
101 #include "tool_metalink.h"
102 #include "tool_msgs.h"
104 #include "memdebug.h" /* keep this as LAST include */
106 /* Copied from tool_getparam.c */
107 #define GetStr(str,val) do { \
113 *(str) = strdup((val)); \
115 return PARAM_NO_MEM; \
118 #ifdef USE_GNUTLS_NETTLE
120 static int MD5_Init(MD5_CTX *ctx)
126 static void MD5_Update(MD5_CTX *ctx,
127 const unsigned char *input,
128 unsigned int inputLen)
130 md5_update(ctx, inputLen, input);
133 static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx)
135 md5_digest(ctx, 16, digest);
138 static int SHA1_Init(SHA_CTX *ctx)
144 static void SHA1_Update(SHA_CTX *ctx,
145 const unsigned char *input,
146 unsigned int inputLen)
148 sha1_update(ctx, inputLen, input);
151 static void SHA1_Final(unsigned char digest[20], SHA_CTX *ctx)
153 sha1_digest(ctx, 20, digest);
156 static int SHA256_Init(SHA256_CTX *ctx)
162 static void SHA256_Update(SHA256_CTX *ctx,
163 const unsigned char *input,
164 unsigned int inputLen)
166 sha256_update(ctx, inputLen, input);
169 static void SHA256_Final(unsigned char digest[32], SHA256_CTX *ctx)
171 sha256_digest(ctx, 32, digest);
174 #elif defined(USE_GNUTLS)
176 static int MD5_Init(MD5_CTX *ctx)
178 gcry_md_open(ctx, GCRY_MD_MD5, 0);
182 static void MD5_Update(MD5_CTX *ctx,
183 const unsigned char *input,
184 unsigned int inputLen)
186 gcry_md_write(*ctx, input, inputLen);
189 static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx)
191 memcpy(digest, gcry_md_read(*ctx, 0), 16);
195 static int SHA1_Init(SHA_CTX *ctx)
197 gcry_md_open(ctx, GCRY_MD_SHA1, 0);
201 static void SHA1_Update(SHA_CTX *ctx,
202 const unsigned char *input,
203 unsigned int inputLen)
205 gcry_md_write(*ctx, input, inputLen);
208 static void SHA1_Final(unsigned char digest[20], SHA_CTX *ctx)
210 memcpy(digest, gcry_md_read(*ctx, 0), 20);
214 static int SHA256_Init(SHA256_CTX *ctx)
216 gcry_md_open(ctx, GCRY_MD_SHA256, 0);
220 static void SHA256_Update(SHA256_CTX *ctx,
221 const unsigned char *input,
222 unsigned int inputLen)
224 gcry_md_write(*ctx, input, inputLen);
227 static void SHA256_Final(unsigned char digest[32], SHA256_CTX *ctx)
229 memcpy(digest, gcry_md_read(*ctx, 0), 32);
233 #elif defined(USE_NSS)
235 static int nss_hash_init(void **pctx, SECOidTag hash_alg)
239 /* we have to initialize NSS if not initialized alraedy */
240 #ifdef HAVE_NSS_INITCONTEXT
241 if(!NSS_IsInitialized() && !nss_context) {
242 static NSSInitParameters params;
243 params.length = sizeof params;
244 nss_context = NSS_InitContext("", "", "", "", ¶ms, NSS_INIT_READONLY
245 | NSS_INIT_NOCERTDB | NSS_INIT_NOMODDB | NSS_INIT_FORCEOPEN
246 | NSS_INIT_NOROOTINIT | NSS_INIT_OPTIMIZESPACE | NSS_INIT_PK11RELOAD);
250 ctx = PK11_CreateDigestContext(hash_alg);
252 return /* failure */ 0;
254 if(PK11_DigestBegin(ctx) != SECSuccess) {
255 PK11_DestroyContext(ctx, PR_TRUE);
256 return /* failure */ 0;
260 return /* success */ 1;
263 static void nss_hash_final(void **pctx, unsigned char *out, unsigned int len)
265 PK11Context *ctx = *pctx;
267 PK11_DigestFinal(ctx, out, &outlen, len);
268 PK11_DestroyContext(ctx, PR_TRUE);
271 static int MD5_Init(MD5_CTX *pctx)
273 return nss_hash_init(pctx, SEC_OID_MD5);
276 static void MD5_Update(MD5_CTX *pctx,
277 const unsigned char *input,
278 unsigned int input_len)
280 PK11_DigestOp(*pctx, input, input_len);
283 static void MD5_Final(unsigned char digest[16], MD5_CTX *pctx)
285 nss_hash_final(pctx, digest, 16);
288 static int SHA1_Init(SHA_CTX *pctx)
290 return nss_hash_init(pctx, SEC_OID_SHA1);
293 static void SHA1_Update(SHA_CTX *pctx,
294 const unsigned char *input,
295 unsigned int input_len)
297 PK11_DigestOp(*pctx, input, input_len);
300 static void SHA1_Final(unsigned char digest[20], SHA_CTX *pctx)
302 nss_hash_final(pctx, digest, 20);
305 static int SHA256_Init(SHA256_CTX *pctx)
307 return nss_hash_init(pctx, SEC_OID_SHA256);
310 static void SHA256_Update(SHA256_CTX *pctx,
311 const unsigned char *input,
312 unsigned int input_len)
314 PK11_DigestOp(*pctx, input, input_len);
317 static void SHA256_Final(unsigned char digest[32], SHA256_CTX *pctx)
319 nss_hash_final(pctx, digest, 32);
322 #elif defined(_WIN32) && !defined(USE_SSLEAY)
324 static void win32_crypto_final(struct win32_crypto_hash *ctx,
325 unsigned char *digest,
326 unsigned int digestLen)
328 unsigned long length;
329 CryptGetHashParam(ctx->hHash, HP_HASHVAL, NULL, &length, 0);
330 if(length == digestLen)
331 CryptGetHashParam(ctx->hHash, HP_HASHVAL, digest, &length, 0);
333 CryptDestroyHash(ctx->hHash);
335 CryptReleaseContext(ctx->hCryptProv, 0);
338 static int MD5_Init(MD5_CTX *ctx)
340 if(CryptAcquireContext(&ctx->hCryptProv, NULL, NULL,
341 PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
342 CryptCreateHash(ctx->hCryptProv, CALG_MD5, 0, 0, &ctx->hHash);
347 static void MD5_Update(MD5_CTX *ctx,
348 const unsigned char *input,
349 unsigned int inputLen)
351 CryptHashData(ctx->hHash, (unsigned char *)input, inputLen, 0);
354 static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx)
356 win32_crypto_final(ctx, digest, 16);
359 static int SHA1_Init(SHA_CTX *ctx)
361 if(CryptAcquireContext(&ctx->hCryptProv, NULL, NULL,
362 PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
363 CryptCreateHash(ctx->hCryptProv, CALG_SHA1, 0, 0, &ctx->hHash);
368 static void SHA1_Update(SHA_CTX *ctx,
369 const unsigned char *input,
370 unsigned int inputLen)
372 CryptHashData(ctx->hHash, (unsigned char *)input, inputLen, 0);
375 static void SHA1_Final(unsigned char digest[20], SHA_CTX *ctx)
377 win32_crypto_final(ctx, digest, 20);
380 static int SHA256_Init(SHA256_CTX *ctx)
382 if(CryptAcquireContext(&ctx->hCryptProv, NULL, NULL,
383 PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
384 CryptCreateHash(ctx->hCryptProv, CALG_SHA_256, 0, 0, &ctx->hHash);
389 static void SHA256_Update(SHA256_CTX *ctx,
390 const unsigned char *input,
391 unsigned int inputLen)
393 CryptHashData(ctx->hHash, (unsigned char *)input, inputLen, 0);
396 static void SHA256_Final(unsigned char digest[32], SHA256_CTX *ctx)
398 win32_crypto_final(ctx, digest, 32);
401 #endif /* CRYPTO LIBS */
403 const digest_params MD5_DIGEST_PARAMS[] = {
405 (Curl_digest_init_func) MD5_Init,
406 (Curl_digest_update_func) MD5_Update,
407 (Curl_digest_final_func) MD5_Final,
413 const digest_params SHA1_DIGEST_PARAMS[] = {
415 (Curl_digest_init_func) SHA1_Init,
416 (Curl_digest_update_func) SHA1_Update,
417 (Curl_digest_final_func) SHA1_Final,
423 const digest_params SHA256_DIGEST_PARAMS[] = {
425 (Curl_digest_init_func) SHA256_Init,
426 (Curl_digest_update_func) SHA256_Update,
427 (Curl_digest_final_func) SHA256_Final,
433 static const metalink_digest_def SHA256_DIGEST_DEF[] = {
434 {"sha-256", SHA256_DIGEST_PARAMS}
437 static const metalink_digest_def SHA1_DIGEST_DEF[] = {
438 {"sha-1", SHA1_DIGEST_PARAMS}
441 static const metalink_digest_def MD5_DIGEST_DEF[] = {
442 {"md5", MD5_DIGEST_PARAMS}
446 * The alias of supported hash functions in the order by preference
447 * (basically stronger hash comes first). We included "sha-256" and
448 * "sha256". The former is the name defined in the IANA registry named
449 * "Hash Function Textual Names". The latter is widely (and
450 * historically) used in Metalink version 3.
452 static const metalink_digest_alias digest_aliases[] = {
453 {"sha-256", SHA256_DIGEST_DEF},
454 {"sha256", SHA256_DIGEST_DEF},
455 {"sha-1", SHA1_DIGEST_DEF},
456 {"sha1", SHA1_DIGEST_DEF},
457 {"md5", MD5_DIGEST_DEF},
461 digest_context *Curl_digest_init(const digest_params *dparams)
463 digest_context *ctxt;
465 /* Create digest context */
466 ctxt = malloc(sizeof *ctxt);
471 ctxt->digest_hashctx = malloc(dparams->digest_ctxtsize);
473 if(!ctxt->digest_hashctx) {
478 ctxt->digest_hash = dparams;
480 if(dparams->digest_init(ctxt->digest_hashctx) != 1) {
488 int Curl_digest_update(digest_context *context,
489 const unsigned char *data,
492 (*context->digest_hash->digest_update)(context->digest_hashctx, data, len);
497 int Curl_digest_final(digest_context *context, unsigned char *result)
499 (*context->digest_hash->digest_final)(result, context->digest_hashctx);
501 free(context->digest_hashctx);
507 static unsigned char hex_to_uint(const char *s)
511 for(i = 0; i < 2; ++i) {
512 v[i] = Curl_raw_toupper(s[i]);
513 if('0' <= v[i] && v[i] <= '9') {
516 else if('A' <= v[i] && v[i] <= 'Z') {
520 return (unsigned char)((v[0] << 4) | v[1]);
524 * Check checksum of file denoted by filename. The expected hash value
525 * is given in hex_hash which is hex-encoded string.
527 * This function returns 1 if it succeeds or one of the following
531 * Checksum didn't match.
533 * Could not open file; or could not read data from file.
535 * Hash algorithm not available.
537 static int check_hash(const char *filename,
538 const metalink_digest_def *digest_def,
539 const unsigned char *digest, FILE *error)
541 unsigned char *result;
542 digest_context *dctx;
543 int check_ok, flags, fd;
547 /* O_BINARY is required in order to avoid binary EOF in text mode */
551 fd = open(filename, flags);
553 fprintf(error, "Metalink: validating (%s) [%s] FAILED (%s)\n", filename,
554 digest_def->hash_name, strerror(errno));
558 dctx = Curl_digest_init(digest_def->dparams);
560 fprintf(error, "Metalink: validating (%s) [%s] FAILED (%s)\n", filename,
561 digest_def->hash_name, "failed to initialize hash algorithm");
566 result = malloc(digest_def->dparams->digest_resultlen);
568 unsigned char buf[4096];
569 ssize_t len = read(fd, buf, sizeof(buf));
574 fprintf(error, "Metalink: validating (%s) [%s] FAILED (%s)\n", filename,
575 digest_def->hash_name, strerror(errno));
576 Curl_digest_final(dctx, result);
580 Curl_digest_update(dctx, buf, (unsigned int)len);
582 Curl_digest_final(dctx, result);
583 check_ok = memcmp(result, digest,
584 digest_def->dparams->digest_resultlen) == 0;
585 /* sha*sum style verdict output */
587 fprintf(error, "Metalink: validating (%s) [%s] OK\n", filename,
588 digest_def->hash_name);
590 fprintf(error, "Metalink: validating (%s) [%s] FAILED (digest mismatch)\n",
591 filename, digest_def->hash_name);
598 int metalink_check_hash(struct Configurable *config,
599 metalinkfile *mlfile,
600 const char *filename)
603 fprintf(config->errors, "Metalink: validating (%s)...\n", filename);
604 if(mlfile->checksum == NULL) {
605 fprintf(config->errors,
606 "Metalink: validating (%s) FAILED (digest missing)\n",
610 rv = check_hash(filename, mlfile->checksum->digest_def,
611 mlfile->checksum->digest, config->errors);
615 static metalink_checksum *new_metalink_checksum_from_hex_digest
616 (const metalink_digest_def *digest_def, const char *hex_digest)
618 metalink_checksum *chksum;
619 unsigned char *digest;
621 size_t len = strlen(hex_digest);
622 digest = malloc(len/2);
623 for(i = 0; i < len; i += 2) {
624 digest[i/2] = hex_to_uint(hex_digest+i);
626 chksum = malloc(sizeof(metalink_checksum));
627 chksum->digest_def = digest_def;
628 chksum->digest = digest;
632 static metalink_resource *new_metalink_resource(const char *url)
634 metalink_resource *res;
635 res = malloc(sizeof(metalink_resource));
637 res->url = strdup(url);
641 /* Returns nonzero if hex_digest is properly formatted; that is each
642 letter is in [0-9A-Za-z] and the length of the string equals to the
643 result length of digest * 2. */
644 static int check_hex_digest(const char *hex_digest,
645 const metalink_digest_def *digest_def)
648 for(i = 0; hex_digest[i]; ++i) {
649 char c = hex_digest[i];
650 if(!(('0' <= c && c <= '9') || ('a' <= c && c <= 'z') ||
651 ('A' <= c && c <= 'Z'))) {
655 return digest_def->dparams->digest_resultlen * 2 == i;
658 static metalinkfile *new_metalinkfile(metalink_file_t *fileinfo)
661 f = (metalinkfile*)malloc(sizeof(metalinkfile));
663 f->filename = strdup(fileinfo->name);
666 if(fileinfo->checksums) {
667 const metalink_digest_alias *digest_alias;
668 for(digest_alias = digest_aliases; digest_alias->alias_name;
670 metalink_checksum_t **p;
671 for(p = fileinfo->checksums; *p; ++p) {
672 if(Curl_raw_equal(digest_alias->alias_name, (*p)->type) &&
673 check_hex_digest((*p)->hash, digest_alias->digest_def)) {
675 new_metalink_checksum_from_hex_digest(digest_alias->digest_def,
685 if(fileinfo->resources) {
686 metalink_resource_t **p;
687 metalink_resource root, *tail;
690 for(p = fileinfo->resources; *p; ++p) {
691 metalink_resource *res;
692 /* Filter by type if it is non-NULL. In Metalink v3, type
693 includes the type of the resource. In curl, we are only
694 interested in HTTP, HTTPS and FTP. In addition to them,
695 Metalink v3 file may contain bittorrent type URL, which
696 points to the BitTorrent metainfo file. We ignore it here.
697 In Metalink v4, type was deprecated and all
698 fileinfo->resources point to the target file. BitTorrent
699 metainfo file URL may be appeared in fileinfo->metaurls.
701 if((*p)->type == NULL ||
702 Curl_raw_equal((*p)->type, "http") ||
703 Curl_raw_equal((*p)->type, "https") ||
704 Curl_raw_equal((*p)->type, "ftp") ||
705 Curl_raw_equal((*p)->type, "ftps")) {
706 res = new_metalink_resource((*p)->url);
711 f->resource = root.next;
716 int parse_metalink(struct Configurable *config, struct OutStruct *outs,
717 const char *metalink_url)
720 metalink_t* metalink;
721 metalink_file_t **files;
722 bool warnings = FALSE;
724 /* metlaink_parse_final deletes outs->metalink_parser */
725 r = metalink_parse_final(outs->metalink_parser, NULL, 0, &metalink);
726 outs->metalink_parser = NULL;
730 if(metalink->files == NULL) {
731 fprintf(config->errors, "Metalink: parsing (%s) WARNING "
732 "(missing or invalid file name)\n",
734 metalink_delete(metalink);
737 for(files = metalink->files; *files; ++files) {
739 /* Skip an entry which has no resource. */
740 if(!(*files)->resources) {
741 fprintf(config->errors, "Metalink: parsing (%s) WARNING "
742 "(missing or invalid resource)\n",
743 metalink_url, (*files)->name);
746 if(config->url_get ||
747 ((config->url_get = config->url_list) != NULL)) {
748 /* there's a node here, if it already is filled-in continue to
749 find an "empty" node */
750 while(config->url_get && (config->url_get->flags & GETOUT_URL))
751 config->url_get = config->url_get->next;
754 /* now there might or might not be an available node to fill in! */
758 url = config->url_get;
760 /* there was no free node, create one! */
761 url = new_getout(config);
764 metalinkfile *mlfile;
765 mlfile = new_metalinkfile(*files);
766 if(!mlfile->checksum) {
768 fprintf(config->errors, "Metalink: parsing (%s) WARNING "
769 "(digest missing)\n",
772 /* Set name as url */
773 GetStr(&url->url, mlfile->filename);
775 /* set flag metalink here */
776 url->flags |= GETOUT_URL | GETOUT_METALINK;
778 if(config->metalinkfile_list) {
779 config->metalinkfile_last->next = mlfile;
780 config->metalinkfile_last = mlfile;
783 config->metalinkfile_list = config->metalinkfile_last = mlfile;
787 metalink_delete(metalink);
788 return (warnings) ? -2 : 0;
791 size_t metalink_write_cb(void *buffer, size_t sz, size_t nmemb,
794 struct OutStruct *outs = userdata;
795 struct Configurable *config = outs->config;
799 * Once that libcurl has called back tool_write_cb() the returned value
800 * is checked against the amount that was intended to be written, if
801 * it does not match then it fails with CURLE_WRITE_ERROR. So at this
802 * point returning a value different from sz*nmemb indicates failure.
804 const size_t failure = (sz * nmemb) ? 0 : 1;
809 rv = metalink_parse_update(outs->metalink_parser, buffer, sz *nmemb);
813 fprintf(config->errors, "Metalink: parsing FAILED\n");
819 * Returns nonzero if content_type includes mediatype.
821 static int check_content_type(const char *content_type, const char *media_type)
823 const char *ptr = content_type;
824 size_t media_type_len = strlen(media_type);
825 for(; *ptr && (*ptr == ' ' || *ptr == '\t'); ++ptr);
829 return Curl_raw_nequal(ptr, media_type, media_type_len) &&
830 (*(ptr+media_type_len) == '\0' || *(ptr+media_type_len) == ' ' ||
831 *(ptr+media_type_len) == '\t' || *(ptr+media_type_len) == ';');
834 int check_metalink_content_type(const char *content_type)
836 return check_content_type(content_type, "application/metalink+xml");
839 int count_next_metalink_resource(metalinkfile *mlfile)
842 metalink_resource *res;
843 for(res = mlfile->resource; res; res = res->next, ++count);
847 static void delete_metalink_checksum(metalink_checksum *chksum)
852 Curl_safefree(chksum->digest);
853 Curl_safefree(chksum);
856 static void delete_metalink_resource(metalink_resource *res)
861 Curl_safefree(res->url);
865 static void delete_metalinkfile(metalinkfile *mlfile)
867 metalink_resource *res;
871 Curl_safefree(mlfile->filename);
872 delete_metalink_checksum(mlfile->checksum);
873 for(res = mlfile->resource; res;) {
874 metalink_resource *next;
876 delete_metalink_resource(res);
879 Curl_safefree(mlfile);
882 void clean_metalink(struct Configurable *config)
884 while(config->metalinkfile_list) {
885 metalinkfile *mlfile = config->metalinkfile_list;
886 config->metalinkfile_list = config->metalinkfile_list->next;
887 delete_metalinkfile(mlfile);
889 config->metalinkfile_last = 0;
892 void metalink_cleanup(void)
894 #if defined(USE_NSS) && defined(HAVE_NSS_INITCONTEXT)
896 NSS_ShutdownContext(nss_context);
902 #endif /* USE_METALINK */