void xmpp_close(void) { if (session.wfs < 0) return; /* Close stream */ { char *s; FORMAT(s, "<iq to='%s' type='get'>" "<query xmlns='urn:cryonline:k01'>" "<player_status prev_status='%u' new_status='%u' to='%s'/>" "</query>" "</iq>", session.online.jid.k01, session.online.status, STATUS_LEFT, session.online.channel ? session.online.channel : ""); stream_send_msg(session.wfs, s); free(s); } stream_send_msg(session.wfs, "</stream:stream>"); stream_flush(session.wfs); close(session.wfs); session.wfs = -1; #ifdef USE_TLS tls_close(); tls_free(); #endif }
/*! \brief used internally by tcp_main_loop() */ static void tcpconn_destroy(struct tcp_connection* tcpconn) { int fd; TCPCONN_LOCK; /*avoid races w/ tcp_send*/ tcpconn->refcnt--; if (tcpconn->refcnt==0){ LM_DBG("destroying connection %p, flags %04x\n", tcpconn, tcpconn->flags); fd=tcpconn->s; #ifdef USE_TLS /*FIXME: lock ->writelock ? */ if (tcpconn->type==PROTO_TLS) tls_close(tcpconn, fd); #endif _tcpconn_rm(tcpconn); close(fd); tcp_connections_no--; }else{ /* force timeout */ tcpconn->timeout=0; tcpconn->state=S_CONN_BAD; LM_DBG("delaying (%p, flags %04x) ...\n", tcpconn, tcpconn->flags); } TCPCONN_UNLOCK; }
/* very ineficient for now - FIXME*/ void tcpconn_timeout(fd_set* set) { struct tcp_connection *c, *next; int ticks; unsigned h; int fd; ticks=get_ticks(); TCPCONN_LOCK; /* fixme: we can lock only on delete IMO */ for(h=0; h<TCP_ADDR_HASH_SIZE; h++){ c=tcpconn_addr_hash[h]; while(c){ next=c->next; if ((c->refcnt==0) && (ticks>c->timeout)) { DBG("tcpconn_timeout: timeout for hash=%d - %p (%d > %d)\n", h, c, ticks, c->timeout); fd=c->s; #ifdef USE_TLS if (c->type==PROTO_TLS) tls_close(c, fd); #endif _tcpconn_rm(c); if (fd>0) { FD_CLR(fd, set); close(fd); } } c=next; } } TCPCONN_UNLOCK; }
/* used internally by tcp_main_loop() */ static void tcpconn_destroy(struct tcp_connection* tcpconn) { int fd; TCPCONN_LOCK; /*avoid races w/ tcp_send*/ tcpconn->refcnt--; if (tcpconn->refcnt==0){ DBG("tcp_main_loop: destroying connection\n"); fd=tcpconn->s; #ifdef USE_TLS /*FIXME: lock ->writelock ? */ if (tcpconn->type==PROTO_TLS) tls_close(tcpconn, fd); #endif _tcpconn_rm(tcpconn); close(fd); }else{ /* force timeout */ tcpconn->timeout=0; tcpconn->state=S_CONN_BAD; DBG("tcp_main_loop: delaying ...\n"); } TCPCONN_UNLOCK; }
IoT_Error_t iot_tls_disconnect(Network *pNetwork) { if (tls_handle) tls_close(&tls_handle); Close_TCPSocket(&pNetwork->my_socket); return AWS_SUCCESS; }
int main(int argc, char *argv[]) { struct tls_config *conf; struct tls *ctx; struct tls_cert_info *cert; int res; const char *host; if (argc < 2) errx(1, "give host as arg\n"); host = argv[1]; res = tls_init(); if (res < 0) errx(1, "tls_init"); conf = tls_config_new(); if (!conf) errx(1, "tls_config_new"); tls_config_set_protocols(conf, TLS_PROTOCOLS_ALL); tls_config_set_ciphers(conf, "fast"); ctx = tls_client(); if (!ctx) errx(1, "tls_client"); res = tls_configure(ctx, conf); if (res < 0) errx(1, "tls_configure: %s", tls_error(ctx)); res = tls_connect(ctx, host, "443"); if (res < 0) errx(1, "tls_connect: %s", tls_error(ctx)); printf("connect ok\n"); res = tls_get_peer_cert(ctx, &cert); if (res < 0) errx(1, "tls_get_peer_cert: %s", tls_error(ctx)); tls_close(ctx); tls_free(ctx); tls_config_free(conf); printf(" CN='%s'\n", cert->subject.common_name); printf(" C='%s'\n", cert->subject.country_name); printf(" ST='%s'\n", cert->subject.state_or_province_name); printf(" L='%s'\n", cert->subject.locality_name); printf(" S='%s'\n", cert->subject.street_address); printf(" O='%s'\n", cert->subject.organization_name); printf(" OU='%s'\n", cert->subject.organizational_unit_name); tls_cert_free(cert); return 0; }
static void worker_cb(int fd, short flags, void *arg) { struct Worker *w = arg; const char *err; char buf[128]; int res; size_t outlen; w->pending = 0; if (w->wstate == HANDSHAKE) { err = do_handshake(w, fd); add_error(w, err); } else if (w->wstate == CONNECTED) { if (flags & EV_READ) { res = tls_read(w->ctx, buf, sizeof buf, &outlen); if (res == TLS_READ_AGAIN) { wait_for_event(w, EV_READ); } else if (res == TLS_WRITE_AGAIN) { wait_for_event(w, EV_WRITE); } else if (res == 0) { if (outlen > 0 && w->is_server) { tls_write(w->ctx, "END", 3, &outlen); w->wstate = CLOSED; } else if (outlen == 0) { w->wstate = CLOSED; } else { wait_for_event(w, EV_READ); } } else { add_error(w, "bad pkt"); } } else { add_error(w, "EV_WRITE?"); } } if (w->wstate == CLOSED && w->ctx) { res = tls_close(w->ctx); if (res == 0) { tls_free(w->ctx); w->ctx = NULL; } else if (res == TLS_READ_AGAIN) { wait_for_event(w, EV_READ); } else if (res == TLS_WRITE_AGAIN) { wait_for_event(w, EV_WRITE); } else { tls_free(w->ctx); w->ctx = NULL; } } if (!w->pending && w->ctx) { errx(1, "missed event setup: %s flags=%d state=%d", w->is_server ? "S":"C", flags, w->wstate); } return; }
void server() { // load Config File and Settings fprintf(stdout, "Starting fidistat Server...\n"); openlog("fidistat-server", LOG_PID, LOG_DAEMON); syslog(LOG_INFO, "Started Fidistat Server"); struct pidfh *pfh = daemon_start('s'); // Handle Signals signal(SIGTERM, handleSigterm_S); signal(SIGCHLD, handleChild); // Open Socket initConf(); tls_init(); struct tls* ctx = tls_server(); int sock = initTLS_S(ctx); sckt = sock; int connfd, pid; listen(sock, 10); // Destroy Config destroyConf(); while(!term) { connfd = accept(sock, (struct sockaddr*) NULL, NULL); if (term) { break; } pid = fork(); if (pid < 0) { syslog(LOG_ERR, "forking new Worker failed"); } else if (pid == 0) { close(sock); syslog(LOG_INFO, "New incoming connection"); worker(connfd, ctx); syslog(LOG_INFO, "Closing connection"); exit(0); } else { close(connfd); } } syslog(LOG_INFO, "Shutting down Server"); close(sock); tls_close(ctx); tls_free(ctx); tls_config_free(tlsServer_conf); pidfile_remove(pfh); syslog(LOG_INFO, "Stopped Fidistat Server"); closelog(); exit(0); }
void close_socket(t_session *session) { if (session->socket_open) { #ifdef ENABLE_TLS if (session->binding->use_tls) { tls_close(&(session->tls_context)); } #endif fsync(session->client_socket); close(session->client_socket); session->socket_open = false; } }
void SocketFree(SocketRef *const socketptr) { SocketRef socket = *socketptr; if(!socket) return; if(socket->secure) tls_close(socket->secure); tls_free(socket->secure); socket->secure = NULL; async_close((uv_handle_t *)socket->stream); FREE(&socket->rdmem); socket->rd->base = NULL; socket->rd->len = 0; FREE(&socket->wr->base); socket->wr->len = 0; socket->err = 0; assert_zeroed(socket, 1); FREE(socketptr); socket = NULL; }
static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options) { TLSContext *c = h->priv_data; TLSShared *s = &c->tls_shared; SECURITY_STATUS sspi_ret; SCHANNEL_CRED schannel_cred = { 0 }; int ret; if ((ret = ff_tls_open_underlying(s, h, uri, options)) < 0) goto fail; if (s->listen) { av_log(h, AV_LOG_ERROR, "TLS Listen Sockets with SChannel is not implemented.\n"); ret = AVERROR(EINVAL); goto fail; } /* SChannel Options */ schannel_cred.dwVersion = SCHANNEL_CRED_VERSION; if (s->verify) schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION | SCH_CRED_REVOCATION_CHECK_CHAIN; else schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION | SCH_CRED_IGNORE_NO_REVOCATION_CHECK | SCH_CRED_IGNORE_REVOCATION_OFFLINE; /* Get credential handle */ sspi_ret = AcquireCredentialsHandle(NULL, (TCHAR *)UNISP_NAME, SECPKG_CRED_OUTBOUND, NULL, &schannel_cred, NULL, NULL, &c->cred_handle, &c->cred_timestamp); if (sspi_ret != SEC_E_OK) { av_log(h, AV_LOG_ERROR, "Unable to acquire security credentials (0x%lx)\n", sspi_ret); ret = AVERROR_UNKNOWN; goto fail; } ret = tls_client_handshake(h); if (ret < 0) goto fail; c->connected = 1; return 0; fail: tls_close(h); return ret; }
/* Free all remaining buffers */ void destroy_session(t_session *session) { #ifdef ENABLE_RPROXY if (session->rproxy_kept_alive) { #ifdef ENABLE_TLS if (session->rproxy_use_tls) { tls_close(&(session->rproxy_ssl)); } #endif close(session->rproxy_socket); session->rproxy_kept_alive = false; } #endif check_free(session->request); session->request = NULL; }
static const char *done_handshake(struct Worker *w) { int res; const char *emsg; emsg = check_fp(w, "sha1", w->peer_fingerprint_sha1, 20); if (emsg) return emsg; emsg = check_fp(w, "sha256", w->peer_fingerprint_sha256, 32); if (emsg) return emsg; if (w->show) { if (strcmp(w->show, "ciphers") == 0) { tls_get_connection_info(w->ctx, w->showbuf, sizeof w->showbuf); } else if (strcmp(w->show, "peer-cert") == 0) { struct tls_cert *cert = NULL; tls_get_peer_cert(w->ctx, &cert, NULL); show_cert(cert, w->showbuf, sizeof w->showbuf); tls_cert_free(cert); } else { snprintf(w->showbuf, sizeof w->showbuf, "bad kw: show=%s", w->show); } } if (w->aggressive_close) { close(w->socket); tls_close(w->ctx); w->wstate = CLOSED; return "OK"; } if (!w->is_server) { res = tls_write(w->ctx, "PKT", 3); if (res < 0) { return tls_error(w->ctx); } else if (res == 0) { return "write==0"; } else if (res != 3) { return "write!=3"; } } return wait_for_event(w, EV_READ); }
int https_get(const char *fn, off_t offset, struct url *url, struct http_hdrs *hdrs) { char range[BUFSIZ]; int res, ret; (void)snprintf(range, sizeof(range), "Range: bytes=%lld-\r\n", offset); https_vprintf(ctx, "GET %s HTTP/1.0\r\n" "Host: %s\r\n" "User-Agent: %s\r\n" "%s" "%s%s" "\r\n", url->path ? url->path : "/", url->host, ua, offset ? range : "", url->basic_auth[0] ? "Authorization: Basic " : "", url->basic_auth[0] ? url->basic_auth : ""); res = https_response(hdrs); if (res != 200 && res != 206) goto err; /* Expected a partial content but got full content */ if (offset && (res == 200)) { offset = 0; if (truncate(fn, 0) == -1) err(1, "%s: truncate", __func__); } https_retr_file(fn, hdrs->c_len + offset, offset); err: while ((ret = tls_close(ctx)) != 0) if (ret != TLS_WANT_POLLIN && ret != TLS_WANT_POLLOUT) errx(1, "%s: tls_close: %s", __func__, tls_error(ctx)); tls_free(ctx); return res; }
/*! \brief very inefficient for now - FIXME * keep in sync with tcpconn_destroy, the "delete" part should be * the same except for io_watch_del.. * \todo FIXME (very inefficient for now) */ static inline void tcpconn_timeout(int force) { struct tcp_connection *c, *next; unsigned int ticks; unsigned h; int fd; ticks=get_ticks(); TCPCONN_LOCK; /* fixme: we can lock only on delete IMO */ for(h=0; h<TCP_ID_HASH_SIZE; h++){ c=tcpconn_id_hash[h]; while(c){ next=c->id_next; if (force ||((c->refcnt==0) && (ticks>c->timeout))) { if (!force) LM_DBG("timeout for hash=%d - %p" " (%d > %d)\n", h, c, ticks, c->timeout); fd=c->s; #ifdef USE_TLS if (c->type==PROTO_TLS) tls_close(c, fd); #endif _tcpconn_rm(c); if ((!force)&&(fd>0)&&(c->refcnt==0)) { if (!(c->flags & F_CONN_REMOVED)){ io_watch_del(&io_h, fd, -1, IO_FD_CLOSING); c->flags|=F_CONN_REMOVED; } close(fd); } tcp_connections_no--; } c=next; } } TCPCONN_UNLOCK; }
static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options) { TLSContext *c = h->priv_data; TLSShared *s = &c->tls_shared; int ret; if ((ret = ff_tls_open_underlying(s, h, uri, options)) < 0) goto fail; c->ssl_context = SSLCreateContext(NULL, s->listen ? kSSLServerSide : kSSLClientSide, kSSLStreamType); if (!c->ssl_context) { av_log(h, AV_LOG_ERROR, "Unable to create SSL context\n"); ret = AVERROR(ENOMEM); goto fail; } if (s->ca_file) { if ((ret = load_ca(h)) < 0) goto fail; } if (s->ca_file || !s->verify) CHECK_ERROR(SSLSetSessionOption, c->ssl_context, kSSLSessionOptionBreakOnServerAuth, true); if (s->cert_file) if ((ret = load_cert(h)) < 0) goto fail; CHECK_ERROR(SSLSetPeerDomainName, c->ssl_context, s->host, strlen(s->host)); CHECK_ERROR(SSLSetIOFuncs, c->ssl_context, tls_read_cb, tls_write_cb); CHECK_ERROR(SSLSetConnection, c->ssl_context, h); while (1) { OSStatus status = SSLHandshake(c->ssl_context); if (status == errSSLServerAuthCompleted) { SecTrustRef peerTrust; SecTrustResultType trustResult; if (!s->verify) continue; if (SSLCopyPeerTrust(c->ssl_context, &peerTrust) != noErr) { ret = AVERROR(ENOMEM); goto fail; } if (SecTrustSetAnchorCertificates(peerTrust, c->ca_array) != noErr) { ret = AVERROR_UNKNOWN; goto fail; } if (SecTrustEvaluate(peerTrust, &trustResult) != noErr) { ret = AVERROR_UNKNOWN; goto fail; } if (trustResult == kSecTrustResultProceed || trustResult == kSecTrustResultUnspecified) { // certificate is trusted status = errSSLWouldBlock; // so we call SSLHandshake again } else if (trustResult == kSecTrustResultRecoverableTrustFailure) { // not trusted, for some reason other than being expired status = errSSLXCertChainInvalid; } else { // cannot use this certificate (fatal) status = errSSLBadCert; } if (peerTrust) CFRelease(peerTrust); } if (status == noErr) break; av_log(h, AV_LOG_ERROR, "Unable to negotiate TLS/SSL session: %i\n", (int)status); ret = AVERROR(EIO); goto fail; } return 0; fail: tls_close(h); return ret; }
int main(int argc, char *argv[]) { struct tls *tls = NULL; struct tls *cctx = NULL; struct tls_config *tls_config = NULL; char buf[BUFSIZ]; int ch; int e; if ((tls_config = tls_config_new()) == NULL) err(EXIT_FAILURE, "tls_config_new"); while ((ch = getopt(argc, argv, "Cc:k:p:f:")) != -1) { switch (ch) { case 'C': tls_config_verify_client(tls_config); break; case 'c': if (tls_config_set_cert_file(tls_config, optarg) == -1) err(EXIT_FAILURE, "tls_config_set_cert_file"); break; case 'k': if (tls_config_set_key_file(tls_config, optarg) == -1) err(EXIT_FAILURE, "tls_config_set_key_file"); break; case 'f': if (tls_config_set_ca_file(tls_config, optarg) == -1) err(EXIT_FAILURE, "tls_config_set_ca_file"); break; case 'p': if (tls_config_set_ca_path(tls_config, optarg) == -1) err(EXIT_FAILURE, "tls_config_set_ca_path"); break; default: usage(); /* NOTREACHED */ } } argc -= optind; argv += optind; /* prepare libtls */ if (tls_init() == -1) err(EXIT_FAILURE, "tls_init"); if ((tls = tls_server()) == NULL) err(EXIT_FAILURE, "tls_server"); if (tls_configure(tls, tls_config) == -1) goto err; if (tls_accept_fds(tls, &cctx, STDIN_FILENO, STDOUT_FILENO) == -1) goto err; if (tls_handshake(cctx) == -1) goto err; if (setenv("PROTO", "SSL", 1) == -1) err(EXIT_FAILURE, "setenv"); /* fork front end program */ char *prog = argv[0]; # define PIPE_READ 0 # define PIPE_WRITE 1 int pi[2]; /* input pipe */ int po[2]; /* output pipe */ if (pipe(pi) == -1) err(EXIT_FAILURE, "pipe"); if (pipe(po) == -1) err(EXIT_FAILURE, "pipe"); switch (fork()) { case -1: err(EXIT_FAILURE, "fork"); case 0: /* client program */ /* close non-using ends of pipes */ if (close(pi[PIPE_READ]) == -1) err(EXIT_FAILURE, "close"); if (close(po[PIPE_WRITE]) == -1) err(EXIT_FAILURE, "close"); /* move pipe end to ucspi defined fd numbers */ if (dup2(po[PIPE_READ], READ_FD) == -1) err(EXIT_FAILURE, "dup2"); if (dup2(pi[PIPE_WRITE], WRITE_FD) == -1) err(EXIT_FAILURE, "dup2"); if (close(po[PIPE_READ]) == -1) err(EXIT_FAILURE, "close"); if (close(pi[PIPE_WRITE]) == -1) err(EXIT_FAILURE, "close"); execv(prog, argv); err(EXIT_FAILURE, "execve"); default: break; /* parent */ } /* close non-using ends of pipes */ if (close(pi[PIPE_WRITE]) == -1) err(EXIT_FAILURE, "close"); if (close(po[PIPE_READ]) == -1) err(EXIT_FAILURE, "close"); int in = pi[PIPE_READ]; int out = po[PIPE_WRITE]; /* communication loop */ for (;;) { int ret; char buf[BUFSIZ]; ssize_t sn = 0; fd_set readfds; FD_ZERO(&readfds); FD_SET(in, &readfds); FD_SET(READ_FD, &readfds); int max_fd = MAX(in, READ_FD); ret = select(max_fd+1, &readfds, NULL, NULL, NULL); if (ret == -1) err(EXIT_FAILURE, "select"); if (FD_ISSET(READ_FD, &readfds)) { do { again: sn = tls_read(cctx, buf, sizeof buf); if (sn == TLS_WANT_POLLIN || sn == TLS_WANT_POLLOUT) goto again; if (sn == -1) goto err; if (sn == 0) return EXIT_SUCCESS; if (write(out, buf, sn) == -1) err(EXIT_FAILURE, "write()"); } while (sn == sizeof buf); } else if (FD_ISSET(in, &readfds)) { if ((sn = read(in, buf, sizeof buf)) == -1) err(EXIT_FAILURE, "read()"); if (sn == 0) /* EOF from inside */ goto out; /* XXX: unable to detect disconnect here */ if (tls_write(cctx, buf, sn) == -1) goto err; } } out: tls_close(cctx); return EXIT_SUCCESS; err: while ((e = ERR_get_error())) { ERR_error_string(e, buf); fprintf(stderr, " %s\n", buf); } errx(EXIT_FAILURE, "tls_error: %s", tls_error(cctx)); errx(EXIT_FAILURE, "tls_error: %s", tls_error(tls)); }
void worker(int connfd, struct tls* ctx) { // Process HEADER //-------------- struct tls* cctx = NULL; tls_accept_socket(ctx, &cctx, connfd); json_t *header = recvOverTLS(cctx); const char* clientName = json_string_value(json_object_get(header, "from")); for (size_t i = 0; i < sizeof(clientName); i++) { if (clientName[i] == '/' || clientName[i] == '\\') { syslog(LOG_ERR, "ERROR in clientName!, aborting"); return; } } const char* clientAuth = json_string_value(json_object_get(header, "auth")); if (strcmp(clientAuth, getClientAuth()) != 0) { syslog(LOG_ERR, "Authentication failed"); return; } connType type = json_integer_value(json_object_get(header, "type")); int size = json_integer_value(json_object_get(header, "size")); // Process Payload //---------------- // new Values for graphs if (type == NEWDATA) { for (int i = 0; i < size; i++) { json_t* payload = recvOverTLS(cctx); pasteJSON(payload, clientName); } } // create .json or update displaysettings if (type == CREATE || type == UPDATE) { for (int i = 0; i < size; i++) { json_t* payload = recvOverTLS(cctx); const char * name = json_string_value(json_object_get(payload, "name")); if (name == NULL) { syslog(LOG_ERR, "Error in Message from Client"); return; } json_t *root = json_object_get(payload, "payload"); char* file = composeFileName(clientName, name, "json"); if (type == CREATE) { dumpJSON(root, file); } else { mergeJSON(root,file); } } } // Look, which files are not available if (type == HELLO) { json_t *relist = json_array(); json_t *list = recvOverTLS(cctx); for (int i = 0; i < size; i++) { const char * name = json_string_value(json_array_get(list, i)); if (name == NULL) { syslog(LOG_ERR, "Error in Message from Client"); return; } char* file = composeFileName(clientName, name, "json"); if (access( file, F_OK ) == -1) { json_array_append_new(relist, json_string(name)); } } char * relistStr = json_dumps(relist, JSON_COMPACT); sendOverTLS(cctx, relistStr); free(relistStr); } // Delete all files from this client if (type == DELETE) { json_t *list = recvOverTLS(cctx); for (int i = 0; i < size; i++) { const char * name = json_string_value(json_array_get(list, i)); delete(clientName, name); } } tls_close(cctx); tls_free(cctx); }
static void worker_cb(int fd, short flags, void *arg) { struct Worker *w = arg; const char *err; char buf[128]; int res; w->pending = 0; if (w->wstate == HANDSHAKE) { err = do_handshake(w, fd); add_error(w, "%s", err); } else if (w->wstate == CONNECTED) { if (flags & EV_READ) { res = tls_read(w->ctx, buf, sizeof buf); if (res == TLS_WANT_POLLIN) { wait_for_event(w, EV_READ); } else if (res == TLS_WANT_POLLOUT) { wait_for_event(w, EV_WRITE); } else if (res >= 0) { if (res > 0 && w->is_server) { res = tls_write(w->ctx, "END", 3); w->wstate = CLOSED; } else if (res == 0) { w->wstate = CLOSED; } else { wait_for_event(w, EV_READ); } } else { add_error(w, "bad pkt: res=%d err=%s", res, tls_error(w->ctx)); } } else { add_error(w, "EV_WRITE?"); } } if (w->wstate == CLOSED && w->ctx) { if (w->aggressive_close) { close(w->socket); tls_close(w->ctx); res = 0; } else { res = tls_close(w->ctx); } if (res == 0) { tls_free(w->ctx); w->ctx = NULL; } else if (res == TLS_WANT_POLLIN) { wait_for_event(w, EV_READ); } else if (res == TLS_WANT_POLLOUT) { wait_for_event(w, EV_WRITE); } else { add_error(w, "close error: res=%d err=%s", res, tls_error(w->ctx)); tls_free(w->ctx); w->ctx = NULL; } } if (!w->pending && w->ctx) { errx(1, "missed event setup: %s flags=%d state=%d", w->is_server ? "S":"C", flags, w->wstate); } return; }
int HTTPServerListen(HTTPServerRef const server, strarg_t const address, strarg_t const port) { if(!server) return 0; assertf(!server->socket->data, "HTTPServer already listening"); int rc; rc = uv_tcp_init(async_loop, server->socket); if(rc < 0) return rc; server->socket->data = server; struct addrinfo const hints = { .ai_flags = AI_V4MAPPED | AI_ADDRCONFIG | AI_NUMERICSERV | AI_PASSIVE, .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM, .ai_protocol = 0, // ??? }; struct addrinfo *info; rc = async_getaddrinfo(address, port, &hints, &info); if(rc < 0) { HTTPServerClose(server); return rc; } int bound = 0; rc = 0; for(struct addrinfo *each = info; each; each = each->ai_next) { rc = uv_tcp_bind(server->socket, each->ai_addr, 0); if(rc >= 0) bound++; } uv_freeaddrinfo(info); if(!bound) { HTTPServerClose(server); if(rc < 0) return rc; return UV_EADDRNOTAVAIL; } rc = uv_listen((uv_stream_t *)server->socket, 511, connection_cb); if(rc < 0) { HTTPServerClose(server); return rc; } return 0; } int HTTPServerListenSecure(HTTPServerRef const server, strarg_t const address, strarg_t const port, struct tls **const tlsptr) { if(!server) return 0; int rc = HTTPServerListen(server, address, port); if(rc < 0) return rc; server->secure = *tlsptr; *tlsptr = NULL; return 0; } void HTTPServerClose(HTTPServerRef const server) { if(!server) return; if(!server->socket->data) return; if(server->secure) tls_close(server->secure); tls_free(server->secure); server->secure = NULL; async_close((uv_handle_t *)server->socket); } static void connection(uv_stream_t *const socket) { HTTPServerRef const server = socket->data; HTTPConnectionRef conn; int rc = HTTPConnectionCreateIncomingSecure(socket, server->secure, 0, &conn); if(rc < 0) { fprintf(stderr, "HTTP server connection error %s\n", uv_strerror(rc)); return; } assert(conn); for(;;) { server->listener(server->context, server, conn); rc = HTTPConnectionDrainMessage(conn); if(rc < 0) break; } HTTPConnectionFree(&conn); }
int main(int argc, char *argv[]) { struct tls_config *conf; struct tls *ctx; int res; const char *host; if (argc < 2) errx(1, "give host as arg\n"); host = argv[1]; res = tls_init(); if (res < 0) errx(1, "tls_init"); conf = tls_config_new(); if (!conf) errx(1, "tls_config_new"); tls_config_set_protocols(conf, TLS_PROTOCOLS_ALL); tls_config_set_ciphers(conf, "HIGH:+3DES:!aNULL"); tls_config_set_ca_file(conf, "/etc/ssl/certs/ca-certificates.crt"); ctx = tls_client(); if (!ctx) errx(1, "tls_client"); res = tls_configure(ctx, conf); if (res < 0) errx(1, "tls_configure: %s", tls_error(ctx)); res = tls_connect(ctx, host, "443"); if (res < 0) errx(1, "tls_connect: %s", tls_error(ctx)); res = tls_handshake(ctx); if (res < 0) errx(1, "tls_handshake: %s", tls_error(ctx)); printf("connect ok\n"); #if 0 struct tls_cert *cert; //res = tls_get_peer_cert(ctx, &cert, NULL); //if (res < 0) //errx(1, "tls_get_peer_cert: %s", tls_error(ctx)); printf(" CN='%s'\n", cert->subject.common_name); printf(" C='%s'\n", cert->subject.country_name); printf(" ST='%s'\n", cert->subject.state_or_province_name); printf(" L='%s'\n", cert->subject.locality_name); printf(" S='%s'\n", cert->subject.street_address); printf(" O='%s'\n", cert->subject.organization_name); printf(" OU='%s'\n", cert->subject.organizational_unit_name); tls_cert_free(cert); #endif tls_close(ctx); tls_free(ctx); tls_config_free(conf); return 0; }
int main(int argc, char *argv[]) { struct tls_config *conf; struct tls *ctx, *ocsp; struct tls_cert *cert; int res; const char *host; char buf[256]; if (argc < 2) errx(1, "give host as arg\n"); host = argv[1]; #ifdef USUAL_LIBSSL_FOR_TLS printf("libssl: %s\n", SSLeay_version(SSLEAY_VERSION)); #endif res = tls_init(); if (res < 0) errx(1, "tls_init"); conf = tls_config_new(); if (!conf) errx(1, "tls_config_new"); tls_config_set_protocols(conf, TLS_PROTOCOLS_ALL); tls_config_set_ciphers(conf, "fast"); ctx = tls_client(); if (!ctx) errx(1, "tls_client"); res = tls_configure(ctx, conf); if (res < 0) errx(1, "tls_configure: %s", tls_error(ctx)); res = tls_connect(ctx, host, "443"); if (res < 0) errx(1, "tls_connect: %s", tls_error(ctx)); res = tls_handshake(ctx); if (res < 0) errx(1, "tls_handshake: %s", tls_error(ctx)); res = tls_get_peer_cert(ctx, &cert, NULL); if (res < 0) errx(1, "tls_get_peer_cert: %s", tls_error(ctx)); tls_get_connection_info(ctx, buf, sizeof buf); printf("Connection: '%s'\n", buf); printf(" CN='%s'\n", cert->subject.common_name); printf(" C='%s'\n", cert->subject.country_name); printf(" ST='%s'\n", cert->subject.state_or_province_name); printf(" L='%s'\n", cert->subject.locality_name); printf(" S='%s'\n", cert->subject.street_address); printf(" O='%s'\n", cert->subject.organization_name); printf(" OU='%s'\n", cert->subject.organizational_unit_name); show_ocsp_info("OCSP stapling", ctx); ocsp = NULL; res = tls_ocsp_check_peer(&ocsp, NULL, ctx); if (ocsp) { show_ocsp_info("OCSP responder", ocsp); tls_free(ocsp); } else if (res == TLS_NO_OCSP) { printf("OCSP responder: No OCSP support in libtls\n"); } if (0) test_context(ctx); tls_close(ctx); tls_free(ctx); tls_config_free(conf); tls_cert_free(cert); return 0; }
static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options) { TLSContext *p = h->priv_data; TLSShared *c = &p->tls_shared; int ret; ff_gnutls_init(); if ((ret = ff_tls_open_underlying(c, h, uri, options)) < 0) goto fail; gnutls_init(&p->session, c->listen ? GNUTLS_SERVER : GNUTLS_CLIENT); if (!c->listen && !c->numerichost) gnutls_server_name_set(p->session, GNUTLS_NAME_DNS, c->host, strlen(c->host)); gnutls_certificate_allocate_credentials(&p->cred); if (c->ca_file) { ret = gnutls_certificate_set_x509_trust_file(p->cred, c->ca_file, GNUTLS_X509_FMT_PEM); if (ret < 0) av_log(h, AV_LOG_ERROR, "%s\n", gnutls_strerror(ret)); } #if GNUTLS_VERSION_MAJOR >= 3 else gnutls_certificate_set_x509_system_trust(p->cred); #endif gnutls_certificate_set_verify_flags(p->cred, c->verify ? GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT : 0); if (c->cert_file && c->key_file) { ret = gnutls_certificate_set_x509_key_file(p->cred, c->cert_file, c->key_file, GNUTLS_X509_FMT_PEM); if (ret < 0) { av_log(h, AV_LOG_ERROR, "Unable to set cert/key files %s and %s: %s\n", c->cert_file, c->key_file, gnutls_strerror(ret)); ret = AVERROR(EIO); goto fail; } } else if (c->cert_file || c->key_file) av_log(h, AV_LOG_ERROR, "cert and key required\n"); gnutls_credentials_set(p->session, GNUTLS_CRD_CERTIFICATE, p->cred); gnutls_transport_set_pull_function(p->session, gnutls_url_pull); gnutls_transport_set_push_function(p->session, gnutls_url_push); gnutls_transport_set_ptr(p->session, c->tcp); gnutls_priority_set_direct(p->session, "NORMAL", NULL); ret = gnutls_handshake(p->session); if (ret) { ret = print_tls_error(h, ret); goto fail; } p->need_shutdown = 1; if (c->verify) { unsigned int status, cert_list_size; gnutls_x509_crt_t cert; const gnutls_datum_t *cert_list; if ((ret = gnutls_certificate_verify_peers2(p->session, &status)) < 0) { av_log(h, AV_LOG_ERROR, "Unable to verify peer certificate: %s\n", gnutls_strerror(ret)); ret = AVERROR(EIO); goto fail; } if (status & GNUTLS_CERT_INVALID) { av_log(h, AV_LOG_ERROR, "Peer certificate failed verification\n"); ret = AVERROR(EIO); goto fail; } if (gnutls_certificate_type_get(p->session) != GNUTLS_CRT_X509) { av_log(h, AV_LOG_ERROR, "Unsupported certificate type\n"); ret = AVERROR(EIO); goto fail; } gnutls_x509_crt_init(&cert); cert_list = gnutls_certificate_get_peers(p->session, &cert_list_size); gnutls_x509_crt_import(cert, cert_list, GNUTLS_X509_FMT_DER); ret = gnutls_x509_crt_check_hostname(cert, c->host); gnutls_x509_crt_deinit(cert); if (!ret) { av_log(h, AV_LOG_ERROR, "The certificate's owner does not match hostname %s\n", c->host); ret = AVERROR(EIO); goto fail; } } return 0; fail: tls_close(h); return ret; }
int main(int argc, char *argv[], char *envp[]) { struct tls *tls = NULL; int ch; environ = envp; /* pipes to communicate with the front end */ int in = -1; int out = -1; bool no_name_verification = false; bool no_cert_verification = false; bool no_time_verification = false; char *host = getenv("TCPREMOTEHOST"); struct tls_config *tls_config; if (getenv("TLSC_NO_VERIFICATION") != NULL) { no_name_verification = true; no_cert_verification = true; no_time_verification = true; } if (getenv("TLSC_NO_HOST_VERIFICATION") != NULL) no_name_verification = true; if (getenv("TLSC_NO_CERT_VERIFICATION") != NULL) no_cert_verification = true; if (getenv("TLSC_NO_TIME_VERIFICATION") != NULL) no_time_verification = true; if ((tls_config = tls_config_new()) == NULL) err(EXIT_FAILURE, "tls_config_new"); char *str = NULL; if ((str = getenv("TLSC_CERT_FILE")) != NULL) if (tls_config_set_cert_file(tls_config, str) == -1) err(EXIT_FAILURE, "tls_config_set_cert_file"); if ((str = getenv("TLSC_KEY_FILE")) != NULL) if (tls_config_set_key_file(tls_config, str) == -1) err(EXIT_FAILURE, "tls_config_set_key_file"); if ((str = getenv("TLSC_CA_FILE")) != NULL) if (tls_config_set_ca_file(tls_config, str) == -1) err(EXIT_FAILURE, "tls_config_set_ca_file"); if ((str = getenv("TLSC_CA_PATH")) != NULL) if (tls_config_set_ca_path(tls_config, str) == -1) err(EXIT_FAILURE, "tls_config_set_ca_path"); while ((ch = getopt(argc, argv, "c:k:f:p:n:HCTVh")) != -1) { switch (ch) { case 'c': if (tls_config_set_cert_file(tls_config, optarg) == -1) err(EXIT_FAILURE, "tls_config_set_cert_file"); break; case 'k': if (tls_config_set_key_file(tls_config, optarg) == -1) err(EXIT_FAILURE, "tls_config_set_key_file"); break; case 'f': if (tls_config_set_ca_file(tls_config, optarg) == -1) err(EXIT_FAILURE, "tls_config_set_ca_file"); break; case 'p': if (tls_config_set_ca_path(tls_config, optarg) == -1) err(EXIT_FAILURE, "tls_config_set_ca_path"); break; case 'n': if ((host = strdup(optarg)) == NULL) goto err; break; case 'H': no_name_verification = true; break; case 'C': no_cert_verification = true; break; case 'T': no_time_verification = true; break; case 'V': no_name_verification = true; no_cert_verification = true; no_time_verification = true; break; case 'h': default: usage(); /* NOTREACHED */ } } argc -= optind; argv += optind; if (argc < 1) usage(); /* verification settings */ if (no_cert_verification) tls_config_insecure_noverifycert(tls_config); if (no_name_verification) tls_config_insecure_noverifyname(tls_config); if (no_time_verification) tls_config_insecure_noverifytime(tls_config); /* libtls setup */ if (tls_init() != 0) err(EXIT_FAILURE, "tls_init"); if ((tls = tls_client()) == NULL) err(EXIT_FAILURE, "tls_client"); if (tls_configure(tls, tls_config) != 0) err(EXIT_FAILURE, "tls_configure"); if (tls_connect_fds(tls, READ_FD, WRITE_FD, host) == -1) goto err; if (tls_handshake(tls) == -1) goto err; /* overide PROTO to signal the application layer that the communication * channel is save. */ if (setenv("PROTO", "SSL", 1) == -1) err(EXIT_FAILURE, "setenv"); /* fork front end program */ char *prog = argv[0]; # define PIPE_READ 0 # define PIPE_WRITE 1 int pi[2]; /* input pipe */ int po[2]; /* output pipe */ if (pipe(pi) == -1) err(EXIT_FAILURE, "pipe"); if (pipe(po) == -1) err(EXIT_FAILURE, "pipe"); switch (fork()) { case -1: err(EXIT_FAILURE, "fork"); case 0: /* client program */ /* close non-using ends of pipes */ if (close(pi[PIPE_READ]) == -1) err(EXIT_FAILURE, "close"); if (close(po[PIPE_WRITE]) == -1) err(EXIT_FAILURE, "close"); /* * We have to move one descriptor cause po[] may * overlaps with descriptor 6 and 7. */ int po_read = 0; if ((po_read = dup(po[PIPE_READ])) == -1) err(EXIT_FAILURE, "dup"); if (close(po[PIPE_READ]) < 0) err(EXIT_FAILURE, "close"); if (dup2(pi[PIPE_WRITE], WRITE_FD) < 0) err(EXIT_FAILURE, "dup2"); if (dup2(po_read, READ_FD) < 0) err(EXIT_FAILURE, "dup2"); if (close(pi[PIPE_WRITE]) < 0) err(EXIT_FAILURE, "close"); if (close(po_read) < 0) err(EXIT_FAILURE, "close"); execvpe(prog, argv, environ); err(EXIT_FAILURE, "execvpe"); default: break; /* parent */ } /* close non-using ends of pipes */ if (close(pi[PIPE_WRITE]) == -1) err(EXIT_FAILURE, "close"); if (close(po[PIPE_READ]) == -1) err(EXIT_FAILURE, "close"); in = pi[PIPE_READ]; out = po[PIPE_WRITE]; /* communication loop */ for (;;) { int ret; char buf[BUFSIZ]; ssize_t sn = 0; fd_set readfds; FD_ZERO(&readfds); FD_SET(in, &readfds); FD_SET(READ_FD, &readfds); int max_fd = MAX(in, READ_FD); ret = select(max_fd+1, &readfds, NULL, NULL, NULL); if (ret == -1) err(EXIT_FAILURE, "select"); if (FD_ISSET(READ_FD, &readfds)) { do { again: sn = tls_read(tls, buf, sizeof buf); if (sn == TLS_WANT_POLLIN || sn == TLS_WANT_POLLOUT) goto again; if (sn == -1) goto err; if (sn == 0) return EXIT_SUCCESS; if (write(out, buf, sn) == -1) err(EXIT_FAILURE, "write()"); } while (sn == sizeof buf); } else if (FD_ISSET(in, &readfds)) { if ((sn = read(in, buf, sizeof buf)) == -1) err(EXIT_FAILURE, "read()"); if (sn == 0) goto out; if ((sn = tls_write(tls, buf, sn)) == -1) goto out; } } out: tls_close(tls); return EXIT_SUCCESS; err: errx(EXIT_FAILURE, "tls_error: %s", tls_error(tls)); }
static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options) { TLSContext *p = h->priv_data; TLSShared *c = &p->tls_shared; BIO *bio; int ret; ff_openssl_init(); if ((ret = ff_tls_open_underlying(c, h, uri, options)) < 0) goto fail; p->ctx = SSL_CTX_new(c->listen ? TLSv1_server_method() : TLSv1_client_method()); if (!p->ctx) { av_log(h, AV_LOG_ERROR, "%s\n", ERR_error_string(ERR_get_error(), NULL)); ret = AVERROR(EIO); goto fail; } if (c->ca_file) SSL_CTX_load_verify_locations(p->ctx, c->ca_file, NULL); if (c->cert_file && !SSL_CTX_use_certificate_chain_file(p->ctx, c->cert_file)) { av_log(h, AV_LOG_ERROR, "Unable to load cert file %s: %s\n", c->cert_file, ERR_error_string(ERR_get_error(), NULL)); ret = AVERROR(EIO); goto fail; } if (c->key_file && !SSL_CTX_use_PrivateKey_file(p->ctx, c->key_file, SSL_FILETYPE_PEM)) { av_log(h, AV_LOG_ERROR, "Unable to load key file %s: %s\n", c->key_file, ERR_error_string(ERR_get_error(), NULL)); ret = AVERROR(EIO); goto fail; } // Note, this doesn't check that the peer certificate actually matches // the requested hostname. if (c->verify) SSL_CTX_set_verify(p->ctx, SSL_VERIFY_PEER, NULL); p->ssl = SSL_new(p->ctx); if (!p->ssl) { av_log(h, AV_LOG_ERROR, "%s\n", ERR_error_string(ERR_get_error(), NULL)); ret = AVERROR(EIO); goto fail; } bio = BIO_new(&url_bio_method); bio->ptr = c->tcp; SSL_set_bio(p->ssl, bio, bio); if (!c->listen && !c->numerichost) SSL_set_tlsext_host_name(p->ssl, c->host); ret = c->listen ? SSL_accept(p->ssl) : SSL_connect(p->ssl); if (ret == 0) { av_log(h, AV_LOG_ERROR, "Unable to negotiate TLS/SSL session\n"); ret = AVERROR(EIO); goto fail; } else if (ret < 0) { ret = print_tls_error(h, ret); goto fail; } return 0; fail: tls_close(h); return ret; }
static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options) { TLSContext *p = h->priv_data; TLSShared *c = &p->tls_shared; BIO *bio; int ret; ff_openssl_init(); if ((ret = ff_tls_open_underlying(c, h, uri, options)) < 0) goto fail; // We want to support all versions of TLS >= 1.0, but not the deprecated // and insecure SSLv2 and SSLv3. Despite the name, SSLv23_*_method() // enables support for all versions of SSL and TLS, and we then disable // support for the old protocols immediately after creating the context. p->ctx = SSL_CTX_new(c->listen ? SSLv23_server_method() : SSLv23_client_method()); if (!p->ctx) { av_log(h, AV_LOG_ERROR, "%s\n", ERR_error_string(ERR_get_error(), NULL)); ret = AVERROR(EIO); goto fail; } SSL_CTX_set_options(p->ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); if (c->ca_file) SSL_CTX_load_verify_locations(p->ctx, c->ca_file, NULL); if (c->cert_file && !SSL_CTX_use_certificate_chain_file(p->ctx, c->cert_file)) { av_log(h, AV_LOG_ERROR, "Unable to load cert file %s: %s\n", c->cert_file, ERR_error_string(ERR_get_error(), NULL)); ret = AVERROR(EIO); goto fail; } if (c->key_file && !SSL_CTX_use_PrivateKey_file(p->ctx, c->key_file, SSL_FILETYPE_PEM)) { av_log(h, AV_LOG_ERROR, "Unable to load key file %s: %s\n", c->key_file, ERR_error_string(ERR_get_error(), NULL)); ret = AVERROR(EIO); goto fail; } // Note, this doesn't check that the peer certificate actually matches // the requested hostname. if (c->verify) SSL_CTX_set_verify(p->ctx, SSL_VERIFY_PEER, NULL); p->ssl = SSL_new(p->ctx); if (!p->ssl) { av_log(h, AV_LOG_ERROR, "%s\n", ERR_error_string(ERR_get_error(), NULL)); ret = AVERROR(EIO); goto fail; } #if OPENSSL_VERSION_NUMBER >= 0x1010000fL p->url_bio_method = BIO_meth_new(BIO_TYPE_SOURCE_SINK, "urlprotocol bio"); BIO_meth_set_write(p->url_bio_method, url_bio_bwrite); BIO_meth_set_read(p->url_bio_method, url_bio_bread); BIO_meth_set_puts(p->url_bio_method, url_bio_bputs); BIO_meth_set_ctrl(p->url_bio_method, url_bio_ctrl); BIO_meth_set_create(p->url_bio_method, url_bio_create); BIO_meth_set_destroy(p->url_bio_method, url_bio_destroy); bio = BIO_new(p->url_bio_method); BIO_set_data(bio, c->tcp); #else bio = BIO_new(&url_bio_method); bio->ptr = c->tcp; #endif SSL_set_bio(p->ssl, bio, bio); if (!c->listen && !c->numerichost) SSL_set_tlsext_host_name(p->ssl, c->host); ret = c->listen ? SSL_accept(p->ssl) : SSL_connect(p->ssl); if (ret == 0) { av_log(h, AV_LOG_ERROR, "Unable to negotiate TLS/SSL session\n"); ret = AVERROR(EIO); goto fail; } else if (ret < 0) { ret = print_tls_error(h, ret); goto fail; } return 0; fail: tls_close(h); return ret; }
int main(int argc, char **argv) { struct tls_config *config = NULL; struct tls *tls = NULL; unsigned int protocols = 0; struct sockaddr_in server, client; int sock = socket(AF_INET, SOCK_STREAM, 0); int opt = 1; int b; struct tls *tls2 = NULL; ssize_t outlen = 0; char bufs[1000], bufc[1000]; int sc; char *msg = "HELLO TLS CLIENT\n"; char *ciphers = "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384"; struct pollfd pfd[2]; if(tls_init() < 0) { printf("tls_init error\n"); exit(1); } config = tls_config_new(); if(config == NULL) { printf("tls_config_new error\n"); exit(1); } tls = tls_server(); if(tls == NULL) { printf("tls_server error\n"); exit(1); } if(tls_config_parse_protocols(&protocols, "secure") < 0) { printf("tls_config_parse_protocols error\n"); exit(1); } tls_config_set_protocols(config, protocols); if(tls_config_set_ciphers(config, ciphers) < 0) { printf("tls_config_set_ciphers error\n"); exit(1); } if(tls_config_set_key_file(config, "private.pem") < 0) { printf("tls_config_set_key_file error\n"); exit(1); } if(tls_config_set_cert_file(config, "server.crt") < 0) { printf("tls_config_set_cert_file error\n"); exit(1); } if(tls_configure(tls, config) < 0) { printf("tls_configure error: %s\n", tls_error(tls)); exit(1); } bzero(&server, sizeof(server)); server.sin_addr.s_addr = inet_addr("127.0.0.1"); server.sin_port = htons(9000); server.sin_family = AF_INET; setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, 4); b = bind(sock, (struct sockaddr *) &server, sizeof(server)); if(b < 0) { printf("erro bind\n"); exit(1); } listen(sock, 10); socklen_t client_size = sizeof(client); sc = accept(sock, (struct sockaddr *) &client, &client_size); if(tls_accept_socket(tls, &tls2, sc) < 0) { printf("tls_accept_socket error\n"); exit(1); } tls_write(tls2, msg, strlen(msg)); pfd[0].fd = 0; pfd[0].events = POLLIN; pfd[1].fd = sc; pfd[1].events = POLLIN; while(bufc[0] != ':' && bufc[1] != 'q') { poll(pfd, 2, -1); bzero(bufs, 1000); bzero(bufc, 1000); if(pfd[0].revents & POLLIN) { int q = read(0, bufc, 1000); tls_write(tls2, bufc, q); } if(pfd[1].revents & POLLIN) { if((outlen = tls_read(tls2, bufs, 1000)) <= 0) break; printf("Mensagem (%lu): %s\n", outlen, bufs); } } tls_close(tls); tls_free(tls); tls_config_free(config); return 0; }
static int tls_connect(const char *srcaddr, const char *dstaddr, int timeout, void **ctxp) { struct tls_ctx *tlsctx; struct proto_conn *sock; pid_t pid; int error; PJDLOG_ASSERT(srcaddr == NULL || srcaddr[0] != '\0'); PJDLOG_ASSERT(dstaddr != NULL); PJDLOG_ASSERT(timeout >= -1); PJDLOG_ASSERT(ctxp != NULL); if (strncmp(dstaddr, "tls://", 6) != 0) return (-1); if (srcaddr != NULL && strncmp(srcaddr, "tls://", 6) != 0) return (-1); if (proto_connect(NULL, "socketpair://", -1, &sock) == -1) return (errno); #if 0 /* * We use rfork() with the following flags to disable SIGCHLD * delivery upon the sandbox process exit. */ pid = rfork(RFFDG | RFPROC | RFTSIGZMB | RFTSIGFLAGS(0)); #else /* * We don't use rfork() to be able to log information about sandbox * process exiting. */ pid = fork(); #endif switch (pid) { case -1: /* Failure. */ error = errno; proto_close(sock); return (error); case 0: /* Child. */ pjdlog_prefix_set("[TLS sandbox] (client) "); #ifdef HAVE_SETPROCTITLE setproctitle("[TLS sandbox] (client) "); #endif tls_call_exec_client(sock, srcaddr, dstaddr, timeout); /* NOTREACHED */ default: /* Parent. */ tlsctx = calloc(1, sizeof(*tlsctx)); if (tlsctx == NULL) { error = errno; proto_close(sock); (void)kill(pid, SIGKILL); return (error); } proto_send(sock, NULL, 0); tlsctx->tls_sock = sock; tlsctx->tls_tcp = NULL; tlsctx->tls_side = TLS_SIDE_CLIENT; tlsctx->tls_wait_called = false; tlsctx->tls_magic = TLS_CTX_MAGIC; if (timeout >= 0) { error = tls_connect_wait(tlsctx, timeout); if (error != 0) { (void)kill(pid, SIGKILL); tls_close(tlsctx); return (error); } } *ctxp = tlsctx; return (0); } }