Commit 23c01ed3 authored by Jakub Kicinski's avatar Jakub Kicinski

Merge tag 'rxrpc-next-20201123' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs

David Howells says:

====================
rxrpc: Prelude to gssapi support

Here are some patches that do some reorganisation of the security class
handling in rxrpc to allow implementation of the RxGK security class that
will allow AF_RXRPC to use GSSAPI-negotiated tokens and better crypto.  The
RxGK security class is not included in this patchset.

It does the following things:

 (1) Add a keyrings patch to provide the original key description, as
     provided to add_key(), to the payload preparser so that it can
     interpret the content on that basis.  Unfortunately, the rxrpc_s key
     type wasn't written to interpret its payload as anything other than a
     string of bytes comprising a key, but for RxGK, more information is
     required as multiple Kerberos enctypes are supported.

 (2) Remove the rxk5 security class key parsing.  The rxk5 class never got
     rolled out in OpenAFS and got replaced with rxgk.

 (3) Support the creation of rxrpc keys with multiple tokens of different
     types.  If some types are not supported, the ENOPKG error is
     suppressed if at least one other token's type is supported.

 (4) Punt the handling of server keys (rxrpc_s type) to the appropriate
     security class.

 (5) Organise the security bits in the rxrpc_connection struct into a
     union to make it easier to override for other classes.

 (6) Move some bits from core code into rxkad that won't be appropriate to
     rxgk.

* tag 'rxrpc-next-20201123' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs:
  rxrpc: Ask the security class how much space to allow in a packet
  rxrpc: rxkad: Don't use pskb_pull() to advance through the response packet
  rxrpc: Organise connection security to use a union
  rxrpc: Don't reserve security header in Tx DATA skbuff
  rxrpc: Merge prime_packet_security into init_connection_security
  rxrpc: Fix example key name in a comment
  rxrpc: Ignore unknown tokens in key payload unless no known tokens
  rxrpc: Make the parsing of xdr payloads more coherent
  rxrpc: Allow security classes to give more info on server keys
  rxrpc: Don't leak the service-side session key to userspace
  rxrpc: Hand server key parsing off to the security class
  rxrpc: Split the server key type (rxrpc_s) into its own file
  rxrpc: Don't retain the server key in the connection
  rxrpc: Support keys with multiple authentication tokens
  rxrpc: List the held token types in the key description in /proc/keys
  rxrpc: Remove the rxk5 security class as it's now defunct
  keys: Provide the original description to the key preparser
====================

Link: https://lore.kernel.org/r/160616220405.830164.2239716599743995145.stgit@warthog.procyon.org.ukSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents d5a05e69 d7d775b1
...@@ -31,63 +31,15 @@ struct rxkad_key { ...@@ -31,63 +31,15 @@ struct rxkad_key {
u8 ticket[]; /* the encrypted ticket */ u8 ticket[]; /* the encrypted ticket */
}; };
/*
* Kerberos 5 principal
* name/name/name@realm
*/
struct krb5_principal {
u8 n_name_parts; /* N of parts of the name part of the principal */
char **name_parts; /* parts of the name part of the principal */
char *realm; /* parts of the realm part of the principal */
};
/*
* Kerberos 5 tagged data
*/
struct krb5_tagged_data {
/* for tag value, see /usr/include/krb5/krb5.h
* - KRB5_AUTHDATA_* for auth data
* -
*/
s32 tag;
u32 data_len;
u8 *data;
};
/*
* RxRPC key for Kerberos V (type-5 security)
*/
struct rxk5_key {
u64 authtime; /* time at which auth token generated */
u64 starttime; /* time at which auth token starts */
u64 endtime; /* time at which auth token expired */
u64 renew_till; /* time to which auth token can be renewed */
s32 is_skey; /* T if ticket is encrypted in another ticket's
* skey */
s32 flags; /* mask of TKT_FLG_* bits (krb5/krb5.h) */
struct krb5_principal client; /* client principal name */
struct krb5_principal server; /* server principal name */
u16 ticket_len; /* length of ticket */
u16 ticket2_len; /* length of second ticket */
u8 n_authdata; /* number of authorisation data elements */
u8 n_addresses; /* number of addresses */
struct krb5_tagged_data session; /* session data; tag is enctype */
struct krb5_tagged_data *addresses; /* addresses */
u8 *ticket; /* krb5 ticket */
u8 *ticket2; /* second krb5 ticket, if related to ticket (via
* DUPLICATE-SKEY or ENC-TKT-IN-SKEY) */
struct krb5_tagged_data *authdata; /* authorisation data */
};
/* /*
* list of tokens attached to an rxrpc key * list of tokens attached to an rxrpc key
*/ */
struct rxrpc_key_token { struct rxrpc_key_token {
u16 security_index; /* RxRPC header security index */ u16 security_index; /* RxRPC header security index */
bool no_leak_key; /* Don't copy the key to userspace */
struct rxrpc_key_token *next; /* the next token in the list */ struct rxrpc_key_token *next; /* the next token in the list */
union { union {
struct rxkad_key *kad; struct rxkad_key *kad;
struct rxk5_key *k5;
}; };
}; };
...@@ -116,12 +68,6 @@ struct rxrpc_key_data_v1 { ...@@ -116,12 +68,6 @@ struct rxrpc_key_data_v1 {
#define AFSTOKEN_RK_TIX_MAX 12000 /* max RxKAD ticket size */ #define AFSTOKEN_RK_TIX_MAX 12000 /* max RxKAD ticket size */
#define AFSTOKEN_GK_KEY_MAX 64 /* max GSSAPI key size */ #define AFSTOKEN_GK_KEY_MAX 64 /* max GSSAPI key size */
#define AFSTOKEN_GK_TOKEN_MAX 16384 /* max GSSAPI token size */ #define AFSTOKEN_GK_TOKEN_MAX 16384 /* max GSSAPI token size */
#define AFSTOKEN_K5_COMPONENTS_MAX 16 /* max K5 components */
#define AFSTOKEN_K5_NAME_MAX 128 /* max K5 name length */
#define AFSTOKEN_K5_REALM_MAX 64 /* max K5 realm name length */
#define AFSTOKEN_K5_TIX_MAX 16384 /* max K5 ticket size */
#define AFSTOKEN_K5_ADDRESSES_MAX 16 /* max K5 addresses */
#define AFSTOKEN_K5_AUTHDATA_MAX 16 /* max K5 pieces of auth data */
/* /*
* Truncate a time64_t to the range from 1970 to 2106 as in the network * Truncate a time64_t to the range from 1970 to 2106 as in the network
......
...@@ -29,6 +29,7 @@ struct kernel_pkey_params; ...@@ -29,6 +29,7 @@ struct kernel_pkey_params;
* clear the contents. * clear the contents.
*/ */
struct key_preparsed_payload { struct key_preparsed_payload {
const char *orig_description; /* Actual or proposed description (maybe NULL) */
char *description; /* Proposed key description (or NULL) */ char *description; /* Proposed key description (or NULL) */
union key_payload payload; /* Proposed payload */ union key_payload payload; /* Proposed payload */
const void *data; /* Raw data */ const void *data; /* Raw data */
......
...@@ -28,6 +28,7 @@ rxrpc-y := \ ...@@ -28,6 +28,7 @@ rxrpc-y := \
rtt.o \ rtt.o \
security.o \ security.o \
sendmsg.o \ sendmsg.o \
server_key.o \
skbuff.o \ skbuff.o \
utils.o utils.o
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <net/netns/generic.h> #include <net/netns/generic.h>
#include <net/sock.h> #include <net/sock.h>
#include <net/af_rxrpc.h> #include <net/af_rxrpc.h>
#include <keys/rxrpc-type.h>
#include "protocol.h" #include "protocol.h"
#if 0 #if 0
...@@ -34,6 +35,7 @@ struct rxrpc_crypt { ...@@ -34,6 +35,7 @@ struct rxrpc_crypt {
#define rxrpc_queue_delayed_work(WS,D) \ #define rxrpc_queue_delayed_work(WS,D) \
queue_delayed_work(rxrpc_workqueue, (WS), (D)) queue_delayed_work(rxrpc_workqueue, (WS), (D))
struct key_preparsed_payload;
struct rxrpc_connection; struct rxrpc_connection;
/* /*
...@@ -216,17 +218,30 @@ struct rxrpc_security { ...@@ -216,17 +218,30 @@ struct rxrpc_security {
/* Clean up a security service */ /* Clean up a security service */
void (*exit)(void); void (*exit)(void);
/* Parse the information from a server key */
int (*preparse_server_key)(struct key_preparsed_payload *);
/* Clean up the preparse buffer after parsing a server key */
void (*free_preparse_server_key)(struct key_preparsed_payload *);
/* Destroy the payload of a server key */
void (*destroy_server_key)(struct key *);
/* Describe a server key */
void (*describe_server_key)(const struct key *, struct seq_file *);
/* initialise a connection's security */ /* initialise a connection's security */
int (*init_connection_security)(struct rxrpc_connection *); int (*init_connection_security)(struct rxrpc_connection *,
struct rxrpc_key_token *);
/* prime a connection's packet security */ /* Work out how much data we can store in a packet, given an estimate
int (*prime_packet_security)(struct rxrpc_connection *); * of the amount of data remaining.
*/
int (*how_much_data)(struct rxrpc_call *, size_t,
size_t *, size_t *, size_t *);
/* impose security on a packet */ /* impose security on a packet */
int (*secure_packet)(struct rxrpc_call *, int (*secure_packet)(struct rxrpc_call *, struct sk_buff *, size_t);
struct sk_buff *,
size_t,
void *);
/* verify the security on a received packet */ /* verify the security on a received packet */
int (*verify_packet)(struct rxrpc_call *, struct sk_buff *, int (*verify_packet)(struct rxrpc_call *, struct sk_buff *,
...@@ -438,10 +453,15 @@ struct rxrpc_connection { ...@@ -438,10 +453,15 @@ struct rxrpc_connection {
struct list_head proc_link; /* link in procfs list */ struct list_head proc_link; /* link in procfs list */
struct list_head link; /* link in master connection list */ struct list_head link; /* link in master connection list */
struct sk_buff_head rx_queue; /* received conn-level packets */ struct sk_buff_head rx_queue; /* received conn-level packets */
const struct rxrpc_security *security; /* applied security module */ const struct rxrpc_security *security; /* applied security module */
struct key *server_key; /* security for this service */ union {
struct {
struct crypto_sync_skcipher *cipher; /* encryption handle */ struct crypto_sync_skcipher *cipher; /* encryption handle */
struct rxrpc_crypt csum_iv; /* packet checksum base */ struct rxrpc_crypt csum_iv; /* packet checksum base */
u32 nonce; /* response re-use preventer */
} rxkad;
};
unsigned long flags; unsigned long flags;
unsigned long events; unsigned long events;
unsigned long idle_timestamp; /* Time at which last became idle */ unsigned long idle_timestamp; /* Time at which last became idle */
...@@ -451,10 +471,7 @@ struct rxrpc_connection { ...@@ -451,10 +471,7 @@ struct rxrpc_connection {
int debug_id; /* debug ID for printks */ int debug_id; /* debug ID for printks */
atomic_t serial; /* packet serial number counter */ atomic_t serial; /* packet serial number counter */
unsigned int hi_serial; /* highest serial number received */ unsigned int hi_serial; /* highest serial number received */
u32 security_nonce; /* response re-use preventer */
u32 service_id; /* Service ID, possibly upgraded */ u32 service_id; /* Service ID, possibly upgraded */
u8 size_align; /* data size alignment (for security) */
u8 security_size; /* security header size */
u8 security_ix; /* security type */ u8 security_ix; /* security type */
u8 out_clientflag; /* RXRPC_CLIENT_INITIATED if we are client */ u8 out_clientflag; /* RXRPC_CLIENT_INITIATED if we are client */
u8 bundle_shift; /* Index into bundle->avail_chans */ u8 bundle_shift; /* Index into bundle->avail_chans */
...@@ -888,8 +905,7 @@ struct rxrpc_connection *rxrpc_find_service_conn_rcu(struct rxrpc_peer *, ...@@ -888,8 +905,7 @@ struct rxrpc_connection *rxrpc_find_service_conn_rcu(struct rxrpc_peer *,
struct sk_buff *); struct sk_buff *);
struct rxrpc_connection *rxrpc_prealloc_service_connection(struct rxrpc_net *, gfp_t); struct rxrpc_connection *rxrpc_prealloc_service_connection(struct rxrpc_net *, gfp_t);
void rxrpc_new_incoming_connection(struct rxrpc_sock *, struct rxrpc_connection *, void rxrpc_new_incoming_connection(struct rxrpc_sock *, struct rxrpc_connection *,
const struct rxrpc_security *, struct key *, const struct rxrpc_security *, struct sk_buff *);
struct sk_buff *);
void rxrpc_unpublish_service_conn(struct rxrpc_connection *); void rxrpc_unpublish_service_conn(struct rxrpc_connection *);
/* /*
...@@ -906,10 +922,8 @@ extern const struct rxrpc_security rxrpc_no_security; ...@@ -906,10 +922,8 @@ extern const struct rxrpc_security rxrpc_no_security;
* key.c * key.c
*/ */
extern struct key_type key_type_rxrpc; extern struct key_type key_type_rxrpc;
extern struct key_type key_type_rxrpc_s;
int rxrpc_request_key(struct rxrpc_sock *, sockptr_t , int); int rxrpc_request_key(struct rxrpc_sock *, sockptr_t , int);
int rxrpc_server_keyring(struct rxrpc_sock *, sockptr_t, int);
int rxrpc_get_server_data_key(struct rxrpc_connection *, const void *, time64_t, int rxrpc_get_server_data_key(struct rxrpc_connection *, const void *, time64_t,
u32); u32);
...@@ -1052,17 +1066,26 @@ extern const struct rxrpc_security rxkad; ...@@ -1052,17 +1066,26 @@ extern const struct rxrpc_security rxkad;
* security.c * security.c
*/ */
int __init rxrpc_init_security(void); int __init rxrpc_init_security(void);
const struct rxrpc_security *rxrpc_security_lookup(u8);
void rxrpc_exit_security(void); void rxrpc_exit_security(void);
int rxrpc_init_client_conn_security(struct rxrpc_connection *); int rxrpc_init_client_conn_security(struct rxrpc_connection *);
bool rxrpc_look_up_server_security(struct rxrpc_local *, struct rxrpc_sock *, const struct rxrpc_security *rxrpc_get_incoming_security(struct rxrpc_sock *,
const struct rxrpc_security **, struct key **,
struct sk_buff *); struct sk_buff *);
struct key *rxrpc_look_up_server_security(struct rxrpc_connection *,
struct sk_buff *, u32, u32);
/* /*
* sendmsg.c * sendmsg.c
*/ */
int rxrpc_do_sendmsg(struct rxrpc_sock *, struct msghdr *, size_t); int rxrpc_do_sendmsg(struct rxrpc_sock *, struct msghdr *, size_t);
/*
* server_key.c
*/
extern struct key_type key_type_rxrpc_s;
int rxrpc_server_keyring(struct rxrpc_sock *, sockptr_t, int);
/* /*
* skbuff.c * skbuff.c
*/ */
......
...@@ -261,7 +261,6 @@ static struct rxrpc_call *rxrpc_alloc_incoming_call(struct rxrpc_sock *rx, ...@@ -261,7 +261,6 @@ static struct rxrpc_call *rxrpc_alloc_incoming_call(struct rxrpc_sock *rx,
struct rxrpc_peer *peer, struct rxrpc_peer *peer,
struct rxrpc_connection *conn, struct rxrpc_connection *conn,
const struct rxrpc_security *sec, const struct rxrpc_security *sec,
struct key *key,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct rxrpc_backlog *b = rx->backlog; struct rxrpc_backlog *b = rx->backlog;
...@@ -309,7 +308,7 @@ static struct rxrpc_call *rxrpc_alloc_incoming_call(struct rxrpc_sock *rx, ...@@ -309,7 +308,7 @@ static struct rxrpc_call *rxrpc_alloc_incoming_call(struct rxrpc_sock *rx,
conn->params.local = rxrpc_get_local(local); conn->params.local = rxrpc_get_local(local);
conn->params.peer = peer; conn->params.peer = peer;
rxrpc_see_connection(conn); rxrpc_see_connection(conn);
rxrpc_new_incoming_connection(rx, conn, sec, key, skb); rxrpc_new_incoming_connection(rx, conn, sec, skb);
} else { } else {
rxrpc_get_connection(conn); rxrpc_get_connection(conn);
} }
...@@ -353,7 +352,6 @@ struct rxrpc_call *rxrpc_new_incoming_call(struct rxrpc_local *local, ...@@ -353,7 +352,6 @@ struct rxrpc_call *rxrpc_new_incoming_call(struct rxrpc_local *local,
struct rxrpc_connection *conn; struct rxrpc_connection *conn;
struct rxrpc_peer *peer = NULL; struct rxrpc_peer *peer = NULL;
struct rxrpc_call *call = NULL; struct rxrpc_call *call = NULL;
struct key *key = NULL;
_enter(""); _enter("");
...@@ -374,11 +372,13 @@ struct rxrpc_call *rxrpc_new_incoming_call(struct rxrpc_local *local, ...@@ -374,11 +372,13 @@ struct rxrpc_call *rxrpc_new_incoming_call(struct rxrpc_local *local,
*/ */
conn = rxrpc_find_connection_rcu(local, skb, &peer); conn = rxrpc_find_connection_rcu(local, skb, &peer);
if (!conn && !rxrpc_look_up_server_security(local, rx, &sec, &key, skb)) if (!conn) {
sec = rxrpc_get_incoming_security(rx, skb);
if (!sec)
goto no_call; goto no_call;
}
call = rxrpc_alloc_incoming_call(rx, local, peer, conn, sec, key, skb); call = rxrpc_alloc_incoming_call(rx, local, peer, conn, sec, skb);
key_put(key);
if (!call) { if (!call) {
skb->mark = RXRPC_SKB_MARK_REJECT_BUSY; skb->mark = RXRPC_SKB_MARK_REJECT_BUSY;
goto no_call; goto no_call;
......
...@@ -180,10 +180,6 @@ rxrpc_alloc_client_connection(struct rxrpc_bundle *bundle, gfp_t gfp) ...@@ -180,10 +180,6 @@ rxrpc_alloc_client_connection(struct rxrpc_bundle *bundle, gfp_t gfp)
if (ret < 0) if (ret < 0)
goto error_1; goto error_1;
ret = conn->security->prime_packet_security(conn);
if (ret < 0)
goto error_2;
atomic_inc(&rxnet->nr_conns); atomic_inc(&rxnet->nr_conns);
write_lock(&rxnet->conn_lock); write_lock(&rxnet->conn_lock);
list_add_tail(&conn->proc_link, &rxnet->conn_proc_list); list_add_tail(&conn->proc_link, &rxnet->conn_proc_list);
...@@ -203,8 +199,6 @@ rxrpc_alloc_client_connection(struct rxrpc_bundle *bundle, gfp_t gfp) ...@@ -203,8 +199,6 @@ rxrpc_alloc_client_connection(struct rxrpc_bundle *bundle, gfp_t gfp)
_leave(" = %p", conn); _leave(" = %p", conn);
return conn; return conn;
error_2:
conn->security->clear(conn);
error_1: error_1:
rxrpc_put_client_connection_id(conn); rxrpc_put_client_connection_id(conn);
error_0: error_0:
......
...@@ -333,11 +333,8 @@ static int rxrpc_process_event(struct rxrpc_connection *conn, ...@@ -333,11 +333,8 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = conn->security->init_connection_security(conn); ret = conn->security->init_connection_security(
if (ret < 0) conn, conn->params.key->payload.data[0]);
return ret;
ret = conn->security->prime_packet_security(conn);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -377,7 +374,6 @@ static void rxrpc_secure_connection(struct rxrpc_connection *conn) ...@@ -377,7 +374,6 @@ static void rxrpc_secure_connection(struct rxrpc_connection *conn)
_enter("{%d}", conn->debug_id); _enter("{%d}", conn->debug_id);
ASSERT(conn->security_ix != 0); ASSERT(conn->security_ix != 0);
ASSERT(conn->server_key);
if (conn->security->issue_challenge(conn) < 0) { if (conn->security->issue_challenge(conn) < 0) {
abort_code = RX_CALL_DEAD; abort_code = RX_CALL_DEAD;
......
...@@ -49,7 +49,6 @@ struct rxrpc_connection *rxrpc_alloc_connection(gfp_t gfp) ...@@ -49,7 +49,6 @@ struct rxrpc_connection *rxrpc_alloc_connection(gfp_t gfp)
conn->security = &rxrpc_no_security; conn->security = &rxrpc_no_security;
spin_lock_init(&conn->state_lock); spin_lock_init(&conn->state_lock);
conn->debug_id = atomic_inc_return(&rxrpc_debug_id); conn->debug_id = atomic_inc_return(&rxrpc_debug_id);
conn->size_align = 4;
conn->idle_timestamp = jiffies; conn->idle_timestamp = jiffies;
} }
...@@ -363,7 +362,6 @@ static void rxrpc_destroy_connection(struct rcu_head *rcu) ...@@ -363,7 +362,6 @@ static void rxrpc_destroy_connection(struct rcu_head *rcu)
conn->security->clear(conn); conn->security->clear(conn);
key_put(conn->params.key); key_put(conn->params.key);
key_put(conn->server_key);
rxrpc_put_bundle(conn->bundle); rxrpc_put_bundle(conn->bundle);
rxrpc_put_peer(conn->params.peer); rxrpc_put_peer(conn->params.peer);
......
...@@ -156,7 +156,6 @@ struct rxrpc_connection *rxrpc_prealloc_service_connection(struct rxrpc_net *rxn ...@@ -156,7 +156,6 @@ struct rxrpc_connection *rxrpc_prealloc_service_connection(struct rxrpc_net *rxn
void rxrpc_new_incoming_connection(struct rxrpc_sock *rx, void rxrpc_new_incoming_connection(struct rxrpc_sock *rx,
struct rxrpc_connection *conn, struct rxrpc_connection *conn,
const struct rxrpc_security *sec, const struct rxrpc_security *sec,
struct key *key,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct rxrpc_skb_priv *sp = rxrpc_skb(skb); struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
...@@ -170,7 +169,6 @@ void rxrpc_new_incoming_connection(struct rxrpc_sock *rx, ...@@ -170,7 +169,6 @@ void rxrpc_new_incoming_connection(struct rxrpc_sock *rx,
conn->security_ix = sp->hdr.securityIndex; conn->security_ix = sp->hdr.securityIndex;
conn->out_clientflag = 0; conn->out_clientflag = 0;
conn->security = sec; conn->security = sec;
conn->server_key = key_get(key);
if (conn->security_ix) if (conn->security_ix)
conn->state = RXRPC_CONN_SERVICE_UNSECURED; conn->state = RXRPC_CONN_SERVICE_UNSECURED;
else else
......
...@@ -8,20 +8,25 @@ ...@@ -8,20 +8,25 @@
#include <net/af_rxrpc.h> #include <net/af_rxrpc.h>
#include "ar-internal.h" #include "ar-internal.h"
static int none_init_connection_security(struct rxrpc_connection *conn) static int none_init_connection_security(struct rxrpc_connection *conn,
struct rxrpc_key_token *token)
{ {
return 0; return 0;
} }
static int none_prime_packet_security(struct rxrpc_connection *conn) /*
* Work out how much data we can put in an unsecured packet.
*/
static int none_how_much_data(struct rxrpc_call *call, size_t remain,
size_t *_buf_size, size_t *_data_size, size_t *_offset)
{ {
*_buf_size = *_data_size = min_t(size_t, remain, RXRPC_JUMBO_DATALEN);
*_offset = 0;
return 0; return 0;
} }
static int none_secure_packet(struct rxrpc_call *call, static int none_secure_packet(struct rxrpc_call *call, struct sk_buff *skb,
struct sk_buff *skb, size_t data_size)
size_t data_size,
void *sechdr)
{ {
return 0; return 0;
} }
...@@ -86,8 +91,8 @@ const struct rxrpc_security rxrpc_no_security = { ...@@ -86,8 +91,8 @@ const struct rxrpc_security rxrpc_no_security = {
.init = none_init, .init = none_init,
.exit = none_exit, .exit = none_exit,
.init_connection_security = none_init_connection_security, .init_connection_security = none_init_connection_security,
.prime_packet_security = none_prime_packet_security,
.free_call_crypto = none_free_call_crypto, .free_call_crypto = none_free_call_crypto,
.how_much_data = none_how_much_data,
.secure_packet = none_secure_packet, .secure_packet = none_secure_packet,
.verify_packet = none_verify_packet, .verify_packet = none_verify_packet,
.locate_data = none_locate_data, .locate_data = none_locate_data,
......
This diff is collapsed.
This diff is collapsed.
...@@ -55,7 +55,7 @@ void rxrpc_exit_security(void) ...@@ -55,7 +55,7 @@ void rxrpc_exit_security(void)
/* /*
* look up an rxrpc security module * look up an rxrpc security module
*/ */
static const struct rxrpc_security *rxrpc_security_lookup(u8 security_index) const struct rxrpc_security *rxrpc_security_lookup(u8 security_index)
{ {
if (security_index >= ARRAY_SIZE(rxrpc_security_types)) if (security_index >= ARRAY_SIZE(rxrpc_security_types))
return NULL; return NULL;
...@@ -81,16 +81,17 @@ int rxrpc_init_client_conn_security(struct rxrpc_connection *conn) ...@@ -81,16 +81,17 @@ int rxrpc_init_client_conn_security(struct rxrpc_connection *conn)
if (ret < 0) if (ret < 0)
return ret; return ret;
token = key->payload.data[0]; for (token = key->payload.data[0]; token; token = token->next) {
if (!token)
return -EKEYREJECTED;
sec = rxrpc_security_lookup(token->security_index); sec = rxrpc_security_lookup(token->security_index);
if (!sec) if (sec)
goto found;
}
return -EKEYREJECTED; return -EKEYREJECTED;
found:
conn->security = sec; conn->security = sec;
ret = conn->security->init_connection_security(conn); ret = conn->security->init_connection_security(conn, token);
if (ret < 0) { if (ret < 0) {
conn->security = &rxrpc_no_security; conn->security = &rxrpc_no_security;
return ret; return ret;
...@@ -101,22 +102,16 @@ int rxrpc_init_client_conn_security(struct rxrpc_connection *conn) ...@@ -101,22 +102,16 @@ int rxrpc_init_client_conn_security(struct rxrpc_connection *conn)
} }
/* /*
* Find the security key for a server connection. * Set the ops a server connection.
*/ */
bool rxrpc_look_up_server_security(struct rxrpc_local *local, struct rxrpc_sock *rx, const struct rxrpc_security *rxrpc_get_incoming_security(struct rxrpc_sock *rx,
const struct rxrpc_security **_sec,
struct key **_key,
struct sk_buff *skb) struct sk_buff *skb)
{ {
const struct rxrpc_security *sec; const struct rxrpc_security *sec;
struct rxrpc_skb_priv *sp = rxrpc_skb(skb); struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
key_ref_t kref = NULL;
char kdesc[5 + 1 + 3 + 1];
_enter(""); _enter("");
sprintf(kdesc, "%u:%u", sp->hdr.serviceId, sp->hdr.securityIndex);
sec = rxrpc_security_lookup(sp->hdr.securityIndex); sec = rxrpc_security_lookup(sp->hdr.securityIndex);
if (!sec) { if (!sec) {
trace_rxrpc_abort(0, "SVS", trace_rxrpc_abort(0, "SVS",
...@@ -124,35 +119,72 @@ bool rxrpc_look_up_server_security(struct rxrpc_local *local, struct rxrpc_sock ...@@ -124,35 +119,72 @@ bool rxrpc_look_up_server_security(struct rxrpc_local *local, struct rxrpc_sock
RX_INVALID_OPERATION, EKEYREJECTED); RX_INVALID_OPERATION, EKEYREJECTED);
skb->mark = RXRPC_SKB_MARK_REJECT_ABORT; skb->mark = RXRPC_SKB_MARK_REJECT_ABORT;
skb->priority = RX_INVALID_OPERATION; skb->priority = RX_INVALID_OPERATION;
return false; return NULL;
} }
if (sp->hdr.securityIndex == RXRPC_SECURITY_NONE) if (sp->hdr.securityIndex != RXRPC_SECURITY_NONE &&
goto out; !rx->securities) {
if (!rx->securities) {
trace_rxrpc_abort(0, "SVR", trace_rxrpc_abort(0, "SVR",
sp->hdr.cid, sp->hdr.callNumber, sp->hdr.seq, sp->hdr.cid, sp->hdr.callNumber, sp->hdr.seq,
RX_INVALID_OPERATION, EKEYREJECTED); RX_INVALID_OPERATION, EKEYREJECTED);
skb->mark = RXRPC_SKB_MARK_REJECT_ABORT; skb->mark = RXRPC_SKB_MARK_REJECT_ABORT;
skb->priority = RX_INVALID_OPERATION; skb->priority = sec->no_key_abort;
return false; return NULL;
} }
return sec;
}
/*
* Find the security key for a server connection.
*/
struct key *rxrpc_look_up_server_security(struct rxrpc_connection *conn,
struct sk_buff *skb,
u32 kvno, u32 enctype)
{
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
struct rxrpc_sock *rx;
struct key *key = ERR_PTR(-EKEYREJECTED);
key_ref_t kref = NULL;
char kdesc[5 + 1 + 3 + 1 + 12 + 1 + 12 + 1];
int ret;
_enter("");
if (enctype)
sprintf(kdesc, "%u:%u:%u:%u",
sp->hdr.serviceId, sp->hdr.securityIndex, kvno, enctype);
else if (kvno)
sprintf(kdesc, "%u:%u:%u",
sp->hdr.serviceId, sp->hdr.securityIndex, kvno);
else
sprintf(kdesc, "%u:%u",
sp->hdr.serviceId, sp->hdr.securityIndex);
rcu_read_lock();
rx = rcu_dereference(conn->params.local->service);
if (!rx)
goto out;
/* look through the service's keyring */ /* look through the service's keyring */
kref = keyring_search(make_key_ref(rx->securities, 1UL), kref = keyring_search(make_key_ref(rx->securities, 1UL),
&key_type_rxrpc_s, kdesc, true); &key_type_rxrpc_s, kdesc, true);
if (IS_ERR(kref)) { if (IS_ERR(kref)) {
trace_rxrpc_abort(0, "SVK", key = ERR_CAST(kref);
sp->hdr.cid, sp->hdr.callNumber, sp->hdr.seq, goto out;
sec->no_key_abort, EKEYREJECTED); }
skb->mark = RXRPC_SKB_MARK_REJECT_ABORT;
skb->priority = sec->no_key_abort; key = key_ref_to_ptr(kref);
return false;
ret = key_validate(key);
if (ret < 0) {
key_put(key);
key = ERR_PTR(ret);
goto out;
} }
out: out:
*_sec = sec; rcu_read_unlock();
*_key = key_ref_to_ptr(kref); return key;
return true;
} }
...@@ -327,7 +327,7 @@ static int rxrpc_send_data(struct rxrpc_sock *rx, ...@@ -327,7 +327,7 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
rxrpc_send_ack_packet(call, false, NULL); rxrpc_send_ack_packet(call, false, NULL);
if (!skb) { if (!skb) {
size_t size, chunk, max, space; size_t remain, bufsize, chunk, offset;
_debug("alloc"); _debug("alloc");
...@@ -342,24 +342,21 @@ static int rxrpc_send_data(struct rxrpc_sock *rx, ...@@ -342,24 +342,21 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
goto maybe_error; goto maybe_error;
} }
max = RXRPC_JUMBO_DATALEN; /* Work out the maximum size of a packet. Assume that
max -= call->conn->security_size; * the security header is going to be in the padded
max &= ~(call->conn->size_align - 1UL); * region (enc blocksize), but the trailer is not.
*/
chunk = max; remain = more ? INT_MAX : msg_data_left(msg);
if (chunk > msg_data_left(msg) && !more) ret = call->conn->security->how_much_data(call, remain,
chunk = msg_data_left(msg); &bufsize, &chunk, &offset);
if (ret < 0)
space = chunk + call->conn->size_align; goto maybe_error;
space &= ~(call->conn->size_align - 1UL);
size = space + call->conn->security_size;
_debug("SIZE: %zu/%zu/%zu", chunk, space, size); _debug("SIZE: %zu/%zu @%zu", chunk, bufsize, offset);
/* create a buffer that we can retain until it's ACK'd */ /* create a buffer that we can retain until it's ACK'd */
skb = sock_alloc_send_skb( skb = sock_alloc_send_skb(
sk, size, msg->msg_flags & MSG_DONTWAIT, &ret); sk, bufsize, msg->msg_flags & MSG_DONTWAIT, &ret);
if (!skb) if (!skb)
goto maybe_error; goto maybe_error;
...@@ -371,9 +368,7 @@ static int rxrpc_send_data(struct rxrpc_sock *rx, ...@@ -371,9 +368,7 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
ASSERTCMP(skb->mark, ==, 0); ASSERTCMP(skb->mark, ==, 0);
_debug("HS: %u", call->conn->security_size); __skb_put(skb, offset);
skb_reserve(skb, call->conn->security_size);
skb->len += call->conn->security_size;
sp->remain = chunk; sp->remain = chunk;
if (sp->remain > skb_tailroom(skb)) if (sp->remain > skb_tailroom(skb))
...@@ -422,17 +417,6 @@ static int rxrpc_send_data(struct rxrpc_sock *rx, ...@@ -422,17 +417,6 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
(msg_data_left(msg) == 0 && !more)) { (msg_data_left(msg) == 0 && !more)) {
struct rxrpc_connection *conn = call->conn; struct rxrpc_connection *conn = call->conn;
uint32_t seq; uint32_t seq;
size_t pad;
/* pad out if we're using security */
if (conn->security_ix) {
pad = conn->security_size + skb->mark;
pad = conn->size_align - pad;
pad &= conn->size_align - 1;
_debug("pad %zu", pad);
if (pad)
skb_put_zero(skb, pad);
}
seq = call->tx_top + 1; seq = call->tx_top + 1;
...@@ -446,8 +430,7 @@ static int rxrpc_send_data(struct rxrpc_sock *rx, ...@@ -446,8 +430,7 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
call->tx_winsize) call->tx_winsize)
sp->hdr.flags |= RXRPC_MORE_PACKETS; sp->hdr.flags |= RXRPC_MORE_PACKETS;
ret = call->security->secure_packet( ret = call->security->secure_packet(call, skb, skb->mark);
call, skb, skb->mark, skb->head);
if (ret < 0) if (ret < 0)
goto out; goto out;
......
// SPDX-License-Identifier: GPL-2.0-or-later
/* RxRPC key management
*
* Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* RxRPC keys should have a description of describing their purpose:
* "afs@CAMBRIDGE.REDHAT.COM>
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <crypto/skcipher.h>
#include <linux/module.h>
#include <linux/net.h>
#include <linux/skbuff.h>
#include <linux/key-type.h>
#include <linux/ctype.h>
#include <linux/slab.h>
#include <net/sock.h>
#include <net/af_rxrpc.h>
#include <keys/rxrpc-type.h>
#include <keys/user-type.h>
#include "ar-internal.h"
static int rxrpc_vet_description_s(const char *);
static int rxrpc_preparse_s(struct key_preparsed_payload *);
static void rxrpc_free_preparse_s(struct key_preparsed_payload *);
static void rxrpc_destroy_s(struct key *);
static void rxrpc_describe_s(const struct key *, struct seq_file *);
/*
* rxrpc server keys take "<serviceId>:<securityIndex>[:<sec-specific>]" as the
* description and the key material as the payload.
*/
struct key_type key_type_rxrpc_s = {
.name = "rxrpc_s",
.flags = KEY_TYPE_NET_DOMAIN,
.vet_description = rxrpc_vet_description_s,
.preparse = rxrpc_preparse_s,
.free_preparse = rxrpc_free_preparse_s,
.instantiate = generic_key_instantiate,
.destroy = rxrpc_destroy_s,
.describe = rxrpc_describe_s,
};
/*
* Vet the description for an RxRPC server key.
*/
static int rxrpc_vet_description_s(const char *desc)
{
unsigned long service, sec_class;
char *p;
service = simple_strtoul(desc, &p, 10);
if (*p != ':' || service > 65535)
return -EINVAL;
sec_class = simple_strtoul(p + 1, &p, 10);
if ((*p && *p != ':') || sec_class < 1 || sec_class > 255)
return -EINVAL;
return 0;
}
/*
* Preparse a server secret key.
*/
static int rxrpc_preparse_s(struct key_preparsed_payload *prep)
{
const struct rxrpc_security *sec;
unsigned int service, sec_class;
int n;
_enter("%zu", prep->datalen);
if (!prep->orig_description)
return -EINVAL;
if (sscanf(prep->orig_description, "%u:%u%n", &service, &sec_class, &n) != 2)
return -EINVAL;
sec = rxrpc_security_lookup(sec_class);
if (!sec)
return -ENOPKG;
prep->payload.data[1] = (struct rxrpc_security *)sec;
return sec->preparse_server_key(prep);
}
static void rxrpc_free_preparse_s(struct key_preparsed_payload *prep)
{
const struct rxrpc_security *sec = prep->payload.data[1];
if (sec)
sec->free_preparse_server_key(prep);
}
static void rxrpc_destroy_s(struct key *key)
{
const struct rxrpc_security *sec = key->payload.data[1];
if (sec)
sec->destroy_server_key(key);
}
static void rxrpc_describe_s(const struct key *key, struct seq_file *m)
{
const struct rxrpc_security *sec = key->payload.data[1];
seq_puts(m, key->description);
if (sec && sec->describe_server_key)
sec->describe_server_key(key, m);
}
/*
* grab the security keyring for a server socket
*/
int rxrpc_server_keyring(struct rxrpc_sock *rx, sockptr_t optval, int optlen)
{
struct key *key;
char *description;
_enter("");
if (optlen <= 0 || optlen > PAGE_SIZE - 1)
return -EINVAL;
description = memdup_sockptr_nul(optval, optlen);
if (IS_ERR(description))
return PTR_ERR(description);
key = request_key(&key_type_keyring, description, NULL);
if (IS_ERR(key)) {
kfree(description);
_leave(" = %ld", PTR_ERR(key));
return PTR_ERR(key);
}
rx->securities = key;
kfree(description);
_leave(" = 0 [key %x]", key->serial);
return 0;
}
...@@ -504,6 +504,7 @@ int key_instantiate_and_link(struct key *key, ...@@ -504,6 +504,7 @@ int key_instantiate_and_link(struct key *key,
int ret; int ret;
memset(&prep, 0, sizeof(prep)); memset(&prep, 0, sizeof(prep));
prep.orig_description = key->description;
prep.data = data; prep.data = data;
prep.datalen = datalen; prep.datalen = datalen;
prep.quotalen = key->type->def_datalen; prep.quotalen = key->type->def_datalen;
...@@ -854,6 +855,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, ...@@ -854,6 +855,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
goto error_put_type; goto error_put_type;
memset(&prep, 0, sizeof(prep)); memset(&prep, 0, sizeof(prep));
prep.orig_description = description;
prep.data = payload; prep.data = payload;
prep.datalen = plen; prep.datalen = plen;
prep.quotalen = index_key.type->def_datalen; prep.quotalen = index_key.type->def_datalen;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment