00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifdef WITH_GSSAPI
00026
00027 #include "GSSAPIHandler.hh"
00028 #include "PrettyDebug.hh"
00029 #include "SocketTCP.hh"
00030
00031 namespace certi {
00032
00033 static pdCDebug D("HLAGSSAPI", "(H-GSSAPI) - ");
00034
00035
00039 void GSSAPIHandler::acquireCred(int InitOrAccept)
00040 {
00041 D.Out(pdInit, "GSSAPI: Acquire Credential.");
00042
00043 Code = gss_acquire_cred(&Minor,
00044 LocalName,
00045 HLA_GSS_SESSION_DURATION,
00046 GSS_C_NULL_OID_SET,
00047 InitOrAccept,
00048 &Credential,
00049 NULL,
00050 NULL);
00051
00052 detectError("GSSAPI: Acquire Credential");
00053
00054 }
00055
00056
00061 void GSSAPIHandler::acceptSecContext(SocketTCP *Socket)
00062 {
00063
00064
00065 gss_buffer_desc InputToken = GSS_C_EMPTY_BUFFER ;
00066 gss_buffer_desc OutputToken = GSS_C_EMPTY_BUFFER ;
00067
00068 int ReturnedFlags = 0 ;
00069 OM_uint32 TimeRec = 0 ;
00070
00071 gss_cred_id_t DelegCredential ;
00072
00073
00074
00075 if (InitSecContext_Started == RTI_TRUE) {
00076 D.Out(pdExcept, "GSSAPI: Reentrant call of GSSHandler::InitSecContext.");
00077 printf("GSSAPI Fatal Error : Reentrant call in InitSecContext.\n");
00078 throw NetworkError("Reentrant call of InitSecContext.");
00079 }
00080
00081 InitSecContext_Started = RTI_TRUE ;
00082 IsClient = RTI_FALSE ;
00083
00084
00085
00086 if (LocalName == GSS_C_NO_NAME) {
00087 printf("GSSAPI: Local Name must be set before accept_sec_ctxt.\n");
00088 throw NetworkError("GSSAPI: Accept_Sec_Context: No name set.");
00089 }
00090
00091
00092
00093
00094 acquireCred(GSS_C_ACCEPT);
00095
00096
00097
00098
00099 do {
00100
00101
00102
00103 getToken(Socket, InputToken);
00104
00105 D.Out(pdInit, "GSSAPI: Received Security Context Token(%d bytes)",
00106 InputToken.length);
00107
00108
00109
00110 Code = gss_accept_sec_context(&Minor,
00111 &Context,
00112 Credential,
00113 &InputToken,
00114 GSS_C_NO_CHANNEL_BINDINGS,
00115 &RemoteName,
00116 &MechType,
00117 &OutputToken,
00118 &ReturnedFlags,
00119 &TimeRec,
00120 &DelegCredential);
00121
00122 detectError("GSSAPI: Accept Security Context");
00123
00124
00125
00126 if (DelegCredential != GSS_C_NO_CREDENTIAL) {
00127 printf("GSSAPI: Warning : Client has delegated his credential.\n");
00128 gss_release_cred(&Minor, &DelegCredential);
00129 }
00130
00131
00132
00133 if (HLA_GSS_FLAGS & !ReturnedFlags) {
00134 printf("GSSAPI: Some unavailable service was requested.\n");
00135 printf("GSSAPI: Returned service flags are : 0x%X\n", ReturnedFlags);
00136 }
00137
00138 D.Out(pdInit, "GSSAPI: Security Context accepted.");
00139
00140
00141
00142 if (InputToken.value != NULL)
00143 free(InputToken.value);
00144
00145 InputToken.length = 0 ;
00146 InputToken.value = NULL ;
00147
00148
00149
00150 if (OutputToken.length > 0) {
00151
00152 D.Out(pdInit,
00153 "GSSAPI: Accept Sec Context sending answer Token(%d bytes).",
00154 OutputToken.length);
00155
00156 sendToken(Socket, OutputToken);
00157
00158 gss_release_buffer(&Minor, &OutputToken);
00159
00160 OutputToken.length = 0 ;
00161 OutputToken.value = NULL ;
00162 }
00163
00164 } while (Code != GSS_S_COMPLETE);
00165
00166 }
00167
00168
00170 GSSAPIHandler::GSSAPIHandler()
00171 {
00172 InitSecContext_Started = RTI_FALSE ;
00173
00174 LocalName = GSS_C_NO_NAME ;
00175 RemoteName = GSS_C_NO_NAME ;
00176
00177 Credential = GSS_C_NO_CREDENTIAL ;
00178 Context = GSS_C_NO_CONTEXT ;
00179
00180 MechType = GSS_C_NULL_OID ;
00181
00182 IsClient = RTI_FALSE ;
00183 }
00184
00185
00187 GSSAPIHandler::~GSSAPIHandler()
00188 {
00189 D.Out(pdTerm, "GSSAPI: Releasing GSSAPI objects.");
00190
00191
00192
00193 if (LocalName != GSS_C_NO_NAME) {
00194 gss_release_name(&Minor, &LocalName);
00195 LocalName = GSS_C_NO_NAME ;
00196 }
00197
00198 if (RemoteName != GSS_C_NO_NAME) {
00199 gss_release_name(&Minor, &RemoteName);
00200 RemoteName = GSS_C_NO_NAME ;
00201 }
00202
00203
00204
00205 if (Credential != GSS_C_NO_CREDENTIAL) {
00206 gss_release_cred(&Minor, &Credential);
00207 Credential = GSS_C_NO_CREDENTIAL ;
00208 }
00209
00210
00211
00212 if ((IsClient == RTI_TRUE) && (Context != GSS_C_NO_CONTEXT)) {
00213
00214 gss_delete_sec_context(&Minor, &Context, GSS_C_NO_BUFFER);
00215
00216 D.Out(pdTerm, "GSSAPI: Released Context.");
00217
00218 Context = GSS_C_NO_CONTEXT ;
00219 }
00220 }
00221
00222
00226 void GSSAPIHandler::detectError(char *ContextString)
00227 {
00228 gss_buffer_desc ErrorMessage ;
00229
00230 if (GSS_ERROR(Code)) {
00231
00232 gss_display_status(&Minor, Code,
00233 GSS_C_GSS_CODE, GSS_MECH_DES,
00234 NULL, &ErrorMessage);
00235
00236 if (ContextString != NULL)
00237 printf("%s: %s\n", ContextString, (char *)ErrorMessage.value);
00238 else
00239 printf("GSSAPI: %s\n", (char *)ErrorMessage.value);
00240
00241 gss_release_buffer(&Minor, &ErrorMessage);
00242
00243 throw NetworkError("Error in GSSAPI(see console output)");
00244 }
00245
00246 }
00247
00248
00252 void GSSAPIHandler::getMessage(SocketTCP *Socket,
00253 gss_buffer_t IncomingBuffer)
00254 {
00255 gss_buffer_desc SealedToken ;
00256 gss_buffer_desc Signature ;
00257
00258 int ConfWasUsed ;
00259 int QOPState ;
00260
00261 switch(RTI_GSSAPI_USAGE) {
00262
00263 case RTI_GSS_NOTHING:
00264
00265 getToken(Socket, SealedToken);
00266
00267
00268 IncomingBuffer->value = SealedToken.value ;
00269 IncomingBuffer->length = SealedToken.length ;
00270
00271
00272
00273 break ;
00274
00275 case RTI_GSS_SIGN_ONLY:
00276
00277 getToken(Socket, SealedToken);
00278
00279
00280 memcpy(& (IncomingBuffer->length), SealedToken.value, sizeof(OM_uint32));
00281
00282
00283 IncomingBuffer->value
00284 = (void *) calloc(IncomingBuffer->length, sizeof(char));
00285
00286 memcpy(IncomingBuffer->value,
00287 (char *) SealedToken.value + sizeof(OM_uint32),
00288 IncomingBuffer->length);
00289
00290
00291 Signature.value
00292 = (char *)SealedToken.value + sizeof(OM_uint32) + IncomingBuffer->length ;
00293 Signature.length
00294 = SealedToken.length - sizeof(OM_uint32) - IncomingBuffer->length ;
00295
00296 Code = gss_verify(&Minor,
00297 Context,
00298 IncomingBuffer,
00299 &Signature,
00300 &QOPState);
00301
00302 detectError("GSSAPI: Get Message[verify]");
00303
00304
00305 free(SealedToken.value);
00306
00307 break ;
00308
00309 case RTI_GSS_ENCRYPT:
00310
00311
00312 getToken(Socket, SealedToken);
00313
00314
00315 Code = gss_unseal(&Minor,
00316 Context,
00317 &SealedToken,
00318 IncomingBuffer,
00319 &ConfWasUsed,
00320 &QOPState);
00321
00322 free(SealedToken.value);
00323 break ;
00324
00325 default:
00326 printf("BAD VALUE FOR RTI_GSSAPI_USAGE\n");
00327 throw RTIinternalError();
00328 }
00329
00330 detectError("GSSAPI: Get Message[unseal]");
00331 }
00332
00333
00339 char *GSSAPIHandler::getRemoteName()
00340 {
00341 gss_buffer_desc OutputName ;
00342 gss_OID OutputNameType ;
00343 char *Buffer ;
00344
00345 gss_display_name(&Minor,
00346 RemoteName,
00347 &OutputName,
00348 &OutputNameType);
00349
00350 detectError("GSSAPI: GetRemoteName");
00351
00352
00353
00354 Buffer = (char *) malloc((OutputName.length + 1) * sizeof(char));
00355 strncpy(Buffer, (char *) OutputName.value, OutputName.length);
00356 Buffer[OutputName.length] = '\0' ;
00357
00358 releaseBuffer(&OutputName);
00359
00360
00361
00362 if (strchr(Buffer, '@') != NULL)
00363 strchr(Buffer, '@')[0] = '\0' ;
00364
00365 D.Out(pdInit, "GSSAPI: Peer is %s.", Buffer);
00366
00367 return Buffer ;
00368 }
00369
00370
00378 void GSSAPIHandler::getToken(SocketTCP *Socket, gss_buffer_desc &Buffer)
00379 {
00380
00381 Socket->SocketTCP::receive((void *) &Buffer.length,
00382 sizeof(Buffer.length));
00383
00384
00385 Buffer.value = (void *) calloc(Buffer.length, sizeof(char));
00386
00387
00388 Socket->SocketTCP::receive((void *) Buffer.value,
00389 Buffer.length);
00390 }
00391
00392
00397 void GSSAPIHandler::initSecContext(SocketTCP *Socket)
00398 {
00399
00400
00401 gss_buffer_desc InputToken = GSS_C_EMPTY_BUFFER ;
00402 gss_buffer_desc OutputToken = GSS_C_EMPTY_BUFFER ;
00403
00404 gss_buffer_t InputTokenPtr = GSS_C_NO_BUFFER ;
00405
00406 int ReturnedFlags = 0 ;
00407 OM_uint32 ContextValidity = 0 ;
00408
00409
00410
00411 if (InitSecContext_Started == RTI_TRUE) {
00412 D.Out(pdExcept, "GSSAPI: Reentrant call of GSSHandler::InitSecContext.");
00413 printf("GSSAPI Fatal Error : Reentrant call in InitSecContext.\n");
00414 throw NetworkError("Reentrant call of InitSecContext.");
00415 }
00416
00417 InitSecContext_Started = RTI_TRUE ;
00418 IsClient = RTI_TRUE ;
00419
00420
00421
00422 if ((LocalName == GSS_C_NO_NAME) || (RemoteName == GSS_C_NO_NAME)) {
00423 printf("GSSAPI: Local/Remote Name must be set before init_sec_ctxt.\n");
00424 throw NetworkError("GSSAPI: Init_Sec_Context: No name set.");
00425 }
00426
00427
00428
00429
00430 acquireCred(GSS_C_INITIATE);
00431
00432 D.Out(pdInit, "GSSAPI: Init Sec Context.");
00433
00434
00435
00436 do {
00437
00438 if (InputToken.length != 0)
00439 InputTokenPtr = &InputToken ;
00440 else
00441 InputTokenPtr = GSS_C_NO_BUFFER ;
00442
00443 Code = gss_init_sec_context(&Minor,
00444 Credential,
00445 &Context,
00446 RemoteName,
00447 GSS_C_NULL_OID,
00448 HLA_GSS_FLAGS,
00449 HLA_GSS_SESSION_DURATION,
00450 GSS_C_NO_CHANNEL_BINDINGS,
00451 InputTokenPtr,
00452 &MechType,
00453 &OutputToken,
00454 &ReturnedFlags,
00455 &ContextValidity);
00456
00457 detectError("GSSAPI: Init Security Context");
00458
00459
00460
00461 if (HLA_GSS_FLAGS & !ReturnedFlags) {
00462 printf("GSSAPI: Some unavailable service was requested.\n");
00463 printf("GSSAPI: Returned service flags are : 0x%X\n", ReturnedFlags);
00464 }
00465
00466 D.Out(pdInit, "GSSAPI: Security Context initiated(Validity: %d).",
00467 ContextValidity);
00468
00469
00470
00471 if (InputToken.value != NULL)
00472 free(InputToken.value);
00473
00474 InputToken.length = 0 ;
00475 InputToken.value = NULL ;
00476
00477
00478
00479 if (OutputToken.length > 0) {
00480
00481 D.Out(pdInit, "GSSAPI: Init Sec Context sending Token(%d bytes).",
00482 OutputToken.length);
00483
00484 sendToken(Socket, OutputToken);
00485
00486 gss_release_buffer(&Minor, &OutputToken);
00487
00488 OutputToken.length = 0 ;
00489 OutputToken.value = NULL ;
00490 }
00491
00492
00493
00494 if (Code==GSS_S_CONTINUE_NEEDED) {
00495
00496 D.Out(pdInit, "GSSAPI: Init Sec Context waiting for server answer...");
00497
00498 getToken(Socket, InputToken);
00499 }
00500
00501 } while (Code != GSS_S_COMPLETE);
00502
00503 }
00504
00505
00509 void GSSAPIHandler::releaseBuffer(gss_buffer_t IncomingBuffer)
00510 {
00511 switch(RTI_GSSAPI_USAGE) {
00512
00513 case RTI_GSS_NOTHING:
00514 case RTI_GSS_SIGN_ONLY:
00515
00516 free(IncomingBuffer->value);
00517 IncomingBuffer->value = NULL ;
00518 IncomingBuffer->length = 0 ;
00519 break ;
00520
00521 case RTI_GSS_ENCRYPT:
00522 gss_release_buffer(&Minor, IncomingBuffer);
00523 }
00524 }
00525
00526
00528 void
00529 GSSAPIHandler::sendMessage(SocketTCP *Socket,
00530 gss_buffer_t OutcomingBuffer)
00531 {
00532 gss_buffer_desc SealedToken ;
00533 gss_buffer_desc SignatureToken ;
00534
00535 OM_uint32 OutLength = OutcomingBuffer->length ;
00536 void *OutValue = OutcomingBuffer->value ;
00537 int ConfState ;
00538
00539 detectError("GSSAPI: Seal Message");
00540
00541 switch(RTI_GSSAPI_USAGE) {
00542
00543 case RTI_GSS_NOTHING:
00544
00545 sendToken(Socket, *OutcomingBuffer);
00546 break ;
00547
00548 case RTI_GSS_SIGN_ONLY:
00549
00550 Code = gss_sign(&Minor,
00551 Context,
00552 GSS_C_QOP_DEFAULT,
00553 OutcomingBuffer,
00554 &SignatureToken);
00555
00556 detectError("GSSAPI: Send Message[sign]");
00557
00558
00559 SealedToken.length = sizeof(OM_uint32);
00560 SealedToken.length += OutLength ;
00561 SealedToken.length += SignatureToken.length ;
00562
00563 SealedToken.value = (void *) calloc(SealedToken.length, sizeof(char));
00564
00565
00566 memcpy(SealedToken.value, & (OutLength), sizeof(OM_uint32));
00567
00568
00569 memcpy((char *) SealedToken.value + sizeof(OM_uint32),
00570 OutValue, OutLength);
00571
00572
00573 memcpy((char *) SealedToken.value + sizeof(OM_uint32) + OutLength,
00574 SignatureToken.value, SignatureToken.length);
00575
00576
00577 sendToken(Socket, SealedToken);
00578
00579
00580 free(SealedToken.value);
00581 gss_release_buffer(&Minor, &SignatureToken);
00582
00583 break ;
00584
00585 case RTI_GSS_ENCRYPT:
00586
00587 Code = gss_seal(&Minor,
00588 Context,
00589 RTI_TRUE,
00590 GSS_C_QOP_DEFAULT,
00591 OutcomingBuffer,
00592 &ConfState,
00593 &SealedToken);
00594
00595 detectError("GSSAPI: Send Message[seal]");
00596
00597 sendToken(Socket, SealedToken);
00598 gss_release_buffer(&Minor, &SealedToken);
00599 }
00600
00601 }
00602
00603
00611 void GSSAPIHandler::sendToken(SocketTCP *Socket, gss_buffer_desc Buffer)
00612 {
00613
00614 Socket->SocketTCP::send((void *) &Buffer.length,
00615 sizeof(Buffer.length));
00616
00617
00618 Socket->SocketTCP::send((void *) Buffer.value,
00619 Buffer.length);
00620 }
00621
00622
00624 void GSSAPIHandler::setLocalName(char *PrincipalName)
00625 {
00626 char *p ;
00627 char bidon[80] ;
00628
00629 gss_buffer_desc LocalBuffer = GSS_C_EMPTY_BUFFER ;
00630
00631 strcpy(bidon, PrincipalName);
00632
00633
00634
00635 if ((PrincipalName == NULL) || (strlen(PrincipalName) == 0))
00636 throw NetworkError("Bad Local Principal Name.");
00637
00638
00639 p = strchr(bidon, '@');
00640 if (p != NULL) {
00641 *p = '\0' ;
00642 }
00643
00644 LocalBuffer.value = bidon ;
00645 LocalBuffer.length = strlen(bidon) + 1 ;
00646
00647
00648
00649 Code = gss_import_name(&Minor,
00650 (gss_buffer_t) &LocalBuffer,
00651 GSS_C_NULL_OID,
00652 &LocalName);
00653
00654 D.Out(pdInit, "GSSAPI: Local Name set to %s.", bidon);
00655
00656 detectError("GSSAPI/setLocalName");
00657 }
00658
00659
00661
00663 void GSSAPIHandler::setRemoteName(char *PrincipalName)
00664 {
00665 gss_buffer_desc LocalBuffer = GSS_C_EMPTY_BUFFER ;
00666
00667
00668
00669 if ((PrincipalName == NULL) || (strlen(PrincipalName) == 0))
00670 throw NetworkError("Bad Local Principal Name.");
00671
00672 LocalBuffer.value = PrincipalName ;
00673 LocalBuffer.length = strlen(PrincipalName) + 1 ;
00674
00675
00676
00677 Code = gss_import_name(&Minor,
00678 (gss_buffer_t) &LocalBuffer,
00679 GSS_C_NULL_OID,
00680 &RemoteName);
00681
00682 D.Out(pdInit, "GSSAPI: Remote Name set to %s.", PrincipalName);
00683
00684 detectError("GSSAPI/setRemoteName");
00685 }
00686
00687 }
00688
00689 #endif // WITH_GSSAPI
00690
00691