Create BIO_read_ex() which handles size_t arguments
[openssl.git] / crypto / bio / bss_conn.c
1 /*
2  * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (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     int (*info_callback) (const BIO *bio, int state, int ret);
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     conn_write,
62     /* TODO: Convert to new style read function */
63     bread_conv,
64     conn_read,
65     conn_puts,
66     NULL,                       /* connect_gets, */
67     conn_ctrl,
68     conn_new,
69     conn_free,
70     conn_callback_ctrl,
71 };
72
73 static int conn_state(BIO *b, BIO_CONNECT *c)
74 {
75     int ret = -1, i;
76     int (*cb) (const BIO *, int, int) = NULL;
77
78     if (c->info_callback != NULL)
79         cb = c->info_callback;
80
81     for (;;) {
82         switch (c->state) {
83         case BIO_CONN_S_BEFORE:
84             if (c->param_hostname == NULL && c->param_service == NULL) {
85                 BIOerr(BIO_F_CONN_STATE, BIO_R_NO_HOSTNAME_OR_SERVICE_SPECIFIED);
86                 ERR_add_error_data(4,
87                                    "hostname=", c->param_hostname,
88                                    " service=", c->param_service);
89                 goto exit_loop;
90             }
91             c->state = BIO_CONN_S_GET_ADDR;
92             break;
93
94         case BIO_CONN_S_GET_ADDR:
95             {
96                 int family = AF_UNSPEC;
97                 switch (c->connect_family) {
98                 case BIO_FAMILY_IPV6:
99                     if (1) { /* This is a trick we use to avoid bit rot.
100                               * at least the "else" part will always be
101                               * compiled.
102                               */
103 #ifdef AF_INET6
104                         family = AF_INET6;
105                     } else {
106 #endif
107                         BIOerr(BIO_F_CONN_STATE, BIO_R_UNAVAILABLE_IP_FAMILY);
108                         goto exit_loop;
109                     }
110                     break;
111                 case BIO_FAMILY_IPV4:
112                     family = AF_INET;
113                     break;
114                 case BIO_FAMILY_IPANY:
115                     family = AF_UNSPEC;
116                     break;
117                 default:
118                     BIOerr(BIO_F_CONN_STATE, BIO_R_UNSUPPORTED_IP_FAMILY);
119                     goto exit_loop;
120                 }
121                 if (BIO_lookup(c->param_hostname, c->param_service,
122                                BIO_LOOKUP_CLIENT,
123                                family, SOCK_STREAM, &c->addr_first) == 0)
124                     goto exit_loop;
125             }
126             if (c->addr_first == NULL) {
127                 BIOerr(BIO_F_CONN_STATE, BIO_R_LOOKUP_RETURNED_NOTHING);
128                 goto exit_loop;
129             }
130             c->addr_iter = c->addr_first;
131             c->state = BIO_CONN_S_CREATE_SOCKET;
132             break;
133
134         case BIO_CONN_S_CREATE_SOCKET:
135             ret = BIO_socket(BIO_ADDRINFO_family(c->addr_iter),
136                              BIO_ADDRINFO_socktype(c->addr_iter),
137                              BIO_ADDRINFO_protocol(c->addr_iter), 0);
138             if (ret == (int)INVALID_SOCKET) {
139                 SYSerr(SYS_F_SOCKET, get_last_socket_error());
140                 ERR_add_error_data(4,
141                                    "hostname=", c->param_hostname,
142                                    " service=", c->param_service);
143                 BIOerr(BIO_F_CONN_STATE, BIO_R_UNABLE_TO_CREATE_SOCKET);
144                 goto exit_loop;
145             }
146             b->num = ret;
147             c->state = BIO_CONN_S_CONNECT;
148             break;
149
150         case BIO_CONN_S_CONNECT:
151             BIO_clear_retry_flags(b);
152             ret = BIO_connect(b->num, BIO_ADDRINFO_address(c->addr_iter),
153                               BIO_SOCK_KEEPALIVE | c->connect_mode);
154             b->retry_reason = 0;
155             if (ret == 0) {
156                 if (BIO_sock_should_retry(ret)) {
157                     BIO_set_retry_special(b);
158                     c->state = BIO_CONN_S_BLOCKED_CONNECT;
159                     b->retry_reason = BIO_RR_CONNECT;
160                     ERR_clear_error();
161                 } else if ((c->addr_iter = BIO_ADDRINFO_next(c->addr_iter))
162                            != NULL) {
163                     /*
164                      * if there are more addresses to try, do that first
165                      */
166                     BIO_closesocket(b->num);
167                     c->state = BIO_CONN_S_CREATE_SOCKET;
168                     ERR_clear_error();
169                     break;
170                 } else {
171                     SYSerr(SYS_F_CONNECT, get_last_socket_error());
172                     ERR_add_error_data(4,
173                                        "hostname=", c->param_hostname,
174                                        " service=", 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                 SYSerr(SYS_F_CONNECT, i);
188                 ERR_add_error_data(4,
189                                    "hostname=", c->param_hostname,
190                                    " service=", c->param_service);
191                 BIOerr(BIO_F_CONN_STATE, BIO_R_NBIO_CONNECT_ERROR);
192                 ret = 0;
193                 goto exit_loop;
194             } else
195                 c->state = BIO_CONN_S_OK;
196             break;
197
198         case BIO_CONN_S_OK:
199             ret = 1;
200             goto exit_loop;
201         default:
202             /* abort(); */
203             goto exit_loop;
204         }
205
206         if (cb != NULL) {
207             if ((ret = cb((BIO *)b, c->state, ret)) == 0)
208                 goto end;
209         }
210     }
211
212     /* Loop does not exit */
213  exit_loop:
214     if (cb != NULL)
215         ret = cb((BIO *)b, c->state, ret);
216  end:
217     return (ret);
218 }
219
220 BIO_CONNECT *BIO_CONNECT_new(void)
221 {
222     BIO_CONNECT *ret;
223
224     if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL)
225         return (NULL);
226     ret->state = BIO_CONN_S_BEFORE;
227     ret->connect_family = BIO_FAMILY_IPANY;
228     return (ret);
229 }
230
231 void BIO_CONNECT_free(BIO_CONNECT *a)
232 {
233     if (a == NULL)
234         return;
235
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,
475                                         (bio_info_cb *)data->info_callback);
476         }
477         break;
478     case BIO_CTRL_SET_CALLBACK:
479         {
480 # if 0                          /* FIXME: Should this be used? -- Richard
481                                  * Levitte */
482             BIOerr(BIO_F_CONN_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
483             ret = -1;
484 # else
485             ret = 0;
486 # endif
487         }
488         break;
489     case BIO_CTRL_GET_CALLBACK:
490         {
491             int (**fptr) (const BIO *bio, int state, int xret);
492
493             fptr = (int (**)(const BIO *bio, int state, int xret))ptr;
494             *fptr = data->info_callback;
495         }
496         break;
497     default:
498         ret = 0;
499         break;
500     }
501     return (ret);
502 }
503
504 static long conn_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
505 {
506     long ret = 1;
507     BIO_CONNECT *data;
508
509     data = (BIO_CONNECT *)b->ptr;
510
511     switch (cmd) {
512     case BIO_CTRL_SET_CALLBACK:
513         {
514             data->info_callback =
515                 (int (*)(const struct bio_st *, int, int))fp;
516         }
517         break;
518     default:
519         ret = 0;
520         break;
521     }
522     return (ret);
523 }
524
525 static int conn_puts(BIO *bp, const char *str)
526 {
527     int n, ret;
528
529     n = strlen(str);
530     ret = conn_write(bp, str, n);
531     return (ret);
532 }
533
534 BIO *BIO_new_connect(const char *str)
535 {
536     BIO *ret;
537
538     ret = BIO_new(BIO_s_connect());
539     if (ret == NULL)
540         return (NULL);
541     if (BIO_set_conn_hostname(ret, str))
542         return (ret);
543     BIO_free(ret);
544     return (NULL);
545 }
546
547 #endif