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
MD5_Init(MD5_CTX * ctx)122 static int MD5_Init(MD5_CTX *ctx)
123 {
124 md5_init(ctx);
125 return 1;
126 }
127
MD5_Update(MD5_CTX * ctx,const unsigned char * input,unsigned int inputLen)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
MD5_Final(unsigned char digest[16],MD5_CTX * ctx)135 static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx)
136 {
137 md5_digest(ctx, 16, digest);
138 }
139
SHA1_Init(SHA_CTX * ctx)140 static int SHA1_Init(SHA_CTX *ctx)
141 {
142 sha1_init(ctx);
143 return 1;
144 }
145
SHA1_Update(SHA_CTX * ctx,const unsigned char * input,unsigned int inputLen)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
SHA1_Final(unsigned char digest[20],SHA_CTX * ctx)153 static void SHA1_Final(unsigned char digest[20], SHA_CTX *ctx)
154 {
155 sha1_digest(ctx, 20, digest);
156 }
157
SHA256_Init(SHA256_CTX * ctx)158 static int SHA256_Init(SHA256_CTX *ctx)
159 {
160 sha256_init(ctx);
161 return 1;
162 }
163
SHA256_Update(SHA256_CTX * ctx,const unsigned char * input,unsigned int inputLen)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
SHA256_Final(unsigned char digest[32],SHA256_CTX * ctx)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
MD5_Init(MD5_CTX * ctx)178 static int MD5_Init(MD5_CTX *ctx)
179 {
180 gcry_md_open(ctx, GCRY_MD_MD5, 0);
181 return 1;
182 }
183
MD5_Update(MD5_CTX * ctx,const unsigned char * input,unsigned int inputLen)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
MD5_Final(unsigned char digest[16],MD5_CTX * ctx)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
SHA1_Init(SHA_CTX * ctx)197 static int SHA1_Init(SHA_CTX *ctx)
198 {
199 gcry_md_open(ctx, GCRY_MD_SHA1, 0);
200 return 1;
201 }
202
SHA1_Update(SHA_CTX * ctx,const unsigned char * input,unsigned int inputLen)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
SHA1_Final(unsigned char digest[20],SHA_CTX * ctx)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
SHA256_Init(SHA256_CTX * ctx)216 static int SHA256_Init(SHA256_CTX *ctx)
217 {
218 gcry_md_open(ctx, GCRY_MD_SHA256, 0);
219 return 1;
220 }
221
SHA256_Update(SHA256_CTX * ctx,const unsigned char * input,unsigned int inputLen)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
SHA256_Final(unsigned char digest[32],SHA256_CTX * ctx)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
nss_hash_init(void ** pctx,SECOidTag hash_alg)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("", "", "", "", ¶ms, 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
nss_hash_final(void ** pctx,unsigned char * out,unsigned int len)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
MD5_Init(MD5_CTX * pctx)271 static int MD5_Init(MD5_CTX *pctx)
272 {
273 return nss_hash_init(pctx, SEC_OID_MD5);
274 }
275
MD5_Update(MD5_CTX * pctx,const unsigned char * input,unsigned int input_len)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
MD5_Final(unsigned char digest[16],MD5_CTX * pctx)283 static void MD5_Final(unsigned char digest[16], MD5_CTX *pctx)
284 {
285 nss_hash_final(pctx, digest, 16);
286 }
287
SHA1_Init(SHA_CTX * pctx)288 static int SHA1_Init(SHA_CTX *pctx)
289 {
290 return nss_hash_init(pctx, SEC_OID_SHA1);
291 }
292
SHA1_Update(SHA_CTX * pctx,const unsigned char * input,unsigned int input_len)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
SHA1_Final(unsigned char digest[20],SHA_CTX * pctx)300 static void SHA1_Final(unsigned char digest[20], SHA_CTX *pctx)
301 {
302 nss_hash_final(pctx, digest, 20);
303 }
304
SHA256_Init(SHA256_CTX * pctx)305 static int SHA256_Init(SHA256_CTX *pctx)
306 {
307 return nss_hash_init(pctx, SEC_OID_SHA256);
308 }
309
SHA256_Update(SHA256_CTX * pctx,const unsigned char * input,unsigned int input_len)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
SHA256_Final(unsigned char digest[32],SHA256_CTX * pctx)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
MD5_Init(MD5_CTX * ctx)324 static int MD5_Init(MD5_CTX *ctx)
325 {
326 md5_starts(ctx);
327 return 1;
328 }
329
MD5_Update(MD5_CTX * ctx,const unsigned char * input,unsigned int inputLen)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
MD5_Final(unsigned char digest[16],MD5_CTX * ctx)337 static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx)
338 {
339 md5_finish(ctx, digest);
340 }
341
SHA1_Init(SHA_CTX * ctx)342 static int SHA1_Init(SHA_CTX *ctx)
343 {
344 sha1_starts(ctx);
345 return 1;
346 }
347
SHA1_Update(SHA_CTX * ctx,const unsigned char * input,unsigned int inputLen)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
SHA1_Final(unsigned char digest[20],SHA_CTX * ctx)355 static void SHA1_Final(unsigned char digest[20], SHA_CTX *ctx)
356 {
357 sha1_finish(ctx, digest);
358 }
359
SHA256_Init(SHA256_CTX * ctx)360 static int SHA256_Init(SHA256_CTX *ctx)
361 {
362 sha256_starts(ctx, 0); /* 0 = sha256 */
363 return 1;
364 }
365
SHA256_Update(SHA256_CTX * ctx,const unsigned char * input,unsigned int inputLen)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
SHA256_Final(unsigned char digest[32],SHA256_CTX * ctx)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
win32_crypto_final(struct win32_crypto_hash * ctx,unsigned char * digest,unsigned int digestLen)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
MD5_Init(MD5_CTX * ctx)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
MD5_Update(MD5_CTX * ctx,const unsigned char * input,unsigned int inputLen)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
MD5_Final(unsigned char digest[16],MD5_CTX * ctx)410 static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx)
411 {
412 win32_crypto_final(ctx, digest, 16);
413 }
414
SHA1_Init(SHA_CTX * ctx)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
SHA1_Update(SHA_CTX * ctx,const unsigned char * input,unsigned int inputLen)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
SHA1_Final(unsigned char digest[20],SHA_CTX * ctx)431 static void SHA1_Final(unsigned char digest[20], SHA_CTX *ctx)
432 {
433 win32_crypto_final(ctx, digest, 20);
434 }
435
SHA256_Init(SHA256_CTX * ctx)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
SHA256_Update(SHA256_CTX * ctx,const unsigned char * input,unsigned int inputLen)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
SHA256_Final(unsigned char digest[32],SHA256_CTX * ctx)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
Curl_digest_init(const digest_params * dparams)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
Curl_digest_update(digest_context * context,const unsigned char * data,unsigned int len)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
Curl_digest_final(digest_context * context,unsigned char * result)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
hex_to_uint(const char * s)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 */
check_hash(const char * filename,const metalink_digest_def * digest_def,const unsigned char * digest,FILE * error)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
metalink_check_hash(struct GlobalConfig * config,metalinkfile * mlfile,const char * filename)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
new_metalink_checksum_from_hex_digest(const metalink_digest_def * digest_def,const char * hex_digest)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
new_metalink_resource(const char * url)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. */
check_hex_digest(const char * hex_digest,const metalink_digest_def * digest_def)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
new_metalinkfile(metalink_file_t * fileinfo)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
parse_metalink(struct OperationConfig * config,struct OutStruct * outs,const char * metalink_url)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
metalink_write_cb(void * buffer,size_t sz,size_t nmemb,void * userdata)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 */
check_content_type(const char * content_type,const char * media_type)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
check_metalink_content_type(const char * content_type)908 int check_metalink_content_type(const char *content_type)
909 {
910 return check_content_type(content_type, "application/metalink+xml");
911 }
912
count_next_metalink_resource(metalinkfile * mlfile)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
delete_metalink_checksum(metalink_checksum * chksum)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
delete_metalink_resource(metalink_resource * res)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
delete_metalinkfile(metalinkfile * mlfile)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
clean_metalink(struct OperationConfig * config)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
metalink_cleanup(void)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 */
977