talloc_set_destructor(ssn, _tls_session_free);
ssn->ctx = conf->ctx;
+ ssn->mtu = conf->fragment_size;
SSL_CTX_set_mode(ssn->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_AUTO_RETRY);
SSL_set_ex_data(ssn->ssl, FR_TLS_EX_INDEX_SSN, (void *)ssn);
SSL_set_fd(ssn->ssl, fd);
ret = SSL_connect(ssn->ssl);
+
+ if (ret < 0) {
+ switch (SSL_get_error(ssn->ssl, ret)) {
+ default:
+ break;
+
+
+
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ ssn->connected = false;
+ return ssn;
+ }
+ }
+
if (ret <= 0) {
tls_error_io_log(NULL, ssn, ret, "Failed in " STRINGIFY(__FUNCTION__) " (SSL_connect)");
talloc_free(ssn);
return NULL;
}
- ssn->mtu = conf->fragment_size;
-
+ ssn->connected = true;
return ssn;
}
-
/** Create a new TLS session
*
* Configures a new TLS session, configuring options, setting callbacks etc...
static void session_close(tls_session_t *ssn)
{
- SSL_set_quiet_shutdown(ssn->ssl, 1);
- SSL_shutdown(ssn->ssl);
-
if (ssn->ssl) {
+ SSL_set_quiet_shutdown(ssn->ssl, 1);
+ SSL_shutdown(ssn->ssl);
+
SSL_free(ssn->ssl);
ssn->ssl = NULL;
}
/* open output file */
snprintf(filename, sizeof(filename), "%s%c%s.asn1",
conf->session_cache_path, FR_DIR_SEP, buffer);
- fd = open(filename, O_RDWR|O_CREAT|O_EXCL, 0600);
+ fd = open(filename, O_RDWR|O_CREAT|O_EXCL, S_IWUSR);
if (fd < 0) {
if (request) RERROR("Session serialisation failed, failed opening session file %s: %s",
filename, fr_syserror(errno));
fr_pair_value_strcpy(vp, filename);
fr_pair_add(&request->state, vp);
}
-
- (void) fchmod(fd, S_IWUSR);
}
todo = blob_len;
/*
* Get the RFC822 Subject Alternative Name
*/
- loc = X509_get_ext_by_NID(client_cert, NID_subject_alt_name, 0);
+ loc = X509_get_ext_by_NID(client_cert, NID_subject_alt_name, -1);
if (certs && (lookup <= 1) && (loc >= 0)) {
X509_EXTENSION *ext = NULL;
GENERAL_NAMES *names = NULL;
}
if (lookup == 0) {
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
ext_list = X509_get0_extensions(client_cert);
#else
X509_CINF *client_inf;
true, true, EXEC_TIMEOUT) != 0) {
AUTH(LOG_PREFIX ": Certificate CN (%s) fails external verification!", common_name);
my_ok = 0;
- } else {
+
+ } else if (request) {
RDEBUG("Client certificate CN %s passed external validation", common_name);
}
#endif
#endif
+/*
+ * DIE OPENSSL DIE DIE DIE
+ *
+ * What a palaver, just to free some data attached the
+ * session. We need to do this because the "remove" callback
+ * is called when refcount > 0 sometimes, if another thread
+ * is using the session
+ */
+static void sess_free_vps(UNUSED void *parent, void *data_ptr,
+ UNUSED CRYPTO_EX_DATA *ad, UNUSED int idx,
+ UNUSED long argl, UNUSED void *argp)
+{
+ VALUE_PAIR *vp = data_ptr;
+ if (!vp) return;
+
+ DEBUG2(LOG_PREFIX ": Freeing cached session VPs");
+
+ fr_pair_list_free(&vp);
+}
+
+static void sess_free_certs(UNUSED void *parent, void *data_ptr,
+ UNUSED CRYPTO_EX_DATA *ad, UNUSED int idx,
+ UNUSED long argl, UNUSED void *argp)
+{
+ VALUE_PAIR **certs = data_ptr;
+ if (!certs) return;
+
+ DEBUG2(LOG_PREFIX ": Freeing cached session Certificates");
+
+ fr_pair_list_free(certs);
+}
+
/** Add all the default ciphers and message digests reate our context.
*
* This should be called exactly once from main, before reading the main config
/*
* Initialize the index for the certificates.
*/
- fr_tls_ex_index_certs = SSL_SESSION_get_ex_new_index(0, NULL, NULL, NULL, NULL);
+ fr_tls_ex_index_certs = SSL_SESSION_get_ex_new_index(0, NULL, NULL, NULL, sess_free_certs);
}
#ifdef ENABLE_OPENSSL_VERSION_CHECK
SSL_CTX_set_quiet_shutdown(ctx, 1);
if (fr_tls_ex_index_vps < 0)
- fr_tls_ex_index_vps = SSL_SESSION_get_ex_new_index(0, NULL, NULL, NULL, NULL);
+ fr_tls_ex_index_vps = SSL_SESSION_get_ex_new_index(0, NULL, NULL, NULL, sess_free_vps);
}
/*
}
/*
- * Cache it, and DON'T auto-clear it.
+ * Cache it, DON'T auto-clear it, and disable the internal OpenSSL session cache.
*/
- SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER | SSL_SESS_CACHE_NO_AUTO_CLEAR);
+ SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER | SSL_SESS_CACHE_NO_AUTO_CLEAR | SSL_SESS_CACHE_NO_INTERNAL);
SSL_CTX_set_session_id_context(ctx,
(unsigned char *) conf->session_context_id,
return 0;
}
-static fr_tls_server_conf_t *tls_server_conf_alloc(TALLOC_CTX *ctx)
+fr_tls_server_conf_t *tls_server_conf_alloc(TALLOC_CTX *ctx)
{
fr_tls_server_conf_t *conf;
*/
if (conf->fragment_size < 100) conf->fragment_size = 100;
- if (!conf->private_key_file) {
- ERROR(LOG_PREFIX ": TLS Server requires a private key file");
- goto error;
- }
+ /*
+ * Only check for certificate things if we don't have a
+ * PSK query.
+ */
+ if (conf->psk_identity) {
+ if (conf->private_key_file) {
+ WARN(LOG_PREFIX ": Ignoring private key file due to psk_identity being used");
+ }
- if (!conf->certificate_file) {
- ERROR(LOG_PREFIX ": TLS Server requires a certificate file");
- goto error;
+ if (conf->certificate_file) {
+ WARN(LOG_PREFIX ": Ignoring certificate file due to psk_identity being used");
+ }
+
+ } else {
+ if (!conf->private_key_file) {
+ ERROR(LOG_PREFIX ": TLS Server requires a private key file");
+ goto error;
+ }
+
+ if (!conf->certificate_file) {
+ ERROR(LOG_PREFIX ": TLS Server requires a certificate file");
+ goto error;
+ }
}
/*