diff options
Diffstat (limited to 'src/libtls/tls_server.c')
-rw-r--r-- | src/libtls/tls_server.c | 54 |
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, |