]> sjero.net Git - wget/blob - src/gen_sslfunc.c
44b5414a22a7c7a6d12f6c5faf1b2f68361fa36f
[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 #include <assert.h>
34 #include <errno.h>
35 #ifdef HAVE_UNISTD_H
36 # include <unistd.h>
37 #endif
38 #ifdef HAVE_STRING_H
39 # include <string.h>
40 #else
41 # include <strings.h>
42 #endif
43
44 #include <openssl/bio.h>
45 #include <openssl/crypto.h>
46 #include <openssl/x509.h>
47 #include <openssl/ssl.h>
48 #include <openssl/err.h>
49 #include <openssl/pem.h>
50 #include <openssl/rand.h>
51
52 #include "wget.h"
53 #include "utils.h"
54 #include "connect.h"
55 #include "url.h"
56 #include "gen_sslfunc.h"
57
58 #ifndef errno
59 extern int errno;
60 #endif
61
62 SSL_CTX *ssl_ctx;
63
64 static void
65 ssl_init_prng (void)
66 {
67   /* It is likely that older versions of OpenSSL will fail on
68      non-Linux machines because this code is unable to seed the PRNG
69      on older versions of the library.  */
70
71 #if SSLEAY_VERSION_NUMBER >= 0x00905100
72   char rand_file[256];
73   int maxrand = 500;
74
75   /* First, seed from a file specified by the user.  This will be
76      $RANDFILE, if set, or ~/.rnd.  */
77   RAND_file_name (rand_file, sizeof (rand_file));
78   if (rand_file)
79     /* Seed at most 16k (value borrowed from curl) from random file. */
80     RAND_load_file (rand_file, 16384);
81
82   if (RAND_status ())
83     return;
84
85   /* Get random data from EGD if opt.sslegdsock was set.  */
86   if (opt.sslegdsock && *opt.sslegdsock)
87     RAND_egd (opt.sslegdsock);
88
89   if (RAND_status ())
90     return;
91
92 #ifdef WINDOWS
93   /* Under Windows, we can try to seed the PRNG using screen content.
94      This may or may not work, depending on whether we'll calling Wget
95      interactively.  */
96
97   RAND_screen ();
98   if (RAND_status ())
99     return;
100 #endif
101
102   /* Still not enough randomness, most likely because neither
103      /dev/random nor EGD were available.  Resort to a simple and
104      stupid method -- seed OpenSSL's PRNG with libc PRNG.  This is
105      cryptographically weak, but people who care about strong
106      cryptography should install /dev/random (default on Linux) or
107      specify their own source of randomness anyway.  */
108
109   logprintf (LOG_VERBOSE, _("Warning: using a weak random seed.\n"));
110
111   while (RAND_status () == 0 && maxrand-- > 0)
112     {
113       unsigned char rnd = random_number (256);
114       RAND_seed (&rnd, sizeof (rnd));
115     }
116 #endif /* SSLEAY_VERSION_NUMBER >= 0x00905100 */
117 }
118
119 static int
120 verify_callback (int ok, X509_STORE_CTX *ctx)
121 {
122   char *s, buf[256];
123   s = X509_NAME_oneline (X509_get_subject_name (ctx->current_cert), buf, 256);
124   if (ok == 0) {
125     switch (ctx->error) {
126     case X509_V_ERR_CERT_NOT_YET_VALID:
127     case X509_V_ERR_CERT_HAS_EXPIRED:
128       /* This mean the CERT is not valid !!! */
129       ok = 0;
130       break;
131     case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
132       /* Unsure if we should handle that this way */
133       ok = 1;
134       break;
135     }
136   }
137   return ok;
138 }
139
140 /* Print SSL errors. */
141
142 static void
143 ssl_print_errors (void) 
144 {
145   unsigned long curerr = 0;
146   while ((curerr = ERR_get_error ()) != 0)
147     logprintf (LOG_NOTQUIET, "OpenSSL: %s\n", ERR_error_string (curerr, NULL));
148 }
149
150 /* Creates a SSL Context and sets some defaults for it */
151 uerr_t
152 ssl_init ()
153 {
154   SSL_METHOD *meth = NULL;
155   int verify;
156   int can_validate;
157
158   if (ssl_ctx)
159     return 0;
160
161   /* Init the PRNG.  If that fails, bail out.  */
162   ssl_init_prng ();
163   if (RAND_status () == 0)
164     {
165       logprintf (LOG_NOTQUIET,
166                  _("Could not seed OpenSSL PRNG; disabling SSL.\n"));
167       scheme_disable (SCHEME_HTTPS);
168       return SSLERRCTXCREATE;
169     }
170
171   SSL_library_init ();
172   SSL_load_error_strings ();
173   SSLeay_add_all_algorithms ();
174   SSLeay_add_ssl_algorithms ();
175   switch (opt.sslprotocol)
176     {
177       default:
178         meth = SSLv23_client_method ();
179         break;
180       case 1 :
181         meth = SSLv2_client_method ();
182         break;
183       case 2 :
184         meth = SSLv3_client_method ();
185         break;
186       case 3 :
187         meth = TLSv1_client_method ();
188         break;
189     }
190   if (meth == NULL)
191     {
192       ssl_print_errors ();
193       return SSLERRCTXCREATE;
194     }
195
196   ssl_ctx = SSL_CTX_new (meth);
197   if (meth == NULL)
198     {
199       ssl_print_errors ();
200       return SSLERRCTXCREATE;
201     }
202   /* Can we validate the server Cert ? */
203   if (opt.sslcadir != NULL || opt.sslcafile != NULL)
204     {
205       SSL_CTX_load_verify_locations (ssl_ctx, opt.sslcafile, opt.sslcadir);
206       can_validate = 1;
207     }
208   else
209     {
210       can_validate = 0;
211     }
212
213   if (!opt.sslcheckcert)
214     {
215       /* check cert but ignore error, do not break handshake on error */
216       verify = SSL_VERIFY_NONE;
217     }
218   else
219     {
220       if (!can_validate)
221         {
222           logputs (LOG_NOTQUIET,
223                    _("Warning: validation of server certificate not possible!\n"));
224           verify = SSL_VERIFY_NONE;
225         }
226      else
227         {
228           /* break handshake if server cert is not valid but allow
229              NO-Cert mode */
230           verify = SSL_VERIFY_PEER;
231         }
232     }
233
234   SSL_CTX_set_verify (ssl_ctx, verify, verify_callback);
235
236   if (opt.sslcertfile != NULL || opt.sslcertkey != NULL)
237     {
238       int ssl_cert_type;
239       if (!opt.sslcerttype)
240         ssl_cert_type = SSL_FILETYPE_PEM;
241       else
242         ssl_cert_type = SSL_FILETYPE_ASN1;
243
244       if (opt.sslcertkey == NULL) 
245         opt.sslcertkey = opt.sslcertfile;
246       if (opt.sslcertfile == NULL)
247         opt.sslcertfile = opt.sslcertkey; 
248
249       if (SSL_CTX_use_certificate_file (ssl_ctx, opt.sslcertfile,
250                                         ssl_cert_type) <= 0)
251         {
252           ssl_print_errors ();
253           return SSLERRCERTFILE;
254         }
255       if (SSL_CTX_use_PrivateKey_file  (ssl_ctx, opt.sslcertkey,
256                                         ssl_cert_type) <= 0)
257         {
258           ssl_print_errors ();
259           return SSLERRCERTKEY;
260         }
261     }
262
263   return 0; /* Succeded */
264 }
265
266 static int
267 ssl_read (int fd, char *buf, int bufsize, void *ctx)
268 {
269   int ret;
270   SSL *ssl = (SSL *) ctx;
271   do
272     ret = SSL_read (ssl, buf, bufsize);
273   while (ret == -1
274          && SSL_get_error (ssl, ret) == SSL_ERROR_SYSCALL
275          && errno == EINTR);
276   return ret;
277 }
278
279 static int
280 ssl_write (int fd, char *buf, int bufsize, void *ctx)
281 {
282   int ret = 0;
283   SSL *ssl = (SSL *) ctx;
284   do
285     ret = SSL_write (ssl, buf, bufsize);
286   while (ret == -1
287          && SSL_get_error (ssl, ret) == SSL_ERROR_SYSCALL
288          && errno == EINTR);
289   return ret;
290 }
291
292 static int
293 ssl_poll (int fd, double timeout, int wait_for, void *ctx)
294 {
295   SSL *ssl = (SSL *) ctx;
296   if (timeout == 0)
297     return 1;
298   if (SSL_pending (ssl))
299     return 1;
300   return select_fd (fd, timeout, wait_for);
301 }
302
303 static int
304 ssl_peek (int fd, char *buf, int bufsize, void *ctx)
305 {
306   int ret;
307   SSL *ssl = (SSL *) ctx;
308   do
309     ret = SSL_peek (ssl, buf, bufsize);
310   while (ret == -1
311          && SSL_get_error (ssl, ret) == SSL_ERROR_SYSCALL
312          && errno == EINTR);
313   return ret;
314 }
315
316 static void
317 ssl_close (int fd, void *ctx)
318 {
319   SSL *ssl = (SSL *) ctx;
320   SSL_shutdown (ssl);
321   SSL_free (ssl);
322
323 #ifdef WINDOWS
324   closesocket (fd);
325 #else
326   close (fd);
327 #endif
328
329   DEBUGP (("Closed %d/SSL 0x%0lx\n", fd, (unsigned long) ssl));
330 }
331
332 /* Sets up a SSL structure and performs the handshake on fd.  The
333    resulting SSL structure is registered with the file descriptor FD
334    using fd_register_transport.  That way subsequent calls to xread,
335    xwrite, etc., will use the appropriate SSL functions.
336
337    Returns 1 on success, 0 on failure.  */
338
339 int
340 ssl_connect (int fd) 
341 {
342   SSL *ssl;
343
344   assert (ssl_ctx != NULL);
345   ssl = SSL_new (ssl_ctx);
346   if (!ssl)
347     goto err;
348   if (!SSL_set_fd (ssl, fd))
349     goto err;
350   SSL_set_connect_state (ssl);
351   if (SSL_connect (ssl) <= 0 || ssl->state != SSL_ST_OK)
352     goto err;
353
354   /* Register FD with Wget's transport layer, i.e. arrange that
355      SSL-enabled functions are used for reading, writing, and polling.
356      That way the rest of Wget can keep using xread, xwrite, and
357      friends and not care what happens underneath.  */
358   fd_register_transport (fd, ssl_read, ssl_write, ssl_poll, ssl_peek,
359                          ssl_close, ssl);
360   DEBUGP (("Connected %d to SSL 0x%0*lx\n", fd, 2 * sizeof (void *),
361            (unsigned long) ssl));
362   return 1;
363
364  err:
365   ssl_print_errors ();
366   if (ssl)
367     SSL_free (ssl);
368   return 0;
369 }