📄 gssapihandler.cc
字号:
// ----------------------------------------------------------------------------// CERTI - HLA RunTime Infrastructure// Copyright (C) 2002, 2003 ONERA//// This file is part of CERTI-libCERTI//// CERTI-libCERTI is free software ; you can redistribute it and/or// modify it under the terms of the GNU Lesser General Public License// as published by the Free Software Foundation ; either version 2 of// the License, or (at your option) any later version.//// CERTI-libCERTI 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// Lesser General Public License for more details.//// You should have received a copy of the GNU Lesser General Public// License along with this program ; if not, write to the Free Software// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307// USA//// $Id: GSSAPIHandler.cc,v 3.4 2003/06/27 17:26:28 breholee Exp $// ----------------------------------------------------------------------------#ifdef WITH_GSSAPI#include <config.h>#include "GSSAPIHandler.hh"#include "RTItypes.hh"#include "PrettyDebug.hh"#include "SocketTCP.hh"namespace certi {static pdCDebug D("HLAGSSAPI", "(H-GSSAPI) - ");// ----------------------------------------------------------------------------/*! Retrieve credential for Local principal. Parameter can be GSS_C_INITIATE(client) or GSS_C_ACCEPT(server).*/void GSSAPIHandler::acquireCred(int InitOrAccept){ D.Out(pdInit, "GSSAPI: Acquire Credential."); Code = gss_acquire_cred(&Minor, LocalName, // Principal Name HLA_GSS_SESSION_DURATION, // Expiration delay GSS_C_NULL_OID_SET, InitOrAccept, // Cred. used to init. &Credential, // Returned Credential NULL, NULL); detectError("GSSAPI: Acquire Credential");}// ----------------------------------------------------------------------------/*! Session Initiator must call SetRemoteName, and then InitSecContext. On the remote side, AcceptSecContext will be directly called. In both case, Local Name must have been previously set.*/void GSSAPIHandler::acceptSecContext(SocketTCP *Socket){ // The Input and Output Buffers used by the initial Handshake. gss_buffer_desc InputToken = GSS_C_EMPTY_BUFFER ; gss_buffer_desc OutputToken = GSS_C_EMPTY_BUFFER ; int ReturnedFlags = 0 ; OM_uint32 TimeRec = 0 ; gss_cred_id_t DelegCredential ; // Prevent Re-entrant calls if (InitSecContext_Started == RTI_TRUE) { D.Out(pdExcept, "GSSAPI: Reentrant call of GSSHandler::InitSecContext."); printf("GSSAPI Fatal Error : Reentrant call in InitSecContext.\n"); throw NetworkError("Reentrant call of InitSecContext."); } InitSecContext_Started = RTI_TRUE ; IsClient = RTI_FALSE ; // Check Local Principal Name if (LocalName == GSS_C_NO_NAME) { printf("GSSAPI: Local Name must be set before accept_sec_ctxt.\n"); throw NetworkError("GSSAPI: Accept_Sec_Context: No name set."); } // Retrieve Credential acquireCred(GSS_C_ACCEPT); // Accept Security Context(Server Side) do { // Wait for peer's response if needed(InputToken may be allocated) getToken(Socket, InputToken); D.Out(pdInit, "GSSAPI: Received Security Context Token(%d bytes)", InputToken.length); // Accept Token Code = gss_accept_sec_context(&Minor, &Context, // Initially no context Credential, &InputToken, // Client Token GSS_C_NO_CHANNEL_BINDINGS, &RemoteName, // Client Name or NULL &MechType, &OutputToken, &ReturnedFlags, &TimeRec, &DelegCredential); detectError("GSSAPI: Accept Security Context"); // If the Credential was delegated, print a warning. if (DelegCredential != GSS_C_NO_CREDENTIAL) { printf("GSSAPI: Warning : Client has delegated his credential.\n"); gss_release_cred(&Minor, &DelegCredential); } // If a service was requested but is not available, print a warning. if (HLA_GSS_FLAGS & !ReturnedFlags) { printf("GSSAPI: Some unavailable service was requested.\n"); printf("GSSAPI: Returned service flags are : 0x%X\n", ReturnedFlags); } D.Out(pdInit, "GSSAPI: Security Context accepted."); // Free Input Token if (InputToken.value != NULL) free(InputToken.value); InputToken.length = 0 ; InputToken.value = NULL ; // Send Output token to peer and then release it. if (OutputToken.length > 0) { D.Out(pdInit, "GSSAPI: Accept Sec Context sending answer Token(%d bytes).", OutputToken.length); sendToken(Socket, OutputToken); gss_release_buffer(&Minor, &OutputToken); OutputToken.length = 0 ; OutputToken.value = NULL ; } } while (Code != GSS_S_COMPLETE); // Loop until no response is needed}// ----------------------------------------------------------------------------//! GSSAPIHandler.GSSAPIHandler::GSSAPIHandler(){ InitSecContext_Started = RTI_FALSE ; LocalName = GSS_C_NO_NAME ; RemoteName = GSS_C_NO_NAME ; Credential = GSS_C_NO_CREDENTIAL ; Context = GSS_C_NO_CONTEXT ; MechType = GSS_C_NULL_OID ; IsClient = RTI_FALSE ; // Reset by Init and Accept Sec. Context}// ----------------------------------------------------------------------------//! Destructor.GSSAPIHandler::~GSSAPIHandler(){ D.Out(pdTerm, "GSSAPI: Releasing GSSAPI objects."); // Release Names if (LocalName != GSS_C_NO_NAME) { gss_release_name(&Minor, &LocalName); LocalName = GSS_C_NO_NAME ; } if (RemoteName != GSS_C_NO_NAME) { gss_release_name(&Minor, &RemoteName); RemoteName = GSS_C_NO_NAME ; } // Release Credential if (Credential != GSS_C_NO_CREDENTIAL) { gss_release_cred(&Minor, &Credential); Credential = GSS_C_NO_CREDENTIAL ; } // Release Context(Client only) if ((IsClient == RTI_TRUE) && (Context != GSS_C_NO_CONTEXT)) { gss_delete_sec_context(&Minor, &Context, GSS_C_NO_BUFFER); D.Out(pdTerm, "GSSAPI: Released Context."); Context = GSS_C_NO_CONTEXT ; }}// ----------------------------------------------------------------------------/*! Throw NetworkError exception if 'Code' is different from GSS_S_COMPLETE. An Error message is displayed, starting with ContextString if not NULL.*/void GSSAPIHandler::detectError(char *ContextString){ gss_buffer_desc ErrorMessage ; if (GSS_ERROR(Code)) { gss_display_status(&Minor, Code, GSS_C_GSS_CODE, GSS_MECH_DES, NULL, &ErrorMessage); if (ContextString != NULL) printf("%s: %s\n", ContextString, (char *)ErrorMessage.value); else printf("GSSAPI: %s\n", (char *)ErrorMessage.value); gss_release_buffer(&Minor, &ErrorMessage); throw NetworkError("Error in GSSAPI(see console output)"); }}// ----------------------------------------------------------------------------/*! All buffers contain clear-text messages. Incoming buffer value array is allocated by getMessage, and must be freed by calling ReleaseBuffer.*/void GSSAPIHandler::getMessage(SocketTCP *Socket, gss_buffer_t IncomingBuffer){ gss_buffer_desc SealedToken ; gss_buffer_desc Signature ; int ConfWasUsed ; int QOPState ; switch(RTI_GSSAPI_USAGE) { case RTI_GSS_NOTHING: // Get non-encrypted token. getToken(Socket, SealedToken); // 'Copy' non encrypted Token into Incoming Buffer(just change pointers) IncomingBuffer->value = SealedToken.value ; IncomingBuffer->length = SealedToken.length ; // Don't free SealedToken ! IncomingBuffer will be freed by a call // to GSSAPIHandler::ReleaseBuffer. break ; case RTI_GSS_SIGN_ONLY: // Get Token(ie "Buffer Length" + "Buffer" + "Signature Token") getToken(Socket, SealedToken); // Get Buffer length memcpy(& (IncomingBuffer->length), SealedToken.value, sizeof(OM_uint32)); // Get Buffer IncomingBuffer->value = (void *) calloc(IncomingBuffer->length, sizeof(char)); memcpy(IncomingBuffer->value, (char *) SealedToken.value + sizeof(OM_uint32), IncomingBuffer->length); // Check Signature Signature.value = (char *)SealedToken.value + sizeof(OM_uint32) + IncomingBuffer->length ; Signature.length = SealedToken.length - sizeof(OM_uint32) - IncomingBuffer->length ; Code = gss_verify(&Minor, Context, IncomingBuffer, &Signature, &QOPState); detectError("GSSAPI: Get Message[verify]"); // Free memory free(SealedToken.value); break ; case RTI_GSS_ENCRYPT: // Get encrypted token. getToken(Socket, SealedToken); // Decrypt Token Code = gss_unseal(&Minor, Context, &SealedToken, IncomingBuffer, &ConfWasUsed, &QOPState); free(SealedToken.value); break ; default: printf("BAD VALUE FOR RTI_GSSAPI_USAGE\n"); throw RTIinternalError(); } detectError("GSSAPI: Get Message[unseal]");}// ----------------------------------------------------------------------------/*! After the security context has been accepted, the server can retrieve the client principal name. The string is allocated with malloc and must be freed by the caller. The returned name is stripped from any network address part(starting with a '@').*/char *GSSAPIHandler::getRemoteName(){ gss_buffer_desc OutputName ; gss_OID OutputNameType ; char *Buffer ; gss_display_name(&Minor,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -