Raise an error on syscall failure in tls_retry_write_records
[openssl.git] / crypto / bio / bss_conn.c
1 /*
2  * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 #include <stdio.h>
11 #include <errno.h>
12
13 #include "bio_lcl.h"
14
15 #ifndef OPENSSL_NO_SOCK
16
17 typedef struct bio_connect_st {
18     int state;
19     int connect_family;
20     char *param_hostname;
21     char *param_service;
22     int connect_mode;
23
24     BIO_ADDRINFO *addr_first;
25     const BIO_ADDRINFO *addr_iter;
26     /*
27      * int socket; this will be kept in bio->num so that it is compatible
28      * with the bss_sock bio
29      */
30     /*
31      * called when the connection is initially made callback(BIO,state,ret);
32      * The callback should return 'ret'.  state is for compatibility with the
33      * ssl info_callback
34      */
35     BIO_info_cb *info_callback;
36 } BIO_CONNECT;
37
38 static int conn_write(BIO *h, const char *buf, int num);
39 static int conn_read(BIO *h, char *buf, int size);
40 static int conn_puts(BIO *h, const char *str);
41 static long conn_ctrl(BIO *h, int cmd, long arg1, void *arg2);
42 static int conn_new(BIO *h);
43 static int conn_free(BIO *data);
44 static long conn_callback_ctrl(BIO *h, int cmd, BIO_info_cb *);
45
46 static int conn_state(BIO *b, BIO_CONNECT *c);
47 static void conn_close_socket(BIO *data);
48 BIO_CONNECT *BIO_CONNECT_new(void);
49 void BIO_CONNECT_free(BIO_CONNECT *a);
50
51 #define BIO_CONN_S_BEFORE                1
52 #define BIO_CONN_S_GET_ADDR              2
53 #define BIO_CONN_S_CREATE_SOCKET         3
54 #define BIO_CONN_S_CONNECT               4
55 #define BIO_CONN_S_OK                    5
56 #define BIO_CONN_S_BLOCKED_CONNECT       6
57
58 static const BIO_METHOD methods_connectp = {
59     BIO_TYPE_CONNECT,
60     "socket connect",
61     /* TODO: Convert to new style write function */
62     bwrite_conv,
63     conn_write,
64     /* TODO: Convert to new style read function */
65     bread_conv,
66     conn_read,
67     conn_puts,
68     NULL,                       /* conn_gets, */
69     conn_ctrl,
70     conn_new,
71     conn_free,
72     conn_callback_ctrl,
73 };
74
75 static int conn_state(BIO *b, BIO_CONNECT *c)
76 {
77     int ret = -1, i;
78     BIO_info_cb *cb = NULL;
79
80     if (c->info_callback != NULL)
81         cb = c->info_callback;
82
83     for (;;) {
84         switch (c->state) {
85         case BIO_CONN_S_BEFORE:
86             if (c->param_hostname == NULL && c->param_service == NULL) {
87                 BIOerr(BIO_F_CONN_STATE, BIO_R_NO_HOSTNAME_OR_SERVICE_SPECIFIED);
88                 ERR_add_error_data(4,
89                                    "hostname=", c->param_hostname,
90                                    " service=", c->param_service);
91                 goto exit_loop;
92             }
93             c->state = BIO_CONN_S_GET_ADDR;
94             break;
95
96         case BIO_CONN_S_GET_ADDR:
97             {
98                 int family = AF_UNSPEC;
99                 switch (c->connect_family) {
100                 case BIO_FAMILY_IPV6:
101                     if (1) { /* This is a trick we use to avoid bit rot.
102                               * at least the "else" part will always be
103                               * compiled.
104                               */
105 #ifdef AF_INET6
106                         family = AF_INET6;
107                     } else {
108 #endif
109                         BIOerr(BIO_F_CONN_STATE, BIO_R_UNAVAILABLE_IP_FAMILY);
110                         goto exit_loop;
111                     }
112                     break;
113                 case BIO_FAMILY_IPV4:
114                     family = AF_INET;
115                     break;
116                 case BIO_FAMILY_IPANY:
117                     family = AF_UNSPEC;
118                     break;
119                 default:
120                     BIOerr(BIO_F_CONN_STATE, BIO_R_UNSUPPORTED_IP_FAMILY);
121                     goto exit_loop;
122                 }
123                 if (BIO_lookup(c->param_hostname, c->param_service,
124                                BIO_LOOKUP_CLIENT,
125                                family, SOCK_STREAM, &c->addr_first) == 0)
126                     goto exit_loop;
127             }
128             if (c->addr_first == NULL) {
129                 BIOerr(BIO_F_CONN_STATE, BIO_R_LOOKUP_RETURNED_NOTHING);
130                 goto exit_loop;
131             }
132             c->addr_iter = c->addr_first;
133             c->state = BIO_CONN_S_CREATE_SOCKET;
134             break;
135
136         case BIO_CONN_S_CREATE_SOCKET:
137             ret = BIO_socket(BIO_ADDRINFO_family(c->addr_iter),
138                              BIO_ADDRINFO_socktype(c->addr_iter),
139                              BIO_ADDRINFO_protocol(c->addr_iter), 0);
140             if (ret == (int)INVALID_SOCKET) {
141                 ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
142                                "calling socket(%s, %s)",
143                                c->param_hostname, c->param_service);
144                 BIOerr(BIO_F_CONN_STATE, BIO_R_UNABLE_TO_CREATE_SOCKET);
145                 goto exit_loop;
146             }
147             b->num = ret;
148             c->state = BIO_CONN_S_CONNECT;
149             break;
150
151         case BIO_CONN_S_CONNECT:
152             BIO_clear_retry_flags(b);
153             ret = BIO_connect(b->num, BIO_ADDRINFO_address(c->addr_iter),
154                               BIO_SOCK_KEEPALIVE | c->connect_mode);
155             b->retry_reason = 0;
156             if (ret == 0) {
157                 if (BIO_sock_should_retry(ret)) {
158                     BIO_set_retry_special(b);
159                     c->state = BIO_CONN_S_BLOCKED_CONNECT;
160                     b->retry_reason = BIO_RR_CONNECT;
161                     ERR_clear_error();
162                 } else if ((c->addr_iter = BIO_ADDRINFO_next(c->addr_iter))
163                            != NULL) {
164                     /*
165                      * if there are more addresses to try, do that first
166                      */
167                     BIO_closesocket(b->num);
168                     c->state = BIO_CONN_S_CREATE_SOCKET;
169                     ERR_clear_error();
170                     break;
171                 } else {
172                     ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
173                                    "calling connect(%s, %s)",
174                                     c->param_hostname, c->param_service);
175                     BIOerr(BIO_F_CONN_STATE, BIO_R_CONNECT_ERROR);
176                 }
177                 goto exit_loop;
178             } else {
179                 c->state = BIO_CONN_S_OK;
180             }
181             break;
182
183         case BIO_CONN_S_BLOCKED_CONNECT:
184             i = BIO_sock_error(b->num);
185             if (i) {
186                 BIO_clear_retry_flags(b);
187                 ERR_raise_data(ERR_LIB_SYS, i,
188                                "calling connect(%s, %s)",
189                                 c->param_hostname, c->param_service);
190                 BIOerr(BIO_F_CONN_STATE, BIO_R_NBIO_CONNECT_ERROR);
191                 ret = 0;
192                 goto exit_loop;
193             } else
194                 c->state = BIO_CONN_S_OK;
195             break;
196
197         case BIO_CONN_S_OK:
198             ret = 1;
199             goto exit_loop;
200         default:
201             /* abort(); */
202             goto exit_loop;
203         }
204
205         if (cb != NULL) {
206             if ((ret = cb((BIO *)b, c->state, ret)) == 0)
207                 goto end;
208         }
209     }
210
211     /* Loop does not exit */
212  exit_loop:
213     if (cb != NULL)
214         ret = cb((BIO *)b, c->state, ret);
215  end:
216     return ret;
217 }
218
219 BIO_CONNECT *BIO_CONNECT_new(void)
220 {
221     BIO_CONNECT *ret;
222
223     if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) {
224         BIOerr(BIO_F_BIO_CONNECT_NEW, ERR_R_MALLOC_FAILURE);
225         return NULL;
226     }
227     ret->state = BIO_CONN_S_BEFORE;
228     ret->connect_family = BIO_FAMILY_IPANY;
229     return ret;
230 }
231
232 void BIO_CONNECT_free(BIO_CONNECT *a)
233 {
234     if (a == NULL)
235         return;
236     OPENSSL_free(a->param_hostname);
237     OPENSSL_free(a->param_service);
238     BIO_ADDRINFO_free(a->addr_first);
239     OPENSSL_free(a);
240 }
241
242 const BIO_METHOD *BIO_s_connect(void)
243 {
244     return &methods_connectp;
245 }
246
247 static int conn_new(BIO *bi)
248 {
249     bi->init = 0;
250     bi->num = (int)INVALID_SOCKET;
251     bi->flags = 0;
252     if ((bi->ptr = (char *)BIO_CONNECT_new()) == NULL)
253         return 0;
254     else
255         return 1;
256 }
257
258 static void conn_close_socket(BIO *bio)
259 {
260     BIO_CONNECT *c;
261
262     c = (BIO_CONNECT *)bio->ptr;
263     if (bio->num != (int)INVALID_SOCKET) {
264         /* Only do a shutdown if things were established */
265         if (c->state == BIO_CONN_S_OK)
266             shutdown(bio->num, 2);
267         BIO_closesocket(bio->num);
268         bio->num = (int)INVALID_SOCKET;
269     }
270 }
271
272 static int conn_free(BIO *a)
273 {
274     BIO_CONNECT *data;
275
276     if (a == NULL)
277         return 0;
278     data = (BIO_CONNECT *)a->ptr;
279
280     if (a->shutdown) {
281         conn_close_socket(a);
282         BIO_CONNECT_free(data);
283         a->ptr = NULL;
284         a->flags = 0;
285         a->init = 0;
286     }
287     return 1;
288 }
289
290 static int conn_read(BIO *b, char *out, int outl)
291 {
292     int ret = 0;
293     BIO_CONNECT *data;
294
295     data = (BIO_CONNECT *)b->ptr;
296     if (data->state != BIO_CONN_S_OK) {
297         ret = conn_state(b, data);
298         if (ret <= 0)
299             return ret;
300     }
301
302     if (out != NULL) {
303         clear_socket_error();
304         ret = readsocket(b->num, out, outl);
305         BIO_clear_retry_flags(b);
306         if (ret <= 0) {
307             if (BIO_sock_should_retry(ret))
308                 BIO_set_retry_read(b);
309         }
310     }
311     return ret;
312 }
313
314 static int conn_write(BIO *b, const char *in, int inl)
315 {
316     int ret;
317     BIO_CONNECT *data;
318
319     data = (BIO_CONNECT *)b->ptr;
320     if (data->state != BIO_CONN_S_OK) {
321         ret = conn_state(b, data);
322         if (ret <= 0)
323             return ret;
324     }
325
326     clear_socket_error();
327     ret = writesocket(b->num, in, inl);
328     BIO_clear_retry_flags(b);
329     if (ret <= 0) {
330         if (BIO_sock_should_retry(ret))
331             BIO_set_retry_write(b);
332     }
333     return ret;
334 }
335
336 static long conn_ctrl(BIO *b, int cmd, long num, void *ptr)
337 {
338     BIO *dbio;
339     int *ip;
340     const char **pptr = NULL;
341     long ret = 1;
342     BIO_CONNECT *data;
343
344     data = (BIO_CONNECT *)b->ptr;
345
346     switch (cmd) {
347     case BIO_CTRL_RESET:
348         ret = 0;
349         data->state = BIO_CONN_S_BEFORE;
350         conn_close_socket(b);
351         BIO_ADDRINFO_free(data->addr_first);
352         data->addr_first = NULL;
353         b->flags = 0;
354         break;
355     case BIO_C_DO_STATE_MACHINE:
356         /* use this one to start the connection */
357         if (data->state != BIO_CONN_S_OK)
358             ret = (long)conn_state(b, data);
359         else
360             ret = 1;
361         break;
362     case BIO_C_GET_CONNECT:
363         if (ptr != NULL) {
364             pptr = (const char **)ptr;
365             if (num == 0) {
366                 *pptr = data->param_hostname;
367             } else if (num == 1) {
368                 *pptr = data->param_service;
369             } else if (num == 2) {
370                 *pptr = (const char *)BIO_ADDRINFO_address(data->addr_iter);
371             } else if (num == 3) {
372                 switch (BIO_ADDRINFO_family(data->addr_iter)) {
373 # ifdef AF_INET6
374                 case AF_INET6:
375                     ret = BIO_FAMILY_IPV6;
376                     break;
377 # endif
378                 case AF_INET:
379                     ret = BIO_FAMILY_IPV4;
380                     break;
381                 case 0:
382                     ret = data->connect_family;
383                     break;
384                 default:
385                     ret = -1;
386                     break;
387                 }
388             } else {
389                 ret = 0;
390             }
391         } else {
392             ret = 0;
393         }
394         break;
395     case BIO_C_SET_CONNECT:
396         if (ptr != NULL) {
397             b->init = 1;
398             if (num == 0) {
399                 char *hold_service = data->param_service;
400                 /* We affect the hostname regardless.  However, the input
401                  * string might contain a host:service spec, so we must
402                  * parse it, which might or might not affect the service
403                  */
404                 OPENSSL_free(data->param_hostname);
405                 data->param_hostname = NULL;
406                 ret = BIO_parse_hostserv(ptr,
407                                          &data->param_hostname,
408                                          &data->param_service,
409                                          BIO_PARSE_PRIO_HOST);
410                 if (hold_service != data->param_service)
411                     OPENSSL_free(hold_service);
412             } else if (num == 1) {
413                 OPENSSL_free(data->param_service);
414                 data->param_service = BUF_strdup(ptr);
415             } else if (num == 2) {
416                 const BIO_ADDR *addr = (const BIO_ADDR *)ptr;
417                 if (ret) {
418                     data->param_hostname = BIO_ADDR_hostname_string(addr, 1);
419                     data->param_service = BIO_ADDR_service_string(addr, 1);
420                     BIO_ADDRINFO_free(data->addr_first);
421                     data->addr_first = NULL;
422                     data->addr_iter = NULL;
423                 }
424             } else if (num == 3) {
425                 data->connect_family = *(int *)ptr;
426             } else {
427                 ret = 0;
428             }
429         }
430         break;
431     case BIO_C_SET_NBIO:
432         if (num != 0)
433             data->connect_mode |= BIO_SOCK_NONBLOCK;
434         else
435             data->connect_mode &= ~BIO_SOCK_NONBLOCK;
436         break;
437     case BIO_C_SET_CONNECT_MODE:
438         data->connect_mode = (int)num;
439         break;
440     case BIO_C_GET_FD:
441         if (b->init) {
442             ip = (int *)ptr;
443             if (ip != NULL)
444                 *ip = b->num;
445             ret = b->num;
446         } else
447             ret = -1;
448         break;
449     case BIO_CTRL_GET_CLOSE:
450         ret = b->shutdown;
451         break;
452     case BIO_CTRL_SET_CLOSE:
453         b->shutdown = (int)num;
454         break;
455     case BIO_CTRL_PENDING:
456     case BIO_CTRL_WPENDING:
457         ret = 0;
458         break;
459     case BIO_CTRL_FLUSH:
460         break;
461     case BIO_CTRL_DUP:
462         {
463             dbio = (BIO *)ptr;
464             if (data->param_hostname)
465                 BIO_set_conn_hostname(dbio, data->param_hostname);
466             if (data->param_service)
467                 BIO_set_conn_port(dbio, data->param_service);
468             BIO_set_conn_ip_family(dbio, data->connect_family);
469             BIO_set_conn_mode(dbio, data->connect_mode);
470             /*
471              * FIXME: the cast of the function seems unlikely to be a good
472              * idea
473              */
474             (void)BIO_set_info_callback(dbio, data->info_callback);
475         }
476         break;
477     case BIO_CTRL_SET_CALLBACK:
478         ret = 0; /* use callback ctrl */
479         break;
480     case BIO_CTRL_GET_CALLBACK:
481         {
482             BIO_info_cb **fptr;
483
484             fptr = (BIO_info_cb **)ptr;
485             *fptr = data->info_callback;
486         }
487         break;
488     default:
489         ret = 0;
490         break;
491     }
492     return ret;
493 }
494
495 static long conn_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
496 {
497     long ret = 1;
498     BIO_CONNECT *data;
499
500     data = (BIO_CONNECT *)b->ptr;
501
502     switch (cmd) {
503     case BIO_CTRL_SET_CALLBACK:
504         {
505             data->info_callback = fp;
506         }
507         break;
508     default:
509         ret = 0;
510         break;
511     }
512     return ret;
513 }
514
515 static int conn_puts(BIO *bp, const char *str)
516 {
517     int n, ret;
518
519     n = strlen(str);
520     ret = conn_write(bp, str, n);
521     return ret;
522 }
523
524 BIO *BIO_new_connect(const char *str)
525 {
526     BIO *ret;
527
528     ret = BIO_new(BIO_s_connect());
529     if (ret == NULL)
530         return NULL;
531     if (BIO_set_conn_hostname(ret, str))
532         return ret;
533     BIO_free(ret);
534     return NULL;
535 }
536
537 #endif