From: Chuck Lever We'd like tlshd to tag certificates according to admin-defined characteristics. The tag list is to be returned on a successful handshake. Upper Layer Protocols (such as NFS) can then authorize access based on the set of tags returned to the kernel. For example, suppose NFSD wants to restrict access to an export to only clients that present certificates whose issuer DN contains "O=Oracle". tlshd can parse incoming certificates, and add an "oraclegroup" tag to handshakes where a client presents a certificate with "O=Oracle" somewhere in its Issuer field. NFSD can then be configured to look for that tag and permit access only when it is present. NFSD needs no knowledge of x.509 certificates. This patch plumbs in the netlink protocol elements for tlshd to return a list of tags to the kernel when a TLS or QUIC handshake succeeds. Subsequent patches add tag extraction and storage in the handshake layer. Signed-off-by: Chuck Lever --- Documentation/netlink/specs/handshake.yaml | 11 +++++++++++ include/uapi/linux/handshake.h | 3 +++ net/handshake/genl.c | 5 +++-- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/Documentation/netlink/specs/handshake.yaml b/Documentation/netlink/specs/handshake.yaml index 24f5a0ac5920..df36ff7da18f 100644 --- a/Documentation/netlink/specs/handshake.yaml +++ b/Documentation/netlink/specs/handshake.yaml @@ -12,6 +12,10 @@ protocol: genetlink doc: Netlink protocol to request a transport layer security handshake. definitions: + - + name: session-tag-max-len + type: const + value: 255 - type: enum name: handler-class @@ -87,6 +91,12 @@ attribute-sets: name: remote-auth type: u32 multi-attr: true + - + name: tag + type: string + checks: + max-len: session-tag-max-len + multi-attr: true operations: list: @@ -124,6 +134,7 @@ operations: - status - sockfd - remote-auth + - tag mcast-groups: list: diff --git a/include/uapi/linux/handshake.h b/include/uapi/linux/handshake.h index d7e40f594888..1ed309e475b4 100644 --- a/include/uapi/linux/handshake.h +++ b/include/uapi/linux/handshake.h @@ -10,6 +10,8 @@ #define HANDSHAKE_FAMILY_NAME "handshake" #define HANDSHAKE_FAMILY_VERSION 1 +#define HANDSHAKE_SESSION_TAG_MAX_LEN 255 + enum handshake_handler_class { HANDSHAKE_HANDLER_CLASS_NONE, HANDSHAKE_HANDLER_CLASS_TLSHD, @@ -56,6 +58,7 @@ enum { HANDSHAKE_A_DONE_STATUS = 1, HANDSHAKE_A_DONE_SOCKFD, HANDSHAKE_A_DONE_REMOTE_AUTH, + HANDSHAKE_A_DONE_TAG, __HANDSHAKE_A_DONE_MAX, HANDSHAKE_A_DONE_MAX = (__HANDSHAKE_A_DONE_MAX - 1) diff --git a/net/handshake/genl.c b/net/handshake/genl.c index 791c45671cd6..385583805e02 100644 --- a/net/handshake/genl.c +++ b/net/handshake/genl.c @@ -17,10 +17,11 @@ static const struct nla_policy handshake_accept_nl_policy[HANDSHAKE_A_ACCEPT_HAN }; /* HANDSHAKE_CMD_DONE - do */ -static const struct nla_policy handshake_done_nl_policy[HANDSHAKE_A_DONE_REMOTE_AUTH + 1] = { +static const struct nla_policy handshake_done_nl_policy[HANDSHAKE_A_DONE_TAG + 1] = { [HANDSHAKE_A_DONE_STATUS] = { .type = NLA_U32, }, [HANDSHAKE_A_DONE_SOCKFD] = { .type = NLA_S32, }, [HANDSHAKE_A_DONE_REMOTE_AUTH] = { .type = NLA_U32, }, + [HANDSHAKE_A_DONE_TAG] = { .type = NLA_STRING, .len = HANDSHAKE_SESSION_TAG_MAX_LEN, }, }; /* Ops table for handshake */ @@ -36,7 +37,7 @@ static const struct genl_split_ops handshake_nl_ops[] = { .cmd = HANDSHAKE_CMD_DONE, .doit = handshake_nl_done_doit, .policy = handshake_done_nl_policy, - .maxattr = HANDSHAKE_A_DONE_REMOTE_AUTH, + .maxattr = HANDSHAKE_A_DONE_TAG, .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, }, }; -- 2.54.0