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