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