Skip to content

Commit

Permalink
Reorganize SPNEGO support
Browse files Browse the repository at this point in the history
* Remove special-case parsing of Bind responses and extract the SASL
  server response, if any, while constructing LdapResultExt.

* Remove handling of SASL responses as pseudo-controls.

* Rework sasl_spnego_bind() accordingly.

* Remove special result handling for Bind responses.
  • Loading branch information
inejge committed Jun 6, 2019
1 parent cf0afc1 commit f2320f2
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 58 deletions.
11 changes: 6 additions & 5 deletions src/bind_spnego.rs
Expand Up @@ -7,6 +7,7 @@ use futures::{Future};
use tokio_service::Service;

use ldap::{Ldap, LdapOp, next_req_controls};
use protocol::LdapResultExt;
use result::LdapResult;

use spnego;
Expand Down Expand Up @@ -47,7 +48,8 @@ fn create_bind_request(token: Vec<u8>) -> Tag {
impl Ldap {
/// See [`LdapConn::sasl_spnego_bind()`](struct.LdapConn.html#method.sasl_spnego_bind).
pub fn sasl_spnego_bind(&self, username: &str, password: &str) ->
Box<Future<Item=LdapResult, Error=io::Error>> {
Box<Future<Item=LdapResult, Error=io::Error>>
{
let mut spnego_client = spnego::Client::new(username, password);

let input = Vec::new();
Expand All @@ -58,11 +60,10 @@ impl Ldap {
let ldap = self.clone();
let fut = self.call(LdapOp::Single(req, next_req_controls(self)))
.and_then(move |response| {

let (mut result, controls) = (LdapResult::from(response.0), response.1);
let (ldap_ext, controls) = (LdapResultExt::from(response.0), response.1);
let (mut result, sasl_creds) = (ldap_ext.0, (ldap_ext.2).0.unwrap_or_else(|| vec![]));
result.ctrls = controls;

let input = result.get_bind_token().unwrap();
let input = sasl_creds;
let mut output = Vec::new();
let _sspi_status = spnego_client.authenticate(input.as_slice(), &mut output).unwrap();
let req = create_bind_request(output.clone());
Expand Down
23 changes: 1 addition & 22 deletions src/controls_impl/mod.rs
Expand Up @@ -9,7 +9,7 @@ pub mod types {
//!
//! Variants are individually reexported from the private submodule
//! to inhibit exhaustive matching.
pub use self::inner::_ControlType::{PagedResults, PostReadResp, PreReadResp, BindResponse};
pub use self::inner::_ControlType::{PagedResults, PostReadResp, PreReadResp};

/// Recognized control types. Variants can't be named in the namespace
/// of this type; they must be used through module-level reexports.
Expand All @@ -20,7 +20,6 @@ pub mod types {
PagedResults,
PostReadResp,
PreReadResp,
BindResponse,
#[doc(hidden)]
_Nonexhaustive,
}
Expand Down Expand Up @@ -206,23 +205,3 @@ pub fn parse_controls(t: StructureTag) -> Vec<Control> {
}
ctrls
}

use lber::common::TagClass;
pub const SPNEGO_MECH_OID: &'static str = "1.3.6.1.5.5.2";

pub fn parse_bind_response(t: StructureTag) -> Vec<Control> {
let mut ctrls = Vec::new();
let tags = t.clone().expect_constructed().expect("result sequence").into_iter();
for tag in tags {
if tag.class == TagClass::Context && tag.id == 7 {
// serverSaslCreds [7] OCTET STRING OPTIONAL
let token = tag.expect_primitive().unwrap().clone();
ctrls.push(Control(Some(types::BindResponse), RawControl {
ctype: SPNEGO_MECH_OID.to_string(),
crit: false,
val: Some(token.clone())
}));
}
}
ctrls
}
20 changes: 12 additions & 8 deletions src/protocol.rs
Expand Up @@ -22,7 +22,7 @@ use lber::universal::Types;
use lber::write;

use controls::Control;
use controls_impl::{parse_controls, parse_bind_response, build_tag};
use controls_impl::{parse_controls, build_tag};
use exop::Exop;
use ldap::LdapOp;
use result::LdapResult;
Expand Down Expand Up @@ -69,7 +69,10 @@ impl SearchHelper {
}

#[derive(Clone, Debug)]
pub struct LdapResultExt(pub LdapResult, pub Exop);
pub(crate) struct ServerSaslCreds(pub Option<Vec<u8>>);

#[derive(Clone, Debug)]
pub(crate) struct LdapResultExt(pub LdapResult, pub Exop, pub ServerSaslCreds);

impl From<Tag> for LdapResultExt {
fn from(t: Tag) -> LdapResultExt {
Expand All @@ -93,6 +96,7 @@ impl From<Tag> for LdapResultExt {
let mut refs = Vec::new();
let mut exop_name = None;
let mut exop_val = None;
let mut sasl_creds = None;
loop {
match tags.next() {
None => break,
Expand All @@ -108,6 +112,9 @@ impl From<Tag> for LdapResultExt {
.map(|s| s.expect("uri"))
.collect());
},
7 => {
sasl_creds = Some(comp.expect_primitive().expect("octet string"));
}
10 => {
exop_name = Some(String::from_utf8(comp.expect_primitive().expect("octet string")).expect("exop name"));
}
Expand All @@ -129,7 +136,9 @@ impl From<Tag> for LdapResultExt {
Exop {
name: exop_name,
val: exop_val
})
},
ServerSaslCreds(sasl_creds),
)
}
}

Expand Down Expand Up @@ -218,11 +227,6 @@ impl Decoder for LdapCodec {
Ok(Some((id, (id_tag, vec![]))))
}
},
1 => {
let controls = parse_bind_response(protoop.clone());
self.bundle.borrow_mut().id_map.remove(&msgid);
Ok(Some((id, (Tag::StructureTag(protoop), controls))))
},
_ => {
self.bundle.borrow_mut().id_map.remove(&msgid);
Ok(Some((id, (Tag::StructureTag(protoop), controls))))
Expand Down
24 changes: 1 addition & 23 deletions src/result.rs
Expand Up @@ -11,7 +11,7 @@ use std::fmt;
use std::io;
use std::result::Result;

use controls::{Control,types};
use controls::Control;
use exop::Exop;
use protocol::LdapResultExt;
use search::ResultEntry;
Expand Down Expand Up @@ -140,28 +140,6 @@ impl LdapResult {
Err(io::Error::new(io::ErrorKind::Other, self))
}
}

/// If the result code is 0 or 14 (saslBindInProgress), return the instance
/// itself wrapped in `Ok()`, otherwise wrap the instance in an
/// `io::Error`.
pub fn bind_ok(self) -> Result<Self, io::Error> {
if self.rc == 0 || self.rc == 14 {
Ok(self)
} else {
Err(io::Error::new(io::ErrorKind::Other, self))
}
}

pub fn get_bind_token(&mut self) -> Option<Vec<u8>> {
for ctrl in &self.ctrls {
if ctrl.0 == Some(types::BindResponse) {
if let Some(val) = ctrl.1.val.clone() {
return Some(val);
}
}
}
None
}
}

/// Wrapper for results of a Search operation which returns all entries at once.
Expand Down

0 comments on commit f2320f2

Please sign in to comment.