diff options
author | Martin Willi <martin@revosec.ch> | 2010-08-23 14:22:38 +0200 |
---|---|---|
committer | Martin Willi <martin@revosec.ch> | 2010-08-23 15:13:37 +0200 |
commit | e6f3ef13303313ce4a87983fe640f958e07cc676 (patch) | |
tree | 7dd486d439e7b7975be96d5160a5ceaf5550a2ea /src/libtls/tls_peer.c | |
parent | 908e752201cc5cfc7f663e724f0ab3dc76c72d0a (diff) | |
download | strongswan-e6f3ef13303313ce4a87983fe640f958e07cc676.tar.bz2 strongswan-e6f3ef13303313ce4a87983fe640f958e07cc676.tar.xz |
Implemented TLS Alert handling
Diffstat (limited to 'src/libtls/tls_peer.c')
-rw-r--r-- | src/libtls/tls_peer.c | 64 |
1 files changed, 47 insertions, 17 deletions
diff --git a/src/libtls/tls_peer.c b/src/libtls/tls_peer.c index ddd117a87..a08e411c7 100644 --- a/src/libtls/tls_peer.c +++ b/src/libtls/tls_peer.c @@ -58,6 +58,11 @@ struct private_tls_peer_t { tls_crypto_t *crypto; /** + * TLS alert handler + */ + tls_alert_t *alert; + + /** * Peer identity */ identification_t *peer; @@ -125,7 +130,8 @@ static status_t process_server_hello(private_tls_peer_t *this, (reader->remaining(reader) && !reader->read_data16(reader, &ext))) { DBG1(DBG_TLS, "received invalid ServerHello"); - return FAILED; + this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR); + return NEED_MORE; } memcpy(this->server_random, random.ptr, sizeof(this->server_random)); @@ -134,14 +140,16 @@ static status_t process_server_hello(private_tls_peer_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; } suite = cipher; if (!this->crypto->select_cipher_suite(this->crypto, &suite, 1)) { DBG1(DBG_TLS, "received TLS cipher suite %N inacceptable", tls_cipher_suite_names, suite); - 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, suite); @@ -165,15 +173,19 @@ static status_t process_certificate(private_tls_peer_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); @@ -198,6 +210,7 @@ static status_t process_certificate(private_tls_peer_t *this, else { DBG1(DBG_TLS, "parsing TLS certificate failed, skipped"); + this->alert->add(this->alert, TLS_WARNING, TLS_BAD_CERTIFICATE); } } certs->destroy(certs); @@ -220,27 +233,35 @@ static status_t process_certreq(private_tls_peer_t *this, tls_reader_t *reader) if (!reader->read_data8(reader, &types)) { - return FAILED; + DBG1(DBG_TLS, "certreq message header invalid"); + this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR); + return NEED_MORE; } if (this->tls->get_version(this->tls) >= TLS_1_2) { if (!reader->read_data16(reader, &hashsig)) { - return FAILED; + DBG1(DBG_TLS, "certreq message invalid"); + this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR); + return NEED_MORE; } /* TODO: store supported hashsig algorithms */ } if (!reader->read_data16(reader, &data)) { - return FAILED; + DBG1(DBG_TLS, "certreq message invalid"); + this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR); + return NEED_MORE; } authorities = tls_reader_create(data); while (authorities->remaining(authorities)) { if (!authorities->read_data16(authorities, &data)) { + DBG1(DBG_TLS, "certreq message invalid"); + this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR); authorities->destroy(authorities); - return FAILED; + return NEED_MORE; } id = identification_create_from_encoding(ID_DER_ASN1_DN, data); cert = lib->credmgr->get_cert(lib->credmgr, @@ -284,17 +305,20 @@ static status_t process_finished(private_tls_peer_t *this, tls_reader_t *reader) if (!reader->read_data(reader, sizeof(buf), &received)) { DBG1(DBG_TLS, "received server 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, "server finished", buf)) { DBG1(DBG_TLS, "calculating server 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 server finished invalid"); - return FAILED; + this->alert->add(this->alert, TLS_FATAL, TLS_DECRYPT_ERROR); + return NEED_MORE; } this->state = STATE_COMPLETE; this->crypto->derive_eap_msk(this->crypto, @@ -348,11 +372,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; } /** @@ -370,7 +396,9 @@ static status_t send_client_hello(private_tls_peer_t *this, rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); if (!rng) { - return FAILED; + DBG1(DBG_TLS, "no suitable RNG found to generate client random"); + this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR); + return NEED_MORE; } rng->get_bytes(rng, sizeof(this->client_random) - 4, this->client_random + 4); rng->destroy(rng); @@ -420,7 +448,8 @@ static status_t send_certificate(private_tls_peer_t *this, if (!this->private) { DBG1(DBG_TLS, "no TLS peer certificate found for '%Y'", this->peer); - return FAILED; + this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR); + return NEED_MORE; } /* generate certificate payload */ @@ -640,7 +669,7 @@ METHOD(tls_handshake_t, destroy, void, /** * See header */ -tls_peer_t *tls_peer_create(tls_t *tls, tls_crypto_t *crypto, +tls_peer_t *tls_peer_create(tls_t *tls, tls_crypto_t *crypto, tls_alert_t *alert, identification_t *peer, identification_t *server) { private_tls_peer_t *this; @@ -659,6 +688,7 @@ tls_peer_t *tls_peer_create(tls_t *tls, tls_crypto_t *crypto, .state = STATE_INIT, .tls = tls, .crypto = crypto, + .alert = alert, .peer = peer, .server = server, .peer_auth = auth_cfg_create(), |