mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-02-02 10:40:38 +01:00
Implemented CORE-4290: Extensible property support which can add properties (name-value pairs) to users
This commit is contained in:
parent
366a58e3a7
commit
40de1dabb0
@ -91,12 +91,19 @@ private:
|
||||
unsigned fieldCount;
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
bool Message::checkType<SLONG>(unsigned t, unsigned sz)
|
||||
{
|
||||
return t == SQL_LONG && sz == sizeof(SLONG);
|
||||
}
|
||||
|
||||
template <>
|
||||
bool Message::checkType<ISC_QUAD>(unsigned t, unsigned sz)
|
||||
{
|
||||
return (t == SQL_BLOB || t == SQL_QUAD) && sz == sizeof(ISC_QUAD);
|
||||
}
|
||||
|
||||
|
||||
// With template magic, we make the fields strongly-typed.
|
||||
template <typename T>
|
||||
@ -151,6 +158,11 @@ public:
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
T* operator&()
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
|
||||
T operator= (T newVal)
|
||||
{
|
||||
*ptr = newVal;
|
||||
|
@ -46,65 +46,9 @@ const unsigned int SZ_LOGIN = 31;
|
||||
const unsigned int SZ_NAME = 31;
|
||||
typedef Field<Varying> Varfield;
|
||||
typedef Field<Text> Name;
|
||||
typedef Field<ISC_QUAD> Blob;
|
||||
|
||||
void setField(Name& to, Auth::ICharUserField* from)
|
||||
{
|
||||
if (from->entered())
|
||||
{
|
||||
to = from->get();
|
||||
}
|
||||
else
|
||||
{
|
||||
to.null = FB_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void allocField(Auth::ICharUserField* value, Firebird::string& update, const char* name)
|
||||
{
|
||||
if (value->entered() || value->specified())
|
||||
{
|
||||
update += ' ';
|
||||
update += name;
|
||||
update += "=?,";
|
||||
}
|
||||
}
|
||||
|
||||
void allocField(Firebird::AutoPtr<Name>& field, Message& up, Auth::ICharUserField* value, const char* name)
|
||||
{
|
||||
if (value->entered() || value->specified())
|
||||
{
|
||||
field = new Name(up);
|
||||
}
|
||||
}
|
||||
|
||||
void assignField(Firebird::AutoPtr<Name>& field, Auth::ICharUserField* name)
|
||||
{
|
||||
if (field.hasData())
|
||||
{
|
||||
if (name->entered())
|
||||
{
|
||||
*field = name->get();
|
||||
field->null = FB_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
fb_assert(name->specified());
|
||||
field->null = FB_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void listField(Auth::ICharUserField* to, Name& from)
|
||||
{
|
||||
to->setEntered(from.null ? 0 : 1);
|
||||
if (!from.null)
|
||||
{
|
||||
to->set(from);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
namespace Auth {
|
||||
|
||||
@ -122,17 +66,21 @@ public:
|
||||
"PLG$VERIFIER VARCHAR(128) CHARACTER SET OCTETS NOT NULL, "
|
||||
"PLG$SALT VARCHAR(32) CHARACTER SET OCTETS NOT NULL, "
|
||||
"PLG$COMMENT RDB$DESCRIPTION, PLG$FIRST SEC$NAME_PART, "
|
||||
"PLG$MIDDLE SEC$NAME_PART, PLG$LAST SEC$NAME_PART)"
|
||||
"PLG$MIDDLE SEC$NAME_PART, PLG$LAST SEC$NAME_PART, "
|
||||
"PLG$ATTRIBUTES RDB$DESCRIPTION)"
|
||||
,
|
||||
"CREATE VIEW PLG$SRP_VIEW AS "
|
||||
"SELECT PLG$USER_NAME, PLG$VERIFIER, PLG$SALT, PLG$COMMENT, PLG$FIRST, PLG$MIDDLE, PLG$LAST "
|
||||
"FROM PLG$SRP WHERE CURRENT_USER = 'SYSDBA' OR CURRENT_ROLE = 'RDB$ADMIN' OR CURRENT_USER = PLG$SRP.PLG$USER_NAME"
|
||||
"SELECT PLG$USER_NAME, PLG$VERIFIER, PLG$SALT, PLG$COMMENT, "
|
||||
" PLG$FIRST, PLG$MIDDLE, PLG$LAST, PLG$ATTRIBUTES "
|
||||
"FROM PLG$SRP WHERE CURRENT_USER = 'SYSDBA' "
|
||||
" OR CURRENT_ROLE = 'RDB$ADMIN' OR CURRENT_USER = PLG$SRP.PLG$USER_NAME"
|
||||
,
|
||||
"GRANT ALL ON PLG$SRP to VIEW PLG$SRP_VIEW"
|
||||
,
|
||||
"GRANT SELECT ON PLG$SRP_VIEW to PUBLIC"
|
||||
,
|
||||
"GRANT UPDATE(PLG$VERIFIER, PLG$SALT, PLG$FIRST, PLG$MIDDLE, PLG$LAST) ON PLG$SRP_VIEW TO PUBLIC"
|
||||
"GRANT UPDATE(PLG$VERIFIER, PLG$SALT, PLG$FIRST, PLG$MIDDLE, PLG$LAST, "
|
||||
" PLG$COMMENT, PLG$ATTRIBUTES) ON PLG$SRP_VIEW TO PUBLIC"
|
||||
,
|
||||
NULL
|
||||
};
|
||||
@ -260,8 +208,8 @@ public:
|
||||
case ADD_OPER:
|
||||
{
|
||||
const char* insert =
|
||||
"INSERT INTO plg$srp_view(PLG$USER_NAME, PLG$VERIFIER, PLG$SALT, PLG$FIRST, PLG$MIDDLE, PLG$LAST) "
|
||||
"VALUES(?, ?, ?, ?, ?, ?)";
|
||||
"INSERT INTO plg$srp_view(PLG$USER_NAME, PLG$VERIFIER, PLG$SALT, PLG$FIRST, PLG$MIDDLE, PLG$LAST, "
|
||||
"PLG$COMMENT, PLG$ATTRIBUTES) VALUES(?, ?, ?, ?, ?, ?, ?, ?)";
|
||||
|
||||
Firebird::IStatement* stmt = NULL;
|
||||
try
|
||||
@ -305,11 +253,14 @@ public:
|
||||
Name login(add);
|
||||
Varfield verifier(add), slt(add);
|
||||
Name first(add), middle(add), last(add);
|
||||
Blob comment(add), attr(add);
|
||||
|
||||
setField(login, user->userName());
|
||||
setField(first, user->firstName());
|
||||
setField(middle, user->middleName());
|
||||
setField(last, user->lastName());
|
||||
setField(status, comment, user->comment());
|
||||
setField(status, attr, user->attributes());
|
||||
|
||||
#if SRP_DEBUG > 1
|
||||
Firebird::BigInteger salt("02E268803000000079A478A700000002D1A6979000000026E1601C000000054F");
|
||||
@ -359,9 +310,12 @@ public:
|
||||
}
|
||||
|
||||
Firebird::AutoPtr<Name> first, middle, last;
|
||||
Firebird::AutoPtr<Blob> comment, attr;
|
||||
allocField(user->firstName(), update, "PLG$FIRST");
|
||||
allocField(user->middleName(), update, "PLG$MIDDLE");
|
||||
allocField(user->lastName(), update, "PLG$LAST");
|
||||
allocField(user->comment(), update, "PLG$COMMENT");
|
||||
allocField(user->attributes(), update, "PLG$ATTRIBUTES");
|
||||
|
||||
if (update[update.length() - 1] != ',')
|
||||
{
|
||||
@ -407,12 +361,16 @@ public:
|
||||
allocField(first, up, user->firstName(), "PLG$FIRST");
|
||||
allocField(middle, up, user->middleName(), "PLG$MIDDLE");
|
||||
allocField(last, up, user->lastName(), "PLG$LAST");
|
||||
allocField(comment, up, user->comment(), "PLG$COMMENT");
|
||||
allocField(attr, up, user->attributes(), "PLG$ATTRIBUTES");
|
||||
|
||||
Name login(up);
|
||||
|
||||
assignField(first, user->firstName());
|
||||
assignField(middle, user->middleName());
|
||||
assignField(last, user->lastName());
|
||||
assignField(status, comment, user->comment());
|
||||
assignField(status, attr, user->attributes());
|
||||
setField(login, user->userName());
|
||||
|
||||
stmt->execute(status, tra, up.metadata, up.buffer, NULL, NULL);
|
||||
@ -478,12 +436,7 @@ public:
|
||||
case OLD_DIS_OPER:
|
||||
case DIS_OPER:
|
||||
{
|
||||
user->uid()->setEntered(0);
|
||||
user->gid()->setEntered(0);
|
||||
user->groupName()->setEntered(0);
|
||||
user->password()->setEntered(0);
|
||||
|
||||
Firebird::string disp = "SELECT PLG$USER_NAME, PLG$FIRST, PLG$MIDDLE, PLG$LAST, "
|
||||
Firebird::string disp = "SELECT PLG$USER_NAME, PLG$FIRST, PLG$MIDDLE, PLG$LAST, PLG$COMMENT, PLG$ATTRIBUTES, "
|
||||
" CASE WHEN RDB$RELATION_NAME IS NULL THEN 0 ELSE 1 END "
|
||||
"FROM PLG$SRP_VIEW LEFT JOIN RDB$USER_PRIVILEGES "
|
||||
" ON PLG$SRP_VIEW.PLG$USER_NAME = RDB$USER_PRIVILEGES.RDB$USER "
|
||||
@ -506,6 +459,7 @@ public:
|
||||
Message di(om);
|
||||
Name login(di);
|
||||
Name first(di), middle(di), last(di);
|
||||
Field<ISC_QUAD> comment(di), attr(di);
|
||||
Field<SLONG> admin(di);
|
||||
|
||||
Firebird::AutoPtr<Message> par;
|
||||
@ -529,6 +483,8 @@ public:
|
||||
listField(user->firstName(), first);
|
||||
listField(user->middleName(), middle);
|
||||
listField(user->lastName(), last);
|
||||
listField(status, user->comment(), comment);
|
||||
listField(status, user->attributes(), attr);
|
||||
user->admin()->set(admin);
|
||||
|
||||
callback->list(user);
|
||||
@ -645,7 +601,7 @@ private:
|
||||
return newCount == oldCount + 1;
|
||||
}
|
||||
|
||||
void check(Firebird::IStatus* status)
|
||||
static void check(Firebird::IStatus* status)
|
||||
{
|
||||
if (!status->isSuccess())
|
||||
{
|
||||
@ -653,6 +609,154 @@ private:
|
||||
Firebird::status_exception::raise(status->get());
|
||||
}
|
||||
}
|
||||
|
||||
static void setField(Name& to, Auth::ICharUserField* from)
|
||||
{
|
||||
if (from->entered())
|
||||
{
|
||||
to = from->get();
|
||||
}
|
||||
else
|
||||
{
|
||||
to.null = FB_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
void setField(Firebird::IStatus* st, Blob& to, Auth::ICharUserField* from)
|
||||
{
|
||||
if (from->entered())
|
||||
{
|
||||
blobWrite(st, to, from);
|
||||
}
|
||||
else
|
||||
{
|
||||
to.null = FB_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static void allocField(Auth::ICharUserField* value, Firebird::string& update, const char* name)
|
||||
{
|
||||
if (value->entered() || value->specified())
|
||||
{
|
||||
update += ' ';
|
||||
update += name;
|
||||
update += "=?,";
|
||||
}
|
||||
}
|
||||
|
||||
template <typename FT>
|
||||
static void allocField(Firebird::AutoPtr<FT>& field, Message& up, Auth::ICharUserField* value, const char* name)
|
||||
{
|
||||
if (value->entered() || value->specified())
|
||||
{
|
||||
field = new FT(up);
|
||||
}
|
||||
}
|
||||
|
||||
static void assignField(Firebird::AutoPtr<Name>& field, Auth::ICharUserField* name)
|
||||
{
|
||||
if (field.hasData())
|
||||
{
|
||||
if (name->entered())
|
||||
{
|
||||
*field = name->get();
|
||||
}
|
||||
else
|
||||
{
|
||||
fb_assert(name->specified());
|
||||
field->null = FB_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void assignField(Firebird::IStatus* st, Firebird::AutoPtr<Blob>& field, Auth::ICharUserField* name)
|
||||
{
|
||||
if (field.hasData())
|
||||
{
|
||||
if (name->entered())
|
||||
{
|
||||
blobWrite(st, *field, name);
|
||||
field->null = FB_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
fb_assert(name->specified());
|
||||
field->null = FB_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void listField(Auth::ICharUserField* to, Name& from)
|
||||
{
|
||||
to->setEntered(from.null ? 0 : 1);
|
||||
if (!from.null)
|
||||
{
|
||||
to->set(from);
|
||||
}
|
||||
}
|
||||
|
||||
void listField(Firebird::IStatus* st, Auth::ICharUserField* to, Blob& from)
|
||||
{
|
||||
to->setEntered(from.null ? 0 : 1);
|
||||
if (!from.null)
|
||||
{
|
||||
Firebird::string s;
|
||||
Firebird::IBlob* blob = NULL;
|
||||
try
|
||||
{
|
||||
blob = att->openBlob(st, tra, &from);
|
||||
check(st);
|
||||
|
||||
char segbuf[256];
|
||||
unsigned len;
|
||||
while ( (len = blob->getSegment(st, sizeof(segbuf), segbuf)) )
|
||||
{
|
||||
if (st->get()[1] != isc_segment)
|
||||
check(st);
|
||||
s.append(segbuf, len);
|
||||
}
|
||||
if (st->get()[1] != isc_segstr_eof)
|
||||
check(st);
|
||||
|
||||
blob->close(st);
|
||||
check(st);
|
||||
|
||||
to->set(s.c_str());
|
||||
}
|
||||
catch(const Firebird::Exception&)
|
||||
{
|
||||
if (blob)
|
||||
blob->release();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void blobWrite(Firebird::IStatus* st, Blob& to, Auth::ICharUserField* from)
|
||||
{
|
||||
to.null = FB_FALSE;
|
||||
const char* ptr = from->get();
|
||||
unsigned l = strlen(ptr);
|
||||
|
||||
Firebird::IBlob* blob = NULL;
|
||||
try
|
||||
{
|
||||
blob = att->createBlob(st, tra, &to);
|
||||
check(st);
|
||||
|
||||
blob->putSegment(st, l, ptr);
|
||||
check(st);
|
||||
|
||||
blob->close(st);
|
||||
check(st);
|
||||
}
|
||||
catch(const Firebird::Exception&)
|
||||
{
|
||||
if (blob)
|
||||
blob->release();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// register plugin
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "../common/utils_proto.h"
|
||||
#include "../common/classes/init.h"
|
||||
#include "../common/classes/UserBlob.h"
|
||||
#include "../common/config/config_file.h"
|
||||
#include "../auth/SecurityDatabase/LegacyManagement.h"
|
||||
#include "../common/classes/ImplementHelper.h"
|
||||
#include "../common/classes/ClumpletWriter.h"
|
||||
@ -365,27 +366,32 @@ int FB_CARG SecurityDatabaseManagement::execute(Firebird::IStatus* st, IUser* us
|
||||
|
||||
STORE (TRANSACTION_HANDLE transaction REQUEST_HANDLE request) U IN PLG$VIEW_USERS USING
|
||||
STR_STORE(U.PLG$USER_NAME, user->userName()->get());
|
||||
if (user->uid()->entered())
|
||||
|
||||
U.PLG$UID.NULL = ISC_TRUE;
|
||||
U.PLG$GID.NULL = ISC_TRUE;
|
||||
U.PLG$GROUP_NAME.NULL = ISC_TRUE;
|
||||
if (user->attributes()->entered())
|
||||
{
|
||||
U.PLG$UID = user->uid()->get();
|
||||
U.PLG$UID.NULL = ISC_FALSE;
|
||||
ConfigFile attr(ConfigFile::USE_TEXT, user->attributes()->get());
|
||||
const ConfigFile::Parameter* p;
|
||||
|
||||
if (((p = attr.findParameter("uid"))) && p->value.hasData())
|
||||
{
|
||||
U.PLG$UID = p->asInteger();
|
||||
U.PLG$UID.NULL = ISC_FALSE;
|
||||
}
|
||||
if (((p = attr.findParameter("gid"))) && p->value.hasData())
|
||||
{
|
||||
U.PLG$GID = p->asInteger();
|
||||
U.PLG$GID.NULL = ISC_FALSE;
|
||||
}
|
||||
if (((p = attr.findParameter("groupName"))) && p->value.hasData())
|
||||
{
|
||||
STR_STORE(U.PLG$GROUP_NAME, p->value.c_str());
|
||||
U.PLG$GROUP_NAME.NULL = ISC_FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
U.PLG$UID.NULL = ISC_TRUE;
|
||||
if (user->gid()->entered())
|
||||
{
|
||||
U.PLG$GID = user->gid()->get();
|
||||
U.PLG$GID.NULL = ISC_FALSE;
|
||||
}
|
||||
else
|
||||
U.PLG$GID.NULL = ISC_TRUE;
|
||||
if (user->groupName()->entered())
|
||||
{
|
||||
STR_STORE(U.PLG$GROUP_NAME, user->groupName()->get());
|
||||
U.PLG$GROUP_NAME.NULL = ISC_FALSE;
|
||||
}
|
||||
else
|
||||
U.PLG$GROUP_NAME.NULL = ISC_TRUE;
|
||||
|
||||
if (user->password()->entered())
|
||||
{
|
||||
ENC_crypt(encrypted1, sizeof encrypted1, user->password()->get(), LEGACY_PASSWORD_SALT);
|
||||
@ -437,29 +443,44 @@ int FB_CARG SecurityDatabaseManagement::execute(Firebird::IStatus* st, IUser* us
|
||||
{
|
||||
found = true;
|
||||
MODIFY U USING
|
||||
if (user->uid()->entered())
|
||||
if (user->attributes()->entered())
|
||||
{
|
||||
U.PLG$UID = user->uid()->get();
|
||||
U.PLG$UID.NULL = ISC_FALSE;
|
||||
}
|
||||
else if (user->uid()->specified())
|
||||
U.PLG$UID.NULL = ISC_TRUE;
|
||||
ConfigFile attr(ConfigFile::USE_TEXT, user->attributes()->get());
|
||||
const ConfigFile::Parameter* p;
|
||||
|
||||
if (user->gid()->entered())
|
||||
{
|
||||
U.PLG$GID = user->gid()->get();
|
||||
U.PLG$GID.NULL = ISC_FALSE;
|
||||
}
|
||||
else if (user->gid()->specified())
|
||||
U.PLG$GID.NULL = ISC_TRUE;
|
||||
if ((p = attr.findParameter("uid")))
|
||||
{
|
||||
if (p->value.hasData())
|
||||
{
|
||||
U.PLG$UID = p->asInteger();
|
||||
U.PLG$UID.NULL = ISC_FALSE;
|
||||
}
|
||||
else
|
||||
U.PLG$UID.NULL = ISC_TRUE;
|
||||
}
|
||||
|
||||
if (user->groupName()->entered())
|
||||
{
|
||||
STR_STORE(U.PLG$GROUP_NAME, user->groupName()->get());
|
||||
U.PLG$GROUP_NAME.NULL = ISC_FALSE;
|
||||
if ((p = attr.findParameter("gid")))
|
||||
{
|
||||
if (p->value.hasData())
|
||||
{
|
||||
U.PLG$GID = p->asInteger();
|
||||
U.PLG$GID.NULL = ISC_FALSE;
|
||||
}
|
||||
else
|
||||
U.PLG$GID.NULL = ISC_TRUE;
|
||||
}
|
||||
|
||||
if ((p = attr.findParameter("groupName")))
|
||||
{
|
||||
if (p->value.hasData())
|
||||
{
|
||||
STR_STORE(U.PLG$GROUP_NAME, p->value.c_str());
|
||||
U.PLG$GROUP_NAME.NULL = ISC_FALSE;
|
||||
}
|
||||
else
|
||||
U.PLG$GROUP_NAME.NULL = ISC_TRUE;
|
||||
}
|
||||
}
|
||||
else if (user->groupName()->specified())
|
||||
U.PLG$GROUP_NAME.NULL = ISC_TRUE;
|
||||
|
||||
if (user->password()->entered())
|
||||
{
|
||||
@ -555,15 +576,20 @@ int FB_CARG SecurityDatabaseManagement::execute(Firebird::IStatus* st, IUser* us
|
||||
found = false;
|
||||
if (!user->userName()->entered())
|
||||
{
|
||||
Firebird::string attr, a1, a2, a3;
|
||||
FOR (TRANSACTION_HANDLE transaction REQUEST_HANDLE request) U IN PLG$VIEW_USERS
|
||||
user->uid()->set(U.PLG$UID);
|
||||
user->uid()->setEntered(U.PLG$UID.NULL ? 0 : 1);
|
||||
user->gid()->set(U.PLG$GID);
|
||||
user->gid()->setEntered(U.PLG$GID.NULL ? 0 : 1);
|
||||
if (!U.PLG$UID.NULL)
|
||||
a1.printf("Uid=%d\n", U.PLG$UID);
|
||||
if (!U.PLG$GID.NULL)
|
||||
a2.printf("Gid=%d\n", U.PLG$GID);
|
||||
if (!U.PLG$GROUP_NAME.NULL)
|
||||
a3.printf("GroupName=%s\n", U.PLG$GROUP_NAME);
|
||||
attr = a1 + a2 + a3;
|
||||
user->attributes()->set(attr.c_str());
|
||||
user->attributes()->setEntered(attr.hasData() ? 1 : 0);
|
||||
|
||||
user->userName()->set(U.PLG$USER_NAME);
|
||||
user->userName()->setEntered(U.PLG$USER_NAME.NULL ? 0 : 1);
|
||||
user->groupName()->set(U.PLG$GROUP_NAME);
|
||||
user->groupName()->setEntered(U.PLG$GROUP_NAME.NULL ? 0 : 1);
|
||||
user->password()->set("");
|
||||
user->password()->setEntered(0);
|
||||
user->firstName()->set(U.PLG$FIRST_NAME);
|
||||
@ -595,16 +621,21 @@ int FB_CARG SecurityDatabaseManagement::execute(Firebird::IStatus* st, IUser* us
|
||||
}
|
||||
else
|
||||
{
|
||||
Firebird::string attr, a1, a2, a3;
|
||||
FOR (TRANSACTION_HANDLE transaction REQUEST_HANDLE request) U IN PLG$VIEW_USERS
|
||||
WITH U.PLG$USER_NAME EQ user->userName()->get()
|
||||
user->uid()->set(U.PLG$UID);
|
||||
user->uid()->setEntered(U.PLG$UID.NULL ? 0 : 1);
|
||||
user->gid()->set(U.PLG$GID);
|
||||
user->gid()->setEntered(U.PLG$GID.NULL ? 0 : 1);
|
||||
if (!U.PLG$UID.NULL)
|
||||
a1.printf("Uid=%d\n", U.PLG$UID);
|
||||
if (!U.PLG$GID.NULL)
|
||||
a2.printf("Gid=%d\n", U.PLG$GID);
|
||||
if (!U.PLG$GROUP_NAME.NULL)
|
||||
a3.printf("GroupName=%s\n", U.PLG$GROUP_NAME);
|
||||
attr = a1 + a2 + a3;
|
||||
user->attributes()->set(attr.c_str());
|
||||
user->attributes()->setEntered(attr.hasData() ? 1 : 0);
|
||||
|
||||
user->userName()->set(U.PLG$USER_NAME);
|
||||
user->userName()->setEntered(U.PLG$USER_NAME.NULL ? 0 : 1);
|
||||
user->groupName()->set(U.PLG$GROUP_NAME);
|
||||
user->groupName()->setEntered(U.PLG$GROUP_NAME.NULL ? 0 : 1);
|
||||
user->password()->set("");
|
||||
user->password()->setEntered(0);
|
||||
user->firstName()->set(U.PLG$FIRST_NAME);
|
||||
|
@ -317,6 +317,27 @@ static void userInfoToSpb(char*& spb, Auth::UserData& userData)
|
||||
}
|
||||
|
||||
|
||||
static void setAttr(string& a, const char* nm, Auth::IIntUserField* f)
|
||||
{
|
||||
if (f->entered())
|
||||
{
|
||||
string s;
|
||||
s.printf("%s=%d\n", nm, f->get());
|
||||
a += s;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void setAttr(Auth::UserData* u)
|
||||
{
|
||||
string attr;
|
||||
setAttr(attr, "Uid", &u->u);
|
||||
setAttr(attr, "Gid", &u->g);
|
||||
u->attributes()->setEntered(attr.hasData());
|
||||
u->attributes()->set(attr.c_str());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
||||
callRemoteServiceManager
|
||||
@ -451,6 +472,7 @@ void callRemoteServiceManager(ISC_STATUS* status,
|
||||
|
||||
if (uData.user.get()[0] && callback)
|
||||
{
|
||||
setAttr(&uData);
|
||||
callback->list(&uData);
|
||||
}
|
||||
}
|
||||
@ -532,12 +554,14 @@ static void parseString2(const char*& p, Auth::CharField& f, size_t& loop)
|
||||
|
||||
p += sizeof(USHORT);
|
||||
f.set(p, len);
|
||||
f.setEntered(1);
|
||||
p += len;
|
||||
}
|
||||
|
||||
static void parseLong(const char*& p, Auth::IntField& f, size_t& loop)
|
||||
{
|
||||
f.set(isc_vax_integer(p, sizeof(ULONG)));
|
||||
f.setEntered(1);
|
||||
|
||||
const size_t len2 = sizeof(ULONG) + 1;
|
||||
if (len2 > loop)
|
||||
@ -617,6 +641,7 @@ static int typeBuffer(ISC_STATUS* status, char* buf, int offset,
|
||||
{
|
||||
if (callback)
|
||||
{
|
||||
setAttr(&uData);
|
||||
callback->list(&uData);
|
||||
}
|
||||
uData.clear();
|
||||
|
@ -55,22 +55,30 @@ Get::Get(Config* firebirdConf)
|
||||
void FB_CARG UserData::clear()
|
||||
{
|
||||
op = trustedRole = trustedAuth = 0;
|
||||
|
||||
// interface fields
|
||||
user.clear();
|
||||
pass.clear();
|
||||
first.clear();
|
||||
last.clear();
|
||||
middle.clear();
|
||||
group.clear();
|
||||
u.clear();
|
||||
g.clear();
|
||||
com.clear();
|
||||
attr.clear();
|
||||
adm.clear();
|
||||
|
||||
// internally used fields
|
||||
database.clear();
|
||||
dba.clear();
|
||||
dbaPassword.clear();
|
||||
role.clear();
|
||||
trustedUser.clear();
|
||||
|
||||
// never clear this permanent block! authenticationBlock.clear();
|
||||
|
||||
// internal support for deprecated fields
|
||||
group.clear();
|
||||
u.clear();
|
||||
g.clear();
|
||||
}
|
||||
|
||||
// This function sets typical gsec return code based on requested operation if it was not set by plugin
|
||||
|
@ -180,19 +180,14 @@ public:
|
||||
return &middle;
|
||||
}
|
||||
|
||||
ICharUserField* FB_CARG groupName()
|
||||
ICharUserField* FB_CARG comment()
|
||||
{
|
||||
return &group;
|
||||
return &com;
|
||||
}
|
||||
|
||||
IIntUserField* FB_CARG uid()
|
||||
ICharUserField* FB_CARG attributes()
|
||||
{
|
||||
return &u;
|
||||
}
|
||||
|
||||
IIntUserField* FB_CARG gid()
|
||||
{
|
||||
return &g;
|
||||
return &attr;
|
||||
}
|
||||
|
||||
IIntUserField* FB_CARG admin()
|
||||
@ -205,10 +200,14 @@ public:
|
||||
typedef Firebird::Array<UCHAR> AuthenticationBlock;
|
||||
|
||||
int op, trustedRole, trustedAuth;
|
||||
CharField user, pass, first, last, middle, group;
|
||||
IntField u, g, adm;
|
||||
CharField user, pass, first, last, middle, com, attr;
|
||||
IntField adm;
|
||||
CharField database, dba, dbaPassword, role, trustedUser;
|
||||
AuthenticationBlock authenticationBlock;
|
||||
|
||||
// deprecated
|
||||
CharField group;
|
||||
IntField u, g;
|
||||
};
|
||||
|
||||
class StackUserData FB_FINAL : public Firebird::AutoIface<UserData, FB_AUTH_USER_VERSION>
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
/* Domain definitions */
|
||||
CREATE DOMAIN PLG$PASSWD AS VARCHAR(64) CHARACTER SET BINARY;
|
||||
CREATE DOMAIN PLG$ID AS INTEGER;
|
||||
|
||||
COMMIT;
|
||||
|
||||
@ -38,8 +39,8 @@ COMMIT;
|
||||
CREATE TABLE PLG$USERS (
|
||||
PLG$USER_NAME SEC$USER_NAME NOT NULL PRIMARY KEY,
|
||||
PLG$GROUP_NAME SEC$USER_NAME,
|
||||
PLG$UID SEC$UID,
|
||||
PLG$GID SEC$GID,
|
||||
PLG$UID PLG$ID,
|
||||
PLG$GID PLG$ID,
|
||||
PLG$PASSWD PLG$PASSWD NOT NULL,
|
||||
PLG$COMMENT RDB$DESCRIPTION,
|
||||
PLG$FIRST_NAME SEC$NAME_PART,
|
||||
|
@ -126,15 +126,15 @@ public:
|
||||
virtual ICharUserField* FB_CARG firstName() = 0;
|
||||
virtual ICharUserField* FB_CARG lastName() = 0;
|
||||
virtual ICharUserField* FB_CARG middleName() = 0;
|
||||
virtual ICharUserField* FB_CARG groupName() = 0;
|
||||
|
||||
virtual IIntUserField* FB_CARG uid() = 0;
|
||||
virtual IIntUserField* FB_CARG gid() = 0;
|
||||
virtual ICharUserField* FB_CARG comment() = 0;
|
||||
virtual ICharUserField* FB_CARG attributes() = 0;
|
||||
|
||||
virtual IIntUserField* FB_CARG admin() = 0;
|
||||
|
||||
virtual void FB_CARG clear() = 0;
|
||||
};
|
||||
#define FB_AUTH_USER_VERSION (FB_VERSIONED_VERSION + 11)
|
||||
#define FB_AUTH_USER_VERSION (FB_VERSIONED_VERSION + 10)
|
||||
|
||||
class IListUsers : public Firebird::IVersioned
|
||||
{
|
||||
|
@ -606,11 +606,10 @@
|
||||
// Relation 43 (SEC$USERS)
|
||||
|
||||
const USHORT f_sec_user_name = 0;
|
||||
const USHORT f_sec_group_name = 1;
|
||||
const USHORT f_sec_uid = 2;
|
||||
const USHORT f_sec_gid = 3;
|
||||
const USHORT f_sec_first_name = 4;
|
||||
const USHORT f_sec_middle_name = 5;
|
||||
const USHORT f_sec_last_name = 6;
|
||||
const USHORT f_sec_first_name = 1;
|
||||
const USHORT f_sec_middle_name = 2;
|
||||
const USHORT f_sec_last_name = 3;
|
||||
const USHORT f_sec_attributes = 4;
|
||||
const USHORT f_sec_comment = 5;
|
||||
|
||||
|
||||
|
@ -238,29 +238,6 @@ void UserManagement::list(Auth::IUser* u)
|
||||
attachment_charset);
|
||||
}
|
||||
|
||||
if (u->groupName()->entered())
|
||||
{
|
||||
putField(threadDbb, record,
|
||||
DumpField(f_sec_group_name, VALUE_STRING, strlen(u->groupName()->get()), u->groupName()->get()),
|
||||
attachment_charset);
|
||||
}
|
||||
|
||||
if (u->uid()->entered())
|
||||
{
|
||||
int tmp = u->uid()->get();
|
||||
putField(threadDbb, record,
|
||||
DumpField(f_sec_uid, VALUE_INTEGER, sizeof(int), &tmp),
|
||||
attachment_charset);
|
||||
}
|
||||
|
||||
if (u->gid()->entered())
|
||||
{
|
||||
int tmp = u->gid()->get();
|
||||
putField(threadDbb, record,
|
||||
DumpField(f_sec_gid, VALUE_INTEGER, sizeof(int), &tmp),
|
||||
attachment_charset);
|
||||
}
|
||||
|
||||
if (u->firstName()->entered())
|
||||
{
|
||||
putField(threadDbb, record,
|
||||
@ -282,6 +259,20 @@ void UserManagement::list(Auth::IUser* u)
|
||||
attachment_charset);
|
||||
}
|
||||
|
||||
if (u->attributes()->entered())
|
||||
{
|
||||
putField(threadDbb, record,
|
||||
DumpField(f_sec_attributes, VALUE_STRING, strlen(u->attributes()->get()), u->attributes()->get()),
|
||||
attachment_charset);
|
||||
}
|
||||
|
||||
if (u->comment()->entered())
|
||||
{
|
||||
putField(threadDbb, record,
|
||||
DumpField(f_sec_comment, VALUE_STRING, strlen(u->comment()->get()), u->comment()->get()),
|
||||
attachment_charset);
|
||||
}
|
||||
|
||||
buffer->store(record);
|
||||
}
|
||||
|
||||
|
@ -168,8 +168,6 @@
|
||||
FIELD(fld_identity_type , nam_identity_type , dtype_short , sizeof(SSHORT) , 0 , NULL , true)
|
||||
|
||||
FIELD(fld_user_name , nam_user_name , dtype_text , MAX_SQL_IDENTIFIER_LEN , dsc_text_type_metadata , NULL , true)
|
||||
FIELD(fld_uid , nam_uid , dtype_long , sizeof(SLONG) , 0 , NULL , true)
|
||||
FIELD(fld_gid , nam_gid , dtype_long , sizeof(SLONG) , 0 , NULL , true)
|
||||
FIELD(fld_name_part , nam_name_part , dtype_text , 32 , dsc_text_type_metadata , NULL , true)
|
||||
FIELD(fld_client_ver , nam_client_ver , dtype_varying , 255 , dsc_text_type_ascii , NULL , true)
|
||||
FIELD(fld_remote_ver , nam_remote_ver , dtype_varying , 255 , dsc_text_type_ascii , NULL , true)
|
||||
|
@ -266,13 +266,12 @@ NAME("RDB$IDENTITY_TYPE", nam_identity_type)
|
||||
NAME("RDB$AUTH_METHOD", nam_auth_method)
|
||||
|
||||
NAME("SEC$USER_NAME", nam_user_name)
|
||||
NAME("SEC$GROUP_NAME", nam_group_name)
|
||||
NAME("SEC$UID", nam_uid)
|
||||
NAME("SEC$GID", nam_gid)
|
||||
NAME("SEC$FIRST_NAME", nam_first_name)
|
||||
NAME("SEC$MIDDLE_NAME", nam_middle_name)
|
||||
NAME("SEC$LAST_NAME", nam_last_name)
|
||||
NAME("SEC$NAME_PART", nam_name_part)
|
||||
NAME("SEC$ATTRIBUTES", nam_attributes)
|
||||
NAME("SEC$DESCRIPTION", nam_sec_description)
|
||||
|
||||
NAME("MON$ATTACHMENTS", nam_mon_attachments)
|
||||
NAME("MON$ATTACHMENT_ID", nam_mon_att_id)
|
||||
|
@ -605,10 +605,9 @@ END_RELATION
|
||||
// Relation 43 (SEC$USERS)
|
||||
RELATION(nam_sec_users, rel_sec_users, ODS_12_0, rel_virtual)
|
||||
FIELD(f_sec_user_name, nam_user_name, fld_user, 1, ODS_12_0)
|
||||
FIELD(f_sec_group_name, nam_group_name, fld_user, 1, ODS_12_0)
|
||||
FIELD(f_sec_uid, nam_uid, fld_uid, 1, ODS_12_0)
|
||||
FIELD(f_sec_gid, nam_gid, fld_gid, 1, ODS_12_0)
|
||||
FIELD(f_sec_first_name, nam_first_name, fld_name_part, 1, ODS_12_0)
|
||||
FIELD(f_sec_middle_name, nam_middle_name, fld_name_part, 1, ODS_12_0)
|
||||
FIELD(f_sec_last_name, nam_last_name, fld_name_part, 1, ODS_12_0)
|
||||
FIELD(f_sec_attributes, nam_attributes, fld_description, 1, ODS_12_0)
|
||||
FIELD(f_sec_comment, nam_sec_description, fld_description, 1, ODS_12_0)
|
||||
END_RELATION
|
||||
|
@ -100,6 +100,52 @@ THREAD_ENTRY_DECLARE GSEC_main(THREAD_ENTRY_PARAM arg)
|
||||
return (THREAD_ENTRY_RETURN)(IPTR) exit_code;
|
||||
}
|
||||
|
||||
|
||||
static void setAttr(Firebird::string& attr, Auth::ICharUserField* field)
|
||||
{
|
||||
attr = field->get();
|
||||
}
|
||||
|
||||
static void setAttr(Firebird::string& attr, Auth::IIntUserField* field)
|
||||
{
|
||||
attr.printf("%d", field->get());
|
||||
}
|
||||
|
||||
template <typename I>
|
||||
static void setAttr(Firebird::string& attr, const char* name, I* field)
|
||||
{
|
||||
Firebird::string s;
|
||||
if (field->entered())
|
||||
{
|
||||
setAttr(s, field);
|
||||
}
|
||||
else if (!field->specified())
|
||||
{
|
||||
return;
|
||||
}
|
||||
attr += name;
|
||||
attr += '=';
|
||||
attr += s;
|
||||
attr += '\n';
|
||||
}
|
||||
|
||||
static bool fieldSet(Auth::IUserField* field)
|
||||
{
|
||||
return field->entered() || field->specified();
|
||||
}
|
||||
|
||||
static void merge(Auth::IIntUserField* to, Auth::IIntUserField* from)
|
||||
{
|
||||
if (fieldSet(to))
|
||||
return;
|
||||
if (from->entered())
|
||||
{
|
||||
to->set(from->get());
|
||||
to->setEntered(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int gsec(Firebird::UtilSvc* uSvc)
|
||||
{
|
||||
/**************************************
|
||||
@ -342,6 +388,30 @@ int gsec(Firebird::UtilSvc* uSvc)
|
||||
}
|
||||
}
|
||||
|
||||
class Attributes : public ConfigFile
|
||||
{
|
||||
public:
|
||||
Attributes(Auth::IUser* data)
|
||||
: ConfigFile(USE_TEXT, data->attributes()->entered() ? data->attributes()->get() : "")
|
||||
{ }
|
||||
|
||||
int operator[](const char* name)
|
||||
{
|
||||
const Parameter* p = findParameter(name);
|
||||
return p ? int(p->asInteger()) : 0;
|
||||
}
|
||||
|
||||
void set(Auth::IIntUserField* field, const char* name)
|
||||
{
|
||||
const Parameter* p = findParameter(name);
|
||||
if (p)
|
||||
{
|
||||
field->set(p->asInteger());
|
||||
field->setEntered(1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class Display : public Firebird::AutoIface<Auth::IListUsers, FB_AUTH_LIST_USERS_VERSION>
|
||||
{
|
||||
public:
|
||||
@ -352,14 +422,16 @@ int gsec(Firebird::UtilSvc* uSvc)
|
||||
// IListUsers implementation
|
||||
void FB_CARG list(Auth::IUser* data)
|
||||
{
|
||||
Attributes attr(data);
|
||||
|
||||
if (tdsec->utilSvc->isService())
|
||||
{
|
||||
tdsec->utilSvc->putLine(isc_spb_sec_username, data->userName()->get());
|
||||
tdsec->utilSvc->putLine(isc_spb_sec_firstname, data->firstName()->get());
|
||||
tdsec->utilSvc->putLine(isc_spb_sec_middlename, data->middleName()->get());
|
||||
tdsec->utilSvc->putLine(isc_spb_sec_lastname, data->lastName()->get());
|
||||
tdsec->utilSvc->putSLong(isc_spb_sec_userid, data->uid()->get());
|
||||
tdsec->utilSvc->putSLong(isc_spb_sec_groupid, data->gid()->get());
|
||||
tdsec->utilSvc->putLine(isc_spb_sec_firstname, data->firstName()->entered() ? data->firstName()->get() : "");
|
||||
tdsec->utilSvc->putLine(isc_spb_sec_middlename, data->middleName()->entered() ? data->middleName()->get() : "");
|
||||
tdsec->utilSvc->putLine(isc_spb_sec_lastname, data->lastName()->entered() ? data->lastName()->get() : "");
|
||||
tdsec->utilSvc->putSLong(isc_spb_sec_userid, attr["uid"]);
|
||||
tdsec->utilSvc->putSLong(isc_spb_sec_groupid, attr["gid"]);
|
||||
if (data->operation() == DIS_OPER)
|
||||
{
|
||||
tdsec->utilSvc->putSLong(isc_spb_sec_admin, data->admin()->get());
|
||||
@ -378,7 +450,7 @@ int gsec(Firebird::UtilSvc* uSvc)
|
||||
|
||||
util_output(false, "%-*.*s %5d %5d %-5.5s %s %s %s\n",
|
||||
USERNAME_LENGTH, USERNAME_LENGTH, data->userName()->get(),
|
||||
data->uid()->get(), data->gid()->get(), data->admin()->get() ? "admin" : "",
|
||||
attr["uid"], attr["gid"], data->admin()->get() ? "admin" : "",
|
||||
data->firstName()->get(), data->middleName()->get(), data->lastName()->get());
|
||||
}
|
||||
}
|
||||
@ -389,6 +461,27 @@ int gsec(Firebird::UtilSvc* uSvc)
|
||||
};
|
||||
|
||||
|
||||
class Callback : public Firebird::AutoIface<Auth::IListUsers, FB_AUTH_LIST_USERS_VERSION>
|
||||
{
|
||||
public:
|
||||
explicit Callback(Auth::StackUserData* pu)
|
||||
: u(pu)
|
||||
{ }
|
||||
|
||||
// IListUsers implementation
|
||||
void FB_CARG list(Auth::IUser* data)
|
||||
{
|
||||
Attributes attr(data);
|
||||
|
||||
attr.set(&u->u, "uid");
|
||||
attr.set(&u->g, "gid");
|
||||
}
|
||||
|
||||
private:
|
||||
Auth::StackUserData* u;
|
||||
};
|
||||
|
||||
|
||||
if (!tdsec->tsec_interactive)
|
||||
{
|
||||
if (ret == 0)
|
||||
@ -404,6 +497,47 @@ int gsec(Firebird::UtilSvc* uSvc)
|
||||
if (! useServices)
|
||||
{
|
||||
Firebird::LocalStatus st;
|
||||
|
||||
if (user_data->operation() == MOD_OPER && user_data->userName()->entered() &&
|
||||
(fieldSet(&user_data->u) || fieldSet(&user_data->g) || fieldSet(&user_data->group)))
|
||||
{
|
||||
Auth::StackUserData u;
|
||||
u.op = OLD_DIS_OPER;
|
||||
u.user.set(user_data->userName()->get());
|
||||
u.user.setEntered(1);
|
||||
|
||||
Callback cb(&u);
|
||||
ret = manager->execute(&st, &u, &cb);
|
||||
|
||||
if (ret)
|
||||
{
|
||||
ret = setGsecCode(ret, user_data); // user_data, not u !
|
||||
fb_utils::copyStatus(status, FB_NELEM(status),
|
||||
st.get(), fb_utils::statusLength(st.get()));
|
||||
GSEC_print(ret, user_data->userName()->get());
|
||||
if (status[1])
|
||||
{
|
||||
GSEC_print_status(status);
|
||||
}
|
||||
get_security_error(status, ret);
|
||||
}
|
||||
|
||||
if (!st.isSuccess())
|
||||
{
|
||||
Firebird::status_exception::raise(st.get());
|
||||
}
|
||||
|
||||
merge(&user_data->u, &u.u);
|
||||
merge(&user_data->g, &u.g);
|
||||
}
|
||||
|
||||
Firebird::string attr;
|
||||
setAttr(attr, "uid", &user_data->u);
|
||||
setAttr(attr, "gid", &user_data->g);
|
||||
setAttr(attr, "groupName", &user_data->group);
|
||||
user_data->attributes()->set(attr.c_str());
|
||||
user_data->attributes()->setEntered(attr.hasData() ? 1 : 0);
|
||||
|
||||
ret = manager->execute(&st, user_data, &disp);
|
||||
|
||||
if (ret)
|
||||
|
Loading…
Reference in New Issue
Block a user