aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/libtls/tls.c22
-rw-r--r--src/libtls/tls.h8
-rw-r--r--src/libtls/tls_handshake.h14
-rw-r--r--src/libtls/tls_peer.c23
-rw-r--r--src/libtls/tls_peer.h8
-rw-r--r--src/libtls/tls_server.c25
-rw-r--r--src/libtls/tls_server.h7
7 files changed, 78 insertions, 29 deletions
diff --git a/src/libtls/tls.c b/src/libtls/tls.c
index 85a05a00b..6d33d843d 100644
--- a/src/libtls/tls.c
+++ b/src/libtls/tls.c
@@ -107,16 +107,6 @@ struct private_tls_t {
bool is_server;
/**
- * Server identity
- */
- identification_t *server;
-
- /**
- * Peer identity
- */
- identification_t *peer;
-
- /**
* Negotiated TLS version
*/
tls_version_t version;
@@ -362,13 +352,13 @@ METHOD(tls_t, is_server, bool,
METHOD(tls_t, get_server_id, identification_t*,
private_tls_t *this)
{
- return this->server;
+ return this->handshake->get_server_id(this->handshake);
}
METHOD(tls_t, get_peer_id, identification_t*,
private_tls_t *this)
{
- return this->peer;
+ return this->handshake->get_peer_id(this->handshake);
}
METHOD(tls_t, get_version, tls_version_t,
@@ -433,8 +423,6 @@ METHOD(tls_t, destroy, void,
this->fragmentation->destroy(this->fragmentation);
this->crypto->destroy(this->crypto);
this->handshake->destroy(this->handshake);
- DESTROY_IF(this->peer);
- this->server->destroy(this->server);
DESTROY_IF(this->application);
this->alert->destroy(this->alert);
@@ -480,8 +468,6 @@ tls_t *tls_create(bool is_server, identification_t *server,
},
.is_server = is_server,
.version = TLS_1_2,
- .server = server->clone(server),
- .peer = peer ? peer->clone(peer) : NULL,
.application = application,
.purpose = purpose,
);
@@ -491,12 +477,12 @@ tls_t *tls_create(bool is_server, identification_t *server,
if (is_server)
{
this->handshake = &tls_server_create(&this->public, this->crypto,
- this->alert, this->server, this->peer)->handshake;
+ this->alert, server, peer)->handshake;
}
else
{
this->handshake = &tls_peer_create(&this->public, this->crypto,
- this->alert, this->peer, this->server)->handshake;
+ this->alert, peer, server)->handshake;
}
this->fragmentation = tls_fragmentation_create(this->handshake, this->alert,
this->application);
diff --git a/src/libtls/tls.h b/src/libtls/tls.h
index c8186b829..7f45b1e09 100644
--- a/src/libtls/tls.h
+++ b/src/libtls/tls.h
@@ -193,16 +193,16 @@ struct tls_t {
bool (*is_server)(tls_t *this);
/**
- * Return the server identity
+ * Return the server identity.
*
- * @return Server identity
+ * @return server identity
*/
identification_t* (*get_server_id)(tls_t *this);
/**
- * Return the peer identity
+ * Return the peer identity.
*
- * @return Peer identity
+ * @return peer identity
*/
identification_t* (*get_peer_id)(tls_t *this);
diff --git a/src/libtls/tls_handshake.h b/src/libtls/tls_handshake.h
index bea0024eb..7fa660c58 100644
--- a/src/libtls/tls_handshake.h
+++ b/src/libtls/tls_handshake.h
@@ -84,6 +84,20 @@ struct tls_handshake_t {
bool (*finished)(tls_handshake_t *this);
/**
+ * Get the peer identity authenticated/to authenticate during handshake.
+ *
+ * @return peer identity
+ */
+ identification_t* (*get_peer_id)(tls_handshake_t *this);
+
+ /**
+ * Get the server identity authenticated/to authenticate during handshake.
+ *
+ * @return server identity
+ */
+ identification_t* (*get_server_id)(tls_handshake_t *this);
+
+ /**
* Destroy a tls_handshake_t.
*/
void (*destroy)(tls_handshake_t *this);
diff --git a/src/libtls/tls_peer.c b/src/libtls/tls_peer.c
index 622df4035..b429da300 100644
--- a/src/libtls/tls_peer.c
+++ b/src/libtls/tls_peer.c
@@ -665,6 +665,8 @@ METHOD(tls_handshake_t, process, status_t,
{
return process_certreq(this, reader);
}
+ /* no cert request, server does not want to authenticate us */
+ DESTROY_IF(this->peer);
this->peer = NULL;
/* fall through since TLS_CERTIFICATE_REQUEST is optional */
case STATE_CERTREQ_RECEIVED:
@@ -850,6 +852,7 @@ static status_t send_certificate(private_tls_peer_t *this,
{
DBG1(DBG_TLS, "no TLS peer certificate found for '%Y', "
"skipping client authentication", this->peer);
+ this->peer->destroy(this->peer);
this->peer = NULL;
}
@@ -1132,11 +1135,25 @@ METHOD(tls_handshake_t, finished, bool,
return this->state == STATE_FINISHED_RECEIVED;
}
+METHOD(tls_handshake_t, get_peer_id, identification_t*,
+ private_tls_peer_t *this)
+{
+ return this->peer;
+}
+
+METHOD(tls_handshake_t, get_server_id, identification_t*,
+ private_tls_peer_t *this)
+{
+ return this->server;
+}
+
METHOD(tls_handshake_t, destroy, void,
private_tls_peer_t *this)
{
DESTROY_IF(this->private);
DESTROY_IF(this->dh);
+ DESTROY_IF(this->peer);
+ this->server->destroy(this->server);
this->peer_auth->destroy(this->peer_auth);
this->server_auth->destroy(this->server_auth);
free(this->hashsig.ptr);
@@ -1161,6 +1178,8 @@ tls_peer_t *tls_peer_create(tls_t *tls, tls_crypto_t *crypto, tls_alert_t *alert
.cipherspec_changed = _cipherspec_changed,
.change_cipherspec = _change_cipherspec,
.finished = _finished,
+ .get_peer_id = _get_peer_id,
+ .get_server_id = _get_server_id,
.destroy = _destroy,
},
},
@@ -1168,8 +1187,8 @@ tls_peer_t *tls_peer_create(tls_t *tls, tls_crypto_t *crypto, tls_alert_t *alert
.tls = tls,
.crypto = crypto,
.alert = alert,
- .peer = peer,
- .server = server,
+ .peer = peer ? peer->clone(peer) : NULL,
+ .server = server->clone(server),
.peer_auth = auth_cfg_create(),
.server_auth = auth_cfg_create(),
);
diff --git a/src/libtls/tls_peer.h b/src/libtls/tls_peer.h
index f773ea72e..e4ff6f83c 100644
--- a/src/libtls/tls_peer.h
+++ b/src/libtls/tls_peer.h
@@ -41,11 +41,15 @@ struct tls_peer_t {
/**
* Create a tls_peer instance.
-*
+ *
+ * If a peer identity is given, but the client does not get requested or is
+ * otherwise unable to perform client authentication, NULL is returned in
+ * tls_handshake_t.get_peer_id() instead of the peer identity.
+ *
* @param tls TLS stack
* @param crypto TLS crypto helper
* @param alert TLS alert handler
- * @param peer peer identity
+ * @param peer peer identity, NULL to skip client authentication
* @param server server identity
*/
tls_peer_t *tls_peer_create(tls_t *tls, tls_crypto_t *crypto, tls_alert_t *alert,
diff --git a/src/libtls/tls_server.c b/src/libtls/tls_server.c
index ec42b67fc..a85a00c4a 100644
--- a/src/libtls/tls_server.c
+++ b/src/libtls/tls_server.c
@@ -367,6 +367,11 @@ static status_t process_certificate(private_tls_server_t *this,
DBG1(DBG_TLS, "received TLS peer certificate '%Y'",
cert->get_subject(cert));
first = FALSE;
+ if (this->peer == NULL)
+ { /* apply identity to authenticate */
+ this->peer = cert->get_subject(cert);
+ this->peer = this->peer->clone(this->peer);
+ }
}
else
{
@@ -1045,11 +1050,25 @@ METHOD(tls_handshake_t, finished, bool,
return this->state == STATE_FINISHED_SENT;
}
+METHOD(tls_handshake_t, get_peer_id, identification_t*,
+ private_tls_server_t *this)
+{
+ return this->peer;
+}
+
+METHOD(tls_handshake_t, get_server_id, identification_t*,
+ private_tls_server_t *this)
+{
+ return this->server;
+}
+
METHOD(tls_handshake_t, destroy, void,
private_tls_server_t *this)
{
DESTROY_IF(this->private);
DESTROY_IF(this->dh);
+ DESTROY_IF(this->peer);
+ this->server->destroy(this->server);
this->peer_auth->destroy(this->peer_auth);
this->server_auth->destroy(this->server_auth);
free(this->hashsig.ptr);
@@ -1075,14 +1094,16 @@ tls_server_t *tls_server_create(tls_t *tls,
.cipherspec_changed = _cipherspec_changed,
.change_cipherspec = _change_cipherspec,
.finished = _finished,
+ .get_peer_id = _get_peer_id,
+ .get_server_id = _get_server_id,
.destroy = _destroy,
},
},
.tls = tls,
.crypto = crypto,
.alert = alert,
- .server = server,
- .peer = peer,
+ .server = server->clone(server),
+ .peer = peer ? peer->clone(peer) : NULL,
.state = STATE_INIT,
.peer_auth = auth_cfg_create(),
.server_auth = auth_cfg_create(),
diff --git a/src/libtls/tls_server.h b/src/libtls/tls_server.h
index 6289dc8eb..d6b8de153 100644
--- a/src/libtls/tls_server.h
+++ b/src/libtls/tls_server.h
@@ -42,11 +42,16 @@ struct tls_server_t {
/**
* Create a tls_server instance.
*
+ * If a peer identity is given, the client must authenticate with a valid
+ * certificate for this identity, or the connection fails. If peer is NULL,
+ * but the client authenticates nonetheless, the authenticated identity
+ * gets returned by tls_handshake_t.get_peer_id().
+ *
* @param tls TLS stack
* @param crypto TLS crypto helper
* @param alert TLS alert handler
* @param server server identity
- * @param peer peer identity
+ * @param peer peer identity, or NULL
*/
tls_server_t *tls_server_create(tls_t *tls,
tls_crypto_t *crypto, tls_alert_t *alert,