]> sjero.net Git - wget/blob - src/gen_sslfunc.c
[svn] Use new macros xnew, xnew0, xnew_array, and xnew0_array in various places.
[wget] / src / gen_sslfunc.c
1 /* SSL support.
2    Copyright (C) 2000 Free Software Foundation, Inc.
3    Contributed by Christian Fraenkel.
4
5 This file is part of GNU Wget.
6
7 GNU Wget is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 GNU Wget is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Wget; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
21 In addition, as a special exception, the Free Software Foundation
22 gives permission to link the code of its release of Wget with the
23 OpenSSL project's "OpenSSL" library (or with modified versions of it
24 that use the same license as the "OpenSSL" library), and distribute
25 the linked executables.  You must obey the GNU General Public License
26 in all respects for all of the code used other than "OpenSSL".  If you
27 modify this file, you may extend this exception to your version of the
28 file, but you are not obligated to do so.  If you do not wish to do
29 so, delete this exception statement from your version.  */
30
31 #include <config.h>
32
33 #ifdef HAVE_SSL
34
35 #include <assert.h>
36 #include <errno.h>
37 #ifdef HAVE_UNISTD_H
38 # include <unistd.h>
39 #endif
40 #ifdef HAVE_STRING_H
41 # include <string.h>
42 #else
43 # include <strings.h>
44 #endif
45
46 #include <openssl/bio.h>
47 #include <openssl/crypto.h>
48 #include <openssl/x509.h>
49 #include <openssl/ssl.h>
50 #include <openssl/err.h>
51 #include <openssl/pem.h>
52 #include <openssl/rand.h>
53
54 #include "wget.h"
55 #include "utils.h"
56 #include "connect.h"
57 #include "url.h"
58
59 #ifndef errno
60 extern int errno;
61 #endif
62
63 void
64 ssl_init_prng (void)
65 {
66   /* It is likely that older versions of OpenSSL will fail on
67      non-Linux machines because this code is unable to seed the PRNG
68      on older versions of the library.  */
69
70 #if SSLEAY_VERSION_NUMBER >= 0x00905100
71   char rand_file[256];
72   int maxrand = 500;
73
74   /* First, seed from a file specified by the user.  This will be
75      $RANDFILE, if set, or ~/.rnd.  */
76   RAND_file_name (rand_file, sizeof (rand_file));
77   if (rand_file)
78     /* Seed at most 16k (value borrowed from curl) from random file. */
79     RAND_load_file (rand_file, 16384);
80
81   if (RAND_status ())
82     return;
83
84   /* Get random data from EGD if opt.sslegdsock was set.  */
85   if (opt.sslegdsock && *opt.sslegdsock)
86     RAND_egd (opt.sslegdsock);
87
88   if (RAND_status ())
89     return;
90
91 #ifdef WINDOWS
92   /* Under Windows, we can try to seed the PRNG using screen content.
93      This may or may not work, depending on whether we'll calling Wget
94      interactively.  */
95
96   RAND_screen ();
97   if (RAND_status ())
98     return;
99 #endif
100
101   /* Still not enough randomness, presumably because neither random
102      file nor EGD have been available.  Use the stupidest possible
103      method -- seed OpenSSL's PRNG with the system's PRNG.  This is
104      insecure in the cryptographic sense, but people who care about
105      security will use /dev/random or their own source of randomness
106      anyway.  */
107
108   while (RAND_status () == 0 && maxrand-- > 0)
109     {
110       unsigned char rnd = random_number (256);
111       RAND_seed (&rnd, sizeof (rnd));
112     }
113
114   if (RAND_status () == 0)
115     {
116       logprintf (LOG_NOTQUIET,
117                  _("Could not seed OpenSSL PRNG; disabling SSL.\n"));
118       scheme_disable (SCHEME_HTTPS);
119     }
120 #endif /* SSLEAY_VERSION_NUMBER >= 0x00905100 */
121 }
122
123 int
124 verify_callback (int ok, X509_STORE_CTX *ctx)
125 {
126   char *s, buf[256];
127   s = X509_NAME_oneline (X509_get_subject_name (ctx->current_cert), buf, 256);
128   if (ok == 0) {
129     switch (ctx->error) {
130     case X509_V_ERR_CERT_NOT_YET_VALID:
131     case X509_V_ERR_CERT_HAS_EXPIRED:
132       /* This mean the CERT is not valid !!! */
133       ok = 0;
134       break;
135     case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
136       /* Unsure if we should handle that this way */
137       ok = 1;
138       break;
139     }
140   }
141   return ok;
142 }
143
144 /* pass all ssl errors to DEBUGP
145    returns the number of printed errors */
146 int
147 ssl_printerrors (void) 
148 {
149   int ocerr = 0;
150   unsigned long curerr = 0;
151   char errbuff[1024];
152   xzero (errbuff);
153   while ((curerr = ERR_get_error ()) != 0)
154     {
155       DEBUGP (("OpenSSL: %s\n", ERR_error_string (curerr, errbuff)));
156       ++ocerr;
157     }
158   return ocerr;
159 }
160
161 /* Creates a SSL Context and sets some defaults for it */
162 uerr_t
163 init_ssl (SSL_CTX **ctx)
164 {
165   SSL_METHOD *meth = NULL;
166   int verify;
167   int can_validate;
168   SSL_library_init ();
169   SSL_load_error_strings ();
170   SSLeay_add_all_algorithms ();
171   SSLeay_add_ssl_algorithms ();
172   switch (opt.sslprotocol)
173     {
174       default:
175         meth = SSLv23_client_method ();
176         break;
177       case 1 :
178         meth = SSLv2_client_method ();
179         break;
180       case 2 :
181         meth = SSLv3_client_method ();
182         break;
183       case 3 :
184         meth = TLSv1_client_method ();
185         break;
186     }
187   if (meth == NULL)
188     {
189       ssl_printerrors ();
190       return SSLERRCTXCREATE;
191     }
192
193   *ctx = SSL_CTX_new (meth);
194   if (meth == NULL)
195     {
196       ssl_printerrors ();
197       return SSLERRCTXCREATE;
198     }
199   /* Can we validate the server Cert ? */
200   if (opt.sslcadir != NULL || opt.sslcafile != NULL)
201     {
202       SSL_CTX_load_verify_locations (*ctx, opt.sslcafile, opt.sslcadir);
203       can_validate = 1;
204     }
205   else
206     {
207       can_validate = 0;
208     }
209
210   if (!opt.sslcheckcert)
211     {
212       /* check cert but ignore error, do not break handshake on error */
213       verify = SSL_VERIFY_NONE;
214     }
215   else
216     {
217       if (!can_validate)
218         {
219           logprintf (LOG_NOTQUIET, "Warrining validation of Server Cert not possible!\n");
220           verify = SSL_VERIFY_NONE;
221         }
222      else
223         {
224           /* break handshake if server cert is not valid but allow NO-Cert mode */
225           verify = SSL_VERIFY_PEER;
226         }
227     }
228
229   SSL_CTX_set_verify (*ctx, verify, verify_callback);
230
231   if (opt.sslcertfile != NULL || opt.sslcertkey != NULL)
232     {
233       int ssl_cert_type;
234       if (!opt.sslcerttype)
235         ssl_cert_type = SSL_FILETYPE_PEM;
236       else
237         ssl_cert_type = SSL_FILETYPE_ASN1;
238
239       if (opt.sslcertkey == NULL) 
240         opt.sslcertkey = opt.sslcertfile;
241       if (opt.sslcertfile == NULL)
242         opt.sslcertfile = opt.sslcertkey; 
243
244       if (SSL_CTX_use_certificate_file (*ctx, opt.sslcertfile, ssl_cert_type) <= 0)
245         {
246           ssl_printerrors ();
247           return SSLERRCERTFILE;
248         }
249       if (SSL_CTX_use_PrivateKey_file  (*ctx, opt.sslcertkey , ssl_cert_type) <= 0)
250         {
251           ssl_printerrors ();
252           return SSLERRCERTKEY;
253         }
254     }
255
256   return 0; /* Succeded */
257 }
258
259 void
260 shutdown_ssl (SSL* con)
261 {
262   if (con == NULL)
263     return;
264   if (0==SSL_shutdown (con))
265     SSL_shutdown (con);
266   SSL_free (con);
267 }
268
269 /* Sets up a SSL structure and performs the handshake on fd 
270    Returns 0 if everything went right
271    Returns 1 if something went wrong ----- TODO: More exit codes
272 */
273 int
274 connect_ssl (SSL **con, SSL_CTX *ctx, int fd) 
275 {
276   if (NULL == (*con = SSL_new (ctx)))
277     {
278       ssl_printerrors ();
279       return 1;
280     }
281   if (!SSL_set_fd (*con, fd))
282     {
283       ssl_printerrors ();
284       return 1;
285     }
286   SSL_set_connect_state (*con);
287   switch (SSL_connect (*con))
288     {
289       case 1 : 
290         return (*con)->state != SSL_ST_OK;
291       default:
292         ssl_printerrors ();
293         shutdown_ssl (*con);
294         *con = NULL;
295         return 1;
296       case 0 :
297         ssl_printerrors ();
298         SSL_free (*con);
299         *con = NULL;
300         return 1;
301     }
302   return 0;
303 }
304
305 void
306 free_ssl_ctx (SSL_CTX * ctx)
307 {
308   SSL_CTX_free (ctx);
309 }
310
311 /* SSL version of iread.  Only exchanged read for SSL_read Read at
312    most LEN bytes from FD, storing them to BUF. */
313
314 int
315 ssl_iread (SSL *con, char *buf, int len)
316 {
317   int res, fd;
318   BIO_get_fd (con->rbio, &fd);
319 #ifdef HAVE_SELECT
320   if (opt.read_timeout && !SSL_pending (con))
321     if (select_fd (fd, opt.read_timeout, 0) <= 0)
322       return -1;
323 #endif
324   do
325     res = SSL_read (con, buf, len);
326   while (res == -1 && errno == EINTR);
327
328   return res;
329 }
330
331 /* SSL version of iwrite.  Only exchanged write for SSL_write Write
332    LEN bytes from BUF to FD.  */
333
334 int
335 ssl_iwrite (SSL *con, char *buf, int len)
336 {
337   int res = 0, fd;
338   BIO_get_fd (con->rbio, &fd);
339   /* `write' may write less than LEN bytes, thus the outward loop
340      keeps trying it until all was written, or an error occurred.  The
341      inner loop is reserved for the usual EINTR f*kage, and the
342      innermost loop deals with the same during select().  */
343   while (len > 0)
344     {
345 #ifdef HAVE_SELECT
346       if (opt.read_timeout)
347         if (select_fd (fd, opt.read_timeout, 1) <= 0)
348           return -1;
349 #endif
350       do
351         res = SSL_write (con, buf, len);
352       while (res == -1 && errno == EINTR);
353       if (res <= 0)
354         break;
355       buf += res;
356       len -= res;
357     }
358   return res;
359 }
360 #endif /* HAVE_SSL */