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


rc_tagdetect_client
Author(s): Monika Florek-Jasinska , Raphael Schaller
autogenerated on Sat Feb 13 2021 03:42:16