• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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("", "", "", "", &params, 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