Sunday, September 5, 2010

What Is A Daemon

.In UNIX, a program that runs in the background (not attached to a terminal) is called a "daemon." It's something you can't see, but it's alive and well doing work behind the scenes. In Windows, lots of programs run in this fashion, and they come in different forms, such as: NT services, IIS worker processes, COM servers, and scheduled processes. As a programmer, it's important to know that, even though the plumbing for these daemons is different (compare an NT service with an instance of the IIS worker process, for example), there are lots of similarities between them. And it's important to know these similarities to help simplify your view of server code. Let's talk briefly about some characteristics of daemons on Windows.
Think about what happens when you, the interactive user, launch a new process, either via Explorer or via a command shell. The new process is bestowed with a copy of your token, which puts it in your interactive logon session (WhatIsALogonSession). It's also naturally placed in the interactive window station (WhatIsAWindowStation), so you'll be able to see any windows it displays and interact with them. When you log off, that program will be closed.
Now think of what happens when you start a daemon. Say you start a service by typing net start myservice. In this case, net.exe talks to a daemon called the Service Control Manager (SCM), which was automatically started at boot time in the highly privileged SYSTEM logon session. The SCM's job is to launch the service process into a logon session and window station that allows it to run in the background, disassociated from your interactive logon. If you log out, that daemon can continue to run. The SCM looks at a configuration database in the registry to figure out what credentials to use for the new process (HowToChooseAnIdentityForADaemon). If you've specified that the service run under an account that you've defined, the SCM will create a brand new logon session using those credentials.
Now think about starting an IIS 6 worker process, which you can do by right-clicking an application pool and choosing Start. Instead of the SCM, some IIS plumbing is responsible for the launch. Instead of the registry, there's the metabase where identity is configured via application pool settings. Still, the procedure is very similar, and the result is a daemon process that continues to run even after you log off. COM is similar: It has a SCM and a configuration database of its own. A COM server can be configured to always run as a daemon simply by choosing any identity configuration option other than "Run as interactive user," or "Run as launching user."
Now think about what happens when a daemon process creates another process programmatically, say via System.Diagnostics.Process.Start. The new process inherits the creator's token, logon session, and window station. The new process is a daemon. Heck, the simplest way to write a program that runs as a daemon is to write a console application and launch it via the ages-old at command: at 7:30pm mydaemon.exe. This just adds an entry to the scheduler service's database, and the scheduler daemon will start the process. The major drawback here is that the at command will always start the scheduled process running as SYSTEM, which is a bad idea (see WhatIsThePrincipleOfLeastPrivilege). This problem was solved as of Windows XP with the new schtasks command, with which you can choose an arbitrary identity for the scheduled process.
Daemons run in noninteractive window stations (WhatIsAWindowStation), so don't ever do something silly like put up a modal dialog box from code that could run as a daemon (HowToDisplayAUserInterfaceFromADaemon).
Daemons don't always have a user profile loaded (WhatIsAUserProfile). Why should they? They only run under a single identity; they don't need a way to store per-user preferences. No daemon I've ever written has needed a Favorites folder! It turns out that the NT SCM does in fact load the user profile, most likely for historical reasons. If you configure an NT service to run as Bob, that service can use HKEY_CURRENT_USER, which will be mapped onto a registry hive in Bob's profile. However, the COM SCM doesn't load the user profile—apparently, the COM team decided this was a waste of time for a daemon. So, if a COM server configured to run as Bob tries to access HKEY_CURRENT_USER, it will end up getting mapped onto a default hive that's reserved for use by SYSTEM, where it likely will have only read permissions. The moral of the story is to avoid relying on user profile settings in daemon code. A couple of examples include secrets stored with DPAPI (HowToStoreSecretsOnAMachine) and certificate stores. Most Win32 APIs that both rely on user profiles and are typically used by daemons have a flag that usually contains the text LOCAL_MACHINE. These flags allow you to indicate that you're a daemon and you want to use a machine store, not a per-user, profile-based store.
Programming your daemon to use machine stores tremendously simplifies administration. You don't ever want the Administrator to have to log in using your daemon's credentials; in fact, your daemon's user account probably shoudn't even have the user right called "Log on locally" (HowToGetATokenForAUser). But if your daemon code relies on a user profile store, say for decrypting a DPAPI secret, and if the administrator is the one who is supposed to encrypt this secret in the first place, she'll need to be logged on using the daemon's user account in order to do this. And daemon accounts normally use long, random passwords that are very difficult for humans to type. This just makes no sense. So stick to machine stores in daemon code!

No comments:

Post a Comment