Skip to content

Commit a108c7d

Browse files
committed
Implemented CORE-5948: Make WIN_SSPI plugin produce keys for wirecrypt plugin
1 parent 5b8f3b6 commit a108c7d

2 files changed

Lines changed: 78 additions & 10 deletions

File tree

src/auth/trusted/AuthSspi.cpp

Lines changed: 72 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,8 @@ bool AuthSspi::initEntries()
105105
}
106106

107107
AuthSspi::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+
128136
bool 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-
353373
int 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+
419469
int 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+
459521
void registerTrustedClient(Firebird::IPluginManager* iPlugin)
460522
{
461523
iPlugin->registerPluginFactory(Firebird::IPluginManager::TYPE_AUTH_CLIENT, plugName, &clientFactory);

src/auth/trusted/AuthSspi.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class AuthSspi
5555
{
5656
public:
5757
typedef Firebird::ObjectsArray<Firebird::string> GroupsList;
58+
typedef Firebird::UCharBuffer Key;
5859

5960
private:
6061
enum {BUFSIZE = 4096};
@@ -66,6 +67,7 @@ class AuthSspi
6667
Firebird::string ctName;
6768
bool wheel;
6869
GroupsList groupNames;
70+
Key sessionKey;
6971

7072
// Handle of library
7173
static HINSTANCE library;
@@ -103,6 +105,9 @@ class AuthSspi
103105

104106
// returns Windows user/group names, matching accepted security context
105107
bool getLogin(Firebird::string& login, bool& wh, GroupsList& grNames);
108+
109+
// returns session key for wire encryption
110+
const Key* getKey() const;
106111
};
107112

108113
class WinSspiServer :
@@ -135,6 +140,7 @@ class WinSspiClient :
135140
private:
136141
AuthSspi::DataHolder sspiData;
137142
AuthSspi sspi;
143+
bool keySet;
138144
};
139145

140146
void registerTrustedClient(Firebird::IPluginManager* iPlugin);

0 commit comments

Comments
 (0)