Oracle Blog

Mike Shapiro's Blog

Unified POSIX and Windows Credentials for Solaris

Last week something really exciting happened in OpenSolaris: we got a native Windows CIFS server checked in. CIFS, also known as SMB, is the file sharing protocol used by Microsoft Windows systems, akin to NFS on UNIX. (Unlike NFS, CIFS crosses boundaries into other aspects of Windows as well, but that's a story for a different day.) The result of this project is that OpenSolaris can now serve up ZFS to UNIX clients over NFS and Windows clients over CIFS, along with all of the other file sharing protocols you find on a modern system. Similar to the Solaris NFS implementation, our CIFS implementation is in-kernel for performance and scale, and is accompanied by a collection of userland services that handle the non-performance-critical aspects of the problem like session management and so forth. The OpenSolaris CIFS putback is the result of a lot of really hard work led by Alan Wright and our team of CIFS engineers. Read Alan's blog for more of the back story there.

To make the CIFS server a reality inside of Solaris, one nasty root design problem we had to confront was how to represent Windows credentials and identities in Solaris. Like all UNIX systems, Solaris represents user and group identities as integers (UIDs and GIDs) that are semantically associated with a name by your current name service. But the kernel and your filesystem just store those integers in memory in the kernel and on-disk, and its up to the system administrator to connect the system to the appropriate name service to semantically bind those identifiers to the right names. However, unlike a UNIX/POSIX system, Windows has a much more complex notion of identity, represented by an identifier called an SID, which is in effect a universally unique identifier with an Active Directory Domain that has a more complex set of security attributes associated with it. The challenge for us was to consider how to represent this other notion of identity and credential in our system, while still maintaining all of the POSIX APIs and compatibility. And we decided to get aggressive: rather than just viewing Windows identities as an artifact of one service on the system and mapping everything to a POSIX lowest-common-denominator internally, we've actually gone much further and changed Solaris to support a much more sophisticated representation of identity and credentials so we can fully support both models.

I worked with the CIFS team earlier this year to make this happen, and now that their putback is done and the project
has been opened to the community, I've made the full details available. (You can also directly download a copy of the design spec here.)
If this is a technical area that interests you, I hope you will benefit from reading our examination of the problem and how we decided to do what we did. Here is the executive summary:

We changed the type of uid_t and gid_t in Solaris from 32-bit signed to 32-bit unsigned. This really should have
been done a long time ago, and brings us (in my opinion) into better alignment with other UNIX variants.

We reserved the UID and GID values 0x80000000 - 0xFFFFFFFE to be used for what I call ephemeral mappings to foreign identifiers, represented by a generic form of an SID. These mappings are done by the new identity mapping service in OpenSolaris, called Winchester. (Winchester also can perform mappings of user names between POSIX and Windows name services: see the Winchester project page for all of the details.

We created a way for Solaris filesystems to store persistent identifiers in the filesystem on-disk that can represent arbitrary identifiers including both POSIX IDs and SIDs and convert those back to credentials in the kernel.

We extended the Solaris ucred mechanism so that these more complex credentials can be expressed back to userland processes for services that need them.

Read the spec for more details, as there is obviously a lot that needed to occur to make this happen. For developers, the best part is that we're able to maintain a very sound compatibility story with existing applications and APIs, as
you would expect from Solaris. The key thing for developers to understand is that, as was always implied by POSIX but now has even more significant meaning, you should not write programs that store integer UIDs and GIDs to files on disk, or send them over the network as part of a network protocol. Instead, programmers should convert identifiers to a persistent form such as an SID or qualified name, and serialize those forms instead. Most modern programs and protocols, such as GNU tar, Solaris tar, NFSv4, and others already do this.

All the ID machinations aside, it's incredibly exciting to see OpenSolaris expand its reach as a high-performance, high-scale server for Windows and Mac clients in a heterogeneous environment. For the first time since I've been at
Sun, I can honestly enthusiastically say: Fire up those Windows laptops! Because there's something interesting to see.