static int acpt_state(BIO *b, BIO_ACCEPT *c) { BIO *bio = NULL, *dbio; int s = -1; int i; again: switch (c->state) { case ACPT_S_BEFORE: if (c->param_addr == NULL) { BIOerr(BIO_F_ACPT_STATE, BIO_R_NO_ACCEPT_PORT_SPECIFIED); return (-1); } s = BIO_get_accept_socket(c->param_addr, c->bind_mode); if (s == INVALID_SOCKET) return (-1); if (c->accept_nbio) { if (!BIO_socket_nbio(s, 1)) { closesocket(s); BIOerr(BIO_F_ACPT_STATE, BIO_R_ERROR_SETTING_NBIO_ON_ACCEPT_SOCKET); return (-1); } } c->accept_sock = s; b->num = s; c->state = ACPT_S_GET_ACCEPT_SOCKET; return (1); /* break; */ case ACPT_S_GET_ACCEPT_SOCKET: if (b->next_bio != NULL) { c->state = ACPT_S_OK; goto again; } BIO_clear_retry_flags(b); b->retry_reason = 0; i = BIO_accept(c->accept_sock, &(c->addr)); /* -2 return means we should retry */ if (i == -2) { BIO_set_retry_special(b); b->retry_reason = BIO_RR_ACCEPT; return -1; } if (i < 0) return (i); bio = BIO_new_socket(i, BIO_CLOSE); if (bio == NULL) goto err; BIO_set_callback(bio, BIO_get_callback(b)); BIO_set_callback_arg(bio, BIO_get_callback_arg(b)); if (c->nbio) { if (!BIO_socket_nbio(i, 1)) { BIOerr(BIO_F_ACPT_STATE, BIO_R_ERROR_SETTING_NBIO_ON_ACCEPTED_SOCKET); goto err; } } /* * If the accept BIO has an bio_chain, we dup it and put the new * socket at the end. */ if (c->bio_chain != NULL) { if ((dbio = BIO_dup_chain(c->bio_chain)) == NULL) goto err; if (!BIO_push(dbio, bio)) goto err; bio = dbio; } if (BIO_push(b, bio) == NULL) goto err; c->state = ACPT_S_OK; return (1); err: if (bio != NULL) BIO_free(bio); else if (s >= 0) closesocket(s); return (0); /* break; */ case ACPT_S_OK: if (b->next_bio == NULL) { c->state = ACPT_S_GET_ACCEPT_SOCKET; goto again; } return (1); /* break; */ default: return (0); /* break; */ } }
static int decryptd(int argc, char *argv[]) { const char *hp = DEO_SOCKET; const char *tlsfile = NULL; const char *encfile = NULL; const char *decdir = NULL; int ret = EXIT_FAILURE; AUTO(ctx, ctx); int lfds = 0; int sock = 0; signal(SIGINT, on_signal); signal(SIGQUIT, on_signal); signal(SIGTERM, on_signal); signal(SIGUSR1, on_signal); signal(SIGUSR2, on_signal); if (!deo_getopt(argc, argv, "ht:e:d:l:", "", NULL, NULL, option, &tlsfile, option, &encfile, option, &decdir, option, &hp) || tlsfile == NULL || encfile == NULL || decdir == NULL || (ctx = ctx_init(tlsfile, encfile, decdir)) == NULL) { ERR_print_errors_fp(stderr); fprintf(stderr, "Usage: deo decryptd " "[-l <[host:]port>] -t <tlsfile> " "-e <encfile> -d <decdir>\n"); return EXIT_FAILURE; } lfds = sd_listen_fds(0); if (lfds <= 0) { sock = BIO_get_accept_socket((char *) hp, 0); if (sock < 0) { ERR_print_errors_fp(stderr); goto error; } if (listen(sock, 64) != 0) goto error; } while (true) { DEO_ERR err = DEO_ERR_NONE; AUTO(ASN1_OCTET_STRING, pt); AUTO(DEO_MSG, in); AUTO(BIO, sio); AUTO_FD(cfd); int lfd; if (!have_conn(lfds, sock, &lfd)) break; if (!do_accept(ctx->ctx, lfd, &cfd, &sio)) continue; in = d2i_bio_max(&DEO_MSG_it, sio, NULL, DEO_MAX_INPUT); if (in == NULL) continue; switch (in->type) { case DEO_MSG_TYPE_CRT_REQ: ASN1_item_i2d_bio(&DEO_MSG_it, sio, &(DEO_MSG) { .type = DEO_MSG_TYPE_CRT_REP, .value.crt_rep = ctx->crt }); break; case DEO_MSG_TYPE_DEC_REQ: err = decrypt(ctx, in->value.dec_req, &pt); if (err != DEO_ERR_NONE) { SEND_ERR(sio, err); break; } ASN1_item_i2d_bio(&DEO_MSG_it, sio, &(DEO_MSG) { .type = DEO_MSG_TYPE_DEC_REP, .value.dec_rep = pt }); break; default: break; }