Commit b3cbf98e authored by Chuck Lever's avatar Chuck Lever
Browse files

SUNRPC: Support TLS handshake in the server-side TCP socket code



This patch adds opportunitistic RPC-with-TLS to the Linux in-kernel
NFS server. If the client requests RPC-with-TLS and the user space
handshake agent is running, the server will set up a TLS session.

There are no policy settings yet. For example, the server cannot
yet require the use of RPC-with-TLS to access its data.

Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
parent 22b620ec
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -27,7 +27,7 @@ struct svc_xprt_ops {
	void		(*xpo_detach)(struct svc_xprt *);
	void		(*xpo_free)(struct svc_xprt *);
	void		(*xpo_kill_temp_xprt)(struct svc_xprt *);
	void		(*xpo_start_tls)(struct svc_xprt *);
	void		(*xpo_handshake)(struct svc_xprt *xprt);
};

struct svc_xprt_class {
@@ -70,6 +70,9 @@ struct svc_xprt {
#define XPT_LOCAL	12		/* connection from loopback interface */
#define XPT_KILL_TEMP   13		/* call xpo_kill_temp_xprt before closing */
#define XPT_CONG_CTRL	14		/* has congestion control */
#define XPT_HANDSHAKE	15		/* xprt requests a handshake */
#define XPT_TLS_SESSION	16		/* transport-layer security established */
#define XPT_PEER_AUTH	17		/* peer has been authenticated */

	struct svc_serv		*xpt_server;	/* service for transport */
	atomic_t    	    	xpt_reserved;	/* space on outq that is rsvd */
+2 −0
Original line number Diff line number Diff line
@@ -38,6 +38,8 @@ struct svc_sock {
	/* Number of queued send requests */
	atomic_t		sk_sendqlen;

	struct completion	sk_handshake_done;

	struct page *		sk_pages[RPCSVC_MAXPAGES];	/* received data */
};

+15 −1
Original line number Diff line number Diff line
@@ -1857,7 +1857,10 @@ TRACE_EVENT(svc_stats_latency,
		{ BIT(XPT_CACHE_AUTH),		"CACHE_AUTH" },		\
		{ BIT(XPT_LOCAL),		"LOCAL" },		\
		{ BIT(XPT_KILL_TEMP),		"KILL_TEMP" },		\
		{ BIT(XPT_CONG_CTRL),		"CONG_CTRL" })
		{ BIT(XPT_CONG_CTRL),		"CONG_CTRL" },		\
		{ BIT(XPT_HANDSHAKE),		"HANDSHAKE" },		\
		{ BIT(XPT_TLS_SESSION),		"TLS_SESSION" },	\
		{ BIT(XPT_PEER_AUTH),		"PEER_AUTH" })

TRACE_EVENT(svc_xprt_create_err,
	TP_PROTO(
@@ -1990,6 +1993,17 @@ DEFINE_SVC_XPRT_EVENT(close);
DEFINE_SVC_XPRT_EVENT(detach);
DEFINE_SVC_XPRT_EVENT(free);

#define DEFINE_SVC_TLS_EVENT(name) \
	DEFINE_EVENT(svc_xprt_event, svc_tls_##name, \
		TP_PROTO(const struct svc_xprt *xprt), \
		TP_ARGS(xprt))

DEFINE_SVC_TLS_EVENT(start);
DEFINE_SVC_TLS_EVENT(upcall);
DEFINE_SVC_TLS_EVENT(unavailable);
DEFINE_SVC_TLS_EVENT(not_started);
DEFINE_SVC_TLS_EVENT(timed_out);

TRACE_EVENT(svc_xprt_accept,
	TP_PROTO(
		const struct svc_xprt *xprt,
+4 −1
Original line number Diff line number Diff line
@@ -427,7 +427,7 @@ static bool svc_xprt_ready(struct svc_xprt *xprt)

	if (xpt_flags & BIT(XPT_BUSY))
		return false;
	if (xpt_flags & (BIT(XPT_CONN) | BIT(XPT_CLOSE)))
	if (xpt_flags & (BIT(XPT_CONN) | BIT(XPT_CLOSE) | BIT(XPT_HANDSHAKE)))
		return true;
	if (xpt_flags & (BIT(XPT_DATA) | BIT(XPT_DEFERRED))) {
		if (xprt->xpt_ops->xpo_has_wspace(xprt) &&
@@ -828,6 +828,9 @@ static int svc_handle_xprt(struct svc_rqst *rqstp, struct svc_xprt *xprt)
			module_put(xprt->xpt_class->xcl_owner);
		}
		svc_xprt_received(xprt);
	} else if (test_bit(XPT_HANDSHAKE, &xprt->xpt_flags)) {
		xprt->xpt_ops->xpo_handshake(xprt);
		svc_xprt_received(xprt);
	} else if (svc_xprt_reserve_slot(rqstp, xprt)) {
		/* XPT_DATA|XPT_DEFERRED case: */
		dprintk("svc: server %p, pool %u, transport %p, inuse=%d\n",
+9 −2
Original line number Diff line number Diff line
@@ -17,8 +17,9 @@
#include <net/ipv6.h>
#include <linux/kernel.h>
#include <linux/user_namespace.h>
#define RPCDBG_FACILITY	RPCDBG_AUTH
#include <trace/events/sunrpc.h>

#define RPCDBG_FACILITY	RPCDBG_AUTH

#include "netns.h"

@@ -832,6 +833,7 @@ svcauth_tls_accept(struct svc_rqst *rqstp)
{
	struct xdr_stream *xdr = &rqstp->rq_arg_stream;
	struct svc_cred	*cred = &rqstp->rq_cred;
	struct svc_xprt *xprt = rqstp->rq_xprt;
	u32 flavor, len;
	void *body;
	__be32 *p;
@@ -865,14 +867,19 @@ svcauth_tls_accept(struct svc_rqst *rqstp)
	if (cred->cr_group_info == NULL)
		return SVC_CLOSE;

	if (rqstp->rq_xprt->xpt_ops->xpo_start_tls) {
	if (xprt->xpt_ops->xpo_handshake) {
		p = xdr_reserve_space(&rqstp->rq_res_stream, XDR_UNIT * 2 + 8);
		if (!p)
			return SVC_CLOSE;
		trace_svc_tls_start(xprt);
		*p++ = rpc_auth_null;
		*p++ = cpu_to_be32(8);
		memcpy(p, "STARTTLS", 8);

		set_bit(XPT_HANDSHAKE, &xprt->xpt_flags);
		svc_xprt_enqueue(xprt);
	} else {
		trace_svc_tls_unavailable(xprt);
		if (xdr_stream_encode_opaque_auth(&rqstp->rq_res_stream,
						  RPC_AUTH_NULL, NULL, 0) < 0)
			return SVC_CLOSE;
Loading