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

Trusted authentication for windows

This commit is contained in:
alexpeshkoff 2006-12-08 18:38:15 +00:00
parent 83a2065a3c
commit 1a4652f01a
44 changed files with 1117 additions and 254 deletions

View File

@ -47,7 +47,7 @@
<Tool
Name="VCLinkerTool"
AdditionalOptions="/MACHINE:I386"
AdditionalDependencies="comctl32.lib ws2_32.lib mpr.lib version.lib icuuc.lib icuin.lib"
AdditionalDependencies="comctl32.lib ws2_32.lib mpr.lib version.lib secur32.lib icuuc.lib icuin.lib"
OutputFile="..\..\..\temp\release\firebird\bin\fb_inet_server.exe"
LinkIncremental="1"
SuppressStartupBanner="TRUE"
@ -115,7 +115,7 @@
<Tool
Name="VCLinkerTool"
AdditionalOptions="/MACHINE:I386"
AdditionalDependencies="comctl32.lib ws2_32.lib mpr.lib version.lib icuuc.lib icuin.lib"
AdditionalDependencies="comctl32.lib ws2_32.lib mpr.lib version.lib secur32.lib icuuc.lib icuin.lib"
OutputFile="..\..\..\temp\debug\firebird\bin\fb_inet_server.exe"
LinkIncremental="1"
SuppressStartupBanner="TRUE"

View File

@ -42,7 +42,7 @@
<Tool
Name="VCLinkerTool"
AdditionalOptions="/MACHINE:I386"
AdditionalDependencies="comctl32.lib ws2_32.lib mpr.lib version.lib"
AdditionalDependencies="comctl32.lib ws2_32.lib mpr.lib version.lib secur32.lib"
OutputFile="..\..\..\temp\debug\firebird\bin\fbclient.dll"
LinkIncremental="1"
SuppressStartupBanner="TRUE"
@ -115,7 +115,7 @@
<Tool
Name="VCLinkerTool"
AdditionalOptions="/MACHINE:I386"
AdditionalDependencies="comctl32.lib ws2_32.lib mpr.lib version.lib"
AdditionalDependencies="comctl32.lib ws2_32.lib mpr.lib version.lib secur32.Lib"
OutputFile="..\..\..\temp\release\firebird\bin\fbclient.dll"
LinkIncremental="1"
SuppressStartupBanner="TRUE"
@ -371,6 +371,15 @@
</FileConfiguration>
</File>
</Filter>
<Filter
Name="AuthSspi">
<File
RelativePath="..\..\..\src\auth\trusted\AuthSspi.cpp">
</File>
<File
RelativePath="..\..\..\src\auth\trusted\AuthSspi.h">
</File>
</Filter>
<File
RelativePath="..\defs\fbclient.def">
</File>

View File

@ -42,7 +42,7 @@
<Tool
Name="VCLinkerTool"
AdditionalOptions="/MACHINE:I386"
AdditionalDependencies="comctl32.lib ws2_32.lib mpr.lib version.lib icuuc.lib icuin.lib"
AdditionalDependencies="comctl32.lib ws2_32.lib mpr.lib version.lib secur32.lib icuuc.lib icuin.lib"
OutputFile="..\..\..\temp\debug\firebird\bin\fbembed.dll"
LinkIncremental="1"
SuppressStartupBanner="TRUE"
@ -116,7 +116,7 @@
<Tool
Name="VCLinkerTool"
AdditionalOptions="/MACHINE:I386"
AdditionalDependencies="mpr.lib ws2_32.lib version.lib icuuc.lib icuin.lib"
AdditionalDependencies="mpr.lib ws2_32.lib version.lib secur32.lib icuuc.lib icuin.lib"
OutputFile="..\..\..\temp\release\firebird/bin/fbembed.dll"
LinkIncremental="1"
SuppressStartupBanner="TRUE"
@ -362,6 +362,15 @@
</FileConfiguration>
</File>
</Filter>
<Filter
Name="AuthSspi">
<File
RelativePath="..\..\..\src\auth\trusted\AuthSspi.cpp">
</File>
<File
RelativePath="..\..\..\src\auth\trusted\AuthSspi.h">
</File>
</Filter>
<File
RelativePath="..\defs\fbclient.def">
</File>

View File

@ -47,7 +47,7 @@
<Tool
Name="VCLinkerTool"
AdditionalOptions="/MACHINE:I386"
AdditionalDependencies="comctl32.lib ws2_32.lib mpr.lib version.lib icuuc.lib icuin.lib"
AdditionalDependencies="comctl32.lib ws2_32.lib mpr.lib secur32.lib version.lib icuuc.lib icuin.lib"
OutputFile="..\..\..\temp\release\firebird\bin\fbserver.exe"
LinkIncremental="1"
SuppressStartupBanner="TRUE"
@ -115,7 +115,7 @@
<Tool
Name="VCLinkerTool"
AdditionalOptions="/MACHINE:I386"
AdditionalDependencies="comctl32.lib ws2_32.lib mpr.lib version.lib icuuc.lib icuin.lib"
AdditionalDependencies="comctl32.lib ws2_32.lib mpr.lib secur32.lib version.lib icuuc.lib icuin.lib"
OutputFile="..\..\..\temp\debug\firebird\bin\fbserver.exe"
LinkIncremental="1"
SuppressStartupBanner="TRUE"

View File

@ -220,6 +220,16 @@
RelativePath="..\..\..\src\remote\xnet_proto.h">
</File>
</Filter>
<Filter
Name="AuthSspi"
Filter="">
<File
RelativePath="..\..\..\src\auth\trusted\AuthSspi.cpp">
</File>
<File
RelativePath="..\..\..\src\auth\trusted\AuthSspi.h">
</File>
</Filter>
</Files>
<Globals>
</Globals>

View File

@ -217,6 +217,15 @@
RelativePath="..\..\..\src\remote\xnet_proto.h">
</File>
</Filter>
<Filter
Name="AuthSspi">
<File
RelativePath="..\..\..\src\auth\trusted\AuthSspi.cpp">
</File>
<File
RelativePath="..\..\..\src\auth\trusted\AuthSspi.h">
</File>
</Filter>
</Files>
<Globals>
</Globals>

View File

@ -253,6 +253,9 @@ int common_main(int argc,
tdgbl->ALICE_data.ua_user = NULL;
tdgbl->ALICE_data.ua_password = NULL;
#ifdef TRUSTED_SERVICES
tdgbl->ALICE_data.ua_tr_user = NULL;
#endif
// Start by parsing switches
@ -318,6 +321,15 @@ int common_main(int argc,
if (table->in_sw_value == sw_z) {
ALICE_print(3, GDS_VERSION, 0, 0, 0, 0); // msg 3: gfix version %s
}
#ifdef TRUSTED_SERVICES
if (strcmp(table->in_sw_name, "trusted") == 0) {
if (--argc <= 0) {
ALICE_error(13); // msg 13: user name required
}
tdgbl->ALICE_data.ua_tr_user = (UCHAR*)(*argv++);
continue;
}
#endif
if ((table->in_sw_incompatibilities & switches) ||
(table->in_sw_requires && !(table->in_sw_requires & switches)))
{
@ -544,7 +556,10 @@ int common_main(int argc,
#else
ALICE_print(21, 0, 0, 0, 0, 0); // msg 21: plausible options are:\n
for (table = alice_in_sw_table; table->in_sw_msg; table++)
{
if (table->in_sw_msg)
ALICE_print(table->in_sw_msg, 0, 0, 0, 0, 0);
}
ALICE_print(22, 0, 0, 0, 0, 0); // msg 22: \n qualifiers show the major option in parenthesis
#endif
exit_local(FINI_ERROR, tdgbl);

View File

@ -60,6 +60,9 @@ struct user_action
ULONG ua_switches;
const UCHAR* ua_user;
const UCHAR* ua_password;
#ifdef TRUSTED_SERVICES
UCHAR* ua_tr_user;
#endif
bool ua_use;
bool ua_force;
bool ua_read_only;

View File

@ -106,7 +106,8 @@ enum alice_switches
IN_SW_ALICE_HIDDEN_FORCE = 40,
IN_SW_ALICE_HIDDEN_TRAN = 41,
IN_SW_ALICE_HIDDEN_ATTACH = 42,
IN_SW_ALICE_SET_DB_SQL_DIALECT = 43
IN_SW_ALICE_SET_DB_SQL_DIALECT = 43,
IN_SW_ALICE_TRUSTED_USER = 44
};
static const char* ALICE_SW_ASYNC = "async";
@ -214,6 +215,10 @@ static in_sw_tab_t alice_in_sw_table[] =
// msg 48: \t-tran\t\tshutdown transaction startup
{IN_SW_ALICE_USE, 0, "use", sw_use,
0, ~(sw_use | sw_user | sw_password), FALSE, 49, 0, NULL},
#ifdef TRUSTED_SERVICES
{IN_SW_ALICE_TRUSTED_USER, 0, "trusted", 0, 0, 0,
FALSE, 0, 0, NULL},
#endif
// msg 49: \t-use\t\tuse full or reserve space for versions
{IN_SW_ALICE_USER, 0, "user", sw_user,
0, 0, FALSE, 50, 0, NULL},

View File

@ -322,6 +322,13 @@ static void buildDpb(Firebird::ClumpletWriter& dpb, const ULONG switches)
tdgbl->ALICE_data.ua_password,
strlen(reinterpret_cast<const char*>(tdgbl->ALICE_data.ua_password)));
}
#ifdef TRUSTED_SERVICES
if (tdgbl->ALICE_data.ua_tr_user) {
dpb.insertBytes(isc_dpb_trusted_auth,
tdgbl->ALICE_data.ua_tr_user,
strlen(reinterpret_cast<const char*>(tdgbl->ALICE_data.ua_tr_user)));
}
#endif
}

View File

@ -202,6 +202,13 @@ bool TDR_attach_database(ISC_STATUS* status_vector,
tdgbl->ALICE_data.ua_password,
strlen(reinterpret_cast<const char*>(tdgbl->ALICE_data.ua_password)));
}
#ifdef TRUSTED_SERVICES
if (tdgbl->ALICE_data.ua_tr_user) {
dpb.insertBytes(isc_dpb_trusted_auth,
tdgbl->ALICE_data.ua_tr_user,
strlen(reinterpret_cast<const char*>(tdgbl->ALICE_data.ua_tr_user)));
}
#endif
trans->tdr_db_handle = 0;

View File

@ -0,0 +1,218 @@
#include "AuthSspi.h"
#ifdef TRUSTED_AUTH
#include <../common/classes/ClumpletReader.h>
AuthSspi::AuthSspi()
: hasContext(false), ctName(*getDefaultMemoryPool())
{
TimeStamp timeOut;
hasCredentials = AcquireCredentialsHandle(0, "NTLM", SECPKG_CRED_BOTH, 0, 0, 0, 0,
&secHndl, &timeOut) == SEC_E_OK;
}
AuthSspi::~AuthSspi()
{
if (hasContext)
{
DeleteSecurityContext(&ctxtHndl);
}
if (hasCredentials)
{
FreeCredentialsHandle(&secHndl);
}
}
namespace
{
void makeDesc(SecBufferDesc& d, SecBuffer& b, size_t len, void* p)
{
b.BufferType = SECBUFFER_TOKEN;
b.cbBuffer = len;
b.pvBuffer = len ? p : 0;
d.ulVersion = SECBUFFER_VERSION;
d.cBuffers = 1;
d.pBuffers = &b;
}
bool checkAdminPrivilege(PCtxtHandle phContext)
{
// Query access token from security context
SecPkgContext_AccessToken spc;
spc.AccessToken = 0;
if (QueryContextAttributes(phContext, SECPKG_ATTR_ACCESS_TOKEN, &spc) != SEC_E_OK)
{
return false;
}
// Query required buffer size
DWORD token_len = 0;
GetTokenInformation(spc.AccessToken,
TokenGroups, 0, 0, &token_len);
// Query actual group information
Firebird::Array<char> buffer;
TOKEN_GROUPS *ptg = (TOKEN_GROUPS *)buffer.getBuffer(token_len);
bool ok = GetTokenInformation(spc.AccessToken,
TokenGroups, ptg, token_len, &token_len);
FreeContextBuffer(spc.AccessToken);
if (! ok)
{
return false;
}
// Create a System Identifier for the Admin group.
SID_IDENTIFIER_AUTHORITY system_sid_authority = {SECURITY_NT_AUTHORITY};
PSID admin_sid;
if (!AllocateAndInitializeSid(&system_sid_authority, 2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0, &admin_sid))
{
return false;
}
// Finally we'll iterate through the list of groups for this access
// token looking for a match against the SID we created above.
for (DWORD i = 0; i < ptg->GroupCount; i++)
{
if (EqualSid(ptg->Groups[i].Sid, admin_sid))
{
FreeSid(admin_sid);
return true;
}
}
FreeSid(admin_sid);
return false;
}
}
bool AuthSspi::request(AuthSspi::DataHolder& data)
{
if (! hasCredentials)
{
data.clear();
return false;
}
TimeStamp timeOut;
char s[BUFSIZE];
SecBuffer outputBuffer, inputBuffer;
SecBufferDesc outputDesc, inputDesc;
makeDesc(outputDesc, outputBuffer, sizeof(s), s);
makeDesc(inputDesc, inputBuffer, data.getCount(), data.begin());
ULONG fContextAttr = 0;
SECURITY_STATUS x = InitializeSecurityContext(
&secHndl, hasContext ? &ctxtHndl : 0, 0, 0, 0, SECURITY_NATIVE_DREP,
hasContext ? &inputDesc : 0, 0, &ctxtHndl, &outputDesc, &fContextAttr, &timeOut);
switch (x)
{
case SEC_E_OK:
DeleteSecurityContext(&ctxtHndl);
hasContext = false;
break;
case SEC_I_CONTINUE_NEEDED:
hasContext = true;
break;
default:
if (hasContext)
{
DeleteSecurityContext(&ctxtHndl);
}
hasContext = false;
data.clear();
return false;
}
if (outputBuffer.cbBuffer)
{
memcpy(data.getBuffer(outputBuffer.cbBuffer),
outputBuffer.pvBuffer, outputBuffer.cbBuffer);
}
else
{
data.clear();
}
return true;
}
bool AuthSspi::accept(AuthSspi::DataHolder& data)
{
if (! hasCredentials)
{
data.clear();
return false;
}
TimeStamp timeOut;
char s[BUFSIZE];
SecBuffer outputBuffer, inputBuffer;
SecBufferDesc outputDesc, inputDesc;
makeDesc(outputDesc, outputBuffer, sizeof(s), s);
makeDesc(inputDesc, inputBuffer, data.getCount(), data.begin());
ULONG fContextAttr = 0;
SecPkgContext_Names name;
SECURITY_STATUS x = AcceptSecurityContext(
&secHndl, hasContext ? &ctxtHndl : 0, &inputDesc, 0,
SECURITY_NATIVE_DREP, &ctxtHndl, &outputDesc,
&fContextAttr, &timeOut);
switch(x)
{
case SEC_E_OK:
if (checkAdminPrivilege(&ctxtHndl))
{
ctName = "SYSDBA";
}
else if (QueryContextAttributes(&ctxtHndl, SECPKG_ATTR_NAMES, &name) == SEC_E_OK)
{
ctName = name.sUserName;
ctName.upper();
FreeContextBuffer(name.sUserName);
}
DeleteSecurityContext(&ctxtHndl);
hasContext = false;
break;
case SEC_I_CONTINUE_NEEDED:
hasContext = true;
break;
default:
if (hasContext)
{
DeleteSecurityContext(&ctxtHndl);
}
hasContext = false;
data.clear();
return false;
}
if (outputBuffer.cbBuffer)
{
memcpy(data.getBuffer(outputBuffer.cbBuffer),
outputBuffer.pvBuffer, outputBuffer.cbBuffer);
}
else
{
data.clear();
}
return true;
}
bool AuthSspi::getLogin(Firebird::string& login)
{
if (ctName.hasData())
{
login = ctName;
ctName.erase();
return true;
}
return false;
}
#endif //TRUSTED_AUTH

View File

@ -0,0 +1,44 @@
#ifndef AUTH_SPPI_H
#define AUTH_SPPI_H
#include <firebird.h>
#ifdef TRUSTED_AUTH
#include <../common/classes/fb_string.h>
#include <../common/classes/array.h>
#include <../jrd/ibase.h>
#define SECURITY_WIN32
#include <windows.h>
#include <Security.h>
#include <stdio.h>
class AuthSspi
{
private:
enum {BUFSIZE = 4096};
SecHandle secHndl;
bool hasCredentials;
CtxtHandle ctxtHndl;
bool hasContext;
Firebird::string ctName;
public:
typedef Firebird::Array<unsigned char> DataHolder;
AuthSspi();
~AuthSspi();
bool isActive()
{
return hasContext;
}
bool request(DataHolder& data);
bool accept(DataHolder& data);
bool getLogin(Firebird::string& login);
};
#endif //TRUSTED_AUTH
#endif //AUTH_SPPI_H

View File

@ -830,6 +830,14 @@ int common_main(int argc,
// user name parameter missing
tdgbl->gbl_sw_user = *argv++;
}
#ifdef TRUSTED_SERVICES
else if (in_sw_tab->in_sw == IN_SW_BURP_TRUSTED_USER) {
if (argv >= end)
BURP_error(188, true, 0, 0, 0, 0, 0);
// trusted user name parameter missing
tdgbl->gbl_sw_tr_user = *argv++;
}
#endif
else if (in_sw_tab->in_sw == IN_SW_BURP_ROLE) {
if (argv >= end)
BURP_error(253, true, 0, 0, 0, 0, 0);
@ -1049,6 +1057,13 @@ int common_main(int argc,
strlen(tdgbl->gbl_sw_user));
break;
#ifdef TRUSTED_SERVICES
case (IN_SW_BURP_TRUSTED_USER):
dpb.insertString(isc_dpb_trusted_auth,
tdgbl->gbl_sw_tr_user,
strlen(tdgbl->gbl_sw_tr_user));
break;
#endif
case (IN_SW_BURP_V):
tdgbl->gbl_sw_verbose = true;
break;

View File

@ -799,6 +799,8 @@ public:
// this is VERY dirty hack to keep current behaviour
memset (&gbl_database_file_name, 0,
&veryEnd - reinterpret_cast<char*>(&gbl_database_file_name));
// normal code follows
exit_code = FINI_ERROR; // prevent FINI_OK in case of unknown error thrown
// would be set to FINI_OK (==0) in exit_local
}
@ -829,6 +831,9 @@ public:
const SCHAR* gbl_sw_sql_role;
const SCHAR* gbl_sw_user;
const SCHAR* gbl_sw_password;
#ifdef TRUSTED_SERVICES
const SCHAR* gbl_sw_tr_user;
#endif
SLONG gbl_sw_skip_count;
SLONG gbl_sw_page_buffers;
burp_fil* gbl_sw_files;

View File

@ -81,6 +81,9 @@ const int IN_SW_BURP_HIDDEN_RDWRITE = 37;
const int IN_SW_BURP_RECREATE = 38; // recreate database
const int IN_SW_BURP_NOD = 39; // do not run database triggers
#ifdef TRUSTED_SERVICES
const int IN_SW_BURP_TRUSTED_USER = 40; // trusted user name to use on attach
#endif
/**************************************************************************/
// used 0BCDEFGILMNOPRSTUVYZ available AHJQWX
@ -153,6 +156,9 @@ static in_sw_tab_t burp_in_sw_table [] =
// msg 276: %sUSE_(ALL_SPACE) do not reserve space for record versions
{IN_SW_BURP_USER, 0, "USER", 0, 0, 0, FALSE, 191, 0, NULL},
// msg 191: %sUSER InterBase user name
#ifdef TRUSTED_SERVICES
{IN_SW_BURP_TRUSTED_USER, 0, "TRUSTED", 0, 0, 0, FALSE, 0, 0, NULL},
#endif
{IN_SW_BURP_V, isc_spb_verbose, "VERBOSE", 0, 0, 0, FALSE, 0, 0, NULL},
{IN_SW_BURP_V, 0, "VERIFY", 0, 0, 0, FALSE, 113, 0, NULL},
// msg 113: %sVERIFY report each action taken

View File

@ -103,6 +103,7 @@
#define isc_dpb_address_path 70
#define isc_dpb_pid 71
#define isc_dpb_no_db_triggers 72
#define isc_dpb_trusted_auth 73
/**************************************************/
/* clumplet tags used inside isc_dpb_address_path */
@ -251,6 +252,7 @@
#define isc_spb_options 108
#define isc_spb_address_path 109
#define isc_spb_pid 110
#define isc_spb_trusted_auth 111
#define isc_spb_connect_timeout isc_dpb_connect_timeout

View File

@ -127,4 +127,11 @@ using namespace NAMESPACE;
#define SERVICE_THREAD
#endif
#if defined(WIN_NT)
#define TRUSTED_AUTH
#if defined(SERVICE_THREAD)
#define TRUSTED_SERVICES
#endif
#endif
#endif /* INCLUDE_Firebird_H */

View File

@ -166,6 +166,9 @@ enum switch_id {
SWITCH_ROLE2,
SWITCH_SQLDIALECT,
SWITCH_TERM,
#ifdef TRUSTED_AUTH
SWITCH_TRUSTED,
#endif
SWITCH_USER,
SWITCH_VERSION,
#ifdef DEV_BUILD
@ -211,6 +214,9 @@ const switch_info switches[] =
{ SWITCH_SQLDIALECT, "sqldialect", 1, SWARG_INTEGER, 137 },
{ SWITCH_SQLDIALECT, "sql_dialect", 1, SWARG_INTEGER, -1 },
{ SWITCH_TERM, "terminator", 1, SWARG_STRING, 138 },
#ifdef TRUSTED_AUTH
{ SWITCH_TRUSTED, "trusted", 2, SWARG_NONE, 155 },
#endif
{ SWITCH_USER, "user", 1, SWARG_STRING, 139 },
{ SWITCH_EXTRACT, "x", 1, SWARG_NONE, 140 },
{ SWITCH_VERSION, "z", 1, SWARG_NONE, 141 }
@ -383,7 +389,10 @@ XSQLDA** global_sqldap;
USHORT global_dialect_spoken = 0;
USHORT requested_SQL_dialect = SQL_DIALECT_V6;
bool connecting_to_pre_v6_server = false;
bool Quiet;
bool Quiet = false;
#ifdef TRUSTED_AUTH
bool Trusted_auth = false;
#endif
bool Version_info = false;
#if defined (WIN95)
bool fAnsiCP;
@ -5178,6 +5187,12 @@ static processing_state newdb(TEXT* dbname,
if (Nodbtriggers)
dpb.insertInt(isc_dpb_no_db_triggers, 1);
#ifdef TRUSTED_AUTH
if (Trusted_auth) {
dpb.insertTag(isc_dpb_trusted_auth);
}
#endif
{ // scope
const TEXT* local_name = isqlGlob.global_Db_name;
@ -5788,6 +5803,12 @@ static processing_state parse_arg(int argc,
Quiet = true;
break;
#ifdef TRUSTED_AUTH
case SWITCH_TRUSTED:
Trusted_auth = true;
break;
#endif
case SWITCH_VERSION:
Version_info = true;
ISQL_msg_get(VERSION, errbuf, FB_VERSION);

View File

@ -72,10 +72,6 @@
static USHORT os_type;
static SECURITY_ATTRIBUTES security_attr;
//static TEXT interbase_directory[MAXPATHLEN];
static bool check_user_privilege();
#endif // WIN_NT
static TEXT user_name[256];
@ -101,6 +97,7 @@ static USHORT ast_count;
static POKE pokes;
static lock_status wake_lock;
#endif /* of ifdef VMS */
#ifdef HAVE_SIGNAL_H
@ -595,148 +592,17 @@ int ISC_get_user(TEXT* name,
{
name[name_len] = 0;
/* NT user name is case insensitive */
// NT user name is case insensitive
for (DWORD i = 0; i < name_len; i++)
{
name[i] = UPPER7(name[i]);
}
/* This check is not internationalized, the security model needs to be
* reengineered, especially on SUPERSERVER where none of these local
* user (in process) assumptions are valid.
if (!strcmp(name, "ADMINISTRATOR"))
{
if (id)
*id = 0;
if (group)
*group = 0;
}
*/
}
}
return check_user_privilege();
}
//____________________________________________________________
//
// Check to see if the user belongs to the administrator group.
//
// This routine was adapted from code in routine RunningAsAdminstrator
// in \mstools\samples\regmpad\regdb.c.
//
static bool check_user_privilege()
{
HANDLE tkhandle;
SID_IDENTIFIER_AUTHORITY system_sid_authority = {SECURITY_NT_AUTHORITY};
// First we must open a handle to the access token for this thread.
if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &tkhandle))
{
if (GetLastError() == ERROR_NO_TOKEN)
{
// If the thread does not have an access token, we'll examine the
// access token associated with the process.
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &tkhandle))
{
CloseHandle(tkhandle);
return false;
}
}
else
{
return false;
}
}
TOKEN_GROUPS* ptg = NULL;
DWORD token_len = 0;
while (true)
{
/* Then we must query the size of the group information associated with
the token. This is guarenteed to fail the first time through
because there is no buffer. */
if (GetTokenInformation(tkhandle,
TokenGroups,
ptg,
token_len,
&token_len))
{
break;
}
/* If there had been a buffer, it's either too small or something
else is wrong. Either way, we can dispose of it. */
if (ptg)
{
gds__free(ptg);
}
/* Here we verify that GetTokenInformation failed for lack of a large
enough buffer. */
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
CloseHandle(tkhandle);
return false;
}
// Allocate a buffer for the group information.
ptg = (TOKEN_GROUPS *) gds__alloc((SLONG) token_len);
if (!ptg)
{
CloseHandle(tkhandle);
return false; /* NOMEM: */
}
// FREE: earlier in this loop, and at procedure return
}
// Create a System Identifier for the Admin group.
PSID admin_sid;
if (!AllocateAndInitializeSid(&system_sid_authority, 2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0, &admin_sid))
{
gds__free(ptg);
CloseHandle(tkhandle);
return false;
}
// Finally we'll iterate through the list of groups for this access
// token looking for a match against the SID we created above.
bool admin_priv = false;
for (DWORD i = 0; i < ptg->GroupCount; i++)
{
if (EqualSid(ptg->Groups[i].Sid, admin_sid))
{
admin_priv = true;
break;
}
}
// Deallocate the SID we created.
FreeSid(admin_sid);
gds__free(ptg);
CloseHandle(tkhandle);
return admin_priv;
}
#endif
#endif //WIN_NT
#ifdef VMS
int ISC_make_desc(const TEXT* string, struct dsc$descriptor* desc, USHORT length)

View File

@ -348,6 +348,9 @@ public:
Firebird::string dpb_set_db_charset;
Firebird::string dpb_network_protocol;
Firebird::string dpb_remote_address;
#ifdef TRUSTED_AUTH
Firebird::string dpb_trusted_login;
#endif
public:
DatabaseOptions()
@ -965,6 +968,9 @@ ISC_STATUS GDS_ATTACH_DATABASE(ISC_STATUS* user_status,
options.dpb_password.nullStr(),
options.dpb_password_enc.nullStr(),
options.dpb_role_name.nullStr(),
#ifdef TRUSTED_AUTH
options.dpb_trusted_login.nullStr(),
#endif
tdbb);
initing_security = false;
@ -1928,6 +1934,9 @@ ISC_STATUS GDS_CREATE_DATABASE(ISC_STATUS* user_status,
options.dpb_password.nullStr(),
options.dpb_password_enc.nullStr(),
options.dpb_role_name.nullStr(),
#ifdef TRUSTED_AUTH
options.dpb_trusted_login.nullStr(),
#endif
tdbb);
initing_security = false;
@ -5474,6 +5483,12 @@ void DatabaseOptions::get(const UCHAR* dpb, USHORT dpb_length)
rdr.getString(dpb_password_enc);
break;
#ifdef TRUSTED_AUTH
case isc_dpb_trusted_auth:
rdr.getString(dpb_trusted_login);
break;
#endif
case isc_dpb_encrypt_key:
#ifdef ISC_DATABASE_ENCRYPTION
rdr.getString(dpb_key);

View File

@ -555,6 +555,9 @@ void SCL_init(bool create,
const TEXT* password,
const TEXT* password_enc,
const TEXT* sql_role,
#ifdef TRUSTED_AUTH
const TEXT* trusted_user,
#endif
thread_db* tdbb)
{
/**************************************
@ -606,6 +609,15 @@ void SCL_init(bool create,
{
if (!JRD_get_thread_security_disabled())
{
#ifdef TRUSTED_AUTH
if (trusted_user)
{
strncpy(name, trusted_user, sizeof name);
name[sizeof name - 1] = 0;
}
else
#endif
{
Attachment* att = tdbb->tdbb_attachment;
Firebird::string remote = att->att_network_protocol +
(att->att_network_protocol.isEmpty() || att->att_remote_address.isEmpty() ? "" : "/") +
@ -613,6 +625,7 @@ void SCL_init(bool create,
SecurityDatabase::verifyUser(name, user_name, password, password_enc,
&id, &group, &node_id, remote);
}
}
else
{
strncpy(name, user_name, sizeof name);

View File

@ -41,8 +41,11 @@ void SCL_check_procedure(const dsc*, Jrd::SecurityClass::flags_t);
void SCL_check_relation(const dsc*, Jrd::SecurityClass::flags_t);
Jrd::SecurityClass* SCL_get_class(const TEXT*);
Jrd::SecurityClass::flags_t SCL_get_mask(const TEXT*, const TEXT*);
void SCL_init(bool, const TEXT*, const TEXT*, const TEXT*, const TEXT*,
const TEXT*, Jrd::thread_db*);
void SCL_init(bool, const TEXT*, const TEXT*, const TEXT*, const TEXT*, const TEXT*,
#ifdef TRUSTED_AUTH
const TEXT*,
#endif
Jrd::thread_db*);
void SCL_move_priv(UCHAR**, Jrd::SecurityClass::flags_t, Firebird::UCharBuffer&, ULONG*);
Jrd::SecurityClass* SCL_recompute_class(Jrd::thread_db*, const TEXT*);
void SCL_release(Jrd::SecurityClass*);

View File

@ -135,7 +135,11 @@ namespace Jrd {
svc_stdout_head(0), svc_stdout_tail(0), svc_stdout(0), svc_argv(p), svc_argc(0),
svc_service(se), svc_resp_buf(0), svc_resp_ptr(0), svc_resp_buf_len(0),
svc_resp_len(0), svc_flags(0), svc_user_flag(0), svc_spb_version(0), svc_do_shutdown(false),
svc_username(p), svc_enc_password(p), svc_switches(p), svc_perm_sw(p)
svc_username(p), svc_enc_password(p),
#ifdef TRUSTED_AUTH
svc_trusted_login(p),
#endif
svc_switches(p), svc_perm_sw(p)
{
memset(svc_start_event, 0, sizeof svc_start_event);
@ -285,6 +289,9 @@ struct Serv_param_block {
Firebird::string spb_command_line;
Firebird::string spb_network_protocol;
Firebird::string spb_remote_address;
#ifdef TRUSTED_AUTH
Firebird::string spb_trusted_login;
#endif
USHORT spb_version;
Serv_param_block() : spb_version(0) { }
@ -553,6 +560,13 @@ Service* SVC_attach(USHORT service_length,
user_flag = SVC_user_none;
}
else {
#ifdef TRUSTED_AUTH
if (options.spb_trusted_login.hasData())
{
options.spb_user_name = options.spb_trusted_login;
}
else
#endif
if (!options.spb_user_name.hasData())
{
// user name and password are required while
@ -608,6 +622,9 @@ Service* SVC_attach(USHORT service_length,
#endif
service->svc_spb_version = options.spb_version;
service->svc_username = options.spb_user_name;
#ifdef TRUSTED_AUTH
service->svc_trusted_login = options.spb_trusted_login;
#endif
/* The password will be issued to the service threads on NT since
* there is no OS authentication. If the password is not yet
@ -1785,7 +1802,19 @@ void* SVC_start(Service* service, USHORT spb_length, const SCHAR* spb_data)
svc_id == isc_action_svc_properties)
{
/* add the username and password to the end of svc_switches if needed */
if (service->svc_switches.hasData()) {
if (service->svc_switches.hasData())
{
#ifdef TRUSTED_AUTH
if (service->svc_trusted_login.hasData())
{
service->svc_switches += ' ';
service->svc_switches += TRUSTED_USER_SWITCH;
service->svc_switches += ' ';
service->svc_switches += service->svc_username;
}
else
#endif
{
if (service->svc_username.hasData())
{
service->svc_switches += ' ';
@ -1803,6 +1832,7 @@ void* SVC_start(Service* service, USHORT spb_length, const SCHAR* spb_data)
}
}
}
}
// All services except for get_ib_log require switches
spb.rewind();
@ -2006,6 +2036,12 @@ static void get_options(Firebird::ClumpletReader& spb,
spb.getString(options->spb_password_enc);
break;
#ifdef TRUSTED_AUTH
case isc_spb_trusted_auth:
spb.getString(options->spb_trusted_login);
break;
#endif
case isc_spb_command_line:
spb.getString(options->spb_command_line);
break;

View File

@ -81,6 +81,9 @@ const USHORT isc_action_max = 14;
#else
#define SERVICE_THD_PARAM "-svc"
#endif
#ifdef TRUSTED_AUTH
#define TRUSTED_USER_SWITCH "-TRUSTED"
#endif
/* Macro used to store services thread specific data */
/* Currently we store empty string, see bug #10394 */
@ -130,6 +133,9 @@ public:
bool svc_do_shutdown;
Firebird::string svc_username;
Firebird::string svc_enc_password;
#ifdef TRUSTED_AUTH
Firebird::string svc_trusted_login;
#endif
Firebird::string svc_switches; // Full set of switches
Firebird::string svc_perm_sw; // Switches, taken from services table
// and/or passed using spb_command_line

View File

@ -2367,6 +2367,10 @@ inline void setTag(Firebird::ClumpletWriter& dpb, UCHAR tag, const TEXT* value)
}
void setLogin(Firebird::ClumpletWriter& dpb)
{
#ifdef TRUSTED_AUTH
if (!dpb.find(isc_dpb_trusted_auth))
#endif
{
Firebird::string username;
if (fb_utils::readenv("ISC_USER", username) && !dpb.find(isc_dpb_sys_user_name))
@ -2380,4 +2384,5 @@ void setLogin(Firebird::ClumpletWriter& dpb)
setTag(dpb, isc_dpb_password, password.c_str());
}
}
}

View File

@ -1797,7 +1797,7 @@ without specifying a character set.', NULL);
INSERT INTO MESSAGES (SYMBOL, ROUTINE, MODULE, TRANS_NOTES, FAC_CODE, NUMBER, FLAGS, TEXT, "ACTION", EXPLANATION) VALUES ('existing_priv_mod', 'trigger_messages', 'ini.e', NULL, 0, 209, NULL, 'cannot modify an existing user privilege', NULL, NULL);
INSERT INTO MESSAGES (SYMBOL, ROUTINE, MODULE, TRANS_NOTES, FAC_CODE, NUMBER, FLAGS, TEXT, "ACTION", EXPLANATION) VALUES ('lock_timeout', '', 'lck.c', NULL, 0, 190, NULL, 'lock time-out on wait transaction', NULL, NULL);
INSERT INTO MESSAGES (SYMBOL, ROUTINE, MODULE, TRANS_NOTES, FAC_CODE, NUMBER, FLAGS, TEXT, "ACTION", EXPLANATION) VALUES (NULL, 'delete_procedure', 'dyn.e', NULL, 8, 138, NULL, 'ERASE RDB$PROCEDURE_PARAMETERS failed', NULL, NULL);
INSERT INTO MESSAGES (SYMBOL, ROUTINE, MODULE, TRANS_NOTES, FAC_CODE, NUMBER, FLAGS, TEXT, "ACTION", EXPLANATION) VALUES (NULL, 'delete_procedure', 'dyh.e', NULL, 8, 139, NULL, 'ERASE RDB$PROCEDURES failed', NULL, NULL);
INSERT INTO MESSAGES (SYMBOL, ROUTINE, MODULE, TRANS_NOTES, FAC_CODE, NUMBER, FLAGS, TEXT, "ACTION", EXPLANATION) VALUES (NULL, 'delete_procedure', 'dyn.e', NULL, 8, 139, NULL, 'ERASE RDB$PROCEDURES failed', NULL, NULL);
INSERT INTO MESSAGES (SYMBOL, ROUTINE, MODULE, TRANS_NOTES, FAC_CODE, NUMBER, FLAGS, TEXT, "ACTION", EXPLANATION) VALUES (NULL, 'delete_procedure', 'dyn.e', NULL, 8, 140, NULL, 'Procedure %s not found', NULL, NULL);
INSERT INTO MESSAGES (SYMBOL, ROUTINE, MODULE, TRANS_NOTES, FAC_CODE, NUMBER, FLAGS, TEXT, "ACTION", EXPLANATION) VALUES ('prcnotdef', 'par_procedure', 'PAR', NULL, 0, 191, NULL, 'procedure %s is not defined', NULL, NULL);
INSERT INTO MESSAGES (SYMBOL, ROUTINE, MODULE, TRANS_NOTES, FAC_CODE, NUMBER, FLAGS, TEXT, "ACTION", EXPLANATION) VALUES ('prcmismat', 'par_procedure', 'par.c', NULL, 0, 192, NULL, 'Input parameter mismatch for procedure %s', NULL, NULL);
@ -3101,6 +3101,7 @@ INSERT INTO MESSAGES (SYMBOL, ROUTINE, MODULE, TRANS_NOTES, FAC_CODE, NUMBER, FL
INSERT INTO MESSAGES (SYMBOL, ROUTINE, MODULE, TRANS_NOTES, FAC_CODE, NUMBER, FLAGS, TEXT, "ACTION", EXPLANATION) VALUES ('dsql_cte_miss_nonrecursive', 'pass1_recursive_cte', 'dsql.cpp', NULL, 13, 945, NULL, 'Non-recursive member is missing in CTE ''%s''', NULL, NULL);
INSERT INTO MESSAGES (SYMBOL, ROUTINE, MODULE, TRANS_NOTES, FAC_CODE, NUMBER, FLAGS, TEXT, "ACTION", EXPLANATION) VALUES ('dsql_cte_nested_with', 'dsql_req::addCTEs', 'dsql.cpp', NULL, 13, 946, NULL, 'WITH clause can''t be nested', NULL, NULL);
INSERT INTO MESSAGES (SYMBOL, ROUTINE, MODULE, TRANS_NOTES, FAC_CODE, NUMBER, FLAGS, TEXT, "ACTION", EXPLANATION) VALUES ('USAGE_NODBTRIGGERS', 'ISQL_main', 'isql.epp', NULL, 17, 154, NULL, ' -nod(btriggers) do not run database triggers', NULL, NULL);
INSERT INTO MESSAGES (SYMBOL, ROUTINE, MODULE, TRANS_NOTES, FAC_CODE, NUMBER, FLAGS, TEXT, "ACTION", EXPLANATION) VALUES ('USAGE_TRUSTED', 'ISQL_main', 'isql.epp', NULL, 17, 155, NULL, ' -tr(usted) use windows trusted authentication', NULL, NULL);
INSERT INTO MESSAGES (SYMBOL, ROUTINE, MODULE, TRANS_NOTES, FAC_CODE, NUMBER, FLAGS, TEXT, "ACTION", EXPLANATION) VALUES (NULL, '', 'burp.cpp', NULL, 12, 294, NULL, ' %sNO_D(BTRIGGERS) do not run database triggers', NULL, NULL);
INSERT INTO MESSAGES (SYMBOL, ROUTINE, MODULE, TRANS_NOTES, FAC_CODE, NUMBER, FLAGS, TEXT, "ACTION", EXPLANATION) VALUES ('dsql_incompatible_trigger_type', 'define_trigger', 'ddl.cpp', NULL, 7, 30, NULL, 'Incompatible trigger type', NULL, NULL);
INSERT INTO MESSAGES (SYMBOL, ROUTINE, MODULE, TRANS_NOTES, FAC_CODE, NUMBER, FLAGS, TEXT, "ACTION", EXPLANATION) VALUES ('dsql_db_trigger_type_cant_change', 'define_trigger', 'ddl.cpp', NULL, 7, 31, NULL, 'Database trigger type can''t be changed', NULL, NULL);

View File

@ -129,6 +129,9 @@ int CLIB_ROUTINE main( int argc, char **argv)
QLI_columns = 80;
#else
QLI_columns = 80;
#endif
#ifdef TRUSTED_AUTH
QLI_trusted = false;
#endif
QLI_lines = 60;
QLI_name_columns = 0;
@ -182,6 +185,12 @@ int CLIB_ROUTINE main( int argc, char **argv)
startup_file = *argv++;
break;
#ifdef TRUSTED_AUTH
case 'K':
QLI_trusted = true;
break;
#endif
case 'N':
banner_flag = false;
break;

View File

@ -499,6 +499,9 @@ EXTERN USHORT QLI_count;
EXTERN bool QLI_explain;
EXTERN bool QLI_hex_output;
#endif
#ifdef TRUSTED_AUTH
EXTERN bool QLI_trusted;
#endif
EXTERN jmp_buf QLI_env; // Error return environment

View File

@ -1420,6 +1420,12 @@ void MET_ready( qli_syntax* node, USHORT create_flag)
dpb.insertString(isc_dpb_password, q, length);
}
#ifdef TRUSTED_AUTH
if (QLI_trusted) {
dpb.insertTag(isc_dpb_trusted_auth);
}
#endif
const qli_syntax* const* const end = node->syn_arg + node->syn_count;
// Start by attaching all databases

View File

@ -507,10 +507,12 @@ rem_port* INET_analyze(Firebird::PathName& file_name,
{
REMOTE_PROTOCOL(PROTOCOL_VERSION8, ptype_rpc, MAX_PTYPE, 1),
REMOTE_PROTOCOL(PROTOCOL_VERSION10, ptype_rpc, MAX_PTYPE, 2),
REMOTE_PROTOCOL(PROTOCOL_VERSION10, ptype_rpc, ptype_lazy_send, 3)
REMOTE_PROTOCOL(PROTOCOL_VERSION10, ptype_rpc, ptype_lazy_send, 3),
REMOTE_PROTOCOL(PROTOCOL_VERSION11, ptype_rpc, MAX_PTYPE, 4),
REMOTE_PROTOCOL(PROTOCOL_VERSION11, ptype_rpc, ptype_lazy_send, 5)
#ifdef SCROLLABLE_CURSORS
,
REMOTE_PROTOCOL(PROTOCOL_SCROLLABLE_CURSORS, ptype_rpc, MAX_PTYPE, 3)
REMOTE_PROTOCOL(PROTOCOL_SCROLLABLE_CURSORS, ptype_rpc, MAX_PTYPE, 99)
#endif
};
@ -597,9 +599,9 @@ rem_port* INET_analyze(Firebird::PathName& file_name,
/* once we've decided on a protocol, concatenate the version
string to reflect it... */
Firebird::string temp;
temp.printf("%s/P%d", port->port_version->str_data, port->port_protocol);
temp.printf("%s/P%d", port->port_version->str_data,
port->port_protocol & FB_PROTOCOL_MASK);
ALLR_free(port->port_version);
port->port_version = REMOTE_make_string(temp.c_str());
@ -1898,6 +1900,10 @@ static void cleanup_port( rem_port* port)
delete port->port_queue;
#endif
#ifdef TRUSTED_AUTH
delete port->port_trusted_auth;
#endif
ALLR_release((UCHAR *) port);
return;
}

View File

@ -66,6 +66,7 @@
#include "../jrd/thread_proto.h"
#include "../common/classes/ClumpletWriter.h"
#include "../common/config/config.h"
#include "../auth/trusted/AuthSspi.h"
#ifdef HAVE_UNISTD_H
#include <unistd.h>
@ -110,7 +111,7 @@ namespace {
// for both services and databases attachments
struct ParametersSet {
UCHAR dummy_packet_interval, user_name, sys_user_name,
password, password_enc, address_path, pid;
password, password_enc, address_path, pid, trusted_auth;
};
const ParametersSet dpbParam = {isc_dpb_dummy_packet_interval,
isc_dpb_user_name,
@ -118,14 +119,16 @@ namespace {
isc_dpb_password,
isc_dpb_password_enc,
isc_dpb_address_path,
isc_dpb_pid};
isc_dpb_pid,
isc_dpb_trusted_auth};
const ParametersSet spbParam = {isc_spb_dummy_packet_interval,
isc_spb_user_name,
isc_spb_sys_user_name,
isc_spb_password,
isc_spb_password_enc,
isc_spb_address_path,
isc_spb_pid};
isc_spb_pid,
isc_spb_trusted_auth};
}
static RVNT add_event(rem_port*);
@ -166,7 +169,8 @@ static bool get_single_user(Firebird::ClumpletReader&);
static ISC_STATUS handle_error(ISC_STATUS *, ISC_STATUS);
static ISC_STATUS info(ISC_STATUS*, RDB, P_OP, USHORT, USHORT, USHORT,
const SCHAR*, USHORT, const SCHAR*, USHORT, SCHAR*);
static bool init(ISC_STATUS *, rem_port*, P_OP, Firebird::PathName&, Firebird::ClumpletWriter&);
static bool init(ISC_STATUS *, rem_port*, P_OP, Firebird::PathName&,
Firebird::ClumpletWriter&, const ParametersSet&);
static RTR make_transaction(RDB, USHORT);
static ISC_STATUS mov_dsql_message(const UCHAR*, const rem_fmt*, UCHAR*, const rem_fmt*);
static void move_error(ISC_STATUS, ...);
@ -345,7 +349,8 @@ ISC_STATUS GDS_ATTACH_DATABASE(ISC_STATUS* user_status,
add_other_params(port, newDpb, dpbParam);
add_working_directory(newDpb, node_name);
const bool result = init(user_status, port, op_attach, expanded_name, newDpb);
const bool result = init(user_status, port, op_attach, expanded_name,
newDpb, dpbParam);
if (!result) {
return error(user_status);
@ -904,7 +909,8 @@ ISC_STATUS GDS_CREATE_DATABASE(ISC_STATUS* user_status,
add_other_params(port, newDpb, dpbParam);
add_working_directory(newDpb, node_name);
const bool result = init(user_status, port, op_create, expanded_name, newDpb);
const bool result = init(user_status, port, op_create, expanded_name,
newDpb, dpbParam);
if (!result) {
return error(user_status);
}
@ -3951,7 +3957,8 @@ ISC_STATUS GDS_SERVICE_ATTACH(ISC_STATUS* user_status,
add_other_params(port, newSpb, spbParam);
const bool result = init(user_status, port, op_service_attach, expanded_name, newSpb);
const bool result = init(user_status, port, op_service_attach, expanded_name,
newSpb, spbParam);
if (!result) {
return error(user_status);
}
@ -5841,7 +5848,8 @@ static bool init(ISC_STATUS* user_status,
rem_port* port,
P_OP op,
Firebird::PathName& file_name,
Firebird::ClumpletWriter& dpb)
Firebird::ClumpletWriter& dpb,
const ParametersSet& param)
{
/**************************************
*
@ -5860,7 +5868,29 @@ static bool init(ISC_STATUS* user_status,
MemoryPool& pool = *getDefaultMemoryPool();
port->port_deferred_packets = FB_NEW(pool) PacketQueue(pool);
/* Make attach packet */
// Do we can & need to try trusted auth
if (dpb.find(param.trusted_auth))
{
dpb.deleteClumplet();
}
#ifdef TRUSTED_AUTH
AuthSspi authSspi;
AuthSspi::DataHolder data;
if ((port->port_protocol >= PROTOCOL_VERSION11) &&
((!dpb.find(param.user_name)) || (dpb.getClumpLength() == 0)))
{
if (authSspi.request(data))
{
// on no error we send data no matter, was context created or not
dpb.insertBytes(param.trusted_auth, data.begin(), data.getCount());
}
}
#endif //TRUSTED_AUTH
// Make attach packet
P_ATCH* attach = &packet->p_atch;
packet->p_operation = op;
@ -5876,9 +5906,54 @@ static bool init(ISC_STATUS* user_status,
return false;
}
/* Get response */
// Get response
if (!receive_response(rdb, packet)) {
#ifdef TRUSTED_AUTH
ISC_STATUS* status = packet->p_resp.p_resp_status_vector = rdb->rdb_status_vector;
if (!receive_packet(rdb->rdb_port, packet, status))
{
REMOTE_save_status_strings(user_status);
disconnect(port);
return false;
}
while (packet->p_operation == op_trusted_auth)
{
if (!authSspi.isActive())
{
disconnect(port);
return false; // isc_unavailable
}
cstring *d = &packet->p_trau.p_trau_data;
memcpy(data.getBuffer(d->cstr_length), d->cstr_address, d->cstr_length);
REMOTE_free_packet(rdb->rdb_port, packet);
if (!authSspi.request(data))
{
disconnect(port);
return false; // isc_unavailable
}
packet->p_operation = op_trusted_auth;
d->cstr_address = data.begin();
d->cstr_length = data.getCount();
if (!send_packet(rdb->rdb_port, packet, user_status))
{
disconnect(port);
return false;
}
if (!receive_packet(rdb->rdb_port, packet, status))
{
REMOTE_save_status_strings(user_status);
disconnect(port);
return false;
}
}
if (!check_response(rdb, packet))
#else // TRUSTED_AUTH
if (!receive_response(rdb, packet))
#endif //TRUSTED_AUTH
{
REMOTE_save_status_strings(user_status);
disconnect(port);
return false;

View File

@ -183,10 +183,11 @@ rem_port* WNET_analyze(Firebird::PathName& file_name,
{
REMOTE_PROTOCOL(PROTOCOL_VERSION7, ptype_rpc, MAX_PTYPE, 1),
REMOTE_PROTOCOL(PROTOCOL_VERSION8, ptype_rpc, MAX_PTYPE, 2),
REMOTE_PROTOCOL(PROTOCOL_VERSION10, ptype_rpc, MAX_PTYPE, 3)
REMOTE_PROTOCOL(PROTOCOL_VERSION10, ptype_rpc, MAX_PTYPE, 3),
REMOTE_PROTOCOL(PROTOCOL_VERSION11, ptype_rpc, MAX_PTYPE, 4)
#ifdef SCROLLABLE_CURSORS
,
REMOTE_PROTOCOL(PROTOCOL_SCROLLABLE_CURSORS, ptype_rpc, MAX_PTYPE, 4)
REMOTE_PROTOCOL(PROTOCOL_SCROLLABLE_CURSORS, ptype_rpc, MAX_PTYPE, 99)
#endif
};
cnct->p_cnct_count = FB_NELEM(protocols_to_try1);
@ -298,7 +299,8 @@ rem_port* WNET_analyze(Firebird::PathName& file_name,
string to reflect it... */
Firebird::string temp;
temp.printf("%s/P%d", port->port_version->str_data, port->port_protocol);
temp.printf("%s/P%d", port->port_version->str_data,
port->port_protocol & FB_PROTOCOL_MASK);
ALLR_free(port->port_version);
port->port_version = REMOTE_make_string(temp.c_str());

View File

@ -289,6 +289,7 @@ bool_t xdr_protocol(XDR* xdrs, PACKET* p)
P_SQLST *prep_stmt;
P_SQLDATA *sqldata;
P_TRRQ *trrq;
P_TRAU *trau;
#ifdef DEBUG
xdr_save_size = xdrs->x_handy;
#endif
@ -786,6 +787,36 @@ bool_t xdr_protocol(XDR* xdrs, PACKET* p)
DEBUG_PRINTSIZE(xdrs, p->p_operation);
return P_TRUE(xdrs, p);
// the following added to have formal vulcan compatibility
case op_update_account_info:
{
p_update_account *stuff = &p->p_account_update;
MAP(xdr_short, reinterpret_cast < SSHORT & >(stuff->p_account_database));
MAP(xdr_cstring_const, stuff->p_account_apb);
DEBUG_PRINTSIZE(xdrs, p->p_operation);
return P_TRUE(xdrs, p);
}
case op_authenticate_user:
{
p_authenticate *stuff = &p->p_authenticate_user;
MAP(xdr_short, reinterpret_cast < SSHORT & >(stuff->p_auth_database));
MAP(xdr_cstring_const, stuff->p_auth_dpb);
MAP(xdr_cstring, stuff->p_auth_items);
MAP(xdr_short, reinterpret_cast < SSHORT & >(stuff->p_auth_buffer_length));
DEBUG_PRINTSIZE(xdrs, p->p_operation);
return P_TRUE(xdrs, p);
}
case op_trusted_auth:
trau = &p->p_trau;
MAP(xdr_cstring, trau->p_trau_data);
DEBUG_PRINTSIZE(xdrs, p->p_operation);
return P_TRUE(xdrs, p);
default:
#ifdef DEBUG
if (xdrs->x_op != XDR_FREE)

View File

@ -79,6 +79,24 @@ const USHORT PROTOCOL_VERSION9 = 9;
const USHORT PROTOCOL_VERSION10 = 10;
/*
Since protocol 11 we must be separated from Borland Interbase.
Therefore always set highmost bit in protocol version to 1.
For unsigned protocol version this does not break version's compare.
*/
const USHORT FB_PROTOCOL_FLAG = 0x8000;
const USHORT FB_PROTOCOL_MASK = ~FB_PROTOCOL_FLAG;
/*
Protocol 11 has support for user authentication related
operations (op_update_account_info, op_authenticate_user and
op_trusted_auth). When specific operation is not supported,
we say "sorry".
*/
const USHORT PROTOCOL_VERSION11 = (FB_PROTOCOL_FLAG | 11);
#ifdef SCROLLABLE_CURSORS
This Protocol includes support for scrollable cursors
and is purposely being undefined so that changes can be made
@ -263,12 +281,15 @@ typedef enum
op_service_start = 85,
op_rollback_retaining = 86,
// Two following opcode are used in vulcan.
// No plans to implement protocol 11, where they are used,
// place here only for informational reasons and to have common op-space.
// op_update_account_info = 87,
// op_authenticate_user = 88,
// No plans to implement them completely for a while, but to
// support protocol 11, where they are used, have them here.
op_update_account_info = 87,
op_authenticate_user = 88,
op_partial = 89, // packet is not complete - delay processing
op_trusted_auth = 90,
op_max
} P_OP;
@ -574,6 +595,26 @@ typedef struct p_sqlcur {
USHORT p_sqlcur_type; /* type of cursor */
} P_SQLCUR;
typedef struct p_trau
{
CSTRING p_trau_data; // Context
} P_TRAU;
struct p_update_account {
OBJCT p_account_database; /* Database object id */
CSTRING_CONST p_account_apb; /* Account parameter block (apb) */
};
struct p_authenticate {
OBJCT p_auth_database; /* Database object id */
CSTRING_CONST p_auth_dpb; /* Database parameter block w/ user credentials */
CSTRING p_auth_items; /* Information */
CSTRING p_auth_recv_items; /* Receive information */
USHORT p_auth_buffer_length; /* Target buffer length */
};
/* Generalize packet (sic!) */
typedef struct packet {
@ -608,6 +649,9 @@ typedef struct packet {
P_SQLCUR p_sqlcur; /* DSQL Set cursor name */
P_SQLFREE p_sqlfree; /* DSQL Free statement */
P_TRRQ p_trrq; /* Transact request packet */
P_TRAU p_trau; /* Trusted authentication */
p_update_account p_account_update;
p_authenticate p_authenticate_user;
} PACKET;
#endif // REMOTE_PROTOCOL_H

View File

@ -882,3 +882,24 @@ bool_t REMOTE_getbytes (XDR * xdrs, SCHAR * buff, u_int count)
return TRUE;
}
#endif //SUPERSERVER
#ifdef TRUSTED_AUTH
ServerAuth::ServerAuth(const char* fName, int fLen, const Firebird::ClumpletWriter& pb,
ServerAuth::Part2* p2, P_OP op)
: fileName(*getDefaultMemoryPool()), clumplet(*getDefaultMemoryPool()),
part2(p2), operation(op)
{
fileName.assign(fName, fLen);
size_t pbLen = pb.getBufferLength();
if (pbLen)
{
memcpy(clumplet.getBuffer(pbLen), pb.getBuffer(), pbLen);
}
authSspi = FB_NEW(*getDefaultMemoryPool()) AuthSspi;
}
ServerAuth::~ServerAuth()
{
delete authSspi;
}
#endif //TRUSTED_AUTH

View File

@ -33,6 +33,9 @@
#include "../remote/remote_def.h"
#include "../jrd/thd.h"
#include "../common/classes/objects_array.h"
#include "../auth/trusted/AuthSspi.h"
#include "../common/classes/fb_string.h"
#include "../common/classes/ClumpletWriter.h"
/* Include some apollo include files for tasking */
@ -364,6 +367,23 @@ struct rem_que_packet
typedef Firebird::Array<rem_que_packet> PacketQueue;
#ifdef TRUSTED_AUTH
// delayed authentication block for trusted auth callback
class ServerAuth
{
public:
typedef void Part2(rem_port*, P_OP, const char* fName, int fLen, const UCHAR* pb, int pbLen, PACKET*);
Firebird::PathName fileName;
Firebird::HalfStaticArray<UCHAR, 128> clumplet;
AuthSspi* authSspi;
Part2* part2;
P_OP operation;
ServerAuth(const char* fName, int fLen, const Firebird::ClumpletWriter& pb, Part2* p2, P_OP op);
~ServerAuth();
};
#endif //TRUSTED_AUTH
/* Port itself */
class port_interface
@ -440,6 +460,9 @@ struct rem_port
#ifdef SUPERSERVER
Firebird::ObjectsArray< Firebird::Array< char > >* port_queue;
size_t port_qoffset; // current packet in the queue
#endif
#ifdef TRUSTED_AUTH
ServerAuth* port_trusted_auth;
#endif
UCHAR port_buffer[1];
@ -488,7 +511,7 @@ struct rem_port
ISC_STATUS seek_blob(P_SEEK*, PACKET*);
ISC_STATUS send_msg(P_DATA*, PACKET*);
ISC_STATUS send_response(PACKET*, OBJCT, USHORT, const ISC_STATUS*, bool);
ISC_STATUS service_attach(P_ATCH*, PACKET*);
ISC_STATUS service_attach(const char*, const USHORT, Firebird::ClumpletWriter&, PACKET*);
ISC_STATUS service_end(P_RLSE*, PACKET*);
ISC_STATUS service_start(P_INFO*, PACKET*);
ISC_STATUS set_cursor(P_SQLCUR*, PACKET*);
@ -496,7 +519,6 @@ struct rem_port
ISC_STATUS start_and_send(P_OP, P_DATA*, PACKET*);
ISC_STATUS start_transaction(P_OP, P_STTR*, PACKET*);
ISC_STATUS transact_request(P_TRRQ *, PACKET*);
};
// port_flags

View File

@ -150,7 +150,16 @@ static ISC_STATUS allocate_statement(rem_port*, P_RLSE*, PACKET*);
static SLONG append_request_chain(SERVER_REQ, SERVER_REQ*);
static SLONG append_request_next(SERVER_REQ, SERVER_REQ*);
#endif
static ISC_STATUS attach_database(rem_port*, P_OP, P_ATCH*, PACKET*);
static void attach_database(rem_port*, P_OP, P_ATCH*, PACKET*);
static void attach_service(rem_port*, P_ATCH*, PACKET*);
static void attach_database2(rem_port*, P_OP, const char*, int,
const UCHAR*, int, PACKET*);
static void attach_service2(rem_port*, P_OP, const char*, int,
const UCHAR*, int, PACKET*);
#ifdef TRUSTED_AUTH
static void trusted_auth(rem_port*, P_TRAU*, PACKET*);
#endif
#ifdef NOT_USED_OR_REPLACED
static void aux_connect(rem_port*, P_REQ*, PACKET*);
#endif
@ -644,23 +653,23 @@ static bool accept_connection(rem_port* port,
* Process a connect packet.
*
**************************************/
P_ARCH architecture = arch_generic;
USHORT version = 0;
USHORT type = 0;
bool accepted = false;
/* Accept the physical connection */
// Accept the physical connection
send->p_operation = op_reject;
P_ACPT* accept = &send->p_acpt;
USHORT weight = 0;
if (!port->accept(connect)) {
port->send(send);
return false;
}
/* Select the most appropriate protocol (this will get smarter) */
// Select the most appropriate protocol (this will get smarter)
P_ARCH architecture = arch_generic;
USHORT version = 0;
USHORT type = 0;
bool accepted = false;
USHORT weight = 0;
const p_cnct::p_cnct_repeat* protocol = connect->p_cnct_versions;
for (const p_cnct::p_cnct_repeat* const end = protocol + connect->p_cnct_count;
@ -673,7 +682,8 @@ static bool accept_connection(rem_port* port,
protocol->p_cnct_version == PROTOCOL_VERSION7 ||
protocol->p_cnct_version == PROTOCOL_VERSION8 ||
protocol->p_cnct_version == PROTOCOL_VERSION9 ||
protocol->p_cnct_version == PROTOCOL_VERSION10
protocol->p_cnct_version == PROTOCOL_VERSION10 ||
protocol->p_cnct_version == PROTOCOL_VERSION11
#ifdef SCROLLABLE_CURSORS
|| protocol->p_cnct_version == PROTOCOL_SCROLLABLE_CURSORS
#endif
@ -702,11 +712,11 @@ static bool accept_connection(rem_port* port,
/* and modify the version string to reflect the chosen protocol */
TEXT buffer[64];
sprintf(buffer, "%s/P%d", port->port_version->str_data,
port->port_protocol);
Firebird::string buffer;
buffer.printf("%s/P%d", port->port_version->str_data,
port->port_protocol & FB_PROTOCOL_MASK);
ALLR_free(port->port_version);
port->port_version = REMOTE_make_string(buffer);
port->port_version = REMOTE_make_string(buffer.c_str());
if (architecture == ARCHITECTURE)
port->port_flags |= PORT_symmetric;
@ -889,9 +899,10 @@ static void addClumplets(Firebird::ClumpletWriter& dpb_buffer,
}
}
static ISC_STATUS attach_database(
rem_port* port,
P_OP operation, P_ATCH * attach, PACKET* send)
static void attach_database(rem_port* port,
P_OP operation,
P_ATCH * attach,
PACKET* send)
{
/**************************************
*
@ -903,10 +914,6 @@ static ISC_STATUS attach_database(
* Process an attach or create packet.
*
**************************************/
ISC_STATUS_ARRAY status_vector;
send->p_operation = op_accept;
FB_API_HANDLE handle = 0;
const char* file = reinterpret_cast<const char*>(attach->p_atch_file.cstr_address);
const USHORT l = attach->p_atch_file.cstr_length;
@ -920,6 +927,79 @@ static ISC_STATUS attach_database(
else
dpb_buffer.reset(isc_dpb_version1);
#ifdef TRUSTED_AUTH
// Do we need trusted authentication?
if (port->port_protocol >= PROTOCOL_VERSION11 && dpb_buffer.find(isc_dpb_trusted_auth))
{
try
{
// extract trusted authentication data from dpb
AuthSspi::DataHolder data;
memcpy(data.getBuffer(dpb_buffer.getClumpLength()),
dpb_buffer.getBytes(), dpb_buffer.getClumpLength());
dpb_buffer.deleteClumplet();
port->port_trusted_auth = FB_NEW(*getDefaultMemoryPool())
ServerAuth(file, l, dpb_buffer, attach_database2, operation);
AuthSspi* authSspi = port->port_trusted_auth->authSspi;
if (authSspi->accept(data) && authSspi->isActive())
{
send->p_operation = op_trusted_auth;
cstring& s = send->p_trau.p_trau_data;
s.cstr_allocated = 0;
s.cstr_length = data.getCount();
s.cstr_address = data.begin();
port->send(send);
return;
}
}
catch(const Firebird::status_exception& e)
{
ISC_STATUS_ARRAY status_vector;
Firebird::stuff_exception(status_vector, e);
port->send_response(send, 0, 0, status_vector, false);
return;
}
}
#endif //TRUSTED_AUTH
attach_database2(port, operation, file, l, dpb_buffer.getBuffer(),
dpb_buffer.getBufferLength(), send);
}
static void attach_database2(rem_port* port,
P_OP operation,
const char* file,
int l,
const UCHAR* dpb,
int dl,
PACKET* send)
{
ISC_STATUS_ARRAY status_vector;
send->p_operation = op_accept;
FB_API_HANDLE handle = 0;
Firebird::ClumpletWriter dpb_buffer(Firebird::ClumpletReader::Tagged, MAX_SSHORT);
if (dl)
dpb_buffer.reset(dpb, dl);
else
dpb_buffer.reset(isc_dpb_version1);
#ifdef TRUSTED_AUTH
// If we have trusted authentication, append it to database parameter block
if (port->port_trusted_auth)
{
AuthSspi* authSspi = port->port_trusted_auth->authSspi;
Firebird::string trustedUserName;
if (authSspi->getLogin(trustedUserName))
{
dpb_buffer.insertString(isc_dpb_trusted_auth, trustedUserName);
}
}
#endif //TRUSTED_AUTH
// If we have user identification, append it to database parameter block
rem_str* string = port->port_user_name;
if (string) {
@ -970,7 +1050,12 @@ static ISC_STATUS attach_database(
rdb->rdb_handle = handle;
}
return port->send_response(send, 0, 0, status_vector, false);
port->send_response(send, 0, 0, status_vector, false);
#ifdef TRUSTED_AUTH
delete port->port_trusted_auth;
port->port_trusted_auth = 0;
#endif
}
@ -3286,7 +3371,25 @@ bool process_packet(rem_port* port,
break;
case op_service_attach:
port->service_attach(&receive->p_atch, sendL);
attach_service(port, &receive->p_atch, sendL);
break;
case op_trusted_auth:
#ifdef TRUSTED_AUTH
trusted_auth(port, &receive->p_trau, sendL);
break;
//else
// fall down ...
#endif
case op_update_account_info:
case op_authenticate_user:
{
ISC_STATUS_ARRAY status_vector;
status_vector[0] = isc_arg_gds;
status_vector[1] = isc_wish_list;
status_vector[2] = isc_arg_end;
port->send_response(sendL, 0, 0, status_vector, false);
}
break;
case op_service_start:
@ -3533,6 +3636,51 @@ bool process_packet(rem_port* port,
}
#ifdef TRUSTED_AUTH
static void trusted_auth(rem_port* port, P_TRAU* p_trau, PACKET* send)
{
ISC_STATUS_ARRAY status_vector;
ServerAuth *sa = port->port_trusted_auth;
if (! sa)
{
status_vector[0] = isc_arg_gds;
status_vector[1] = isc_unavailable;
status_vector[2] = isc_arg_end;
port->send_response(send, 0, 0, status_vector, false);
}
try
{
AuthSspi::DataHolder data;
memcpy(data.getBuffer(p_trau->p_trau_data.cstr_length),
p_trau->p_trau_data.cstr_address, p_trau->p_trau_data.cstr_length);
AuthSspi* authSspi = sa->authSspi;
if (authSspi->accept(data) && authSspi->isActive())
{
send->p_operation = op_trusted_auth;
cstring& s = send->p_trau.p_trau_data;
s.cstr_allocated = 0;
s.cstr_length = data.getCount();
s.cstr_address = data.begin();
port->send(send);
return;
}
}
catch(const Firebird::status_exception& e)
{
ISC_STATUS_ARRAY status_vector;
Firebird::stuff_exception(status_vector, e);
port->send_response(send, 0, 0, status_vector, false);
return;
}
sa->part2(port, sa->operation, sa->fileName.c_str(), sa->fileName.length(),
sa->clumplet.begin(), sa->clumplet.getCount(), send);
}
#endif //TRUSTED_AUTH
ISC_STATUS rem_port::put_segment(P_OP op, P_SGMT * segment, PACKET* sendL)
{
/**************************************
@ -4589,7 +4737,80 @@ static void server_ast(void* event_void, USHORT length, const UCHAR* items)
}
ISC_STATUS rem_port::service_attach(P_ATCH* attach, PACKET* sendL)
static void attach_service(rem_port* port, P_ATCH* attach, PACKET* sendL)
{
const char* service_name = reinterpret_cast<const char*>
(attach->p_atch_file.cstr_address);
const USHORT service_length = attach->p_atch_file.cstr_length;
Firebird::ClumpletWriter spb(Firebird::ClumpletReader::SpbAttach, MAX_DPB_SIZE,
attach->p_atch_dpb.cstr_address, attach->p_atch_dpb.cstr_length, isc_spb_current_version);
#ifdef TRUSTED_AUTH
// Do we can & need trusted authentication?
if (port->port_protocol >= PROTOCOL_VERSION11 && spb.find(isc_spb_trusted_auth))
{
try
{
// extract trusted authentication data from spb
AuthSspi::DataHolder data;
memcpy(data.getBuffer(spb.getClumpLength()),
spb.getBytes(), spb.getClumpLength());
spb.deleteClumplet();
port->port_trusted_auth = FB_NEW(*getDefaultMemoryPool())
ServerAuth(service_name, service_length, spb, attach_service2, op_trusted_auth);
AuthSspi* authSspi = port->port_trusted_auth->authSspi;
if (authSspi->accept(data) && authSspi->isActive())
{
sendL->p_operation = op_trusted_auth;
cstring& s = sendL->p_trau.p_trau_data;
s.cstr_allocated = 0;
s.cstr_length = data.getCount();
s.cstr_address = data.begin();
port->send(sendL);
return;
}
}
catch(const Firebird::status_exception& e)
{
ISC_STATUS_ARRAY status_vector;
Firebird::stuff_exception(status_vector, e);
port->send_response(sendL, 0, 0, status_vector, false);
return;
}
}
#endif //TRUSTED_AUTH
attach_service2(port, op_trusted_auth, service_name, service_length,
spb.getBuffer(), spb.getBufferLength(), sendL);
}
static void attach_service2(rem_port* port,
P_OP,
const char* service_name,
int service_length,
const UCHAR* spb,
int sl,
PACKET* sendL)
{
port->service_attach(service_name, service_length,
Firebird::ClumpletWriter(Firebird::ClumpletReader::SpbAttach, MAX_DPB_SIZE,
spb, sl, isc_spb_current_version),
sendL);
#ifdef TRUSTED_AUTH
delete port->port_trusted_auth;
port->port_trusted_auth = 0;
#endif
}
ISC_STATUS rem_port::service_attach(const char* service_name,
const USHORT service_length,
Firebird::ClumpletWriter& spb,
PACKET* sendL)
{
/**************************************
*
@ -4603,11 +4824,20 @@ ISC_STATUS rem_port::service_attach(P_ATCH* attach, PACKET* sendL)
**************************************/
sendL->p_operation = op_accept;
FB_API_HANDLE handle = 0;
const UCHAR* service_name = attach->p_atch_file.cstr_address;
const USHORT service_length = attach->p_atch_file.cstr_length;
Firebird::ClumpletWriter spb(Firebird::ClumpletReader::SpbAttach, MAX_DPB_SIZE,
attach->p_atch_dpb.cstr_address, attach->p_atch_dpb.cstr_length, isc_spb_current_version);
#ifdef TRUSTED_AUTH
// If we have trusted authentication, append it to database parameter block
if (port_trusted_auth)
{
AuthSspi* authSspi = port_trusted_auth->authSspi;
Firebird::string trustedUserName;
if (authSspi->getLogin(trustedUserName))
{
spb.insertString(isc_spb_trusted_auth, trustedUserName);
}
}
#endif //TRUSTED_AUTH
// If we have user identification, append it to database parameter block
const rem_str* string = port_user_name;
@ -4628,7 +4858,7 @@ ISC_STATUS rem_port::service_attach(P_ATCH* attach, PACKET* sendL)
ISC_STATUS_ARRAY status_vector;
isc_service_attach(status_vector,
service_length,
reinterpret_cast<const char*>(service_name),
service_name,
&handle,
spb.getBufferLength(),
reinterpret_cast<const char*>(spb.getBuffer()));
@ -4636,6 +4866,8 @@ ISC_STATUS rem_port::service_attach(P_ATCH* attach, PACKET* sendL)
if (!status_vector[1]) {
RDB rdb = (RDB) ALLR_block(type_rdb, 0);
if (rdb)
{
this->port_context = rdb;
#ifdef DEBUG_REMOTE_MEMORY
printf("attach_service(server) allocate rdb %x\n", rdb);
@ -4644,6 +4876,13 @@ ISC_STATUS rem_port::service_attach(P_ATCH* attach, PACKET* sendL)
rdb->rdb_handle = handle;
rdb->rdb_flags |= RDB_service;
}
else
{
status_vector[0] = isc_arg_gds;
status_vector[1] = isc_bad_svc_handle;
status_vector[2] = isc_arg_end;
}
}
return this->send_response(sendL, 0, 0, status_vector, false);
}

View File

@ -286,10 +286,11 @@ rem_port* XNET_analyze(Firebird::PathName& file_name,
{
REMOTE_PROTOCOL(PROTOCOL_VERSION7, ptype_rpc, MAX_PTYPE, 1),
REMOTE_PROTOCOL(PROTOCOL_VERSION8, ptype_rpc, MAX_PTYPE, 2),
REMOTE_PROTOCOL(PROTOCOL_VERSION10, ptype_rpc, MAX_PTYPE, 3)
REMOTE_PROTOCOL(PROTOCOL_VERSION10, ptype_rpc, MAX_PTYPE, 3),
REMOTE_PROTOCOL(PROTOCOL_VERSION11, ptype_rpc, MAX_PTYPE, 4)
#ifdef SCROLLABLE_CURSORS
,
REMOTE_PROTOCOL(PROTOCOL_SCROLLABLE_CURSORS, ptype_rpc, MAX_PTYPE, 4)
REMOTE_PROTOCOL(PROTOCOL_SCROLLABLE_CURSORS, ptype_rpc, MAX_PTYPE, 99)
#endif
};
cnct->p_cnct_count = FB_NELEM(protocols_to_try1);
@ -399,7 +400,8 @@ rem_port* XNET_analyze(Firebird::PathName& file_name,
// string to reflect it...
Firebird::string temp;
temp.printf("%s/P%d", port->port_version->str_data, port->port_protocol);
temp.printf("%s/P%d", port->port_version->str_data,
port->port_protocol & FB_PROTOCOL_MASK);
ALLR_free((UCHAR *) port->port_version);
port->port_version = REMOTE_make_string(temp.c_str());

View File

@ -281,16 +281,28 @@ int common_main(int argc,
Firebird::ClumpletWriter dpb(Firebird::ClumpletReader::Tagged, MAX_DPB_SIZE, isc_dpb_version1);
dpb.insertByte(isc_dpb_gsec_attach, 1); // not 0 - yes, I'm gsec
if (user_data->dba_user_name_entered) {
#ifdef TRUSTED_SERVICES
if (user_data->dba_trust_user_name_entered)
{
dpb.insertString(isc_dpb_trusted_auth,
user_data->dba_trust_user_name, strlen(user_data->dba_trust_user_name));
}
else
#endif
{
if (user_data->dba_user_name_entered)
{
dpb.insertString(isc_dpb_user_name,
user_data->dba_user_name, strlen(user_data->dba_user_name));
}
if (user_data->dba_password_entered) {
if (user_data->dba_password_entered)
{
dpb.insertString(tdsec->tsec_service_gsec ?
isc_dpb_password_enc : isc_dpb_password,
user_data->dba_password, strlen(user_data->dba_password));
}
}
if (user_data->sql_role_name_entered) {
dpb.insertString(isc_dpb_sql_role_name,
@ -698,6 +710,12 @@ static bool get_switches(
strncpy(user_data->sql_role_name, string, sizeof(user_data->sql_role_name));
user_data->sql_role_name_entered = true;
break;
#ifdef TRUSTED_SERVICES
case IN_SW_GSEC_DBA_TRUST_USER:
strncpy(user_data->dba_trust_user_name, string, sizeof(user_data->dba_trust_user_name));
user_data->dba_trust_user_name_entered = true;
break;
#endif
case IN_SW_GSEC_Z:
case IN_SW_GSEC_0:
#ifdef SERVICE_THREAD
@ -799,6 +817,9 @@ static bool get_switches(
case IN_SW_GSEC_MNAME:
case IN_SW_GSEC_LNAME:
case IN_SW_GSEC_DATABASE:
#ifdef TRUSTED_SERVICES
case IN_SW_GSEC_DBA_TRUST_USER:
#endif
case IN_SW_GSEC_DBA_USER_NAME:
case IN_SW_GSEC_DBA_PASSWORD:
case IN_SW_GSEC_SQL_ROLE_NAME:
@ -884,6 +905,16 @@ static bool get_switches(
user_data->dba_user_name_specified = true;
user_data->dba_user_name[0] = '\0';
break;
#ifdef TRUSTED_SERVICES
case IN_SW_GSEC_DBA_TRUST_USER:
if (user_data->dba_trust_user_name_specified) {
err_msg_no = GsecMsg79;
break;
}
user_data->dba_trust_user_name_specified = true;
user_data->dba_trust_user_name[0] = '\0';
break;
#endif
case IN_SW_GSEC_DBA_PASSWORD:
if (user_data->dba_password_specified) {
err_msg_no = GsecMsg80;

View File

@ -91,6 +91,11 @@ struct internal_user_data {
TEXT dba_user_name [USER_NAME_LEN]; /* the user's name */
bool dba_user_name_entered; /* user name entered flag */
bool dba_user_name_specified;/* database specified flag */
#ifdef TRUSTED_SERVICES
TEXT dba_trust_user_name [USER_NAME_LEN]; /* the trusted dba user's name */
bool dba_trust_user_name_entered; /* trusted dba user name entered flag */
bool dba_trust_user_name_specified;/* trusted dba user name specified flag */
#endif
TEXT dba_password [NAME_LEN]; /* the user's name */
bool dba_password_entered; /* user name entered flag */
bool dba_password_specified; /* database specified flag */

View File

@ -52,6 +52,9 @@ const int IN_SW_GSEC_DBA_PASSWORD = 18; /* Database Admin. Password */
const int IN_SW_GSEC_SQL_ROLE_NAME = 19; /* SQL Role to assume */
const int IN_SW_GSEC_AMBIG = 20; /* ambiguous switch */
const int IN_SW_GSEC_USERNAME = 21; /* placeholder for the username */
#ifdef TRUSTED_SERVICES
const int IN_SW_GSEC_DBA_TRUST_USER = 22; /* Database Admin. Trusted User name */
#endif
static struct in_sw_tab_t gsec_in_sw_table [] = {
@ -74,6 +77,9 @@ static struct in_sw_tab_t gsec_in_sw_table [] = {
{IN_SW_GSEC_DBA_USER_NAME, 0, "USER", 0, 0, 0, FALSE, 0, 1, NULL}, /* Database Admin. User name */
{IN_SW_GSEC_DBA_PASSWORD, 0, "PASSWORD", 0, 0, 0, FALSE, 0, 2, NULL}, /* Database Admin. Password */
{IN_SW_GSEC_SQL_ROLE_NAME, isc_spb_sql_role_name, "ROLE", 0, 0, 0, FALSE, 0, 2, NULL}, /* SQL Role to assume */
#ifdef TRUSTED_SERVICES
{IN_SW_GSEC_DBA_TRUST_USER, 0, "TRUSTED", 0, 0, 0, FALSE, 0, 1, NULL}, /* Database Admin. Trusted User name */
#endif
{IN_SW_GSEC_0, 0, NULL, 0, 0, 0, FALSE, 0, 0, NULL} /* End of List */
};

View File

@ -326,8 +326,15 @@ int CLIB_ROUTINE main(int argc, char** argv)
bool sw_nocreation = false;
isc_db_handle db_handle = 0;
UCHAR buf[256];
UCHAR pass_buff[128], user_buff[128], *password = pass_buff, *username =
user_buff;
UCHAR pass_buff[128], user_buff[128], *password = pass_buff, *username = user_buff;
MOVE_CLEAR(user_buff, sizeof(user_buff));
MOVE_CLEAR(pass_buff, sizeof(pass_buff));
#ifdef TRUSTED_SERVICES
UCHAR tr_buff[128], *tr_user = tr_buff;
MOVE_CLEAR(tr_buff, sizeof(tr_buff));
#endif
tdba thd_context, *tddba;
tdba::putSpecific(tddba, &thd_context);
@ -403,9 +410,6 @@ int CLIB_ROUTINE main(int argc, char** argv)
}
const char* name = NULL;
MOVE_CLEAR(user_buff, sizeof(user_buff));
MOVE_CLEAR(pass_buff, sizeof(pass_buff));
const TEXT* const* const end = argv + argc;
++argv;
while (argv < end) {
@ -449,12 +453,18 @@ int CLIB_ROUTINE main(int argc, char** argv)
break;
case IN_SW_DBA_USERNAME:
if (argv < end)
strcpy((char*) username, *argv++);
strncpy((char*) username, *argv++, sizeof(user_buff) - 1);
break;
case IN_SW_DBA_PASSWORD:
if (argv < end)
strcpy((char*) password, *argv++);
strncpy((char*) password, *argv++, sizeof(pass_buff) - 1);
break;
#ifdef TRUSTED_SERVICES
case IN_SW_DBA_TRUSTEDUSER:
if (argv < end)
strncpy((char*) tr_user, *argv++, sizeof(tr_buff) - 1);
break;
#endif
case IN_SW_DBA_SYSTEM:
sw_system = true;
break;
@ -656,13 +666,21 @@ int CLIB_ROUTINE main(int argc, char** argv)
dpb.insertTag(isc_dpb_gstat_attach);
dpb.insertTag(isc_dpb_no_garbage_collect);
if (*username) {
if (*username)
{
dpb.insertBytes(isc_dpb_user_name, username, strlen((char*) username));
}
if (*password) {
if (*password)
{
dpb.insertBytes(called_as_service ? isc_dpb_password_enc : isc_dpb_password,
password, strlen((char*) password));
}
#ifdef TRUSTED_SERVICES
if (*tr_user)
{
dpb.insertBytes(isc_dpb_trusted_auth, tr_user, strlen((char*) tr_user));
}
#endif
isc_attach_database(status_vector, 0, name, &DB, dpb.getBufferLength(),
reinterpret_cast<const char*>(dpb.getBuffer()));

View File

@ -43,6 +43,9 @@ const int IN_SW_DBA_PASSWORD = 9; /* password */
const int IN_SW_DBA_RECORD = 10; /* analyze record versions */
const int IN_SW_DBA_RELATION = 11; /* analyze specific relations */
const int IN_SW_DBA_NOCREATION = 12; /* don't print creation date */
#ifdef TRUSTED_SERVICES
const int IN_SW_DBA_TRUSTEDUSER = 13; /* trusted user name */
#endif
static struct in_sw_tab_t dba_in_sw_table [] = {
{IN_SW_DBA_DATAIDX, 0, "ALL", 0,0,0, FALSE, 22, 0, NULL}, /* msg 22: -a analyze data and index pages */
@ -58,6 +61,9 @@ static struct in_sw_tab_t dba_in_sw_table [] = {
{IN_SW_DBA_VERSION, 0, "Z", 0,0,0, FALSE, 28, 0, NULL}, /* msg 28: -z display version number */
// special switch to avoid including creation date, only for tests (no message)
{IN_SW_DBA_NOCREATION, isc_spb_sts_nocreation, "NOCREATION", 0,0,0, FALSE, 0, 0, NULL}, /* msg 35: -n suppress creation date */
#ifdef TRUSTED_SERVICES
{IN_SW_DBA_TRUSTEDUSER, 0, "TRUSTED", 0,0,0, FALSE, 0, 0, NULL}, /* msg 0 - ignored */
#endif
{IN_SW_DBA_0, 0, NULL, 0,0,0, FALSE, 0, 0, NULL} /* End of List */
};
#endif /* DBA_DBASWI_H */