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