Eugene's Site
FAQ: Security
This section contains answers to questions about logons, user identities and other security related things.

Currently logged in user

Problem

I want to know X about currently logged in/logged on user. There are many variations of this problem. Usually people like to get user's name, domain or even credentials.

Solution

What you are asking for doesn't exist and impossible. Try to redesign your application

Explanation

There is no such thing as currently logged in/logged on user. On NT based systems in general there can be (and are) many users simultaneously logged in to a given machine. What you probably have in mind are interactive users but even with this clarification you are out of luck. On NT Terminal Server, Win2k with terminal services and plain vanilla XP and later there could be multiple interactive users at the same time.

If you suddenly discover that your application requires knowledge of "currently logged in user" it means that you are doing something wrong that violates OS design. Rather than trying to outsmart the OS consider redesigning your application. People often hit this problem when they are trying to communicate to the "current user" from a service. If so you are going in the wrong direction. Services shouldn't interact with users. If you have some information to convey write it to a log file or an event log.

Back to top

Users logged on to domain

Problem

I want to know X about users logged on to domain.

Solution

Your real problem probably has a solution but you will have to reformulate the question to specify what users you are interested in.

Explanation

There is no such thing as users logged on to a domain. It is a misnomer perpetuated by some MS documentation. You always, always log on to a computer. It could be a terminal you are sitting before or a remote host you are trying to access files on -- it doesn't matter. You always log on to a specific machine. Now the question is how the machine knows who you are (authenticates you). In a simplest pre-network world case it you present what you claim to be (username) and what you know (password) and the machine matches this information against it's local database (called SAM database on Windows). This scheme works as long as you are willing to replicate this database across all the computers you will ever be likely to access (don't laugh, some Unix machines are still configured that way). In a networked world an obvious idea is to centralize this database on some server. This server becomes a "security authority" (domain controller in Windows lingo) and it is relied on to perform security related tasks by other machines (workstations). But now the question is how a specific machine knows which server to go to and how can it trust this server. Your machine cannot just go to the Internet and use any server for authentication since you never know whether it belongs to bad-guys.org or good-guys.net :-) Don't forget that when your machine tries to authenticate you it may send your password to this server and you do not want bad-guys.org to know it. There are various ways to solve the trust problem and Windows developers have chosen that machine administrator must manually configure which (group of) servers your computer trusts. This operations is called "joining the domain". After joining your workstation will trust any of domain controllers in the designated domain to perform security related tasks for it. When you are "logging into domain" you simply present your workstation with a set of credentials stored on a domain controller and all the workstation has to do is to go to DC to validate them. Then it logs you on locally.

Back to top

User's host

Problem

How to find the host from which the user is logged on.

Solution

There isn't an easy solution to this one. Thought the request is reasonable, Windows authentication mechanism isn't designed to support this kind of query. The solutions below may help but they all have many deficiencies. You should consider redesigning your application instead of relying on them. All possible solutions can be divided into two groups: event driven and polling. Event driven solutions rely on some kind of notification about user logon. They have an advantage of seeing all relevant logons regardless of their timing. The polling methods rely on periodic enumeration of some data and can miss some users. Whether this matters depends on your goals. All event driven methods suffer from the logoff problem which is the fact that in general there isn't any meaningful notification about user's logoff (think what happens when user's machine just) crashes. Again, this may or may not be a problem. 

Polling solutions

Enumerate CIFS/SMB sessions on the domain controller

The APIs you need are:

NetSessionEnum();
NetSessionGetInfo();

One thing to realize here is that this method is not even guaranteed to work for all users logged on now. Recall, that users do not log on to domain but to their workstations. Whether this would result in a network session to a domain controller is unspecified by MS. Sometimes it does and sometimes it doesn't (probably a subject for another FAQ entry). Again, depending on what kind of users you are interested in this method may or may not work for you.

Enumerate terminal services sessions on the machine in question

The APIs you need are:

WTSEnumerateSessions();
WTSQuerySessionInformation();

This method obviously is intended to work with users logged on interactively either locally or remotely. If this is what you need it is guaranteed to work. Again, there is a caveat about not being event driven.

Event-driven solutions

Logon script

Use logon script to run a small application that will report to some central server about the fact that user is logged on and the host on which this happened. The advantage of this approach is its simplicity. You don't need to program anything sophisticated to make it work. The disadvantages are, however, numerous. First if most of your users logon at the same time (say 8:00 AM) you will clog your network. Second, the mechanism is unreliable and shouldn't be used for security. It is too easy for a workstation user to disable the logon script. Third, there is a problem discovering when the user logged off since you won't necessarily have time to report it. Finally, and most importantly, this is not a shrink-wrapped solution. The nature of logon scripts is such that each of your customers will have to do a whole lot of manual configuration to make it work.

SENS notifications

This solution was suggested by Ivan Brugiolo from Microsoft. I have never tried to use it and don't know anybody who did so I'll just quote his comment here

If you "own" all the machines of the network, you could use SENS notifications for Logon Events from all the workstations.

If anybody has more information about this method, please let me know

Logon interception on a DC

Intercept all logons on the domain controller by hooking

LsaApLogonUser[Ex|Ex2]();

in MSV1_0 authentication package. As you can see from the documentation on of the parameters of the above API's contains the name of the machine from which the logon is made. This method is very powerful but, unfortunately, it is limited to old-style (NT) domains only. New Win2k style domains that use Kerberos authentication do not pass this information. In fact if you look on your Win2k domain DC security event log you will notice that all logon events are missing machine name too. Apparently, Windows itself doesn't know. If you decide to use this method you will need to inject your code into lsass.exe (Local Security Authority SubSystem) process. If you do so make sure you give your users a way to disable your software in boot sequence. If you crash lsass.exe the system will die and there is nothing the users will be able to do.

Explanation

This is not really an explanation but a gripe about the way Microsoft implemented its authentication mechanism. The request to know the host from which the authentication was performed is a natural one, especially in security applications, and there should be a simple way to do it.

Back to top

Pass through authentication

Problem

I have two domains A and B. My account in both domains is Bob and has the same password. I've noticed that when I am logged on on a machine A1 in domain A as A\Bob and try to access machine B1 in domain B I am not prompted for credentials and silently authenticated as B\Bob. What is going on? Is this normal?

Explantion

Yes it is normal and documented behavior. More details are here. Make sure you read the last section in this article.

Explantion

While I don't know the precise reasons for this feature I can speculate that this is a

  1. Legacy of old pre-domain Windows networks.
  2. A way to make ad-hoc networks of NT-based workstations work.
The legacy argument goes like this. In the old days all you had was username as there was no concept of domains. When an old style Windows/Lan Manager client connects to a share it probably sends only the username "Bob" without the domain. A modern server must somehow make sense of such request by assuming that the client belongs to the same domain and trying its username and password.

The second argument is that many people (especially home users and small businesses) create ad-hoc networks of NT-based computers with same account names and passwords on all machines. It would be very inconvenient for them if every access to a share resulted in a logon box. One could imagine a user shouting "why couldn't stupid Windows figure out that I am Bob?". So it does

Back to top