8
0
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:
alexpeshkoff 2013-12-06 17:10:10 +00:00
parent 366a58e3a7
commit 40de1dabb0
14 changed files with 484 additions and 184 deletions

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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();

View File

@ -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

View File

@ -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>

View File

@ -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,

View File

@ -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
{

View File

@ -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;

View File

@ -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);
}

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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)