How to increase logging for debugging of LDAP authentication setup?

Started by gromit, February 18, 2021, 10:11:19 PM

Previous topic - Next topic
Quote from: crayon on February 24, 2021, 01:15:51 AM
Just to note, there's already a pull request related to this: https://github.com/opnsense/plugins/pull/2166
Thanks!
Deciso DEC750
People who think they know everything are a great annoyance to those of us who do. (Isaac Asimov)

Quote from: Fright on February 23, 2021, 07:47:54 PM
can you try this changes to add some debug to Tester and try again?
in /usr/local/www/diag_authenticatiopn.php add

            foreach ($authenticator->getLastAuthProperties() as $attr_name => $attr_value) {
                if (is_array($attr_value)) {
                    $attr_value = implode(",", $attr_value);
                }
                $input_errors[] = "{$attr_name}: {$attr_value}";
            }


after

            $input_errors[] = gettext("Authentication failed.");

string


in /usr/local/opnsese/mvc/app/library/opnsense/auth/ldap.php add

            $this->lastAuthProperties['error'] = $error_string;
            $this->lastAuthProperties['ldap_error'] = ldap_error($this->ldapHandle);

after

            syslog(LOG_ERR, sprintf($message . " [%s,%s]", $error_string, ldap_error($this->ldapHandle)));

string in logLDAPError function
and add

else {
                    $this->lastAuthProperties['error'] = "User DN not found";
                }

after brace in

                if ($result !== false && count($result) > 0) {
                    $user_dn = $result[0]['dn'];
                    $ldap_is_connected = $this->connect($this->ldapBindURL, $result[0]['dn'], $password);
                }

in authenticate function

I added the above debugging code and now when I use Tester I get this error:

QuoteThe following input errors were detected:

  • Authentication failed.
  • error: User DN not found

I have tried to use the same LDAP server configuration options that I use with the same LDAP server on pfSense.  The pfSense setup works (or at least worked).  The two setup screens aren't parallel in how you specify the configuration (e.g., pfSense has an explicit specification for CA), so I'll go back and double-check to see if I haven't made any obvious mistakes.

PS: The extra debugging info output by Tester is very helpful.  It would be great if this could be added to the OPNsense release itself.

Quoteso I'll go back and double-check to see if I haven't made any obvious mistakes
as you can see in the proposed code, the "User DN not found" error occurs when the user's search does not return any results. that is, the binding itself is successful. so it's not about the SSL params.
search uses username from tester input, "User naming attribute" from server config and "Extended Query" from server config (if any). plus underlying search function uses "Base DN" and "Authentication containers" (if any) from server config.so I would pay attention to these parameters of server config

Quote from: Fright on March 05, 2021, 06:36:16 AM
Quoteso I'll go back and double-check to see if I haven't made any obvious mistakes
as you can see in the proposed code, the "User DN not found" error occurs when the user's search does not return any results. that is, the binding itself is successful. so it's not about the SSL params.
search uses username from tester input, "User naming attribute" from server config and "Extended Query" from server config (if any). plus underlying search function uses "Base DN" and "Authentication containers" (if any) from server config.so I would pay attention to these parameters of server config

I double-checked the working pfSense configuration against the OPNsense configuration and didn't see any obvious differences.

It turns out the problem may stem from misleading help text and that the solution ultimately turned out to be straightforward.

The problem lay with the setting in "Authentication containers."  The help text states this: "Semicolon-separated list of distinguished names optionally containing DC= components" (my emphasis).  Indeed, in my working pfSense setup I have only "ou=People" for this, and that is the value I was using in OPNsense.

What got authentication working was to append the base DN to this value to fully qualify it.  ???

Another odd difference is that in the pfSense setup I can press the "Select a container" button alongside the "Authentication containers" setting and it will pop up a window with a couple of entries (including the one with "ou=People").  OPNsense always just pops up an empty list.

QuoteWhat got authentication working was to append the base DN to this value to fully qualify it.
I think it's worth a ticket on github: either change the help text or attach a basedn to the container in the search function
QuoteI can press the "Select a container" button alongside the "Authentication containers"
tried without specifying a "Authentication containers"? with "base dn" only
(button uses the same search function, which does not attach the basedn to the container) <- error:
listOUs function not using auth containers when searching for OUs.
 

Quote from: Fright on March 05, 2021, 05:33:08 PM
QuoteI can press the "Select a container" button alongside the "Authentication containers"
tried without specifying a "Authentication containers"? with "base dn" only
(button uses the same search function, which does not attach the basedn to the container)

This is even when pressing "Select a container" with the fully-specified DN entered in the setting field.  It also has the unfortunate side effect of clearing the "Authentication containers" setting if you dismiss the pop-up window via the "Close" button (given there's nothing to select in the pop-up).

Quotesetting if you dismiss the pop-up window via the "Close" button (given there's nothing to select in the pop-up)
hm. agree. it looks like the button can be renamed to Save. and modal should be closed by 'x' button in this case
QuoteThis is even when pressing "Select a container" with the fully-specified DN entered in the setting field
I have a feeling that when calling the lists of containers with this button, the value of this field is not involved in the search. only baseDN. "Authentication containers" values are used to check for matches and mark the matched containers as selected in the result table. so can you try with empty "Authentication containers" and Base DN only?

Quote from: Fright on March 06, 2021, 07:40:58 AM
I have a feeling that when calling the lists of containers with this button, the value of this field is not involved in the search. only baseDN. "Authentication containers" values are used to check for matches and mark the matched containers as selected in the result table. so can you try with empty "Authentication containers" and Base DN only?

When I try the "Select" button alongside "Authentication containers" with just a base DN and the "Authentication containers" field empty I get an empty popup as a result.

I have not been able to find any combination of inputs in OPNsense that will yield anything but an empty popup.

can you try to modify listOUs function in /usr/local/opnsese/mvc/app/library/opnsense/auth/ldap.php:
before:

            if ($searchResults !== false) {
                for ($i = 0; $i < $searchResults["count"]; $i++) {
                    $result[] = $searchResults[$i]['dn'];
                }

after:

            if ($searchResults !== false) {
                $this->logLdapError("LDAP containers search result count: " . $searchResults["count"]);
                for ($i = 0; $i < $searchResults["count"]; $i++) {
                    $result[] = $searchResults[$i]['dn'];
                }

try to "Select" again and look General log for some ldap errors?

Quote from: Fright on March 08, 2021, 10:02:34 PM
can you try to modify listOUs function in /usr/local/opnsese/mvc/app/library/opnsense/auth/ldap.php:
before:

            if ($searchResults !== false) {
                for ($i = 0; $i < $searchResults["count"]; $i++) {
                    $result[] = $searchResults[$i]['dn'];
                }

after:

            if ($searchResults !== false) {
                $this->logLdapError("LDAP containers search result count: " . $searchResults["count"]);
                for ($i = 0; $i < $searchResults["count"]; $i++) {
                    $result[] = $searchResults[$i]['dn'];
                }

try to "Select" again and look General log for some ldap errors?

I modified the code as given above and tried "Select" again.  The result was the same (nothing in the popup) and also no errors appeared in "System: Log Files: General".

I'm sorry, I probably didn't guess the place where we need to catch the error (it worked for AD in my case).
If you are not tired yet, can you try to replace the  listOUs function with (try to log it from another place also):

    public function listOUs()
    {
        $result = array();
        if ($this->ldapHandle !== false) {
            $searchResults = $this->search("(|(ou=*)(cn=Users))");
            if ($searchResults !== false) {
                $this->logLdapError("LDAP containers search result count: " . $searchResults["count"]);
                for ($i = 0; $i < $searchResults["count"]; $i++) {
                    $result[] = $searchResults[$i]['dn'];
                }

                return $result;
            } else {
                  $this->logLdapError("LDAP containers search returned no results");
            }
        }

        return false;
    }


I replaced the listOUs code with the version with extra debugging.  When I try "Select" afterwards, I get this in the general log file:

QuoteLDAP containers search returned no results [,Time limit exceeded]

OPNsense doesn't let you set a timeout in the LDAP server setup, and in the pfSense version I do set this to 60 in order to allow extra time for the Duo second factor challenge to be completed during actual authentication attempts.  However, in the OPNsense case, it takes > 20 seconds for the popup to appear after pressing select whereas in the pfSense setup it pops up immediately.  I'm taking this to indicate that whatever search the OPNsense version is doing is not completing (or not completing in a timely fashion) whereas the pfSense search is completing quickly.

well, at least some result )
(will try to make PR to add this debug info too)
QuoteTime limit exceeded
hm. have you tried with "One level" in "Search scope" parameter?
and imho (not tested) you can try to play with timelimit in ldap_list and ldap_search functions in search function.
can try to make it like (for 60 sec limit. if LDAP server allows it) in search function:

                if ($this->ldapScope == 'one') {
                    $sr = @ldap_list($this->ldapHandle, $baseDN, $filter, $this->ldapSearchAttr, 0, 0, 60);
                } else {
                    $sr = @ldap_search($this->ldapHandle, $baseDN, $filter, $this->ldapSearchAttr, 0, 0, 60);
                }


Quote from: Fright on March 09, 2021, 08:46:27 PM
hm. have you tried with "One level" in "Search scope" parameter?
and imho (not tested) you can try to play with timelimit in ldap_list and ldap_search functions in search function.
can try to make it like (for 60 sec limit. if LDAP server allows it) in search function:

                if ($this->ldapScope == 'one') {
                    $sr = @ldap_list($this->ldapHandle, $baseDN, $filter, $this->ldapSearchAttr, 0, 0, 60);
                } else {
                    $sr = @ldap_search($this->ldapHandle, $baseDN, $filter, $this->ldapSearchAttr, 0, 0, 60);
                }


I am using "One Level" in the "Search scope" parameter, which is the setting I took from the working pfSense setup.

I applied the suggested code change but it didn't make any difference.  The popup also appeared after the same amount of time, too, as far as I could discern.  I did manually restart the WebGUI via /usr/local/etc/rc.restart_webgui after making the edit.

Note, the LDAP server works for me in OPNsense as far as authentication is concerned.  It's only the "Select" popup that doesn't, and given this is basically used to know what to put in the "Authentication containers" setting, I can say it's a moot point it not working for me (as I've figured out via trial and error what to put in there).  :)

I consider this "solved" for me, though I am willing to help test things if you want.