1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
use std::collections::HashMap; use lber::structure::{PL, StructureTag}; use lber::structures::{ASNTag, Boolean, OctetString, Sequence, Tag}; use lber::universal::Types; pub mod types { pub type ControlType = self::inner::_ControlType; pub use self::inner::_ControlType::{PagedResults, RelaxRules}; mod inner { #[derive(Clone, Copy, Debug)] pub enum _ControlType { PagedResults, RelaxRules, #[doc(hidden)] _Nonexhaustive, } } } use self::types::ControlType; mod paged_results; pub use self::paged_results::PagedResults; mod relax_rules; pub use self::relax_rules::RelaxRules; lazy_static! { static ref CONTROLS: HashMap<&'static str, ControlType> = { let mut map = HashMap::new(); map.insert(self::paged_results::PAGED_RESULTS_OID, types::PagedResults); map }; } pub trait MakeCritical { fn critical(self) -> CriticalControl<Self> where Self: Sized { CriticalControl { control: self, } } } pub struct CriticalControl<T> { control: T } impl<T> From<CriticalControl<T>> for StructureTag where T: Oid, Option<Vec<u8>>: From<T> { fn from(cc: CriticalControl<T>) -> StructureTag { let oid = cc.control.oid(); construct_control(oid, true, cc.control.into()) } } pub trait Oid { fn oid(&self) -> &'static str; } pub trait ControlParser { fn parse(&[u8]) -> Self; } pub fn parse_control<T: ControlParser>(val: &[u8]) -> T { T::parse(val) } #[derive(Clone, Debug)] pub struct Control(pub Option<ControlType>, pub RawControl); #[derive(Clone, Debug)] pub struct RawControl { pub ctype: String, pub crit: bool, pub val: Option<Vec<u8>>, } impl From<RawControl> for StructureTag { fn from(ctrl: RawControl) -> StructureTag { construct_control(&ctrl.ctype, ctrl.crit, ctrl.val) } } pub fn construct_control(oid: &str, crit: bool, val: Option<Vec<u8>>) -> StructureTag { let mut seq = vec![ Tag::OctetString(OctetString { inner: Vec::from(oid.as_bytes()), .. Default::default() }) ]; if crit { seq.push(Tag::Boolean(Boolean { inner: true, .. Default::default() })); } if let Some(val) = val { seq.push(Tag::OctetString(OctetString { inner: val, .. Default::default() })); } Tag::Sequence(Sequence { inner: seq, .. Default::default() }).into_structure() } pub fn parse_controls(t: StructureTag) -> Vec<Control> { let tags = t.expect_constructed().expect("result sequence").into_iter(); let mut ctrls = Vec::new(); for ctrl in tags { let mut components = ctrl.expect_constructed().expect("components").into_iter(); let ctype = String::from_utf8(components.next().expect("element").expect_primitive().expect("octet string")).expect("control type"); let next = components.next(); let (crit, maybe_val) = match next { None => (false, None), Some(c) => match c { StructureTag { id, class: _, ref payload } if id == Types::Boolean as u64 => match *payload { PL::P(ref v) => (v[0] != 0, components.next()), PL::C(_) => panic!("decoding error"), }, StructureTag { id, class: _, payload: _ } if id == Types::OctetString as u64 => (false, Some(c.clone())), _ => panic!("decoding error"), }, }; let val = match maybe_val { None => None, Some(v) => Some(Vec::from(v.expect_primitive().expect("octet string"))), }; let known_type = match CONTROLS.get(&*ctype) { Some(val) => Some(*val), None => None, }; ctrls.push(Control(known_type, RawControl { ctype: ctype, crit: crit, val: val })); } ctrls }