/* * GSSAPIAuthRequestHandler.cpp * * Copyright (C) 2008 Matthias Schiffer * * 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 3 of the License, or * (at your option) any later version. * * 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. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include "GSSAPIAuthRequestHandler.h" #include #include #include namespace Mad { namespace Server { namespace RequestHandlers { // TODO Error handling void GSSAPIAuthRequestHandler::handlePacket(const Common::XmlPacket &packet) { if(packet.getType() != "AuthGSSAPI") { Common::Logger::log(Common::Logger::ERROR, "Received an unexpected packet."); Common::XmlPacket ret; ret.setType("Error"); ret.add("ErrorCode", Net::Exception::UNEXPECTED_PACKET); sendPacket(ret); signalFinished()(); return; } OM_uint32 majStat, minStat; gss_buffer_desc recvBuffer, sendBuffer; // Needs error handling! if(gssContinue) { const void *pkgData; packet["authToken"].getBinaryData(&pkgData, &recvBuffer.length); recvBuffer.value = std::malloc(recvBuffer.length); std::memcpy(recvBuffer.value, pkgData, recvBuffer.length); 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); if(majStat == GSS_S_COMPLETE) { Common::Logger::log(Common::Logger::VERBOSE, "GSS context established."); gssContinue = false; } else if(majStat != GSS_S_CONTINUE_NEEDED) { gss_release_buffer(&minStat, &sendBuffer); return; } Common::XmlPacket ret; ret.setType("AuthGSSAPI"); ret.addBinary("authToken", sendBuffer.value, sendBuffer.length); sendPacket(ret); gss_release_buffer(&minStat, &sendBuffer); } else if(!sentSignature) { if(!packet["binary"].isEmpty()) return; /*const gnutls_datum_t *cert = getConnection()->getCertificate(); recvBuffer.length = cert->size; recvBuffer.value = cert->data;*/ recvBuffer.value = getConnection()->getCertificate(&recvBuffer.length); majStat = gss_get_mic(&minStat, gssContext, GSS_C_QOP_DEFAULT, &recvBuffer, &sendBuffer); if(majStat != GSS_S_COMPLETE) { gss_release_buffer(&minStat, &sendBuffer); return; } Common::XmlPacket ret; ret.setType("AuthGSSAPI"); ret.addBinary("certMic", sendBuffer.value, sendBuffer.length); sendPacket(ret); gss_release_buffer(&minStat, &sendBuffer); sentSignature = true; } else { const void *pkgData; packet["authToken"].getBinaryData(&pkgData, &recvBuffer.length); recvBuffer.value = std::malloc(recvBuffer.length); std::memcpy(recvBuffer.value, pkgData, recvBuffer.length); majStat = gss_process_context_token(&minStat, gssContext, &recvBuffer); std::free(recvBuffer.value); if(majStat != GSS_S_COMPLETE) return; signalFinished()(); } } } } }