xref: /linux/fs/afs/cm_security.c (revision 9d1d2b59341f58126a69b51f9f5f8ccb9f12e54a)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Cache manager security.
3  *
4  * Copyright (C) 2025 Red Hat, Inc. All Rights Reserved.
5  * Written by David Howells (dhowells@redhat.com)
6  */
7 
8 #include <linux/slab.h>
9 #include <crypto/krb5.h>
10 #include "internal.h"
11 #include "afs_fs.h"
12 #include "protocol_yfs.h"
13 #define RXRPC_TRACE_ONLY_DEFINE_ENUMS
14 #include <trace/events/rxrpc.h>
15 
16 /*
17  * Respond to an RxGK challenge, adding appdata.
18  */
19 static int afs_respond_to_challenge(struct sk_buff *challenge)
20 {
21 #ifdef CONFIG_RXGK
22 	struct krb5_buffer appdata = {};
23 #endif
24 	struct rxrpc_peer *peer;
25 	unsigned long peer_data;
26 	u16 service_id;
27 	u8 security_index;
28 
29 	rxrpc_kernel_query_challenge(challenge, &peer, &peer_data,
30 				     &service_id, &security_index);
31 
32 	_enter("%u,%u", service_id, security_index);
33 
34 	switch (service_id) {
35 		/* We don't send CM_SERVICE RPCs, so don't expect a challenge
36 		 * therefrom.
37 		 */
38 	case FS_SERVICE:
39 	case VL_SERVICE:
40 	case YFS_FS_SERVICE:
41 	case YFS_VL_SERVICE:
42 		break;
43 	default:
44 		pr_warn("Can't respond to unknown challenge %u:%u",
45 			service_id, security_index);
46 		return rxrpc_kernel_reject_challenge(challenge, RX_USER_ABORT, -EPROTO,
47 						     afs_abort_unsupported_sec_class);
48 	}
49 
50 	switch (security_index) {
51 #ifdef CONFIG_RXKAD
52 	case RXRPC_SECURITY_RXKAD:
53 		return rxkad_kernel_respond_to_challenge(challenge);
54 #endif
55 
56 #ifdef CONFIG_RXGK
57 	case RXRPC_SECURITY_RXGK:
58 	case RXRPC_SECURITY_YFS_RXGK:
59 		return rxgk_kernel_respond_to_challenge(challenge, &appdata);
60 #endif
61 
62 	default:
63 		return rxrpc_kernel_reject_challenge(challenge, RX_USER_ABORT, -EPROTO,
64 						     afs_abort_unsupported_sec_class);
65 	}
66 }
67 
68 /*
69  * Process the OOB message queue, processing challenge packets.
70  */
71 void afs_process_oob_queue(struct work_struct *work)
72 {
73 	struct afs_net *net = container_of(work, struct afs_net, rx_oob_work);
74 	struct sk_buff *oob;
75 	enum rxrpc_oob_type type;
76 
77 	while ((oob = rxrpc_kernel_dequeue_oob(net->socket, &type))) {
78 		switch (type) {
79 		case RXRPC_OOB_CHALLENGE:
80 			afs_respond_to_challenge(oob);
81 			break;
82 		}
83 		rxrpc_kernel_free_oob(oob);
84 	}
85 }
86