key zeroisation fix for p12
[openssl.git] / crypto / bio / bss_conn.c
1 /*
2  * Copyright 1995-2018 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     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                 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         BIOerr(BIO_F_BIO_CONNECT_NEW, ERR_R_MALLOC_FAILURE);
228         return NULL;
229     }
230     ret->state = BIO_CONN_S_BEFORE;
231     ret->connect_family = BIO_FAMILY_IPANY;
232     return ret;
233 }
234
235 void BIO_CONNECT_free(BIO_CONNECT *a)
236 {
237     if (a == NULL)
238         return;
239     OPENSSL_free(a->param_hostname);
240     OPENSSL_free(a->param_service);
241     BIO_ADDRINFO_free(a->addr_first);
242     OPENSSL_free(a);
243 }
244
245 const BIO_METHOD *BIO_s_connect(void)
246 {
247     return &methods_connectp;
248 }
249
250 static int conn_new(BIO *bi)
251 {
252     bi->init = 0;
253     bi->num = (int)INVALID_SOCKET;
254     bi->flags = 0;
255     if ((bi->ptr = (char *)BIO_CONNECT_new()) == NULL)
256         return 0;
257     else
258         return 1;
259 }
260
261 static void conn_close_socket(BIO *bio)
262 {
263     BIO_CONNECT *c;
264
265     c = (BIO_CONNECT *)bio->ptr;
266     if (bio->num != (int)INVALID_SOCKET) {
267         /* Only do a shutdown if things were established */
268         if (c->state == BIO_CONN_S_OK)
269             shutdown(bio->num, 2);
270         BIO_closesocket(bio->num);
271         bio->num = (int)INVALID_SOCKET;
272     }
273 }
274
275 static int conn_free(BIO *a)
276 {
277     BIO_CONNECT *data;
278
279     if (a == NULL)
280         return 0;
281     data = (BIO_CONNECT *)a->ptr;
282
283     if (a->shutdown) {
284         conn_close_socket(a);
285         BIO_CONNECT_free(data);
286         a->ptr = NULL;
287         a->flags = 0;
288         a->init = 0;
289     }
290     return 1;
291 }
292
293 static int conn_read(BIO *b, char *out, int outl)
294 {
295     int ret = 0;
296     BIO_CONNECT *data;
297
298     data = (BIO_CONNECT *)b->ptr;
299     if (data->state != BIO_CONN_S_OK) {
300         ret = conn_state(b, data);
301         if (ret <= 0)
302             return ret;
303     }
304
305     if (out != NULL) {
306         clear_socket_error();
307         ret = readsocket(b->num, out, outl);
308         BIO_clear_retry_flags(b);
309         if (ret <= 0) {
310             if (BIO_sock_should_retry(ret))
311                 BIO_set_retry_read(b);
312         }
313     }
314     return ret;
315 }
316
317 static int conn_write(BIO *b, const char *in, int inl)
318 {
319     int ret;
320     BIO_CONNECT *data;
321
322     data = (BIO_CONNECT *)b->ptr;
323     if (data->state != BIO_CONN_S_OK) {
324         ret = conn_state(b, data);
325         if (ret <= 0)
326             return ret;
327     }
328
329     clear_socket_error();
330     ret = writesocket(b->num, in, inl);
331     BIO_clear_retry_flags(b);
332     if (ret <= 0) {
333         if (BIO_sock_should_retry(ret))
334             BIO_set_retry_write(b);
335     }
336     return ret;
337 }
338
339 static long conn_ctrl(BIO *b, int cmd, long num, void *ptr)
340 {
341     BIO *dbio;
342     int *ip;
343     const char **pptr = NULL;
344     long ret = 1;
345     BIO_CONNECT *data;
346
347     data = (BIO_CONNECT *)b->ptr;
348
349     switch (cmd) {
350     case BIO_CTRL_RESET:
351         ret = 0;
352         data->state = BIO_CONN_S_BEFORE;
353         conn_close_socket(b);
354         BIO_ADDRINFO_free(data->addr_first);
355         data->addr_first = NULL;
356         b->flags = 0;
357         break;
358     case BIO_C_DO_STATE_MACHINE:
359         /* use this one to start the connection */
360         if (data->state != BIO_CONN_S_OK)
361             ret = (long)conn_state(b, data);
362         else
363             ret = 1;
364         break;
365     case BIO_C_GET_CONNECT:
366         if (ptr != NULL) {
367             pptr = (const char **)ptr;
368             if (num == 0) {
369                 *pptr = data->param_hostname;
370             } else if (num == 1) {
371                 *pptr = data->param_service;
372             } else if (num == 2) {
373                 *pptr = (const char *)BIO_ADDRINFO_address(data->addr_iter);
374             } else if (num == 3) {
375                 switch (BIO_ADDRINFO_family(data->addr_iter)) {
376 # ifdef AF_INET6
377                 case AF_INET6:
378                     ret = BIO_FAMILY_IPV6;
379                     break;
380 # endif
381                 case AF_INET:
382                     ret = BIO_FAMILY_IPV4;
383                     break;
384                 case 0:
385                     ret = data->connect_family;
386                     break;
387                 default:
388                     ret = -1;
389                     break;
390                 }
391             } else {
392                 ret = 0;
393             }
394         } else {
395             ret = 0;
396         }
397         break;
398     case BIO_C_SET_CONNECT:
399         if (ptr != NULL) {
400             b->init = 1;
401             if (num == 0) {
402                 char *hold_service = data->param_service;
403                 /* We affect the hostname regardless.  However, the input
404                  * string might contain a host:service spec, so we must
405                  * parse it, which might or might not affect the service
406                  */
407                 OPENSSL_free(data->param_hostname);
408                 data->param_hostname = NULL;
409                 ret = BIO_parse_hostserv(ptr,
410                                          &data->param_hostname,
411                                          &data->param_service,
412                                          BIO_PARSE_PRIO_HOST);
413                 if (hold_service != data->param_service)
414                     OPENSSL_free(hold_service);
415             } else if (num == 1) {
416                 OPENSSL_free(data->param_service);
417                 data->param_service = BUF_strdup(ptr);
418             } else if (num == 2) {
419                 const BIO_ADDR *addr = (const BIO_ADDR *)ptr;
420                 if (ret) {
421                     data->param_hostname = BIO_ADDR_hostname_string(addr, 1);
422                     data->param_service = BIO_ADDR_service_string(addr, 1);
423                     BIO_ADDRINFO_free(data->addr_first);
424                     data->addr_first = NULL;
425                     data->addr_iter = NULL;
426                 }
427             } else if (num == 3) {
428                 data->connect_family = *(int *)ptr;
429             } else {
430                 ret = 0;
431             }
432         }
433         break;
434     case BIO_C_SET_NBIO:
435         if (num != 0)
436             data->connect_mode |= BIO_SOCK_NONBLOCK;
437         else
438             data->connect_mode &= ~BIO_SOCK_NONBLOCK;
439         break;
440     case BIO_C_SET_CONNECT_MODE:
441         data->connect_mode = (int)num;
442         break;
443     case BIO_C_GET_FD:
444         if (b->init) {
445             ip = (int *)ptr;
446             if (ip != NULL)
447                 *ip = b->num;
448             ret = b->num;
449         } else
450             ret = -1;
451         break;
452     case BIO_CTRL_GET_CLOSE:
453         ret = b->shutdown;
454         break;
455     case BIO_CTRL_SET_CLOSE:
456         b->shutdown = (int)num;
457         break;
458     case BIO_CTRL_PENDING:
459     case BIO_CTRL_WPENDING:
460         ret = 0;
461         break;
462     case BIO_CTRL_FLUSH:
463         break;
464     case BIO_CTRL_DUP:
465         {
466             dbio = (BIO *)ptr;
467             if (data->param_hostname)
468                 BIO_set_conn_hostname(dbio, data->param_hostname);
469             if (data->param_service)
470                 BIO_set_conn_port(dbio, data->param_service);
471             BIO_set_conn_ip_family(dbio, data->connect_family);
472             BIO_set_conn_mode(dbio, data->connect_mode);
473             /*
474              * FIXME: the cast of the function seems unlikely to be a good
475              * idea
476              */
477             (void)BIO_set_info_callback(dbio, data->info_callback);
478         }
479         break;
480     case BIO_CTRL_SET_CALLBACK:
481         ret = 0; /* use callback ctrl */
482         break;
483     case BIO_CTRL_GET_CALLBACK:
484         {
485             BIO_info_cb **fptr;
486
487             fptr = (BIO_info_cb **)ptr;
488             *fptr = data->info_callback;
489         }
490         break;
491     default:
492         ret = 0;
493         break;
494     }
495     return ret;
496 }
497
498 static long conn_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
499 {
500     long ret = 1;
501     BIO_CONNECT *data;
502
503     data = (BIO_CONNECT *)b->ptr;
504
505     switch (cmd) {
506     case BIO_CTRL_SET_CALLBACK:
507         {
508             data->info_callback = fp;
509         }
510         break;
511     default:
512         ret = 0;
513         break;
514     }
515     return ret;
516 }
517
518 static int conn_puts(BIO *bp, const char *str)
519 {
520     int n, ret;
521
522     n = strlen(str);
523     ret = conn_write(bp, str, n);
524     return ret;
525 }
526
527 BIO *BIO_new_connect(const char *str)
528 {
529     BIO *ret;
530
531     ret = BIO_new(BIO_s_connect());
532     if (ret == NULL)
533         return NULL;
534     if (BIO_set_conn_hostname(ret, str))
535         return ret;
536     BIO_free(ret);
537     return NULL;
538 }
539
540 #endif