1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0-or-later */
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * CIPSO - Commercial IP Security Option
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * This is an implementation of the CIPSO 2.2 protocol as specified in
6*4882a593Smuzhiyun * draft-ietf-cipso-ipsecurity-01.txt with additional tag types as found in
7*4882a593Smuzhiyun * FIPS-188, copies of both documents can be found in the Documentation
8*4882a593Smuzhiyun * directory. While CIPSO never became a full IETF RFC standard many vendors
9*4882a593Smuzhiyun * have chosen to adopt the protocol and over the years it has become a
10*4882a593Smuzhiyun * de-facto standard for labeled networking.
11*4882a593Smuzhiyun *
12*4882a593Smuzhiyun * Author: Paul Moore <paul@paul-moore.com>
13*4882a593Smuzhiyun */
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun /*
16*4882a593Smuzhiyun * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
17*4882a593Smuzhiyun */
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun #ifndef _CIPSO_IPV4_H
20*4882a593Smuzhiyun #define _CIPSO_IPV4_H
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun #include <linux/types.h>
23*4882a593Smuzhiyun #include <linux/rcupdate.h>
24*4882a593Smuzhiyun #include <linux/list.h>
25*4882a593Smuzhiyun #include <linux/net.h>
26*4882a593Smuzhiyun #include <linux/skbuff.h>
27*4882a593Smuzhiyun #include <net/netlabel.h>
28*4882a593Smuzhiyun #include <net/request_sock.h>
29*4882a593Smuzhiyun #include <linux/atomic.h>
30*4882a593Smuzhiyun #include <linux/refcount.h>
31*4882a593Smuzhiyun #include <asm/unaligned.h>
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun /* known doi values */
34*4882a593Smuzhiyun #define CIPSO_V4_DOI_UNKNOWN 0x00000000
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun /* standard tag types */
37*4882a593Smuzhiyun #define CIPSO_V4_TAG_INVALID 0
38*4882a593Smuzhiyun #define CIPSO_V4_TAG_RBITMAP 1
39*4882a593Smuzhiyun #define CIPSO_V4_TAG_ENUM 2
40*4882a593Smuzhiyun #define CIPSO_V4_TAG_RANGE 5
41*4882a593Smuzhiyun #define CIPSO_V4_TAG_PBITMAP 6
42*4882a593Smuzhiyun #define CIPSO_V4_TAG_FREEFORM 7
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun /* non-standard tag types (tags > 127) */
45*4882a593Smuzhiyun #define CIPSO_V4_TAG_LOCAL 128
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun /* doi mapping types */
48*4882a593Smuzhiyun #define CIPSO_V4_MAP_UNKNOWN 0
49*4882a593Smuzhiyun #define CIPSO_V4_MAP_TRANS 1
50*4882a593Smuzhiyun #define CIPSO_V4_MAP_PASS 2
51*4882a593Smuzhiyun #define CIPSO_V4_MAP_LOCAL 3
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun /* limits */
54*4882a593Smuzhiyun #define CIPSO_V4_MAX_REM_LVLS 255
55*4882a593Smuzhiyun #define CIPSO_V4_INV_LVL 0x80000000
56*4882a593Smuzhiyun #define CIPSO_V4_MAX_LOC_LVLS (CIPSO_V4_INV_LVL - 1)
57*4882a593Smuzhiyun #define CIPSO_V4_MAX_REM_CATS 65534
58*4882a593Smuzhiyun #define CIPSO_V4_INV_CAT 0x80000000
59*4882a593Smuzhiyun #define CIPSO_V4_MAX_LOC_CATS (CIPSO_V4_INV_CAT - 1)
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun /*
62*4882a593Smuzhiyun * CIPSO DOI definitions
63*4882a593Smuzhiyun */
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun /* DOI definition struct */
66*4882a593Smuzhiyun #define CIPSO_V4_TAG_MAXCNT 5
67*4882a593Smuzhiyun struct cipso_v4_doi {
68*4882a593Smuzhiyun u32 doi;
69*4882a593Smuzhiyun u32 type;
70*4882a593Smuzhiyun union {
71*4882a593Smuzhiyun struct cipso_v4_std_map_tbl *std;
72*4882a593Smuzhiyun } map;
73*4882a593Smuzhiyun u8 tags[CIPSO_V4_TAG_MAXCNT];
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun refcount_t refcount;
76*4882a593Smuzhiyun struct list_head list;
77*4882a593Smuzhiyun struct rcu_head rcu;
78*4882a593Smuzhiyun };
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun /* Standard CIPSO mapping table */
81*4882a593Smuzhiyun /* NOTE: the highest order bit (i.e. 0x80000000) is an 'invalid' flag, if the
82*4882a593Smuzhiyun * bit is set then consider that value as unspecified, meaning the
83*4882a593Smuzhiyun * mapping for that particular level/category is invalid */
84*4882a593Smuzhiyun struct cipso_v4_std_map_tbl {
85*4882a593Smuzhiyun struct {
86*4882a593Smuzhiyun u32 *cipso;
87*4882a593Smuzhiyun u32 *local;
88*4882a593Smuzhiyun u32 cipso_size;
89*4882a593Smuzhiyun u32 local_size;
90*4882a593Smuzhiyun } lvl;
91*4882a593Smuzhiyun struct {
92*4882a593Smuzhiyun u32 *cipso;
93*4882a593Smuzhiyun u32 *local;
94*4882a593Smuzhiyun u32 cipso_size;
95*4882a593Smuzhiyun u32 local_size;
96*4882a593Smuzhiyun } cat;
97*4882a593Smuzhiyun };
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun /*
100*4882a593Smuzhiyun * Sysctl Variables
101*4882a593Smuzhiyun */
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun #ifdef CONFIG_NETLABEL
104*4882a593Smuzhiyun extern int cipso_v4_cache_enabled;
105*4882a593Smuzhiyun extern int cipso_v4_cache_bucketsize;
106*4882a593Smuzhiyun extern int cipso_v4_rbm_optfmt;
107*4882a593Smuzhiyun extern int cipso_v4_rbm_strictvalid;
108*4882a593Smuzhiyun #endif
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun /*
111*4882a593Smuzhiyun * DOI List Functions
112*4882a593Smuzhiyun */
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun #ifdef CONFIG_NETLABEL
115*4882a593Smuzhiyun int cipso_v4_doi_add(struct cipso_v4_doi *doi_def,
116*4882a593Smuzhiyun struct netlbl_audit *audit_info);
117*4882a593Smuzhiyun void cipso_v4_doi_free(struct cipso_v4_doi *doi_def);
118*4882a593Smuzhiyun int cipso_v4_doi_remove(u32 doi, struct netlbl_audit *audit_info);
119*4882a593Smuzhiyun struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi);
120*4882a593Smuzhiyun void cipso_v4_doi_putdef(struct cipso_v4_doi *doi_def);
121*4882a593Smuzhiyun int cipso_v4_doi_walk(u32 *skip_cnt,
122*4882a593Smuzhiyun int (*callback) (struct cipso_v4_doi *doi_def, void *arg),
123*4882a593Smuzhiyun void *cb_arg);
124*4882a593Smuzhiyun #else
cipso_v4_doi_add(struct cipso_v4_doi * doi_def,struct netlbl_audit * audit_info)125*4882a593Smuzhiyun static inline int cipso_v4_doi_add(struct cipso_v4_doi *doi_def,
126*4882a593Smuzhiyun struct netlbl_audit *audit_info)
127*4882a593Smuzhiyun {
128*4882a593Smuzhiyun return -ENOSYS;
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun
cipso_v4_doi_free(struct cipso_v4_doi * doi_def)131*4882a593Smuzhiyun static inline void cipso_v4_doi_free(struct cipso_v4_doi *doi_def)
132*4882a593Smuzhiyun {
133*4882a593Smuzhiyun return;
134*4882a593Smuzhiyun }
135*4882a593Smuzhiyun
cipso_v4_doi_remove(u32 doi,struct netlbl_audit * audit_info)136*4882a593Smuzhiyun static inline int cipso_v4_doi_remove(u32 doi,
137*4882a593Smuzhiyun struct netlbl_audit *audit_info)
138*4882a593Smuzhiyun {
139*4882a593Smuzhiyun return 0;
140*4882a593Smuzhiyun }
141*4882a593Smuzhiyun
cipso_v4_doi_getdef(u32 doi)142*4882a593Smuzhiyun static inline struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi)
143*4882a593Smuzhiyun {
144*4882a593Smuzhiyun return NULL;
145*4882a593Smuzhiyun }
146*4882a593Smuzhiyun
cipso_v4_doi_walk(u32 * skip_cnt,int (* callback)(struct cipso_v4_doi * doi_def,void * arg),void * cb_arg)147*4882a593Smuzhiyun static inline int cipso_v4_doi_walk(u32 *skip_cnt,
148*4882a593Smuzhiyun int (*callback) (struct cipso_v4_doi *doi_def, void *arg),
149*4882a593Smuzhiyun void *cb_arg)
150*4882a593Smuzhiyun {
151*4882a593Smuzhiyun return 0;
152*4882a593Smuzhiyun }
153*4882a593Smuzhiyun #endif /* CONFIG_NETLABEL */
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun /*
156*4882a593Smuzhiyun * Label Mapping Cache Functions
157*4882a593Smuzhiyun */
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun #ifdef CONFIG_NETLABEL
160*4882a593Smuzhiyun void cipso_v4_cache_invalidate(void);
161*4882a593Smuzhiyun int cipso_v4_cache_add(const unsigned char *cipso_ptr,
162*4882a593Smuzhiyun const struct netlbl_lsm_secattr *secattr);
163*4882a593Smuzhiyun #else
cipso_v4_cache_invalidate(void)164*4882a593Smuzhiyun static inline void cipso_v4_cache_invalidate(void)
165*4882a593Smuzhiyun {
166*4882a593Smuzhiyun return;
167*4882a593Smuzhiyun }
168*4882a593Smuzhiyun
cipso_v4_cache_add(const unsigned char * cipso_ptr,const struct netlbl_lsm_secattr * secattr)169*4882a593Smuzhiyun static inline int cipso_v4_cache_add(const unsigned char *cipso_ptr,
170*4882a593Smuzhiyun const struct netlbl_lsm_secattr *secattr)
171*4882a593Smuzhiyun {
172*4882a593Smuzhiyun return 0;
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun #endif /* CONFIG_NETLABEL */
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun /*
177*4882a593Smuzhiyun * Protocol Handling Functions
178*4882a593Smuzhiyun */
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun #ifdef CONFIG_NETLABEL
181*4882a593Smuzhiyun void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway);
182*4882a593Smuzhiyun int cipso_v4_getattr(const unsigned char *cipso,
183*4882a593Smuzhiyun struct netlbl_lsm_secattr *secattr);
184*4882a593Smuzhiyun int cipso_v4_sock_setattr(struct sock *sk,
185*4882a593Smuzhiyun const struct cipso_v4_doi *doi_def,
186*4882a593Smuzhiyun const struct netlbl_lsm_secattr *secattr);
187*4882a593Smuzhiyun void cipso_v4_sock_delattr(struct sock *sk);
188*4882a593Smuzhiyun int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr);
189*4882a593Smuzhiyun int cipso_v4_req_setattr(struct request_sock *req,
190*4882a593Smuzhiyun const struct cipso_v4_doi *doi_def,
191*4882a593Smuzhiyun const struct netlbl_lsm_secattr *secattr);
192*4882a593Smuzhiyun void cipso_v4_req_delattr(struct request_sock *req);
193*4882a593Smuzhiyun int cipso_v4_skbuff_setattr(struct sk_buff *skb,
194*4882a593Smuzhiyun const struct cipso_v4_doi *doi_def,
195*4882a593Smuzhiyun const struct netlbl_lsm_secattr *secattr);
196*4882a593Smuzhiyun int cipso_v4_skbuff_delattr(struct sk_buff *skb);
197*4882a593Smuzhiyun int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
198*4882a593Smuzhiyun struct netlbl_lsm_secattr *secattr);
199*4882a593Smuzhiyun unsigned char *cipso_v4_optptr(const struct sk_buff *skb);
200*4882a593Smuzhiyun int cipso_v4_validate(const struct sk_buff *skb, unsigned char **option);
201*4882a593Smuzhiyun #else
cipso_v4_error(struct sk_buff * skb,int error,u32 gateway)202*4882a593Smuzhiyun static inline void cipso_v4_error(struct sk_buff *skb,
203*4882a593Smuzhiyun int error,
204*4882a593Smuzhiyun u32 gateway)
205*4882a593Smuzhiyun {
206*4882a593Smuzhiyun return;
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun
cipso_v4_getattr(const unsigned char * cipso,struct netlbl_lsm_secattr * secattr)209*4882a593Smuzhiyun static inline int cipso_v4_getattr(const unsigned char *cipso,
210*4882a593Smuzhiyun struct netlbl_lsm_secattr *secattr)
211*4882a593Smuzhiyun {
212*4882a593Smuzhiyun return -ENOSYS;
213*4882a593Smuzhiyun }
214*4882a593Smuzhiyun
cipso_v4_sock_setattr(struct sock * sk,const struct cipso_v4_doi * doi_def,const struct netlbl_lsm_secattr * secattr)215*4882a593Smuzhiyun static inline int cipso_v4_sock_setattr(struct sock *sk,
216*4882a593Smuzhiyun const struct cipso_v4_doi *doi_def,
217*4882a593Smuzhiyun const struct netlbl_lsm_secattr *secattr)
218*4882a593Smuzhiyun {
219*4882a593Smuzhiyun return -ENOSYS;
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun
cipso_v4_sock_delattr(struct sock * sk)222*4882a593Smuzhiyun static inline void cipso_v4_sock_delattr(struct sock *sk)
223*4882a593Smuzhiyun {
224*4882a593Smuzhiyun }
225*4882a593Smuzhiyun
cipso_v4_sock_getattr(struct sock * sk,struct netlbl_lsm_secattr * secattr)226*4882a593Smuzhiyun static inline int cipso_v4_sock_getattr(struct sock *sk,
227*4882a593Smuzhiyun struct netlbl_lsm_secattr *secattr)
228*4882a593Smuzhiyun {
229*4882a593Smuzhiyun return -ENOSYS;
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun
cipso_v4_req_setattr(struct request_sock * req,const struct cipso_v4_doi * doi_def,const struct netlbl_lsm_secattr * secattr)232*4882a593Smuzhiyun static inline int cipso_v4_req_setattr(struct request_sock *req,
233*4882a593Smuzhiyun const struct cipso_v4_doi *doi_def,
234*4882a593Smuzhiyun const struct netlbl_lsm_secattr *secattr)
235*4882a593Smuzhiyun {
236*4882a593Smuzhiyun return -ENOSYS;
237*4882a593Smuzhiyun }
238*4882a593Smuzhiyun
cipso_v4_req_delattr(struct request_sock * req)239*4882a593Smuzhiyun static inline void cipso_v4_req_delattr(struct request_sock *req)
240*4882a593Smuzhiyun {
241*4882a593Smuzhiyun return;
242*4882a593Smuzhiyun }
243*4882a593Smuzhiyun
cipso_v4_skbuff_setattr(struct sk_buff * skb,const struct cipso_v4_doi * doi_def,const struct netlbl_lsm_secattr * secattr)244*4882a593Smuzhiyun static inline int cipso_v4_skbuff_setattr(struct sk_buff *skb,
245*4882a593Smuzhiyun const struct cipso_v4_doi *doi_def,
246*4882a593Smuzhiyun const struct netlbl_lsm_secattr *secattr)
247*4882a593Smuzhiyun {
248*4882a593Smuzhiyun return -ENOSYS;
249*4882a593Smuzhiyun }
250*4882a593Smuzhiyun
cipso_v4_skbuff_delattr(struct sk_buff * skb)251*4882a593Smuzhiyun static inline int cipso_v4_skbuff_delattr(struct sk_buff *skb)
252*4882a593Smuzhiyun {
253*4882a593Smuzhiyun return -ENOSYS;
254*4882a593Smuzhiyun }
255*4882a593Smuzhiyun
cipso_v4_skbuff_getattr(const struct sk_buff * skb,struct netlbl_lsm_secattr * secattr)256*4882a593Smuzhiyun static inline int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
257*4882a593Smuzhiyun struct netlbl_lsm_secattr *secattr)
258*4882a593Smuzhiyun {
259*4882a593Smuzhiyun return -ENOSYS;
260*4882a593Smuzhiyun }
261*4882a593Smuzhiyun
cipso_v4_optptr(const struct sk_buff * skb)262*4882a593Smuzhiyun static inline unsigned char *cipso_v4_optptr(const struct sk_buff *skb)
263*4882a593Smuzhiyun {
264*4882a593Smuzhiyun return NULL;
265*4882a593Smuzhiyun }
266*4882a593Smuzhiyun
cipso_v4_validate(const struct sk_buff * skb,unsigned char ** option)267*4882a593Smuzhiyun static inline int cipso_v4_validate(const struct sk_buff *skb,
268*4882a593Smuzhiyun unsigned char **option)
269*4882a593Smuzhiyun {
270*4882a593Smuzhiyun unsigned char *opt = *option;
271*4882a593Smuzhiyun unsigned char err_offset = 0;
272*4882a593Smuzhiyun u8 opt_len = opt[1];
273*4882a593Smuzhiyun u8 opt_iter;
274*4882a593Smuzhiyun u8 tag_len;
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun if (opt_len < 8) {
277*4882a593Smuzhiyun err_offset = 1;
278*4882a593Smuzhiyun goto out;
279*4882a593Smuzhiyun }
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun if (get_unaligned_be32(&opt[2]) == 0) {
282*4882a593Smuzhiyun err_offset = 2;
283*4882a593Smuzhiyun goto out;
284*4882a593Smuzhiyun }
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun for (opt_iter = 6; opt_iter < opt_len;) {
287*4882a593Smuzhiyun if (opt_iter + 1 == opt_len) {
288*4882a593Smuzhiyun err_offset = opt_iter;
289*4882a593Smuzhiyun goto out;
290*4882a593Smuzhiyun }
291*4882a593Smuzhiyun tag_len = opt[opt_iter + 1];
292*4882a593Smuzhiyun if ((tag_len == 0) || (tag_len > (opt_len - opt_iter))) {
293*4882a593Smuzhiyun err_offset = opt_iter + 1;
294*4882a593Smuzhiyun goto out;
295*4882a593Smuzhiyun }
296*4882a593Smuzhiyun opt_iter += tag_len;
297*4882a593Smuzhiyun }
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun out:
300*4882a593Smuzhiyun *option = opt + err_offset;
301*4882a593Smuzhiyun return err_offset;
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun }
304*4882a593Smuzhiyun #endif /* CONFIG_NETLABEL */
305*4882a593Smuzhiyun
306*4882a593Smuzhiyun #endif /* _CIPSO_IPV4_H */
307