openGauss源码解析(196)

openGauss源码解析:安全管理源码解析(7)

9.3.2 角色管理

1. 修改角色属性

修改一个数据库角色可以使用SQL命令ALTER ROLE。角色属性的修改是通过调用AlterRole函数来实现的,该函数只有一个类型为AlterRoleStmt结构的参数。相关代码如下:

typedef struct AlterRoleStmt {

NodeTag type;

char* role; /* 角色的名称 */

List* options; /* 需要修改的属性列表 */

int action; /* +1增加成员关系, -1删除成员关系 */

RoleLockType lockstatus; /* 角色锁定状态 */

} AlterRoleStmt;

修改角色的流程如图9-15所示。

图9-15 openGauss角色管理流程图

调用函数AlterRole修改用户角色属性时,首先循环判断options,依次提取要修改的角色属性;然后查看系统表pg_authid判断是否已存在该角色,如果不存在则提示报错;再进行相应的权限判断,检查执行者是否有权限去更改该角色的属性;最后构建一个新的元组,将要更改的属性更新到新元组中,存入系统表pg_authid。同时AlterRole函数也可以用来调整角色的成员关系,结构体中的action字段值设置为1和-1分别表示增加和删除成员关系,该选项将在授予和回收角色章节具体描述。AlterRole函数的具体实现代码如下:

void AlterRole(AlterRoleStmt* stmt)

{

. . .

/* 循环提取角色的属性options */

foreach (option, stmt->options) {

DefElem* defel = (DefElem*)lfirst(option);

if (strcmp(defel->defname, "password") == 0 || strcmp(defel->defname, "encryptedPassword") == 0 ||

strcmp(defel->defname, "unencryptedPassword") == 0) {

if (dpassword != NULL) {

clean_role_password(dpassword);

ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant options")));

}

dpassword = defel;

if (strcmp(defel->defname, "encryptedPassword") == 0)

encrypt_password = true;

else if (strcmp(defel->defname, "unencryptedPassword") == 0) {

clean_role_password(dpassword);

ereport(ERROR,

(errcode(ERRCODE_INVALID_ROLE_SPECIFICATION),

errmsg("Permission denied to create role with option UNENCRYPTED.")));

}

} else if (strcmp(defel->defname, "createrole") == 0) {

if (dcreaterole != NULL) {

clean_role_password(dpassword);

ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant options")));

}

dcreaterole = defel;

} else if (strcmp(defel->defname, "inherit") == 0) {

if (dinherit != NULL) {

clean_role_password(dpassword);

ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant options")));

}

dinherit = defel;

}

. . .

else {

clean_role_password(dpassword);

ereport(ERROR,

(errcode(ERRCODE_UNRECOGNIZED_NODE_TYPE), errmsg("option \"%s\" not recognized", defel->defname)));

}

}

/* 将提取的属性赋值给对应的变量 */

if (dpassword != NULL && dpassword->arg != NULL) {

head = list_head((List*)dpassword->arg);

if (head != NULL) {

pwdargs = (A_Const*)linitial((List*)dpassword->arg);

if (pwdargs != NULL) {

password = strVal(&pwdargs->val);

}

if (lnext(head)) {

pwdargs = (A_Const*)lsecond((List*)dpassword->arg);

if (pwdargs != NULL) {

replPasswd = strVal(&pwdargs->val);

}

}

}

}

if (dinherit != NULL)

inherit = intVal(dinherit->arg);

if (dcreaterole != NULL)

createrole = intVal(dcreaterole->arg);

. . .

/* 查看要修改的角色是否存在,不存在则提示报错 */

Relation pg_authid_rel = heap_open(AuthIdRelationId, RowExclusiveLock);

HeapTuple tuple = SearchSysCache1(AUTHNAME, PointerGetDatum(stmt->role));

if (!HeapTupleIsValid(tuple)) {

str_reset(password);

str_reset(replPasswd);

if (!have_createrole_privilege())

ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("Permission denied.")));

else

ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("role \"%s\" does not exist", stmt->role)));

}

roleid = HeapTupleGetOid(tuple);

. . .

/* 检查是否有权限更改相应角色的属性,权限不足则提示报错 */

if (roleid == BOOTSTRAP_SUPERUSERID) {

if (!(issuper < 0 && inherit < 0 && createrole < 0 && createdb < 0 && canlogin < 0 && isreplication < 0 &&

isauditadmin < 0 && issystemadmin < 0 && isvcadmin < 0 && useft < 0 && dconnlimit == NULL &&

rolemembers == NULL && validBegin == NULL && validUntil == NULL && drespool == NULL &&

dparent == NULL && dnode_group == NULL && dspacelimit == NULL && dtmpspacelimit == NULL &&

dspillspacelimit == NULL)) {

str_reset(password);

str_reset(replPasswd);

ereport(ERROR,

(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),

errmsg("Permission denied to change privilege of the initial account.")));

}

}

if (dpassword != NULL && roleid == BOOTSTRAP_SUPERUSERID && GetUserId() != BOOTSTRAP_SUPERUSERID) {

str_reset(password);

str_reset(replPasswd);

ereport(ERROR,

(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),

errmsg("Permission denied to change password of the initial account.")));

}

. . .

} else if (!have_createrole_privilege()) {

if (!(inherit < 0 && createrole < 0 && createdb < 0 && canlogin < 0 && isreplication < 0 && isauditadmin < 0 &&

issystemadmin < 0 && isvcadmin < 0 && useft < 0 && dconnlimit == NULL && rolemembers == NULL &&

validBegin == NULL && validUntil == NULL && !*respool && !OidIsValid(parentid) && dnode_group == NULL &&

!spacelimit && !tmpspacelimit && !spillspacelimit &&

/* if not superuser or have createrole privilege, permission of lock and unlock is denied */

stmt->lockstatus == DO_NOTHING &&

/* if alter password, it will be handled below */

roleid == GetUserId()) ||

(roleid != GetUserId() && dpassword == NULL)) {

str_reset(password);

str_reset(replPasswd);

ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("Permission denied.")));

}

}

...

/* 将要更改的角色属性值分别更新到新元组中,再将新元组替代旧元组存入系统表pg_authid中 */

if (issuper >= 0) {

new_record[Anum_pg_authid_rolsuper - 1] = BoolGetDatum(issuper > 0);

new_record_repl[Anum_pg_authid_rolsuper - 1] = true;

new_record[Anum_pg_authid_rolcatupdate - 1] = BoolGetDatum(issuper > 0);

new_record_repl[Anum_pg_authid_rolcatupdate - 1] = true;

}

if (inherit >= 0) {

new_record[Anum_pg_authid_rolinherit - 1] = BoolGetDatum(inherit > 0);

new_record_repl[Anum_pg_authid_rolinherit - 1] = true;

}

. . .

HeapTuple new_tuple = heap_modify_tuple(tuple, pg_authid_dsc, new_record, new_record_nulls, new_record_repl);

simple_heap_update(pg_authid_rel, &tuple->t_self, new_tuple);

CatalogUpdateIndexes(pg_authid_rel, new_tuple);

. . .

/* 判断成员关系,增加或删除成员 */

if (stmt->action == 1)

AddRoleMems(stmt->role, roleid, rolemembers, roleNamesToIds(rolemembers), GetUserId(), false);

else if (stmt->action == -1) /* drop members FROM role */

DelRoleMems(stmt->role, roleid, rolemembers, roleNamesToIds(rolemembers), false);

. . .

heap_close(pg_authid_rel, NoLock);

}

posted @ 2024-05-07 09:25  openGauss-bot  阅读(11)  评论(0)    收藏  举报