Using PSloggedon to troubleshoot BlueCoat Single Sign On (SSO)

I won’t go into an introduction of what SSO is and Bluecoat’s implementation of it, there are some good KB articles on this subject. The following article (hopefully to be published soon on the bluecoat KB) explores how SSO interacts with windows and how to use the sysinternals PSloggedon tool to troubleshoot this.

Symptom:

When using Windows SSO, authentication intermittently fails with:

“Last Error: The user could not be determined by the Single Sign-on agent.”

FTP clients will show the following error:

clip_image002

A policy trace on the proxy will show the same error:

“Last Error: The user could not be determined by the Single Sign-on agent.”

The proxy will not show anyone as logged in via SSO

(https://a.b.c.d/Auth/User-Logins/Summary/Realm/ ):

clip_image004

This happens even though the user is actually logged into the domain.

Explanation and troubleshooting:

The reason this is happening is actually down to the inner workings of windows. SSO has two modes: “Domain Controller Querying” (DCQ) and “Client Querying”.

DCQ uses an API provided by Microsoft called “NetSessionEnum”. Even though the user is logged in, BCAAA does not see the user as logged in because this API does not see my user as logged in.

A useful tool you can use to check what users the API is returning is “PSloggedOn”, a Microsoft tool available from their website:

http://technet.microsoft.com/en-us/sysinternals/bb897545

This tool utilises the same API that BCAAA does when checking the users logged in on a server remotely (hence the heading “resource shares in the screenshot below). In this particular example, we see that the tool returns the following:

clip_image006

Note that Psloggedon must be run using the same user BCAAA uses and should be run on the domain controller, without any arguments.

From the client PC, we then access a shared folder on the domain controller, and run the tool again on the Domain Controller:

clip_image008

Now we check the proxy and we see the users logged in correctly:

clip_image010

If we check the BCAAA debug logs (see : https://kb.bluecoat.com/index?page=content&id=KB2934 for more information on the SSO debug logs) we also see the correct user:

2011/04/14 09:30:41.034 10.91.25.58 DAVVAS CHILD 10.91.25.1

Why is the issue intermittent?

The windows API does not always return the user. It seems like after a period of inactivity, the API “times out” the user. BCAAA mitigates this by using a “time to live”. This setting is controlled in the sso.ini file:

ValidTTL=86400

But if the TTL expires and the API still does not return the username, the error is displayed.

Why does it work more reliably when using IWA?

When using IWA, not SSO, BCAAA does not use the same windows API, but actually does try to logon to the domain controller (using another API – NetLogon)

What can be done to mitigate this:

– Enable both Domain Controller Querying and Client Querying.

To do this, you need to first change the ProxySG configuration > Authentication > Windows SSO > Agents:

clip_image011

This will cause BCAAA to not only rely on that API we spoke about previously, but also to check who is logged in on the client (using yet another API – NetWkstauserEnum). There are a couple of pointers here:

  • Advantages
  • – More current data than DCQ

  • Disadvantages
  • – Workstations must have port 445 open (possible security risk)

    – Remote registry service should be enabled (disabled by default on Vista and later)
    – BCAAA service must run as a domain user / admin that can query the clients.
    – Client query will fail if the workstation reports that more than one user is logged in

Again, PSlogged on uses the same API. To test, run PSloggedon on the domain controller, using the same BCAAA user and adding the \\w.x.y.z as an argument (where w.x.y.z is the client IP)

If any of those requirements are not met, PSloggedon will show:

clip_image013

If all the above conditions are met, PSloggedon will show:

clip_image015

If multiple users are logged in you will see multiple users under “users logged on locally” and the proxy will throw an error.

Some other useful links when troubleshooting BCAAA SSO:

Single sign-on failed due to Appliance Error (configuration_error)

Window SSO realm authentication failed, browser may received error message "The user could not be determined by the Single Sign-on agent."

Advertisements

User based access control for Skype

I recently wrote an article for Bluecoat describing how to limit Skype access based on usernames and passwords. The article is available here.

This got me wondering if I can achieve the same functionality that the Bluecoat ProxySG offers but using open source programs. In short…. yes we can with a little tinkering. For those of you not interested in reading through the draft for BlueCoat, here is a summary of requirements that this article attempts to achieve:

Skype is allowed to be installed on the desktops, but Skype connectivity should be allowed/denied based on username and password, not on source IP or destination IP. ideally, the usernames and passwords are centrally managed through Active Directory.

The above problem was tackled with BlueCoat by using SOCKS authentication. The Bluecoat proxy then uses it’s BCAAA agent to verify the provided username and password with Active Directory.

After some research, it turn out you can achieve the above method by using DANTE socks server. The site for Dante is here:

http://www.inet.no/dante/

I wont go through the caveats and security implications of this method, for that, see the BlueCoat document above. I will go into the technical details of setting up a DANTE socks server and using LDAP to verify usernames/passwords against an AD domain controller.

For my particular setup, I’ve used an Ubuntu machine which already has SQUID installed on it. DANTE and SQUID run happily side by side. Ubuntu has DANTE as a package in Synaptic so installing it is a simple matter of applying the package. When configuring DANTE, the following three sites from their documentation really helped to clarify what needed to be done:

http://www.inet.no/dante/config/server.html

http://www.inet.no/dante/config/auth.html

http://www.inet.no/dante/doc/faq.html

Let me highlight step by step what needed to be done in my case:

1. Install the DANTE server and pre-requisites for LDAP PAM authentication:

sudo apt-get install danted libpam-ldap libnss-ldap

2. These should install successfully  and you should now be able to modify the DANTE configuration file located at /etc/danted.conf. This was my (basic) configuration. I’ve commented in some explanations to the statements:

#enable logging to a particular file (/var/log/dante.log)

logoutput: stdout /var/log/dante.log

#instruct the server which IPs and ports to listen on. In my case, the server has only a single #interface, so both IPs are the same. Note the standard SOCKS port of 1080

internal: 10.91.25.3 port = 1080
external: 10.91.25.3

# (this was part of the automatically generated default configuration) when doing something that # can require privilege, it will use the userid:
user.privileged: proxy

# (this was part of the automatically generated default configuration) when running as usual, it   # will use the unprivileged userid of:
user.notprivileged: nobody

# (this was part of the automatically generated default configuration)

# If you compiled with libwrap support, what userid should it use
# when executing your libwrap commands?  “libwrap”.
user.libwrap: nobody

# the following instructs the SOCKS server which authentication method to support. In my case, # since DANTE is going to pass the credentials on to PAM which in turn hands over to LDAP, I     # specified “pam” and “none”. (see note on point 3 below)

clientmethod: pam none
method: username pam none

# these rules define who is allowed to use the SOCKS server. These rules get applied before any  # SOCKS data is passed so PAM authentication is not applied here (only can only authenticate     # using IP information at this stage)

client pass {
from: 0.0.0.0/0 to: 0.0.0.0/0
log: error connect disconnect
}

# these rules define what the SOCKS clients can reach. This is where we enforce PAM                   # authentication using the method keyword, so only authenticated users can connect to the      # outside world

pass {
from: 0.0.0.0/0 to: 0.0.0.0/0
command: bind connect udpassociate bindreply udpreply
method: pam
log: error connect disconnect iooperation
}

3. A quick note on the above configuration file. I found that the SOCKS server would reset the skype conenction if I used

clientmethod: pam
method: username pam

Right after Skype provides it’s supported methods of authentication, SOCKS reset the connection. It seems that Skype provides two methods of authentication: none and username/password. It seems that the SOCKS server needs to be configured to support both these methods also. Using

clientmethod: pam none
method: username pam none

resolved this issue for me

Also, note that in a production environment the access rules should be very much more restricted. Keep in mind that as I outlined in the bluecoat document, the username and password are still sent as cleartext so you need very restrictive access rules in case those credentials are compromised.

4. As per the DANTE FAQ, we next modify the PAM file for the socks server to instruct it to use LDAP for authentication. The file to be created is /etc/pam.d/socksd:

# cat /etc/pam.d/socksd
#%PAM-1.0
auth       required /lib/security/pam_ldap.so
account    required /lib/security/pam_ldap.so
password   required /lib/security/pam_ldap.so

Note I deviated from the proposed file in the FAQ. The FAQ proposition checked first the LDAP server, then if that failed, checked the local password file. In my case, I want to restrict logins to only AD users, so in the above file I force PAM to use LDAP only

5. Still following the FAQ, we next move on to modify the file /etc/ldap.conf. This file controls the LDAP client, which the PAM subsytem uses to check the credentials supplied to it. In Ubuntu, the file is already pre-populated with information generated when installing the packages in step 1, but after uncommenting some lines you should end up with something similar to the fillowing:

/etc/ldap.conf

host 10.91.25.2
base dc=davidv,dc=local
ldap_version 3
binddn cn=Administrator,cn=Users,dc=davidv,dc=local
bindpw password02!
#rootbinddn cn=Administrator,cn=Users,dc=davidv,dc=local
pam_filter objectclass=user
pam_login_attribute cn

A couple of points:

  • The auto-generated file uses and LDAP URI to define which host to connect to. This didnt work for me and I had to change to the host 10.91.25.2 statement
  • The file proposed by the FAQ uses the “rootbinddn” statement, which I commented out above since the LDAP client is nornally nut run under root privileges and so I stuck to the “binddn” statement

That was really all there is to it. Of course you need to instruct users on setting up Skype to use your new SOCKS server – see the bluecoat document for info on how to do this.

Verification and Troubleshooting Tips

I found two files to be of great help during verification and troubleshooting:

/var/log/dante.log : the SOCKS server log that I specified in the configuration file

/var/log/auth.log : the PAM logs – this is where you’ll see authentication issues

Some examples of the logs:

  • Non-working dante.log (the problem here was authentcation – wrong credentials)

minty davvas # tail /var/log/dante.log

Mar 15 07:57:44 (1300175864) danted[20026]: block(0): tcp/connect [: pam%[email protected] -> 78.141.181.38.21219: pam_authenticate(): Authentication failure
Mar 15 07:57:44 (1300175864) danted[20024]: block(0): tcp/connect [: pam%[email protected] -> 78.141.181.26.33033: pam_authenticate(): Authentication failure

  • Working dante.log

minty davvas # tail /var/log/dante.log
Mar 15 07:54:01 (1300175641) danted[20027]: pass(1): tcp/connect ]: 39 -> pam%[email protected] -> 42,  42 -> pam%[email protected] -> 39: remote closed
Mar 15 07:54:01 (1300175641) danted[20027]: pass(1): tcp/connect ]: 39 -> pam%[email protected] -> 42,  42 -> 93.156.120.52.21516 -> 39: remote closed
Mar 15 07:54:02 (1300175642) danted[20027]: pass(1): tcp/connect -: 78.141.181.31.21219 -> pam%[email protected] (0)
Mar 15 07:54:02 (1300175642) danted[20027]: pass(1): tcp/connect ]: 32 -> pam%[email protected] -> 53,  53 -> pam%[email protected] -> 32: remote closed
Mar 15 07:54:02 (1300175642) danted[20027]: pass(1): tcp/connect ]: 32 -> pam%[email protected] -> 53,  53 -> 78.141.181.31.21219 -> 32: remote closed
Mar 15 07:54:06 (1300175646) danted[20027]: pass(1): tcp/connect -: pam%[email protected] -> 78.141.181.21.21219 (163)
Mar 15 07:54:06 (1300175646) danted[20027]: pass(1): tcp/connect -: 78.141.181.21.21219 -> pam%[email protected] (4)
Mar 15 07:54:07 (1300175647) danted[20027]: pass(1): tcp/connect -: pam%[email protected] -> 78.141.181.21.21219 (0)
Mar 15 07:54:07 (1300175647) danted[20027]: pass(1): tcp/connect ]: 13352 -> pam%[email protected] -> 20681,  20681 -> pam%[email protected] -> 13352: client closed
Mar 15 07:54:07 (1300175647) danted[20027]: pass(1): tcp/connect ]: 13352 -> pam%[email protected] -> 20681,  20681 -> 78.141.181.21.21219 -> 13352: client closed

  • Non working auth.log file (bad credentials)

Mar 15 07:57:39 minty danted: pam_unix(sockd:auth): check pass; user unknown
Mar 15 07:57:39 minty danted: pam_unix(sockd:auth): authentication failure; logname= uid=0 euid=13 tty= ruser= rhost=10.91.25.1

As always, wireshark is a great help. You can see the Skype authentication to SOCKS (note the cleartext credentials!):

socks1

And you can also see the SOCKS server verifying the credentials with LDAP:

socks2

Note that by default the LDAP client uses simple authentication, which sends the password out in cleartext… if this is a security issue consider securing LDAP using SSL/TLS

Some useful links for linux / microsoft LDAPS:

http://www.openldap.org/doc/admin24/tls.html

http://support.microsoft.com/kb/321051

http://support.microsoft.com/kb/938703