tool_metalink.c 26 KB

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