Web Gateway: Understanding LDAP Authentication

Version 4

     

    Introduction

    The Light Weight Directory Access Protocol 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 MWG can query and use for authentication, logging and filtering purposes. This article steps through the configuration needed to allow MWG to authenticate clients and also query and store their attributes.

     

     

    Authentication Rules and Settings

    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.

    ldap_authentication_rule.png

     

     

    The settings of the authentication engine can be seen by clicking the link for "ACME_LDAP" :

    acme_ldap_authentication.PNG

     

    Setting up the engine to authenticate clients requires only a few settings:

      • Authentication Method - Set to LDAP.
      • LDAP Server - Defines the LDAP server that MWG will contact to authenticate the user. The server is defined using the syntax ldap[s]://server[:port]. By default, LDAP is an unsecure protocol that will transmit information in clear text. It is recommended to use ldaps when possible. The default ldap port is 389 while ldaps uses 636.
      • Admin Credentials - Administrator credentials are required for the MWG to bind to the directory service.
      • Allow LDAP library to follow referrals - should be unchecked for use with Active Directory.
      • Base Distinguished Name - This is the starting point MWG uses to search for user objects.
      • Map user name to DN - In order to authenticate a user, MWG must perform a second bind using the user's DN and password. For example, the username jsmith maps to a distinguished name of cn=John Smith,cn=users,dc=acme,dc=local.
      • Filter Expression - Used to find the user's distinguished name. %u is a variable that stores the username. In this example, MWG will query the directory service for user objects that have a sAMAccountName attribute that equals the username.  NOTE: sAMAccountName is an Active Directory attribute.  Other LDAP servers use different attributes to store the username.

     

    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.

    ldap_authenticate_and_bind_screenshot.png

     

    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.

     

    User and Group Attributes

    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.

     

    User Attributes

    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.

    acme_ldap_userattributes.png

     

     

    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:

    ldap_user_lookup_tcpdump.png

     

     

    Group Attributes

    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.

    acme_ldap_groupattributes.png

     

    And as it appears in wireshark:

     

    group_tcpdump_lookup.png

     

    Correcting Logged Username

    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:

    correctingtheusername.png

     

    The settings for the engine look like:

    samaccoutnname2.png

     

    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:

     

    groups2.png

     

    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.

     

     

    Pulling Additional Attributes

    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:

     

    correct_username_and_get_email2.png

     

    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:

     

    email2.png

     

    The User-Defined.mail property can then be used elsewhere in the configuration for logging, filtering, sending notifications, etc...

     

     

    Testing

    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:

    success.png

     

    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.

     

    Troubleshooting

    A couple of tools are available in the MWG GUI to help troubleshoot ldap authentication issues; Auth debug logging and tcpdumps.

     

    Authentication Debug Logging

    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] [9960] LDAP (122, 10.10.67.4) URL: http://www.mcafee.com/
    [2013-09-05 23:01:10.153 +00:00] [9960] LDAP (122, 10.10.67.4) Configuration: ACME_LDAP Connection: 0x4350a10 RR: 0x4549d80
    [2013-09-05 23:01:10.153 +00:00] [9960] LDAP (122, 10.10.67.4) Added authentication method: Basic realm="ACME"
    [2013-09-05 23:01:10.153 +00:00] [9960] 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] [9974] LDAP (123, 10.10.67.4) URL: http://www.mcafee.com/
    [2013-09-05 23:01:19.722 +00:00] [9974] LDAP (123, 10.10.67.4) Configuration: ACME_LDAP Connection: 0x4350a10 RR: 0x454aa40
    [2013-09-05 23:01:19.722 +00:00] [9974] LDAP (123, 10.10.67.4) Incoming credentials: Basic anNtaXRoOndyb25ncGFzc3dvcmQ=
    [2013-09-05 23:01:19.722 +00:00] [9974] LDAP (123, 10.10.67.4) User entry not found in user cache
    [2013-09-05 23:01:19.751 +00:00] [9891] 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] [9926] LDAP (123, 10.10.67.4) Added authentication method: Basic realm="ACME"
    [2013-09-05 23:01:19.751 +00:00] [9926] 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

     

    Tcpdump

    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:

     

    changepassword.png

     

    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