]> sjero.net Git - wget/blob - src/gen_sslfunc.c
8b64b581e106945a1dad379a408c3eca178a699f
[wget] / src / gen_sslfunc.c
1 /* SSL support.
2    Copyright (C) 2000 Christian Fraenkel.
3
4 This file is part of Wget.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
19
20 #include <config.h>
21
22 #ifdef HAVE_SSL
23
24 #include <assert.h>
25 #include <sys/time.h>
26 #include <errno.h>
27
28 #include <openssl/bio.h>
29 #include <openssl/crypto.h>
30 #include <openssl/x509.h>
31 #include <openssl/ssl.h>
32 #include <openssl/err.h>
33 #include <openssl/pem.h>
34
35 #define SSL_ERR_CTX_CREATION -2
36
37 #include "wget.h"
38 #include "connect.h"
39
40 #ifndef errno
41 extern int errno;
42 #endif
43
44 /* #### Shouldn't this be static?  --hniksic */
45 int verify_callback PARAMS ((int, X509_STORE_CTX *));
46
47 /* Creates a SSL Context and sets some defaults for it */
48 int
49 init_ssl (SSL_CTX **ctx)
50 {
51   SSL_METHOD *meth = NULL;
52   int verify = SSL_VERIFY_NONE;
53   SSL_library_init ();
54   SSL_load_error_strings ();
55   SSLeay_add_all_algorithms ();
56   SSLeay_add_ssl_algorithms ();
57   meth = SSLv23_client_method ();
58   *ctx = SSL_CTX_new (meth);
59   SSL_CTX_set_verify (*ctx, verify, verify_callback);
60   if (*ctx == NULL) return SSL_ERR_CTX_CREATION;
61   return 0; /* Succeded */
62 }
63
64 /* Sets up a SSL structure and performs the handshake on fd 
65    Returns 0 if everything went right
66    Returns 1 if something went wrong ----- TODO: More exit codes
67 */
68 int
69 connect_ssl (SSL **con, SSL_CTX *ctx, int fd) 
70 {
71   *con = (SSL *)SSL_new (ctx);
72   SSL_set_fd (*con, fd);
73   SSL_set_connect_state (*con); 
74   SSL_connect (*con);  
75   if ((*con)->state != SSL_ST_OK)
76     return 1;
77   return 0;
78 }
79
80 void
81 shutdown_ssl (SSL* con)
82 {
83   SSL_shutdown (con);
84   if (con != NULL)
85     SSL_free (con);
86 }
87
88 void
89 free_ssl_ctx (SSL_CTX * ctx)
90 {
91   SSL_CTX_free (ctx);
92 }
93
94 int
95 verify_callback (int ok, X509_STORE_CTX *ctx)
96 {
97   char *s, buf[256];
98   s = X509_NAME_oneline (X509_get_subject_name (ctx->current_cert), buf, 256);
99   if (ok == 0) {
100     switch (ctx->error) {
101     case X509_V_ERR_CERT_NOT_YET_VALID:
102     case X509_V_ERR_CERT_HAS_EXPIRED:
103     case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
104       ok = 1;
105     }
106   }
107   return ok;
108 }
109
110 /* SSL version of iread. Only exchanged read for SSL_read 
111    Read at most LEN bytes from FD, storing them to BUF.  This is
112    virtually the same as read(), but takes care of EINTR braindamage
113    and uses select() to timeout the stale connections (a connection is
114    stale if more than OPT.TIMEOUT time is spent in select() or
115    read()).  */
116 int
117 ssl_iread (SSL *con, char *buf, int len)
118 {
119   int res;
120   int fd;
121   BIO_get_fd (con->rbio, &fd);
122   do
123     {
124 #ifdef HAVE_SELECT
125       if (opt.timeout)
126         {
127           
128           do
129             {
130               res = select_fd (fd, opt.timeout, 0);
131             }
132           while (res == -1 && errno == EINTR);
133           if (res <= 0)
134             {
135               /* Set errno to ETIMEDOUT on timeout.  */
136               if (res == 0)
137                 /* #### Potentially evil!  */
138                 errno = ETIMEDOUT;
139               return -1;
140             }
141         }
142 #endif
143       res = SSL_read (con, buf, len);
144     }
145   while (res == -1 && errno == EINTR);
146
147   return res;
148 }
149
150 /* SSL version of iwrite. Only exchanged write for SSL_write 
151    Write LEN bytes from BUF to FD.  This is similar to iread(), but
152    doesn't bother with select().  Unlike iread(), it makes sure that
153    all of BUF is actually written to FD, so callers needn't bother
154    with checking that the return value equals to LEN.  Instead, you
155    should simply check for -1.  */
156 int
157 ssl_iwrite (SSL *con, char *buf, int len)
158 {
159   int res = 0;
160   int fd;
161   BIO_get_fd (con->rbio, &fd);
162   /* `write' may write less than LEN bytes, thus the outward loop
163      keeps trying it until all was written, or an error occurred.  The
164      inner loop is reserved for the usual EINTR f*kage, and the
165      innermost loop deals with the same during select().  */
166   while (len > 0)
167     {
168       do
169         {
170 #ifdef HAVE_SELECT
171           if (opt.timeout)
172             {
173               do
174                 {
175                   res = select_fd (fd, opt.timeout, 1);
176                 }
177               while (res == -1 && errno == EINTR);
178               if (res <= 0)
179                 {
180                   /* Set errno to ETIMEDOUT on timeout.  */
181                   if (res == 0)
182                     /* #### Potentially evil!  */
183                     errno = ETIMEDOUT;
184                   return -1;
185                 }
186             }
187 #endif
188           res = SSL_write (con, buf, len);
189         }
190       while (res == -1 && errno == EINTR);
191       if (res <= 0)
192         break;
193       buf += res;
194       len -= res;
195     }
196   return res;
197 }
198 #endif /* HAVE_SSL */