8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 07:23:04 +01:00

Fixed some authentication errors

This commit is contained in:
alexpeshkoff 2013-05-22 07:31:34 +00:00
parent cf9594ec32
commit c3e6fe4632
12 changed files with 179 additions and 98 deletions

View File

@ -58,62 +58,53 @@ DebugServer::DebugServer(Firebird::IPluginConfig*)
: str(getPool())
{ }
int FB_CARG DebugServer::authenticate(Firebird::IStatus* status, IServerBlock* sBlock,
int FB_CARG DebugServer::authenticate(Firebird::IStatus* status, IServerBlock* sb,
IWriter* writerInterface)
{
/***
try
{
Firebird::MasterInterfacePtr()->upgradeInterface(dpb, FB_AUTH_CLUMPLETS_VERSION, upInfo);
str.erase();
#ifdef AUTH_VERBOSE
fprintf(stderr, "DebugServer::authenticate\n");
#endif
unsigned int length;
const unsigned char* val = sb->getData(&length);
#ifdef AUTH_VERBOSE
fprintf(stderr, "DebugServer::authenticate: get()=%.*s\n", length, val);
#endif
#ifdef AUTH_VERBOSE
fprintf(stderr, "DebugServer::startAuthentication: tA-tag=%d dpb=%p\n", tags->trustedAuth, dpb);
#endif
if (tags->trustedAuth && dpb && dpb->find(tags->trustedAuth))
if (str.isEmpty())
{
unsigned int len;
const UCHAR* s = dpb->get(&len);
str.assign(val, length);
str += '_';
#ifdef AUTH_VERBOSE
fprintf(stderr, "DebugServer::startAuthentication: get()=%.*s\n", len, s);
fprintf(stderr, "DebugServer::authenticate1: %s\n", str.c_str());
#endif
str.assign(s, len);
sb->putData(status, str.length(), str.c_str());
if (!status->isSuccess())
{
return AUTH_FAILED;
}
return AUTH_MORE_DATA;
}
str += '_';
str.assign(val, length);
#ifdef AUTH_VERBOSE
fprintf(stderr, "DebugServer::startAuthentication: %s\n", str.c_str());
fprintf(stderr, "DebugServer::authenticate2: %s\n", str.c_str());
#endif
return AUTH_MORE_DATA;
}
catch (const Firebird::Exception& ex)
{
ex.stuffException(status);
}
***/
return AUTH_FAILED;
}
writerInterface->add(str.c_str());
str.erase();
/***
int FB_CARG DebugServer::contAuthentication(Firebird::IStatus* status, const unsigned char* data,
unsigned int size, IWriter* writerInterface)
{
try
{
#ifdef AUTH_VERBOSE
fprintf(stderr, "DebugServer::contAuthentication: %.*s\n", size, data);
#endif
Firebird::MasterInterfacePtr()->upgradeInterface(writerInterface, FB_AUTH_WRITER_VERSION, upInfo);
writerInterface->add(Firebird::string((const char*) data, size).c_str());
return AUTH_SUCCESS;
}
catch (const Firebird::Exception& ex)
{
ex.stuffException(status);
return AUTH_FAILED;
}
return AUTH_FAILED;
}
***/
int FB_CARG DebugServer::release()
{
@ -130,58 +121,53 @@ DebugClient::DebugClient(Firebird::IPluginConfig*)
: str(getPool())
{ }
int FB_CARG DebugClient::authenticate(Firebird::IStatus* status, IClientBlock* cBlock)
int FB_CARG DebugClient::authenticate(Firebird::IStatus* status, IClientBlock* cb)
{
/***
try
{
str = "HAND";
#ifdef AUTH_VERBOSE
fprintf(stderr, "DebugClient::startAuthentication: %s\n", str.c_str());
#endif
if (dpb && tags->trustedAuth)
if (str != "HAND")
{
Firebird::MasterInterfacePtr()->upgradeInterface(dpb, FB_AUTH_CLUMPLETS_VERSION, upInfo);
dpb->add(tags->trustedAuth, str.c_str(), str.length());
#ifdef AUTH_VERBOSE
fprintf(stderr, "DebugClient::startAuthentication: DPB filled\n");
#endif
return AUTH_SUCCESS;
str = "HAND";
}
return AUTH_MORE_DATA;
else
{
unsigned int length;
const unsigned char* v = cb->getData(&length);
str.assign(v, length);
#ifdef AUTH_VERBOSE
fprintf(stderr, "DebugClient::authenticate2: from srv=%s\n", str.c_str());
#endif
const char* env = getenv("ISC_DEBUG_AUTH");
if (env && env[0] && str.length() > 0 && str[str.length() - 1] == '_')
str = env;
else
str += "SHAKE";
}
#ifdef AUTH_VERBOSE
fprintf(stderr, "DebugClient::authenticate: sending %s\n", str.c_str());
#endif
cb->putData(status, str.length(), str.c_str());
if (! status->isSuccess())
{
return AUTH_FAILED;
}
#ifdef AUTH_VERBOSE
fprintf(stderr, "DebugClient::authenticate: data filled\n");
#endif
return AUTH_SUCCESS;
}
catch (const Firebird::Exception& ex)
{
ex.stuffException(status);
}
***/
return AUTH_FAILED;
}
/***
int FB_CARG DebugClient::contAuthentication(Firebird::IStatus* status, const unsigned char* data, unsigned int size)
{
try
{
#ifdef AUTH_VERBOSE
fprintf(stderr, "DebugClient::contAuthentication: %.*s\n", size, data);
#endif
str.assign(data, size);
const char* env = getenv("ISC_DEBUG_AUTH");
if (env && env[0] && str.length() > 0 && str[str.length() - 1] == '_')
str = env;
else
str += "SHAKE";
return AUTH_CONTINUE;
}
catch (const Firebird::Exception& ex)
{
ex.stuffException(status);
return AUTH_FAILED;
}
}
***/
int FB_CARG DebugClient::release()
{
if (--refCounter == 0)

View File

@ -64,7 +64,7 @@ int SrpClient::authenticate(IStatus* status, IClientBlock* cb)
if (!client)
{
HANDSHAKE_DEBUG(fprintf(stderr, "Cln SRP1: %s %s\n", cb->getLogin(), cb->getPassword()));
HANDSHAKE_DEBUG(fprintf(stderr, "Client: SRP1: login=%s password=%s\n", cb->getLogin(), cb->getPassword()));
if (!(cb->getLogin() && cb->getPassword()))
{
return AUTH_CONTINUE;
@ -77,7 +77,7 @@ int SrpClient::authenticate(IStatus* status, IClientBlock* cb)
return status->isSuccess() ? AUTH_MORE_DATA : AUTH_FAILED;
}
HANDSHAKE_DEBUG(fprintf(stderr, "Cln SRP2\n"));
HANDSHAKE_DEBUG(fprintf(stderr, "Client: SRP2\n"));
unsigned int length;
const unsigned char* saltAndKey = cb->getData(&length);
if (length > (RemotePassword::SRP_SALT_SIZE + RemotePassword::SRP_KEY_SIZE + 2) * 2)

View File

@ -102,7 +102,8 @@ int SrpServer::authenticate(IStatus* status, IServerBlock* sb, IWriter* writerIn
if (!clientPubKey.hasData())
{
return AUTH_CONTINUE;
HANDSHAKE_DEBUG(fprintf(stderr, "Srv SRP: empty pubkey AUTH_MORE_DATA\n"));
return AUTH_MORE_DATA;
}
// read salt and verifier from database

View File

@ -67,8 +67,11 @@ public:
{
Firebird::UCharBuffer bytes;
data.getBytes(bytes);
unsigned int n = (bytes[0] == 0) ? 1u : 0;
process(bytes.getCount() - n, bytes.begin() + n);
if (bytes.getCount())
{
unsigned int n = (bytes[0] == 0) ? 1u : 0;
process(bytes.getCount() - n, bytes.begin() + n);
}
}
};

View File

@ -37,6 +37,7 @@ namespace Auth {
int SecurityDatabaseClient::authenticate(Firebird::IStatus* status, IClientBlock* cb)
{
// fprintf(stderr, "Clnt: Legacy: lgn=%s pswd=%s\n", cb->getLogin(), cb->getPassword());
if (!(cb->getLogin() && cb->getPassword()))
{
return AUTH_CONTINUE;

View File

@ -5296,17 +5296,21 @@ static void add_working_directory(ClumpletWriter& dpb, const PathName& node_name
}
static void authenticateStep0(ClntAuthBlock& wire)
static void authenticateStep0(ClntAuthBlock& cBlock)
{
for (LocalStatus s; wire.plugins.hasData(); wire.plugins.next())
for (LocalStatus s; cBlock.plugins.hasData(); cBlock.plugins.next())
{
switch(wire.plugins.plugin()->authenticate(&s, &wire))
HANDSHAKE_DEBUG(fprintf(stderr, "Cli: authenticateStep0(%s)\n", cBlock.plugins.name()));
switch(cBlock.plugins.plugin()->authenticate(&s, &cBlock))
{
case Auth::AUTH_SUCCESS:
case Auth::AUTH_MORE_DATA:
return;
case Auth::AUTH_FAILED:
gds__log_status("Authentication, client plugin:", s.get());
if (s.get()[1] != FB_SUCCESS)
{
gds__log_status("Authentication, client plugin:", s.get());
}
(Arg::Gds(isc_login)
#ifdef DEV_BUILD
<< Arg::StatusVector(s.get())
@ -6169,6 +6173,7 @@ static void authFillParametersBlock(ClntAuthBlock& cBlock, ClumpletWriter& dpb,
{
// OK to use plugin
cBlock.resetDataFromPlugin();
HANDSHAKE_DEBUG(fprintf(stderr, "Cli: authFillParametersBlock(%s)\n", cBlock.plugins.name()));
int authRc = cBlock.plugins.plugin()->authenticate(&s, &cBlock);
switch (authRc)
@ -6179,6 +6184,10 @@ static void authFillParametersBlock(ClntAuthBlock& cBlock, ClumpletWriter& dpb,
cleanDpb(dpb, tags);
cBlock.extractDataFromPluginTo(dpb, tags, port->port_protocol);
return;
case Auth::AUTH_CONTINUE:
continue;
case Auth::AUTH_FAILED:
HANDSHAKE_DEBUG(fprintf(stderr, "FPB: plugin %s FAILED\n", cBlock.plugins.name()));
(Arg::Gds(isc_login) << Arg::StatusVector(s.get())).raise();
@ -6305,6 +6314,7 @@ static void authReceiveResponse(ClntAuthBlock& cBlock, rem_port* port, Rdb* rdb,
}
cBlock.storeDataForPlugin(d->cstr_length, d->cstr_address);
HANDSHAKE_DEBUG(fprintf(stderr, "Cli: receiveResponse: authenticate(%s)\n", cBlock.plugins.name()));
if (cBlock.plugins.plugin()->authenticate(&s, &cBlock) == Auth::AUTH_FAILED)
{
break;
@ -7455,7 +7465,8 @@ static void cleanDpb(Firebird::ClumpletWriter& dpb, const ParametersSet* tags)
ClntAuthBlock::ClntAuthBlock(const Firebird::PathName* fileName, Firebird::ClumpletReader* dpb,
const ParametersSet* tags)
: pluginList(getPool()), userName(getPool()), password(getPool()),
: pluginList(getPool()), serverPluginList(getPool()),
userName(getPool()), password(getPool()),
dataForPlugin(getPool()), dataFromPlugin(getPool()),
cryptKeys(getPool()), dpbConfig(getPool()), hasCryptKey(false),
plugins(PluginType::AuthClient, FB_AUTH_CLIENT_VERSION, upInfo),

View File

@ -621,6 +621,7 @@ rem_port* INET_analyze(ClntAuthBlock* cBlock,
packet->p_acpd.p_acpt_data.cstr_address);
cBlock->authComplete = packet->p_acpd.p_acpt_authenticated;
port->addServerKeys(&packet->p_acpd.p_acpt_keys);
cBlock->resetClnt(&file_name, &packet->p_acpd.p_acpt_keys);
}
break;

View File

@ -208,6 +208,8 @@ rem_port* WNET_analyze(ClntAuthBlock* cBlock,
cBlock->storeDataForPlugin(packet->p_acpd.p_acpt_data.cstr_length,
packet->p_acpd.p_acpt_data.cstr_address);
cBlock->authComplete = packet->p_acpd.p_acpt_authenticated;
port->addServerKeys(&packet->p_acpd.p_acpt_keys);
cBlock->resetClnt(&file_name, &packet->p_acpd.p_acpt_keys);
}
break;

View File

@ -293,6 +293,7 @@ rem_port* XNET_analyze(ClntAuthBlock* cBlock,
cBlock->storeDataForPlugin(packet->p_acpd.p_acpt_data.cstr_length,
packet->p_acpd.p_acpt_data.cstr_address);
cBlock->authComplete = packet->p_acpd.p_acpt_authenticated;
cBlock->resetClnt(&file_name, &packet->p_acpd.p_acpt_keys);
}
break;

View File

@ -1021,6 +1021,7 @@ void ClntAuthBlock::extractDataFromPluginTo(Firebird::ClumpletWriter& user_id)
// Add user login name
if (userName.hasData())
{
HANDSHAKE_DEBUG(fprintf(stderr, "extractDataFromPluginTo: userName=%s\n", userName.c_str()));
user_id.insertString(CNCT_login, userName);
}
@ -1028,6 +1029,7 @@ void ClntAuthBlock::extractDataFromPluginTo(Firebird::ClumpletWriter& user_id)
Firebird::PathName pluginName = getPluginName();
if (pluginName.hasData())
{
HANDSHAKE_DEBUG(fprintf(stderr, "extractDataFromPluginTo: pluginName=%s\n", pluginName.c_str()));
user_id.insertPath(CNCT_plugin_name, pluginName);
}
@ -1063,15 +1065,69 @@ void ClntAuthBlock::extractDataFromPluginTo(Firebird::ClumpletWriter& user_id)
}
}
void ClntAuthBlock::resetClnt(const Firebird::PathName* fileName)
void ClntAuthBlock::resetClnt(const Firebird::PathName* fileName, const CSTRING* listStr)
{
if (listStr)
{
if (dataForPlugin.hasData())
{
// We should not change plugins iterator now
return;
}
Firebird::ClumpletReader srvList(Firebird::ClumpletReader::UnTagged,
listStr->cstr_address, listStr->cstr_length);
if (srvList.find(TAG_KNOWN_PLUGINS))
{
srvList.getPath(serverPluginList);
}
}
dataForPlugin.clear();
dataFromPlugin.clear();
authComplete = false;
firstTime = true;
config = REMOTE_get_config(fileName, &dpbConfig);
pluginList = config->getPlugins(Firebird::PluginType::AuthClient);
plugins.set(pluginList.c_str());
Firebird::PathName final;
if (serverPluginList.hasData())
{
Remote::ParsedList onClient, fromServer, merged;
REMOTE_parseList(onClient, pluginList);
REMOTE_parseList(fromServer, serverPluginList);
for (unsigned c = 0; c < onClient.getCount(); ++c)
{
// do not expect too long lists, therefore use double loop
for (unsigned s = 0; s < fromServer.getCount(); ++s)
{
if (onClient[c] == fromServer[s])
{
merged.push(onClient[c]);
}
}
}
if (merged.getCount() == 0)
{
HANDSHAKE_DEBUG(fprintf(stderr, "No matching plugins on client\n"));
(Firebird::Arg::Gds(isc_login)
#ifdef DEV_BUILD
<< Firebird::Arg::Gds(isc_random) << "No matching plugins on client"
#endif
).raise();
}
REMOTE_makeList(final, merged);
}
else
{
final = pluginList;
}
plugins.set(final.c_str());
}
Firebird::RefPtr<Config>* ClntAuthBlock::getConfig()
@ -1243,6 +1299,11 @@ void rem_port::addServerKeys(CSTRING* passedStr)
for (newKeys.rewind(); !newKeys.isEof(); newKeys.moveNext())
{
if (newKeys.getClumpTag() == TAG_KNOWN_PLUGINS)
{
continue;
}
KnownServerKey key;
fb_assert(newKeys.getClumpTag() == TAG_KEY_TYPE);
newKeys.getPath(key.type);

View File

@ -635,6 +635,7 @@ class ClntAuthBlock : public Firebird::StdPlugin<Auth::IClientBlock, FB_AUTH_CLI
{
private:
Firebird::PathName pluginList; // To be passed to server
Firebird::PathName serverPluginList; // Received from server
Firebird::string userName, password; // Used by plugin, taken from DPB
// These two are legacy encrypted password, trusted auth data and so on - what plugin needs
Firebird::UCharBuffer dataForPlugin, dataFromPlugin;
@ -665,7 +666,7 @@ public:
void extractDataFromPluginTo(P_AUTH_CONT* to);
void loadClnt(Firebird::ClumpletWriter& dpb, const ParametersSet*);
void extractDataFromPluginTo(Firebird::ClumpletWriter& user_id);
void resetClnt(const Firebird::PathName* fileName);
void resetClnt(const Firebird::PathName* fileName, const CSTRING* listStr = NULL);
bool checkPluginName(Firebird::PathName& nameToCheck);
void saveServiceDataTo(rem_port*);
void loadServiceDataFrom(rem_port*);
@ -737,7 +738,7 @@ public:
void createPluginsItr();
void setDataForPlugin(const p_auth_continue* data);
void reset();
bool extractNewKeys(CSTRING* to);
bool extractNewKeys(CSTRING* to, bool flagPlugList = false);
// Auth::IServerBlock implementation
int FB_CARG release();
@ -771,9 +772,10 @@ private:
KnownServerKey& operator=(const KnownServerKey&);
};
// Tags for server keys clumplet, passed from server to client
// Tags for clumplets, passed from server to client
const UCHAR TAG_KEY_TYPE = 0;
const UCHAR TAG_KEY_PLUGINS = 1;
const UCHAR TAG_KNOWN_PLUGINS = 2;
// port_flags
const USHORT PORT_symmetric = 0x0001; // Server/client architectures are symmetic

View File

@ -427,7 +427,7 @@ public:
case Auth::AUTH_FAILED:
HANDSHAKE_DEBUG(fprintf(stderr, "No luck today...\n"));
isc_print_status(st.get());
HANDSHAKE_DEBUG(isc_print_status(st.get()));
authServer = NULL;
working = false;
break;
@ -1542,6 +1542,7 @@ static bool accept_connection(rem_port* port, P_CNCT* connect, PACKET* send)
// We are going to try authentication handshake
LocalStatus status;
bool returnData = false;
//bool returnPlugList = false;
if (accepted && version >= PROTOCOL_VERSION13)
{
HANDSHAKE_DEBUG(fprintf(stderr, "accept connection creates port_srv_auth_block\n"));
@ -1587,10 +1588,13 @@ static bool accept_connection(rem_port* port, P_CNCT* connect, PACKET* send)
case Auth::AUTH_CONTINUE:
// try next plugin
continue;
// First try failed - extractNewKeys will send to client list of known plugins
//returnPlugList = true;
//break;
case Auth::AUTH_MORE_DATA:
port->port_srv_auth_block->extractDataFromPluginTo(&send->p_acpd.p_acpt_data);
port->port_srv_auth_block->extractPluginName(&send->p_acpd.p_acpt_plugin);
port->port_srv_auth_block->extractDataFromPluginTo(&send->p_acpd.p_acpt_data);
returnData = true;
break;
@ -1610,10 +1614,6 @@ static bool accept_connection(rem_port* port, P_CNCT* connect, PACKET* send)
}
break;
}
if (!plugins->hasData())
{
accepted = false;
}
}
}
}
@ -1628,7 +1628,9 @@ static bool accept_connection(rem_port* port, P_CNCT* connect, PACKET* send)
return false;
}
if (version >= PROTOCOL_VERSION13 && port->port_srv_auth_block->extractNewKeys(&send->p_acpd.p_acpt_keys))
// extractNewKeys() will also send to client list of known plugins
if (version >= PROTOCOL_VERSION13 &&
port->port_srv_auth_block->extractNewKeys(&send->p_acpd.p_acpt_keys, returnData))
{
returnData = true;
}
@ -6359,6 +6361,10 @@ const char* SrvAuthBlock::getLogin()
const unsigned char* SrvAuthBlock::getData(unsigned int* length)
{
*length = (ULONG) dataForPlugin.getCount();
if (*length && pluginName != plugins->name())
{
*length = 0;
}
return *length ? dataForPlugin.begin() : NULL;
}
@ -6483,7 +6489,7 @@ void SrvAuthBlock::reset()
plugins = NULL;
}
bool SrvAuthBlock::extractNewKeys(CSTRING* to)
bool SrvAuthBlock::extractNewKeys(CSTRING* to, bool flagPluginsList)
{
lastExtractedKeys.reset();
for (unsigned n = 0; n < newKeys.getCount(); ++n)
@ -6496,6 +6502,12 @@ bool SrvAuthBlock::extractNewKeys(CSTRING* to)
lastExtractedKeys.insertPath(TAG_KEY_PLUGINS, plugins);
}
}
if (flagPluginsList && dataFromPlugin.getCount() == 0)
{
lastExtractedKeys.insertPath(TAG_KNOWN_PLUGINS, pluginList);
}
to->cstr_length = (ULONG) lastExtractedKeys.getBufferLength();
to->cstr_address = const_cast<UCHAR*>(lastExtractedKeys.getBuffer());
to->cstr_allocated = 0;