Open Directory Programming Guide Networking > Mac OS X Server 2007-01-08
Apple Inc. © 2007 Apple Inc. All rights reserved. No part of this publication may be reproduced, stored in a retrieval system, or transmitted, in any form or by any means, mechanical, electronic, photocopying, recording, or otherwise, without prior written permission of Apple Inc.
Contents Introduction Introduction 7 Organization of This Document 7 See Also 7 Chapter 1 Concepts 9 Open Directory Overview 9 Nodes 10 Search Policies and Search Nodes 12 Record Types 12 Standard Attribute Types 14 Native Attribute Types 15 Authentication 15 Directory Proxy 21 Open Directory, lookupd, and NetInfo 22 Directory Service Command Line Utility 24 Debugging 24 Chapter 2 Working with Nodes 25 Listing Registered Nodes 25 Finding a Node 27 Opening and Closing a Node 28 Authenticating a User to
C O N T E N T S 4 2007-01-08 | © 2007 Apple Inc. All Rights Reserved.
Figures, Tables, and Listings Chapter 1 Concepts 9 Figure 1-1 Figure 1-2 Figure 1-3 Figure 1-4 Table 1-1 Table 1-2 Chapter 2 Working with Nodes 25 Listing 2-1 Listing 2-2 Listing 2-3 Listing 2-4 Chapter 3 Flow of an Open Directory request 10 An Open Directory request over a network 11 lookupd and NetInfo interaction when using SSH 23 lookupd, NetInfo, and Open Directory interaction when using SSH 23 Standard record types 13 Standard attribute types 14 Listing registered nodes 25 Finding the node for a
F I G U R E S , T A B L E S , A N D 6 2007-01-08 | © 2007 Apple Inc. All Rights Reserved.
I N T R O D U C T I O N Introduction This manual describes the Open Directory application programming interface for Mac OS X v10.4. Open Directory is a directory service architecture whose programming interface provides a centralized way for applications and services to retrieve information stored in directories. The Open Directory architecture consists of the DirectoryServices daemon, which receives Open Directory client API calls and sends them to the appropriate Open Directory plug-in.
I N T R O D U C T I O N Introduction 8 See Also 2007-01-08 | © 2007 Apple Inc. All Rights Reserved.
C H A P T E R 1 Concepts Open Directory is a directory service architecture whose programming interface provides a centralized way for applications and services to retrieve information stored in directories. Often, the information that is being sought is configuration information stored in a NetInfo database or in flat files, with each file having its own record format and field delimiters.
C H A P T E R 1 Concepts Figure 1-1 Flow of an Open Directory request Open Directory client DirectoryServices daemon Open Directory plug-ins Request Response The Open Directory programming interface identifies the basic features that are common to many directory services and provides the functions necessary to support the development of high-quality applications that can work with a wide range of dissimilar directory services.
C H A P T E R 1 Concepts Figure 1-2 An Open Directory request over a network Open Directory client DirectoryService daemon LDAP plug-in Local System NetInfo plug-in public.example.com Publications Remote System private.example.
C H A P T E R 1 Concepts Note: An Open Directory plug-in is not required to return information that conforms exactly to the information that the directory service maintains. A plug-in can generate information “on the fly.” In addition, a plug-in may not return information about certain nodes; the plug-in's behavior in this respect can be configurable.
C H A P T E R 1 Concepts Table 1-1 Standard record types Constant Description kDSStdRecordTypeUsers Standard record for describing users kDSStdRecordTypeGroups Standard record for describing groups kDSStdRecordTypeMachines Standard record for describing machines kDSStdRecordTypeHosts Standard record for describing hosts kDSStdRecordTypePrinters Standard record for describing printers kDSStdRecordTypeNetworks Standard record for describing records in the networks file kDSStdRecordTypeServi
C H A P T E R 1 Concepts Constant Description kDSStdRecordTypePrintServiceUser Standard record for storing quota usage for a user in the local node kDSStdRecordTypeBootp Standard record for storing bootp information kDSStdRecordTypeNetDomains Standard record for storing net domains kDSStdRecordTypeEthernets Standard record for storing Ethernets kDSStdRecordTypeNetGroups Standard record for storing net groups kDSStdRecordTypeHostServices Standard record for storing host services Standard Att
C H A P T E R 1 Concepts Constant Description kDS1AttrPort Standard attribute for storing the port number at which a service is available; commonly found in kDSStdRecordTypeAFPServer, kDSStdRecordTypeFTPServer, kDSStdRecordTypeLDAPServer, kDSStdRecordTypeWebServer, and other service discovery records kDSNAttrGroupMembership Standard attribute for storing group memberships kDSNAttrAuthenticationAuthority Standard attribute for storing authentication authorities; commonly found in records of type kD
C H A P T E R 1 Concepts ■ Kerberos Version 5 authentication, which is used to authenticate users to Kerberos v5 systems. For more information, see “Kerberos Version 5 Authentication” (page 19). ■ Disabled User authentication, which prevents any authentication from taking place. For more information, see “Disabled User Authentication” (page 20).
C H A P T E R 1 Concepts an appropriate network-based authentication method, such as CRAM-MD5, APOP, NT, LAN Manager, DHX, or Web-DAV Digest. Note that the Password Server’s administrator may disable some authentication methods in accordance with local security policies. The authority data field must contain two strings separated by a single colon (:) character. The first string begins with a SASL ID. The SASL ID is provided to the Password Server to identify who is attempting to authenticate.
C H A P T E R 1 Concepts Local Windows Hash Authentication The Local Windows Hash authentication type was used on Mac OS X v10.2 in combination with Basic authentication, but its use is superseded by Shadow Hash authentication in this version of Mac OS X. With Local Windows Hash authentication, hashes for NT and LAN Manager authentication are stored in a local file that is readable only by root. The local file is updated to contain the proper hashes when the password changes.
C H A P T E R 1 Concepts Local Cached User Authentication Local Cached User authentication is used for mobile home directories. The authority data field must be present. Its format is DS Nodename:DS Recordname:DS GUID where the colon (:) character delimits the three individual strings. All three strings are required. The first string is any valid node name in UTF-8 format. The second string is any valid record name in UTF-8 format.
C H A P T E R 1 Concepts Disabled User Authentication The Disabled User authentication is used to indicate that an account has been disabled. The complete previous authentication attribute value is retained in the authority data field and is enclosed by left and right angle brackets. If the authority data field is absent, Basic authentication is assumed.
C H A P T E R 1 Concepts Other directory services store authorization information outside of the service. By providing an interface between clients of directory services and the directory services themselves, authorization information that is stored outside of the directory service can be shared.
C H A P T E R 1 Concepts Directory function that requires such a reference. Once a remote Open Directory session is successfully opened, Open Directory automatically sends all calls to Open Directory functions that use the remote directory reference to the DirectoryService daemon over the encrypted TCP/IP connection. Other than calling dsOpenDirServiceProxy, there is nothing the application has to do in order for its actions to take effect on the remote system.
C H A P T E R 1 Concepts Figure 1-3 lookupd and NetInfo interaction when using SSH tjones SSH 1. lookupd cache lookupd 2. NetInfo agent DSAgent Request local.nidb tjones Positive response Negative response In Figure 1-3, the user’s record is located on the local system. Figure 1-4 shows what happens when the user’s record is located on a remote system. Figure 1-4 lookupd, NetInfo, and Open Directory interaction when using SSH tjones SSH 1. lookupd cache lookupd 2. NetInfo agent 3.
C H A P T E R 1 Concepts In this example, lookupd queries its local cache and NetInfo, and gets negative responses — “tjones” could not be found in either location. Now, lookupd tells its DSAgent to query Open Directory. Searching the local NetInfo database is the first step in every Open Directory search, so Open Directory tells its NetInfo plug-in to search the local NetInfo database. Again, “tjones” is not found.
C H A P T E R 2 Working with Nodes This chapter provides sample code that shows how to work with nodes. Finding a specific node, opening a session with the node, and authenticating a user to the node are fundamental Open Directory tasks. Listing Registered Nodes The sample code in Listing 2-1 demonstrates how to get a list of all registered nodes. The sample code opens an Open Directory session and gets an Open Directory reference. Then it calls its own ListNodes routine.
C H A P T E R 2 Working with Nodes tContextData context = NULL; dirStatus = dsGetDirNodeCount( gDirRef, &nodeCount ); printf( "Registered node count is: %lu\n", nodeCount ); if ( (dirStatus == eDSNoErr) && (nodeCount != 0) ) { //Allocate a 32k buffer.
C H A P T E R 2 Working with Nodes } // PrintNodeName Finding a Node The sample code in Listing 2-2 (page 27) demonstrates how to find the node for a specific pathname. The sample code opens an Open Directory session and gets an Open Directory reference. Then it calls its own FindNodes routine and passes to it the pathname for the node that is to be found (/NetInfo/root).
C H A P T E R 2 Working with Nodes dirStatus = dsFindDirNodes( gDirRef, dataBuffer, nodeName, eDSContains, &bufferCount, &context ); if ( dirStatus == eDSNoErr ) { for ( index = 1; index <= bufferCount; index++ ) { dirStatus = dsGetDirNodeName( gDirRef, dataBuffer, index, &nodeName ); if ( dirStatus == eDSNoErr ) { printf( "#%4ld ", index ); PrintNodeName( nodeName ); //Deallocate the nodes.
C H A P T E R 2 Working with Nodes if ( dirStatus == eDSNoErr ) { dirStatus = MyOpenDirNode( &nodeRef ); if ( dirStatus == eDSNoErr ) { dsCloseDirNode( nodeRef ); } } if ( gDirRef != NULL ) { dirStatus = dsCloseDirService( gDirRef ); } } long MyOpenDirNode ( tDirNodeReference *outNodeRef ) { long dirStatus = eDSNoErr; char nodeName[ 256 ] = "\0"; tDataListPtr nodePath = NULL; printf( "Open Node : " ); fflush( stdout ); scanf( "%s", nodeName ); printf( "Opening: %s.
C H A P T E R 2 Working with Nodes If the authentication methods that an authentication authority implements are known, the authentication authority may be used to deduce those authentication methods that are available for a user. Note, however, that it is possible to disable hash storage on a per-user basis, which has the effect of disabling some authentication methods that would otherwise be available.
C H A P T E R 2 Working with Nodes ::memcpy(&(anAuthDataBuf->fBufferData[aCurLength]), &aTempLength, sizeof(long)); aCurLength += sizeof(long); ::memcpy(&(anAuthDataBuf->fBufferData[aCurLength]), inUserPassword, aTempLength); aCurLength += aTempLength; anAuthBuff->fBufferLength = aDataBufSize; aDirErr = dsDoDirNodeAuth(inDirNodeRef, anAuthType2Use, true, anAuthDataBuf, aAuthRespBuf, &aContinueData); switch(aDirErr) { case eDSNoErr: aResult = true; break; default: // If any other error, assume the name or
C H A P T E R 2 Working with Nodes 32 Authenticating a User to a Node 2007-01-08 | © 2007 Apple Inc. All Rights Reserved.
C H A P T E R 3 Working with Records Using records is an essential part of using Open Directory. This chapter covers basic examples of how to interact with records. Listing Records The sample code in Listing 3-1 (page 34) demonstrates how to list all records in a node. The sample code opens an Open Directory session and gets an Open Directory reference. Then it calls its MyOpenDirNode routine and passes to it the address of the node reference (nodeRef) that it has allocated.
C H A P T E R 3 Working with Records When the GetRecordList routine returns, the sample code in Listing 3-1 calls dsCloseDirNode to close the node that it opened in order to get the record list.
C H A P T E R 3 Working with Records dirStatus = dsGetRecordList( nodeRef, dataBuffer, &recNames, &recTypes, &attrTypes, false, &recCount, &context ); for ( i = 1; i <= recCount; i++ ) { dirStatus = dsGetRecordEntry( nodeRef, dataBuffer, i, &attrListRef, &pRecEntry ); for ( j = 1; j <= pRecEntry->fRecordAttributeCount; j++ ) { dirStatus = dsGetAttributeEntry( nodeRef, dataBuffer, attrListRef, j, &valueRef, &pAttrEntry ); for ( k = 1; k <= pAttrEntry->fAttributeValueCount; k++ ) { dirStatus = dsGetAttribu
C H A P T E R 3 Working with Records The sample code then calls its GetRecInfo routine and passes to it the node reference (nodeRef) obtained by calling its MyOpenDirNode routine. The GetRecInfo routine calls dsDataNodeAllocateString to allocate two data nodes: one named recName allocated using the string “admin” and one named recType using the constant kDSStdRecordTypeGroups. Then the GetRecInfo routine calls dsOpenRecord to open the record whose name and record type match recName and recType.
C H A P T E R 3 Working with Records if ( dirStatus == eDSNoErr ) { attrType = dsDataNodeAllocateString(gDirRef, kDS1AttrPrimaryGroupID ); if ( attrType != NULL ) { dirStatus = dsGetRecordAttributeInfo(recRef, attrType, &pAttrInfo ); if ( pAttrInfo != NULL ) { dirStatus = dsDeallocAttributeEntry( gDirRef, pAttrInfo ); pAttrInfo = NULL; } dirStatus = dsDataNodeDeAllocate( gDirRef, attrType ); attrType = NULL; } } dirStatus = dsDataNodeDeAllocate( gDirRef, recType ); recType = NULL; } dirStatus = dsDataNod
C H A P T E R 3 Working with Records Listing 3-3 Setting the name of a record void main ( ) { long dirStatus = eDSNoErr; tDirNodeReference nodeRef = NULL; dirStatus = dsOpenDirService( &gDirRef ); if ( dirStatus == eDSNoErr ) { dirStatus = MyOpenDirNode( &nodeRef ); if ( dirStatus == eDSNoErr ) { SetRecordName( nodeRef ); dsCloseDirNode( nodeRef ); } } if ( gDirRef != NULL ) { dirStatus = dsCloseDirService( gDirRef ); } } void SetRecordName ( const tDirNodeReference nodeRef ) { long dirStatus = eDSNoEr
C H A P T E R 3 Working with Records Note that for this example to work, it would have to be run by a root process on the local NetInfo domain, or by a user process that has called dsDoDirNodeAuth with the inDirNodeAuthOnlyFlag parameter set to FALSE to get permission to make this change. Creating a Record and Adding an Attribute The sample code in Listing 3-4 demonstrates how to create a record, open it, and add an attribute to it.
C H A P T E R 3 Working with Records } } void CreateRecord ( const tDirNodeReference inDirNodeRef ) { long dirStatus = eDSNoErr; tDataNodePtr recName = NULL; tDataNodePtr recType = NULL; tDataNodePtr attrName = NULL; tDataNodePtr attrValue = NULL; tRecordReference recRef = NULL; recName = dsDataNodeAllocateString( gDirRef, "NewUserRecordName" ); if ( recName != NULL ) { recType = dsDataNodeAllocateString( gDirRef, kDSStdRecordTypeUsers ); if ( recType != NULL ) { dirStatus = dsCreateRecordAndOpen( inDirN
C H A P T E R 3 Working with Records Deleting a Record The sample code in Listing 3-5 demonstrates how to delete a record. The sample code opens an Open Directory session and gets an Open Directory reference. Then it calls its MyOpenDirNode routine and passes to it the address of the node reference (nodeRef) that it has allocated. The MyOpenDirNode routine is described in the section “Opening and Closing a Node” (page 28).
C H A P T E R 3 Working with Records dirStatus = dsOpenRecord( nodeRef, recType, recName, if ( dirStatus == eDSNoErr ) { dirStatus = dsDeleteRecord( recRef ); if (dirStatus != eDSNoErr) { // The record was not deleted, so close it.
R E V I S I O N H I S T O R Y Document Revision History This table describes the changes to Open Directory Programming Guide. Date Notes 2007-01-08 Fixed code listing in Working With Records. 2006-04-04 Moved reference documentation to become a separate document. 2005-04-29 Updated for Mac OS X v10.4. Changed "Rendezvous" to "Bonjour." Changed title from "Open Directory." 43 2007-01-08 | © 2007 Apple Inc. All Rights Reserved.
R E V I S I O N H I S T O R Y Document Revision History 44 2007-01-08 | © 2007 Apple Inc. All Rights Reserved.