int https_connect(struct url *url, struct url *proxy) { static struct tls_config *tls_config = NULL; int s; /* One time initialization */ if (tls_config == NULL) tls_config = https_init(); if ((ctx = tls_client()) == NULL) { warnx("failed to create tls client"); return -1; } if (tls_configure(ctx, tls_config) != 0) { warnx("%s: %s", __func__, tls_error(ctx)); return -1; } if (url->port[0] == '\0') (void)strlcpy(url->port, "443", sizeof(url->port)); if ((s = http_connect(url, proxy)) == -1) return -1; if (tls_connect_socket(ctx, s, url->host) != 0) { warnx("%s: %s", __func__, tls_error(ctx)); return -1; } return s; }
void connection_init_tls() { tls_init(); CurrentConnectionState.TlsConfiguration = tls_config_new(); CurrentConnectionState.ServerContext = tls_server(); CurrentConnectionState.ClientContext = tls_client(); tls_config_set_key_file(CurrentConnectionState.TlsConfiguration, CurrentConnectionState.PrivateKey); tls_config_set_cert_file(CurrentConnectionState.TlsConfiguration, CurrentConnectionState.CertificateFile); tls_config_insecure_noverifycert(CurrentConnectionState.TlsConfiguration); if(tls_configure(CurrentConnectionState.ServerContext, CurrentConnectionState.TlsConfiguration) != 0) { printf("%s\n", tls_error(CurrentConnectionState.ServerContext)); } if(tls_configure(CurrentConnectionState.ClientContext, CurrentConnectionState.TlsConfiguration) != 0) { printf("%s\n", tls_error(CurrentConnectionState.ClientContext)); } }
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 tls_init_client_cert_verification(const char *cert_file) { if (cert_file == NULL) { tls_error(__LINE__, 0); } SSL_CTX_set_verify(tls_ctx, SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_PEER, NULL); if (SSL_CTX_load_verify_locations(tls_ctx, cert_file, NULL) != 1) { tls_error(__LINE__, 0); } }
int tls_init_data_session(const int fd, const int passive) { const SSL_CIPHER *cipher; int ret; int ret_; (void) passive; if (tls_ctx == NULL) { logfile(LOG_ERR, MSG_TLS_NO_CTX); tls_error(__LINE__, 0); } if (tls_data_cnx != NULL) { tls_close_session(&tls_data_cnx); } else if ((tls_data_cnx = SSL_new(tls_ctx)) == NULL) { tls_error(__LINE__, 0); } if (SSL_set_fd(tls_data_cnx, fd) != 1) { tls_error(__LINE__, 0); } SSL_set_accept_state(tls_data_cnx); for (;;) { ret = SSL_accept(tls_data_cnx); if (ret <= 0) { ret_ = SSL_get_error(tls_data_cnx, ret); if (ret == -1 && (ret_ == SSL_ERROR_WANT_READ || ret_ == SSL_ERROR_WANT_WRITE)) { continue; } logfile(LOG_INFO, MSG_LOGOUT); _EXIT(EXIT_FAILURE); } break; } # if ONLY_ACCEPT_REUSED_SSL_SESSIONS if (broken_client_compat == 0 && SSL_session_reused(tls_data_cnx) == 0) { tls_error(__LINE__, 0); } # endif if ((cipher = SSL_get_current_cipher(tls_data_cnx)) != NULL) { int strength_bits = SSL_CIPHER_get_bits(cipher, NULL); logfile(LOG_INFO, MSG_TLS_INFO, SSL_CIPHER_get_version(cipher), SSL_CIPHER_get_name(cipher), strength_bits); if (strength_bits < MINIMAL_CIPHER_STRENGTH_BITS) { die(534, LOG_ERR, MSG_TLS_WEAK); } } return 0; }
static int copy_from_tls_to_stdout(struct tls *ctx) { static size_t buf[BUFSIZE]; ssize_t n,r; int i = 0; dbg("DEBUG: data from TLS\n"); do { n = tls_read(ctx, buf, sizeof(buf)); } while (n == TLS_WANT_POLLIN || r == TLS_WANT_POLLOUT); if (n < 0) err(1, "tls read: %s", tls_error(ctx)); if (n == 0) return 1; while (n) { r = write(STDOUT_FILENO, &buf[i], n); if (r < 0) err(1, "write"); i += r; n -= r; } return 0; }
/*-------------------------------------------------------------------------*/ svalue_t * f_tls_error(svalue_t *sp) /* EFUN tls_error() * * string tls_error(int errorno) * * tls_error() returns a string describing the error behind the * error number <errorno>. */ { string_t *s; const char *text; int err = sp->u.number; text = tls_error(err); if (text) { memsafe(s = new_mstring(text), strlen(text), "tls_error()"); free_svalue(sp); put_string(sp, s); } else { free_svalue(sp); put_number(sp, 0); } return sp; } /* f_tls_error() */
static int _handle_proceedtls_default(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata) { char *name; name = xmpp_stanza_get_name(stanza); xmpp_debug(conn->ctx, "xmpp", "handle proceedtls called for %s", name); if (strcmp(name, "proceed") == 0) { xmpp_debug(conn->ctx, "xmpp", "proceeding with TLS"); conn->tls = tls_new(conn->ctx, conn->sock); if (!tls_start(conn->tls)) { xmpp_debug(conn->ctx, "xmpp", "Couldn't start TLS! error %d", tls_error(conn->tls)); tls_free(conn->tls); conn->tls = NULL; conn->tls_failed = 1; /* failed tls spoils the connection, so disconnect */ xmpp_disconnect(conn); } else { conn->secured = 1; conn_prepare_reset(conn, auth_handle_open); conn_open_stream(conn); } } return 0; }
int conn_tls_start(xmpp_conn_t * const conn) { int rc; if (conn->tls_disabled) { conn->tls = NULL; rc = XMPP_EINVOP; } else { conn->tls = tls_new(conn); rc = conn->tls == NULL ? XMPP_EMEM : 0; } if (conn->tls != NULL) { if (tls_start(conn->tls)) { conn->secured = 1; } else { rc = XMPP_EINT; conn->error = tls_error(conn->tls); tls_free(conn->tls); conn->tls = NULL; conn->tls_failed = 1; } } if (rc != 0) { xmpp_debug(conn->ctx, "conn", "Couldn't start TLS! " "error %d tls_error %d", rc, conn->error); } return rc; }
tls_t *tls_new(xmpp_ctx_t *ctx, xmpp_sock_t sock) { tls_t *tls = xmpp_alloc(ctx, sizeof(*tls)); if (tls) { int ret; memset(tls, 0, sizeof(*tls)); tls->ctx = ctx; tls->sock = sock; tls->ssl_ctx = SSL_CTX_new(SSLv23_client_method()); SSL_CTX_set_client_cert_cb(tls->ssl_ctx, NULL); SSL_CTX_set_mode (tls->ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE); SSL_CTX_set_verify (tls->ssl_ctx, SSL_VERIFY_NONE, NULL); tls->ssl = SSL_new(tls->ssl_ctx); ret = SSL_set_fd(tls->ssl, sock); if (ret <= 0) { tls->lasterror = SSL_get_error(tls->ssl, ret); tls_error(tls); tls_free(tls); tls = NULL; } } return tls; }
static const char *check_fp(struct Worker *w, const char *algo, const char *fn, size_t xlen) { const char *emsg; int res; struct tls_cert *cert = NULL; static char buf[1024]; if (!fn) return NULL; res = tls_get_peer_cert(w->ctx, &cert, algo); if (res != 0) { snprintf(buf, sizeof buf, "fp-cert: %s", tls_error(w->ctx)); return buf; } if (cert->fingerprint_size != xlen) { tls_cert_free(cert); return "FP-sha1-fail"; } emsg = hexcmp(fn, cert->fingerprint, cert->fingerprint_size); tls_cert_free(cert); if (emsg) return emsg; return NULL; }
static void copy_from_stdin_to_tls(struct tls *ctx, int *fd) { static size_t buf[BUFSIZE]; ssize_t n; int i = 0; dbg("DEBUG: data from STDIN\n"); do { n = read(STDIN_FILENO, buf, sizeof(buf)); dbg("read %zu\n", n); } while (n < 0 && errno == EINTR); if (n < 1) { *fd = -1; return; } while (n > 0) { ssize_t r = tls_write(ctx, &buf[i], n); if (r == TLS_WANT_POLLIN || r == TLS_WANT_POLLOUT) continue; if (r < 0) err(1, "tls_write: %s", tls_error(ctx)); i += r; n -= r; } }
ssize_t tls_read(tls_t *tls) { ssize_t ret; if (tls == NULL) { errno = EINVAL; return -1; } if (0) SU_DEBUG_1(("tls_read(%p) called on %s (events %u)\n", (void *)tls, tls->type ? "master" : "slave", tls->read_events)); if (tls->read_buffer_len) return (ssize_t)tls->read_buffer_len; tls->read_events = SU_WAIT_IN; ret = SSL_read(tls->con, tls->read_buffer, tls_buffer_size); if (ret <= 0) return tls_error(tls, ret, "tls_read: SSL_read", NULL, 0); return (ssize_t)(tls->read_buffer_len = ret); }
static void https_vprintf(struct tls *tls, const char *fmt, ...) { va_list ap, ap2; char *string; ssize_t nw; int len; va_start(ap, fmt); if (ftp_debug) { va_copy(ap2, ap); fprintf(stderr, ">>> "); vfprintf(stderr, fmt, ap2); va_end(ap2); } if ((len = vasprintf(&string, fmt, ap)) == -1) errx(1, "%s: vasprintf failed", __func__); va_end(ap); again: nw = tls_write(tls, string, len); if (nw == TLS_WANT_POLLIN || nw == TLS_WANT_POLLOUT) goto again; else if (nw < 0) errx(1, "%s: tls_write: %s", __func__, tls_error(tls)); free(string); }
int conn_tls_start(xmpp_conn_t * const conn) { int rc; if (conn->tls_disabled) { conn->tls = NULL; rc = -ENOSYS; } else { conn->tls = tls_new(conn->ctx, conn->sock); rc = conn->tls == NULL ? -ENOMEM : 0; } if (conn->tls != NULL) { if (tls_start(conn->tls)) { conn->secured = 1; conn_prepare_reset(conn, auth_handle_open); } else { rc = tls_error(conn->tls); conn->error = rc; tls_free(conn->tls); conn->tls = NULL; conn->tls_failed = 1; } } if (rc != 0) xmpp_debug(conn->ctx, "conn", "Couldn't start TLS! error %d", rc); return rc; }
static int init_https(void) { if(!SERVER_PORT_TLS) return 0; struct tls_config *config = tls_config_new(); if(!config) { alogf("TLS config error: %s\n", strerror(errno)); return -1; } int rc = tls_config_set_ciphers(config, TLS_CIPHERS); if(0 != rc) { alogf("TLS ciphers error: %s\n", strerror(errno)); tls_config_free(config); config = NULL; return -1; } tls_config_set_protocols(config, TLS_PROTOCOLS); str_t pemfile[PATH_MAX]; snprintf(pemfile, sizeof(pemfile), "%s/key.pem", path); rc = tls_config_set_key_file(config, pemfile); if(0 != rc) { alogf("TLS key file error: %s\n", strerror(errno)); tls_config_free(config); config = NULL; return -1; } snprintf(pemfile, sizeof(pemfile), "%s/crt.pem", path); rc = tls_config_set_cert_file(config, pemfile); if(0 != rc) { alogf("TLS crt file error: %s\n", strerror(errno)); tls_config_free(config); config = NULL; return -1; } struct tls *tls = tls_server(); if(!tls) { alogf("TLS engine error: %s\n", strerror(errno)); tls_config_free(config); config = NULL; return -1; } rc = tls_configure(tls, config); tls_config_free(config); config = NULL; if(0 != rc) { alogf("TLS config error: %s\n", tls_error(tls)); tls_free(tls); tls = NULL; return -1; } server_tls = HTTPServerCreate((HTTPListener)listener, blog); if(!server_tls) { alogf("HTTPS server could not be initialized\n"); tls_free(tls); tls = NULL; return -1; } rc = HTTPServerListenSecure(server_tls, SERVER_ADDRESS, SERVER_PORT_TLS, &tls); tls_free(tls); tls = NULL; if(rc < 0) { alogf("HTTPS server could not be started: %s\n", sln_strerror(rc)); return -1; } int const port = SERVER_PORT_TLS; alogf("StrongLink server running at https://localhost:%d/\n", port); return 0; }
json_t* recvOverTLS(struct tls*ctx) { json_error_t error; size_t getSize, size; size_t len = sizeof(getSize); // read length while (len > 0) { int ret = tls_read(ctx, &getSize, len, &size); if (ret == TLS_READ_AGAIN || ret == TLS_WRITE_AGAIN) { /* retry. May use select to wait for nonblocking */ } else if (ret < 0) { syslog(LOG_ERR, "%s\n", tls_error(ctx)); break; } else { len -= size; } } // create buffer char* buffer = (char*)malloc((getSize +1) *sizeof(char)); char* buf = buffer; while (getSize > 0) { int ret = tls_read(ctx, buf, getSize, &size); if (ret == TLS_READ_AGAIN || ret == TLS_WRITE_AGAIN) { /* retry. May use select to wait for nonblocking */ } else if (ret < 0) { syslog(LOG_ERR, "%s\n", tls_error(ctx)); break; } else { buf += size; getSize -= size; } } // Process buffer to json json_t *json = json_loads(buffer, JSON_DISABLE_EOF_CHECK, &error); if (verbose_flag) { syslog(LOG_DEBUG, "%s\n", buffer); } return json; }
static void record_io_error(int ec, uschar *when, uschar *text) { const char *msg; if (ec == GNUTLS_E_FATAL_ALERT_RECEIVED) msg = string_sprintf("%s: %s", gnutls_strerror(ec), gnutls_alert_get_name(gnutls_alert_get(tls_session))); else msg = gnutls_strerror(ec); tls_error(when, client_host, msg); }
static void https_retr_file(const char *fn, off_t file_sz, off_t offset) { size_t wlen; ssize_t i, r; char *cp; static char *buf; int fd, flags; if (buf == NULL) { buf = malloc(TMPBUF_LEN); /* allocate once */ if (buf == NULL) err(1, "%s: malloc", __func__); } flags = O_CREAT | O_WRONLY; if (offset) flags |= O_APPEND; if (strcmp(fn, "-") == 0) fd = STDOUT_FILENO; else if ((fd = open(fn, flags, 0666)) == -1) err(1, "%s: open %s", __func__, fn); start_progress_meter(file_sz, &offset); while (1) { r = tls_read(ctx, buf, TMPBUF_LEN); if (r == TLS_WANT_POLLIN || r == TLS_WANT_POLLOUT) continue; else if (r < 0) { errx(1, "%s: tls_read: %s", __func__, tls_error(ctx)); } if (r == 0) break; offset += r; for (cp = buf, wlen = r; wlen > 0; wlen -= i, cp += i) { if ((i = write(fd, cp, wlen)) == -1) { if (errno != EINTR) err(1, "%s: write", __func__); } else if (i == 0) break; } } if (strcmp(fn, "-") != 0) close(fd); stop_progress_meter(); }
void HttpProxyPost::sock_connected() { #ifdef PROX_DEBUG fprintf(stderr, "HttpProxyPost: Connected\n"); #endif if(d->useSsl) { d->tls = new QCA::TLS(this); connect(d->tls, SIGNAL(readyRead()), SLOT(tls_readyRead())); connect(d->tls, SIGNAL(readyReadOutgoing()), SLOT(tls_readyReadOutgoing())); connect(d->tls, SIGNAL(error()), SLOT(tls_error())); d->tls->startClient(); } d->lastAddress = d->sock.peerAddress(); d->inHeader = true; d->headerLines.clear(); QUrl u = d->url; // connected, now send the request QString s; s += QString("POST ") + d->url + " HTTP/1.1\r\n"; if(d->asProxy) { if(!d->user.isEmpty()) { QString str = d->user + ':' + d->pass; s += QString("Proxy-Authorization: Basic ") + QCA::Base64().encodeString(str) + "\r\n"; } s += "Pragma: no-cache\r\n"; s += QString("Host: ") + u.host() + "\r\n"; } else { s += QString("Host: ") + d->host + "\r\n"; } s += "Content-Type: application/x-www-form-urlencoded\r\n"; s += QString("Content-Length: ") + QString::number(d->postdata.size()) + "\r\n"; s += "\r\n"; if(d->useSsl) { // write request d->tls->write(s.toUtf8()); // write postdata d->tls->write(d->postdata); } else { // write request d->sock.write(s.toUtf8()); // write postdata d->sock.write(d->postdata); } }
static const char *start_worker(struct Worker *w, int fd) { int err; w->socket = fd; if (w->is_server) { err = tls_accept_socket(w->base, &w->ctx, fd); } else { err = tls_connect_socket(w->ctx, fd, w->hostname); } if (err != 0) { return tls_error(w->ctx ? w->ctx : w->base); } return do_handshake(w, fd); }
static int tls_create_new_context(const char *cert_file, const char *key_file) { # ifdef HAVE_TLS_SERVER_METHOD if ((tls_ctx = SSL_CTX_new(TLS_server_method())) == NULL) { tls_error(__LINE__, 0); } # else if ((tls_ctx = SSL_CTX_new(SSLv23_server_method())) == NULL) { tls_error(__LINE__, 0); } # endif tls_init_options(); tls_init_cache(); tls_load_cert_file(cert_file, key_file); if (ssl_verify_client_cert) { tls_init_client_cert_verification(cert_file); } tls_init_ecdh_curve(); tls_init_dhparams(); return 0; }
int tls_init_new_session(void) { const SSL_CIPHER *cipher; int ret; int ret_; if (tls_ctx == NULL || (tls_cnx = SSL_new(tls_ctx)) == NULL) { tls_error(__LINE__, 0); } if (SSL_set_fd(tls_cnx, clientfd) != 1) { tls_error(__LINE__, 0); } SSL_set_accept_state(tls_cnx); for (;;) { ret = SSL_accept(tls_cnx); if (ret != 1) { ret_ = SSL_get_error(tls_cnx, ret); if (ret == -1 && (ret_ == SSL_ERROR_WANT_READ || ret_ == SSL_ERROR_WANT_WRITE)) { continue; } die(400, LOG_WARNING, MSG_TLS_NEEDED); } break; } if ((cipher = SSL_get_current_cipher(tls_cnx)) != NULL) { int strength_bits = SSL_CIPHER_get_bits(cipher, NULL); logfile(LOG_INFO, MSG_TLS_INFO, SSL_CIPHER_get_version(cipher), SSL_CIPHER_get_name(cipher), strength_bits); if (strength_bits < MINIMAL_CIPHER_STRENGTH_BITS) { die(534, LOG_ERR, MSG_TLS_WEAK); } } return 0; }
void sendOverTLS(struct tls* ctx, const char *buf) { size_t sent; // send Length of buf size_t length = strlen(buf); size_t len = sizeof(length); while (len > 0) { int ret = tls_write(ctx, &length, len, &sent); if (ret == TLS_READ_AGAIN || ret == TLS_WRITE_AGAIN) { syslog(LOG_DEBUG, "READ/WRITE AGAIN\n"); } else if (ret < 0) { syslog(LOG_ERR, "%s\n", tls_error(ctx)); break; } else { len -= sent; } } // send actual buf size_t toSend = length; while (toSend > 0) { int ret = tls_write(ctx, buf, toSend, &sent); if (ret == TLS_READ_AGAIN || ret == TLS_WRITE_AGAIN) { syslog(LOG_DEBUG, "READ/WRITE AGAIN\n"); } else if (ret < 0) { syslog(LOG_ERR, "%s\n", tls_error(ctx)); break; } else { buf += sent; toSend -= sent; } } }
static void tls_load_cert_file(const char * const cert_file, const char * const key_file) { if (SSL_CTX_use_certificate_chain_file(tls_ctx, cert_file) != 1) { die(421, LOG_ERR, MSG_FILE_DOESNT_EXIST ": [%s]", cert_file); } if (SSL_CTX_use_PrivateKey_file(tls_ctx, key_file, SSL_FILETYPE_PEM) != 1) { die(421, LOG_ERR, MSG_FILE_DOESNT_EXIST ": [%s]", key_file); } if (SSL_CTX_check_private_key(tls_ctx) != 1) { tls_error(__LINE__, 0); } }
static const char *do_handshake(struct Worker *w, int fd) { int err; const char *msg; err = tls_handshake(w->ctx); if (err == TLS_WANT_POLLIN) { return wait_for_event(w, EV_READ); } else if (err == TLS_WANT_POLLIN) { return wait_for_event(w, EV_WRITE); } else if (err == 0) { w->wstate = CONNECTED; return done_handshake(w); } msg = tls_error(w->ctx ? w->ctx : w->base); return msg ? msg : "handshake failure"; }
ssize_t tls_write(tls_t *tls, void *buf, size_t size) { ssize_t ret; if (0) SU_DEBUG_1(("tls_write(%p, %p, "MOD_ZU") called on %s\n", (void *)tls, buf, size, tls && tls->type == tls_slave ? "master" : "slave")); if (tls == NULL || buf == NULL) { errno = EINVAL; return -1; } if (tls->write_buffer) { assert(buf == tls->write_buffer); assert(size >= tls->write_buffer_len); assert(tls->write_events == 0); if (tls->write_events || buf != tls->write_buffer || size < tls->write_buffer_len) { errno = EIO; return -1; } ret = tls->write_buffer_len; tls->write_buffer = NULL; tls->write_buffer_len = 0; return ret; } if (size == 0) return 0; tls->write_events = 0; ret = SSL_write(tls->con, buf, size); if (ret < 0) return tls_error(tls, ret, "tls_write: SSL_write", buf, size); return ret; }
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); }
void tls_close_session(SSL ** const cnx) { unsigned int retries = 10U; unsigned int max_shutdowns = 2; if (*cnx == NULL) { return; } retry: switch (SSL_shutdown(*cnx)) { case 0: if (--max_shutdowns > 0) { goto retry; } case 1: break; default: { switch (SSL_get_error(*cnx, -1)) { case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: { struct pollfd pfd; pfd.fd = SSL_get_fd(*cnx); pfd.events = POLLIN | POLLOUT | POLLERR | POLLHUP; pfd.revents = 0; if (poll(&pfd, 1U, idletime * 1000UL) > 0 && retries-- > 0U) { goto retry; } } } if (SSL_clear(*cnx) == 1) { break; } tls_error(__LINE__, 0); } } if (*cnx == tls_cnx) { tls_cnx_handshook = 0; } else if (*cnx == tls_data_cnx) { tls_data_cnx_handshook = 0; } SSL_free(*cnx); *cnx = NULL; }
static const char *run_time(const char *val) { #ifdef USUAL_LIBSSL_FOR_TLS ASN1_TIME tmp; time_t t = 0; static char buf[128]; struct tm *tm, tmbuf; struct tls *ctx; int err; memset(&tmp, 0, sizeof tmp); memset(&tmbuf, 0, sizeof tmbuf); tmp.data = (unsigned char*)val+2; tmp.length = strlen(val+2); if (val[0] == 'G' && val[1] == ':') { tmp.type = V_ASN1_GENERALIZEDTIME; } else if (val[0] == 'U' && val[1] == ':') { tmp.type = V_ASN1_UTCTIME; } else { tmp.type = val[0]; } ctx = tls_client(); if (!ctx) return "NOMEM"; err = tls_asn1_parse_time(ctx, &tmp, &t); if (err) { strlcpy(buf, tls_error(ctx), sizeof buf); tls_free(ctx); return buf; } tls_free(ctx); tm = gmtime_r(&t, &tmbuf); if (!tm) return "E-GMTIME"; strftime(buf, sizeof buf, "%Y-%m-%d %H:%M:%S GMT", tm); return buf; #else return "no-asn1"; #endif }