1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel (at) haxx.se>, et al. 9 * 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. 13 * 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. 17 * 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 * KIND, either express or implied. 20 * 21 ***************************************************************************/ 22 #include "tool_setup.h" 23 24 #ifdef USE_METALINK 25 26 #include <sys/stat.h> 27 28 #ifdef HAVE_FCNTL_H 29 # include <fcntl.h> 30 #endif 31 32 #ifdef USE_OPENSSL 33 # include <openssl/md5.h> 34 # include <openssl/sha.h> 35 #elif defined(USE_GNUTLS_NETTLE) 36 # include <nettle/md5.h> 37 # include <nettle/sha.h> 38 # define MD5_CTX struct md5_ctx 39 # define SHA_CTX struct sha1_ctx 40 # define SHA256_CTX struct sha256_ctx 41 #elif defined(USE_GNUTLS) 42 # include <gcrypt.h> 43 # define MD5_CTX gcry_md_hd_t 44 # define SHA_CTX gcry_md_hd_t 45 # define SHA256_CTX gcry_md_hd_t 46 #elif defined(USE_NSS) 47 # include <nss.h> 48 # include <pk11pub.h> 49 # define MD5_CTX void * 50 # define SHA_CTX void * 51 # define SHA256_CTX void * 52 static NSSInitContext *nss_context; 53 #elif defined(USE_POLARSSL) 54 # include <polarssl/md5.h> 55 # include <polarssl/sha1.h> 56 # include <polarssl/sha256.h> 57 # define MD5_CTX md5_context 58 # define SHA_CTX sha1_context 59 # define SHA256_CTX sha256_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. 67 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> 72 #elif defined(_WIN32) 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; 79 HCRYPTHASH hHash; 80 }; 81 /* Custom Microsoft AES Cryptographic Provider defines required for MinGW */ 82 # ifndef ALG_SID_SHA_256 83 # define ALG_SID_SHA_256 12 84 # endif 85 # ifndef CALG_SHA_256 86 # define CALG_SHA_256 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA_256) 87 # endif 88 # define MD5_CTX struct win32_crypto_hash 89 # define SHA_CTX struct win32_crypto_hash 90 # define SHA256_CTX struct win32_crypto_hash 91 #else 92 # error "Can't compile METALINK support without a crypto library." 93 #endif 94 95 #include "rawstr.h" 96 97 #define ENABLE_CURLX_PRINTF 98 /* use our own printf() functions */ 99 #include "curlx.h" 100 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" 106 107 #include "memdebug.h" /* keep this as LAST include */ 108 109 /* Copied from tool_getparam.c */ 110 #define GetStr(str,val) do { \ 111 if(*(str)) { \ 112 free(*(str)); \ 113 *(str) = NULL; \ 114 } \ 115 if((val)) \ 116 *(str) = strdup((val)); \ 117 if(!(val)) \ 118 return PARAM_NO_MEM; \ 119 } WHILE_FALSE 120 121 #ifdef USE_GNUTLS_NETTLE 122 123 static int MD5_Init(MD5_CTX *ctx) 124 { 125 md5_init(ctx); 126 return 1; 127 } 128 129 static void MD5_Update(MD5_CTX *ctx, 130 const unsigned char *input, 131 unsigned int inputLen) 132 { 133 md5_update(ctx, inputLen, input); 134 } 135 136 static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx) 137 { 138 md5_digest(ctx, 16, digest); 139 } 140 141 static int SHA1_Init(SHA_CTX *ctx) 142 { 143 sha1_init(ctx); 144 return 1; 145 } 146 147 static void SHA1_Update(SHA_CTX *ctx, 148 const unsigned char *input, 149 unsigned int inputLen) 150 { 151 sha1_update(ctx, inputLen, input); 152 } 153 154 static void SHA1_Final(unsigned char digest[20], SHA_CTX *ctx) 155 { 156 sha1_digest(ctx, 20, digest); 157 } 158 159 static int SHA256_Init(SHA256_CTX *ctx) 160 { 161 sha256_init(ctx); 162 return 1; 163 } 164 165 static void SHA256_Update(SHA256_CTX *ctx, 166 const unsigned char *input, 167 unsigned int inputLen) 168 { 169 sha256_update(ctx, inputLen, input); 170 } 171 172 static void SHA256_Final(unsigned char digest[32], SHA256_CTX *ctx) 173 { 174 sha256_digest(ctx, 32, digest); 175 } 176 177 #elif defined(USE_GNUTLS) 178 179 static int MD5_Init(MD5_CTX *ctx) 180 { 181 gcry_md_open(ctx, GCRY_MD_MD5, 0); 182 return 1; 183 } 184 185 static void MD5_Update(MD5_CTX *ctx, 186 const unsigned char *input, 187 unsigned int inputLen) 188 { 189 gcry_md_write(*ctx, input, inputLen); 190 } 191 192 static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx) 193 { 194 memcpy(digest, gcry_md_read(*ctx, 0), 16); 195 gcry_md_close(*ctx); 196 } 197 198 static int SHA1_Init(SHA_CTX *ctx) 199 { 200 gcry_md_open(ctx, GCRY_MD_SHA1, 0); 201 return 1; 202 } 203 204 static void SHA1_Update(SHA_CTX *ctx, 205 const unsigned char *input, 206 unsigned int inputLen) 207 { 208 gcry_md_write(*ctx, input, inputLen); 209 } 210 211 static void SHA1_Final(unsigned char digest[20], SHA_CTX *ctx) 212 { 213 memcpy(digest, gcry_md_read(*ctx, 0), 20); 214 gcry_md_close(*ctx); 215 } 216 217 static int SHA256_Init(SHA256_CTX *ctx) 218 { 219 gcry_md_open(ctx, GCRY_MD_SHA256, 0); 220 return 1; 221 } 222 223 static void SHA256_Update(SHA256_CTX *ctx, 224 const unsigned char *input, 225 unsigned int inputLen) 226 { 227 gcry_md_write(*ctx, input, inputLen); 228 } 229 230 static void SHA256_Final(unsigned char digest[32], SHA256_CTX *ctx) 231 { 232 memcpy(digest, gcry_md_read(*ctx, 0), 32); 233 gcry_md_close(*ctx); 234 } 235 236 #elif defined(USE_NSS) 237 238 static int nss_hash_init(void **pctx, SECOidTag hash_alg) 239 { 240 PK11Context *ctx; 241 242 /* we have to initialize NSS if not initialized alraedy */ 243 if(!NSS_IsInitialized() && !nss_context) { 244 static NSSInitParameters params; 245 params.length = sizeof params; 246 nss_context = NSS_InitContext("", "", "", "", ¶ms, NSS_INIT_READONLY 247 | NSS_INIT_NOCERTDB | NSS_INIT_NOMODDB | NSS_INIT_FORCEOPEN 248 | NSS_INIT_NOROOTINIT | NSS_INIT_OPTIMIZESPACE | NSS_INIT_PK11RELOAD); 249 } 250 251 ctx = PK11_CreateDigestContext(hash_alg); 252 if(!ctx) 253 return /* failure */ 0; 254 255 if(PK11_DigestBegin(ctx) != SECSuccess) { 256 PK11_DestroyContext(ctx, PR_TRUE); 257 return /* failure */ 0; 258 } 259 260 *pctx = ctx; 261 return /* success */ 1; 262 } 263 264 static void nss_hash_final(void **pctx, unsigned char *out, unsigned int len) 265 { 266 PK11Context *ctx = *pctx; 267 unsigned int outlen; 268 PK11_DigestFinal(ctx, out, &outlen, len); 269 PK11_DestroyContext(ctx, PR_TRUE); 270 } 271 272 static int MD5_Init(MD5_CTX *pctx) 273 { 274 return nss_hash_init(pctx, SEC_OID_MD5); 275 } 276 277 static void MD5_Update(MD5_CTX *pctx, 278 const unsigned char *input, 279 unsigned int input_len) 280 { 281 PK11_DigestOp(*pctx, input, input_len); 282 } 283 284 static void MD5_Final(unsigned char digest[16], MD5_CTX *pctx) 285 { 286 nss_hash_final(pctx, digest, 16); 287 } 288 289 static int SHA1_Init(SHA_CTX *pctx) 290 { 291 return nss_hash_init(pctx, SEC_OID_SHA1); 292 } 293 294 static void SHA1_Update(SHA_CTX *pctx, 295 const unsigned char *input, 296 unsigned int input_len) 297 { 298 PK11_DigestOp(*pctx, input, input_len); 299 } 300 301 static void SHA1_Final(unsigned char digest[20], SHA_CTX *pctx) 302 { 303 nss_hash_final(pctx, digest, 20); 304 } 305 306 static int SHA256_Init(SHA256_CTX *pctx) 307 { 308 return nss_hash_init(pctx, SEC_OID_SHA256); 309 } 310 311 static void SHA256_Update(SHA256_CTX *pctx, 312 const unsigned char *input, 313 unsigned int input_len) 314 { 315 PK11_DigestOp(*pctx, input, input_len); 316 } 317 318 static void SHA256_Final(unsigned char digest[32], SHA256_CTX *pctx) 319 { 320 nss_hash_final(pctx, digest, 32); 321 } 322 323 #elif defined(USE_POLARSSL) 324 325 static int MD5_Init(MD5_CTX *ctx) 326 { 327 md5_starts(ctx); 328 return 1; 329 } 330 331 static void MD5_Update(MD5_CTX *ctx, 332 const unsigned char *input, 333 unsigned int inputLen) 334 { 335 md5_update(ctx, input, inputLen); 336 } 337 338 static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx) 339 { 340 md5_finish(ctx, digest); 341 } 342 343 static int SHA1_Init(SHA_CTX *ctx) 344 { 345 sha1_starts(ctx); 346 return 1; 347 } 348 349 static void SHA1_Update(SHA_CTX *ctx, 350 const unsigned char *input, 351 unsigned int inputLen) 352 { 353 sha1_update(ctx, input, inputLen); 354 } 355 356 static void SHA1_Final(unsigned char digest[20], SHA_CTX *ctx) 357 { 358 sha1_finish(ctx, digest); 359 } 360 361 static int SHA256_Init(SHA256_CTX *ctx) 362 { 363 sha256_starts(ctx, 0); /* 0 = sha256 */ 364 return 1; 365 } 366 367 static void SHA256_Update(SHA256_CTX *ctx, 368 const unsigned char *input, 369 unsigned int inputLen) 370 { 371 sha256_update(ctx, input, inputLen); 372 } 373 374 static void SHA256_Final(unsigned char digest[32], SHA256_CTX *ctx) 375 { 376 sha256_finish(ctx, digest); 377 } 378 379 #elif defined(_WIN32) && !defined(USE_OPENSSL) 380 381 static void win32_crypto_final(struct win32_crypto_hash *ctx, 382 unsigned char *digest, 383 unsigned int digestLen) 384 { 385 unsigned long length; 386 CryptGetHashParam(ctx->hHash, HP_HASHVAL, NULL, &length, 0); 387 if(length == digestLen) 388 CryptGetHashParam(ctx->hHash, HP_HASHVAL, digest, &length, 0); 389 if(ctx->hHash) 390 CryptDestroyHash(ctx->hHash); 391 if(ctx->hCryptProv) 392 CryptReleaseContext(ctx->hCryptProv, 0); 393 } 394 395 static int MD5_Init(MD5_CTX *ctx) 396 { 397 if(CryptAcquireContext(&ctx->hCryptProv, NULL, NULL, 398 PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { 399 CryptCreateHash(ctx->hCryptProv, CALG_MD5, 0, 0, &ctx->hHash); 400 } 401 return 1; 402 } 403 404 static void MD5_Update(MD5_CTX *ctx, 405 const unsigned char *input, 406 unsigned int inputLen) 407 { 408 CryptHashData(ctx->hHash, (unsigned char *)input, inputLen, 0); 409 } 410 411 static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx) 412 { 413 win32_crypto_final(ctx, digest, 16); 414 } 415 416 static int SHA1_Init(SHA_CTX *ctx) 417 { 418 if(CryptAcquireContext(&ctx->hCryptProv, NULL, NULL, 419 PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { 420 CryptCreateHash(ctx->hCryptProv, CALG_SHA1, 0, 0, &ctx->hHash); 421 } 422 return 1; 423 } 424 425 static void SHA1_Update(SHA_CTX *ctx, 426 const unsigned char *input, 427 unsigned int inputLen) 428 { 429 CryptHashData(ctx->hHash, (unsigned char *)input, inputLen, 0); 430 } 431 432 static void SHA1_Final(unsigned char digest[20], SHA_CTX *ctx) 433 { 434 win32_crypto_final(ctx, digest, 20); 435 } 436 437 static int SHA256_Init(SHA256_CTX *ctx) 438 { 439 if(CryptAcquireContext(&ctx->hCryptProv, NULL, NULL, 440 PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) { 441 CryptCreateHash(ctx->hCryptProv, CALG_SHA_256, 0, 0, &ctx->hHash); 442 } 443 return 1; 444 } 445 446 static void SHA256_Update(SHA256_CTX *ctx, 447 const unsigned char *input, 448 unsigned int inputLen) 449 { 450 CryptHashData(ctx->hHash, (unsigned char *)input, inputLen, 0); 451 } 452 453 static void SHA256_Final(unsigned char digest[32], SHA256_CTX *ctx) 454 { 455 win32_crypto_final(ctx, digest, 32); 456 } 457 458 #endif /* CRYPTO LIBS */ 459 460 const digest_params MD5_DIGEST_PARAMS[] = { 461 { 462 (Curl_digest_init_func) MD5_Init, 463 (Curl_digest_update_func) MD5_Update, 464 (Curl_digest_final_func) MD5_Final, 465 sizeof(MD5_CTX), 466 16 467 } 468 }; 469 470 const digest_params SHA1_DIGEST_PARAMS[] = { 471 { 472 (Curl_digest_init_func) SHA1_Init, 473 (Curl_digest_update_func) SHA1_Update, 474 (Curl_digest_final_func) SHA1_Final, 475 sizeof(SHA_CTX), 476 20 477 } 478 }; 479 480 const digest_params SHA256_DIGEST_PARAMS[] = { 481 { 482 (Curl_digest_init_func) SHA256_Init, 483 (Curl_digest_update_func) SHA256_Update, 484 (Curl_digest_final_func) SHA256_Final, 485 sizeof(SHA256_CTX), 486 32 487 } 488 }; 489 490 static const metalink_digest_def SHA256_DIGEST_DEF[] = { 491 {"sha-256", SHA256_DIGEST_PARAMS} 492 }; 493 494 static const metalink_digest_def SHA1_DIGEST_DEF[] = { 495 {"sha-1", SHA1_DIGEST_PARAMS} 496 }; 497 498 static const metalink_digest_def MD5_DIGEST_DEF[] = { 499 {"md5", MD5_DIGEST_PARAMS} 500 }; 501 502 /* 503 * The alias of supported hash functions in the order by preference 504 * (basically stronger hash comes first). We included "sha-256" and 505 * "sha256". The former is the name defined in the IANA registry named 506 * "Hash Function Textual Names". The latter is widely (and 507 * historically) used in Metalink version 3. 508 */ 509 static const metalink_digest_alias digest_aliases[] = { 510 {"sha-256", SHA256_DIGEST_DEF}, 511 {"sha256", SHA256_DIGEST_DEF}, 512 {"sha-1", SHA1_DIGEST_DEF}, 513 {"sha1", SHA1_DIGEST_DEF}, 514 {"md5", MD5_DIGEST_DEF}, 515 {NULL, NULL} 516 }; 517 518 digest_context *Curl_digest_init(const digest_params *dparams) 519 { 520 digest_context *ctxt; 521 522 /* Create digest context */ 523 ctxt = malloc(sizeof *ctxt); 524 525 if(!ctxt) 526 return ctxt; 527 528 ctxt->digest_hashctx = malloc(dparams->digest_ctxtsize); 529 530 if(!ctxt->digest_hashctx) { 531 free(ctxt); 532 return NULL; 533 } 534 535 ctxt->digest_hash = dparams; 536 537 if(dparams->digest_init(ctxt->digest_hashctx) != 1) { 538 free(ctxt); 539 return NULL; 540 } 541 542 return ctxt; 543 } 544 545 int Curl_digest_update(digest_context *context, 546 const unsigned char *data, 547 unsigned int len) 548 { 549 (*context->digest_hash->digest_update)(context->digest_hashctx, data, len); 550 551 return 0; 552 } 553 554 int Curl_digest_final(digest_context *context, unsigned char *result) 555 { 556 (*context->digest_hash->digest_final)(result, context->digest_hashctx); 557 558 free(context->digest_hashctx); 559 free(context); 560 561 return 0; 562 } 563 564 static unsigned char hex_to_uint(const char *s) 565 { 566 int v[2]; 567 int i; 568 for(i = 0; i < 2; ++i) { 569 v[i] = Curl_raw_toupper(s[i]); 570 if('0' <= v[i] && v[i] <= '9') { 571 v[i] -= '0'; 572 } 573 else if('A' <= v[i] && v[i] <= 'Z') { 574 v[i] -= 'A'-10; 575 } 576 } 577 return (unsigned char)((v[0] << 4) | v[1]); 578 } 579 580 /* 581 * Check checksum of file denoted by filename. The expected hash value 582 * is given in hex_hash which is hex-encoded string. 583 * 584 * This function returns 1 if it succeeds or one of the following 585 * integers: 586 * 587 * 0: 588 * Checksum didn't match. 589 * -1: 590 * Could not open file; or could not read data from file. 591 * -2: 592 * Hash algorithm not available. 593 */ 594 static int check_hash(const char *filename, 595 const metalink_digest_def *digest_def, 596 const unsigned char *digest, FILE *error) 597 { 598 unsigned char *result; 599 digest_context *dctx; 600 int check_ok, flags, fd; 601 602 flags = O_RDONLY; 603 #ifdef O_BINARY 604 /* O_BINARY is required in order to avoid binary EOF in text mode */ 605 flags |= O_BINARY; 606 #endif 607 608 fd = open(filename, flags); 609 if(fd == -1) { 610 fprintf(error, "Metalink: validating (%s) [%s] FAILED (%s)\n", filename, 611 digest_def->hash_name, strerror(errno)); 612 return -1; 613 } 614 615 dctx = Curl_digest_init(digest_def->dparams); 616 if(!dctx) { 617 fprintf(error, "Metalink: validating (%s) [%s] FAILED (%s)\n", filename, 618 digest_def->hash_name, "failed to initialize hash algorithm"); 619 close(fd); 620 return -2; 621 } 622 623 result = malloc(digest_def->dparams->digest_resultlen); 624 if(!result) { 625 close(fd); 626 return -1; 627 } 628 while(1) { 629 unsigned char buf[4096]; 630 ssize_t len = read(fd, buf, sizeof(buf)); 631 if(len == 0) { 632 break; 633 } 634 else if(len == -1) { 635 fprintf(error, "Metalink: validating (%s) [%s] FAILED (%s)\n", filename, 636 digest_def->hash_name, strerror(errno)); 637 Curl_digest_final(dctx, result); 638 close(fd); 639 return -1; 640 } 641 Curl_digest_update(dctx, buf, (unsigned int)len); 642 } 643 Curl_digest_final(dctx, result); 644 check_ok = memcmp(result, digest, 645 digest_def->dparams->digest_resultlen) == 0; 646 /* sha*sum style verdict output */ 647 if(check_ok) 648 fprintf(error, "Metalink: validating (%s) [%s] OK\n", filename, 649 digest_def->hash_name); 650 else 651 fprintf(error, "Metalink: validating (%s) [%s] FAILED (digest mismatch)\n", 652 filename, digest_def->hash_name); 653 654 free(result); 655 close(fd); 656 return check_ok; 657 } 658 659 int metalink_check_hash(struct GlobalConfig *config, 660 metalinkfile *mlfile, 661 const char *filename) 662 { 663 int rv; 664 fprintf(config->errors, "Metalink: validating (%s)...\n", filename); 665 if(mlfile->checksum == NULL) { 666 fprintf(config->errors, 667 "Metalink: validating (%s) FAILED (digest missing)\n", filename); 668 return -2; 669 } 670 rv = check_hash(filename, mlfile->checksum->digest_def, 671 mlfile->checksum->digest, config->errors); 672 return rv; 673 } 674 675 static metalink_checksum *new_metalink_checksum_from_hex_digest 676 (const metalink_digest_def *digest_def, const char *hex_digest) 677 { 678 metalink_checksum *chksum; 679 unsigned char *digest; 680 size_t i; 681 size_t len = strlen(hex_digest); 682 digest = malloc(len/2); 683 if(!digest) 684 return 0; 685 686 for(i = 0; i < len; i += 2) { 687 digest[i/2] = hex_to_uint(hex_digest+i); 688 } 689 chksum = malloc(sizeof(metalink_checksum)); 690 if(chksum) { 691 chksum->digest_def = digest_def; 692 chksum->digest = digest; 693 } 694 return chksum; 695 } 696 697 static metalink_resource *new_metalink_resource(const char *url) 698 { 699 metalink_resource *res; 700 res = malloc(sizeof(metalink_resource)); 701 if(res) { 702 res->next = NULL; 703 res->url = strdup(url); 704 if(!res->url) { 705 free(res); 706 return NULL; 707 } 708 } 709 return res; 710 } 711 712 /* Returns nonzero if hex_digest is properly formatted; that is each 713 letter is in [0-9A-Za-z] and the length of the string equals to the 714 result length of digest * 2. */ 715 static int check_hex_digest(const char *hex_digest, 716 const metalink_digest_def *digest_def) 717 { 718 size_t i; 719 for(i = 0; hex_digest[i]; ++i) { 720 char c = hex_digest[i]; 721 if(!(('0' <= c && c <= '9') || ('a' <= c && c <= 'z') || 722 ('A' <= c && c <= 'Z'))) { 723 return 0; 724 } 725 } 726 return digest_def->dparams->digest_resultlen * 2 == i; 727 } 728 729 static metalinkfile *new_metalinkfile(metalink_file_t *fileinfo) 730 { 731 metalinkfile *f; 732 f = (metalinkfile*)malloc(sizeof(metalinkfile)); 733 if(!f) 734 return NULL; 735 736 f->next = NULL; 737 f->filename = strdup(fileinfo->name); 738 if(!f->filename) { 739 free(f); 740 return NULL; 741 } 742 f->checksum = NULL; 743 f->resource = NULL; 744 if(fileinfo->checksums) { 745 const metalink_digest_alias *digest_alias; 746 for(digest_alias = digest_aliases; digest_alias->alias_name; 747 ++digest_alias) { 748 metalink_checksum_t **p; 749 for(p = fileinfo->checksums; *p; ++p) { 750 if(Curl_raw_equal(digest_alias->alias_name, (*p)->type) && 751 check_hex_digest((*p)->hash, digest_alias->digest_def)) { 752 f->checksum = 753 new_metalink_checksum_from_hex_digest(digest_alias->digest_def, 754 (*p)->hash); 755 break; 756 } 757 } 758 if(f->checksum) { 759 break; 760 } 761 } 762 } 763 if(fileinfo->resources) { 764 metalink_resource_t **p; 765 metalink_resource root, *tail; 766 root.next = NULL; 767 tail = &root; 768 for(p = fileinfo->resources; *p; ++p) { 769 metalink_resource *res; 770 /* Filter by type if it is non-NULL. In Metalink v3, type 771 includes the type of the resource. In curl, we are only 772 interested in HTTP, HTTPS and FTP. In addition to them, 773 Metalink v3 file may contain bittorrent type URL, which 774 points to the BitTorrent metainfo file. We ignore it here. 775 In Metalink v4, type was deprecated and all 776 fileinfo->resources point to the target file. BitTorrent 777 metainfo file URL may be appeared in fileinfo->metaurls. 778 */ 779 if((*p)->type == NULL || 780 Curl_raw_equal((*p)->type, "http") || 781 Curl_raw_equal((*p)->type, "https") || 782 Curl_raw_equal((*p)->type, "ftp") || 783 Curl_raw_equal((*p)->type, "ftps")) { 784 res = new_metalink_resource((*p)->url); 785 tail->next = res; 786 tail = res; 787 } 788 } 789 f->resource = root.next; 790 } 791 return f; 792 } 793 794 int parse_metalink(struct OperationConfig *config, struct OutStruct *outs, 795 const char *metalink_url) 796 { 797 metalink_error_t r; 798 metalink_t* metalink; 799 metalink_file_t **files; 800 bool warnings = FALSE; 801 802 /* metlaink_parse_final deletes outs->metalink_parser */ 803 r = metalink_parse_final(outs->metalink_parser, NULL, 0, &metalink); 804 outs->metalink_parser = NULL; 805 if(r != 0) { 806 return -1; 807 } 808 if(metalink->files == NULL) { 809 fprintf(config->global->errors, "Metalink: parsing (%s) WARNING " 810 "(missing or invalid file name)\n", 811 metalink_url); 812 metalink_delete(metalink); 813 return -1; 814 } 815 for(files = metalink->files; *files; ++files) { 816 struct getout *url; 817 /* Skip an entry which has no resource. */ 818 if(!(*files)->resources) { 819 fprintf(config->global->errors, "Metalink: parsing (%s) WARNING " 820 "(missing or invalid resource)\n", 821 metalink_url, (*files)->name); 822 continue; 823 } 824 if(config->url_get || 825 ((config->url_get = config->url_list) != NULL)) { 826 /* there's a node here, if it already is filled-in continue to 827 find an "empty" node */ 828 while(config->url_get && (config->url_get->flags & GETOUT_URL)) 829 config->url_get = config->url_get->next; 830 } 831 832 /* now there might or might not be an available node to fill in! */ 833 834 if(config->url_get) 835 /* existing node */ 836 url = config->url_get; 837 else 838 /* there was no free node, create one! */ 839 url = new_getout(config); 840 841 if(url) { 842 metalinkfile *mlfile = new_metalinkfile(*files); 843 if(!mlfile) 844 break; 845 846 if(!mlfile->checksum) { 847 warnings = TRUE; 848 fprintf(config->global->errors, 849 "Metalink: parsing (%s) WARNING (digest missing)\n", 850 metalink_url); 851 } 852 /* Set name as url */ 853 GetStr(&url->url, mlfile->filename); 854 855 /* set flag metalink here */ 856 url->flags |= GETOUT_URL | GETOUT_METALINK; 857 858 if(config->metalinkfile_list) { 859 config->metalinkfile_last->next = mlfile; 860 config->metalinkfile_last = mlfile; 861 } 862 else { 863 config->metalinkfile_list = config->metalinkfile_last = mlfile; 864 } 865 } 866 } 867 metalink_delete(metalink); 868 return (warnings) ? -2 : 0; 869 } 870 871 size_t metalink_write_cb(void *buffer, size_t sz, size_t nmemb, 872 void *userdata) 873 { 874 struct OutStruct *outs = userdata; 875 struct OperationConfig *config = outs->config; 876 int rv; 877 878 /* 879 * Once that libcurl has called back tool_write_cb() the returned value 880 * is checked against the amount that was intended to be written, if 881 * it does not match then it fails with CURLE_WRITE_ERROR. So at this 882 * point returning a value different from sz*nmemb indicates failure. 883 */ 884 const size_t failure = (sz * nmemb) ? 0 : 1; 885 886 if(!config) 887 return failure; 888 889 rv = metalink_parse_update(outs->metalink_parser, buffer, sz *nmemb); 890 if(rv == 0) 891 return sz * nmemb; 892 else { 893 fprintf(config->global->errors, "Metalink: parsing FAILED\n"); 894 return failure; 895 } 896 } 897 898 /* 899 * Returns nonzero if content_type includes mediatype. 900 */ 901 static int check_content_type(const char *content_type, const char *media_type) 902 { 903 const char *ptr = content_type; 904 size_t media_type_len = strlen(media_type); 905 for(; *ptr && (*ptr == ' ' || *ptr == '\t'); ++ptr); 906 if(!*ptr) { 907 return 0; 908 } 909 return Curl_raw_nequal(ptr, media_type, media_type_len) && 910 (*(ptr+media_type_len) == '\0' || *(ptr+media_type_len) == ' ' || 911 *(ptr+media_type_len) == '\t' || *(ptr+media_type_len) == ';'); 912 } 913 914 int check_metalink_content_type(const char *content_type) 915 { 916 return check_content_type(content_type, "application/metalink+xml"); 917 } 918 919 int count_next_metalink_resource(metalinkfile *mlfile) 920 { 921 int count = 0; 922 metalink_resource *res; 923 for(res = mlfile->resource; res; res = res->next, ++count); 924 return count; 925 } 926 927 static void delete_metalink_checksum(metalink_checksum *chksum) 928 { 929 if(chksum == NULL) { 930 return; 931 } 932 Curl_safefree(chksum->digest); 933 Curl_safefree(chksum); 934 } 935 936 static void delete_metalink_resource(metalink_resource *res) 937 { 938 if(res == NULL) { 939 return; 940 } 941 Curl_safefree(res->url); 942 Curl_safefree(res); 943 } 944 945 static void delete_metalinkfile(metalinkfile *mlfile) 946 { 947 metalink_resource *res; 948 if(mlfile == NULL) { 949 return; 950 } 951 Curl_safefree(mlfile->filename); 952 delete_metalink_checksum(mlfile->checksum); 953 for(res = mlfile->resource; res;) { 954 metalink_resource *next; 955 next = res->next; 956 delete_metalink_resource(res); 957 res = next; 958 } 959 Curl_safefree(mlfile); 960 } 961 962 void clean_metalink(struct OperationConfig *config) 963 { 964 while(config->metalinkfile_list) { 965 metalinkfile *mlfile = config->metalinkfile_list; 966 config->metalinkfile_list = config->metalinkfile_list->next; 967 delete_metalinkfile(mlfile); 968 } 969 config->metalinkfile_last = 0; 970 } 971 972 void metalink_cleanup(void) 973 { 974 #ifdef USE_NSS 975 if(nss_context) { 976 NSS_ShutdownContext(nss_context); 977 nss_context = NULL; 978 } 979 #endif 980 } 981 982 #endif /* USE_METALINK */ 983