Advertisement
Guest User

Untitled

a guest
Jan 24th, 2017
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.42 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, Hash};
  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<T: Hash + Eq> {
  26. domain: Option<T>,
  27. actions: Option<SeaHashSet<T>>,
  28. targets: Option<SeaHashSet<T>>
  29. }
  30.  
  31. impl<'a> Permission<&'a str> {
  32. fn new(wildcard_perm: &str) -> Permission<&str> {
  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_str(&self, wildcard_permission: &str) -> bool {
  69. let permission = Permission::new(wildcard_permission);
  70. self.implies_from_perm(&permission)
  71. }
  72. }
  73.  
  74. impl<T> Permission<T> where T: Hash + Eq {
  75. fn implies_from_perm(&self, permission: &Permission<T>) -> bool {
  76. match (self.domain.as_ref(), permission.domain.as_ref()) {
  77. (Some(ref my_domain), Some(ref other_domain)) if my_domain != other_domain => {
  78. return false;
  79. }
  80. _ => {}
  81. }
  82.  
  83. match (self.actions.as_ref(), permission.actions.as_ref()) {
  84. (Some(my_set), Some(other_set)) if !my_set.is_superset(other_set) => {
  85. return false;
  86. }
  87. (None, Some(_)) => return false,
  88. _ => {}
  89. }
  90.  
  91. match (self.actions.as_ref(), permission.actions.as_ref()) {
  92. (Some(my_set), Some(other_set)) if !my_set.is_superset(other_set) => {
  93. return false;
  94. }
  95. (None, Some(_)) => return false,
  96. _ => {}
  97. }
  98.  
  99. return true;
  100. }
  101. }
  102.  
  103. #[no_mangle]
  104. pub extern fn is_permitted_from_str(required_perm: *const c_char, assigned_perms: *const *const c_char, assigned_perms_len: size_t) -> i32 {
  105.  
  106. let res = panic::catch_unwind(|| {
  107. let ffi_required_permission = unsafe {CStr::from_ptr(required_perm)};
  108. let required_permission = match ffi_required_permission.to_str() {
  109. Ok(s) => s,
  110. Err(_) => return -1
  111. };
  112.  
  113. let perms = unsafe {slice::from_raw_parts(assigned_perms, assigned_perms_len as usize)};
  114. let assigned_permissions = perms.iter()
  115. .map(|&p| unsafe { CStr::from_ptr(p) })
  116. .map(|cs| cs.to_bytes())
  117. .map(|bs| str::from_utf8(bs).unwrap_or_else(|_| ""));
  118.  
  119. _is_permitted_from_str(required_permission, assigned_permissions)
  120. });
  121.  
  122. match res {
  123. Ok(rc) => rc,
  124. Err(_) => -1,
  125. }
  126. }
  127.  
  128. fn _is_permitted_from_str<'a, I>(required_perm: &str, assigned_perms: I) -> i32
  129. where I: IntoIterator<Item=&'a str>
  130. {
  131. let required_permission = Permission::new(&required_perm);
  132.  
  133. for assigned in assigned_perms {
  134. let assigned_permission = Permission::new(assigned);
  135. if assigned_permission.implies_from_perm(&required_permission){
  136. return 1;
  137. }
  138. }
  139. return 0;
  140. }
  141.  
  142. fn test_perm() {
  143. let required_perm = "domain1:action4:target4";
  144. let assigned_perms: Vec<&str> = vec!("domain1:action1", "domain1:action2", "domain1:action4");
  145. let _ = _is_permitted_from_str(&required_perm, assigned_perms);
  146. }
  147.  
  148. #[bench]
  149. fn test_is_permitted_from_str(b: &mut Bencher) {
  150. b.iter(|| test_perm())
  151. }
  152.  
  153. fn main() {
  154. let perm1: Permission<&str> = Permission::new("domain1:action1");
  155. let perm2: Permission<&str> = Permission::new("domain1:action1,action2");
  156. let perm3: Permission<&str> = Permission::new("domain1:action1,action2:target1");
  157. let perm4: Permission<&str> = Permission::new("domain1:action3,action4:target2,target3");
  158. let perm5: Permission<&str> = Permission::new("domain1:action1,action2,action3,action4");
  159.  
  160. assert_eq!(perm5.implies_from_perm(&perm1), true);
  161. assert_eq!(perm5.implies_from_perm(&perm2), true);
  162. assert_eq!(perm5.implies_from_perm(&perm3), true);
  163. assert_eq!(perm5.implies_from_perm(&perm4), true);
  164. assert_eq!(perm1.implies_from_perm(&perm5), false);
  165. assert_eq!(perm3.implies_from_perm(&perm5), false);
  166.  
  167. assert_eq!(perm5.implies_from_str("domain1:action1"), true);
  168. assert_eq!(perm5.implies_from_str("domain1:action3, action4:target2, target3"), true);
  169. assert_eq!(perm1.implies_from_str("domain1:action3, action4:target2, target3"), false);
  170. assert_eq!(perm3.implies_from_str("domain1:action3, action4:target2, target3"), false);
  171. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement