1

Python code used for AD authentication

I'm using the Python library ldap to write a client for authentication on a Microsoft Active Directory.

I'm using with success the following code:

uri = "ldap://active.directory.server:389" con = ldap.initialize(uri, bytes_mode = False) con.protocol_version = ldap.VERSION3 con.set_option(ldap.OPT_REFERRALS, ldap.OPT_OFF) con.set_option(ldap.OPT_NETWORK_TIMEOUT, timeout = 3) bindDistinguishedName = "mydomain\\myuser" bind_result = con.simple_bind_s(bindDistinguishedName, "mypassword") 

By this post I have understand that in the previous code I'm using the (legacy) format:

  • <Domain NetBIOS Name>\<sAMAccountName>

Use of the FQDN for bind DN

I have tested the previous code by setting the bindDistinguishedName with UserPrincipalName (UPN) as showed below:

bindDistinguishedName = "[email protected]" 

(as well explained here, mydomain.com is called FQDN, where FQDN stands for Fully Qualified Domain Name).

The authentication has been completed with success also in this case.

FQDN not allowed in NetBIOS form

In the UPN mode I have added the .com after mydomain, so I have tested the NetBIOS form with the value mydomain.com as showed below:

bindDistinguishedName = "mydomain.com\\myuser" 

but the authentication fails.

Why in the NetBIOS form the .com part of the FQDN is not allowed? If for example FQDN is equal to mydomain.mycompany.com the NetBIOS form is only mydomain?

2
  • Why in the NetBIOS form the .com part of the FQDN is not allowed? That was really a design and implementation decision from Microsoft 25 years ago. There are now traditionally two well known formats: UPN or DomainShortname\username. Adding a third would have been trivial, but no-one was asking for it yet, and they wanted to persuade people to adopt UPN usage. Also as an FYI, in the near future, the code you provided will not be able to authenticate on port 389. A TLS secured port will be required, such as 636 or 3269. Commented 7 hours ago
  • Thank you I'm modifying my code to use UPN form and replace the legacy NetBIOS form. I'm already using LDAPS on port 636 (or 3269), but I have written in the question my code for LDAP authentication. I have got in my code a parameter to select between LDAP or LDAPS. Commented 7 hours ago

1 Answer 1

1

Why in the NetBIOS form the .com part of the FQDN is not allowed?

Because the FQDN is a DNS domain name, whereas NetBIOS form does not deal in DNS names – it deals in NetBIOS names, an entirely unrelated namespace from DNS. NetBIOS names typically consist of exactly one component1. Your NetBIOS domain name is MYDOMAIN, upper-case.

Every Active Directory domain has a NetBIOS name for legacy compatibility with the "Windows NT domains" (and/or "LAN Manager domains") that preceded AD. The NetBIOS name was chosen manually during initial domain setup; it may match the first word of the AD DNS domain name, or it may be entirely different from the DNS name. For example, our DNS domain name at work looks like ad.verbose-corporation.tld but our NetBIOS domain name is VCORPO.

(Local accounts use the computer name as the "domain", e.g. DC01\Administrator.)

So if you use the NetBIOS syntax, then you must use the NetBIOS domain name and the user's 'sAMAccountName' (and note that the latter may also be different from the user's "modern" UPN; effectively an AD user has two usernames in the same way as an AD directory has two domain names).

Make a search under base CN=Partitions,CN=Configuration,DC=[your_suffix] for entries matching (nETBIOSName=*). If there's only one result then its nETBIOSName attribute will tell you what your legacy domain name actually is.

All of this could be avoided if you were using Kerberos for authentication. Have the user acquire Kerberos tickets using kinit, then call con.sasl_non_interactive_bind_s("GSS-SPNEGO") or perhaps con.sasl_gssapi_bind_s(). Not only would this avoid sending the password in plain text (as your current code doesn't use LDAPS), but it would also give you Kerberos-based transport encryption as a free bonus, without needing to configure TLS certificates or anything.

(That is, unless the sole purpose of your script is to 'authenticate' the client and do nothing else with that LDAP connection... in that case you'll need to stick with simple bind, but please use ldaps:// for such things.)

Finally, for pure 'authenticate only' implementation, another method is possible: 1) first bind using the app's "service account", 2) search for the user's AD entry, 2) bind again using the user's distinguishedName (or their <SID=..> pseudo-DN) as the bind DN.


1 (A multiple-component NetBIOS name is technically possible with the NetBIOS scope parameter, e.g. FOO.example.com could be the NetBIOS name FOO under the scope example.com, but I don't think that the "scope" feature was widely used at all – and is certainly not used in modern Active Directory installations.)

3
  • Thanks. I have some problem to understand the last part of the answer where you list the method composed by 3 steps.. Could you explain better that part. What do you mean as service account, pseudo-DN? Commented 9 hours ago
  • If you're writing for example a web app, or an API server, then it would be typically issued its own AD account that represents the app itself (I think IIS might call that "application identity"). By pseudo-DN I mean things that AD accepts in the "bind DN" field that aren't actually DNs – e.g. it also accepts user UPNs as you already know, it accepts the NetBIOS style usernames, but it also accepts <SID=...> and <GUID=...> strings that can represent some user (or any other entry) by that user's objectSid or objectGUID. Commented 9 hours ago
  • Thank you very much. I have tested the LDAP search starting from CN=Partitions,CN=Configuration,DC=[my_suffix] and with the filter (nETBIOSName=*) on my company AD server and I have found an entity with attribute nETBIOSName equals to only one value that is the correct legacy domain name defined in my company. Your help has been precious for my understanding of LDAP protocol. Commented 6 hours ago

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.