Skip to content

Commit 1207265

Browse files
chuckleverTrond Myklebust
authored andcommitted
SUNRPC: Add RPC client support for the RPC_AUTH_TLS auth flavor
The new authentication flavor is used only to discover peer support for RPC-over-TLS. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
1 parent 97d1c83 commit 1207265

File tree

5 files changed

+182
-2
lines changed

5 files changed

+182
-2
lines changed

include/linux/sunrpc/auth.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ struct rpc_authops {
120120
struct rpcsec_gss_info *);
121121
int (*key_timeout)(struct rpc_auth *,
122122
struct rpc_cred *);
123+
int (*ping)(struct rpc_clnt *clnt);
123124
};
124125

125126
struct rpc_credops {
@@ -144,6 +145,7 @@ struct rpc_credops {
144145

145146
extern const struct rpc_authops authunix_ops;
146147
extern const struct rpc_authops authnull_ops;
148+
extern const struct rpc_authops authtls_ops;
147149

148150
int __init rpc_init_authunix(void);
149151
int __init rpcauth_init_module(void);

net/sunrpc/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ obj-$(CONFIG_SUNRPC_GSS) += auth_gss/
99
obj-$(CONFIG_SUNRPC_XPRT_RDMA) += xprtrdma/
1010

1111
sunrpc-y := clnt.o xprt.o socklib.o xprtsock.o sched.o \
12-
auth.o auth_null.o auth_unix.o \
12+
auth.o auth_null.o auth_tls.o auth_unix.o \
1313
svc.o svcsock.o svcauth.o svcauth_unix.o \
1414
addr.o rpcb_clnt.o timer.o xdr.o \
1515
sunrpc_syms.o cache.o rpc_pipe.o sysfs.o \

net/sunrpc/auth.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ static unsigned int auth_hashbits = RPC_CREDCACHE_DEFAULT_HASHBITS;
3232
static const struct rpc_authops __rcu *auth_flavors[RPC_AUTH_MAXFLAVOR] = {
3333
[RPC_AUTH_NULL] = (const struct rpc_authops __force __rcu *)&authnull_ops,
3434
[RPC_AUTH_UNIX] = (const struct rpc_authops __force __rcu *)&authunix_ops,
35-
NULL, /* others can be loadable modules */
35+
[RPC_AUTH_TLS] = (const struct rpc_authops __force __rcu *)&authtls_ops,
3636
};
3737

3838
static LIST_HEAD(cred_unused);

net/sunrpc/auth_tls.c

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/*
3+
* Copyright (c) 2021, 2022 Oracle. All rights reserved.
4+
*
5+
* The AUTH_TLS credential is used only to probe a remote peer
6+
* for RPC-over-TLS support.
7+
*/
8+
9+
#include <linux/types.h>
10+
#include <linux/module.h>
11+
#include <linux/sunrpc/clnt.h>
12+
13+
static const char *starttls_token = "STARTTLS";
14+
static const size_t starttls_len = 8;
15+
16+
static struct rpc_auth tls_auth;
17+
static struct rpc_cred tls_cred;
18+
19+
static void tls_encode_probe(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
20+
const void *obj)
21+
{
22+
}
23+
24+
static int tls_decode_probe(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
25+
void *obj)
26+
{
27+
return 0;
28+
}
29+
30+
static const struct rpc_procinfo rpcproc_tls_probe = {
31+
.p_encode = tls_encode_probe,
32+
.p_decode = tls_decode_probe,
33+
};
34+
35+
static void rpc_tls_probe_call_prepare(struct rpc_task *task, void *data)
36+
{
37+
task->tk_flags &= ~RPC_TASK_NO_RETRANS_TIMEOUT;
38+
rpc_call_start(task);
39+
}
40+
41+
static void rpc_tls_probe_call_done(struct rpc_task *task, void *data)
42+
{
43+
}
44+
45+
static const struct rpc_call_ops rpc_tls_probe_ops = {
46+
.rpc_call_prepare = rpc_tls_probe_call_prepare,
47+
.rpc_call_done = rpc_tls_probe_call_done,
48+
};
49+
50+
static int tls_probe(struct rpc_clnt *clnt)
51+
{
52+
struct rpc_message msg = {
53+
.rpc_proc = &rpcproc_tls_probe,
54+
};
55+
struct rpc_task_setup task_setup_data = {
56+
.rpc_client = clnt,
57+
.rpc_message = &msg,
58+
.rpc_op_cred = &tls_cred,
59+
.callback_ops = &rpc_tls_probe_ops,
60+
.flags = RPC_TASK_SOFT | RPC_TASK_SOFTCONN,
61+
};
62+
struct rpc_task *task;
63+
int status;
64+
65+
task = rpc_run_task(&task_setup_data);
66+
if (IS_ERR(task))
67+
return PTR_ERR(task);
68+
status = task->tk_status;
69+
rpc_put_task(task);
70+
return status;
71+
}
72+
73+
static struct rpc_auth *tls_create(const struct rpc_auth_create_args *args,
74+
struct rpc_clnt *clnt)
75+
{
76+
refcount_inc(&tls_auth.au_count);
77+
return &tls_auth;
78+
}
79+
80+
static void tls_destroy(struct rpc_auth *auth)
81+
{
82+
}
83+
84+
static struct rpc_cred *tls_lookup_cred(struct rpc_auth *auth,
85+
struct auth_cred *acred, int flags)
86+
{
87+
return get_rpccred(&tls_cred);
88+
}
89+
90+
static void tls_destroy_cred(struct rpc_cred *cred)
91+
{
92+
}
93+
94+
static int tls_match(struct auth_cred *acred, struct rpc_cred *cred, int taskflags)
95+
{
96+
return 1;
97+
}
98+
99+
static int tls_marshal(struct rpc_task *task, struct xdr_stream *xdr)
100+
{
101+
__be32 *p;
102+
103+
p = xdr_reserve_space(xdr, 4 * XDR_UNIT);
104+
if (!p)
105+
return -EMSGSIZE;
106+
/* Credential */
107+
*p++ = rpc_auth_tls;
108+
*p++ = xdr_zero;
109+
/* Verifier */
110+
*p++ = rpc_auth_null;
111+
*p = xdr_zero;
112+
return 0;
113+
}
114+
115+
static int tls_refresh(struct rpc_task *task)
116+
{
117+
set_bit(RPCAUTH_CRED_UPTODATE, &task->tk_rqstp->rq_cred->cr_flags);
118+
return 0;
119+
}
120+
121+
static int tls_validate(struct rpc_task *task, struct xdr_stream *xdr)
122+
{
123+
__be32 *p;
124+
void *str;
125+
126+
p = xdr_inline_decode(xdr, XDR_UNIT);
127+
if (!p)
128+
return -EIO;
129+
if (*p != rpc_auth_null)
130+
return -EIO;
131+
if (xdr_stream_decode_opaque_inline(xdr, &str, starttls_len) != starttls_len)
132+
return -EIO;
133+
if (memcmp(str, starttls_token, starttls_len))
134+
return -EIO;
135+
return 0;
136+
}
137+
138+
const struct rpc_authops authtls_ops = {
139+
.owner = THIS_MODULE,
140+
.au_flavor = RPC_AUTH_TLS,
141+
.au_name = "NULL",
142+
.create = tls_create,
143+
.destroy = tls_destroy,
144+
.lookup_cred = tls_lookup_cred,
145+
.ping = tls_probe,
146+
};
147+
148+
static struct rpc_auth tls_auth = {
149+
.au_cslack = NUL_CALLSLACK,
150+
.au_rslack = NUL_REPLYSLACK,
151+
.au_verfsize = NUL_REPLYSLACK,
152+
.au_ralign = NUL_REPLYSLACK,
153+
.au_ops = &authtls_ops,
154+
.au_flavor = RPC_AUTH_TLS,
155+
.au_count = REFCOUNT_INIT(1),
156+
};
157+
158+
static const struct rpc_credops tls_credops = {
159+
.cr_name = "AUTH_TLS",
160+
.crdestroy = tls_destroy_cred,
161+
.crmatch = tls_match,
162+
.crmarshal = tls_marshal,
163+
.crwrap_req = rpcauth_wrap_req_encode,
164+
.crrefresh = tls_refresh,
165+
.crvalidate = tls_validate,
166+
.crunwrap_resp = rpcauth_unwrap_resp_decode,
167+
};
168+
169+
static struct rpc_cred tls_cred = {
170+
.cr_lru = LIST_HEAD_INIT(tls_cred.cr_lru),
171+
.cr_auth = &tls_auth,
172+
.cr_ops = &tls_credops,
173+
.cr_count = REFCOUNT_INIT(2),
174+
.cr_flags = 1UL << RPCAUTH_CRED_UPTODATE,
175+
};

net/sunrpc/clnt.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2833,6 +2833,9 @@ static int rpc_ping(struct rpc_clnt *clnt)
28332833
struct rpc_task *task;
28342834
int status;
28352835

2836+
if (clnt->cl_auth->au_ops->ping)
2837+
return clnt->cl_auth->au_ops->ping(clnt);
2838+
28362839
task = rpc_call_null_helper(clnt, NULL, NULL, 0, NULL, NULL);
28372840
if (IS_ERR(task))
28382841
return PTR_ERR(task);

0 commit comments

Comments
 (0)