aboutsummaryrefslogtreecommitdiffstats
path: root/src/libtls/tls_server.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libtls/tls_server.c')
-rw-r--r--src/libtls/tls_server.c54
1 files changed, 39 insertions, 15 deletions
diff --git a/src/libtls/tls_server.c b/src/libtls/tls_server.c
index 3248a0c1a..4f988c603 100644
--- a/src/libtls/tls_server.c
+++ b/src/libtls/tls_server.c
@@ -60,6 +60,11 @@ struct private_tls_server_t {
tls_crypto_t *crypto;
/**
+ * TLS alert handler
+ */
+ tls_alert_t *alert;
+
+ /**
* Server identity
*/
identification_t *server;
@@ -132,7 +137,8 @@ static status_t process_client_hello(private_tls_server_t *this,
(reader->remaining(reader) && !reader->read_data16(reader, &ext)))
{
DBG1(DBG_TLS, "received invalid ClientHello");
- return FAILED;
+ this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
+ return NEED_MORE;
}
memcpy(this->client_random, random.ptr, sizeof(this->client_random));
@@ -141,7 +147,8 @@ static status_t process_client_hello(private_tls_server_t *this,
{
DBG1(DBG_TLS, "negotiated version %N not supported",
tls_version_names, version);
- return FAILED;
+ this->alert->add(this->alert, TLS_FATAL, TLS_PROTOCOL_VERSION);
+ return NEED_MORE;
}
count = ciphers.len / sizeof(u_int16_t);
suites = alloca(count * sizeof(tls_cipher_suite_t));
@@ -155,7 +162,8 @@ static status_t process_client_hello(private_tls_server_t *this,
if (!this->suite)
{
DBG1(DBG_TLS, "received cipher suites inacceptable");
- return FAILED;
+ this->alert->add(this->alert, TLS_FATAL, TLS_HANDSHAKE_FAILURE);
+ return NEED_MORE;
}
DBG1(DBG_TLS, "negotiated TLS version %N with suite %N",
tls_version_names, version, tls_cipher_suite_names, this->suite);
@@ -179,15 +187,19 @@ static status_t process_certificate(private_tls_server_t *this,
if (!reader->read_data24(reader, &data))
{
- return FAILED;
+ DBG1(DBG_TLS, "certificate message header invalid");
+ this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
+ return NEED_MORE;
}
certs = tls_reader_create(data);
while (certs->remaining(certs))
{
if (!certs->read_data24(certs, &data))
{
+ DBG1(DBG_TLS, "certificate message invalid");
+ this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
certs->destroy(certs);
- return FAILED;
+ return NEED_MORE;
}
cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
BUILD_BLOB_ASN1_DER, data, BUILD_END);
@@ -211,6 +223,7 @@ static status_t process_certificate(private_tls_server_t *this,
else
{
DBG1(DBG_TLS, "parsing TLS certificate failed, skipped");
+ this->alert->add(this->alert, TLS_WARNING, TLS_BAD_CERTIFICATE);
}
}
certs->destroy(certs);
@@ -232,7 +245,8 @@ static status_t process_key_exchange(private_tls_server_t *this,
if (!reader->read_data16(reader, &encrypted))
{
DBG1(DBG_TLS, "received invalid Client Key Exchange");
- return FAILED;
+ this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
+ return NEED_MORE;
}
if (!this->private ||
@@ -240,7 +254,8 @@ static status_t process_key_exchange(private_tls_server_t *this,
encrypted, &premaster))
{
DBG1(DBG_TLS, "decrypting Client Key Exchange data failed");
- return FAILED;
+ this->alert->add(this->alert, TLS_FATAL, TLS_DECRYPT_ERROR);
+ return NEED_MORE;
}
this->crypto->derive_secrets(this->crypto, premaster,
chunk_from_thing(this->client_random),
@@ -282,7 +297,8 @@ static status_t process_cert_verify(private_tls_server_t *this,
{
DBG1(DBG_TLS, "no trusted certificate found for '%Y' to verify TLS peer",
this->peer);
- return FAILED;
+ this->alert->add(this->alert, TLS_FATAL, TLS_CERTIFICATE_UNKNOWN);
+ return NEED_MORE;
}
this->crypto->append_handshake(this->crypto,
@@ -303,17 +319,20 @@ static status_t process_finished(private_tls_server_t *this,
if (!reader->read_data(reader, sizeof(buf), &received))
{
DBG1(DBG_TLS, "received client finished too short");
- return FAILED;
+ this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
+ return NEED_MORE;
}
if (!this->crypto->calculate_finished(this->crypto, "client finished", buf))
{
DBG1(DBG_TLS, "calculating client finished failed");
- return FAILED;
+ this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
+ return NEED_MORE;
}
if (!chunk_equals(received, chunk_from_thing(buf)))
{
DBG1(DBG_TLS, "received client finished invalid");
- return FAILED;
+ this->alert->add(this->alert, TLS_FATAL, TLS_DECRYPT_ERROR);
+ return NEED_MORE;
}
this->crypto->append_handshake(this->crypto, TLS_FINISHED, received);
@@ -377,11 +396,13 @@ METHOD(tls_handshake_t, process, status_t,
default:
DBG1(DBG_TLS, "TLS %N not expected in current state",
tls_handshake_type_names, type);
- return FAILED;
+ this->alert->add(this->alert, TLS_FATAL, TLS_UNEXPECTED_MESSAGE);
+ return NEED_MORE;
}
DBG1(DBG_TLS, "TLS %N expected, but received %N",
tls_handshake_type_names, expected, tls_handshake_type_names, type);
- return FAILED;
+ this->alert->add(this->alert, TLS_FATAL, TLS_UNEXPECTED_MESSAGE);
+ return NEED_MORE;
}
/**
@@ -397,6 +418,7 @@ static status_t send_server_hello(private_tls_server_t *this,
rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
if (!rng)
{
+ DBG1(DBG_TLS, "no suitable RNG found to generate server random");
return FAILED;
}
rng->get_bytes(rng, sizeof(this->server_random) - 4, this->server_random + 4);
@@ -630,8 +652,9 @@ METHOD(tls_handshake_t, destroy, void,
/**
* See header
*/
-tls_server_t *tls_server_create(tls_t *tls, tls_crypto_t *crypto,
- identification_t *server, identification_t *peer)
+tls_server_t *tls_server_create(tls_t *tls,
+ tls_crypto_t *crypto, tls_alert_t *alert,
+ identification_t *server, identification_t *peer)
{
private_tls_server_t *this;
@@ -648,6 +671,7 @@ tls_server_t *tls_server_create(tls_t *tls, tls_crypto_t *crypto,
},
.tls = tls,
.crypto = crypto,
+ .alert = alert,
.server = server,
.peer = peer,
.state = STATE_INIT,