FreeBSD/Mach OpenDirectory Port — Scoping (Deferred)

Status: SCOPING ONLY — not a commitment to execute; deferred until a real consumer emerges

This document captures everything currently known about what porting Apple’s OpenDirectory stack (and related directory infrastructure) would entail on the freebsd-launchd-mach image. It is NOT a commitment to do this work — it’s discovery so the decision can be made later from a position of accurate information rather than guesses. The companion PAM port plan intentionally does NOT depend on any of this.

1. Why this is its own plan

Two reasons OD is split from the PAM port:

  1. The PAM port is a small, well-bounded vendoring task (~1–2 weeks); OD is a multi-month, multi-component undertaking with genuine architectural questions still open.
  2. Apple’s upstream pam_unix defers to NSS — whatever directory lives at the NSS layer is invisible to PAM. So the PAM port works against any directory backend (today gershwin DS via nss_gershwin; tomorrow potentially OD; the day after potentially something else). They’re orthogonal decisions.

2. The binding constraints

2.1 opendirectoryd daemon source is CLOSED

Apple stopped publishing the directory-services daemon when it was renamed opendirectoryd in Mac OS X 10.7 Lion (2011). The XPC + MIG wire-protocol headers (opendirectory/odipc.h, opendirectory/odutils.h, opendirectory/odconstants.h) ship only with the closed daemon. The open client framework (apple-oss-distributions/OpenDirectory, 313 KB / ~6,200 LOC CF core) is functional code but has no server to talk to.

2.2 Active Directory plugin source is CLOSED

Apple ships an AD plugin for OpenDirectory but never open-sourced it. A code search across apple-oss-distributions for DSActiveDirectory* / PlugInActiveDirectory* returns zero results. The other DS plugins (LDAPv3, NIS, PasswordServer, NSL, etc.) are open; AD is the conspicuous exception.

2.3 Tiger NetInfo open-source drop is incomplete

apple-oss-distributions/netinfo (tag netinfo-384) ships only the common/ shared library (~382 KB of C). The actual daemons (netinfod, nibindd, lookupd) and tools (nicl, niutil, nidump, niload, nigrep, nipush, nireport, nifind, nidomain) were dropped from the open-source bundle. Reconstructing the daemons is real engineering, not just a rebuild.

3. What IS open and portable

ComponentApple repoSizeRole
OpenDirectory client framework OpenDirectory 313 KB / ~6,200 LOC C core Pure XPC client to opendirectoryd. Functional but needs the closed daemon’s wire-protocol headers and a server to talk to.
Legacy DirectoryService daemon DirectoryService 2.2 MB / ~50k LOC C++/MIG opendirectoryd’s 2009-vintage predecessor (Snow Leopard). Plugin host. Uses Mach IPC + MIG + optional DH+AES TCP proxy. Fully open including SDK.
DS admin tools DSTools 432 KB Source for dscl, dscacheutil, dsenableroot, dsmemberutil, dsconfigldap, pwpolicy, dserr, ugtools, dirt. NOT in DSTools (closed): dseditgroup, dsexport, dsimport, dsconfigad.
DS plugin backends DSLDAPv3PlugIn, DSLDAPPlugIn, DSNISPlugin, DSPasswordServerPlugin, DSNSLPlugins, DSAgent ~1.4 MB total LDAPv3, NIS, PasswordServer, mDNS/SLP/SMB-browse backends for the DS daemon. AD plugin is NOT here.
Kerberos (Heimdal) Kerberos, KerberosHelper, KerberosLibraries 22 MB + 300 KB + 14 MB Apple’s Heimdal port plus their helper daemon and libraries. Tightly tied to OS X internals; FreeBSD ports already has Heimdal so this isn’t the only path.
SMB client (modern) SMBClient 4.8 MB Apple’s SMB3 client. Replaced Samba when GPLv3 became unacceptable to Apple in OS X 10.7.
SMB kernel module smb 2.8 MB Apple’s kernel smbfs (XNU). Not portable to FreeBSD kernel without major rewrite.
Samba (legacy) samba 43 MB Apple’s Samba 3.x fork, frozen at the GPLv2 era. Still buildable but Apple stopped maintaining it.
NetInfo (lib only) netinfo 382 KB C (lib only) Daemons + CLIs not published. See §2.3.

4. Directory-service landscape comparison

Feature Tiger NetInfo Snow Leopard DirectoryService Gershwin DS (today)
Record types ~20 (users, groups, machines, networks, services, printers, mounts, aliases, bootp, …) ~50 (extensible per plug-in via dsRecTypeNative: prefix) 2 — users + groups only
Attributes Flexible key/value ~100 standard + native-per-plugin 6 fixed per type (uid/gid/realName/shell/hash/noPassword for users)
Pluggable backends No (monolithic engine over single NIDB store) Yes — Local plist, LDAPv3, AD, NIS, BSD-flat, Bonjour/mDNS, PasswordServer, NBP/SLP/SMB No (single plist backend)
Auth methods crypt(3) only 25+ (Crypt, NTLMv1/v2, MS-CHAPv1/v2, CRAM-MD5, DIGEST-MD5, APOP, CHAP, Kerberos, …) SHA-512 crypt(3) only
Password policy None Rich via PasswordServer (pwpolicy(8)): lockout, expiry, history, complexity, admin status, disabled flag None — NSS module hardcodes all shadow fields to -1
Group nesting No Yes (kDSNAttrNestedGroups, resolved by memberd) Special-case admin→wheel/sudo injection only
Replication Master/clone with DB-version delta sync Delegated per-backend (LDAP replicas, PasswordServer replica set) None — one server per LAN; data shared via NFS
Server discovery Broadcast (parent-domain chaining) DHCP option / SLP / Bonjour / manual dsconfigldap gdomap broadcast (GNUstep portmapper)
Transport security Plaintext Sun RPC over UDP/TCP; no server auth Mach IPC (audit-token authenticated) + optional Diffie-Hellman + AES TCP proxy + Kerberos for AD Plaintext everywhere — AF_UNIX socket, TCP/4721 LAN listener, NFS (AUTH_SYS), gdomap broadcasts. No TLS, no signing, no Kerberos
Open-source status Partial — only common/ lib; daemons + CLIs dropped Fully open (daemon, SDK, all major plug-ins, tools, framework) — except AD plugin Fully open (this is gershwin’s own code)
Source size ~382 KB C library only ~3.1 MB DS daemon + ~860 KB DSTools + ~810 KB OpenDirectory framework + ~1.4 MB plugins = ~6 MB ~4.7k LOC total (~80% Obj-C, 20% C)

5. Possible end-states and what each requires

5.1 OD client on the FreeBSD/Mach box (no AD)

Means: pam_opendirectory.so works against a local or remote OD/LDAP directory. No AD support.

ComponentStatus
OpenDirectory frameworkVendor, ~6,200 LOC, modest shimming (asl, assumes, CrashReporterClient, mbr_*, NetBSD rb-tree)
opendirectoryd-equivalent daemonClosed. Either: (a) port legacy DirectoryService daemon and bridge OD framework calls to dsapi, or (b) write a minimal XPC-speaking daemon that mimics the wire protocol enough for the framework's needs.
DS daemon (Path B)2.2 MB / 50k LOC C++/MIG, 2009 vintage, multi-week port
LDAPv3 plugin or Local pluginOpen, ~weeks to port + adapt to read our user store
DSToolsOpen, ~432 KB, port to get the dscl family of admin tools

Realistic effort: ~6–8 weeks of focused porting. Result: an OD client capable of running pam_opendirectory + admin via dscl. Still no AD binding.

5.2 OD + AD bind on the FreeBSD/Mach box

Means: machine can join an Active Directory domain, users can log in with AD credentials, machine can pull GPOs.

ComponentStatus
Everything in 5.1Required
AD pluginClosed. Write from scratch against the DS plugin SDK. Realistic: ~5–10k LOC integrating Kerberos + LDAP + SMB + DNS SRV + computer-account creation + GPO retrieval.
KerberosOpen (or use FreeBSD’s Heimdal port). Needs modern enctypes (AES-256-CTS-HMAC-SHA384-192) for current AD environments — FreeBSD’s port has this; Apple’s 22 MB port may need upgrades.
SMBClientOpen, 4.8 MB. ~1–2 weeks port atop existing CF/launchd/configd.
DNS SRV lookupsAlready work via libresolv.

Realistic effort: 5.1 + 2–3 months for the AD plugin. Result: AD-bound FreeBSD/Mach box. Modern AD features (claims, gMSA, smartcard, FIDO2) still won’t work without further plugin work; basic user-login + group-resolution would.

5.3 OD server for modern Macs to bind to

Means: FreeBSD/Mach box runs an Open Directory server. Newer macOS clients can bind to it for users + Kerberos auth.

ComponentStatus
Everything in 5.1Required
OpenLDAP slapd~50 MB FreeBSD port, well-known build effort. Several hours to compile cleanly.
Kerberos KDCApple ports / FreeBSD’s Heimdal. KDC requires careful crypto configuration to satisfy current macOS clients.
PasswordServerOpen at apple-oss-distributions/DSPasswordServerPlugin (482 KB). 2009 era; modern clients may require crypto modernization.
DS daemonRequired (5.1)

Realistic effort: ~2–3 months stand-up, plus permanent ongoing maintenance for crypto modernization as macOS raises security bars. Result: OD server. Modern Macs can bind for user login + Kerberos. Some features may need patching over time.

5.4 AD server impersonation

Means: pretend to be a Windows AD server, accept Mac and Windows client binds.

Not viable via Apple sources. Apple has never shipped an AD server. AD server requires Microsoft’s specific schema (~5000 attributes), DRSR replication protocol, GPO infrastructure, SYSVOL share, etc. That’s Samba 4’s territory — ~15 years of focused engineering. If this is ever a real need, use Samba 4 directly (FreeBSD port exists).

6. What this would actually buy us

Gershwin DS today covers ~5–10% of OD/DS’s surface but covers the things actively used: user/group lookup, password verification, simple admin CLI. The gap that an OD port would fill:

7. When to revisit

This plan is in scoping-only state until at least one of the following becomes true:

Until then, focus stays on completing the PAM port (see PAM plan) which is unaffected by any of this.

8. Open questions for future decision

  1. If we ever pursue 5.1, do we port the legacy DirectoryService daemon (Path B) or write a minimal XPC-speaking opendirectoryd-equivalent that bridges the OD framework? The latter is smaller code but requires reverse-engineering the XPC schema from OpenDirectory/Core/odxpc.c.
  2. If we ever pursue 5.2, is FreeBSD’s Heimdal port acceptable, or do we vendor Apple’s Kerberos (22 MB)?
  3. If we ever pursue 5.3, do we vendor Apple’s legacy Samba (43 MB, GPLv2-era) for SYSVOL share serving, or use FreeBSD’s Samba 4 port?
  4. Could the gershwin DS evolution path (incrementally add Kerberos, password policy, transport security) reach feature parity with what we need for less effort than porting OD? Likely yes; the strategic question is whether maintaining our own daemon vs. carrying Apple’s 2009 code is the better long-term burden.
  5. Would a community reimplementation of the OD XPC protocol ever emerge? Unlikely; the audience is tiny and the reverse-engineering effort substantial.

Scoping document generated 2026-05-25 from deep-dive of apple-oss-distributions/{OpenDirectory, DirectoryService, DSTools, DSLDAPv3PlugIn, DSNISPlugin, DSPasswordServerPlugin, DSNSLPlugins, Kerberos, SMBClient, samba, netinfo} and gershwin-desktop/gershwin-components/DirectoryServices.