The Light Weight Directory Access Protocol (LDAP) provides the McAfee Web Gateway with one(!) way to integrate with existing directory services on a network. The directory is responsible for holding information about the network including user information which Web Gateway can query and use for authentication, logging and filtering purposes. This article steps through the configuration needed to allow Web Gateway to authenticate clients and also query and store their attributes.
Below is a typical configuration using directory proxy authentication with an LDAP backend. The Authentication.Authenticate property is using an authentication engine (ACME_LDAP) that has been created and configured to contact a network LDAP server.
The settings of the authentication engine can be seen by clicking the link for "ACME_LDAP":
Setting up the engine to authenticate clients requires only a few settings:
The image below shows the authentication process captured in a tcpdump. I've included the tcpdump for closer review, but the image provides a quick summary of what we'd expect to see in a normal authentication process.
The pink packets highlight the initial bind request to the ldap server using the administration credentials. In packet 4 we see the admin bind request and in packet 5 we see the ldap server respond with a "success" message. After the admin bind is successful MWG submits a query to find the distinguished name for the jsmith user. The ldap server is able to map the username (jsmith) to a DN and sends back "cn=John Smith,cn=users,dc=acme,dc=local".
The green packets highlight the second bind attempt in which MWG tries to authenticate the user, jsmith, using the returned DN. In Packet 12, MWG uses the DN returned by the first query to bind to the LDAP server again. Since this bind attempt is using the user's DN and password, if it is successful, then the user is authenticated. In packet 13 we can see that the bind was successful and the user is authenticated.
In addition to authenticating users, MWG is capable of querying the directory service to find other pieces of information either about the user or about the groups that the user belongs to. These pieces of information are called attributes. User objects in Active Directory for example typically have a "memberOf "attribute that contain all the groups that a user belongs to. Group objects in turn will usually also have a "member" attribute to hold the username of members. The values returned for both user and group attribute lookups are stored in the Authentication.Groups property and are separated by the character(s) defined in the "Attributes concatenation string" field.
This is the most common configuration since in most cases a query for user attributes is all that is needed. Querying for user attributes requires that the "Get user attributes" option is enabled and to define a list of attributes to be retrieved. In the example below, MWG is configured to retrieve the "memberOf" attribute of user objects.
Once the MWG is successfully binds to the LDAP server using the user's credentials, it then queries the LDAP server for the attributes in the list. Pink highlights the stream containing the query:
Instead of performing a search for user objects and gathering attributes assigned to the user, it is sometimes needed to look for group objects and pull information on the group. For example, if group information is stored in a location other than in a user attribute. Group attribute lookups can be enabled by checking the "Get group attributes" options and defining the filter to find group objects that the user belongs to. In the example below, MWG is configured to query the directory starting in OU=groups,DC=acme,DC=LOCAL for objects that have an attribute of "member" containing the user's username. The directory service will return the "Common Name" or "CN" for any objects that match this query.
And as it appears in wireshark:
When a user is authenticated using LDAP, the Authentication.Username property is set to equal the user DN. This will lead to logs showing entries like:
[04/Sep/2013:16:27:43 -0400] "CN=John Smith,CN=Users,DC=acme,DC=local" 10.10.67.4 301 "GET http://www.mcafee.com/ HTTP/1.1" "" "-" "" 1161 688 "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C; .NET4.0E)" "" "0" ""
To ensure the log entry shows the original username, jsmith, rather than the user DN displayed above, we'll add a rule to temporarily store the original username. After authentication we'll replace the user DN with the original username. The first step below (Authenticate) is responsible for authenticating the user, querying the directory to find the users sAMAccountName, and storing the value in a User-Defined property:
The settings for the engine look like:
At this point the Authentication.UserGroups property also contains the sAMAccountName. To correct this, another rule using a separate ldap authentication container is created below the first rule. This second rule uses the Authentication.GetUserGroups property to query the ldap server and find the actual groups the user belongs to:
An important item to point out is the use of the "Map user to DN" option. In the first engine this option is enabled in order to authenticate the user properly. The second engine has this option disabled because the first engine has already mapped the username to the DN and it is no longer necessary to find the DN. Enabling the option will produce an error. After all the queries against ldap are done, the third step corrects the username so it can be logged properly.
Building off the example above, we can configure the MWG to pull additional information about the user. The example below shows how to pull the email address:
The steps are the same as the above example but with the addition of the "Get Email" Rule. This rule again uses the Authentication.GetUserGroups property to find the user's email address and assign it to the User-Defined.email property. The engine is configured to pull the "mail" attribute and again not to map the username to the DN:
The User-Defined.mail property can then be used elsewhere in the configuration for logging, filtering, sending notifications, etc...
At the top of the LDAP engine settings screen is a handy testing tool. Given a username and password, MWG will attempt to authenticate the user and pull any attributes it has been configured to gather. When testing it is often necessary to disable the "Use authentication cache" option. With this option enabled, MWG will not be able to detect changes to the directory until the cache time has been exceeded.
A successful test looks like:
A failed attempt for any reason simply displays the message "Error: Authentication failed". If you get this message, the first thing to do is double-check the settings on the page. It is likely that something has been misconfigured. If the settings look good then a closer look is required.
A couple of tools are available in the MWG GUI to help troubleshoot ldap authentication issues; Auth debug logging and tcpdumps.
Authentication debug logging is one tool that can shed some light on the situation. This can be enabled under Configuration > Troubleshooting > Authentication Troubleshooting > Log authentication events. The option "Restrict tracing to one IP" should also be checked and a single client IP entered to avoid the log become too large and difficult to read. This option will create a mwg-core__Auth.debug.log file found in Troubleshooting > *appliance* > Log Files > debug and will look something like:
[2013-09-05 23:01:10.153 +00:00]  LDAP (122, 10.10.67.4) URL: http://www.mcafee.com/
[2013-09-05 23:01:10.153 +00:00]  LDAP (122, 10.10.67.4) Configuration: ACME_LDAP Connection: 0x4350a10 RR: 0x4549d80
[2013-09-05 23:01:10.153 +00:00]  LDAP (122, 10.10.67.4) Added authentication method: Basic realm="ACME"
[2013-09-05 23:01:10.153 +00:00]  LDAP (122, 10.10.67.4) Authentication didn't return values, failure ID: 4, authentication failed: 0
[2013-09-05 23:01:19.722 +00:00]  LDAP (123, 10.10.67.4) URL: http://www.mcafee.com/
[2013-09-05 23:01:19.722 +00:00]  LDAP (123, 10.10.67.4) Configuration: ACME_LDAP Connection: 0x4350a10 RR: 0x454aa40
[2013-09-05 23:01:19.722 +00:00]  LDAP (123, 10.10.67.4) Incoming credentials: Basic anNtaXRoOndyb25ncGFzc3dvcmQ=
[2013-09-05 23:01:19.722 +00:00]  LDAP (123, 10.10.67.4) User entry not found in user cache
[2013-09-05 23:01:19.751 +00:00]  LDAP (123, 10.10.67.4) Mapping of user name "jsmith" to DN returned 0 "CN=John Smith,CN=Users,DC=acme,DC=local"
[2013-09-05 23:01:19.751 +00:00]  LDAP (123, 10.10.67.4) Added authentication method: Basic realm="ACME"
[2013-09-05 23:01:19.751 +00:00]  LDAP (123, 10.10.67.4) Authentication didn't return values, failure ID: 3, authentication failed: 1
The important pieces to look for are the failure IDs. In this example there are two. The first being ID 4 and the second being ID 3. ID 4 indicates that the user hasn't provided any credentials. This can be ignored since it is expected - in the initial request the user doesn't know it must provide credentials and so it doesn't.
The second time the client makes the request MWG logs a failure ID 3. ID 3 tells us that the password provided is bad:
0 - kNoFailure - Authentication was successful
2 - kUnknownUser - can't map user name to user DN
3 - kWrongPassword - bind with user password failed
4 - kNoCredentials - credentials are missing or have invalid format
5 - kNoServerAvailable - could not get a server connection
6 - kProxyTimeout - Request is being processed longer than defined in the configuration timeout
8 - kCommunicationError - communication with server failed, e.g. timeout
Sometimes authentication debug logging is not enough to find the true reason for the failure. ID 3 for example can not only mean that the password provided was wrong, but also that Active Directory is requiring the user to change their password. In order to dig deeper and see this though a tcpdump is necessary. For troubleshooting purposes it is necessary that MWG is configured to contact the ldap server over its unencrypted port.
The tcpdump can be started under Troubleshooting > Packet tracing with the parameters "-s 0 -i any port 389".
After reproducing the problem, stop the trace, open it with Wireshark and use the ldap.bindResponse display filter to find response from the ldap server. We can see in the example below the failed attempt:
The Wireshark trace shows us the error "invalidCredentials (80090308: LdapErr: DSID-0c09030f, comment: AcceptSecurityContext error, data 773, vece)". The 773 error code is an Active Directory code the tells us that the user needs to change their password.
A list of AD specific error codes can be found at http://www-01.ibm.com/support/docview.wss?uid=swg21290631 while a list of standard LDAP error codes can be found at https://wiki.servicenow.com/index.php?title=LDAP_Error_Codes