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_OS_X_VERSION_MAX_ALLOWED) && \
61 (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040)) || \
62 (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \
63 (__IPHONE_OS_VERSION_MAX_ALLOWED >= 20000))
64 /* For Apple operating systems: CommonCrypto has the functions we need.
65 The library's headers are even backward-compatible with OpenSSL's
66 headers as long as we define COMMON_DIGEST_FOR_OPENSSL first.
68 These functions are available on Tiger and later, as well as iOS 2.0
69 and later. If you're building for an older cat, well, sorry. */
70 # define COMMON_DIGEST_FOR_OPENSSL
71 # include <CommonCrypto/CommonDigest.h>
73 /* For Windows: If no other crypto library is provided, we fallback
74 to the hash functions provided within the Microsoft Windows CryptoAPI */
75 # include <wincrypt.h>
76 /* Custom structure in order to store the required provider and hash handle */
77 struct win32_crypto_hash {
78 HCRYPTPROV hCryptProv;
81 /* Custom Microsoft AES Cryptographic Provider defines required for MinGW */
82 # ifndef ALG_SID_SHA_256
83 # define ALG_SID_SHA_256 12
86 # define CALG_SHA_256 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_256)
88 # define MD5_CTX struct win32_crypto_hash
89 # define SHA_CTX struct win32_crypto_hash
90 # define SHA256_CTX struct win32_crypto_hash
92 # error "Can't compile METALINK support without a crypto library."
97 #define ENABLE_CURLX_PRINTF
98 /* use our own printf() functions */
101 #include "tool_getparam.h"
102 #include "tool_paramhlp.h"
103 #include "tool_cfgable.h"
104 #include "tool_metalink.h"
105 #include "tool_msgs.h"
107 #include "memdebug.h" /* keep this as LAST include */
109 /* Copied from tool_getparam.c */
110 #define GetStr(str,val) do { \
116 *(str) = strdup((val)); \
118 return PARAM_NO_MEM; \
121 #ifdef USE_GNUTLS_NETTLE
123 static int MD5_Init(MD5_CTX *ctx)
129 static void MD5_Update(MD5_CTX *ctx,
130 const unsigned char *input,
131 unsigned int inputLen)
133 md5_update(ctx, inputLen, input);
136 static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx)
138 md5_digest(ctx, 16, digest);
141 static int SHA1_Init(SHA_CTX *ctx)
147 static void SHA1_Update(SHA_CTX *ctx,
148 const unsigned char *input,
149 unsigned int inputLen)
151 sha1_update(ctx, inputLen, input);
154 static void SHA1_Final(unsigned char digest[20], SHA_CTX *ctx)
156 sha1_digest(ctx, 20, digest);
159 static int SHA256_Init(SHA256_CTX *ctx)
165 static void SHA256_Update(SHA256_CTX *ctx,
166 const unsigned char *input,
167 unsigned int inputLen)
169 sha256_update(ctx, inputLen, input);
172 static void SHA256_Final(unsigned char digest[32], SHA256_CTX *ctx)
174 sha256_digest(ctx, 32, digest);
177 #elif defined(USE_GNUTLS)
179 static int MD5_Init(MD5_CTX *ctx)
181 gcry_md_open(ctx, GCRY_MD_MD5, 0);
185 static void MD5_Update(MD5_CTX *ctx,
186 const unsigned char *input,
187 unsigned int inputLen)
189 gcry_md_write(*ctx, input, inputLen);
192 static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx)
194 memcpy(digest, gcry_md_read(*ctx, 0), 16);
198 static int SHA1_Init(SHA_CTX *ctx)
200 gcry_md_open(ctx, GCRY_MD_SHA1, 0);
204 static void SHA1_Update(SHA_CTX *ctx,
205 const unsigned char *input,
206 unsigned int inputLen)
208 gcry_md_write(*ctx, input, inputLen);
211 static void SHA1_Final(unsigned char digest[20], SHA_CTX *ctx)
213 memcpy(digest, gcry_md_read(*ctx, 0), 20);
217 static int SHA256_Init(SHA256_CTX *ctx)
219 gcry_md_open(ctx, GCRY_MD_SHA256, 0);
223 static void SHA256_Update(SHA256_CTX *ctx,
224 const unsigned char *input,
225 unsigned int inputLen)
227 gcry_md_write(*ctx, input, inputLen);
230 static void SHA256_Final(unsigned char digest[32], SHA256_CTX *ctx)
232 memcpy(digest, gcry_md_read(*ctx, 0), 32);
236 #elif defined(USE_NSS)
238 static int nss_hash_init(void **pctx, SECOidTag hash_alg)
242 /* we have to initialize NSS if not initialized alraedy */
243 #ifdef HAVE_NSS_INITCONTEXT
244 if(!NSS_IsInitialized() && !nss_context) {
245 static NSSInitParameters params;
246 params.length = sizeof params;
247 nss_context = NSS_InitContext("", "", "", "", ¶ms, NSS_INIT_READONLY
248 | NSS_INIT_NOCERTDB | NSS_INIT_NOMODDB | NSS_INIT_FORCEOPEN
249 | NSS_INIT_NOROOTINIT | NSS_INIT_OPTIMIZESPACE | NSS_INIT_PK11RELOAD);
253 ctx = PK11_CreateDigestContext(hash_alg);
255 return /* failure */ 0;
257 if(PK11_DigestBegin(ctx) != SECSuccess) {
258 PK11_DestroyContext(ctx, PR_TRUE);
259 return /* failure */ 0;
263 return /* success */ 1;
266 static void nss_hash_final(void **pctx, unsigned char *out, unsigned int len)
268 PK11Context *ctx = *pctx;
270 PK11_DigestFinal(ctx, out, &outlen, len);
271 PK11_DestroyContext(ctx, PR_TRUE);
274 static int MD5_Init(MD5_CTX *pctx)
276 return nss_hash_init(pctx, SEC_OID_MD5);
279 static void MD5_Update(MD5_CTX *pctx,
280 const unsigned char *input,
281 unsigned int input_len)
283 PK11_DigestOp(*pctx, input, input_len);
286 static void MD5_Final(unsigned char digest[16], MD5_CTX *pctx)
288 nss_hash_final(pctx, digest, 16);
291 static int SHA1_Init(SHA_CTX *pctx)
293 return nss_hash_init(pctx, SEC_OID_SHA1);
296 static void SHA1_Update(SHA_CTX *pctx,
297 const unsigned char *input,
298 unsigned int input_len)
300 PK11_DigestOp(*pctx, input, input_len);
303 static void SHA1_Final(unsigned char digest[20], SHA_CTX *pctx)
305 nss_hash_final(pctx, digest, 20);
308 static int SHA256_Init(SHA256_CTX *pctx)
310 return nss_hash_init(pctx, SEC_OID_SHA256);
313 static void SHA256_Update(SHA256_CTX *pctx,
314 const unsigned char *input,
315 unsigned int input_len)
317 PK11_DigestOp(*pctx, input, input_len);
320 static void SHA256_Final(unsigned char digest[32], SHA256_CTX *pctx)
322 nss_hash_final(pctx, digest, 32);
325 #elif defined(_WIN32) && !defined(USE_SSLEAY)
327 static void win32_crypto_final(struct win32_crypto_hash *ctx,
328 unsigned char *digest,
329 unsigned int digestLen)
331 unsigned long length;
332 CryptGetHashParam(ctx->hHash, HP_HASHVAL, NULL, &length, 0);
333 if(length == digestLen)
334 CryptGetHashParam(ctx->hHash, HP_HASHVAL, digest, &length, 0);
336 CryptDestroyHash(ctx->hHash);
338 CryptReleaseContext(ctx->hCryptProv, 0);
341 static int MD5_Init(MD5_CTX *ctx)
343 if(CryptAcquireContext(&ctx->hCryptProv, NULL, NULL,
344 PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
345 CryptCreateHash(ctx->hCryptProv, CALG_MD5, 0, 0, &ctx->hHash);
350 static void MD5_Update(MD5_CTX *ctx,
351 const unsigned char *input,
352 unsigned int inputLen)
354 CryptHashData(ctx->hHash, (unsigned char *)input, inputLen, 0);
357 static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx)
359 win32_crypto_final(ctx, digest, 16);
362 static int SHA1_Init(SHA_CTX *ctx)
364 if(CryptAcquireContext(&ctx->hCryptProv, NULL, NULL,
365 PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
366 CryptCreateHash(ctx->hCryptProv, CALG_SHA1, 0, 0, &ctx->hHash);
371 static void SHA1_Update(SHA_CTX *ctx,
372 const unsigned char *input,
373 unsigned int inputLen)
375 CryptHashData(ctx->hHash, (unsigned char *)input, inputLen, 0);
378 static void SHA1_Final(unsigned char digest[20], SHA_CTX *ctx)
380 win32_crypto_final(ctx, digest, 20);
383 static int SHA256_Init(SHA256_CTX *ctx)
385 if(CryptAcquireContext(&ctx->hCryptProv, NULL, NULL,
386 PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
387 CryptCreateHash(ctx->hCryptProv, CALG_SHA_256, 0, 0, &ctx->hHash);
392 static void SHA256_Update(SHA256_CTX *ctx,
393 const unsigned char *input,
394 unsigned int inputLen)
396 CryptHashData(ctx->hHash, (unsigned char *)input, inputLen, 0);
399 static void SHA256_Final(unsigned char digest[32], SHA256_CTX *ctx)
401 win32_crypto_final(ctx, digest, 32);
404 #endif /* CRYPTO LIBS */
406 const digest_params MD5_DIGEST_PARAMS[] = {
408 (Curl_digest_init_func) MD5_Init,
409 (Curl_digest_update_func) MD5_Update,
410 (Curl_digest_final_func) MD5_Final,
416 const digest_params SHA1_DIGEST_PARAMS[] = {
418 (Curl_digest_init_func) SHA1_Init,
419 (Curl_digest_update_func) SHA1_Update,
420 (Curl_digest_final_func) SHA1_Final,
426 const digest_params SHA256_DIGEST_PARAMS[] = {
428 (Curl_digest_init_func) SHA256_Init,
429 (Curl_digest_update_func) SHA256_Update,
430 (Curl_digest_final_func) SHA256_Final,
436 static const metalink_digest_def SHA256_DIGEST_DEF[] = {
437 {"sha-256", SHA256_DIGEST_PARAMS}
440 static const metalink_digest_def SHA1_DIGEST_DEF[] = {
441 {"sha-1", SHA1_DIGEST_PARAMS}
444 static const metalink_digest_def MD5_DIGEST_DEF[] = {
445 {"md5", MD5_DIGEST_PARAMS}
449 * The alias of supported hash functions in the order by preference
450 * (basically stronger hash comes first). We included "sha-256" and
451 * "sha256". The former is the name defined in the IANA registry named
452 * "Hash Function Textual Names". The latter is widely (and
453 * historically) used in Metalink version 3.
455 static const metalink_digest_alias digest_aliases[] = {
456 {"sha-256", SHA256_DIGEST_DEF},
457 {"sha256", SHA256_DIGEST_DEF},
458 {"sha-1", SHA1_DIGEST_DEF},
459 {"sha1", SHA1_DIGEST_DEF},
460 {"md5", MD5_DIGEST_DEF},
464 digest_context *Curl_digest_init(const digest_params *dparams)
466 digest_context *ctxt;
468 /* Create digest context */
469 ctxt = malloc(sizeof *ctxt);
474 ctxt->digest_hashctx = malloc(dparams->digest_ctxtsize);
476 if(!ctxt->digest_hashctx) {
481 ctxt->digest_hash = dparams;
483 if(dparams->digest_init(ctxt->digest_hashctx) != 1) {
491 int Curl_digest_update(digest_context *context,
492 const unsigned char *data,
495 (*context->digest_hash->digest_update)(context->digest_hashctx, data, len);
500 int Curl_digest_final(digest_context *context, unsigned char *result)
502 (*context->digest_hash->digest_final)(result, context->digest_hashctx);
504 free(context->digest_hashctx);
510 static unsigned char hex_to_uint(const char *s)
514 for(i = 0; i < 2; ++i) {
515 v[i] = Curl_raw_toupper(s[i]);
516 if('0' <= v[i] && v[i] <= '9') {
519 else if('A' <= v[i] && v[i] <= 'Z') {
523 return (unsigned char)((v[0] << 4) | v[1]);
527 * Check checksum of file denoted by filename. The expected hash value
528 * is given in hex_hash which is hex-encoded string.
530 * This function returns 1 if it succeeds or one of the following
534 * Checksum didn't match.
536 * Could not open file; or could not read data from file.
538 * Hash algorithm not available.
540 static int check_hash(const char *filename,
541 const metalink_digest_def *digest_def,
542 const unsigned char *digest, FILE *error)
544 unsigned char *result;
545 digest_context *dctx;
546 int check_ok, flags, fd;
550 /* O_BINARY is required in order to avoid binary EOF in text mode */
554 fd = open(filename, flags);
556 fprintf(error, "Metalink: validating (%s) [%s] FAILED (%s)\n", filename,
557 digest_def->hash_name, strerror(errno));
561 dctx = Curl_digest_init(digest_def->dparams);
563 fprintf(error, "Metalink: validating (%s) [%s] FAILED (%s)\n", filename,
564 digest_def->hash_name, "failed to initialize hash algorithm");
569 result = malloc(digest_def->dparams->digest_resultlen);
571 unsigned char buf[4096];
572 ssize_t len = read(fd, buf, sizeof(buf));
577 fprintf(error, "Metalink: validating (%s) [%s] FAILED (%s)\n", filename,
578 digest_def->hash_name, strerror(errno));
579 Curl_digest_final(dctx, result);
583 Curl_digest_update(dctx, buf, (unsigned int)len);
585 Curl_digest_final(dctx, result);
586 check_ok = memcmp(result, digest,
587 digest_def->dparams->digest_resultlen) == 0;
588 /* sha*sum style verdict output */
590 fprintf(error, "Metalink: validating (%s) [%s] OK\n", filename,
591 digest_def->hash_name);
593 fprintf(error, "Metalink: validating (%s) [%s] FAILED (digest mismatch)\n",
594 filename, digest_def->hash_name);
601 int metalink_check_hash(struct Configurable *config,
602 metalinkfile *mlfile,
603 const char *filename)
606 fprintf(config->errors, "Metalink: validating (%s)...\n", filename);
607 if(mlfile->checksum == NULL) {
608 fprintf(config->errors,
609 "Metalink: validating (%s) FAILED (digest missing)\n",
613 rv = check_hash(filename, mlfile->checksum->digest_def,
614 mlfile->checksum->digest, config->errors);
618 static metalink_checksum *new_metalink_checksum_from_hex_digest
619 (const metalink_digest_def *digest_def, const char *hex_digest)
621 metalink_checksum *chksum;
622 unsigned char *digest;
624 size_t len = strlen(hex_digest);
625 digest = malloc(len/2);
626 for(i = 0; i < len; i += 2) {
627 digest[i/2] = hex_to_uint(hex_digest+i);
629 chksum = malloc(sizeof(metalink_checksum));
630 chksum->digest_def = digest_def;
631 chksum->digest = digest;
635 static metalink_resource *new_metalink_resource(const char *url)
637 metalink_resource *res;
638 res = malloc(sizeof(metalink_resource));
640 res->url = strdup(url);
644 /* Returns nonzero if hex_digest is properly formatted; that is each
645 letter is in [0-9A-Za-z] and the length of the string equals to the
646 result length of digest * 2. */
647 static int check_hex_digest(const char *hex_digest,
648 const metalink_digest_def *digest_def)
651 for(i = 0; hex_digest[i]; ++i) {
652 char c = hex_digest[i];
653 if(!(('0' <= c && c <= '9') || ('a' <= c && c <= 'z') ||
654 ('A' <= c && c <= 'Z'))) {
658 return digest_def->dparams->digest_resultlen * 2 == i;
661 static metalinkfile *new_metalinkfile(metalink_file_t *fileinfo)
664 f = (metalinkfile*)malloc(sizeof(metalinkfile));
666 f->filename = strdup(fileinfo->name);
669 if(fileinfo->checksums) {
670 const metalink_digest_alias *digest_alias;
671 for(digest_alias = digest_aliases; digest_alias->alias_name;
673 metalink_checksum_t **p;
674 for(p = fileinfo->checksums; *p; ++p) {
675 if(Curl_raw_equal(digest_alias->alias_name, (*p)->type) &&
676 check_hex_digest((*p)->hash, digest_alias->digest_def)) {
678 new_metalink_checksum_from_hex_digest(digest_alias->digest_def,
688 if(fileinfo->resources) {
689 metalink_resource_t **p;
690 metalink_resource root, *tail;
693 for(p = fileinfo->resources; *p; ++p) {
694 metalink_resource *res;
695 /* Filter by type if it is non-NULL. In Metalink v3, type
696 includes the type of the resource. In curl, we are only
697 interested in HTTP, HTTPS and FTP. In addition to them,
698 Metalink v3 file may contain bittorrent type URL, which
699 points to the BitTorrent metainfo file. We ignore it here.
700 In Metalink v4, type was deprecated and all
701 fileinfo->resources point to the target file. BitTorrent
702 metainfo file URL may be appeared in fileinfo->metaurls.
704 if((*p)->type == NULL ||
705 Curl_raw_equal((*p)->type, "http") ||
706 Curl_raw_equal((*p)->type, "https") ||
707 Curl_raw_equal((*p)->type, "ftp") ||
708 Curl_raw_equal((*p)->type, "ftps")) {
709 res = new_metalink_resource((*p)->url);
714 f->resource = root.next;
719 int parse_metalink(struct Configurable *config, struct OutStruct *outs,
720 const char *metalink_url)
723 metalink_t* metalink;
724 metalink_file_t **files;
725 bool warnings = FALSE;
727 /* metlaink_parse_final deletes outs->metalink_parser */
728 r = metalink_parse_final(outs->metalink_parser, NULL, 0, &metalink);
729 outs->metalink_parser = NULL;
733 if(metalink->files == NULL) {
734 fprintf(config->errors, "Metalink: parsing (%s) WARNING "
735 "(missing or invalid file name)\n",
737 metalink_delete(metalink);
740 for(files = metalink->files; *files; ++files) {
742 /* Skip an entry which has no resource. */
743 if(!(*files)->resources) {
744 fprintf(config->errors, "Metalink: parsing (%s) WARNING "
745 "(missing or invalid resource)\n",
746 metalink_url, (*files)->name);
749 if(config->url_get ||
750 ((config->url_get = config->url_list) != NULL)) {
751 /* there's a node here, if it already is filled-in continue to
752 find an "empty" node */
753 while(config->url_get && (config->url_get->flags & GETOUT_URL))
754 config->url_get = config->url_get->next;
757 /* now there might or might not be an available node to fill in! */
761 url = config->url_get;
763 /* there was no free node, create one! */
764 url = new_getout(config);
767 metalinkfile *mlfile;
768 mlfile = new_metalinkfile(*files);
769 if(!mlfile->checksum) {
771 fprintf(config->errors, "Metalink: parsing (%s) WARNING "
772 "(digest missing)\n",
775 /* Set name as url */
776 GetStr(&url->url, mlfile->filename);
778 /* set flag metalink here */
779 url->flags |= GETOUT_URL | GETOUT_METALINK;
781 if(config->metalinkfile_list) {
782 config->metalinkfile_last->next = mlfile;
783 config->metalinkfile_last = mlfile;
786 config->metalinkfile_list = config->metalinkfile_last = mlfile;
790 metalink_delete(metalink);
791 return (warnings) ? -2 : 0;
794 size_t metalink_write_cb(void *buffer, size_t sz, size_t nmemb,
797 struct OutStruct *outs = userdata;
798 struct Configurable *config = outs->config;
802 * Once that libcurl has called back tool_write_cb() the returned value
803 * is checked against the amount that was intended to be written, if
804 * it does not match then it fails with CURLE_WRITE_ERROR. So at this
805 * point returning a value different from sz*nmemb indicates failure.
807 const size_t failure = (sz * nmemb) ? 0 : 1;
812 rv = metalink_parse_update(outs->metalink_parser, buffer, sz *nmemb);
816 fprintf(config->errors, "Metalink: parsing FAILED\n");
822 * Returns nonzero if content_type includes mediatype.
824 static int check_content_type(const char *content_type, const char *media_type)
826 const char *ptr = content_type;
827 size_t media_type_len = strlen(media_type);
828 for(; *ptr && (*ptr == ' ' || *ptr == '\t'); ++ptr);
832 return Curl_raw_nequal(ptr, media_type, media_type_len) &&
833 (*(ptr+media_type_len) == '\0' || *(ptr+media_type_len) == ' ' ||
834 *(ptr+media_type_len) == '\t' || *(ptr+media_type_len) == ';');
837 int check_metalink_content_type(const char *content_type)
839 return check_content_type(content_type, "application/metalink+xml");
842 int count_next_metalink_resource(metalinkfile *mlfile)
845 metalink_resource *res;
846 for(res = mlfile->resource; res; res = res->next, ++count);
850 static void delete_metalink_checksum(metalink_checksum *chksum)
855 Curl_safefree(chksum->digest);
856 Curl_safefree(chksum);
859 static void delete_metalink_resource(metalink_resource *res)
864 Curl_safefree(res->url);
868 static void delete_metalinkfile(metalinkfile *mlfile)
870 metalink_resource *res;
874 Curl_safefree(mlfile->filename);
875 delete_metalink_checksum(mlfile->checksum);
876 for(res = mlfile->resource; res;) {
877 metalink_resource *next;
879 delete_metalink_resource(res);
882 Curl_safefree(mlfile);
885 void clean_metalink(struct Configurable *config)
887 while(config->metalinkfile_list) {
888 metalinkfile *mlfile = config->metalinkfile_list;
889 config->metalinkfile_list = config->metalinkfile_list->next;
890 delete_metalinkfile(mlfile);
892 config->metalinkfile_last = 0;
895 void metalink_cleanup(void)
897 #if defined(USE_NSS) && defined(HAVE_NSS_INITCONTEXT)
899 NSS_ShutdownContext(nss_context);
905 #endif /* USE_METALINK */