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