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