summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/Common/Request/GSSAPIAuthRequest.h39
-rw-r--r--src/Core/RequestHandler/GSSAPIAuthRequestHandler.h46
-rw-r--r--src/Net/Connection.cpp2
-rw-r--r--src/Net/Connection.h16
-rw-r--r--src/madc.cpp10
5 files changed, 103 insertions, 10 deletions
diff --git a/src/Common/Request/GSSAPIAuthRequest.h b/src/Common/Request/GSSAPIAuthRequest.h
index 51ab0f8..138107e 100644
--- a/src/Common/Request/GSSAPIAuthRequest.h
+++ b/src/Common/Request/GSSAPIAuthRequest.h
@@ -86,7 +86,7 @@ class GSSAPIAuthRequest : public Request {
}
majStat = gss_init_sec_context(&minStat, GSS_C_NO_CREDENTIAL, &gssContext, gssServiceName, GSS_C_NO_OID, GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG,
- 0, GSS_C_NO_CHANNEL_BINDINGS, GSS_C_NO_BUFFER, NULL, &buffer, NULL, NULL);
+ 0, GSS_C_NO_CHANNEL_BINDINGS, GSS_C_NO_BUFFER, 0, &buffer, 0, 0);
if(majStat == GSS_S_COMPLETE) {
std::cout << "GSS context established." << std::endl;
@@ -124,7 +124,7 @@ class GSSAPIAuthRequest : public Request {
std::memcpy(recvBuffer.value, packet.getData(), recvBuffer.length);
majStat = gss_init_sec_context(&minStat, GSS_C_NO_CREDENTIAL, &gssContext, gssServiceName, GSS_C_NO_OID, GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | GSS_C_INTEG_FLAG,
- 0, GSS_C_NO_CHANNEL_BINDINGS, &recvBuffer, NULL, &sendBuffer, NULL, NULL);
+ 0, GSS_C_NO_CHANNEL_BINDINGS, &recvBuffer, 0, &sendBuffer, 0, 0);
std::free(recvBuffer.value);
@@ -145,9 +145,40 @@ class GSSAPIAuthRequest : public Request {
gss_release_buffer(&minStat, &sendBuffer);
}
else {
- return false;
+ recvBuffer.length = packet.getLength();
+ recvBuffer.value = std::malloc(recvBuffer.length);
+ std::memcpy(recvBuffer.value, packet.getData(), recvBuffer.length);
+
+ const gnutls_datum_t *cert = connection->getPeerCertificate();
+
+ sendBuffer.length = cert->size;
+ sendBuffer.value = cert->data;
+
+ majStat = gss_verify_mic(&minStat, gssContext, &sendBuffer, &recvBuffer, 0);
+
+ std::free(recvBuffer.value);
+
+ if(majStat != GSS_S_COMPLETE)
+ return false;
+
+ connection->setAuthenticated();
+ std::cout << "Authentication complete." << std::endl;
+
+ majStat = gss_delete_sec_context(&minStat, &gssContext, &sendBuffer);
+
+ if(majStat != GSS_S_COMPLETE) {
+ gss_release_buffer(&minStat, &sendBuffer);
+ return false;
+ }
+
+ if(!connection->send(Net::Packet(Net::Packet::TYPE_GSSAPI_AUTH, packet.getRequestId(), sendBuffer.value, sendBuffer.length))) {
+ gss_release_buffer(&minStat, &sendBuffer);
+ return false;
+ }
+
+ gss_release_buffer(&minStat, &sendBuffer);
- //setFinished();
+ setFinished();
}
return true;
diff --git a/src/Core/RequestHandler/GSSAPIAuthRequestHandler.h b/src/Core/RequestHandler/GSSAPIAuthRequestHandler.h
index 204af6f..47538a4 100644
--- a/src/Core/RequestHandler/GSSAPIAuthRequestHandler.h
+++ b/src/Core/RequestHandler/GSSAPIAuthRequestHandler.h
@@ -31,14 +31,16 @@ namespace Mad {
namespace Core {
namespace RequestHandler {
+// TODO Error handling
+
class GSSAPIAuthRequestHandler : public Common::RequestHandler {
private:
gss_ctx_id_t gssContext;
- bool gssContinue;
+ bool gssContinue, sentSignature;
public:
- GSSAPIAuthRequestHandler() : gssContext(GSS_C_NO_CONTEXT), gssContinue(true) {}
+ GSSAPIAuthRequestHandler() : gssContext(GSS_C_NO_CONTEXT), gssContinue(true), sentSignature(false) {}
virtual bool handlePacket(Net::Connection *connection, const Net::Packet &packet) {
if(isFinished())
@@ -55,7 +57,7 @@ class GSSAPIAuthRequestHandler : public Common::RequestHandler {
recvBuffer.value = std::malloc(recvBuffer.length);
std::memcpy(recvBuffer.value, packet.getData(), recvBuffer.length);
- majStat = gss_accept_sec_context(&minStat, &gssContext, GSS_C_NO_CREDENTIAL, &recvBuffer, GSS_C_NO_CHANNEL_BINDINGS, NULL, NULL, &sendBuffer, NULL, NULL, NULL);
+ majStat = gss_accept_sec_context(&minStat, &gssContext, GSS_C_NO_CREDENTIAL, &recvBuffer, GSS_C_NO_CHANNEL_BINDINGS, 0, 0, &sendBuffer, 0, 0, 0);
std::free(recvBuffer.value);
@@ -75,10 +77,44 @@ class GSSAPIAuthRequestHandler : public Common::RequestHandler {
gss_release_buffer(&minStat, &sendBuffer);
}
+ else if(!sentSignature) {
+ if(packet.getLength() != 0)
+ return false;
+
+ const gnutls_datum_t *cert = connection->getCertificate();
+
+ recvBuffer.length = cert->size;
+ recvBuffer.value = cert->data;
+
+ majStat = gss_get_mic(&minStat, gssContext, GSS_C_QOP_DEFAULT, &recvBuffer, &sendBuffer);
+
+ if(majStat != GSS_S_COMPLETE) {
+ gss_release_buffer(&minStat, &sendBuffer);
+ return false;
+ }
+
+ if(!connection->send(Net::Packet(Net::Packet::TYPE_GSSAPI_AUTH, packet.getRequestId(), sendBuffer.value, sendBuffer.length))) {
+ gss_release_buffer(&minStat, &sendBuffer);
+ return false;
+ }
+
+ gss_release_buffer(&minStat, &sendBuffer);
+
+ sentSignature = true;
+ }
else {
- return false;
+ recvBuffer.length = packet.getLength();
+ recvBuffer.value = std::malloc(recvBuffer.length);
+ std::memcpy(recvBuffer.value, packet.getData(), recvBuffer.length);
+
+ majStat = gss_process_context_token(&minStat, gssContext, &recvBuffer);
+
+ std::free(recvBuffer.value);
+
+ if(majStat != GSS_S_COMPLETE)
+ return false;
- //setFinished();
+ setFinished();
}
return true;
diff --git a/src/Net/Connection.cpp b/src/Net/Connection.cpp
index 6a30d11..cfced4f 100644
--- a/src/Net/Connection.cpp
+++ b/src/Net/Connection.cpp
@@ -226,6 +226,8 @@ void Connection::doDisconnect() {
delete peer;
peer = 0;
+ authenticated = false;
+
state = DISCONNECTED;
}
diff --git a/src/Net/Connection.h b/src/Net/Connection.h
index 21e8444..d733ee3 100644
--- a/src/Net/Connection.h
+++ b/src/Net/Connection.h
@@ -54,6 +54,8 @@ class Connection {
sigc::signal<void,Connection*,const Packet&> signal;
+ bool authenticated;
+
void doHandshake();
void packetHeaderReceiveHandler(const void *data, unsigned long length);
@@ -126,7 +128,7 @@ class Connection {
}
public:
- Connection() : state(DISCONNECTED), peer(0) {
+ Connection() : state(DISCONNECTED), authenticated(false), peer(0) {
transR.length = transR.transmitted = 0;
transR.data = 0;
@@ -157,6 +159,18 @@ class Connection {
return (state == DISCONNECT || state == BYE);
}
+ bool isAuthenticated() const {return authenticated;}
+ void setAuthenticated() {authenticated = true;}
+
+ const gnutls_datum_t* getCertificate() {
+ return gnutls_certificate_get_ours(session);
+ }
+
+ const gnutls_datum_t* getPeerCertificate() {
+ unsigned int n;
+ return gnutls_certificate_get_peers(session, &n);
+ }
+
const IPAddress* getPeer() {return peer;}
int getSocket() const {return sock;}
diff --git a/src/madc.cpp b/src/madc.cpp
index 43b37d3..3732079 100644
--- a/src/madc.cpp
+++ b/src/madc.cpp
@@ -46,6 +46,16 @@ int main() {
Mad::Common::Request::IdentifyRequest::send(connection, requestManager, "localhost");
Mad::Common::Request::GSSAPIAuthRequest::send(connection, requestManager, "host");
+
+ while(true) {
+ struct pollfd fd = connection->getPollfd();
+
+ if(poll(&fd, 1, 1500) > 0)
+ connection->sendReceive(fd.revents);
+ else
+ break;
+ }
+
Mad::Common::Request::DisconnectRequest::send(connection, requestManager);
while(connection->isConnected()) {