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

 

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值