~ubuntu-branches/ubuntu/feisty/elinks/feisty-updates

« back to all changes in this revision

Viewing changes to src/ssl/connect.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2006-06-30 08:57:43 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060630085743-l81fgbw9dehvl1ds
Tags: 0.11.1-1ubuntu1
* Merge to Debian unstable.
* Removed gnutls12 porting, this is upstream now.
* Only Ubuntu changes left:
  - Killed type-handling.
  - Add X-Ubuntu-Gettext-Domain to .desktop files.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* SSL socket workshop */
2
 
/* $Id: connect.c,v 1.86 2004/11/04 21:10:10 jonas Exp $ */
3
 
 
4
 
#ifdef HAVE_CONFIG_H
5
 
#include "config.h"
6
 
#endif
7
 
 
8
 
#ifdef CONFIG_OPENSSL
9
 
#include <openssl/ssl.h>
10
 
#elif defined(CONFIG_GNUTLS)
11
 
#include <gnutls/gnutls.h>
12
 
#else
13
 
#error "Huh?! You have SSL enabled, but not OPENSSL nor GNUTLS!! And then you want exactly *what* from me?"
14
 
#endif
15
 
 
16
 
#include <errno.h>
17
 
 
18
 
#include "elinks.h"
19
 
 
20
 
#include "config/options.h"
21
 
#include "lowlevel/connect.h"
22
 
#include "lowlevel/dns.h"
23
 
#include "lowlevel/select.h"
24
 
#include "sched/connection.h"
25
 
#include "ssl/connect.h"
26
 
#include "ssl/ssl.h"
27
 
#include "util/memory.h"
28
 
 
29
 
 
30
 
/* SSL errors */
31
 
#ifdef CONFIG_OPENSSL
32
 
#define SSL_ERROR_WANT_READ2    9999 /* XXX */
33
 
#define SSL_ERROR_WANT_WRITE2   SSL_ERROR_WANT_WRITE
34
 
#define SSL_ERROR_SYSCALL2      SSL_ERROR_SYSCALL
35
 
#elif defined(CONFIG_GNUTLS)
36
 
#define SSL_ERROR_NONE          GNUTLS_E_SUCCESS
37
 
#define SSL_ERROR_WANT_READ     GNUTLS_E_AGAIN
38
 
#define SSL_ERROR_WANT_READ2    GNUTLS_E_INTERRUPTED
39
 
#define SSL_ERROR_WANT_WRITE    GNUTLS_E_AGAIN
40
 
#define SSL_ERROR_WANT_WRITE2   GNUTLS_E_INTERRUPTED
41
 
#define SSL_ERROR_SYSCALL       GNUTLS_E_PUSH_ERROR
42
 
#define SSL_ERROR_SYSCALL2      GNUTLS_E_PULL_ERROR
43
 
#endif
44
 
 
45
 
#ifdef CONFIG_OPENSSL
46
 
 
47
 
#define ssl_do_connect(socket)          SSL_get_error(socket->ssl, SSL_connect(socket->ssl))
48
 
#define ssl_do_write(socket, data, len) SSL_write(socket->ssl, data, len)
49
 
#define ssl_do_read(socket, rb)         SSL_read(socket->ssl, rb->data + rb->len, rb->freespace)
50
 
#define ssl_do_close(socket)            /* Hmh? No idea.. */
51
 
 
52
 
#elif defined(CONFIG_GNUTLS)
53
 
 
54
 
#define ssl_do_connect(conn)            gnutls_handshake(*((ssl_t *) socket->ssl))
55
 
#define ssl_do_write(socket, data, len) gnutls_record_send(*((ssl_t *) socket->ssl), data, len)
56
 
#define ssl_do_read(socket, rb)         gnutls_record_recv(*((ssl_t *) socket->ssl), rb->data + rb->len, rb->freespace)
57
 
/* We probably don't handle this entirely correctly.. */
58
 
#define ssl_do_close(socket)            gnutls_bye(*((ssl_t *) socket->ssl), GNUTLS_SHUT_RDWR);
59
 
 
60
 
#endif
61
 
 
62
 
 
63
 
static void
64
 
ssl_set_no_tls(struct connection_socket *socket)
65
 
{
66
 
#ifdef CONFIG_OPENSSL
67
 
        ((ssl_t *) socket->ssl)->options |= SSL_OP_NO_TLSv1;
68
 
#elif defined(CONFIG_GNUTLS)
69
 
        /* We do a little more work here, setting up all these priorities (like
70
 
         * they couldn't have some reasonable defaults there).. */
71
 
 
72
 
        {
73
 
                int protocol_priority[3] = {
74
 
                        GNUTLS_TLS1,
75
 
                        GNUTLS_SSL3,
76
 
                        0
77
 
                };
78
 
 
79
 
                gnutls_protocol_set_priority(*((ssl_t *) socket->ssl), protocol_priority);
80
 
        }
81
 
 
82
 
        /* Note that I have no clue about these; I just put all I found here
83
 
         * ;-). It is all a bit confusing for me, and I just want this to work.
84
 
         * Feel free to send me patch removing useless superfluous bloat,
85
 
         * thanks in advance. --pasky */
86
 
 
87
 
        {
88
 
                int cipher_priority[5] = {
89
 
                        GNUTLS_CIPHER_RIJNDAEL_128_CBC,
90
 
                        GNUTLS_CIPHER_3DES_CBC,
91
 
                        GNUTLS_CIPHER_ARCFOUR,
92
 
                        GNUTLS_CIPHER_RIJNDAEL_256_CBC,
93
 
                        0
94
 
                };
95
 
 
96
 
                gnutls_cipher_set_priority(*((ssl_t *) socket->ssl), cipher_priority);
97
 
        }
98
 
 
99
 
        {
100
 
                /* Does any httpd support this..? ;) */
101
 
                int comp_priority[3] = {
102
 
                        GNUTLS_COMP_ZLIB,
103
 
                        GNUTLS_COMP_NULL,
104
 
                        0
105
 
                };
106
 
 
107
 
                gnutls_compression_set_priority(*((ssl_t *) socket->ssl), comp_priority);
108
 
        }
109
 
 
110
 
        {
111
 
                int kx_priority[5] = {
112
 
                        GNUTLS_KX_RSA,
113
 
                        GNUTLS_KX_DHE_DSS,
114
 
                        GNUTLS_KX_DHE_RSA,
115
 
                        /* Looks like we don't want SRP, do we? */
116
 
                        GNUTLS_KX_ANON_DH,
117
 
                        0
118
 
                };
119
 
 
120
 
                gnutls_kx_set_priority(*((ssl_t *) socket->ssl), kx_priority);
121
 
        }
122
 
 
123
 
        {
124
 
                int mac_priority[3] = {
125
 
                        GNUTLS_MAC_SHA,
126
 
                        GNUTLS_MAC_MD5,
127
 
                        0
128
 
                };
129
 
 
130
 
                gnutls_mac_set_priority(*((ssl_t *) socket->ssl), mac_priority);
131
 
        }
132
 
 
133
 
        {
134
 
                int cert_type_priority[2] = {
135
 
                        GNUTLS_CRT_X509,
136
 
                        /* We don't link with -extra now; by time of writing
137
 
                         * this, it's unclear where OpenPGP will end up. */
138
 
                        0
139
 
                };
140
 
 
141
 
                gnutls_certificate_type_set_priority(*((ssl_t *) socket->ssl), cert_type_priority);
142
 
        }
143
 
 
144
 
        gnutls_dh_set_prime_bits(*((ssl_t *) socket->ssl), 1024);
145
 
#endif
146
 
}
147
 
 
148
 
static void
149
 
ssl_want_read(struct connection *conn)
150
 
{
151
 
        struct conn_info *conn_info = conn->conn_info;
152
 
        struct connection_socket *socket;
153
 
 
154
 
        if (!conn_info) return;
155
 
 
156
 
        socket = conn_info->socket;
157
 
 
158
 
        if (conn->no_tls)
159
 
                ssl_set_no_tls(socket);
160
 
 
161
 
        switch (ssl_do_connect(socket)) {
162
 
                case SSL_ERROR_NONE:
163
 
#ifdef CONFIG_GNUTLS
164
 
                        if (get_opt_bool("connection.ssl.cert_verify")
165
 
                            && gnutls_certificate_verify_peers(*((ssl_t *) socket->ssl))) {
166
 
                                retry_conn_with_state(conn, S_SSL_ERROR);
167
 
                                return;
168
 
                        }
169
 
#endif
170
 
 
171
 
                        done_connection_info(conn);
172
 
 
173
 
                case SSL_ERROR_WANT_READ:
174
 
                case SSL_ERROR_WANT_READ2:
175
 
                        break;
176
 
 
177
 
                default:
178
 
                        conn->no_tls = 1;
179
 
                        retry_conn_with_state(conn, S_SSL_ERROR);
180
 
        }
181
 
}
182
 
 
183
 
/* Return -1 on error, 0 or success. */
184
 
int
185
 
ssl_connect(struct connection *conn, struct connection_socket *socket)
186
 
{
187
 
        int ret;
188
 
 
189
 
        if (init_ssl_connection(&conn->socket) == S_SSL_ERROR) {
190
 
                abort_conn_with_state(conn, S_SSL_ERROR);
191
 
                return -1;
192
 
        }
193
 
 
194
 
        if (conn->no_tls)
195
 
                ssl_set_no_tls(socket);
196
 
 
197
 
#ifdef CONFIG_OPENSSL
198
 
        SSL_set_fd(socket->ssl, socket->fd);
199
 
 
200
 
        if (get_opt_bool("connection.ssl.cert_verify"))
201
 
                SSL_set_verify(socket->ssl, SSL_VERIFY_PEER
202
 
                                          | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
203
 
                                NULL);
204
 
 
205
 
        if (get_opt_bool("connection.ssl.client_cert.enable")) {
206
 
                unsigned char *client_cert;
207
 
 
208
 
                client_cert = get_opt_str("connection.ssl.client_cert.file");
209
 
                if (!*client_cert) {
210
 
                        client_cert = getenv("X509_CLIENT_CERT");
211
 
                        if (client_cert && !*client_cert)
212
 
                                client_cert = NULL;
213
 
                }
214
 
 
215
 
                if (client_cert) {
216
 
                        SSL_CTX *ctx = ((SSL *) socket->ssl)->ctx;
217
 
 
218
 
                        SSL_CTX_use_certificate_chain_file(ctx, client_cert);
219
 
                        SSL_CTX_use_PrivateKey_file(ctx, client_cert,
220
 
                                                    SSL_FILETYPE_PEM);
221
 
                }
222
 
        }
223
 
 
224
 
#elif defined(CONFIG_GNUTLS)
225
 
        gnutls_transport_set_ptr(*((ssl_t *) socket->ssl),
226
 
                                 (gnutls_transport_ptr) socket->fd);
227
 
 
228
 
        /* TODO: Some certificates fuss. --pasky */
229
 
#endif
230
 
 
231
 
        ret = ssl_do_connect(socket);
232
 
 
233
 
        switch (ret) {
234
 
                case SSL_ERROR_WANT_READ:
235
 
                case SSL_ERROR_WANT_READ2:
236
 
                        set_connection_state(conn, S_SSL_NEG);
237
 
                        set_handlers(socket->fd, (void (*)(void *)) ssl_want_read,
238
 
                                     NULL, dns_exception, conn);
239
 
                        return -1;
240
 
 
241
 
                case SSL_ERROR_NONE:
242
 
#ifdef CONFIG_GNUTLS
243
 
                        if (!get_opt_bool("connection.ssl.cert_verify"))
244
 
                                break;
245
 
 
246
 
                        if (!gnutls_certificate_verify_peers(*((ssl_t *) socket->ssl)))
247
 
#endif
248
 
                                break;
249
 
 
250
 
                default:
251
 
                        if (ret != SSL_ERROR_NONE) {
252
 
                                /* DBG("sslerr %s", gnutls_strerror(ret)); */
253
 
                                conn->no_tls = 1;
254
 
                        }
255
 
 
256
 
                        set_connection_state(conn, S_SSL_ERROR);
257
 
                        close_socket(NULL, conn->conn_info->socket);
258
 
                        dns_found(conn, 0);
259
 
                        return -1;
260
 
        }
261
 
 
262
 
        return 0;
263
 
}
264
 
 
265
 
/* Return -1 on error, wr or success. */
266
 
int
267
 
ssl_write(struct connection *conn, struct connection_socket *socket,
268
 
          unsigned char *data, int len)
269
 
{
270
 
        int wr = ssl_do_write(socket, data, len);
271
 
 
272
 
        if (wr <= 0) {
273
 
#ifdef CONFIG_OPENSSL
274
 
                int err = SSL_get_error(socket->ssl, wr);
275
 
#elif defined(CONFIG_GNUTLS)
276
 
                int err = wr;
277
 
#endif
278
 
 
279
 
                if (err == SSL_ERROR_WANT_WRITE ||
280
 
                    err == SSL_ERROR_WANT_WRITE2) {
281
 
                        return -1;
282
 
                }
283
 
 
284
 
                set_connection_state(conn, wr ? (err == SSL_ERROR_SYSCALL ? -errno
285
 
                                                               : S_SSL_ERROR)
286
 
                                   : S_CANT_WRITE);
287
 
 
288
 
                if (!wr || err == SSL_ERROR_SYSCALL)
289
 
                        retry_connection(conn);
290
 
                else
291
 
                        abort_connection(conn);
292
 
 
293
 
                return -1;
294
 
        }
295
 
 
296
 
        return wr;
297
 
}
298
 
 
299
 
/* Return -1 on error, rd or success. */
300
 
int
301
 
ssl_read(struct connection *conn, struct connection_socket *socket,
302
 
         struct read_buffer *rb)
303
 
{
304
 
        int rd = ssl_do_read(socket, rb);
305
 
 
306
 
        if (rd <= 0) {
307
 
#ifdef CONFIG_OPENSSL
308
 
                int err = SSL_get_error(socket->ssl, rd);
309
 
#elif defined(CONFIG_GNUTLS)
310
 
                int err = rd;
311
 
#endif
312
 
 
313
 
#ifdef CONFIG_GNUTLS
314
 
                if (err == GNUTLS_E_REHANDSHAKE)
315
 
                        return -1;
316
 
#endif
317
 
 
318
 
                if (err == SSL_ERROR_WANT_READ ||
319
 
                    err == SSL_ERROR_WANT_READ2) {
320
 
                        read_from_socket(conn, rb->socket, rb, rb->done);
321
 
                        return -1;
322
 
                }
323
 
 
324
 
                if (rb->close != READ_BUFFER_RETRY_ONCLOSE && !rd) {
325
 
                        rb->close = READ_BUFFER_END;
326
 
                        rb->done(conn, rb);
327
 
                        return -1;
328
 
                }
329
 
 
330
 
                set_connection_state(conn, rd ? (err == SSL_ERROR_SYSCALL2 ? -errno
331
 
                                                                : S_SSL_ERROR)
332
 
                                   : S_CANT_READ);
333
 
 
334
 
                /* mem_free(rb); */
335
 
 
336
 
                if (!rd || err == SSL_ERROR_SYSCALL2)
337
 
                        retry_connection(conn);
338
 
                else
339
 
                        abort_connection(conn);
340
 
 
341
 
                return -1;
342
 
        }
343
 
 
344
 
        return rd;
345
 
}
346
 
 
347
 
int
348
 
ssl_close(struct connection *conn, struct connection_socket *socket)
349
 
{
350
 
        ssl_do_close(socket);
351
 
        done_ssl_connection(socket);
352
 
 
353
 
        return 0;
354
 
}