15
15
* limitations under the License.
16
16
*/
17
17
18
- use std:: sync:: { Arc , Mutex , MutexGuard , RwLock } ;
18
+ use std:: {
19
+ fmt:: Display ,
20
+ sync:: { Arc , Mutex , MutexGuard , RwLock } ,
21
+ } ;
19
22
20
23
use crate :: {
21
24
data_model:: objects:: { Access , Privilege } ,
@@ -24,6 +27,7 @@ use crate::{
24
27
interaction_model:: messages:: GenericPath ,
25
28
sys:: Psm ,
26
29
tlv:: { FromTLV , TLVElement , TLVList , TLVWriter , TagType , ToTLV } ,
30
+ transport:: session:: MAX_CAT_IDS_PER_NOC ,
27
31
utils:: writebuf:: WriteBuf ,
28
32
} ;
29
33
use log:: error;
@@ -67,23 +71,112 @@ impl ToTLV for AuthMode {
67
71
}
68
72
}
69
73
74
+ /// An accessor can have as many identities: one node id and Upto MAX_CAT_IDS_PER_NOC
75
+ const MAX_ACCESSOR_SUBJECTS : usize = 1 + MAX_CAT_IDS_PER_NOC ;
76
+ /// The CAT Prefix used in Subjects
77
+ pub const NOC_CAT_SUBJECT_PREFIX : u64 = 0xFFFF_FFFD_0000_0000 ;
78
+ const NOC_CAT_ID_MASK : u64 = 0xFFFF_0000 ;
79
+ const NOC_CAT_VERSION_MASK : u64 = 0xFFFF ;
80
+
81
+ fn is_noc_cat ( id : u64 ) -> bool {
82
+ ( id & NOC_CAT_SUBJECT_PREFIX ) == NOC_CAT_SUBJECT_PREFIX
83
+ }
84
+
85
+ fn get_noc_cat_id ( id : u64 ) -> u64 {
86
+ ( id & NOC_CAT_ID_MASK ) >> 16
87
+ }
88
+
89
+ fn get_noc_cat_version ( id : u64 ) -> u64 {
90
+ id & NOC_CAT_VERSION_MASK
91
+ }
92
+
93
+ /// Generate CAT that is embeddedable in the NoC
94
+ /// This only generates the 32-bit CAT ID
95
+ pub fn gen_noc_cat ( id : u16 , version : u16 ) -> u32 {
96
+ ( ( id as u32 ) << 16 ) | version as u32
97
+ }
98
+
99
+ pub struct AccessorSubjects ( [ u64 ; MAX_ACCESSOR_SUBJECTS ] ) ;
100
+
101
+ impl AccessorSubjects {
102
+ pub fn new ( id : u64 ) -> Self {
103
+ let mut a = Self ( Default :: default ( ) ) ;
104
+ a. 0 [ 0 ] = id;
105
+ a
106
+ }
107
+
108
+ pub fn add_catid ( & mut self , subject : u32 ) -> Result < ( ) , Error > {
109
+ for ( i, val) in self . 0 . iter ( ) . enumerate ( ) {
110
+ if * val == 0 {
111
+ self . 0 [ i] = NOC_CAT_SUBJECT_PREFIX | ( subject as u64 ) ;
112
+ return Ok ( ( ) ) ;
113
+ }
114
+ }
115
+ Err ( Error :: NoSpace )
116
+ }
117
+
118
+ /// Match the match_subject with any of the current subjects
119
+ /// If a NOC CAT is specified, CAT aware matching is also performed
120
+ pub fn matches ( & self , acl_subject : u64 ) -> bool {
121
+ for v in self . 0 . iter ( ) {
122
+ if * v == 0 {
123
+ continue ;
124
+ }
125
+
126
+ if * v == acl_subject {
127
+ return true ;
128
+ } else {
129
+ // NOC CAT match
130
+ if is_noc_cat ( * v)
131
+ && is_noc_cat ( acl_subject)
132
+ && ( get_noc_cat_id ( * v) == get_noc_cat_id ( acl_subject) )
133
+ && ( get_noc_cat_version ( * v) >= get_noc_cat_version ( acl_subject) )
134
+ {
135
+ return true ;
136
+ }
137
+ }
138
+ }
139
+
140
+ false
141
+ }
142
+ }
143
+
144
+ impl Display for AccessorSubjects {
145
+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: result:: Result < ( ) , std:: fmt:: Error > {
146
+ write ! ( f, "[" ) ?;
147
+ for i in self . 0 {
148
+ if is_noc_cat ( i) {
149
+ write ! ( f, "CAT({} - {})" , get_noc_cat_id( i) , get_noc_cat_version( i) ) ?;
150
+ } else if i != 0 {
151
+ write ! ( f, "{}, " , i) ?;
152
+ }
153
+ }
154
+ write ! ( f, "]" )
155
+ }
156
+ }
157
+
70
158
/// The Accessor Object
71
159
pub struct Accessor {
72
160
/// The fabric index of the accessor
73
161
pub fab_idx : u8 ,
74
- /// Accessor's identified : could be node-id, NoC CAT, group id
75
- id : u64 ,
162
+ /// Accessor's subject : could be node-id, NoC CAT, group id
163
+ subjects : AccessorSubjects ,
76
164
/// The Authmode of this session
77
165
auth_mode : AuthMode ,
78
166
// TODO: Is this the right place for this though, or should we just use a global-acl-handle-get
79
167
acl_mgr : Arc < AclMgr > ,
80
168
}
81
169
82
170
impl Accessor {
83
- pub fn new ( fab_idx : u8 , id : u64 , auth_mode : AuthMode , acl_mgr : Arc < AclMgr > ) -> Self {
171
+ pub fn new (
172
+ fab_idx : u8 ,
173
+ subjects : AccessorSubjects ,
174
+ auth_mode : AuthMode ,
175
+ acl_mgr : Arc < AclMgr > ,
176
+ ) -> Self {
84
177
Self {
85
178
fab_idx,
86
- id ,
179
+ subjects ,
87
180
auth_mode,
88
181
acl_mgr,
89
182
}
@@ -196,6 +289,10 @@ impl AclEntry {
196
289
Ok ( ( ) )
197
290
}
198
291
292
+ pub fn add_subject_catid ( & mut self , cat_id : u32 ) -> Result < ( ) , Error > {
293
+ self . add_subject ( NOC_CAT_SUBJECT_PREFIX | cat_id as u64 )
294
+ }
295
+
199
296
pub fn add_target ( & mut self , target : Target ) -> Result < ( ) , Error > {
200
297
let index = self
201
298
. targets
@@ -215,7 +312,7 @@ impl AclEntry {
215
312
let mut entries_exist = false ;
216
313
for i in self . subjects . iter ( ) . flatten ( ) {
217
314
entries_exist = true ;
218
- if accessor. id == * i {
315
+ if accessor. subjects . matches ( * i ) {
219
316
allow = true ;
220
317
}
221
318
}
@@ -467,8 +564,8 @@ impl AclMgr {
467
564
}
468
565
}
469
566
error ! (
470
- "ACL Disallow for src id {} fab idx {}" ,
471
- req. accessor. id , req. accessor. fab_idx
567
+ "ACL Disallow for subjects {} fab idx {}" ,
568
+ req. accessor. subjects , req. accessor. fab_idx
472
569
) ;
473
570
error ! ( "{}" , self ) ;
474
571
false
@@ -490,6 +587,7 @@ impl std::fmt::Display for AclMgr {
490
587
#[ allow( clippy:: bool_assert_comparison) ]
491
588
mod tests {
492
589
use crate :: {
590
+ acl:: { gen_noc_cat, AccessorSubjects } ,
493
591
data_model:: objects:: { Access , Privilege } ,
494
592
interaction_model:: messages:: GenericPath ,
495
593
} ;
@@ -501,7 +599,7 @@ mod tests {
501
599
fn test_basic_empty_subject_target ( ) {
502
600
let am = Arc :: new ( AclMgr :: new_with ( false ) . unwrap ( ) ) ;
503
601
am. erase_all ( ) ;
504
- let accessor = Accessor :: new ( 2 , 112233 , AuthMode :: Case , am. clone ( ) ) ;
602
+ let accessor = Accessor :: new ( 2 , AccessorSubjects :: new ( 112233 ) , AuthMode :: Case , am. clone ( ) ) ;
505
603
let path = GenericPath :: new ( Some ( 1 ) , Some ( 1234 ) , None ) ;
506
604
let mut req = AccessReq :: new ( & accessor, & path, Access :: READ ) ;
507
605
req. set_target_perms ( Access :: RWVA ) ;
@@ -529,7 +627,7 @@ mod tests {
529
627
fn test_subject ( ) {
530
628
let am = Arc :: new ( AclMgr :: new_with ( false ) . unwrap ( ) ) ;
531
629
am. erase_all ( ) ;
532
- let accessor = Accessor :: new ( 2 , 112233 , AuthMode :: Case , am. clone ( ) ) ;
630
+ let accessor = Accessor :: new ( 2 , AccessorSubjects :: new ( 112233 ) , AuthMode :: Case , am. clone ( ) ) ;
533
631
let path = GenericPath :: new ( Some ( 1 ) , Some ( 1234 ) , None ) ;
534
632
let mut req = AccessReq :: new ( & accessor, & path, Access :: READ ) ;
535
633
req. set_target_perms ( Access :: RWVA ) ;
@@ -547,11 +645,81 @@ mod tests {
547
645
assert_eq ! ( req. allow( ) , true ) ;
548
646
}
549
647
648
+ #[ test]
649
+ fn test_cat ( ) {
650
+ let am = Arc :: new ( AclMgr :: new_with ( false ) . unwrap ( ) ) ;
651
+ am. erase_all ( ) ;
652
+
653
+ let allow_cat = 0xABCD ;
654
+ let disallow_cat = 0xCAFE ;
655
+ let v2 = 2 ;
656
+ let v3 = 3 ;
657
+ // Accessor has nodeif and CAT 0xABCD_0002
658
+ let mut subjects = AccessorSubjects :: new ( 112233 ) ;
659
+ subjects. add_catid ( gen_noc_cat ( allow_cat, v2) ) . unwrap ( ) ;
660
+
661
+ let accessor = Accessor :: new ( 2 , subjects, AuthMode :: Case , am. clone ( ) ) ;
662
+ let path = GenericPath :: new ( Some ( 1 ) , Some ( 1234 ) , None ) ;
663
+ let mut req = AccessReq :: new ( & accessor, & path, Access :: READ ) ;
664
+ req. set_target_perms ( Access :: RWVA ) ;
665
+
666
+ // Deny for CAT id mismatch
667
+ let mut new = AclEntry :: new ( 2 , Privilege :: VIEW , AuthMode :: Case ) ;
668
+ new. add_subject_catid ( gen_noc_cat ( disallow_cat, v2) )
669
+ . unwrap ( ) ;
670
+ am. add ( new) . unwrap ( ) ;
671
+ assert_eq ! ( req. allow( ) , false ) ;
672
+
673
+ // Deny of CAT version mismatch
674
+ let mut new = AclEntry :: new ( 2 , Privilege :: VIEW , AuthMode :: Case ) ;
675
+ new. add_subject_catid ( gen_noc_cat ( allow_cat, v3) ) . unwrap ( ) ;
676
+ am. add ( new) . unwrap ( ) ;
677
+ assert_eq ! ( req. allow( ) , false ) ;
678
+
679
+ // Allow for CAT match
680
+ let mut new = AclEntry :: new ( 2 , Privilege :: VIEW , AuthMode :: Case ) ;
681
+ new. add_subject_catid ( gen_noc_cat ( allow_cat, v2) ) . unwrap ( ) ;
682
+ am. add ( new) . unwrap ( ) ;
683
+ assert_eq ! ( req. allow( ) , true ) ;
684
+ }
685
+
686
+ #[ test]
687
+ fn test_cat_version ( ) {
688
+ let am = Arc :: new ( AclMgr :: new_with ( false ) . unwrap ( ) ) ;
689
+ am. erase_all ( ) ;
690
+
691
+ let allow_cat = 0xABCD ;
692
+ let disallow_cat = 0xCAFE ;
693
+ let v2 = 2 ;
694
+ let v3 = 3 ;
695
+ // Accessor has nodeif and CAT 0xABCD_0003
696
+ let mut subjects = AccessorSubjects :: new ( 112233 ) ;
697
+ subjects. add_catid ( gen_noc_cat ( allow_cat, v3) ) . unwrap ( ) ;
698
+
699
+ let accessor = Accessor :: new ( 2 , subjects, AuthMode :: Case , am. clone ( ) ) ;
700
+ let path = GenericPath :: new ( Some ( 1 ) , Some ( 1234 ) , None ) ;
701
+ let mut req = AccessReq :: new ( & accessor, & path, Access :: READ ) ;
702
+ req. set_target_perms ( Access :: RWVA ) ;
703
+
704
+ // Deny for CAT id mismatch
705
+ let mut new = AclEntry :: new ( 2 , Privilege :: VIEW , AuthMode :: Case ) ;
706
+ new. add_subject_catid ( gen_noc_cat ( disallow_cat, v2) )
707
+ . unwrap ( ) ;
708
+ am. add ( new) . unwrap ( ) ;
709
+ assert_eq ! ( req. allow( ) , false ) ;
710
+
711
+ // Allow for CAT match and version more than ACL version
712
+ let mut new = AclEntry :: new ( 2 , Privilege :: VIEW , AuthMode :: Case ) ;
713
+ new. add_subject_catid ( gen_noc_cat ( allow_cat, v2) ) . unwrap ( ) ;
714
+ am. add ( new) . unwrap ( ) ;
715
+ assert_eq ! ( req. allow( ) , true ) ;
716
+ }
717
+
550
718
#[ test]
551
719
fn test_target ( ) {
552
720
let am = Arc :: new ( AclMgr :: new_with ( false ) . unwrap ( ) ) ;
553
721
am. erase_all ( ) ;
554
- let accessor = Accessor :: new ( 2 , 112233 , AuthMode :: Case , am. clone ( ) ) ;
722
+ let accessor = Accessor :: new ( 2 , AccessorSubjects :: new ( 112233 ) , AuthMode :: Case , am. clone ( ) ) ;
555
723
let path = GenericPath :: new ( Some ( 1 ) , Some ( 1234 ) , None ) ;
556
724
let mut req = AccessReq :: new ( & accessor, & path, Access :: READ ) ;
557
725
req. set_target_perms ( Access :: RWVA ) ;
@@ -612,7 +780,8 @@ mod tests {
612
780
fn test_privilege ( ) {
613
781
let am = Arc :: new ( AclMgr :: new_with ( false ) . unwrap ( ) ) ;
614
782
am. erase_all ( ) ;
615
- let accessor = Accessor :: new ( 2 , 112233 , AuthMode :: Case , am. clone ( ) ) ;
783
+
784
+ let accessor = Accessor :: new ( 2 , AccessorSubjects :: new ( 112233 ) , AuthMode :: Case , am. clone ( ) ) ;
616
785
let path = GenericPath :: new ( Some ( 1 ) , Some ( 1234 ) , None ) ;
617
786
618
787
// Create an Exact Match ACL with View privilege
0 commit comments