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