@@ -105,7 +105,8 @@ bool AuthSspi::initEntries()
105105}
106106
107107AuthSspi::AuthSspi ()
108- : hasContext(false ), ctName(*getDefaultMemoryPool ()), wheel(false ), groupNames(*getDefaultMemoryPool ())
108+ : hasContext(false ), ctName(*getDefaultMemoryPool ()), wheel(false ),
109+ groupNames(*getDefaultMemoryPool ()), sessionKey(*getDefaultMemoryPool ())
109110{
110111 TimeStamp timeOut;
111112 hasCredentials = initEntries () && (fAcquireCredentialsHandle (0 , " NTLM" ,
@@ -125,6 +126,13 @@ AuthSspi::~AuthSspi()
125126 }
126127}
127128
129+ const AuthSspi::Key* AuthSspi::getKey () const
130+ {
131+ if (sessionKey.hasData ())
132+ return &sessionKey;
133+ return NULL ;
134+ }
135+
128136bool AuthSspi::checkAdminPrivilege ()
129137{
130138 // Query access token from security context
@@ -231,15 +239,23 @@ bool AuthSspi::request(AuthSspi::DataHolder& data)
231239 SECURITY_STATUS x = fInitializeSecurityContext (
232240 &secHndl, hasContext ? &ctxtHndl : 0 , 0 , 0 , 0 , SECURITY_NATIVE_DREP,
233241 hasContext ? &inputDesc : 0 , 0 , &ctxtHndl, &outputDesc, &fContextAttr , &timeOut);
242+
243+ SecPkgContext_SessionKey key;
234244 switch (x)
235245 {
236246 case SEC_E_OK:
247+ if (fQueryContextAttributes (&ctxtHndl, SECPKG_ATTR_SESSION_KEY, &key) == SEC_E_OK)
248+ {
249+ sessionKey.assign (key.SessionKey , key.SessionKeyLength );
250+ }
237251 fDeleteSecurityContext (&ctxtHndl);
238252 hasContext = false ;
239253 break ;
254+
240255 case SEC_I_CONTINUE_NEEDED:
241256 hasContext = true ;
242257 break ;
258+
243259 default :
244260 if (hasContext)
245261 {
@@ -281,10 +297,12 @@ bool AuthSspi::accept(AuthSspi::DataHolder& data)
281297
282298 ULONG fContextAttr = 0 ;
283299 SecPkgContext_Names name;
300+ SecPkgContext_SessionKey key;
284301 SECURITY_STATUS x = fAcceptSecurityContext (
285302 &secHndl, hasContext ? &ctxtHndl : 0 , &inputDesc, 0 ,
286303 SECURITY_NATIVE_DREP, &ctxtHndl, &outputDesc,
287304 &fContextAttr , &timeOut);
305+
288306 switch (x)
289307 {
290308 case SEC_E_OK:
@@ -295,12 +313,18 @@ bool AuthSspi::accept(AuthSspi::DataHolder& data)
295313 fFreeContextBuffer (name.sUserName );
296314 wheel = checkAdminPrivilege ();
297315 }
316+ if (fQueryContextAttributes (&ctxtHndl, SECPKG_ATTR_SESSION_KEY, &key) == SEC_E_OK)
317+ {
318+ sessionKey.assign (key.SessionKey , key.SessionKeyLength );
319+ }
298320 fDeleteSecurityContext (&ctxtHndl);
299321 hasContext = false ;
300322 break ;
323+
301324 case SEC_I_CONTINUE_NEEDED:
302325 hasContext = true ;
303326 break ;
327+
304328 default :
305329 if (hasContext)
306330 {
@@ -346,10 +370,6 @@ WinSspiServer::WinSspiServer(Firebird::IPluginConfig*)
346370 : sspiData(getPool())
347371{ }
348372
349- WinSspiClient::WinSspiClient (Firebird::IPluginConfig*)
350- : sspiData(getPool())
351- { }
352-
353373int WinSspiServer::authenticate (Firebird::CheckStatusWrapper* status,
354374 IServerBlock* sBlock ,
355375 IWriter* writerInterface)
@@ -374,21 +394,46 @@ int WinSspiServer::authenticate(Firebird::CheckStatusWrapper* status,
374394 sspi.getLogin (login, wheel, grNames);
375395 ISC_systemToUtf8 (login);
376396
397+ // publish user name obtained during SSPI handshake
377398 writerInterface->add (status, login.c_str ());
399+ if (status->getState () & IStatus::STATE_ERRORS)
400+ return AUTH_FAILED;
401+
402+ // is it suser account?
378403 if (wheel)
379404 {
380405 writerInterface->add (status, FB_DOMAIN_ANY_RID_ADMINS);
406+ if (status->getState () & IStatus::STATE_ERRORS)
407+ return AUTH_FAILED;
381408 writerInterface->setType (status, FB_PREDEFINED_GROUP);
409+ if (status->getState () & IStatus::STATE_ERRORS)
410+ return AUTH_FAILED;
382411 }
383412
384- // ToDo: walk groups to which login belongs and list them using writerInterface
413+ // walk groups to which login belongs and list them using writerInterface
385414 Firebird::string grName;
386415 for (unsigned n = 0 ; n < grNames.getCount (); ++n)
387416 {
388417 grName = grNames[n];
389418 ISC_systemToUtf8 (grName);
390419 writerInterface->add (status, grName.c_str ());
420+ if (status->getState () & IStatus::STATE_ERRORS)
421+ return AUTH_FAILED;
391422 writerInterface->setType (status, " Group" );
423+ if (status->getState () & IStatus::STATE_ERRORS)
424+ return AUTH_FAILED;
425+ }
426+
427+ // set wire crypt key
428+ const UCharBuffer* key = sspi.getKey ();
429+ if (key)
430+ {
431+ ICryptKey* cKey = sBlock ->newKey (status);
432+ if (status->getState () & IStatus::STATE_ERRORS)
433+ return AUTH_FAILED;
434+ cKey->setSymmetric (status, " Symmetric" , key->getCount (), key->begin ());
435+ if (status->getState () & IStatus::STATE_ERRORS)
436+ return AUTH_FAILED;
392437 }
393438
394439 return AUTH_SUCCESS;
@@ -416,13 +461,16 @@ int WinSspiServer::release()
416461 return 1 ;
417462}
418463
464+
465+ WinSspiClient::WinSspiClient (Firebird::IPluginConfig*)
466+ : sspiData(getPool()), keySet(false )
467+ { }
468+
419469int WinSspiClient::authenticate (Firebird::CheckStatusWrapper* status,
420470 IClientBlock* cBlock)
421471{
422472 try
423473 {
424- const bool wasActive = sspi.isActive ();
425-
426474 sspiData.clear ();
427475 unsigned int length;
428476 const unsigned char * bytes = cBlock->getData (&length);
@@ -432,9 +480,22 @@ int WinSspiClient::authenticate(Firebird::CheckStatusWrapper* status,
432480 return AUTH_CONTINUE;
433481
434482 cBlock->putData (status, sspiData.getCount (), sspiData.begin ());
483+ if (status->getState () & IStatus::STATE_ERRORS)
484+ return AUTH_FAILED;
435485
436- if (!wasActive)
437- return AUTH_SUCCESS;
486+ // set wire crypt key
487+ const UCharBuffer* key = sspi.getKey ();
488+ if (key && !keySet)
489+ {
490+ ICryptKey* cKey = cBlock->newKey (status);
491+ if (status->getState () & IStatus::STATE_ERRORS)
492+ return AUTH_FAILED;
493+ cKey->setSymmetric (status, " Symmetric" , key->getCount (), key->begin ());
494+ if (status->getState () & IStatus::STATE_ERRORS)
495+ return AUTH_FAILED;
496+
497+ keySet = true ;
498+ }
438499 }
439500 catch (const Firebird::Exception& ex)
440501 {
@@ -456,6 +517,7 @@ int WinSspiClient::release()
456517 return 1 ;
457518}
458519
520+
459521void registerTrustedClient (Firebird::IPluginManager* iPlugin)
460522{
461523 iPlugin->registerPluginFactory (Firebird::IPluginManager::TYPE_AUTH_CLIENT, plugName, &clientFactory);
0 commit comments