Advertisement
Guest User

Untitled

a guest
Jan 24th, 2017
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.27 KB | None | 0 0
  1. #![feature(libc)]
  2. #![feature(test)]
  3. extern crate libc;
  4. extern crate test;
  5. extern crate seahash;
  6.  
  7. use std::slice;
  8. use std::ffi::CStr;
  9. use std::panic;
  10. use std::str;
  11. use libc::{size_t, c_char};
  12. use std::collections::HashSet;
  13. use std::hash::BuildHasherDefault;
  14. use test::Bencher;
  15. use seahash::SeaHasher;
  16.  
  17. type SeaHashSet<K> = HashSet<K, BuildHasherDefault<SeaHasher>>;
  18.  
  19.  
  20. static PART_DELIMETER: &'static str = ":";
  21. static SUBPART_DELIMETER: &'static str = ",";
  22.  
  23.  
  24. #[derive(Debug)]
  25. struct Permission<'a> {
  26. domain: Option<&'a str>,
  27. actions: Option<SeaHashSet<&'a str>>,
  28. targets: Option<SeaHashSet<&'a str>>
  29. }
  30.  
  31. impl<'a> Permission<'a> {
  32. fn new(wildcard_perm: &str) -> Permission {
  33. let mut perm = Permission {
  34. domain: None,
  35. actions: None,
  36. targets: None,
  37. };
  38. perm.init_parts(wildcard_perm);
  39. perm
  40. }
  41.  
  42. fn part_from_str(s: Option<&str>) -> Option<SeaHashSet<&str>> {
  43. match s {
  44. Some("") | None => None,
  45. Some(s) => {
  46. let mut set = SeaHashSet::default();
  47. for rule in s.split(SUBPART_DELIMETER).map(str::trim) {
  48. if rule == "*" { return None }
  49. set.insert(rule);
  50. }
  51. Some(set)
  52. }
  53. }
  54.  
  55. }
  56.  
  57. fn init_parts(&mut self, wildcard_perm: &'a str) {
  58. let mut iter = wildcard_perm.split(PART_DELIMETER).map(str::trim);
  59.  
  60. self.domain = match iter.next() {
  61. Some("") | Some("*") | None => None,
  62. domain => domain
  63. };
  64. self.actions = Permission::part_from_str(iter.next());
  65. self.targets = Permission::part_from_str(iter.next());
  66. }
  67.  
  68. fn implies_from_perm(&self, permission: &Permission) -> bool {
  69. match (self.domain, permission.domain) {
  70. (Some(my_domain), Some(other_domain)) if my_domain != other_domain => return false,
  71. _ => {}
  72. }
  73.  
  74. match (self.actions.as_ref(), permission.actions.as_ref()) {
  75. (Some(my_set), Some(other_set)) if !my_set.is_superset(other_set) => {
  76. return false;
  77. }
  78. (None, Some(_)) => return false,
  79. _ => {}
  80. }
  81.  
  82. match (self.actions.as_ref(), permission.actions.as_ref()) {
  83. (Some(my_set), Some(other_set)) if !my_set.is_superset(other_set) => {
  84. return false;
  85. }
  86. (None, Some(_)) => return false,
  87. _ => {}
  88. }
  89.  
  90. return true;
  91. }
  92.  
  93. fn implies_from_str(&self, wildcard_permission: &str) -> bool {
  94. let permission = Permission::new(wildcard_permission);
  95. self.implies_from_perm(&permission)
  96. }
  97. }
  98.  
  99. #[no_mangle]
  100. pub extern fn is_permitted_from_str(required_perm: *const c_char, assigned_perms: *const *const c_char, assigned_perms_len: size_t) -> i32 {
  101.  
  102. let res = panic::catch_unwind(|| {
  103. let ffi_required_permission = unsafe {CStr::from_ptr(required_perm)};
  104. let required_permission = match ffi_required_permission.to_str() {
  105. Ok(s) => s,
  106. Err(_) => return -1
  107. };
  108.  
  109. let perms = unsafe {slice::from_raw_parts(assigned_perms, assigned_perms_len as usize)};
  110. let assigned_permissions = perms.iter()
  111. .map(|&p| unsafe { CStr::from_ptr(p) })
  112. .map(|cs| cs.to_bytes())
  113. .map(|bs| str::from_utf8(bs).unwrap_or_else(|_| ""));
  114.  
  115. _is_permitted_from_str(required_permission, assigned_permissions)
  116. });
  117.  
  118. match res {
  119. Ok(rc) => rc,
  120. Err(_) => -1,
  121. }
  122. }
  123.  
  124. fn _is_permitted_from_str<'a, I>(required_perm: &str, assigned_perms: I) -> i32
  125. where I: IntoIterator<Item=&'a str>
  126. {
  127. let required_permission = Permission::new(&required_perm);
  128.  
  129. for assigned in assigned_perms {
  130. let assigned_permission = Permission::new(assigned);
  131. if assigned_permission.implies_from_perm(&required_permission){
  132. return 1;
  133. }
  134. }
  135. return 0;
  136. }
  137.  
  138. fn test_perm() {
  139. let required_perm = "domain1:action4:target4";
  140. let assigned_perms: Vec<&str> = vec!("domain1:action1", "domain1:action2", "domain1:action4");
  141. let _ = _is_permitted_from_str(&required_perm, assigned_perms);
  142. }
  143.  
  144. #[bench]
  145. fn test_is_permitted_from_str(b: &mut Bencher) {
  146. b.iter(|| test_perm())
  147. }
  148.  
  149. fn main() {
  150. let perm1: Permission = Permission::new("domain1:action1");
  151. let perm2: Permission = Permission::new("domain1:action1,action2");
  152. let perm3: Permission = Permission::new("domain1:action1,action2:target1");
  153. let perm4: Permission = Permission::new("domain1:action3,action4:target2,target3");
  154. let perm5: Permission = Permission::new("domain1:action1,action2,action3,action4");
  155.  
  156. assert_eq!(perm5.implies_from_perm(&perm1), true);
  157. assert_eq!(perm5.implies_from_perm(&perm2), true);
  158. assert_eq!(perm5.implies_from_perm(&perm3), true);
  159. assert_eq!(perm5.implies_from_perm(&perm4), true);
  160. assert_eq!(perm1.implies_from_perm(&perm5), false);
  161. assert_eq!(perm3.implies_from_perm(&perm5), false);
  162.  
  163. assert_eq!(perm5.implies_from_str("domain1:action1"), true);
  164. assert_eq!(perm5.implies_from_str("domain1:action3, action4:target2, target3"), true);
  165. assert_eq!(perm1.implies_from_str("domain1:action3, action4:target2, target3"), false);
  166. assert_eq!(perm3.implies_from_str("domain1:action3, action4:target2, target3"), false);
  167. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement