上一篇文章中我们讲解了一个RPC请求的处理流程,其中涉及到了RPC请求报文中的认证信息。Linux支持多种认证方式,不同的认证方式中认证信息的内容是不同的,需要按照认证方式进行处理。这篇文件中我们以UNIX认证为例,详细讲解UNIX认证方式中认证信息的处理过程。
Linux中,每种认证方式用数据结构auth_ops表示,每种认证方式都需要实现这个数据结构中的函数。
struct auth_ops {
char * name; // 这是认证方式的名称
struct module *owner;
int flavour; // 这是认证方式的编号
// 这是认证信息处理函数,负责解析RPC请求报文中的Credential字段和Verifier字段
// 然后填充RPC应答报文中的Verifier字段
int (*accept)(struct svc_rqst *rq, __be32 *authp);
// 这个函数负责一些清理工作,当RPC请求处理结束后会调用这个函数
int (*release)(struct svc_rqst *rq);
// 这是释放认证域的函数,auth_domain是一个与认证信息相关的数据结构,
// 存放了认证相关的数据
void (*domain_release)(struct auth_domain *);
// 这个函数负责对用户进行认证,负责填充auth_domain结构,
// 这个函数被svc_program结构中的pg_authenticate函数调用
int (*set_client)(struct svc_rqst *rq);
};
UNIX认证中,这个数据结构的定义如下
struct auth_ops svcauth_unix = {
.name = "unix",
.owner = THIS_MODULE,
.flavour = RPC_AUTH_UNIX,
.accept = svcauth_unix_accept,
.release = svcauth_unix_release,
.domain_release = svcauth_unix_domain_release,
.set_client = svcauth_unix_set_client,
};
1.svcauth_unix_accept
这个函数负责解析RPC请求报文中的认证信息,并组装RPC应答报文中的认证信息。这个函数只解析数据,不进行用户身份验证。这个函数的完整流程如下:
static int
svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp)
{
// 调用这个函数前已经解析出了Credential中的Flavor字段,确定了RPC请求报文中包含的是UNIX认证数据,
// 接着解析报文中下一个字段Length,这个字段表示认证信息的长度
struct kvec *argv = &rqstp->rq_arg.head[0];
// resv是RPC应答消息的缓存,调用这个函数前已经封装了XID、Message Type、Reply State三个字段,
// 这个函数中需要继续封装Verifier字段.
struct kvec *resv = &rqstp->rq_res.head[0];
// 这是保存认证信息的数据结构,从RPC请求报文中解析出的UID、GID将保存在这个数据结构中.
struct svc_cred *cred = &rqstp-&