Create BIO_write_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     /* 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,                       /* connect_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     int (*cb) (const BIO *, int, int) = 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                 SYSerr(SYS_F_SOCKET, get_last_socket_error());
142                 ERR_add_error_data(4,
143                                    "hostname=", c->param_hostname,
144                                    " service=", c->param_service);
145                 BIOerr(BIO_F_CONN_STATE, BIO_R_UNABLE_TO_CREATE_SOCKET);
146                 goto exit_loop;
147             }
148             b->num = ret;
149             c->state = BIO_CONN_S_CONNECT;
150             break;
151
152         case BIO_CONN_S_CONNECT:
153             BIO_clear_retry_flags(b);
154             ret = BIO_connect(b->num, BIO_ADDRINFO_address(c->addr_iter),
155                               BIO_SOCK_KEEPALIVE | c->connect_mode);
156             b->retry_reason = 0;
157             if (ret == 0) {
158                 if (BIO_sock_should_retry(ret)) {
159                     BIO_set_retry_special(b);
160                     c->state = BIO_CONN_S_BLOCKED_CONNECT;
161                     b->retry_reason = BIO_RR_CONNECT;
162                     ERR_clear_error();
163                 } else if ((c->addr_iter = BIO_ADDRINFO_next(c->addr_iter))
164                            != NULL) {
165                     /*
166                      * if there are more addresses to try, do that first
167                      */
168                     BIO_closesocket(b->num);
169                     c->state = BIO_CONN_S_CREATE_SOCKET;
170                     ERR_clear_error();
171                     break;
172                 } else {
173                     SYSerr(SYS_F_CONNECT, get_last_socket_error());
174                     ERR_add_error_data(4,
175                                        "hostname=", c->param_hostname,
176                                        " service=", c->param_service);
177                     BIOerr(BIO_F_CONN_STATE, BIO_R_CONNECT_ERROR);
178                 }
179                 goto exit_loop;
180             } else {
181                 c->state = BIO_CONN_S_OK;
182             }
183             break;
184
185         case BIO_CONN_S_BLOCKED_CONNECT:
186             i = BIO_sock_error(b->num);
187             if (i) {
188                 BIO_clear_retry_flags(b);
189                 SYSerr(SYS_F_CONNECT, i);
190                 ERR_add_error_data(4,
191                                    "hostname=", c->param_hostname,
192                                    " service=", c->param_service);
193                 BIOerr(BIO_F_CONN_STATE, BIO_R_NBIO_CONNECT_ERROR);
194                 ret = 0;
195                 goto exit_loop;
196             } else
197                 c->state = BIO_CONN_S_OK;
198             break;
199
200         case BIO_CONN_S_OK:
201             ret = 1;
202             goto exit_loop;
203         default:
204             /* abort(); */
205             goto exit_loop;
206         }
207
208         if (cb != NULL) {
209             if ((ret = cb((BIO *)b, c->state, ret)) == 0)
210                 goto end;
211         }
212     }
213
214     /* Loop does not exit */
215  exit_loop:
216     if (cb != NULL)
217         ret = cb((BIO *)b, c->state, ret);
218  end:
219     return (ret);
220 }
221
222 BIO_CONNECT *BIO_CONNECT_new(void)
223 {
224     BIO_CONNECT *ret;
225
226     if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL)
227         return (NULL);
228     ret->state = BIO_CONN_S_BEFORE;
229     ret->connect_family = BIO_FAMILY_IPANY;
230     return (ret);
231 }
232
233 void BIO_CONNECT_free(BIO_CONNECT *a)
234 {
235     if (a == NULL)
236         return;
237
238     OPENSSL_free(a->param_hostname);
239     OPENSSL_free(a->param_service);
240     BIO_ADDRINFO_free(a->addr_first);
241     OPENSSL_free(a);
242 }
243
244 const BIO_METHOD *BIO_s_connect(void)
245 {
246     return (&methods_connectp);
247 }
248
249 static int conn_new(BIO *bi)
250 {
251     bi->init = 0;
252     bi->num = (int)INVALID_SOCKET;
253     bi->flags = 0;
254     if ((bi->ptr = (char *)BIO_CONNECT_new()) == NULL)
255         return (0);
256     else
257         return (1);
258 }
259
260 static void conn_close_socket(BIO *bio)
261 {
262     BIO_CONNECT *c;
263
264     c = (BIO_CONNECT *)bio->ptr;
265     if (bio->num != (int)INVALID_SOCKET) {
266         /* Only do a shutdown if things were established */
267         if (c->state == BIO_CONN_S_OK)
268             shutdown(bio->num, 2);
269         BIO_closesocket(bio->num);
270         bio->num = (int)INVALID_SOCKET;
271     }
272 }
273
274 static int conn_free(BIO *a)
275 {
276     BIO_CONNECT *data;
277
278     if (a == NULL)
279         return (0);
280     data = (BIO_CONNECT *)a->ptr;
281
282     if (a->shutdown) {
283         conn_close_socket(a);
284         BIO_CONNECT_free(data);
285         a->ptr = NULL;
286         a->flags = 0;
287         a->init = 0;
288     }
289     return (1);
290 }
291
292 static int conn_read(BIO *b, char *out, int outl)
293 {
294     int ret = 0;
295     BIO_CONNECT *data;
296
297     data = (BIO_CONNECT *)b->ptr;
298     if (data->state != BIO_CONN_S_OK) {
299         ret = conn_state(b, data);
300         if (ret <= 0)
301             return (ret);
302     }
303
304     if (out != NULL) {
305         clear_socket_error();
306         ret = readsocket(b->num, out, outl);
307         BIO_clear_retry_flags(b);
308         if (ret <= 0) {
309             if (BIO_sock_should_retry(ret))
310                 BIO_set_retry_read(b);
311         }
312     }
313     return (ret);
314 }
315
316 static int conn_write(BIO *b, const char *in, int inl)
317 {
318     int ret;
319     BIO_CONNECT *data;
320
321     data = (BIO_CONNECT *)b->ptr;
322     if (data->state != BIO_CONN_S_OK) {
323         ret = conn_state(b, data);
324         if (ret <= 0)
325             return (ret);
326     }
327
328     clear_socket_error();
329     ret = writesocket(b->num, in, inl);
330     BIO_clear_retry_flags(b);
331     if (ret <= 0) {
332         if (BIO_sock_should_retry(ret))
333             BIO_set_retry_write(b);
334     }
335     return (ret);
336 }
337
338 static long conn_ctrl(BIO *b, int cmd, long num, void *ptr)
339 {
340     BIO *dbio;
341     int *ip;
342     const char **pptr = NULL;
343     long ret = 1;
344     BIO_CONNECT *data;
345
346     data = (BIO_CONNECT *)b->ptr;
347
348     switch (cmd) {
349     case BIO_CTRL_RESET:
350         ret = 0;
351         data->state = BIO_CONN_S_BEFORE;
352         conn_close_socket(b);
353         BIO_ADDRINFO_free(data->addr_first);
354         data->addr_first = NULL;
355         b->flags = 0;
356         break;
357     case BIO_C_DO_STATE_MACHINE:
358         /* use this one to start the connection */
359         if (data->state != BIO_CONN_S_OK)
360             ret = (long)conn_state(b, data);
361         else
362             ret = 1;
363         break;
364     case BIO_C_GET_CONNECT:
365         if (ptr != NULL) {
366             pptr = (const char **)ptr;
367             if (num == 0) {
368                 *pptr = data->param_hostname;
369             } else if (num == 1) {
370                 *pptr = data->param_service;
371             } else if (num == 2) {
372                 *pptr = (const char *)BIO_ADDRINFO_address(data->addr_iter);
373             } else if (num == 3) {
374                 switch (BIO_ADDRINFO_family(data->addr_iter)) {
375 # ifdef AF_INET6
376                 case AF_INET6:
377                     ret = BIO_FAMILY_IPV6;
378                     break;
379 # endif
380                 case AF_INET:
381                     ret = BIO_FAMILY_IPV4;
382                     break;
383                 case 0:
384                     ret = data->connect_family;
385                     break;
386                 default:
387                     ret = -1;
388                     break;
389                 }
390             } else {
391                 ret = 0;
392             }
393         } else {
394             ret = 0;
395         }
396         break;
397     case BIO_C_SET_CONNECT:
398         if (ptr != NULL) {
399             b->init = 1;
400             if (num == 0) {
401                 char *hold_service = data->param_service;
402                 /* We affect the hostname regardless.  However, the input
403                  * string might contain a host:service spec, so we must
404                  * parse it, which might or might not affect the service
405                  */
406                 OPENSSL_free(data->param_hostname);
407                 data->param_hostname = NULL;
408                 ret = BIO_parse_hostserv(ptr,
409                                          &data->param_hostname,
410                                          &data->param_service,
411                                          BIO_PARSE_PRIO_HOST);
412                 if (hold_service != data->param_service)
413                     OPENSSL_free(hold_service);
414             } else if (num == 1) {
415                 OPENSSL_free(data->param_service);
416                 data->param_service = BUF_strdup(ptr);
417             } else if (num == 2) {
418                 const BIO_ADDR *addr = (const BIO_ADDR *)ptr;
419                 if (ret) {
420                     data->param_hostname = BIO_ADDR_hostname_string(addr, 1);
421                     data->param_service = BIO_ADDR_service_string(addr, 1);
422                     BIO_ADDRINFO_free(data->addr_first);
423                     data->addr_first = NULL;
424                     data->addr_iter = NULL;
425                 }
426             } else if (num == 3) {
427                 data->connect_family = *(int *)ptr;
428             } else {
429                 ret = 0;
430             }
431         }
432         break;
433     case BIO_C_SET_NBIO:
434         if (num != 0)
435             data->connect_mode |= BIO_SOCK_NONBLOCK;
436         else
437             data->connect_mode &= ~BIO_SOCK_NONBLOCK;
438         break;
439     case BIO_C_SET_CONNECT_MODE:
440         data->connect_mode = (int)num;
441         break;
442     case BIO_C_GET_FD:
443         if (b->init) {
444             ip = (int *)ptr;
445             if (ip != NULL)
446                 *ip = b->num;
447             ret = b->num;
448         } else
449             ret = -1;
450         break;
451     case BIO_CTRL_GET_CLOSE:
452         ret = b->shutdown;
453         break;
454     case BIO_CTRL_SET_CLOSE:
455         b->shutdown = (int)num;
456         break;
457     case BIO_CTRL_PENDING:
458     case BIO_CTRL_WPENDING:
459         ret = 0;
460         break;
461     case BIO_CTRL_FLUSH:
462         break;
463     case BIO_CTRL_DUP:
464         {
465             dbio = (BIO *)ptr;
466             if (data->param_hostname)
467                 BIO_set_conn_hostname(dbio, data->param_hostname);
468             if (data->param_service)
469                 BIO_set_conn_port(dbio, data->param_service);
470             BIO_set_conn_ip_family(dbio, data->connect_family);
471             BIO_set_conn_mode(dbio, data->connect_mode);
472             /*
473              * FIXME: the cast of the function seems unlikely to be a good
474              * idea
475              */
476             (void)BIO_set_info_callback(dbio,
477                                         (bio_info_cb *)data->info_callback);
478         }
479         break;
480     case BIO_CTRL_SET_CALLBACK:
481         {
482 # if 0                          /* FIXME: Should this be used? -- Richard
483                                  * Levitte */
484             BIOerr(BIO_F_CONN_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
485             ret = -1;
486 # else
487             ret = 0;
488 # endif
489         }
490         break;
491     case BIO_CTRL_GET_CALLBACK:
492         {
493             int (**fptr) (const BIO *bio, int state, int xret);
494
495             fptr = (int (**)(const BIO *bio, int state, int xret))ptr;
496             *fptr = data->info_callback;
497         }
498         break;
499     default:
500         ret = 0;
501         break;
502     }
503     return (ret);
504 }
505
506 static long conn_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
507 {
508     long ret = 1;
509     BIO_CONNECT *data;
510
511     data = (BIO_CONNECT *)b->ptr;
512
513     switch (cmd) {
514     case BIO_CTRL_SET_CALLBACK:
515         {
516             data->info_callback =
517                 (int (*)(const struct bio_st *, int, int))fp;
518         }
519         break;
520     default:
521         ret = 0;
522         break;
523     }
524     return (ret);
525 }
526
527 static int conn_puts(BIO *bp, const char *str)
528 {
529     int n, ret;
530
531     n = strlen(str);
532     ret = conn_write(bp, str, n);
533     return (ret);
534 }
535
536 BIO *BIO_new_connect(const char *str)
537 {
538     BIO *ret;
539
540     ret = BIO_new(BIO_s_connect());
541     if (ret == NULL)
542         return (NULL);
543     if (BIO_set_conn_hostname(ret, str))
544         return (ret);
545     BIO_free(ret);
546     return (NULL);
547 }
548
549 #endif