Merge branch 'pt-tls'
This commit is contained in:
@@ -7,4 +7,6 @@ libpttls_la_LIBADD = $(top_builddir)/src/libtls/libtls.la
|
|||||||
libpttls_la_SOURCES = pt_tls.c pt_tls.h \
|
libpttls_la_SOURCES = pt_tls.c pt_tls.h \
|
||||||
pt_tls_client.c pt_tls_client.h \
|
pt_tls_client.c pt_tls_client.h \
|
||||||
pt_tls_server.c pt_tls_server.h \
|
pt_tls_server.c pt_tls_server.h \
|
||||||
pt_tls_dispatcher.c pt_tls_dispatcher.h
|
pt_tls_dispatcher.c pt_tls_dispatcher.h \
|
||||||
|
sasl/sasl_plain/sasl_plain.c sasl/sasl_plain/sasl_plain.h \
|
||||||
|
sasl/sasl_mechanism.c sasl/sasl_mechanism.h
|
||||||
|
|||||||
@@ -38,6 +38,8 @@
|
|||||||
#define PT_TLS_HEADER_LEN 16
|
#define PT_TLS_HEADER_LEN 16
|
||||||
|
|
||||||
typedef enum pt_tls_message_type_t pt_tls_message_type_t;
|
typedef enum pt_tls_message_type_t pt_tls_message_type_t;
|
||||||
|
typedef enum pt_tls_sasl_result_t pt_tls_sasl_result_t;
|
||||||
|
typedef enum pt_tls_auth_t pt_tls_auth_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Message types, as defined by NEA PT-TLS
|
* Message types, as defined by NEA PT-TLS
|
||||||
@@ -54,6 +56,32 @@ enum pt_tls_message_type_t {
|
|||||||
PT_TLS_ERROR = 8,
|
PT_TLS_ERROR = 8,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Result code for a single SASL mechansim, as sent in PT_TLS_SASL_RESULT
|
||||||
|
*/
|
||||||
|
enum pt_tls_sasl_result_t {
|
||||||
|
PT_TLS_SASL_RESULT_SUCCESS = 0,
|
||||||
|
PT_TLS_SASL_RESULT_FAILURE = 1,
|
||||||
|
PT_TLS_SASL_RESULT_ABORT = 2,
|
||||||
|
PT_TLS_SASL_RESULT_MECH_FAILURE = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client authentication to require as PT-TLS server.
|
||||||
|
*/
|
||||||
|
enum pt_tls_auth_t {
|
||||||
|
/** don't require TLS client certificate or request SASL authentication */
|
||||||
|
PT_TLS_AUTH_NONE,
|
||||||
|
/** require TLS certificate authentication, no SASL */
|
||||||
|
PT_TLS_AUTH_TLS,
|
||||||
|
/** do SASL regardless of TLS certificate authentication */
|
||||||
|
PT_TLS_AUTH_SASL,
|
||||||
|
/* if client does not authenticate with a TLS certificate, request SASL */
|
||||||
|
PT_TLS_AUTH_TLS_OR_SASL,
|
||||||
|
/* require both, TLS certificate authentication and SASL */
|
||||||
|
PT_TLS_AUTH_TLS_AND_SASL,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read a PT-TLS message, create reader over Message Value.
|
* Read a PT-TLS message, create reader over Message Value.
|
||||||
*
|
*
|
||||||
|
|||||||
+208
-17
@@ -16,6 +16,8 @@
|
|||||||
#include "pt_tls_client.h"
|
#include "pt_tls_client.h"
|
||||||
#include "pt_tls.h"
|
#include "pt_tls.h"
|
||||||
|
|
||||||
|
#include <sasl/sasl_mechanism.h>
|
||||||
|
|
||||||
#include <tls_socket.h>
|
#include <tls_socket.h>
|
||||||
#include <utils/debug.h>
|
#include <utils/debug.h>
|
||||||
|
|
||||||
@@ -48,7 +50,12 @@ struct private_pt_tls_client_t {
|
|||||||
/**
|
/**
|
||||||
* Server identity
|
* Server identity
|
||||||
*/
|
*/
|
||||||
identification_t *id;
|
identification_t *server;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client authentication identity
|
||||||
|
*/
|
||||||
|
identification_t *client;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Current PT-TLS message identifier
|
* Current PT-TLS message identifier
|
||||||
@@ -77,7 +84,7 @@ static bool make_connection(private_pt_tls_client_t *this)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->tls = tls_socket_create(FALSE, this->id, NULL, fd, NULL);
|
this->tls = tls_socket_create(FALSE, this->server, this->client, fd, NULL);
|
||||||
if (!this->tls)
|
if (!this->tls)
|
||||||
{
|
{
|
||||||
close(fd);
|
close(fd);
|
||||||
@@ -128,33 +135,211 @@ static bool negotiate_version(private_pt_tls_client_t *this)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Authenticate session using SASL
|
* Run a SASL mechanism
|
||||||
*/
|
*/
|
||||||
static bool authenticate(private_pt_tls_client_t *this)
|
static status_t do_sasl(private_pt_tls_client_t *this, sasl_mechanism_t *sasl)
|
||||||
|
{
|
||||||
|
u_int32_t type, vendor, identifier;
|
||||||
|
u_int8_t result;
|
||||||
|
bio_reader_t *reader;
|
||||||
|
bio_writer_t *writer;
|
||||||
|
chunk_t data;
|
||||||
|
|
||||||
|
writer = bio_writer_create(32);
|
||||||
|
writer->write_data8(writer, chunk_from_str(sasl->get_name(sasl)));
|
||||||
|
switch (sasl->build(sasl, &data))
|
||||||
|
{
|
||||||
|
case INVALID_STATE:
|
||||||
|
break;
|
||||||
|
case NEED_MORE:
|
||||||
|
writer->write_data(writer, data);
|
||||||
|
free(data.ptr);
|
||||||
|
break;
|
||||||
|
case SUCCESS:
|
||||||
|
/* shouldn't happen */
|
||||||
|
free(data.ptr);
|
||||||
|
/* FALL */
|
||||||
|
case FAILED:
|
||||||
|
default:
|
||||||
|
writer->destroy(writer);
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
if (!pt_tls_write(this->tls, writer, PT_TLS_SASL_MECH_SELECTION,
|
||||||
|
this->identifier++))
|
||||||
|
{
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
|
reader = pt_tls_read(this->tls, &vendor, &type, &identifier);
|
||||||
|
if (!reader)
|
||||||
|
{
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
if (vendor != 0)
|
||||||
|
{
|
||||||
|
reader->destroy(reader);
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case PT_TLS_SASL_AUTH_DATA:
|
||||||
|
switch (sasl->process(sasl, reader->peek(reader)))
|
||||||
|
{
|
||||||
|
case NEED_MORE:
|
||||||
|
reader->destroy(reader);
|
||||||
|
break;
|
||||||
|
case SUCCESS:
|
||||||
|
/* should not happen, as it would come in a RESULT */
|
||||||
|
case FAILED:
|
||||||
|
default:
|
||||||
|
reader->destroy(reader);
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PT_TLS_SASL_RESULT:
|
||||||
|
if (!reader->read_uint8(reader, &result))
|
||||||
|
{
|
||||||
|
reader->destroy(reader);
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
switch (result)
|
||||||
|
{
|
||||||
|
case PT_TLS_SASL_RESULT_ABORT:
|
||||||
|
DBG1(DBG_TNC, "received SASL abort result");
|
||||||
|
reader->destroy(reader);
|
||||||
|
return FAILED;
|
||||||
|
case PT_TLS_SASL_RESULT_SUCCESS:
|
||||||
|
DBG1(DBG_TNC, "received SASL success result");
|
||||||
|
switch (sasl->process(sasl, reader->peek(reader)))
|
||||||
|
{
|
||||||
|
case SUCCESS:
|
||||||
|
reader->destroy(reader);
|
||||||
|
return SUCCESS;
|
||||||
|
case NEED_MORE:
|
||||||
|
/* inacceptable, it won't get more. FALL */
|
||||||
|
case FAILED:
|
||||||
|
default:
|
||||||
|
reader->destroy(reader);
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PT_TLS_SASL_RESULT_MECH_FAILURE:
|
||||||
|
case PT_TLS_SASL_RESULT_FAILURE:
|
||||||
|
DBG1(DBG_TNC, "received SASL failure result");
|
||||||
|
/* non-fatal failure, try again */
|
||||||
|
reader->destroy(reader);
|
||||||
|
return NEED_MORE;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
writer = bio_writer_create(32);
|
||||||
|
switch (sasl->build(sasl, &data))
|
||||||
|
{
|
||||||
|
case INVALID_STATE:
|
||||||
|
break;
|
||||||
|
case SUCCESS:
|
||||||
|
/* shoudln't happen, continue until we get a result */
|
||||||
|
case NEED_MORE:
|
||||||
|
writer->write_data(writer, data);
|
||||||
|
free(data.ptr);
|
||||||
|
break;
|
||||||
|
case FAILED:
|
||||||
|
default:
|
||||||
|
writer->destroy(writer);
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
if (!pt_tls_write(this->tls, writer, PT_TLS_SASL_AUTH_DATA,
|
||||||
|
this->identifier++))
|
||||||
|
{
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read SASL mechanism list, select and run mechanism
|
||||||
|
*/
|
||||||
|
static status_t select_and_do_sasl(private_pt_tls_client_t *this)
|
||||||
{
|
{
|
||||||
bio_reader_t *reader;
|
bio_reader_t *reader;
|
||||||
|
sasl_mechanism_t *sasl = NULL;
|
||||||
u_int32_t type, vendor, identifier;
|
u_int32_t type, vendor, identifier;
|
||||||
|
u_int8_t len;
|
||||||
|
chunk_t chunk;
|
||||||
|
char buf[21];
|
||||||
|
status_t status = NEED_MORE;
|
||||||
|
|
||||||
reader = pt_tls_read(this->tls, &vendor, &type, &identifier);
|
reader = pt_tls_read(this->tls, &vendor, &type, &identifier);
|
||||||
if (!reader)
|
if (!reader)
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FAILED;
|
||||||
}
|
}
|
||||||
if (vendor != 0 || type != PT_TLS_SASL_MECHS)
|
if (vendor != 0 || type != PT_TLS_SASL_MECHS)
|
||||||
{
|
{
|
||||||
DBG1(DBG_TNC, "PT-TLS authentication failed");
|
|
||||||
reader->destroy(reader);
|
reader->destroy(reader);
|
||||||
return FALSE;
|
return FAILED;
|
||||||
}
|
}
|
||||||
|
if (!reader->remaining(reader))
|
||||||
if (reader->remaining(reader))
|
{ /* mechanism list empty, SASL completed */
|
||||||
{ /* mechanism list not empty, FAIL until we support it */
|
DBG1(DBG_TNC, "PT-TLS authentication complete");
|
||||||
reader->destroy(reader);
|
reader->destroy(reader);
|
||||||
return FALSE;
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
while (reader->remaining(reader))
|
||||||
|
{
|
||||||
|
if (!reader->read_uint8(reader, &len) ||
|
||||||
|
!reader->read_data(reader, len & 0x1F, &chunk))
|
||||||
|
{
|
||||||
|
reader->destroy(reader);
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
snprintf(buf, sizeof(buf), "%.*s", (int)chunk.len, chunk.ptr);
|
||||||
|
sasl = sasl_mechanism_create(buf, this->client);
|
||||||
|
if (sasl)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
DBG1(DBG_TNC, "PT-TLS authentication complete");
|
|
||||||
reader->destroy(reader);
|
reader->destroy(reader);
|
||||||
return TRUE;
|
|
||||||
|
if (!sasl)
|
||||||
|
{
|
||||||
|
/* TODO: send PT-TLS error (5) */
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
while (status == NEED_MORE)
|
||||||
|
{
|
||||||
|
status = do_sasl(this, sasl);
|
||||||
|
}
|
||||||
|
sasl->destroy(sasl);
|
||||||
|
if (status == SUCCESS)
|
||||||
|
{ /* continue until we receive empty SASL mechanism list */
|
||||||
|
return NEED_MORE;
|
||||||
|
}
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authenticate session using SASL
|
||||||
|
*/
|
||||||
|
static bool authenticate(private_pt_tls_client_t *this)
|
||||||
|
{
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
|
switch (select_and_do_sasl(this))
|
||||||
|
{
|
||||||
|
case NEED_MORE:
|
||||||
|
continue;
|
||||||
|
case SUCCESS:
|
||||||
|
return TRUE;
|
||||||
|
case FAILED:
|
||||||
|
default:
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -276,18 +461,23 @@ METHOD(pt_tls_client_t, destroy, void,
|
|||||||
{
|
{
|
||||||
if (this->tls)
|
if (this->tls)
|
||||||
{
|
{
|
||||||
close(this->tls->get_fd(this->tls));
|
int fd;
|
||||||
|
|
||||||
|
fd = this->tls->get_fd(this->tls);
|
||||||
this->tls->destroy(this->tls);
|
this->tls->destroy(this->tls);
|
||||||
|
close(fd);
|
||||||
}
|
}
|
||||||
this->address->destroy(this->address);
|
this->address->destroy(this->address);
|
||||||
this->id->destroy(this->id);
|
this->server->destroy(this->server);
|
||||||
|
this->client->destroy(this->client);
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See header
|
* See header
|
||||||
*/
|
*/
|
||||||
pt_tls_client_t *pt_tls_client_create(host_t *address, identification_t *id)
|
pt_tls_client_t *pt_tls_client_create(host_t *address, identification_t *server,
|
||||||
|
identification_t *client)
|
||||||
{
|
{
|
||||||
private_pt_tls_client_t *this;
|
private_pt_tls_client_t *this;
|
||||||
|
|
||||||
@@ -297,7 +487,8 @@ pt_tls_client_t *pt_tls_client_create(host_t *address, identification_t *id)
|
|||||||
.destroy = _destroy,
|
.destroy = _destroy,
|
||||||
},
|
},
|
||||||
.address = address,
|
.address = address,
|
||||||
.id = id,
|
.server = server,
|
||||||
|
.client = client,
|
||||||
);
|
);
|
||||||
|
|
||||||
return &this->public;
|
return &this->public;
|
||||||
|
|||||||
@@ -50,10 +50,16 @@ struct pt_tls_client_t {
|
|||||||
/**
|
/**
|
||||||
* Create a pt_tls_client instance.
|
* Create a pt_tls_client instance.
|
||||||
*
|
*
|
||||||
|
* The client identity is used for:
|
||||||
|
* - TLS authentication if an appropirate certificate is found
|
||||||
|
* - SASL authentication if requested from the server
|
||||||
|
*
|
||||||
* @param address address/port to run assessments against, gets owned
|
* @param address address/port to run assessments against, gets owned
|
||||||
* @param id server identity to use for authentication, gets owned
|
* @param server server identity to use for authentication, gets owned
|
||||||
|
* @param client client identity to use for authentication, gets owned
|
||||||
* @return PT-TLS context
|
* @return PT-TLS context
|
||||||
*/
|
*/
|
||||||
pt_tls_client_t *pt_tls_client_create(host_t *address, identification_t *id);
|
pt_tls_client_t *pt_tls_client_create(host_t *address, identification_t *server,
|
||||||
|
identification_t *client);
|
||||||
|
|
||||||
#endif /** PT_TLS_CLIENT_H_ @}*/
|
#endif /** PT_TLS_CLIENT_H_ @}*/
|
||||||
|
|||||||
@@ -41,6 +41,11 @@ struct private_pt_tls_dispatcher_t {
|
|||||||
*/
|
*/
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client authentication requirements
|
||||||
|
*/
|
||||||
|
pt_tls_auth_t auth;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Server identity
|
* Server identity
|
||||||
*/
|
*/
|
||||||
@@ -141,7 +146,7 @@ METHOD(pt_tls_dispatcher_t, dispatch, void,
|
|||||||
close(fd);
|
close(fd);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
connection = pt_tls_server_create(this->server, fd, tnccs);
|
connection = pt_tls_server_create(this->server, fd, this->auth, tnccs);
|
||||||
if (!connection)
|
if (!connection)
|
||||||
{
|
{
|
||||||
close(fd);
|
close(fd);
|
||||||
@@ -171,7 +176,7 @@ METHOD(pt_tls_dispatcher_t, destroy, void,
|
|||||||
* See header
|
* See header
|
||||||
*/
|
*/
|
||||||
pt_tls_dispatcher_t *pt_tls_dispatcher_create(host_t *address,
|
pt_tls_dispatcher_t *pt_tls_dispatcher_create(host_t *address,
|
||||||
identification_t *id)
|
identification_t *id, pt_tls_auth_t auth)
|
||||||
{
|
{
|
||||||
private_pt_tls_dispatcher_t *this;
|
private_pt_tls_dispatcher_t *this;
|
||||||
|
|
||||||
@@ -184,6 +189,7 @@ pt_tls_dispatcher_t *pt_tls_dispatcher_create(host_t *address,
|
|||||||
/* we currently don't authenticate the peer, use %any identity */
|
/* we currently don't authenticate the peer, use %any identity */
|
||||||
.peer = identification_create_from_encoding(ID_ANY, chunk_empty),
|
.peer = identification_create_from_encoding(ID_ANY, chunk_empty),
|
||||||
.fd = -1,
|
.fd = -1,
|
||||||
|
.auth = auth,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!open_socket(this, address))
|
if (!open_socket(this, address))
|
||||||
|
|||||||
@@ -26,6 +26,8 @@
|
|||||||
|
|
||||||
#include <tnc/tnccs/tnccs.h>
|
#include <tnc/tnccs/tnccs.h>
|
||||||
|
|
||||||
|
#include "pt_tls.h"
|
||||||
|
|
||||||
typedef struct pt_tls_dispatcher_t pt_tls_dispatcher_t;
|
typedef struct pt_tls_dispatcher_t pt_tls_dispatcher_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -64,9 +66,10 @@ struct pt_tls_dispatcher_t {
|
|||||||
*
|
*
|
||||||
* @param address server address with port to listen on, gets owned
|
* @param address server address with port to listen on, gets owned
|
||||||
* @param id TLS server identity, gets owned
|
* @param id TLS server identity, gets owned
|
||||||
|
* @param auth client authentication to perform
|
||||||
* @return dispatcher service
|
* @return dispatcher service
|
||||||
*/
|
*/
|
||||||
pt_tls_dispatcher_t *pt_tls_dispatcher_create(host_t *address,
|
pt_tls_dispatcher_t *pt_tls_dispatcher_create(host_t *address,
|
||||||
identification_t *id);
|
identification_t *id, pt_tls_auth_t auth);
|
||||||
|
|
||||||
#endif /** PT_TLS_DISPATCHER_H_ @}*/
|
#endif /** PT_TLS_DISPATCHER_H_ @}*/
|
||||||
|
|||||||
@@ -14,7 +14,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "pt_tls_server.h"
|
#include "pt_tls_server.h"
|
||||||
#include "pt_tls.h"
|
|
||||||
|
#include <sasl/sasl_mechanism.h>
|
||||||
|
|
||||||
#include <utils/debug.h>
|
#include <utils/debug.h>
|
||||||
|
|
||||||
@@ -35,6 +36,11 @@ struct private_pt_tls_server_t {
|
|||||||
*/
|
*/
|
||||||
tls_socket_t *tls;
|
tls_socket_t *tls;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client authentication requirements
|
||||||
|
*/
|
||||||
|
pt_tls_auth_t auth;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
/* expecting version negotiation */
|
/* expecting version negotiation */
|
||||||
PT_TLS_SERVER_VERSION,
|
PT_TLS_SERVER_VERSION,
|
||||||
@@ -99,18 +105,279 @@ static bool negotiate_version(private_pt_tls_server_t *this)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Authenticated PT-TLS session with SASL
|
* Process SASL data, send result
|
||||||
*/
|
*/
|
||||||
static bool authenticate(private_pt_tls_server_t *this)
|
static status_t process_sasl(private_pt_tls_server_t *this,
|
||||||
|
sasl_mechanism_t *sasl, chunk_t data)
|
||||||
{
|
{
|
||||||
bio_writer_t *writer;
|
bio_writer_t *writer;
|
||||||
|
|
||||||
/* send empty SASL mechanims list to skip authentication */
|
switch (sasl->process(sasl, data))
|
||||||
writer = bio_writer_create(0);
|
{
|
||||||
|
case NEED_MORE:
|
||||||
|
return NEED_MORE;
|
||||||
|
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++))
|
||||||
|
{
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
return 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++);
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a SASL message and process it
|
||||||
|
*/
|
||||||
|
static status_t read_sasl(private_pt_tls_server_t *this,
|
||||||
|
sasl_mechanism_t *sasl)
|
||||||
|
{
|
||||||
|
u_int32_t vendor, type, identifier;
|
||||||
|
bio_reader_t *reader;
|
||||||
|
status_t status;
|
||||||
|
chunk_t data;
|
||||||
|
|
||||||
|
reader = pt_tls_read(this->tls, &vendor, &type, &identifier);
|
||||||
|
if (!reader)
|
||||||
|
{
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
if (vendor != 0 || type != PT_TLS_SASL_AUTH_DATA ||
|
||||||
|
!reader->read_data(reader, reader->remaining(reader), &data))
|
||||||
|
{
|
||||||
|
reader->destroy(reader);
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
status = process_sasl(this, sasl, data);
|
||||||
|
reader->destroy(reader);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build and write SASL message, or result message
|
||||||
|
*/
|
||||||
|
static status_t write_sasl(private_pt_tls_server_t *this,
|
||||||
|
sasl_mechanism_t *sasl)
|
||||||
|
{
|
||||||
|
bio_writer_t *writer;
|
||||||
|
chunk_t chunk;
|
||||||
|
|
||||||
|
switch (sasl->build(sasl, &chunk))
|
||||||
|
{
|
||||||
|
case NEED_MORE:
|
||||||
|
writer = bio_writer_create(chunk.len);
|
||||||
|
writer->write_data(writer, chunk);
|
||||||
|
free(chunk.ptr);
|
||||||
|
if (pt_tls_write(this->tls, writer, PT_TLS_SASL_AUTH_DATA,
|
||||||
|
this->identifier++))
|
||||||
|
{
|
||||||
|
return NEED_MORE;
|
||||||
|
}
|
||||||
|
return FAILED;
|
||||||
|
case SUCCESS:
|
||||||
|
DBG1(DBG_TNC, "SASL %s authentication successful",
|
||||||
|
sasl->get_name(sasl));
|
||||||
|
writer = bio_writer_create(1 + chunk.len);
|
||||||
|
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;
|
||||||
|
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++);
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send the list of supported SASL mechanisms
|
||||||
|
*/
|
||||||
|
static bool send_sasl_mechs(private_pt_tls_server_t *this)
|
||||||
|
{
|
||||||
|
enumerator_t *enumerator;
|
||||||
|
bio_writer_t *writer = NULL;
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
enumerator = sasl_mechanism_create_enumerator(TRUE);
|
||||||
|
while (enumerator->enumerate(enumerator, &name))
|
||||||
|
{
|
||||||
|
if (!writer)
|
||||||
|
{
|
||||||
|
writer = bio_writer_create(32);
|
||||||
|
}
|
||||||
|
DBG1(DBG_TNC, "offering SASL %s", name);
|
||||||
|
writer->write_data8(writer, chunk_from_str(name));
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
|
||||||
|
if (!writer)
|
||||||
|
{ /* no mechanisms available? */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
return pt_tls_write(this->tls, writer, PT_TLS_SASL_MECHS,
|
return pt_tls_write(this->tls, writer, PT_TLS_SASL_MECHS,
|
||||||
this->identifier++);
|
this->identifier++);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the selected SASL mechanism, and process piggybacked data
|
||||||
|
*/
|
||||||
|
static status_t read_sasl_mech_selection(private_pt_tls_server_t *this,
|
||||||
|
sasl_mechanism_t **out)
|
||||||
|
{
|
||||||
|
u_int32_t vendor, type, identifier;
|
||||||
|
sasl_mechanism_t *sasl;
|
||||||
|
bio_reader_t *reader;
|
||||||
|
chunk_t chunk;
|
||||||
|
u_int8_t len;
|
||||||
|
char buf[21];
|
||||||
|
|
||||||
|
reader = pt_tls_read(this->tls, &vendor, &type, &identifier);
|
||||||
|
if (!reader)
|
||||||
|
{
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
if (vendor != 0 || type != PT_TLS_SASL_MECH_SELECTION ||
|
||||||
|
!reader->read_uint8(reader, &len) ||
|
||||||
|
!reader->read_data(reader, len & 0x1F, &chunk))
|
||||||
|
{
|
||||||
|
reader->destroy(reader);
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
snprintf(buf, sizeof(buf), "%.*s", (int)chunk.len, chunk.ptr);
|
||||||
|
|
||||||
|
DBG1(DBG_TNC, "client starts SASL %s authentication", buf);
|
||||||
|
|
||||||
|
sasl = sasl_mechanism_create(buf, NULL);
|
||||||
|
if (!sasl)
|
||||||
|
{
|
||||||
|
reader->destroy(reader);
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
/* initial SASL data piggybacked? */
|
||||||
|
if (reader->remaining(reader))
|
||||||
|
{
|
||||||
|
switch (process_sasl(this, sasl, reader->peek(reader)))
|
||||||
|
{
|
||||||
|
case NEED_MORE:
|
||||||
|
break;
|
||||||
|
case SUCCESS:
|
||||||
|
reader->destroy(reader);
|
||||||
|
*out = sasl;
|
||||||
|
return SUCCESS;
|
||||||
|
case FAILED:
|
||||||
|
default:
|
||||||
|
reader->destroy(reader);
|
||||||
|
sasl->destroy(sasl);
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reader->destroy(reader);
|
||||||
|
*out = sasl;
|
||||||
|
return NEED_MORE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do a single SASL exchange
|
||||||
|
*/
|
||||||
|
static bool do_sasl(private_pt_tls_server_t *this)
|
||||||
|
{
|
||||||
|
sasl_mechanism_t *sasl;
|
||||||
|
status_t status;
|
||||||
|
|
||||||
|
switch (this->auth)
|
||||||
|
{
|
||||||
|
case PT_TLS_AUTH_NONE:
|
||||||
|
return TRUE;
|
||||||
|
case PT_TLS_AUTH_TLS:
|
||||||
|
if (this->tls->get_peer_id(this->tls))
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
DBG1(DBG_TNC, "requiring TLS certificate 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))
|
||||||
|
{
|
||||||
|
DBG1(DBG_TNC, "skipping SASL, client authenticated with TLS "
|
||||||
|
"certificate");
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PT_TLS_AUTH_TLS_AND_SASL:
|
||||||
|
default:
|
||||||
|
if (!this->tls->get_peer_id(this->tls))
|
||||||
|
{
|
||||||
|
DBG1(DBG_TNC, "requiring TLS certificate client authentication");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!send_sasl_mechs(this))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
status = read_sasl_mech_selection(this, &sasl);
|
||||||
|
if (status == FAILED)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
while (status == NEED_MORE)
|
||||||
|
{
|
||||||
|
status = write_sasl(this, sasl);
|
||||||
|
if (status == NEED_MORE)
|
||||||
|
{
|
||||||
|
status = read_sasl(this, sasl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sasl->destroy(sasl);
|
||||||
|
return status == SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authenticated PT-TLS session with a single SASL method
|
||||||
|
*/
|
||||||
|
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 FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform assessment
|
* Perform assessment
|
||||||
*/
|
*/
|
||||||
@@ -213,7 +480,6 @@ METHOD(pt_tls_server_t, handle, status_t,
|
|||||||
this->state = PT_TLS_SERVER_AUTH;
|
this->state = PT_TLS_SERVER_AUTH;
|
||||||
break;
|
break;
|
||||||
case PT_TLS_SERVER_AUTH:
|
case PT_TLS_SERVER_AUTH:
|
||||||
DBG1(DBG_TNC, "sending empty mechanism list to skip SASL");
|
|
||||||
if (!authenticate(this))
|
if (!authenticate(this))
|
||||||
{
|
{
|
||||||
return FAILED;
|
return FAILED;
|
||||||
@@ -251,7 +517,7 @@ METHOD(pt_tls_server_t, destroy, void,
|
|||||||
* See header
|
* See header
|
||||||
*/
|
*/
|
||||||
pt_tls_server_t *pt_tls_server_create(identification_t *server, int fd,
|
pt_tls_server_t *pt_tls_server_create(identification_t *server, int fd,
|
||||||
tnccs_t *tnccs)
|
pt_tls_auth_t auth, tnccs_t *tnccs)
|
||||||
{
|
{
|
||||||
private_pt_tls_server_t *this;
|
private_pt_tls_server_t *this;
|
||||||
|
|
||||||
@@ -264,6 +530,7 @@ pt_tls_server_t *pt_tls_server_create(identification_t *server, int fd,
|
|||||||
.state = PT_TLS_SERVER_VERSION,
|
.state = PT_TLS_SERVER_VERSION,
|
||||||
.tls = tls_socket_create(TRUE, server, NULL, fd, NULL),
|
.tls = tls_socket_create(TRUE, server, NULL, fd, NULL),
|
||||||
.tnccs = (tls_t*)tnccs,
|
.tnccs = (tls_t*)tnccs,
|
||||||
|
.auth = auth,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!this->tls)
|
if (!this->tls)
|
||||||
|
|||||||
@@ -25,6 +25,8 @@
|
|||||||
|
|
||||||
#include <tnc/tnccs/tnccs.h>
|
#include <tnc/tnccs/tnccs.h>
|
||||||
|
|
||||||
|
#include "pt_tls.h"
|
||||||
|
|
||||||
typedef struct pt_tls_server_t pt_tls_server_t;
|
typedef struct pt_tls_server_t pt_tls_server_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -60,10 +62,11 @@ struct pt_tls_server_t {
|
|||||||
*
|
*
|
||||||
* @param server TLS server identity
|
* @param server TLS server identity
|
||||||
* @param fd client connection socket
|
* @param fd client connection socket
|
||||||
|
* @param auth client authentication requirements
|
||||||
* @param tnccs inner TNCCS protocol handler to use for this connection
|
* @param tnccs inner TNCCS protocol handler to use for this connection
|
||||||
* @return PT-TLS server
|
* @return PT-TLS server
|
||||||
*/
|
*/
|
||||||
pt_tls_server_t *pt_tls_server_create(identification_t *server, int fd,
|
pt_tls_server_t *pt_tls_server_create(identification_t *server, int fd,
|
||||||
tnccs_t *tnccs);
|
pt_tls_auth_t auth, tnccs_t *tnccs);
|
||||||
|
|
||||||
#endif /** PT_TLS_SERVER_H_ @}*/
|
#endif /** PT_TLS_SERVER_H_ @}*/
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2013 Martin Willi
|
||||||
|
* Copyright (C) 2013 revosec AG
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at your
|
||||||
|
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "sasl_mechanism.h"
|
||||||
|
|
||||||
|
#include "sasl_plain/sasl_plain.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Available SASL mechanisms.
|
||||||
|
*/
|
||||||
|
static struct {
|
||||||
|
char *name;
|
||||||
|
bool server;
|
||||||
|
sasl_mechanism_constructor_t create;
|
||||||
|
} mechs[] = {
|
||||||
|
{ "PLAIN", TRUE, (sasl_mechanism_constructor_t)sasl_plain_create },
|
||||||
|
{ "PLAIN", FALSE, (sasl_mechanism_constructor_t)sasl_plain_create },
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See header.
|
||||||
|
*/
|
||||||
|
sasl_mechanism_t *sasl_mechanism_create(char *name, identification_t *client)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < countof(mechs); i++)
|
||||||
|
{
|
||||||
|
if (streq(mechs[i].name, name) && mechs[i].server == (client == NULL))
|
||||||
|
{
|
||||||
|
return mechs[i].create(name, client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SASL mechanism enumerator
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
/** implements enumerator_t */
|
||||||
|
enumerator_t public;
|
||||||
|
/** looking for client or server? */
|
||||||
|
bool server;
|
||||||
|
/** position in mechs[] */
|
||||||
|
int i;
|
||||||
|
} mech_enumerator_t;
|
||||||
|
|
||||||
|
METHOD(enumerator_t, mech_enumerate, bool,
|
||||||
|
mech_enumerator_t *this, char **name)
|
||||||
|
{
|
||||||
|
while (this->i < countof(mechs))
|
||||||
|
{
|
||||||
|
if (mechs[this->i].server == this->server)
|
||||||
|
{
|
||||||
|
*name = mechs[this->i].name;
|
||||||
|
this->i++;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
this->i++;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See header.
|
||||||
|
*/
|
||||||
|
enumerator_t* sasl_mechanism_create_enumerator(bool server)
|
||||||
|
{
|
||||||
|
mech_enumerator_t *enumerator;
|
||||||
|
|
||||||
|
INIT(enumerator,
|
||||||
|
.public = {
|
||||||
|
.enumerate = (void*)_mech_enumerate,
|
||||||
|
.destroy = (void*)free,
|
||||||
|
},
|
||||||
|
.server = server,
|
||||||
|
);
|
||||||
|
return &enumerator->public;
|
||||||
|
}
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2013 Martin Willi
|
||||||
|
* Copyright (C) 2013 revosec AG
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at your
|
||||||
|
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup sasl_mechanism sasl_mechanism
|
||||||
|
* @{ @ingroup sasl
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SASL_MECHANISM_H_
|
||||||
|
#define SASL_MECHANISM_H_
|
||||||
|
|
||||||
|
typedef struct sasl_mechanism_t sasl_mechanism_t;
|
||||||
|
|
||||||
|
#include <library.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor function for SASL mechansims.
|
||||||
|
*
|
||||||
|
* @param name name of the requested SASL mechanism
|
||||||
|
* @param client client identity, NULL to act as server
|
||||||
|
* @return SASL mechanism, NULL on failure
|
||||||
|
*/
|
||||||
|
typedef sasl_mechanism_t*(*sasl_mechanism_constructor_t)(char *name,
|
||||||
|
identification_t *client);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic interface for SASL mechanisms.
|
||||||
|
*/
|
||||||
|
struct sasl_mechanism_t {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the name of this SASL mechanism.
|
||||||
|
*
|
||||||
|
* @return name of SASL mechanism
|
||||||
|
*/
|
||||||
|
char* (*get_name)(sasl_mechanism_t *this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a SASL message to send to remote host.
|
||||||
|
*
|
||||||
|
* A message is returned if the return value is NEED_MORE or SUCCESS. A
|
||||||
|
* client MUST NOT return SUCCESS in build(), as the final message
|
||||||
|
* is always from server to client (even if it is an empty result message).
|
||||||
|
*
|
||||||
|
* @param message receives allocated SASL message, to free
|
||||||
|
* @return
|
||||||
|
* - FAILED if mechanism failed
|
||||||
|
* - NEED_MORE if additional exchanges required
|
||||||
|
* - INVALID_STATE if currently nothing to build
|
||||||
|
* - SUCCESS if mechanism authenticated successfully
|
||||||
|
*/
|
||||||
|
status_t (*build)(sasl_mechanism_t *this, chunk_t *message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process a SASL message received from remote host.
|
||||||
|
*
|
||||||
|
* If a server returns SUCCESS during process(), an empty result message
|
||||||
|
* is sent to complete the SASL exchange.
|
||||||
|
*
|
||||||
|
* @param message received SASL message to process
|
||||||
|
* @return
|
||||||
|
* - FAILED if mechanism failed
|
||||||
|
* - NEED_MORE if additional exchanges required
|
||||||
|
* - SUCCESS if mechanism authenticated successfully
|
||||||
|
*/
|
||||||
|
status_t (*process)(sasl_mechanism_t *this, chunk_t message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy a sasl_mechanism_t.
|
||||||
|
*/
|
||||||
|
void (*destroy)(sasl_mechanism_t *this);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a sasl_mechanism instance.
|
||||||
|
*
|
||||||
|
* @param name name of SASL mechanism to create
|
||||||
|
* @param client client identity, NULL to act as server
|
||||||
|
* @return SASL mechanism instance, NULL if not found
|
||||||
|
*/
|
||||||
|
sasl_mechanism_t *sasl_mechanism_create(char *name, identification_t *client);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an enumerator over supported SASL mechanism names.
|
||||||
|
*
|
||||||
|
* @param server TRUE for server instance, FALSE for client
|
||||||
|
* @return enumerator over char*
|
||||||
|
*/
|
||||||
|
enumerator_t* sasl_mechanism_create_enumerator(bool server);
|
||||||
|
|
||||||
|
#endif /** SASL_MECHANISM_H_ @}*/
|
||||||
@@ -0,0 +1,171 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2013 Martin Willi
|
||||||
|
* Copyright (C) 2013 revosec AG
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at your
|
||||||
|
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "sasl_plain.h"
|
||||||
|
|
||||||
|
#include <utils/debug.h>
|
||||||
|
|
||||||
|
typedef struct private_sasl_plain_t private_sasl_plain_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private data of an sasl_plain_t object.
|
||||||
|
*/
|
||||||
|
struct private_sasl_plain_t {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public sasl_plain_t interface.
|
||||||
|
*/
|
||||||
|
sasl_plain_t public;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client identity
|
||||||
|
*/
|
||||||
|
identification_t *client;
|
||||||
|
};
|
||||||
|
|
||||||
|
METHOD(sasl_mechanism_t, get_name, char*,
|
||||||
|
private_sasl_plain_t *this)
|
||||||
|
{
|
||||||
|
return "PLAIN";
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(sasl_mechanism_t, build_server, status_t,
|
||||||
|
private_sasl_plain_t *this, chunk_t *message)
|
||||||
|
{
|
||||||
|
/* gets never called */
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(sasl_mechanism_t, process_server, status_t,
|
||||||
|
private_sasl_plain_t *this, chunk_t message)
|
||||||
|
{
|
||||||
|
chunk_t authz, authi, password;
|
||||||
|
identification_t *id;
|
||||||
|
shared_key_t *shared;
|
||||||
|
u_char *pos;
|
||||||
|
|
||||||
|
pos = memchr(message.ptr, 0, message.len);
|
||||||
|
if (!pos)
|
||||||
|
{
|
||||||
|
DBG1(DBG_CFG, "invalid authz encoding");
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
authz = chunk_create(message.ptr, pos - message.ptr);
|
||||||
|
message = chunk_skip(message, authz.len + 1);
|
||||||
|
pos = memchr(message.ptr, 0, message.len);
|
||||||
|
if (!pos)
|
||||||
|
{
|
||||||
|
DBG1(DBG_CFG, "invalid authi encoding");
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
authi = chunk_create(message.ptr, pos - message.ptr);
|
||||||
|
password = chunk_skip(message, authi.len + 1);
|
||||||
|
id = identification_create_from_data(authi);
|
||||||
|
shared = lib->credmgr->get_shared(lib->credmgr, SHARED_EAP, id, NULL);
|
||||||
|
if (!shared)
|
||||||
|
{
|
||||||
|
DBG1(DBG_CFG, "no shared secret found for '%Y'", id);
|
||||||
|
id->destroy(id);
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
if (!chunk_equals(shared->get_key(shared), password))
|
||||||
|
{
|
||||||
|
DBG1(DBG_CFG, "shared secret for '%Y' does not match", id);
|
||||||
|
id->destroy(id);
|
||||||
|
shared->destroy(shared);
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
id->destroy(id);
|
||||||
|
shared->destroy(shared);
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(sasl_mechanism_t, build_client, status_t,
|
||||||
|
private_sasl_plain_t *this, chunk_t *message)
|
||||||
|
{
|
||||||
|
shared_key_t *shared;
|
||||||
|
chunk_t password;
|
||||||
|
char buf[256];
|
||||||
|
ssize_t len;
|
||||||
|
|
||||||
|
/* we currently use the EAP type of shared secret */
|
||||||
|
shared = lib->credmgr->get_shared(lib->credmgr, SHARED_EAP,
|
||||||
|
this->client, NULL);
|
||||||
|
if (!shared)
|
||||||
|
{
|
||||||
|
DBG1(DBG_CFG, "no shared secret found for %Y", this->client);
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
password = shared->get_key(shared);
|
||||||
|
len = snprintf(buf, sizeof(buf), "%s%c%Y%c%.*s",
|
||||||
|
"", 0, this->client, 0,
|
||||||
|
(int)password.len, password.ptr);
|
||||||
|
if (len < 0 || len >= sizeof(buf))
|
||||||
|
{
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
*message = chunk_clone(chunk_create(buf, len));
|
||||||
|
return NEED_MORE;
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(sasl_mechanism_t, process_client, status_t,
|
||||||
|
private_sasl_plain_t *this, chunk_t message)
|
||||||
|
{
|
||||||
|
/* if the server sends a result, authentication successful */
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(sasl_mechanism_t, destroy, void,
|
||||||
|
private_sasl_plain_t *this)
|
||||||
|
{
|
||||||
|
DESTROY_IF(this->client);
|
||||||
|
free(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See header
|
||||||
|
*/
|
||||||
|
sasl_plain_t *sasl_plain_create(char *name, identification_t *client)
|
||||||
|
{
|
||||||
|
private_sasl_plain_t *this;
|
||||||
|
|
||||||
|
if (!streq(get_name(NULL), name))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
INIT(this,
|
||||||
|
.public = {
|
||||||
|
.sasl = {
|
||||||
|
.get_name = _get_name,
|
||||||
|
.destroy = _destroy,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (client)
|
||||||
|
{
|
||||||
|
this->public.sasl.build = _build_client;
|
||||||
|
this->public.sasl.process = _process_client;
|
||||||
|
this->client = client->clone(client);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->public.sasl.build = _build_server;
|
||||||
|
this->public.sasl.process = _process_server;
|
||||||
|
}
|
||||||
|
return &this->public;
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2013 Martin Willi
|
||||||
|
* Copyright (C) 2013 revosec AG
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at your
|
||||||
|
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup sasl_plain sasl_plain
|
||||||
|
* @{ @ingroup sasl
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SASL_PLAIN_H_
|
||||||
|
#define SASL_PLAIN_H_
|
||||||
|
|
||||||
|
#include <sasl/sasl_mechanism.h>
|
||||||
|
|
||||||
|
typedef struct sasl_plain_t sasl_plain_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SASL Mechanism implementing PLAIN.
|
||||||
|
*/
|
||||||
|
struct sasl_plain_t {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements sasl_mechanism_t
|
||||||
|
*/
|
||||||
|
sasl_mechanism_t sasl;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a sasl_plain instance.
|
||||||
|
*
|
||||||
|
* @param name name of mechanism, must be "PLAIN"
|
||||||
|
* @param client client identity, NULL to act as server
|
||||||
|
* @return mechanism implementing PLAIN, NULL on error
|
||||||
|
*/
|
||||||
|
sasl_plain_t *sasl_plain_create(char *name, identification_t *client);
|
||||||
|
|
||||||
|
#endif /** SASL_PLAIN_H_ @}*/
|
||||||
+4
-18
@@ -106,16 +106,6 @@ struct private_tls_t {
|
|||||||
*/
|
*/
|
||||||
bool is_server;
|
bool is_server;
|
||||||
|
|
||||||
/**
|
|
||||||
* Server identity
|
|
||||||
*/
|
|
||||||
identification_t *server;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Peer identity
|
|
||||||
*/
|
|
||||||
identification_t *peer;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Negotiated TLS version
|
* Negotiated TLS version
|
||||||
*/
|
*/
|
||||||
@@ -362,13 +352,13 @@ METHOD(tls_t, is_server, bool,
|
|||||||
METHOD(tls_t, get_server_id, identification_t*,
|
METHOD(tls_t, get_server_id, identification_t*,
|
||||||
private_tls_t *this)
|
private_tls_t *this)
|
||||||
{
|
{
|
||||||
return this->server;
|
return this->handshake->get_server_id(this->handshake);
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(tls_t, get_peer_id, identification_t*,
|
METHOD(tls_t, get_peer_id, identification_t*,
|
||||||
private_tls_t *this)
|
private_tls_t *this)
|
||||||
{
|
{
|
||||||
return this->peer;
|
return this->handshake->get_peer_id(this->handshake);
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(tls_t, get_version, tls_version_t,
|
METHOD(tls_t, get_version, tls_version_t,
|
||||||
@@ -433,8 +423,6 @@ METHOD(tls_t, destroy, void,
|
|||||||
this->fragmentation->destroy(this->fragmentation);
|
this->fragmentation->destroy(this->fragmentation);
|
||||||
this->crypto->destroy(this->crypto);
|
this->crypto->destroy(this->crypto);
|
||||||
this->handshake->destroy(this->handshake);
|
this->handshake->destroy(this->handshake);
|
||||||
DESTROY_IF(this->peer);
|
|
||||||
this->server->destroy(this->server);
|
|
||||||
DESTROY_IF(this->application);
|
DESTROY_IF(this->application);
|
||||||
this->alert->destroy(this->alert);
|
this->alert->destroy(this->alert);
|
||||||
|
|
||||||
@@ -480,8 +468,6 @@ tls_t *tls_create(bool is_server, identification_t *server,
|
|||||||
},
|
},
|
||||||
.is_server = is_server,
|
.is_server = is_server,
|
||||||
.version = TLS_1_2,
|
.version = TLS_1_2,
|
||||||
.server = server->clone(server),
|
|
||||||
.peer = peer ? peer->clone(peer) : NULL,
|
|
||||||
.application = application,
|
.application = application,
|
||||||
.purpose = purpose,
|
.purpose = purpose,
|
||||||
);
|
);
|
||||||
@@ -491,12 +477,12 @@ tls_t *tls_create(bool is_server, identification_t *server,
|
|||||||
if (is_server)
|
if (is_server)
|
||||||
{
|
{
|
||||||
this->handshake = &tls_server_create(&this->public, this->crypto,
|
this->handshake = &tls_server_create(&this->public, this->crypto,
|
||||||
this->alert, this->server, this->peer)->handshake;
|
this->alert, server, peer)->handshake;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this->handshake = &tls_peer_create(&this->public, this->crypto,
|
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->fragmentation = tls_fragmentation_create(this->handshake, this->alert,
|
||||||
this->application);
|
this->application);
|
||||||
|
|||||||
+4
-4
@@ -193,16 +193,16 @@ struct tls_t {
|
|||||||
bool (*is_server)(tls_t *this);
|
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);
|
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);
|
identification_t* (*get_peer_id)(tls_t *this);
|
||||||
|
|
||||||
|
|||||||
@@ -83,6 +83,20 @@ struct tls_handshake_t {
|
|||||||
*/
|
*/
|
||||||
bool (*finished)(tls_handshake_t *this);
|
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.
|
* Destroy a tls_handshake_t.
|
||||||
*/
|
*/
|
||||||
|
|||||||
+21
-2
@@ -665,6 +665,8 @@ METHOD(tls_handshake_t, process, status_t,
|
|||||||
{
|
{
|
||||||
return process_certreq(this, reader);
|
return process_certreq(this, reader);
|
||||||
}
|
}
|
||||||
|
/* no cert request, server does not want to authenticate us */
|
||||||
|
DESTROY_IF(this->peer);
|
||||||
this->peer = NULL;
|
this->peer = NULL;
|
||||||
/* fall through since TLS_CERTIFICATE_REQUEST is optional */
|
/* fall through since TLS_CERTIFICATE_REQUEST is optional */
|
||||||
case STATE_CERTREQ_RECEIVED:
|
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', "
|
DBG1(DBG_TLS, "no TLS peer certificate found for '%Y', "
|
||||||
"skipping client authentication", this->peer);
|
"skipping client authentication", this->peer);
|
||||||
|
this->peer->destroy(this->peer);
|
||||||
this->peer = NULL;
|
this->peer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1132,11 +1135,25 @@ METHOD(tls_handshake_t, finished, bool,
|
|||||||
return this->state == STATE_FINISHED_RECEIVED;
|
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,
|
METHOD(tls_handshake_t, destroy, void,
|
||||||
private_tls_peer_t *this)
|
private_tls_peer_t *this)
|
||||||
{
|
{
|
||||||
DESTROY_IF(this->private);
|
DESTROY_IF(this->private);
|
||||||
DESTROY_IF(this->dh);
|
DESTROY_IF(this->dh);
|
||||||
|
DESTROY_IF(this->peer);
|
||||||
|
this->server->destroy(this->server);
|
||||||
this->peer_auth->destroy(this->peer_auth);
|
this->peer_auth->destroy(this->peer_auth);
|
||||||
this->server_auth->destroy(this->server_auth);
|
this->server_auth->destroy(this->server_auth);
|
||||||
free(this->hashsig.ptr);
|
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,
|
.cipherspec_changed = _cipherspec_changed,
|
||||||
.change_cipherspec = _change_cipherspec,
|
.change_cipherspec = _change_cipherspec,
|
||||||
.finished = _finished,
|
.finished = _finished,
|
||||||
|
.get_peer_id = _get_peer_id,
|
||||||
|
.get_server_id = _get_server_id,
|
||||||
.destroy = _destroy,
|
.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,
|
.tls = tls,
|
||||||
.crypto = crypto,
|
.crypto = crypto,
|
||||||
.alert = alert,
|
.alert = alert,
|
||||||
.peer = peer,
|
.peer = peer ? peer->clone(peer) : NULL,
|
||||||
.server = server,
|
.server = server->clone(server),
|
||||||
.peer_auth = auth_cfg_create(),
|
.peer_auth = auth_cfg_create(),
|
||||||
.server_auth = auth_cfg_create(),
|
.server_auth = auth_cfg_create(),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -41,11 +41,15 @@ struct tls_peer_t {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a tls_peer instance.
|
* 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 tls TLS stack
|
||||||
* @param crypto TLS crypto helper
|
* @param crypto TLS crypto helper
|
||||||
* @param alert TLS alert handler
|
* @param alert TLS alert handler
|
||||||
* @param peer peer identity
|
* @param peer peer identity, NULL to skip client authentication
|
||||||
* @param server server identity
|
* @param server server identity
|
||||||
*/
|
*/
|
||||||
tls_peer_t *tls_peer_create(tls_t *tls, tls_crypto_t *crypto, tls_alert_t *alert,
|
tls_peer_t *tls_peer_create(tls_t *tls, tls_crypto_t *crypto, tls_alert_t *alert,
|
||||||
|
|||||||
+43
-11
@@ -79,6 +79,11 @@ struct private_tls_server_t {
|
|||||||
*/
|
*/
|
||||||
identification_t *peer;
|
identification_t *peer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is it acceptable if we couldn't verify the peer certificate?
|
||||||
|
*/
|
||||||
|
bool peer_auth_optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* State we are in
|
* State we are in
|
||||||
*/
|
*/
|
||||||
@@ -367,6 +372,12 @@ static status_t process_certificate(private_tls_server_t *this,
|
|||||||
DBG1(DBG_TLS, "received TLS peer certificate '%Y'",
|
DBG1(DBG_TLS, "received TLS peer certificate '%Y'",
|
||||||
cert->get_subject(cert));
|
cert->get_subject(cert));
|
||||||
first = FALSE;
|
first = FALSE;
|
||||||
|
if (this->peer == NULL)
|
||||||
|
{ /* apply identity to authenticate */
|
||||||
|
this->peer = cert->get_subject(cert);
|
||||||
|
this->peer = this->peer->clone(this->peer);
|
||||||
|
this->peer_auth_optional = TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -550,13 +561,22 @@ static status_t process_cert_verify(private_tls_server_t *this,
|
|||||||
{
|
{
|
||||||
DBG1(DBG_TLS, "no trusted certificate found for '%Y' to verify TLS peer",
|
DBG1(DBG_TLS, "no trusted certificate found for '%Y' to verify TLS peer",
|
||||||
this->peer);
|
this->peer);
|
||||||
this->alert->add(this->alert, TLS_FATAL, TLS_CERTIFICATE_UNKNOWN);
|
if (!this->peer_auth_optional)
|
||||||
return NEED_MORE;
|
{ /* client authentication is required */
|
||||||
|
this->alert->add(this->alert, TLS_FATAL, TLS_CERTIFICATE_UNKNOWN);
|
||||||
|
return NEED_MORE;
|
||||||
|
}
|
||||||
|
/* reset peer identity, we couldn't authenticate it */
|
||||||
|
this->peer->destroy(this->peer);
|
||||||
|
this->peer = NULL;
|
||||||
|
this->state = STATE_KEY_EXCHANGE_RECEIVED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->state = STATE_CERT_VERIFY_RECEIVED;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->crypto->append_handshake(this->crypto,
|
this->crypto->append_handshake(this->crypto,
|
||||||
TLS_CERTIFICATE_VERIFY, reader->peek(reader));
|
TLS_CERTIFICATE_VERIFY, reader->peek(reader));
|
||||||
this->state = STATE_CERT_VERIFY_RECEIVED;
|
|
||||||
return NEED_MORE;
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -979,11 +999,7 @@ METHOD(tls_handshake_t, build, status_t,
|
|||||||
}
|
}
|
||||||
/* otherwise fall through to next state */
|
/* otherwise fall through to next state */
|
||||||
case STATE_KEY_EXCHANGE_SENT:
|
case STATE_KEY_EXCHANGE_SENT:
|
||||||
if (this->peer)
|
return send_certificate_request(this, type, writer);
|
||||||
{
|
|
||||||
return send_certificate_request(this, type, writer);
|
|
||||||
}
|
|
||||||
/* otherwise fall through to next state */
|
|
||||||
case STATE_CERTREQ_SENT:
|
case STATE_CERTREQ_SENT:
|
||||||
return send_hello_done(this, type, writer);
|
return send_hello_done(this, type, writer);
|
||||||
case STATE_CIPHERSPEC_CHANGED_OUT:
|
case STATE_CIPHERSPEC_CHANGED_OUT:
|
||||||
@@ -1045,11 +1061,25 @@ METHOD(tls_handshake_t, finished, bool,
|
|||||||
return this->state == STATE_FINISHED_SENT;
|
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,
|
METHOD(tls_handshake_t, destroy, void,
|
||||||
private_tls_server_t *this)
|
private_tls_server_t *this)
|
||||||
{
|
{
|
||||||
DESTROY_IF(this->private);
|
DESTROY_IF(this->private);
|
||||||
DESTROY_IF(this->dh);
|
DESTROY_IF(this->dh);
|
||||||
|
DESTROY_IF(this->peer);
|
||||||
|
this->server->destroy(this->server);
|
||||||
this->peer_auth->destroy(this->peer_auth);
|
this->peer_auth->destroy(this->peer_auth);
|
||||||
this->server_auth->destroy(this->server_auth);
|
this->server_auth->destroy(this->server_auth);
|
||||||
free(this->hashsig.ptr);
|
free(this->hashsig.ptr);
|
||||||
@@ -1075,14 +1105,16 @@ tls_server_t *tls_server_create(tls_t *tls,
|
|||||||
.cipherspec_changed = _cipherspec_changed,
|
.cipherspec_changed = _cipherspec_changed,
|
||||||
.change_cipherspec = _change_cipherspec,
|
.change_cipherspec = _change_cipherspec,
|
||||||
.finished = _finished,
|
.finished = _finished,
|
||||||
|
.get_peer_id = _get_peer_id,
|
||||||
|
.get_server_id = _get_server_id,
|
||||||
.destroy = _destroy,
|
.destroy = _destroy,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.tls = tls,
|
.tls = tls,
|
||||||
.crypto = crypto,
|
.crypto = crypto,
|
||||||
.alert = alert,
|
.alert = alert,
|
||||||
.server = server,
|
.server = server->clone(server),
|
||||||
.peer = peer,
|
.peer = peer ? peer->clone(peer) : NULL,
|
||||||
.state = STATE_INIT,
|
.state = STATE_INIT,
|
||||||
.peer_auth = auth_cfg_create(),
|
.peer_auth = auth_cfg_create(),
|
||||||
.server_auth = auth_cfg_create(),
|
.server_auth = auth_cfg_create(),
|
||||||
|
|||||||
@@ -42,11 +42,16 @@ struct tls_server_t {
|
|||||||
/**
|
/**
|
||||||
* Create a tls_server instance.
|
* 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 tls TLS stack
|
||||||
* @param crypto TLS crypto helper
|
* @param crypto TLS crypto helper
|
||||||
* @param alert TLS alert handler
|
* @param alert TLS alert handler
|
||||||
* @param server server identity
|
* @param server server identity
|
||||||
* @param peer peer identity
|
* @param peer peer identity, or NULL
|
||||||
*/
|
*/
|
||||||
tls_server_t *tls_server_create(tls_t *tls,
|
tls_server_t *tls_server_create(tls_t *tls,
|
||||||
tls_crypto_t *crypto, tls_alert_t *alert,
|
tls_crypto_t *crypto, tls_alert_t *alert,
|
||||||
|
|||||||
@@ -378,6 +378,18 @@ METHOD(tls_socket_t, get_fd, int,
|
|||||||
return this->fd;
|
return this->fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
METHOD(tls_socket_t, get_server_id, identification_t*,
|
||||||
|
private_tls_socket_t *this)
|
||||||
|
{
|
||||||
|
return this->tls->get_server_id(this->tls);
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(tls_socket_t, get_peer_id, identification_t*,
|
||||||
|
private_tls_socket_t *this)
|
||||||
|
{
|
||||||
|
return this->tls->get_peer_id(this->tls);
|
||||||
|
}
|
||||||
|
|
||||||
METHOD(tls_socket_t, destroy, void,
|
METHOD(tls_socket_t, destroy, void,
|
||||||
private_tls_socket_t *this)
|
private_tls_socket_t *this)
|
||||||
{
|
{
|
||||||
@@ -403,6 +415,8 @@ tls_socket_t *tls_socket_create(bool is_server, identification_t *server,
|
|||||||
.write = _write_,
|
.write = _write_,
|
||||||
.splice = _splice,
|
.splice = _splice,
|
||||||
.get_fd = _get_fd,
|
.get_fd = _get_fd,
|
||||||
|
.get_server_id = _get_server_id,
|
||||||
|
.get_peer_id = _get_peer_id,
|
||||||
.destroy = _destroy,
|
.destroy = _destroy,
|
||||||
},
|
},
|
||||||
.app = {
|
.app = {
|
||||||
|
|||||||
@@ -76,6 +76,20 @@ struct tls_socket_t {
|
|||||||
*/
|
*/
|
||||||
int (*get_fd)(tls_socket_t *this);
|
int (*get_fd)(tls_socket_t *this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the server identity.
|
||||||
|
*
|
||||||
|
* @return server identity
|
||||||
|
*/
|
||||||
|
identification_t* (*get_server_id)(tls_socket_t *this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the peer identity.
|
||||||
|
*
|
||||||
|
* @return peer identity
|
||||||
|
*/
|
||||||
|
identification_t* (*get_peer_id)(tls_socket_t *this);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy a tls_socket_t.
|
* Destroy a tls_socket_t.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user