summaryrefslogtreecommitdiff
path: root/src/libpttls/pt_tls_server.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libpttls/pt_tls_server.c')
-rw-r--r--src/libpttls/pt_tls_server.c238
1 files changed, 121 insertions, 117 deletions
diff --git a/src/libpttls/pt_tls_server.c b/src/libpttls/pt_tls_server.c
index 3e134f0dd..9af00e7c2 100644
--- a/src/libpttls/pt_tls_server.c
+++ b/src/libpttls/pt_tls_server.c
@@ -61,6 +61,7 @@ struct private_pt_tls_server_t {
* TNCCS protocol handler, implemented as tls_t
*/
tls_t *tnccs;
+
};
/**
@@ -72,6 +73,7 @@ static bool negotiate_version(private_pt_tls_server_t *this)
bio_writer_t *writer;
u_int32_t vendor, type, identifier;
u_int8_t reserved, vmin, vmax, vpref;
+ bool res;
reader = pt_tls_read(this->tls, &vendor, &type, &identifier);
if (!reader)
@@ -99,9 +101,10 @@ static bool negotiate_version(private_pt_tls_server_t *this)
writer = bio_writer_create(4);
writer->write_uint24(writer, 0);
writer->write_uint8(writer, PT_TLS_VERSION);
-
- return pt_tls_write(this->tls, writer, PT_TLS_VERSION_RESPONSE,
- this->identifier++);
+ res = pt_tls_write(this->tls, PT_TLS_VERSION_RESPONSE,
+ this->identifier++, writer->get_buf(writer));
+ writer->destroy(writer);
+ return res;
}
/**
@@ -111,6 +114,9 @@ static status_t process_sasl(private_pt_tls_server_t *this,
sasl_mechanism_t *sasl, chunk_t data)
{
bio_writer_t *writer;
+ identification_t *client;
+ tnccs_t *tnccs;
+ bool res;
switch (sasl->process(sasl, data))
{
@@ -119,14 +125,23 @@ static status_t process_sasl(private_pt_tls_server_t *this,
case SUCCESS:
DBG1(DBG_TNC, "SASL %s authentication successful",
sasl->get_name(sasl));
- writer = bio_writer_create(1);
- writer->write_uint8(writer, PT_TLS_SASL_RESULT_SUCCESS);
- if (pt_tls_write(this->tls, writer, PT_TLS_SASL_RESULT,
- this->identifier++))
+ client = sasl->get_client(sasl);
+ if (client)
{
- return SUCCESS;
+ DBG1(DBG_TNC, "SASL client identity is '%Y'", client);
+ this->tnccs->set_peer_id(this->tnccs, client);
+ if (streq(sasl->get_name(sasl), "PLAIN"))
+ {
+ tnccs = (tnccs_t*)this->tnccs;
+ tnccs->set_auth_type(tnccs, TNC_AUTH_PASSWORD);
+ }
}
- return FAILED;
+ writer = bio_writer_create(1);
+ writer->write_uint8(writer, PT_TLS_SASL_RESULT_SUCCESS);
+ res = pt_tls_write(this->tls, PT_TLS_SASL_RESULT,
+ this->identifier++, writer->get_buf(writer));
+ writer->destroy(writer);
+ return res ? SUCCESS : FAILED;
case FAILED:
default:
DBG1(DBG_TNC, "SASL %s authentication failed",
@@ -134,8 +149,8 @@ static status_t process_sasl(private_pt_tls_server_t *this,
writer = bio_writer_create(1);
/* sending abort does not allow the client to retry */
writer->write_uint8(writer, PT_TLS_SASL_RESULT_ABORT);
- pt_tls_write(this->tls, writer, PT_TLS_SASL_RESULT,
- this->identifier++);
+ pt_tls_write(this->tls, PT_TLS_SASL_RESULT,
+ this->identifier++, writer->get_buf(writer));
return FAILED;
}
}
@@ -175,19 +190,15 @@ static status_t write_sasl(private_pt_tls_server_t *this,
{
bio_writer_t *writer;
chunk_t chunk;
+ bool res;
switch (sasl->build(sasl, &chunk))
{
case NEED_MORE:
- writer = bio_writer_create(chunk.len);
- writer->write_data(writer, chunk);
+ res = pt_tls_write(this->tls, PT_TLS_SASL_AUTH_DATA,
+ this->identifier++, chunk);
free(chunk.ptr);
- if (pt_tls_write(this->tls, writer, PT_TLS_SASL_AUTH_DATA,
- this->identifier++))
- {
- return NEED_MORE;
- }
- return FAILED;
+ return res ? NEED_MORE : FAILED;
case SUCCESS:
DBG1(DBG_TNC, "SASL %s authentication successful",
sasl->get_name(sasl));
@@ -195,21 +206,18 @@ static status_t write_sasl(private_pt_tls_server_t *this,
writer->write_uint8(writer, PT_TLS_SASL_RESULT_SUCCESS);
writer->write_data(writer, chunk);
free(chunk.ptr);
- if (pt_tls_write(this->tls, writer, PT_TLS_SASL_RESULT,
- this->identifier++))
- {
- return SUCCESS;
- }
- return FAILED;
+ res = pt_tls_write(this->tls, PT_TLS_SASL_RESULT,
+ this->identifier++, writer->get_buf(writer));
+ writer->destroy(writer);
+ return res ? SUCCESS : FAILED;
case FAILED:
default:
DBG1(DBG_TNC, "SASL %s authentication failed",
sasl->get_name(sasl));
- writer = bio_writer_create(1);
/* sending abort does not allow the client to retry */
- writer->write_uint8(writer, PT_TLS_SASL_RESULT_ABORT);
- pt_tls_write(this->tls, writer, PT_TLS_SASL_RESULT,
- this->identifier++);
+ chunk = chunk_from_chars(PT_TLS_SASL_RESULT_ABORT);
+ pt_tls_write(this->tls, PT_TLS_SASL_RESULT,
+ this->identifier++, chunk);
return FAILED;
}
}
@@ -222,6 +230,7 @@ static bool send_sasl_mechs(private_pt_tls_server_t *this)
enumerator_t *enumerator;
bio_writer_t *writer = NULL;
char *name;
+ bool res;
enumerator = sasl_mechanism_create_enumerator(TRUE);
while (enumerator->enumerate(enumerator, &name))
@@ -239,8 +248,10 @@ static bool send_sasl_mechs(private_pt_tls_server_t *this)
{ /* no mechanisms available? */
return FALSE;
}
- return pt_tls_write(this->tls, writer, PT_TLS_SASL_MECHS,
- this->identifier++);
+ res = pt_tls_write(this->tls, PT_TLS_SASL_MECHS,
+ this->identifier++, writer->get_buf(writer));
+ writer->destroy(writer);
+ return res;
}
/**
@@ -307,34 +318,45 @@ static status_t read_sasl_mech_selection(private_pt_tls_server_t *this,
static bool do_sasl(private_pt_tls_server_t *this)
{
sasl_mechanism_t *sasl;
+ identification_t *client_id;
+ tnccs_t *tnccs;
status_t status;
+ client_id = this->tls->get_peer_id(this->tls);
+ tnccs = (tnccs_t*)this->tnccs;
+
switch (this->auth)
{
case PT_TLS_AUTH_NONE:
return TRUE;
case PT_TLS_AUTH_TLS:
- if (this->tls->get_peer_id(this->tls))
+ if (client_id)
{
+ this->tnccs->set_peer_id(this->tnccs, client_id);
+ tnccs->set_auth_type(tnccs, TNC_AUTH_X509_CERT);
return TRUE;
}
- DBG1(DBG_TNC, "requiring TLS certificate client authentication");
+ DBG1(DBG_TNC, "requiring TLS certificate-based "
+ "client authentication");
return FALSE;
case PT_TLS_AUTH_SASL:
break;
case PT_TLS_AUTH_TLS_OR_SASL:
- if (this->tls->get_peer_id(this->tls))
+ if (client_id)
{
- DBG1(DBG_TNC, "skipping SASL, client authenticated with TLS "
- "certificate");
+ this->tnccs->set_peer_id(this->tnccs, client_id);
+ tnccs->set_auth_type(tnccs, TNC_AUTH_X509_CERT);
+ DBG1(DBG_TNC, "skipping SASL, client already authenticated by "
+ "TLS certificate");
return TRUE;
}
break;
case PT_TLS_AUTH_TLS_AND_SASL:
default:
- if (!this->tls->get_peer_id(this->tls))
+ if (!client_id)
{
- DBG1(DBG_TNC, "requiring TLS certificate client authentication");
+ DBG1(DBG_TNC, "requiring TLS certificate-based "
+ "client authentication");
return FALSE;
}
break;
@@ -369,11 +391,8 @@ static bool authenticate(private_pt_tls_server_t *this)
if (do_sasl(this))
{
/* complete SASL with emtpy mechanism list */
- bio_writer_t *writer;
-
- writer = bio_writer_create(0);
- return pt_tls_write(this->tls, writer, PT_TLS_SASL_MECHS,
- this->identifier++);
+ return pt_tls_write(this->tls, PT_TLS_SASL_MECHS, this->identifier++,
+ chunk_empty);
}
return FALSE;
}
@@ -381,89 +400,66 @@ static bool authenticate(private_pt_tls_server_t *this)
/**
* Perform assessment
*/
-static bool assess(private_pt_tls_server_t *this, tls_t *tnccs)
+static status_t assess(private_pt_tls_server_t *this, tls_t *tnccs)
{
- while (TRUE)
- {
- bio_writer_t *writer;
- bio_reader_t *reader;
- u_int32_t vendor, type, identifier;
- chunk_t data;
+ size_t msglen;
+ size_t buflen = PT_TLS_MAX_MESSAGE_LEN;
+ char buf[buflen];
+ bio_reader_t *reader;
+ u_int32_t vendor, type, identifier;
+ chunk_t data;
+ status_t status;
- writer = bio_writer_create(32);
- while (TRUE)
+ reader = pt_tls_read(this->tls, &vendor, &type, &identifier);
+ if (!reader)
+ {
+ return FAILED;
+ }
+ if (vendor == 0)
+ {
+ if (type == PT_TLS_ERROR)
{
- char buf[2048];
- size_t buflen, msglen;
-
- buflen = sizeof(buf);
- switch (tnccs->build(tnccs, buf, &buflen, &msglen))
- {
- case SUCCESS:
- writer->destroy(writer);
- return tnccs->is_complete(tnccs);
- case FAILED:
- default:
- writer->destroy(writer);
- return FALSE;
- case INVALID_STATE:
- writer->destroy(writer);
- break;
- case NEED_MORE:
- writer->write_data(writer, chunk_create(buf, buflen));
- continue;
- case ALREADY_DONE:
- writer->write_data(writer, chunk_create(buf, buflen));
- if (!pt_tls_write(this->tls, writer, PT_TLS_PB_TNC_BATCH,
- this->identifier++))
- {
- return FALSE;
- }
- writer = bio_writer_create(32);
- continue;
- }
- break;
+ DBG1(DBG_TNC, "received PT-TLS error");
+ reader->destroy(reader);
+ return FAILED;
}
-
- reader = pt_tls_read(this->tls, &vendor, &type, &identifier);
- if (!reader)
+ if (type != PT_TLS_PB_TNC_BATCH)
{
- return FALSE;
+ DBG1(DBG_TNC, "unexpected PT-TLS message: %d", type);
+ reader->destroy(reader);
+ return FAILED;
}
- if (vendor == 0)
+ data = reader->peek(reader);
+ switch (tnccs->process(tnccs, data.ptr, data.len))
{
- if (type == PT_TLS_ERROR)
- {
- DBG1(DBG_TNC, "received PT-TLS error");
+ case SUCCESS:
reader->destroy(reader);
- return FALSE;
- }
- if (type != PT_TLS_PB_TNC_BATCH)
- {
- DBG1(DBG_TNC, "unexpected PT-TLS message: %d", type);
+ return tnccs->is_complete(tnccs) ? SUCCESS : FAILED;
+ case FAILED:
+ default:
reader->destroy(reader);
return FALSE;
- }
- data = reader->peek(reader);
- switch (tnccs->process(tnccs, data.ptr, data.len))
- {
- case SUCCESS:
- reader->destroy(reader);
- return tnccs->is_complete(tnccs);
- case FAILED:
- default:
- reader->destroy(reader);
- return FALSE;
- case NEED_MORE:
- break;
- }
+ case NEED_MORE:
+ break;
}
- else
+ }
+ else
+ {
+ DBG1(DBG_TNC, "ignoring vendor specific PT-TLS message");
+ }
+ reader->destroy(reader);
+
+ status = tnccs->build(tnccs, buf, &buflen, &msglen);
+ if (status == ALREADY_DONE)
+ {
+ data = chunk_create(buf, buflen);
+ if (!pt_tls_write(this->tls, PT_TLS_PB_TNC_BATCH,
+ this->identifier++, data))
{
- DBG1(DBG_TNC, "ignoring vendor specific PT-TLS message");
+ return FAILED;
}
- reader->destroy(reader);
}
+ return status;
}
METHOD(pt_tls_server_t, handle, status_t,
@@ -472,27 +468,35 @@ METHOD(pt_tls_server_t, handle, status_t,
switch (this->state)
{
case PT_TLS_SERVER_VERSION:
+ DBG1(DBG_TNC, "entering PT-TLS negotiation phase");
if (!negotiate_version(this))
{
return FAILED;
}
DBG1(DBG_TNC, "negotiated PT-TLS version %d", PT_TLS_VERSION);
this->state = PT_TLS_SERVER_AUTH;
- break;
+ /* fall through to next state */
case PT_TLS_SERVER_AUTH:
+ DBG1(DBG_TNC, "doing SASL client authentication");
if (!authenticate(this))
{
return FAILED;
}
this->state = PT_TLS_SERVER_TNCCS;
+ DBG1(DBG_TNC, "entering PT-TLS data transport phase");
break;
case PT_TLS_SERVER_TNCCS:
- if (!assess(this, (tls_t*)this->tnccs))
+ switch (assess(this, (tls_t*)this->tnccs))
{
- return FAILED;
+ case SUCCESS:
+ this->state = PT_TLS_SERVER_END;
+ return SUCCESS;
+ case FAILED:
+ return FAILED;
+ default:
+ break;
}
- this->state = PT_TLS_SERVER_END;
- return SUCCESS;
+ break;
default:
return FAILED;
}