Behind the Scenes: Open Directory and Kerberos

Perhaps the most peculiar thing about the recent root user vulnerability in High Sierra is the fact that it occurred in one of the older corners of macOS, in Open Directory, which was introduced in Mac OS X Server 10.2 in 2002.

It’s a system within macOS which seems to have changed relatively little for the last decade, but has apparently changed greatly in the step from Sierra to High Sierra, which took it from version 417.50.4 (10.12.6) to the current 483.20.7 (10.13.1 updated).

Open Directory quietly assists a lot of different services in macOS, but in this context is most important for handling information about users, specifically for authenticating users in conjunction with the Apple Password Server (APS, not to be confused with Apple Push Service and its daemon apsd).

The normal user interface to Open Directory is through the Directory Utility app, now inconveniently hidden away in /System/Library/CoreServices/Applications, although it can be opened through the Users & Groups pane if you prefer. This offers three tabs:

  • Services, which lets you select between different directory services,
  • Search Policy, which determines search policies, and
  • Directory Editor, which lets you view and change settings for individual users, and so on.

Directory Utility’s menu is also where you can enable and disable the root user, should you need to.


Should you ever wish to configure opendirectoryd, the Open Directory service, you’ll need to use the odutil command, which is complex and extensive, and as ever is documented in man odutil.

Often the best way to see how macOS systems work is to browse their entries in the log. Unfortunately, the unified log protects the privacy of most opendirectoryd entries, turning them into
14:13:18.697835 opendirectoryd queuing request to connection - '<private>'
14:13:18.698957 opendirectoryd Client: <private>, UID: 501, EUID: 501, GID: 20, EGID: 20

in Sierra, and making them almost vanish in High Sierra, so my log transcripts are here drawn from the earlier version of macOS. opendirectoryd still keeps its own traditional text logs, in /var/log/opendirectoryd.log, but these are mostly diagnostic information for its activities, rather than a detailed account of its transactions.

opendirectoryd initialises quite early during startup, at that stage for user ID 0, root:
0:02.078206 opendirectoryd Client: <private>, UID: 0, EUID: 0, GID: 0, EGID: 0
0:02.253659 <APSDaemon: 0x7fd203628570>: Finishing login of uid 0

(Times are given as minutes:seconds elapsed since startup, iMac17,1.)

Twenty seconds or more later, the login window is displayed:
0:27.322536 Login Window Application Started

Once the user has completed logging in, Apple Password Server recognises the change in users, and initiates setting the system up for the user. If that is the primary admin user account, the user ID will be 501:
0:34.654357 Login Window login proceeding
0:48.504283 <APSDaemon: 0x7fd203628570>: Change in users with uid new = (501), logged out = ()
0:48.504737 <APSSystemUser: 0x7fd203616b30>: Initializing system user with uid 501
0:48.504795 <APSDaemon: 0x7fd203628570>: Starting login of uid 501

Armed with the user password, the user’s login keychain can now be unlocked, and the user’s operating environment set up for them:
0:48.510472 0x6180000786c0 opened /Users/hoakley/Library/Keychains/login.keychain-db: 1612808 bytes
0:48.510683 <APSSystemUser: 0x7fd203616b30>: Changing status for uid 501 from logged out to logged in
0:48.510696 <APSCourier: 0x7fd20351eac0>: Logging user with uid 501 into environment production
0:48.562940 SecKeychainLogin result: 0, password was supplied

Shortly after this, the first messages from opendirectoryd for user ID 501 start to appear:
0:48.570038 opendirectoryd Client: <private>, UID: 501, EUID: 501, GID: 20, EGID: 20

This sequence of events appears quite similar in High Sierra, although because of changed privacy settings the user ID of 501 is often substituted by <private>. Surrounding messages usually make it obvious when that is the case.

So far, I have only referred to local login and authentication using Password Server. When you connect to your Mac to use it as a file server, or using a remote control system such as Apple’s Remote Desktop, different services will be used to accomplish authentication. One of those is Kerberos, which allows a single sign-on for multiple services.

When you connect to a Mac to share files, the process of authentication may quite possibly proceed using the Kerberos Key Distribution Centre, KDC, which in turn works with the Open Directory service. Kerberos has been part of Mac OS X for even longer than Open Directory, as it was introduced in version 10.1.

Kerberos operates a complex sequence of exchanges, involving ‘tickets’ with short periods of validity, to grant access to services. From the first step, Kerberos depends on access to a directory server, which is normally Open Directory. Hence the close relationship between shared services, Kerberos, and Open Directory.

What was wrong in High Sierra, and was fixed by the recent security update, was that Open Directory was checking attempts to log on as, for example, root, but was not refusing them for recognised users which were not supposed to be able to log on. When the root user is disabled, Open Directory should have automatically refused, but instead accepted and created a new account with an empty password.

When this bug was fixed by the first release of the security update, the local Kerberos Key Distribution Centre required rebuilding before file sharing services would be allowed to authenticate using Kerberos, hence Apple’s additional instruction to run the configureLocalKDC command to restore authentication for those services. I also suspect that those who followed my initial advice, to restart their Macs after installing the update, may not have had any problems with authenticating for file sharing, as that should have had the same effect.