]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/bio/bss_acpt.c
Replace FUNCerr with ERR_raise_data
[thirdparty/openssl.git] / crypto / bio / bss_acpt.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 #include "bio_lcl.h"
13
14 #ifndef OPENSSL_NO_SOCK
15
16 typedef struct bio_accept_st {
17 int state;
18 int accept_family;
19 int bind_mode; /* Socket mode for BIO_listen */
20 int accepted_mode; /* Socket mode for BIO_accept (set on accepted sock) */
21 char *param_addr;
22 char *param_serv;
23
24 int accept_sock;
25
26 BIO_ADDRINFO *addr_first;
27 const BIO_ADDRINFO *addr_iter;
28 BIO_ADDR cache_accepting_addr; /* Useful if we asked for port 0 */
29 char *cache_accepting_name, *cache_accepting_serv;
30 BIO_ADDR cache_peer_addr;
31 char *cache_peer_name, *cache_peer_serv;
32
33 BIO *bio_chain;
34 } BIO_ACCEPT;
35
36 static int acpt_write(BIO *h, const char *buf, int num);
37 static int acpt_read(BIO *h, char *buf, int size);
38 static int acpt_puts(BIO *h, const char *str);
39 static long acpt_ctrl(BIO *h, int cmd, long arg1, void *arg2);
40 static int acpt_new(BIO *h);
41 static int acpt_free(BIO *data);
42 static int acpt_state(BIO *b, BIO_ACCEPT *c);
43 static void acpt_close_socket(BIO *data);
44 static BIO_ACCEPT *BIO_ACCEPT_new(void);
45 static void BIO_ACCEPT_free(BIO_ACCEPT *a);
46
47 # define ACPT_S_BEFORE 1
48 # define ACPT_S_GET_ADDR 2
49 # define ACPT_S_CREATE_SOCKET 3
50 # define ACPT_S_LISTEN 4
51 # define ACPT_S_ACCEPT 5
52 # define ACPT_S_OK 6
53
54 static const BIO_METHOD methods_acceptp = {
55 BIO_TYPE_ACCEPT,
56 "socket accept",
57 /* TODO: Convert to new style write function */
58 bwrite_conv,
59 acpt_write,
60 /* TODO: Convert to new style read function */
61 bread_conv,
62 acpt_read,
63 acpt_puts,
64 NULL, /* connect_gets, */
65 acpt_ctrl,
66 acpt_new,
67 acpt_free,
68 NULL, /* connect_callback_ctrl */
69 };
70
71 const BIO_METHOD *BIO_s_accept(void)
72 {
73 return &methods_acceptp;
74 }
75
76 static int acpt_new(BIO *bi)
77 {
78 BIO_ACCEPT *ba;
79
80 bi->init = 0;
81 bi->num = (int)INVALID_SOCKET;
82 bi->flags = 0;
83 if ((ba = BIO_ACCEPT_new()) == NULL)
84 return 0;
85 bi->ptr = (char *)ba;
86 ba->state = ACPT_S_BEFORE;
87 bi->shutdown = 1;
88 return 1;
89 }
90
91 static BIO_ACCEPT *BIO_ACCEPT_new(void)
92 {
93 BIO_ACCEPT *ret;
94
95 if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) {
96 BIOerr(BIO_F_BIO_ACCEPT_NEW, ERR_R_MALLOC_FAILURE);
97 return NULL;
98 }
99 ret->accept_family = BIO_FAMILY_IPANY;
100 ret->accept_sock = (int)INVALID_SOCKET;
101 return ret;
102 }
103
104 static void BIO_ACCEPT_free(BIO_ACCEPT *a)
105 {
106 if (a == NULL)
107 return;
108 OPENSSL_free(a->param_addr);
109 OPENSSL_free(a->param_serv);
110 BIO_ADDRINFO_free(a->addr_first);
111 OPENSSL_free(a->cache_accepting_name);
112 OPENSSL_free(a->cache_accepting_serv);
113 OPENSSL_free(a->cache_peer_name);
114 OPENSSL_free(a->cache_peer_serv);
115 BIO_free(a->bio_chain);
116 OPENSSL_free(a);
117 }
118
119 static void acpt_close_socket(BIO *bio)
120 {
121 BIO_ACCEPT *c;
122
123 c = (BIO_ACCEPT *)bio->ptr;
124 if (c->accept_sock != (int)INVALID_SOCKET) {
125 shutdown(c->accept_sock, 2);
126 closesocket(c->accept_sock);
127 c->accept_sock = (int)INVALID_SOCKET;
128 bio->num = (int)INVALID_SOCKET;
129 }
130 }
131
132 static int acpt_free(BIO *a)
133 {
134 BIO_ACCEPT *data;
135
136 if (a == NULL)
137 return 0;
138 data = (BIO_ACCEPT *)a->ptr;
139
140 if (a->shutdown) {
141 acpt_close_socket(a);
142 BIO_ACCEPT_free(data);
143 a->ptr = NULL;
144 a->flags = 0;
145 a->init = 0;
146 }
147 return 1;
148 }
149
150 static int acpt_state(BIO *b, BIO_ACCEPT *c)
151 {
152 BIO *bio = NULL, *dbio;
153 int s = -1, ret = -1;
154
155 for (;;) {
156 switch (c->state) {
157 case ACPT_S_BEFORE:
158 if (c->param_addr == NULL && c->param_serv == NULL) {
159 BIOerr(BIO_F_ACPT_STATE, BIO_R_NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED);
160 ERR_add_error_data(4,
161 "hostname=", c->param_addr,
162 " service=", c->param_serv);
163 goto exit_loop;
164 }
165
166 /* Because we're starting a new bind, any cached name and serv
167 * are now obsolete and need to be cleaned out.
168 * QUESTION: should this be done in acpt_close_socket() instead?
169 */
170 OPENSSL_free(c->cache_accepting_name);
171 c->cache_accepting_name = NULL;
172 OPENSSL_free(c->cache_accepting_serv);
173 c->cache_accepting_serv = NULL;
174 OPENSSL_free(c->cache_peer_name);
175 c->cache_peer_name = NULL;
176 OPENSSL_free(c->cache_peer_serv);
177 c->cache_peer_serv = NULL;
178
179 c->state = ACPT_S_GET_ADDR;
180 break;
181
182 case ACPT_S_GET_ADDR:
183 {
184 int family = AF_UNSPEC;
185 switch (c->accept_family) {
186 case BIO_FAMILY_IPV6:
187 if (1) { /* This is a trick we use to avoid bit rot.
188 * at least the "else" part will always be
189 * compiled.
190 */
191 #ifdef AF_INET6
192 family = AF_INET6;
193 } else {
194 #endif
195 BIOerr(BIO_F_ACPT_STATE, BIO_R_UNAVAILABLE_IP_FAMILY);
196 goto exit_loop;
197 }
198 break;
199 case BIO_FAMILY_IPV4:
200 family = AF_INET;
201 break;
202 case BIO_FAMILY_IPANY:
203 family = AF_UNSPEC;
204 break;
205 default:
206 BIOerr(BIO_F_ACPT_STATE, BIO_R_UNSUPPORTED_IP_FAMILY);
207 goto exit_loop;
208 }
209 if (BIO_lookup(c->param_addr, c->param_serv, BIO_LOOKUP_SERVER,
210 family, SOCK_STREAM, &c->addr_first) == 0)
211 goto exit_loop;
212 }
213 if (c->addr_first == NULL) {
214 BIOerr(BIO_F_ACPT_STATE, BIO_R_LOOKUP_RETURNED_NOTHING);
215 goto exit_loop;
216 }
217 /* We're currently not iterating, but set this as preparation
218 * for possible future development in that regard
219 */
220 c->addr_iter = c->addr_first;
221 c->state = ACPT_S_CREATE_SOCKET;
222 break;
223
224 case ACPT_S_CREATE_SOCKET:
225 ret = BIO_socket(BIO_ADDRINFO_family(c->addr_iter),
226 BIO_ADDRINFO_socktype(c->addr_iter),
227 BIO_ADDRINFO_protocol(c->addr_iter), 0);
228 if (ret == (int)INVALID_SOCKET) {
229 ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
230 "calling socket(%s, %s)",
231 c->param_addr, c->param_serv);
232 BIOerr(BIO_F_ACPT_STATE, BIO_R_UNABLE_TO_CREATE_SOCKET);
233 goto exit_loop;
234 }
235 c->accept_sock = ret;
236 b->num = ret;
237 c->state = ACPT_S_LISTEN;
238 break;
239
240 case ACPT_S_LISTEN:
241 {
242 if (!BIO_listen(c->accept_sock,
243 BIO_ADDRINFO_address(c->addr_iter),
244 c->bind_mode)) {
245 BIO_closesocket(c->accept_sock);
246 goto exit_loop;
247 }
248 }
249
250 {
251 union BIO_sock_info_u info;
252
253 info.addr = &c->cache_accepting_addr;
254 if (!BIO_sock_info(c->accept_sock, BIO_SOCK_INFO_ADDRESS,
255 &info)) {
256 BIO_closesocket(c->accept_sock);
257 goto exit_loop;
258 }
259 }
260
261 c->cache_accepting_name =
262 BIO_ADDR_hostname_string(&c->cache_accepting_addr, 1);
263 c->cache_accepting_serv =
264 BIO_ADDR_service_string(&c->cache_accepting_addr, 1);
265 c->state = ACPT_S_ACCEPT;
266 s = -1;
267 ret = 1;
268 goto end;
269
270 case ACPT_S_ACCEPT:
271 if (b->next_bio != NULL) {
272 c->state = ACPT_S_OK;
273 break;
274 }
275 BIO_clear_retry_flags(b);
276 b->retry_reason = 0;
277
278 OPENSSL_free(c->cache_peer_name);
279 c->cache_peer_name = NULL;
280 OPENSSL_free(c->cache_peer_serv);
281 c->cache_peer_serv = NULL;
282
283 s = BIO_accept_ex(c->accept_sock, &c->cache_peer_addr,
284 c->accepted_mode);
285
286 /* If the returned socket is invalid, this might still be
287 * retryable
288 */
289 if (s < 0) {
290 if (BIO_sock_should_retry(s)) {
291 BIO_set_retry_special(b);
292 b->retry_reason = BIO_RR_ACCEPT;
293 goto end;
294 }
295 }
296
297 /* If it wasn't retryable, we fail */
298 if (s < 0) {
299 ret = s;
300 goto exit_loop;
301 }
302
303 bio = BIO_new_socket(s, BIO_CLOSE);
304 if (bio == NULL)
305 goto exit_loop;
306
307 BIO_set_callback(bio, BIO_get_callback(b));
308 BIO_set_callback_arg(bio, BIO_get_callback_arg(b));
309
310 /*
311 * If the accept BIO has an bio_chain, we dup it and put the new
312 * socket at the end.
313 */
314 if (c->bio_chain != NULL) {
315 if ((dbio = BIO_dup_chain(c->bio_chain)) == NULL)
316 goto exit_loop;
317 if (!BIO_push(dbio, bio))
318 goto exit_loop;
319 bio = dbio;
320 }
321 if (BIO_push(b, bio) == NULL)
322 goto exit_loop;
323
324 c->cache_peer_name =
325 BIO_ADDR_hostname_string(&c->cache_peer_addr, 1);
326 c->cache_peer_serv =
327 BIO_ADDR_service_string(&c->cache_peer_addr, 1);
328 c->state = ACPT_S_OK;
329 bio = NULL;
330 ret = 1;
331 goto end;
332
333 case ACPT_S_OK:
334 if (b->next_bio == NULL) {
335 c->state = ACPT_S_ACCEPT;
336 break;
337 }
338 ret = 1;
339 goto end;
340
341 default:
342 ret = 0;
343 goto end;
344 }
345 }
346
347 exit_loop:
348 if (bio != NULL)
349 BIO_free(bio);
350 else if (s >= 0)
351 BIO_closesocket(s);
352 end:
353 return ret;
354 }
355
356 static int acpt_read(BIO *b, char *out, int outl)
357 {
358 int ret = 0;
359 BIO_ACCEPT *data;
360
361 BIO_clear_retry_flags(b);
362 data = (BIO_ACCEPT *)b->ptr;
363
364 while (b->next_bio == NULL) {
365 ret = acpt_state(b, data);
366 if (ret <= 0)
367 return ret;
368 }
369
370 ret = BIO_read(b->next_bio, out, outl);
371 BIO_copy_next_retry(b);
372 return ret;
373 }
374
375 static int acpt_write(BIO *b, const char *in, int inl)
376 {
377 int ret;
378 BIO_ACCEPT *data;
379
380 BIO_clear_retry_flags(b);
381 data = (BIO_ACCEPT *)b->ptr;
382
383 while (b->next_bio == NULL) {
384 ret = acpt_state(b, data);
385 if (ret <= 0)
386 return ret;
387 }
388
389 ret = BIO_write(b->next_bio, in, inl);
390 BIO_copy_next_retry(b);
391 return ret;
392 }
393
394 static long acpt_ctrl(BIO *b, int cmd, long num, void *ptr)
395 {
396 int *ip;
397 long ret = 1;
398 BIO_ACCEPT *data;
399 char **pp;
400
401 data = (BIO_ACCEPT *)b->ptr;
402
403 switch (cmd) {
404 case BIO_CTRL_RESET:
405 ret = 0;
406 data->state = ACPT_S_BEFORE;
407 acpt_close_socket(b);
408 BIO_ADDRINFO_free(data->addr_first);
409 data->addr_first = NULL;
410 b->flags = 0;
411 break;
412 case BIO_C_DO_STATE_MACHINE:
413 /* use this one to start the connection */
414 ret = (long)acpt_state(b, data);
415 break;
416 case BIO_C_SET_ACCEPT:
417 if (ptr != NULL) {
418 if (num == 0) {
419 char *hold_serv = data->param_serv;
420 /* We affect the hostname regardless. However, the input
421 * string might contain a host:service spec, so we must
422 * parse it, which might or might not affect the service
423 */
424 OPENSSL_free(data->param_addr);
425 data->param_addr = NULL;
426 ret = BIO_parse_hostserv(ptr,
427 &data->param_addr,
428 &data->param_serv,
429 BIO_PARSE_PRIO_SERV);
430 if (hold_serv != data->param_serv)
431 OPENSSL_free(hold_serv);
432 b->init = 1;
433 } else if (num == 1) {
434 OPENSSL_free(data->param_serv);
435 data->param_serv = BUF_strdup(ptr);
436 b->init = 1;
437 } else if (num == 2) {
438 data->bind_mode |= BIO_SOCK_NONBLOCK;
439 } else if (num == 3) {
440 BIO_free(data->bio_chain);
441 data->bio_chain = (BIO *)ptr;
442 } else if (num == 4) {
443 data->accept_family = *(int *)ptr;
444 }
445 } else {
446 if (num == 2) {
447 data->bind_mode &= ~BIO_SOCK_NONBLOCK;
448 }
449 }
450 break;
451 case BIO_C_SET_NBIO:
452 if (num != 0)
453 data->accepted_mode |= BIO_SOCK_NONBLOCK;
454 else
455 data->accepted_mode &= ~BIO_SOCK_NONBLOCK;
456 break;
457 case BIO_C_SET_FD:
458 b->num = *((int *)ptr);
459 data->accept_sock = b->num;
460 data->state = ACPT_S_ACCEPT;
461 b->shutdown = (int)num;
462 b->init = 1;
463 break;
464 case BIO_C_GET_FD:
465 if (b->init) {
466 ip = (int *)ptr;
467 if (ip != NULL)
468 *ip = data->accept_sock;
469 ret = data->accept_sock;
470 } else
471 ret = -1;
472 break;
473 case BIO_C_GET_ACCEPT:
474 if (b->init) {
475 if (num == 0 && ptr != NULL) {
476 pp = (char **)ptr;
477 *pp = data->cache_accepting_name;
478 } else if (num == 1 && ptr != NULL) {
479 pp = (char **)ptr;
480 *pp = data->cache_accepting_serv;
481 } else if (num == 2 && ptr != NULL) {
482 pp = (char **)ptr;
483 *pp = data->cache_peer_name;
484 } else if (num == 3 && ptr != NULL) {
485 pp = (char **)ptr;
486 *pp = data->cache_peer_serv;
487 } else if (num == 4) {
488 switch (BIO_ADDRINFO_family(data->addr_iter)) {
489 #ifdef AF_INET6
490 case AF_INET6:
491 ret = BIO_FAMILY_IPV6;
492 break;
493 #endif
494 case AF_INET:
495 ret = BIO_FAMILY_IPV4;
496 break;
497 case 0:
498 ret = data->accept_family;
499 break;
500 default:
501 ret = -1;
502 break;
503 }
504 } else
505 ret = -1;
506 } else
507 ret = -1;
508 break;
509 case BIO_CTRL_GET_CLOSE:
510 ret = b->shutdown;
511 break;
512 case BIO_CTRL_SET_CLOSE:
513 b->shutdown = (int)num;
514 break;
515 case BIO_CTRL_PENDING:
516 case BIO_CTRL_WPENDING:
517 ret = 0;
518 break;
519 case BIO_CTRL_FLUSH:
520 break;
521 case BIO_C_SET_BIND_MODE:
522 data->bind_mode = (int)num;
523 break;
524 case BIO_C_GET_BIND_MODE:
525 ret = (long)data->bind_mode;
526 break;
527 case BIO_CTRL_DUP:
528 break;
529
530 default:
531 ret = 0;
532 break;
533 }
534 return ret;
535 }
536
537 static int acpt_puts(BIO *bp, const char *str)
538 {
539 int n, ret;
540
541 n = strlen(str);
542 ret = acpt_write(bp, str, n);
543 return ret;
544 }
545
546 BIO *BIO_new_accept(const char *str)
547 {
548 BIO *ret;
549
550 ret = BIO_new(BIO_s_accept());
551 if (ret == NULL)
552 return NULL;
553 if (BIO_set_accept_name(ret, str))
554 return ret;
555 BIO_free(ret);
556 return NULL;
557 }
558
559 #endif