inejge / ldap3

A pure-Rust LDAP library using the Tokio stack
Apache License 2.0
220 stars 38 forks source link

panicked at 'entry', /ldap3/src/search.rs #45

Closed fdubois1 closed 4 years ago

fdubois1 commented 4 years ago

Hi, I moved to the alpha version to use async/await. I kept my code almost the same except that now, I use LdapConnAsync and all async call.

I use streaming_search() in my code below and it panics with this : panicked at 'entry', /opt/wayk/dev/ldap3/src/search.rs:148:13

The line who panic is SearchEntry::construct(entry). Any idea ?

Here is my code. The connection is already opened, I receive it in parameter.

async fn get_groups_internal(&self, ldap_conn: &mut Ldap) -> Result<Vec<AccountGroup>, AdAccountError> {
        let mut groups = Vec::new();

        let filter = "(&(objectCategory=group)(objectClass=group))";

        let mut entry_stream = ldap_conn
            .streaming_search(&self.base_dn, Scope::Subtree, &filter, AD_GROUP_ATTRIBUTES.to_vec())
            .await?;

        while let Some(entry) = entry_stream.next().await? {
            match self.build_group(&SearchEntry::construct(entry)) {
                Ok(group) => groups.push(group),
                Err(e) => error!("Build_group failed: {:?}", e),
            }
        }
        entry_stream.finish();

        Ok(groups)
    }

Thank you in advance

fdubois1 commented 4 years ago

If it can help, here is the expect that fail in my case :

    pub fn construct(re: ResultEntry) -> SearchEntry {
        let mut tags =
            re.0.match_id(4)
                .and_then(|t| t.expect_constructed())
panic---->      .expect("entry")
                .into_iter();

The match_id(4) returns none since the id is 19.

I'm not familiar enough with the ldap protocol to understand what is going on. Any idea ? Thanks a lot

fdubois1 commented 4 years ago

It seems that entries return by stream.next() could be a referral. I'm not sure to know what is it and if it is normal to get, but I fixed my issue by adding this code before the SearchEntry::construct(entry)

if entry.is_ref() || entry.is_intermediate() {
   continue;
}

Do I have to write this condition or is it an issue in the lib ? I didn't have to do that with the previous version. Thank you for your help

inejge commented 4 years ago

It's documented in CHANGELOG.md:

[breaking change]: Streaming Search returns raw entries, without trying to parse referrals or intermediate messages.

So yes, filtering with is_ref() should be enough (intermediate messages are something you have to explicitly request, no reason to look for them in general). However, I believe I can restore the earlier behavior by introducing a new search option; I'll have to think about it.

fdubois1 commented 4 years ago

Thank you for your help.

Now, I have this panic : thread 'tokio-runtime-worker' panicked at 'message id', /home/fdubois/.cargo/git/checkouts/ldap3-164a77dff2c2ecf1/8586c96/src/protocol.rs:83:13

Everything works fine but I think it happens at then end of the connection. Why could I get this error, any idea ?

Thanks again

inejge commented 4 years ago

You shouldn't get a panic there. If it's reproducible, could you:

  1. Post the source of your program
  2. Capture the failing packet trace with tcpdump or wireshark

Alternatively or additionally, put a

println!("{:?}", tags);

on line 82 of src/protocol.rs, before let msgid = ... and post the output.

If possible, open a separate issue for this, since it's unrelated to entry parsing.

fdubois1 commented 4 years ago

Sure, I will create a new issue for that and close that one. Thanks

inejge commented 4 years ago

@fdubois1 I'm not reopening this, just a note that the latest alpha contains a workaround for non-filtered entries: search adapters which can be associated with a Search operation. The EntriesOnly adapter, which makes search behave like the previous versions, is built in. See examples/search_adapted.rs for sample code.

fdubois1 commented 4 years ago

Great, thanks a lot for the information !!