
学习 探索 分享数据库前沿知识和技术 共建数据库技术交流圈
上篇图文,我们分享了安全管理整体架构和代码概览及安全认证中身份认证、口令存储的精彩内容,本文将接着介绍安全认证中认证机制、Kerberos安全认证的相关内容。
9.2.3 认证机制
SaltedPassword := Hi(password, salt, iteration_count) /*其中,Hi()本质上是PBKDF2*/ClientKey := HMAC(SaltedPassword, "Client Key")StoredKey := sha256(ClientKey)ServerKey := HMAC(SaltedPassword, "Sever Key")ClientSignature:=HMAC(StoredKey, token)ServerSignature:= HMAC(ServerKey, token)ClientProof:= ClientSignature XOR ClientKey
具体密钥衍生过程如图1所示。

图1 密钥衍生过程
(1) StoredKey用来验证客户端用户身份。
(2) ServerKey用来向客户端表明自己身份的。
(3) 在认证过程中,服务端可以计算出来ClientKey,验证完后直接丢弃不必存储。
接下来详细描述在一个认证会话期间的客户端和服务端的信息交换过程。如图2所示。

图2 openGauss认证流程
(1) 客户端发送username。
(2) 服务端返回盐值salt、iteration-count(迭代次数)、ServerSignature以及随机生成的字符串token给客户端。token是随机生成字符串。服务端通过计算得到的ServerSignature返回给客户端。
ServerSignature := HMAC(ServerKey, token)
(3) 客户端认证服务端并发送认证响应。响应信息包含客户端认证信息ClientProof。ClientProof证明客户端拥有ClientKey,但是不通过网络的方式发送。在收到信息后,计算ClientProof。
ClientSignature := HMAC(StoredKey,token)
ClientProof := ClientKey XOR ClientSignature
(4) 服务端接收并校验客户端信息。
ClientSignature := HMAC(StoredKey, token)HMAC(ClientProof XOR ClientSignature ) = StoredKey
void ClientAuthentication(Port* port){int status = STATUS_ERROR;char details[PGAUDIT_MAXLENGTH] = {0};char token[TOKEN_LENGTH + 1] = {0};errno_t rc = EOK;GS_UINT32 retval = 0;hba_getauthmethod(port);……switch (port->hba->auth_method) {case uaReject:……case uaImplicitReject:……/* 使用MD5口令认证 */case uaMD5:sendAuthRequest(port, AUTH_REQ_MD5);status = recv_and_check_password_packet(port);break;/* 使用sha256认证方法 */case uaSHA256:/* 禁止使用初始用户进行远程连接 */if (isRemoteInitialUser(port)) {ereport(FATAL,(errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION), errmsg("Forbid remote connection with initial user.")));}rc = memset_s(port->token, TOKEN_LENGTH * 2 + 1, 0, TOKEN_LENGTH * 2 + 1);securec_check(rc, "\0", "\0");HOLD_INTERRUPTS();/* 生成随机数token */retval = RAND_priv_bytes ((GS_UCHAR*)token, (GS_UINT32)TOKEN_LENGTH);RESUME_INTERRUPTS();CHECK_FOR_INTERRUPTS();if (retval != 1) {ereport(ERROR, (errmsg("Failed to Generate the random number,errcode:%u", retval)));}sha_bytes_to_hex8((uint8*)token, port->token);port->token[TOKEN_LENGTH * 2] = '\0';/* 发送认证请求到前端,认证码为AUTH_REQ_SHA256 */sendAuthRequest(port, AUTH_REQ_SHA256);/* 接收并校验客户端的信息 */status = recv_and_check_password_packet(port);break;……}……if (status == STATUS_OK)sendAuthRequest(port, AUTH_REQ_OK);else {auth_failed(port, status);}/* 完成认证,关闭参数ImmediateInterruptOK */t_thrd.int_cxt.ImmediateInterruptOK = false;}
static int pg_password_sendauth(PGconn* conn, const char* password, AuthRequest areq){int ret;/* 初始化变量 */……char h[HMAC_LENGTH + 1] = {0};char h_string[HMAC_LENGTH * 2 + 1] = {0};char hmac_result[HMAC_LENGTH + 1] = {0};char client_key_bytes[HMAC_LENGTH + 1] = {0};switch (areq) {case AUTH_REQ_MD5:/* pg_md5_encrypt()通过MD5Salt进行MD5加密 */……case AUTH_REQ_MD5_SHA256:……case AUTH_REQ_SHA256: {char* crypt_pwd2 = NULL;if (SHA256_PASSWORD == conn->password_stored_method || PLAIN_PASSWORD == conn->password_stored_method) {/* 通过SHA256方式加密密码 */if (!pg_sha256_encrypt(password, conn->salt, strlen(conn->salt), (char*)buf, client_key_buf, conn->iteration_count))return STATUS_ERROR;rc = strncpy_s(server_key_string,sizeof(server_key_string),&buf[SHA256_LENGTH + SALT_STRING_LENGTH],sizeof(server_key_string) - 1);securec_check_c(rc, "\0", "\0");rc = strncpy_s(stored_key_string,sizeof(stored_key_string),&buf[SHA256_LENGTH + SALT_STRING_LENGTH + HMAC_STRING_LENGTH],sizeof(stored_key_string) - 1);securec_check_c(rc, "\0", "\0");server_key_string[sizeof(server_key_string) - 1] = '\0';stored_key_string[sizeof(stored_key_string) - 1] = '\0';sha_hex_to_bytes32(server_key_bytes, server_key_string);sha_hex_to_bytes4(token, conn->token);/* 通过server_key和token调用HMAC算法计算,得到client_server_signature_bytes,通过该变量转为字符串变量,用来验证与服务端传来的server_signature是否相等。*/CRYPT_hmac_ret1 = CRYPT_hmac(NID_hmacWithSHA256,(GS_UCHAR*)server_key_bytes,HMAC_LENGTH,(GS_UCHAR*)token,TOKEN_LENGTH,(GS_UCHAR*)client_server_signature_bytes,(GS_UINT32*)&hmac_length);if (CRYPT_hmac_ret1) {return STATUS_ERROR;}sha_bytes_to_hex64((uint8*)client_server_signature_bytes, client_server_signature_string);/* 调用函数strncmp判断计算的client_server_signature_string和服务端传来的server_signature值是否相等 */if (PG_PROTOCOL_MINOR(conn->pversion) < PG_PROTOCOL_GAUSS_BASE &&0 != strncmp(conn->server_signature, client_server_signature_string, HMAC_STRING_LENGTH)) {pwd_to_send = fail_info; /* 不相等则认证失败 */} else {sha_hex_to_bytes32(stored_key_bytes, stored_key_string);/* 通过stored_key和token计算得到hmac_result */CRYPT_hmac_ret2 = CRYPT_hmac(NID_hmacWithSHA256,(GS_UCHAR*)stored_key_bytes,STORED_KEY_LENGTH,(GS_UCHAR*)token,TOKEN_LENGTH,(GS_UCHAR*)hmac_result,(GS_UINT32*)&hmac_length);if (CRYPT_hmac_ret2) {return STATUS_ERROR;}sha_hex_to_bytes32(client_key_bytes, client_key_buf);/* hmac_result和client_key_bytes异或得到h,然后将其发送给服务端,用于验证客户端 */if (XOR_between_password(hmac_result, client_key_bytes, h, HMAC_LENGTH)) {return STATUS_ERROR;}sha_bytes_to_hex64((uint8*)h, h_string);pwd_to_send = h_string; /* 设置要发送给服务端的值 */}}……break;/* 清空变量 */……return ret;}
9.2.4 Kerberos安全认证
Kerberos是一种基于对称密钥技术的身份认证协议。开源组件Kerberos可以解决集群内节点或者进程之间的认证问题,即当开启kerberos之后,恶意用户无法仿冒集群内节点或进程来登录数据库系统,只有内部组件才可以持有用于认证的凭证。从而保证通过Kerberos认证,消减了仿冒风险,提升了数据库系统的安全性。Kerberos协议认证交互如图3所示。

openGauss可在数据库系统部署完毕之后开启Kerberos模式,即Kerberos服务部署在数据库系统机器上,部署过程中会开启Kerberos相关的服务,并派发凭证给集群内部所有的节点,初始化一系列Kerberos需要用到的环境变量,数据库内核中通过调用GSS-API来实现Kebreros标准协议的通信内容。以openGauss主备之间的认证为例,在Kerberos开启后openGauss内部进程之间认证流程如图4所示。

右侧侧虚线框内的数据库内侧认证,主要是图4右侧虚线框内的AP-REQ流程实现,简化流程如图5所示。

typedef struct GssConn {int sock;gss_ctx_id_t gctx; /* GSS 上下文 */gss_name_t gtarg_nam; /* GSS 名称 */gss_buffer_desc ginbuf; /* GSS 输入token */gss_buffer_desc goutbuf; /* GSS 输出token */} GssConn;/* 客户端、服务端接口,用于封装标准kerberos协议调用,其中客户端接口用于向服务端 *//* 发起访问,同时响应服务端接口GssServerAuth发起的票据请求 */int GssClientAuth(int socket, char* server_host);int GssServerAuth(int socket, const char* krb_keyfile);

(1) 服务端通过数据库配置文件决定使用Kerberos协议对客户端连接进行认证。
(2) 发起认证请求,客户端准备需要Kerberos认证的环境和票证,发’P’报文响应请求并发送票证。
(3) 服务端验证通过后会发送响应’R’报文,完成Kerberos认证。
以上内容为安全管理源码解析—安全认证中认证机制、Kerberos安全认证的相关内容,下篇图文,将详细介绍“角色管理”相关内容,敬请期待!
- END -
文章转载自Gauss松鼠会,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。






