Add even more of the source

This should be about everything needed to build so far?
This commit is contained in:
Darren VanBuren 2017-03-07 17:14:16 -08:00
parent af3619d4fa
commit 849723c9cf
547 changed files with 149239 additions and 0 deletions

View file

@ -0,0 +1,646 @@
/*
*
* Copyright (c) 1999-2005 Apple Computer, Inc. All Rights Reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*
*/
/*
File: DSAccessChecker.cpp
Contains: Class definition for access checking via Open Directory
Created By: Dan Sinema
Created: Jan 14, 2005
*/
/*
* Directory Service code added by Dan Sinema
*
* Jan 14, 2005 - Cleaned up code and added more comments.
* Nov 8, 2004 - Finsihed final code. Added group support.
*
*/
// ANSI / POSIX Headers
#include <grp.h>
#include <membership.h>
#include <pwd.h>
#include <signal.h>
#include <unistd.h>
// STL Headers
#include <cstdio>
#include <cstdlib>
#include <cstring>
// Project Headers
#include "SafeStdLib.h"
#include "StrPtrLen.h"
#include "StringParser.h"
#include "ResizeableStringFormatter.h"
#include "DSAccessChecker.h"
#include "DSDataList.h"
#include "QTAccessFile.h"
#define DEBUG_DSACCESS 0
#define debug_printf if (DEBUG_DSACCESS) ::qtss_printf
#include <AvailabilityMacros.h>
#ifdef AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER
#if OSX_OD_API
#define OD_API 1
#define DS_API 0
#else
#define OD_API 0
#define DS_API 1
#endif
#else
#define OD_API 0
#define DS_API 1
#endif
// Framework Headers
#if DS_API
#include <DirectoryService/DirectoryService.h>
using namespace DirectoryServices;
#endif
#if OD_API
#include <OpenDirectory/OpenDirectory.h>
#endif
#if __LP64__
#define ds_API_PTR UInt32*
#else
#define ds_API_PTR long unsigned int*
#endif
#pragma mark DSAccessChecker class globals
const char* DSAccessChecker::kDefaultAccessFileName = "qtaccess";
#pragma mark DSAccessChecker class implementation
#if DS_API
// Find a list of records that match the given criteria.
static SInt32 _GetRecordList(
tDirReference inDSRef,
const char *inDomain,
const char *inRecName,
const char *inRecType,
tDataList *inAttrType,
tDirNodeReference *outNodeRef,
tDataBuffer **outDataBuff,
UInt32 *outRecCount )
{
SInt32 status = eDSNoErr;
tDataBuffer *pDataBuff = NULL;
tDirNodeReference nodeRef = 0;
tContextData context = NULL;
UInt32 nodeCount = 0;
tDataList *nodeName = NULL;
UInt32 recCount = 0;
*outNodeRef = 0;
*outDataBuff = NULL;
*outRecCount = 0;
pDataBuff = ::dsDataBufferAllocate( inDSRef, 4096 );
if (pDataBuff == NULL)
{
// We need the buffer for locating the node for which the user object resides
debug_printf("QTSSODAuthModule: Unable to allocate buffer.\n");
return eDSAllocationFailed;
}
// This is the default action with no domain: use the Search node.
status = ::dsFindDirNodes( inDSRef, pDataBuff, NULL, eDSSearchNodeName, (ds_API_PTR) &nodeCount, &context );
if ( context != NULL )
{
::dsReleaseContinueData( inDSRef, context );
context = NULL;
}
// Check for failure of the dsFindDirNodes
// Node count less than 1 means no node found...doh!
if ( nodeCount < 1 )
{
status = eDSNodeNotFound;
}
if ( status != eDSNoErr )
{
goto cleanupBadGetRecordList;
}
// Extract the name of the found node.
status = ::dsGetDirNodeName( inDSRef, pDataBuff, 1, &nodeName );
if (status == eDSNoErr)
{
// Open the node so we can do the DS magic
status = ::dsOpenDirNode( inDSRef, nodeName, &nodeRef );
::dsDataListDeallocate( inDSRef, nodeName );
std::free( nodeName );
nodeName = NULL;
}
if (status != eDSNoErr)
{
// Bail if we cannot open the node.
debug_printf("QTSSODAuthModule: Could not open node - error: %"_S32BITARG_"\n", status);
}
else
{
// Specify what we are looking for...
// pRecName: the passed name of the record
// pRecType: the passed name of the record type
// pAttrType: attributes to return to the caller
DSDataList recName( inDSRef, inRecName );
DSDataList recType( inDSRef, inRecType );
recCount = 1;
// Find the record that matchs the above criteria
status = ::dsGetRecordList( nodeRef, pDataBuff, recName, eDSExact, recType, inAttrType, 0, (ds_API_PTR)&recCount, &context );
if ( context != NULL )
{
::dsReleaseContinueData( inDSRef, context );
context = NULL;
}
if ( recCount == 0 )
{
status = eDSRecordNotFound;
debug_printf("QTSSODAuthModule: No records found.\n");
}
else if ( status != eDSNoErr )
{
debug_printf("QTSSODAuthModule: No records found - error: %"_S32BITARG_"\n", status);
}
}
if ( status == eDSNoErr )
{
*outNodeRef = nodeRef;
*outDataBuff = pDataBuff;
*outRecCount = recCount;
return eDSNoErr;
}
cleanupBadGetRecordList:
if ( nodeRef != 0 )
{
::dsCloseDirNode( nodeRef );
}
// This variable is guaranteed to be valid because the function would
// have returned if it was bad.
::dsDataBufferDeAllocate( inDSRef, pDataBuff );
return status;
}
static SInt32 _FindRecordNode(
tDirReference inDSRef,
const char *inDomain,
const char *inRecName,
const char *inRecType,
tDataList *outHomeNodeName )
{
tDataBuffer *pRecBuff = NULL;
tDirNodeReference nodeRef = 0;
SInt32 status = eDSNoErr;
UInt32 attrIndex = 0;
UInt32 recCount = 0;
tRecordEntry *pRecEntry = NULL;
tAttributeListRef attrListRef = 0;
if ( outHomeNodeName == NULL )
{
return eDSNullDataList;
}
std::memset( outHomeNodeName, 0, sizeof( *outHomeNodeName) );
// A Username and Password is needed, if either one is not present then bail!
if ( inRecName == NULL )
{
return eDSInvalidRecordName;
}
if ( inRecType == NULL )
{
return eDSInvalidRecordType;
}
status = ::_GetRecordList( inDSRef, inDomain, inRecName, inRecType,
DSDataList (inDSRef, kDSNAttrMetaNodeLocation),
&nodeRef, &pRecBuff, &recCount );
if ( status != eDSNoErr )
{
return status;
}
// Get the record entry out of the list, there should only be one record!
status = ::dsGetRecordEntry( nodeRef, pRecBuff, 1, &attrListRef, &pRecEntry );
if ( status != eDSNoErr )
{
// These variables are guaranteed to be valid because the function would
// have returned if they were bad.
::dsCloseDirNode( nodeRef );
::dsDataBufferDeAllocate( inDSRef, pRecBuff );
return status;
}
// Now loop through attributes of the entry...looking for kDSNAttrMetaNodeLocation and kDSNAttrRecordName
for ( attrIndex = 1; (attrIndex <= pRecEntry->fRecordAttributeCount) && (status == eDSNoErr); attrIndex++ )
{
tAttributeEntryPtr pAttrEntry = NULL;
tAttributeValueListRef valueRef = 0;
status = ::dsGetAttributeEntry( nodeRef, pRecBuff, attrListRef, attrIndex, &valueRef, &pAttrEntry );
if ( ( status != eDSNoErr ) || ( pAttrEntry == NULL ) )
continue;
// Test for kDSNAttrMetaNodeLocation
if ( std::strcmp( pAttrEntry->fAttributeSignature.fBufferData, kDSNAttrMetaNodeLocation ) == 0 )
{
tAttributeValueEntry *pValueEntry = NULL;
// If it matches then get the value of the attribute
status = ::dsGetAttributeValue( nodeRef, pRecBuff, 1, valueRef, &pValueEntry );
if ( ( status == eDSNoErr ) && ( pValueEntry != NULL ) )
{
// Store the node location in outHomeNodeName
if ( outHomeNodeName->fDataNodeCount != 0 )
{
debug_printf("QTSSODAuthModule: Multiple user locations found!?\n");
}
else
{
status = ::dsBuildListFromPathAlloc( inDSRef, outHomeNodeName, pValueEntry->fAttributeValueData.fBufferData, "/" );
::dsDeallocAttributeValueEntry( inDSRef, pValueEntry );
}
}
}
::dsDeallocAttributeEntry( inDSRef, pAttrEntry );
::dsCloseAttributeValueList( valueRef );
}
// Cleanup dsGetRecordEntry() return values.
::dsCloseAttributeList( attrListRef );
::dsDeallocRecordEntry( inDSRef, pRecEntry );
::dsCloseDirNode( nodeRef );
::dsDataBufferDeAllocate( inDSRef, pRecBuff );
return status;
}
#endif
#pragma mark -
#pragma mark "Public Methods"
// Now the class proper.
DSAccessChecker::DSAccessChecker()
{
}
DSAccessChecker::~DSAccessChecker()
{
#if DEBUG
debug_printf("QTSSODAuthModule: Access checker object destroyed.\n");
#endif
}
#if 0 //OD_API notes
/*
This is Leopard or later code so some check before using OD based code is needed.
Implement this api for digest auth.
*/
#include <OpenDirectory/OpenDirectoryPriv.h>
/System/Library/PrivateFrameworks/OpenDirectory.framework/Frameworks/CFOpenDirectory.framework/CFOpenDirectory
CFErrorRef outError = NULL;
ODNodeRef cfNode = ODNodeCreateWithNodeType( kCFAllocatorDefault, kODSessionDefault, kODTypeAuthenticationSearchNode, NULL );
if (cfNode)
{
ODRecordRef cfUserRecord = ODNodeCopyRecord( kCFAllocatorDefault, cfNode, CFSTR("username"), NULL );
if (cfUserRecord != NULL)
{
CFArrayRef authItems = CFArrayCreate.... ( username, server challenge, client response, http method);
// for DIGEST_MD5
if (ODRecordVerifyPasswordExtended( cfUserRecord, CFSTR(kDSStdAuthDIGEST_MD5), authItems, NULL, NULL, &outError ))
{
}
// this for password
if (ODRecordVerifyPassword( cfUserRecord, CFSTR("password") ) )
{
}
CFRelease( cfUserRecord );
CFRelease( autItems );
}
CFRelease( cfNode );
}
// kDSStdAuthDIGEST_MD5
* user name in UTF8 encoding,
* server challenge in UTF8 encoding,
* client response data,
* HTTP method in UTF8 encoding
}
}
#endif
#if OD_API
Bool16 DSAccessChecker::CheckPassword(const char* inUsername, const char* inPassword)
{
Bool16 checkedResult = false;
CFErrorRef outError = NULL;
debug_printf("DSAccessChecker::CheckPassword userName=%s password=%s\n", inUsername,inPassword);
ODNodeRef cfNodeRef= ODNodeCreateWithNodeType( kCFAllocatorDefault, kODSessionDefault, kODTypeAuthenticationSearchNode, NULL );
//static ODRecordRef _ODNodeCopyRecord( ODNodeRef inNodeRef, CFStringRef inRecordType, CFStringRef inRecordName, CFArrayRef inAttributes, CFErrorRef *outError );
CFStringRef cfPassword = CFStringCreateWithCString(kCFAllocatorDefault, inPassword, kCFStringEncodingUTF8);
CFStringRef cfUsername = CFStringCreateWithCString(kCFAllocatorDefault, inUsername, kCFStringEncodingUTF8);
CFTypeRef vals[] = { CFSTR(kDSAttributesStandardAll) };
CFArrayRef reqAttrs = CFArrayCreate(NULL, vals,1, &kCFTypeArrayCallBacks);
ODRecordRef cfUserRecord = ODNodeCopyRecord(cfNodeRef, CFSTR(kDSStdRecordTypeUsers), cfUsername, reqAttrs, &outError );
if (cfNodeRef && cfUserRecord && cfPassword && cfUsername)
{
// this for password
if ( ODRecordVerifyPassword( cfUserRecord, cfPassword , NULL ) )
{ checkedResult = true;
debug_printf("DSAccessChecker::CheckPassword ODRecordVerifyPassword user is authenticated\n");
}
else
{ debug_printf("DSAccessChecker::CheckPassword ODRecordVerifyPassword user failed to authenticate\n");
}
}
if (reqAttrs) CFRelease( reqAttrs );
if (cfUserRecord) CFRelease( cfUserRecord );
if (cfPassword) CFRelease( cfPassword );
if (cfUsername) CFRelease( cfUsername );
if (cfNodeRef) CFRelease( cfNodeRef );
return checkedResult;
}
Bool16 DSAccessChecker::CheckDigest(const char* inUsername, const char* inServerChallenge, const char* inClientResponse, const char* inMethod)
{
Bool16 checkedResult = false;
CFErrorRef outError = NULL;
CFArrayRef outItems = NULL;
if (NULL == inUsername || NULL == inServerChallenge || NULL == inClientResponse )
return false;
ResizeableStringFormatter challengeString;
challengeString.Put((char*) inServerChallenge);
challengeString.PutTerminator();
char* challengeCString= challengeString.GetBufPtr();
ResizeableStringFormatter responseString;
responseString.Put( (char*)inClientResponse);
responseString.PutTerminator();
char* responseCString= responseString.GetBufPtr();
ODNodeRef cfNode = ODNodeCreateWithNodeType( kCFAllocatorDefault, kODSessionDefault, kODTypeAuthenticationSearchNode, NULL );
debug_printf("DSAccessChecker::CheckDigest \nuserName=[%s] \nchallenge=[%s] \nresponse=[%s] \nmethod=[%s]\n", inUsername,challengeCString, responseCString,inMethod);
CFTypeRef vals[] = { CFSTR(kDSAttributesStandardAll) };
CFArrayRef reqAttrs = CFArrayCreate(NULL, vals,1, &kCFTypeArrayCallBacks);
CFStringRef cfUsername = CFStringCreateWithCString(kCFAllocatorDefault, inUsername, kCFStringEncodingUTF8);
ODRecordRef cfUserRecord = ODNodeCopyRecord(cfNode, CFSTR(kDSStdRecordTypeUsers), cfUsername, reqAttrs, &outError );
CFRelease( cfUsername );
cfUsername = NULL;
enum { kNumAuthValues=4 };
CFStringRef cfStringArray[kNumAuthValues];
cfStringArray[0] = CFStringCreateWithCString(kCFAllocatorDefault, inUsername, kCFStringEncodingUTF8);
cfStringArray[1] = CFStringCreateWithCString(kCFAllocatorDefault, challengeCString, kCFStringEncodingUTF8);
cfStringArray[2] = CFStringCreateWithCString(kCFAllocatorDefault, responseCString, kCFStringEncodingUTF8);
cfStringArray[3] = CFStringCreateWithCString(kCFAllocatorDefault, inMethod, kCFStringEncodingUTF8);
CFArrayRef cfAuthItems = CFArrayCreate(kCFAllocatorDefault, (const void **) &cfStringArray,kNumAuthValues, &kCFTypeArrayCallBacks);
if (cfNode && cfUserRecord && cfAuthItems)
{
debug_printf("DSAccessChecker::CheckDigest call ODRecordVerifyPasswordExtended\n");
// for DIGEST_MD5
if (ODRecordVerifyPasswordExtended( cfUserRecord, CFSTR(kDSStdAuthDIGEST_MD5), cfAuthItems, &outItems, NULL, &outError ))
{
checkedResult = true;
debug_printf("DSAccessChecker::CheckDigest SUCCESS ODRecordVerifyPasswordExtended response=%d\n",outError);
}
else
{ debug_printf("DSAccessChecker::CheckDigest ODRecordVerifyPasswordExtended response=%d\n", outError ? CFErrorGetCode(outError) : -1);
}
}
for (int i = 0; i < kNumAuthValues; i++)
CFRelease(cfStringArray[i]);
if (reqAttrs) CFRelease( reqAttrs );
if (cfAuthItems) CFRelease( cfAuthItems );
if (cfUserRecord) CFRelease( cfUserRecord );
if (cfNode) CFRelease( cfNode );
if (outItems) CFRelease( outItems );
if (outError) CFRelease( outError );
return checkedResult;
}
#endif
#if DS_API
Bool16 DSAccessChecker::CheckPassword(const char* inUsername, const char* inPassword)
{
tDirReference dsRef = 0;
tDataList userNode = { 0, NULL };
tDirNodeReference nodeRef = 0;
SInt32 status = eDSNoErr;
// A Username and Password is needed, if either one is not present then bail!
if ( inUsername == NULL )
{
debug_printf("QTSSODAuthModule: Username required.\n");
return false;
}
if ( inPassword == NULL )
{
debug_printf("QTSSODAuthModule: Password required.\n");
return false;
}
status = ::dsOpenDirService( &dsRef );
if ( status != eDSNoErr )
{
// Some DS error, tell the admin what the error is and bail.
// Error can be found in DirectoryService man page.
debug_printf("QTSSODAuthModule: Could not open Directory Services - error: %"_S32BITARG_"", status);
return false;
}
status = _FindRecordNode( dsRef, NULL, inUsername, kDSStdRecordTypeUsers, &userNode );
if ( status != eDSNoErr )
{
debug_printf("QTSSODAuthModule: Could not find user node.\n");
return false;
}
// Now that we know the node location of the user object, lets open that node.
status = ::dsOpenDirNode( dsRef, &userNode, &nodeRef );
::dsDataListDeallocate( dsRef, &userNode );
if ( status == eDSNoErr )
{
UInt32 uiLen = std::strlen( inUsername );
tDataNode *pAuthType = ::dsDataNodeAllocateString( dsRef, kDSStdAuthNodeNativeClearTextOK );
tDataBuffer *pStepBuff = ::dsDataBufferAllocate( dsRef, 128 );
tDataBuffer *pAuthBuff = ::dsDataBufferAllocate( dsRef, ( sizeof( UInt32 ) + sizeof( UInt32 ) + uiLen + std::strlen( inPassword ) ) );
if ( ( pStepBuff != NULL ) && ( pAuthType != NULL ) && ( pAuthBuff != NULL ) )
{
UInt32 uiCurr = 0;
// Copy username (that is passed into this function) into buffer for dsDoDirNodeAuth()
std::memcpy( &(pAuthBuff->fBufferData[ uiCurr ]), &uiLen, sizeof( UInt32 ) );
uiCurr += sizeof( UInt32 );
std::memcpy( &(pAuthBuff->fBufferData[ uiCurr ]), inUsername, uiLen );
uiCurr += uiLen;
// Copy password into a buffer for dsDoDirNodeAuth()
uiLen = std::strlen( inPassword );
std::memcpy( &(pAuthBuff->fBufferData[ uiCurr ]), &uiLen, sizeof( UInt32 ) );
uiCurr += sizeof( UInt32 );
std::memcpy( &(pAuthBuff->fBufferData[ uiCurr ]), inPassword, uiLen );
uiCurr += uiLen;
pAuthBuff->fBufferLength = uiCurr;
// Perform the authentication
status = ::dsDoDirNodeAuth( nodeRef, pAuthType, 1, pAuthBuff, pStepBuff, NULL );
// Since the buffer held a name & password, clear it immediately.
std::memset( pAuthBuff, 0, pAuthBuff->fBufferSize );
}
// Free the auth buffer.
if ( pAuthBuff != NULL )
{
::dsDataBufferDeAllocate( dsRef, pAuthBuff );
}
// Free the ignored step buffer.
if ( pStepBuff != NULL )
{
::dsDataBufferDeAllocate( dsRef, pStepBuff );
}
// Free the auth string.
if ( pAuthType != NULL )
{
::dsDataNodeDeAllocate( dsRef, pAuthType );
}
::dsCloseDirNode( nodeRef );
}
::dsCloseDirService( dsRef );
if( status == eDSNoErr )
{
debug_printf("QTSSODAuthModule: Authentication is good.\n");
return true;
}
// For admins running QTSS in debug
debug_printf("QTSSODAuthModule: OD returned %"_S32BITARG_" status.\n", status);
debug_printf("QTSSODAuthModule: Authentication failed.\n");
// If the Authentication failed then return false, which boots the user...
return false;
}
Bool16 DSAccessChecker::CheckDigest(const char* inUsername, const char* inServerChallenge, const char* inClientResponse, const char* inMethod)
{
return false;
}
#endif
#pragma mark -
#pragma mark "Protected Methods"
Bool16 DSAccessChecker::CheckGroupMembership(const char* inUsername, const char* inGroupName)
{
// In Tiger, group membership is painfully simple: we ask memberd for it!
struct passwd *user = NULL;
struct group *group = NULL;
uuid_t userID;
uuid_t groupID;
int isMember = 0;
// Look up the user using the POSIX APIs: only care about the UID.
user = getpwnam(inUsername);
endpwent();
if ( user == NULL )
return false;
uuid_clear(userID);
if ( mbr_uid_to_uuid(user->pw_uid, userID) )
return false;
// Look up the group using the POSIX APIs: only care about the GID.
group = getgrnam(inGroupName);
endgrent();
if ( group == NULL )
return false;
uuid_clear(groupID);
if ( mbr_gid_to_uuid(group->gr_gid, groupID) )
return false;
// mbr_check_membership() returns 0 on success and error code on failure.
if ( mbr_check_membership(userID, groupID, &isMember) )
return false;
return (bool)isMember;
}

View file

@ -0,0 +1,70 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*
*/
/*
File: DSAccessChecker.h
Contains: Class definition for access checking via Open Directory
Created By: Dan Sinema
Created: Jan 14, 2005
*/
#ifndef _QTSSACCESSCHECKER_H_
#define _QTSSACCESSCHECKER_H_
// STL Headers
#include <cstdio> // for struct FILE
#include <string>
#include "QTAccessFile.h"
class DSAccessChecker
{
/*
Access check logic:
If "modAccess_enabled" == "enabled,
*/
public:
static const char* kDefaultAccessFileName;
DSAccessChecker();
virtual ~DSAccessChecker();
Bool16 CheckPassword(const char* inUsername, const char* inPassword);
Bool16 CheckDigest(const char* inUsername, const char* inServerChallenge, const char* inClientResponse, const char* inMethod);
protected:
Bool16 CheckGroupMembership(const char* inUsername, const char* inGroupName);
};
#endif //_QTSSACCESSCHECKER_H_

View file

@ -0,0 +1,91 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*
*/
/*
File: CDirService.h
Contains: Implements DSException.
Created By: chris jalbert
Created: 26 July 2000
*/
// This file is only meaningful if exceptions are enabled.
#if USE_EXCEPTIONS
// STL and Std C++ Library Headers
#include <cstdlib> // for abs()
#include <stdexcept> // for standard exceptions
// Project Headers
#include "CDirService.h"
using namespace DirectoryServices ;
using namespace std ;
// ----------------------------------------------------------------------------
// ¥ CDirService Class Globals
// These private typedefs, globals, and functions are not declared statically
// in the class definition because I want to hide the implementation details
// and reduce unrelated dependencies in the class header.
// ----------------------------------------------------------------------------
static const char * const _DSErr = "DirectoryService error: " ;
/*
* Convert an UInt32 to ASCII for printf purposes, returning
* a pointer to the first character of the string representation.
* Borrowed from vfprintf.c.
*/
static char *_ltoa (
SInt32 val,
char *endp)
{
register char *cp = endp ;
register SInt32 sval = std::abs (val) ;
// Terminate the string.
*--cp = '\0' ;
do {
*--cp = '0' + (sval % 10) ;
sval /= 10 ;
} while (sval != 0) ;
// Handle signed values.
if (val < 0)
*--cp = '-' ;
return cp ;
}
DSException::DSException (tDirStatus err)
: inherited (string (_DSErr) + _ltoa (err, &mErrStr[sizeof (mErrStr)])),
mErr (err)
{
}
#endif /* USE_EXCEPTIONS */

View file

@ -0,0 +1,87 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*
*/
/*
File: CDirService.h
Contains: Defines DSException.
Created By: chris jalbert
Created: 26 July 2000
*/
#ifndef _CDirService_h
#define _CDirService_h
// Framework Headers
#include <DirectoryService/DirServicesTypes.h>
namespace DirectoryServices {
const tDirReference kDSDirRefNull = 0 ;
// This file is only meaningful if exceptions are enabled.
#if __EXCEPTIONS
// STL and Std C++ Library Headers
#include <stdexcept> // for standard exceptions
//-----------------------------------------------------------------------------
// ¥ DSException - exception class that wraps a tDirStatus result code.
//-----------------------------------------------------------------------------
class DSException : public std::runtime_error {
public:
typedef std::runtime_error inherited ;
DSException ( tDirStatus err ) ;
tDirStatus status ( void ) const { return mErr ; }
private:
tDirStatus mErr ;
char mErrStr [12] ;
} ;
#define throw_ds_error(err) throw DSException(err)
#else /* __EXCEPTIONS */
//-----------------------------------------------------------------------------
// ¥ DSException - with exceptions disabled, this is dummy code.
//-----------------------------------------------------------------------------
class DSException {
public:
DSException ( tDirStatus ) { }
} ;
// Define away the throw spec.
#define throw(spec)
#define throw_ds_error(err)
#endif /* __EXCEPTIONS */
} // namespace DirectoryServices
#endif /* _CDirService_h */

View file

@ -0,0 +1,94 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*
*/
/*
File: DSBuffer.cpp
Contains: Class implementation for Open Directory buffers
(wraps tDataBufferPtr)
Created By: chris jalbert
Created: 28 November 2000
*/
// ANSI / POSIX headers
// STL and Std C++ Library Headers
#include <stdexcept> // for standard exceptions
// Framework Headers
#include <DirectoryService/DirServices.h>
// Project Headers
#include "DSBuffer.h"
using namespace DirectoryServices ;
// ----------------------------------------------------------------------------
// ¥ DSBuffer Class Globals
// These private typedefs, globals, and functions are not declared statically
// in the class definition because I want to hide the implementation details
// and reduce unrelated dependencies in the class header.
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// ¥ DSBuffer Protected Instance Methods
// ----------------------------------------------------------------------------
#pragma mark **** DSBuffer Protected Instance Methods ****
// ----------------------------------------------------------------------------
// ¥ÊGrow
// All memory management (even in the c'tors) are handled in this method.
// An inNewSize value of 0 implies the use of the default buffer size!
// To leave the buffer alone, call with an argument value of 1.
// ----------------------------------------------------------------------------
tDataBufferPtr DSBuffer::grow ( size_t inNewSize )
{
if (!inNewSize)
inNewSize = kDefaultSize ;
if (mBuffer && (inNewSize <= mBuffer->fBufferSize))
return mBuffer ;
register size_t ulTemp = 16 ;
if (inNewSize == kDefaultSize)
ulTemp = inNewSize ;
else
for ( ; ulTemp < inNewSize ; ulTemp <<= 1) ;
register tDataBufferPtr bufNew = ::dsDataBufferAllocate (mDirRef, ulTemp) ;
if (!bufNew)
throw_ds_error (eDSAllocationFailed) ;
if (mBuffer && (ulTemp = mBuffer->fBufferLength))
std::memcpy (bufNew->fBufferData, mBuffer->fBufferData, ulTemp) ;
else
ulTemp = 0 ;
bufNew->fBufferLength = ulTemp ;
::dsDataBufferDeAllocate (mDirRef, mBuffer) ;
return (mBuffer = bufNew) ;
}

View file

@ -0,0 +1,125 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*
*/
/*
File: DSBuffer.h
Contains: Class definition for Open Directory buffers
(wraps tDataBufferPtr)
Created By: chris jalbert
Created: 26 July 2000
*/
#ifndef _DSBuffer_h
#define _DSBuffer_h
// Framework Headers
#include <DirectoryService/DirServicesTypes.h>
#include <DirectoryService/DirServicesUtils.h>
// Project Headers
#include "CDirService.h"
namespace DirectoryServices {
//-----------------------------------------------------------------------------
// ¥ DSBuffer - a wrapper for tDataBufferPtr.
// This should be considered a private class, primarily used by DSNode.
// All methods except Grow() are inlined for performance reasons (sorry).
//-----------------------------------------------------------------------------
class DSBuffer
{
public:
/**** Typedefs, enums, and constants. ****/
enum { kDefaultSize = 128 } ;
public:
/**** Instance methods. ****/
// ctor and dtor.
DSBuffer ( tDirReference inDirRef = 0,
size_t inBufferSize = kDefaultSize ) throw (DSException)
: mDirRef (inDirRef), mBuffer (0)
{ if (!grow (inBufferSize)) throw_ds_error (eDSAllocationFailed) ; }
~DSBuffer ( void ) throw ()
{ if (mBuffer) ::dsDataBufferDeAllocate (mDirRef, mBuffer) ; }
// Inline accessors.
size_t capacity ( void ) const throw ()
{ return (size_t) mBuffer->fBufferSize ; }
size_t size ( void ) const throw ()
{ return (size_t) mBuffer->fBufferSize ; }
size_t length ( void ) const throw ()
{ return (size_t) mBuffer->fBufferLength ; }
const char *c_str ( void ) const throw ()
{ return (const char *) mBuffer->fBufferData ; }
const void *data ( void ) const throw ()
{ return (const void *) mBuffer->fBufferData ; }
// Inline setters.
void clear ( void ) throw ()
{ mBuffer->fBufferLength = 0 ; }
void resize ( size_t inLength ) throw (DSException)
{ if (inLength > mBuffer->fBufferSize)
throw_ds_error (eDSBufferTooSmall) ;
mBuffer->fBufferLength = inLength ; }
void set ( const char *inString ) throw (DSException)
{ clear () ; append (inString) ; }
void set ( const void *inData, size_t inLength ) throw (DSException)
{ clear () ; append (inData, inLength) ; }
void append ( const char *inString ) throw (DSException)
{ append ((const void *) inString, 1 + strlen (inString)) ; }
void append ( const void *inData, size_t inLength ) throw (DSException)
{ grow (mBuffer->fBufferLength + inLength) ;
char *cpBuf = mBuffer->fBufferData + mBuffer->fBufferLength ;
std::memcpy (cpBuf, inData, inLength) ;
mBuffer->fBufferLength += inLength ; }
// Casting operators.
tDataBufferPtr operator->() throw ()
{ return mBuffer ; }
operator tDataBufferPtr() const throw ()
{ return mBuffer ; }
operator const char*() const throw ()
{ return this->c_str () ; }
operator const void*() const throw ()
{ return this->data () ; }
protected:
/**** Instance methods accessible only to class and subclasses. ****/
tDataBufferPtr grow ( size_t inNewSize ) throw (DSException) ;
/**** Instance data. ****/
tDirReference mDirRef ;
tDataBufferPtr mBuffer ;
} ;
} // namespace DirectoryServices
#endif /* _DSBuffer_h */

View file

@ -0,0 +1,140 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*
*/
/*
File: DSDataList.h
Contains: Class definition for Open Directory data list
(wraps tDataListPtr)
Created By: chris jalbert
Created: 26 July 2000
*/
#ifndef _DSDataList_h
#define _DSDataList_h
// ANSI / POSIX Headers
#include <stdarg.h> // for varargs stuff
#include <string.h> // for memset()
// STL and Std C++ Library Headers
#include <memory> // for auto_ptr<>
// Framework Headers
#include <DirectoryService/DirServicesTypes.h>
#include <DirectoryService/DirServicesUtils.h>
// Project Headers
#include "DSDataNode.h"
namespace DirectoryServices {
//-----------------------------------------------------------------------------
// ¥ DSDataList - simple wrapper for tDataBufferPtr.
// This should be considered a private class, primarily used by DSNode.
// All methods are inlined for performance reasons (sorry).
// Logically, a tDataList is a collection of tDataNode's, so this
// implementation offers GetCount() and operator[](u_long) methods.
//-----------------------------------------------------------------------------
class DSDataList
{
public:
/**** Instance methods. ****/
// ctor and dtor.
/* Not used anywhere and conflicts with next ctor, which is more useful.
DSDataList ( tDirReference inDirRef,
const char *inString, ... ) throw (DSException)
: mDirRef (inDirRef)
{ va_list args ; va_start (args, inString) ;
std::memset (&mList, 0, sizeof (mList)) ;
tDirStatus nError = ::dsBuildListFromStringsAllocV (
inDirRef, &mList, inString, args) ;
va_end (args) ;
if (nError) throw_ds_error (nError) ; }
*/
DSDataList ( tDirReference inDirRef,
const char *inPath ) throw (DSException)
: mDirRef (inDirRef)
{ std::memset (&mList, 0, sizeof (mList)) ;
tDirStatus nError = ::dsBuildListFromPathAlloc (inDirRef, &mList, inPath, "/") ;
if (nError) throw_ds_error (nError) ; }
DSDataList ( const DSDataList& inOrg ) throw (DSException)
: mDirRef (inOrg.mDirRef)
{ tDataList *dlp = ::dsDataListCopyList (inOrg.mDirRef, &inOrg.mList) ;
if (!dlp) throw_ds_error (eDSAllocationFailed) ;
mList = *dlp ; std::free (dlp) ; }
// The following constructor changes the ownership of the list buffer!
DSDataList ( tDirReference inDirRef,
tDataListPtr inList = 0 ) throw (DSException)
: mDirRef (inDirRef)
{ if (inList) {
mList = *inList ; std::memset (inList, 0, sizeof (mList)) ;
} else std::memset (&mList, 0, sizeof (mList)) ; }
~DSDataList ( void ) throw ()
{ ::dsDataListDeallocate (mDirRef, &mList) ; }
// Inline accessors.
UInt32 count ( void ) const throw ()
{ return ::dsDataListGetNodeCount (&mList) ; }
size_t length ( void ) const throw ()
{ return (size_t) ::dsGetDataLength (&mList) ; }
// GetPath()'s return value will be freed when it goes out of scope.
// If it is important, COPY IT to another auto_ptr (which will
// properly invalidate the original).
std::auto_ptr<const char> path ( const char *inSep = "/" ) const
{ return std::auto_ptr<const char> (::dsGetPathFromList (mDirRef,
&mList, inSep)) ; }
// Casting operators.
operator tDataListPtr() throw ()
{ return &mList ; }
operator const tDataList*() const throw ()
{ return &mList ; }
DSDataNode* operator[] ( UInt32 inIndex ) const throw (DSException)
{ tDataNodePtr dnTemp ;
tDirStatus nError = ::dsDataListGetNodeAlloc (
mDirRef, &mList, inIndex, &dnTemp) ;
if (nError) throw_ds_error (nError) ;
return new DSDataNode (mDirRef, dnTemp) ; }
// Setters.
void append ( const char *inString ) throw (DSException)
{ tDirStatus nError = ::dsAppendStringToListAlloc (
mDirRef, &mList, inString) ;
if (nError) throw_ds_error (nError) ; }
protected:
/**** Instance data. ****/
tDirReference mDirRef ;
tDataList mList ;
} ;
} // namespace DirectoryServices
#endif /* _DSDataList_h */

View file

@ -0,0 +1,118 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*
*/
/*
File: DSDataNode.h
Contains: Class definition for Open Directory data node
(wraps tDataNodePtr)
Created By: chris jalbert
Created: 26 July 2000
*/
#ifndef _DSDataNode_h
#define _DSDataNode_h
// Framework Headers
#include <DirectoryService/DirServicesTypes.h>
#include <DirectoryService/DirServicesUtils.h>
// Project Headers
#include "CDirService.h"
namespace DirectoryServices {
//-----------------------------------------------------------------------------
// ¥ DSDataNode - simple wrapper for tDataBufferPtr.
// This should be considered a private class, primarily used by DSNode.
// All methods are inlined for performance reasons (sorry).
// tDataNode's are identical to tDataBuffer's in implementation, however,
// nodes are treated as opaque objects with DS accessor functions. As a
// result, DSDataNode is not a subclass of DSBuffer.
//-----------------------------------------------------------------------------
class DSDataNode
{
public:
/**** Instance methods. ****/
// ctor and dtor.
DSDataNode ( tDirReference inDirRef,
size_t inBufSize,
size_t inBufUsed,
const void *inData ) throw (DSException)
: mDirRef (inDirRef),
mNode (::dsDataNodeAllocateBlock (inDirRef,
(UInt32) inBufSize, (UInt32) inBufUsed,
(void *) inData))
{ if (!mNode) throw_ds_error (eDSAllocationFailed) ; }
DSDataNode ( tDirReference inDirRef,
const char *inString ) throw (DSException)
: mDirRef (inDirRef),
mNode (::dsDataNodeAllocateString (inDirRef, inString))
{ if (!mNode) throw_ds_error (eDSAllocationFailed) ; }
// Used by DSDataList
DSDataNode ( tDirReference inDirRef,
tDataNode *inNode ) throw (DSException)
: mDirRef (inDirRef), mNode (inNode)
{ if (!mNode) throw_ds_error (eDSAllocationFailed) ; }
// Something of a "copy" constructor
DSDataNode ( tDirReference inDirRef,
const tDataNode *inNode ) throw (DSException)
: mDirRef (inDirRef),
mNode (::dsDataNodeAllocateBlock (inDirRef,
inNode->fBufferSize, inNode->fBufferLength,
(void *) inNode->fBufferData))
{ if (!mNode) throw_ds_error (eDSAllocationFailed) ; }
~DSDataNode ( void ) throw ()
{ if (mNode) ::dsDataNodeDeAllocate (mDirRef, mNode) ; }
// Inline accessors.
size_t capacity ( void ) const throw ()
{ return (size_t) ::dsDataNodeGetSize (mNode) ; }
size_t size ( void ) const throw ()
{ return (size_t) ::dsDataNodeGetSize (mNode) ; }
size_t length ( void ) const throw ()
{ return (size_t) ::dsDataNodeGetLength (mNode) ; }
void resize ( size_t inLength ) throw (DSException)
{ tDirStatus nError = ::dsDataNodeSetLength (mNode, inLength) ;
if (nError) throw_ds_error (nError) ; }
// Casting operators.
operator tDataNodePtr() const throw ()
{ return mNode ; }
protected:
/**** Instance data. ****/
tDirReference mDirRef ;
tDataNodePtr mNode ;
} ;
} // namespace DirectoryServices
#endif /* _DSDataNode_h */

View file

@ -0,0 +1,528 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*
*/
/*
File: QTSSODSAuthModule.cpp
Contains: Implementation of QTSSDSAuthModule, a modified version of the AuthenticateRequestModule
is sample code.
*/
#include "QTSSDSAuthModule.h"
#include "../../defaultPaths.h"
#include "DSAccessChecker.h"
#include "StrPtrLen.h"
#include "QTSSModuleUtils.h"
#include "OSArrayObjectDeleter.h"
#include "SafeStdLib.h"
#include "QTSSMemoryDeleter.h"
#include "QTSS_Private.h"
#include "OS.h"
//#define SACL 1
#if OSX_SACL
extern "C"
{
#include <membershipPriv.h>
}
#include <membership.h>
#include <errno.h>
#endif
// ATTRIBUTES
// STATIC DATA
const UInt32 kBuffLen = 512;
#define MODPREFIX_ "modDSAuth_"
#define AUTHDEBUG 0
#define debug_printf if (AUTHDEBUG) qtss_printf
static QTSS_ModulePrefsObject sPrefs = NULL;
static QTSS_PrefsObject sServerPrefs = NULL;
static OSMutex* sAuthMutex = NULL;
static Bool16 sDefaultAuthenticationEnabled = true;
static Bool16 sAuthenticationEnabled = true;
static char* sDefaultAccessFileName = "qtaccess";
static char* sAccessFileName = NULL;
static Bool16 sAllowGuestDefaultEnabled = true;
static Bool16 sDefaultGuestEnabled = true;
// FUNCTION PROTOTYPES
static QTSS_Error QTSSDSAuthModuleDispatch(QTSS_Role inRole, QTSS_RoleParamPtr inParams);
static QTSS_Error Register();
static QTSS_Error Initialize(QTSS_Initialize_Params* inParams);
static QTSS_Error Shutdown();
static QTSS_Error RereadPrefs();
static QTSS_Error AuthenticateRTSPRequest(QTSS_RTSPAuth_Params* inParams);
static QTSS_Error Authorize(QTSS_StandardRTSP_Params* inParams);
static Bool16 AuthenticateRequest(QTSS_StandardRTSP_Params* inParams, const char* pathBuff, const char* movieRootDir, StrPtrLen* ioRealmName, Bool16* foundUserPtr);
static int check_sacl(const char *inUser);
#define kSACLNotAuthorized 0
#define kSACLAuthorized 1
#define kSACLUnknownUser 2
#define kSACLAnyUser 3
// FUNCTION IMPLEMENTATIONS
QTSS_Error QTSSDSAuthModule_Main(void* inPrivateArgs)
{
printf("QTSSDSAuthModule_Main\n");
#if OSX_SACL
printf("QTSSDSAuthModule_Main OSX_SACL\n");
#endif
#if OSX_OD_API
printf("QTSSDSAuthModule_Main OSX_OD_API\n");
#endif
return _stublibrary_main(inPrivateArgs, QTSSDSAuthModuleDispatch);
}
QTSS_Error QTSSDSAuthModuleDispatch(QTSS_Role inRole, QTSS_RoleParamPtr inParams)
{
switch (inRole)
{
case QTSS_Register_Role:
return Register();
case QTSS_Initialize_Role:
return Initialize(&inParams->initParams);
case QTSS_RereadPrefs_Role:
return RereadPrefs();
case QTSS_RTSPAuthenticate_Role:
if (sAuthenticationEnabled)
return AuthenticateRTSPRequest(&inParams->rtspAthnParams);
case QTSS_RTSPAuthorize_Role:
if (sAuthenticationEnabled)
return Authorize(&inParams->rtspRequestParams);
case QTSS_Shutdown_Role:
return Shutdown();
}
return QTSS_NoErr;
}
QTSS_Error Register()
{
// Do role & attribute setup
(void)QTSS_AddRole(QTSS_Initialize_Role);
(void)QTSS_AddRole(QTSS_RereadPrefs_Role);
(void)QTSS_AddRole(QTSS_RTSPAuthenticate_Role);
(void)QTSS_AddRole(QTSS_RTSPAuthorize_Role);
return QTSS_NoErr;
}
QTSS_Error Initialize(QTSS_Initialize_Params* inParams)
{
// Setup module utils
QTSSModuleUtils::Initialize(inParams->inMessages, inParams->inServer, inParams->inErrorLogStream);
sPrefs = QTSSModuleUtils::GetModulePrefsObject(inParams->inModule);
sServerPrefs = inParams->inPrefs;
sAuthMutex = new OSMutex();
RereadPrefs();
return QTSS_NoErr;
}
QTSS_Error Shutdown()
{
return QTSS_NoErr;
}
char* GetCheckedFileName()
{
char *result = NULL;
static char *badChars = "/'\"";
char theBadCharMessage[] = "' '";
char *theBadChar = NULL;
result = QTSSModuleUtils::GetStringAttribute(sPrefs, MODPREFIX_"dsaccessfilename", sDefaultAccessFileName);
StrPtrLen searchStr(result);
theBadChar = strpbrk(searchStr.Ptr, badChars);
if ( theBadChar!= NULL)
{
theBadCharMessage[1] = theBadChar[0];
QTSSModuleUtils::LogErrorStr(qtssWarningVerbosity,MODPREFIX_"found invalid DS access file name in prefs");
delete[] result;
result = new char[::strlen(sDefaultAccessFileName) + 2];
::strcpy(result, sDefaultAccessFileName);
}
return result;
}
QTSS_Error RereadPrefs()
{
OSMutexLocker locker(sAuthMutex);
QTSSModuleUtils::GetAttribute(sPrefs, MODPREFIX_"enabled", qtssAttrDataTypeBool16,
&sAuthenticationEnabled, &sDefaultAuthenticationEnabled, sizeof(sAuthenticationEnabled));
QTSSModuleUtils::GetAttribute(sServerPrefs,"enable_allow_guest_default", qtssAttrDataTypeBool16,
&sAllowGuestDefaultEnabled,(void *)&sDefaultGuestEnabled, sizeof(sAllowGuestDefaultEnabled));
delete [] sAccessFileName;
sAccessFileName = GetCheckedFileName();
return QTSS_NoErr;
}
Bool16 AuthenticateRequest(QTSS_StandardRTSP_Params* inParams,
const char* pathBuff,
const char* movieRootDir,
StrPtrLen* ioRealmName,
Bool16* foundUserPtr)
{
if (foundUserPtr)
*foundUserPtr = false;
if (ioRealmName) //Set Value to Empty for now use whatever is set by access file or the default
{
ioRealmName->Ptr[0] = '\0';
ioRealmName->Len = 0;
}
QTSS_Error theErr = QTSS_NoErr;
char passwordBuff[kBuffLen];
StrPtrLen passwordStr(passwordBuff, kBuffLen -1);
char nameBuff[kBuffLen];
StrPtrLen nameStr(nameBuff, kBuffLen -1);
theErr = QTSS_GetValue (inParams->inRTSPRequest,qtssRTSPReqUserName,0, (void *) nameStr.Ptr, &nameStr.Len);
if ( (QTSS_NoErr != theErr) || (nameStr.Len >= kBuffLen) )
{
debug_printf("QTSSDSAuthModule:AuthenticateRequest() Username Error - %"_S32BITARG_"\n", theErr);
return false;
}
theErr = QTSS_GetValue (inParams->inRTSPRequest,qtssRTSPReqUserPassword,0, (void *) passwordStr.Ptr, &passwordStr.Len);
if ( (QTSS_NoErr != theErr) || (passwordStr.Len >= kBuffLen) )
{
debug_printf("QTSSDSAuthModule:AuthenticateRequest() Password Error - %"_S32BITARG_"\n", theErr);
return false;
}
nameBuff[nameStr.Len] = '\0';
passwordBuff[passwordStr.Len] = '\0';
//
// Use the name and password to check access
DSAccessChecker accessChecker;
if ( !accessChecker.CheckPassword( nameBuff, passwordBuff) )
{
return false;
}
if (foundUserPtr)
*foundUserPtr = true;
return true;
}
QTSS_Error AuthenticateRTSPRequest(QTSS_RTSPAuth_Params* inParams)
{
OSMutexLocker locker(sAuthMutex);
QTSS_RTSPRequestObject theRTSPRequest = inParams->inRTSPRequest;
QTSS_AuthScheme authScheme = qtssAuthNone;
debug_printf("QTSSDSAuthModule:AuthenticateRTSPRequest start\n");
if ( (NULL == inParams) || (NULL == inParams->inRTSPRequest) )
{
debug_printf("QTSSDSAuthModule:AuthenticateRTSPRequest inParams NULL\n");
return QTSS_RequestFailed;
}
// Get the user profile object from the request object
QTSS_UserProfileObject theUserProfile = NULL;
UInt32 len = sizeof(QTSS_UserProfileObject);
QTSS_Error theErr = QTSS_GetValue(theRTSPRequest, qtssRTSPReqUserProfile, 0, (void*)&theUserProfile, &len);
Assert(len == sizeof(QTSS_UserProfileObject));
if (theErr != QTSS_NoErr)
{
debug_printf("QTSSDSAuthModule:AuthenticateRTSPRequest - username error is %"_S32BITARG_"\n", theErr);
return theErr;
}
char* nameBuff = NULL;
theErr = QTSS_GetValueAsString(theUserProfile, qtssUserName, 0, &nameBuff);
debug_printf("QTSSDSAuthModule:AuthenticateRTSPRequest - username is %s\n", nameBuff);
OSCharArrayDeleter usernameBufDeleter(nameBuff);
if (theErr != QTSS_NoErr)
{
debug_printf("QTSSDSAuthModule:AuthenticateRTSPRequest - theUserProfile nameBuff error is %"_S32BITARG_"\n", theErr);
}
len = sizeof(authScheme);
theErr = QTSS_GetValue(theRTSPRequest, qtssRTSPReqAuthScheme, 0, (void*)&authScheme, &len);
if (theErr != QTSS_NoErr)
return theErr;
DSAccessChecker accessChecker;
Bool16 allowed = true;
Bool16 foundUser = true;
Bool16 authHandled = true;
if ( authScheme == qtssAuthDigest)
{
debug_printf("QTSSDSAuthModule:AuthenticateRTSPRequest - authScheme = qtssAuthDigest\n");
char* challengeBuff = NULL;
(void) QTSS_GetValueAsString(theRTSPRequest, qtssRTSPReqDigestChallenge, 0, &challengeBuff);
OSCharArrayDeleter challengeDeleter(challengeBuff);
debug_printf("QTSSDSAuthModule:AuthenticateRTSPRequest - Server Challenge =%s\n",challengeBuff);
char* responseBuff = NULL;
(void) QTSS_GetValueAsString(theRTSPRequest, qtssRTSPReqDigestResponse, 0, &responseBuff);
OSCharArrayDeleter responseDeleter(responseBuff);
char* methodBuff = NULL;
(void) QTSS_GetValueAsString(theRTSPRequest, qtssRTSPReqMethodStr, 0, &methodBuff);
OSCharArrayDeleter methodDeleter(methodBuff);
debug_printf("QTSSDSAuthModule:AuthenticateRTSPRequest - Server Method =%s\n",methodBuff);
debug_printf("QTSSDSAuthModule:AuthenticateRTSPRequest - username is %s challenge=%s response=%s method=%s\n", nameBuff, challengeBuff, responseBuff, methodBuff);
if ( false == accessChecker.CheckDigest(nameBuff, challengeBuff, responseBuff, methodBuff) )
{ debug_printf("QTSSDSAuthModule CheckDigest returned false\n");
}
else
{ debug_printf("QTSSDSAuthModule CheckDigest returned true\n");
(void) QTSSModuleUtils::AuthorizeRequest(theRTSPRequest,&allowed,&foundUser,&authHandled);
}
}
if ( authScheme == qtssAuthBasic)
{
debug_printf("QTSSDSAuthModule:AuthenticateRTSPRequest - authScheme = qtssAuthBasic\n");
char passwordBuff[kBuffLen];
StrPtrLen passwordStr(passwordBuff, kBuffLen -1);
char nameBuff[kBuffLen];
StrPtrLen nameStr(nameBuff, kBuffLen -1);
theErr = QTSS_GetValue (inParams->inRTSPRequest,qtssRTSPReqUserName,0, (void *) nameStr.Ptr, &nameStr.Len);
if ( (QTSS_NoErr != theErr) || (nameStr.Len >= kBuffLen) )
{
debug_printf("QTSSDSAuthModule:AuthenticateRequest() Username Error - %"_S32BITARG_"\n", theErr);
return false;
}
theErr = QTSS_GetValue (inParams->inRTSPRequest,qtssRTSPReqUserPassword,0, (void *) passwordStr.Ptr, &passwordStr.Len);
if ( (QTSS_NoErr != theErr) || (passwordStr.Len >= kBuffLen) )
{
debug_printf("QTSSDSAuthModule:AuthenticateRequest() Password Error - %"_S32BITARG_"\n", theErr);
}
nameBuff[nameStr.Len] = '\0';
passwordBuff[passwordStr.Len] = '\0';
debug_printf("QTSSDSAuthModule:AuthenticateRTSPRequest - username is %s\n", nameBuff);
debug_printf("QTSSDSAuthModule:AuthenticateRTSPRequest - password is %s\n", passwordBuff);
if ( !accessChecker.CheckPassword(nameBuff, passwordBuff) )
{ debug_printf("QTSSDSAuthModule CheckPassword returned false\n");
}
else
{
debug_printf("QTSSDSAuthModule CheckPassword returned true\n");
(void) QTSSModuleUtils::AuthorizeRequest(theRTSPRequest,&allowed,&foundUser,&authHandled);
}
}
return QTSS_NoErr;
}
int check_sacl(const char *inUser)
{
#if OSX_SACL
int mbrErr = ENOENT;
int isMember = 0;
uuid_t user_uuid;
uuid_t uu;
mbrErr = mbr_uid_to_uuid(geteuid(), uu);
if (0 == mbrErr)
{
mbrErr = mbr_check_service_membership(uu, "qtss", &isMember);
if (ENOENT == mbrErr) //no acl exists so allow any user.
return kSACLAnyUser;
}
if( (mbrErr = mbr_user_name_to_uuid(inUser, user_uuid)) != 0)
{
return kSACLUnknownUser;
}
if((mbrErr = mbr_check_service_membership(user_uuid, "qtss", &isMember)) != 0)
{
if(mbrErr == ENOENT){ // no ACL exists
return kSACLAuthorized;
} else {
return kSACLNotAuthorized;
}
}
if(isMember == kSACLAuthorized)
{
return kSACLAuthorized;
}
return kSACLNotAuthorized;
#else
return kSACLAuthorized;
#endif
}
QTSS_Error Authorize(QTSS_StandardRTSP_Params* inParams)
{
OSMutexLocker locker(sAuthMutex);
QTSS_RTSPRequestObject theRTSPRequest = inParams->inRTSPRequest;
if ( (NULL == inParams) || (NULL == inParams->inRTSPRequest) )
{
debug_printf("QTSSDSAuthModule - Authorize inParams: Error");
return QTSS_RequestFailed;
}
//get the local file path
char* pathBuffStr = NULL;
QTSS_Error theErr = QTSS_GetValueAsString(theRTSPRequest, qtssRTSPReqLocalPath, 0, &pathBuffStr);
QTSSCharArrayDeleter pathBuffDeleter(pathBuffStr);
if (theErr != QTSS_NoErr)
{
debug_printf("QTSSDSAuthModule - Authorize [QTSS_GetValueAsString]: Error %"_S32BITARG_"", theErr);
return QTSS_RequestFailed;
}
//get the root movie directory
char* movieRootDirStr = NULL;
theErr = QTSS_GetValueAsString(theRTSPRequest,qtssRTSPReqRootDir, 0, &movieRootDirStr);
OSCharArrayDeleter movieRootDeleter(movieRootDirStr);
if (theErr != QTSS_NoErr)
{
debug_printf("QTSSDSAuthModule - Authorize[QTSS_GetValueAsString]: Error %"_S32BITARG_"", theErr);
return false;
}
//check if this user is allowed to see this movie
DSAccessFile accessFile;
Bool16 allowNoAccessFiles = sAllowGuestDefaultEnabled; //no access files allowed means allowing guest access (unknown users)
Bool16 allowAnyUser = false;
QTSS_ActionFlags noAction = ~qtssActionFlagsRead; //only handle read
QTSS_ActionFlags authorizeAction = QTSSModuleUtils::GetRequestActions(theRTSPRequest);
Bool16 authorized =false;
Bool16 saclUser = false;
char *name = NULL;
(void) QTSS_GetValueAsString (theRTSPRequest,qtssRTSPReqUserName,0, &name);
OSCharArrayDeleter nameDeleter(name);
if (sAllowGuestDefaultEnabled) // if guest access is on, sacls are ignored.
{
authorized = true;
}
else
{ int result = check_sacl(name);
switch (result)
{
case kSACLAuthorized: authorized = true;
break;
case kSACLUnknownUser: authorized = false; //set this to true to allow file based and other non-directory service users access, when SACLs are enabled in the system for QTSS.
break;
case kSACLNotAuthorized: authorized = false;
break;
case kSACLAnyUser: authorized = true;
break;
default: authorized = false;
}
debug_printf("QTSSDSAuthModule:Authorize sacl_check result=%d for %s authorized = %d\n",result, name, authorized);
if (false == authorized)
saclUser = true;
}
Bool16 foundUser = false;
Bool16 passwordOK = false; //::AuthenticateRequest(inParams, pathBuffStr, movieRootDirStr, &sRealmNameStr, &foundUser);
if (authorized) //have to be authorized by sacls or guest first before qtaccess file checks can allow or disallow.
{
theErr = accessFile.AuthorizeRequest(inParams,allowNoAccessFiles, noAction, authorizeAction,&authorized, &allowAnyUser);
debug_printf("QTSSDSAuthModule:Authorize AuthorizeRequest() returned authorized=%d allowAnyUser=%d\n", authorized, allowAnyUser);
}
debug_printf("QTSSDSAuthModule:Authorize AuthenticateRequest() returned passwordOK=%d foundUser=%d authorized=%d allowAnyUser=%d\n", passwordOK ,foundUser, authorized,allowAnyUser);
Bool16 allowRequest = authorized;
Bool16 authHandled = true;
if(!(authorizeAction & qtssActionFlagsRead)) //not for us
{
debug_printf("QTSSDSAuthModule:Authorize(qtssActionFlagsRead) not handled do nothing.\n");
}
else if (allowRequest)
{
debug_printf("QTSSDSAuthModule:Authorize() succeeded.\n");
theErr = QTSSModuleUtils::AuthorizeRequest(theRTSPRequest, &allowRequest, &foundUser, &authHandled);
debug_printf("QTSSDSAuthModule:Authorize allowRequest=%d founduser=%d authHandled=%d\n", allowRequest, foundUser, authHandled);
}
else //request denied
{
debug_printf("QTSSDSAuthModule:Authorize() failed.\n");
foundUser = saclUser;
authHandled = true;
theErr = QTSSModuleUtils::AuthorizeRequest(theRTSPRequest, &allowRequest, &foundUser, &authHandled);
debug_printf("QTSSDSAuthModule:Authorize allowRequest=%d founduser=%d authHandled=%d saclUser=%d\n", allowRequest, foundUser, authHandled,saclUser);
}
return theErr;
}

View file

@ -0,0 +1,46 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*
*/
/*
File: QTSSODAuthModule.h
Contains: This is a modified version of the QTSSAccessModule also released with
QTSS 2.0. It has been modified to shrink the linespacing so that
the code can fit on slides. Also, this module issues redirects to
an error movie.
*/
#ifndef _QTSSDSAUTHMODULE_H__
#define _QTSSDSAUTHMODULE_H__
#include "QTSS.h"
extern "C"
{
QTSS_Error QTSSDSAuthModule_Main(void* inPrivateArgs);
}
#endif