Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GSSAPI appears to fail with fqdn #84

Closed
1Dragoon opened this issue May 28, 2022 · 5 comments
Closed

GSSAPI appears to fail with fqdn #84

1Dragoon opened this issue May 28, 2022 · 5 comments

Comments

@1Dragoon
Copy link

1Dragoon commented May 28, 2022

It seems the gssapi bit is failing if I pass the fqdn of the server I connected to:

Reason: GSSAPI operation error: ClientCtx::step failed The specified target is unknown or unreachable ', src\ad.rs:33:41

Could just be an environment specific thing? Or maybe just an active directory thing? Here's the code that actually works for me:

use crate::Duration;
use itertools::Itertools;
use ldap3::Ldap;
use anyhow::{bail, Result};
use byteorder::{LittleEndian, ReadBytesExt};
use chrono::NaiveDateTime;
use ldap3::{SearchEntry, LdapConnAsync};
use trust_dns_resolver::TokioAsyncResolver;

pub(crate) async fn autoconnect_ldap() -> Result<Ldap, anyhow::Error> {
    let resolver = TokioAsyncResolver::tokio_from_system_conf()?;
    let lookup = resolver.srv_lookup("_ldap._tcp").await?;
    let records = lookup
        .into_iter()
        .sorted_by(|srv_a, srv_b| srv_a.priority().cmp(&srv_b.priority()))
        .collect::<Vec<_>>();
    let mut recs_iter = records.iter();
    loop {
        if let Some(srv) = recs_iter.next() {
            let mut server = srv.target().to_string();
            if server.ends_with('.') {
                server.truncate(server.len()-1);
            }
            let url = format!("ldaps://{server}:636");
            match LdapConnAsync::new(url.as_str()).await
            {
                Ok((conn, mut ldap)) => {
                    if let Some(first_label) = srv.target().iter().next() {
                        if let Ok(host) = std::str::from_utf8(first_label) {
                            ldap3::drive!(conn);
                            ldap.with_timeout(Duration::from_millis(100));
                            if let Err(err) = ldap.sasl_gssapi_bind(host).await {
                                bail!("Failed to authenticate to AD\nReason: {err}")
                            }
                            break Ok(ldap);
                        } else {
                            continue;
                        }
    
                    }
                },
                Err(err) => {
                    println!("Error: {server} {err}");
                    continue;
                },
            };
        } else {
            bail!("Couldn't find an appropriate domain controller to connect to.");
        }
    }
}

Also FWIW, native-tls fails without truncating that root dot (i.e. 'www.example.com.' needs to be 'www.example.com') Not sure whether the native-tls maintainers would consider that a feature or a bug.

@inejge
Copy link
Owner

inejge commented May 28, 2022

It seems the gssapi bit is failing if I pass the fqdn of the server I connected to

As you surmised, it's probably environment-specific. Running klist should tell you the SPN of the domain controller in the ticket cache (ldap/dc.fq.dn); if the FQDN part is identical to what you get back from the SRV query, I can't explain it. Anyhow, a GSSAPI bind never failed for me in that way, neither on Linux nor on Windows.

Also FWIW, native-tls fails without truncating that root dot

Hostnames in TLS certificates don't have the final dot, so a straight comparison will fail. Whether that dot should be accomodated is debatable.

@1Dragoon
Copy link
Author

Is it possible to request that info via ldap?

It seems the gssapi bit is failing if I pass the fqdn of the server I connected to

As you surmised, it's probably environment-specific. Running klist should tell you the SPN of the domain controller in the ticket cache (ldap/dc.fq.dn); if the FQDN part is identical to what you get back from the SRV query, I can't explain it. Anyhow, a GSSAPI bind never failed for me in that way, neither on Linux nor on Windows.

Is it possible to discover what it would need via the api? or would it just need to be trial and error?

Also FWIW, native-tls fails without truncating that root dot

Hostnames in TLS certificates don't have the final dot, so a straight comparison will fail. Whether that dot should be accomodated is debatable.

Yep: https://datatracker.ietf.org/doc/html/rfc3546#section-3.1

Would be nice if the error message somehow indicated what was being searched for vs what was found, as I literally had to guess that was the problem as I wasn't aware that the resolver crate returned the trailing dot. I'll submit a bug report to them and see if they deem it worth doing anything about.

One thing I'm really big on is offering as much as can be given about why something failed in my user facing code, though I don't force that philosophy on anybody else, merely suggesting it. Rustc itself is such an excellent example of error messages done right.

@inejge
Copy link
Owner

inejge commented May 28, 2022

Is it possible to request that info [SPN] via ldap?

No, it's pure Kerberos.

Is it possible to discover what it would need [SPN format] via the api? or would it just need to be trial and error?

It shouldn't be trial and error, the FQDN ought to work. I'm not sure about cross-domain trusts and their interaction with Kerberos and DNS, but that's a very advanced topic and probably not the issue here.

@inejge
Copy link
Owner

inejge commented Aug 21, 2022

Closing for lack of feedback and inability to reproduce.

@inejge inejge closed this as not planned Won't fix, can't repro, duplicate, stale Aug 21, 2022
@1Dragoon
Copy link
Author

Oh sorry didn't have time to do additional tests and I just left that employer, so I'm not able to do so anymore.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants