681 lines
24 KiB
C++
681 lines
24 KiB
C++
/*
|
|
*
|
|
* @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: QTAccessFile.cpp
|
|
|
|
Contains: This file contains the implementation for finding and parsing qtaccess files.
|
|
|
|
|
|
*/
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include "SafeStdLib.h"
|
|
#include "QTSS.h"
|
|
#include "OSHeaders.h"
|
|
#include "StrPtrLen.h"
|
|
#include "StringParser.h"
|
|
#include "QTSSModuleUtils.h"
|
|
#include "OSFileSource.h"
|
|
#include "OSMemory.h"
|
|
#include "OSHeaders.h"
|
|
#include "QTAccessFile.h"
|
|
#include "OSArrayObjectDeleter.h"
|
|
|
|
|
|
#include <grp.h>
|
|
#if __MacOSX__
|
|
#include <membership.h>
|
|
#endif
|
|
#include <pwd.h>
|
|
#include <signal.h>
|
|
#include <unistd.h>
|
|
|
|
#define DEBUG_QTACCESS 0
|
|
#define debug_printf if (DEBUG_QTACCESS) qtss_printf
|
|
|
|
char* QTAccessFile::sAccessValidUser = "require valid-user\n";
|
|
char* QTAccessFile::sAccessAnyUser = "require any-user\n";
|
|
|
|
UInt8 QTAccessFile::sWhitespaceAndGreaterThanMask[] =
|
|
{
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, //0-9 // \t is a stop
|
|
1, 1, 1, 1, 0, 0, 0, 0, 0, 0, //10-19 //'\r' & '\n' are stop conditions
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //20-29
|
|
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, //30-39 ' ' is a stop
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //40-49
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //50-59
|
|
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, //60-69 // '>' is a stop
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //70-79
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //80-89
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //90-99
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //100-109
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //110-119
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //120-129
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //130-139
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //140-149
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //150-159
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //160-169
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //170-179
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //180-189
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //190-199
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //200-209
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //210-219
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //220-229
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //230-239
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //240-249
|
|
0, 0, 0, 0, 0, 0 //250-255
|
|
};
|
|
|
|
char* QTAccessFile::sQTAccessFileName = "qtaccess";
|
|
Bool16 QTAccessFile::sAllocatedName = false;
|
|
OSMutex* QTAccessFile::sAccessFileMutex = NULL;//QTAccessFile isn't reentrant
|
|
const int kBuffLen = 512;
|
|
|
|
void QTAccessFile::Initialize() // called by server at initialize never call again
|
|
{
|
|
if (NULL == sAccessFileMutex)
|
|
{ sAccessFileMutex = NEW OSMutex();
|
|
}
|
|
}
|
|
|
|
void QTAccessFile::SetAccessFileName(const char *inQTAccessFileName)
|
|
{
|
|
OSMutexLocker locker(sAccessFileMutex);
|
|
if (NULL == inQTAccessFileName)
|
|
{ Assert(NULL != inQTAccessFileName);
|
|
return;
|
|
}
|
|
|
|
if (sAllocatedName)
|
|
{ delete [] sQTAccessFileName;
|
|
}
|
|
|
|
sAllocatedName = true;
|
|
sQTAccessFileName = NEW char[strlen(inQTAccessFileName)+1];
|
|
::strcpy(sQTAccessFileName, inQTAccessFileName);
|
|
|
|
}
|
|
|
|
|
|
Bool16 QTAccessFile::HaveUser(char *userName, void* extraDataPtr)
|
|
{
|
|
Bool16 result = false;
|
|
|
|
if (NULL != userName && 0 != userName[0])
|
|
result = true;
|
|
|
|
return result;
|
|
}
|
|
|
|
Bool16 QTAccessFile::HaveGroups( char** groupArray, UInt32 numGroups, void* extraDataPtr)
|
|
{
|
|
Bool16 result = false;
|
|
|
|
if (numGroups > 0 && groupArray != NULL)
|
|
result = true;
|
|
|
|
return result;
|
|
}
|
|
|
|
Bool16 QTAccessFile::HaveRealm( char *userName, StrPtrLen* ioRealmNameStr, void *extraData )
|
|
{
|
|
Bool16 result = false;
|
|
|
|
if (ioRealmNameStr != NULL && ioRealmNameStr->Ptr != NULL && ioRealmNameStr->Len > 0)
|
|
result = true;
|
|
|
|
return result;
|
|
}
|
|
|
|
void QTAccessFile::GetRealm(StrPtrLen* accessRealm, StrPtrLen* ioRealmNameStr, char *userName,void *extraDataPtr )
|
|
{
|
|
|
|
if (ioRealmNameStr->Len <= accessRealm->Len)
|
|
accessRealm->Len = ioRealmNameStr->Len -1; // just copy what we can
|
|
::memcpy(ioRealmNameStr->Ptr, accessRealm->Ptr,accessRealm->Len);
|
|
ioRealmNameStr->Ptr[accessRealm->Len] = 0;
|
|
|
|
}
|
|
|
|
Bool16 QTAccessFile::TestUser(StrPtrLen* accessUser, char *userName,void *extraDataPtr )
|
|
{
|
|
Bool16 result = false;
|
|
|
|
if ( accessUser->Equal(userName) )
|
|
result = true;
|
|
|
|
return result;
|
|
}
|
|
|
|
Bool16 QTAccessFile::TestGroup( StrPtrLen* accessGroup, char *userName, char**groupArray, UInt32 numGroups, void *extraDataPtr)
|
|
{
|
|
|
|
for (UInt32 index = 0; index < numGroups; index ++)
|
|
{ if(accessGroup->Equal(groupArray[index]))
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
Bool16 QTAccessFile::TestExtraData( StrPtrLen* wordPtr, StringParser* lineParserPtr, void* extraDataPtr)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
|
|
Bool16 QTAccessFile::AccessAllowed ( char *userName, char**groupArray, UInt32 numGroups, StrPtrLen *accessFileBufPtr,
|
|
QTSS_ActionFlags inFlags,StrPtrLen* ioRealmNameStr, Bool16 *outAllowAnyUserPtr, void *extraDataPtr
|
|
)
|
|
{
|
|
if (NULL == accessFileBufPtr || NULL == accessFileBufPtr->Ptr || 0 == accessFileBufPtr->Len)
|
|
return true; // nothing to check
|
|
|
|
if (ioRealmNameStr != NULL && ioRealmNameStr->Ptr != NULL && ioRealmNameStr->Len > 0)
|
|
ioRealmNameStr->Ptr[0] = 0;
|
|
|
|
StringParser accessFileParser(accessFileBufPtr);
|
|
QTSS_ActionFlags currentFlags = qtssActionFlagsRead;
|
|
StrPtrLen line;
|
|
StrPtrLen word;
|
|
Bool16 haveUserName = false;
|
|
Bool16 haveRealmResultBuffer = false;
|
|
Bool16 haveGroups = false;
|
|
|
|
*outAllowAnyUserPtr = false;
|
|
|
|
haveUserName = HaveUser(userName, extraDataPtr);
|
|
|
|
haveGroups = HaveGroups(groupArray, numGroups, extraDataPtr);
|
|
|
|
haveRealmResultBuffer = HaveRealm(userName, ioRealmNameStr, extraDataPtr );
|
|
|
|
while( accessFileParser.GetDataRemaining() != 0 )
|
|
{
|
|
accessFileParser.GetThruEOL(&line); // Read each line
|
|
StringParser lineParser(&line);
|
|
lineParser.ConsumeWhitespace();//skip over leading whitespace
|
|
if (lineParser.GetDataRemaining() == 0) // must be an empty line
|
|
continue;
|
|
|
|
char firstChar = lineParser.PeekFast();
|
|
if ( (firstChar == '#') || (firstChar == '\0') )
|
|
continue; //skip over comments and blank lines...
|
|
|
|
lineParser.ConsumeUntilWhitespace(&word);
|
|
if ( word.Equal("<Limit") ) // a limit line
|
|
{
|
|
currentFlags = qtssActionFlagsNoFlags; // clear to no access
|
|
lineParser.ConsumeWhitespace();
|
|
lineParser.ConsumeUntil( &word, sWhitespaceAndGreaterThanMask); // the flag <limit Read> or <limit Read >
|
|
while (word.Len != 0) // compare each word in the line
|
|
{
|
|
if (word.Equal("WRITE") )
|
|
{ currentFlags |= inFlags & qtssActionFlagsWrite; // accept following lines if inFlags has write
|
|
}
|
|
|
|
if (word.Equal("READ") )
|
|
{ currentFlags |= inFlags & qtssActionFlagsRead; // accept following lines if inFlags has read
|
|
}
|
|
lineParser.ConsumeWhitespace();
|
|
lineParser.ConsumeUntil(&word, sWhitespaceAndGreaterThanMask);
|
|
}
|
|
continue; //done with limit line
|
|
}
|
|
if ( word.Equal("</Limit>") )
|
|
currentFlags = qtssActionFlagsRead; // set the current access state to the default of read access
|
|
|
|
if (0 == (currentFlags & inFlags))
|
|
continue; // ignore lines because inFlags doesn't match the current access state
|
|
|
|
if (haveRealmResultBuffer && word.Equal("AuthName") ) //realm name
|
|
{
|
|
lineParser.ConsumeWhitespace();
|
|
lineParser.GetThruEOL(&word);
|
|
StringParser::UnQuote(&word);// if the parsed string is surrounded by quotes then remove them.
|
|
|
|
GetRealm(&word, ioRealmNameStr, userName, extraDataPtr );
|
|
|
|
// we don't change the buffer len ioRealmNameStr->Len because we might have another AuthName tag to copy
|
|
continue; // done with AuthName (realm)
|
|
}
|
|
|
|
|
|
if (word.Equal("require") )
|
|
{
|
|
lineParser.ConsumeWhitespace();
|
|
lineParser.ConsumeUntilWhitespace(&word);
|
|
|
|
if (haveUserName && word.Equal("valid-user") )
|
|
{ return true;
|
|
}
|
|
|
|
if ( word.Equal("any-user") )
|
|
{
|
|
*outAllowAnyUserPtr = true;
|
|
return true;
|
|
}
|
|
|
|
if (!haveUserName)
|
|
continue;
|
|
|
|
if (word.Equal("user") )
|
|
{
|
|
lineParser.ConsumeWhitespace();
|
|
lineParser.ConsumeUntilWhitespace(&word);
|
|
|
|
while (word.Len != 0) // compare each word in the line
|
|
{
|
|
if (TestUser(&word, userName, extraDataPtr ))
|
|
return true;
|
|
|
|
lineParser.ConsumeWhitespace();
|
|
lineParser.ConsumeUntilWhitespace(&word);
|
|
}
|
|
continue; // done with "require user" line
|
|
}
|
|
|
|
if (haveGroups && word.Equal("group")) // check if we have groups for the user
|
|
{
|
|
lineParser.ConsumeWhitespace();
|
|
lineParser.ConsumeUntilWhitespace(&word);
|
|
|
|
while (word.Len != 0) // compare each word in the line
|
|
{
|
|
if (TestGroup(&word, userName, groupArray, numGroups, extraDataPtr) )
|
|
return true;
|
|
|
|
lineParser.ConsumeWhitespace();
|
|
lineParser.ConsumeUntilWhitespace(&word);
|
|
}
|
|
continue; // done with "require group" line
|
|
}
|
|
|
|
if (TestExtraData(&word, &lineParser, extraDataPtr))
|
|
return true;
|
|
|
|
|
|
continue; // done with unparsed "require" line
|
|
}
|
|
|
|
}
|
|
|
|
return false; // user or group not found
|
|
}
|
|
|
|
char* QTAccessFile::GetAccessFile_Copy( const char* movieRootDir, const char* dirPath)
|
|
{
|
|
OSMutexLocker locker(sAccessFileMutex);
|
|
|
|
char* currentDir= NULL;
|
|
char* lastSlash = NULL;
|
|
int movieRootDirLen = ::strlen(movieRootDir);
|
|
int maxLen = strlen(dirPath)+strlen(sQTAccessFileName) + strlen(kPathDelimiterString) + 1;
|
|
currentDir = NEW char[maxLen];
|
|
|
|
::strcpy(currentDir, dirPath);
|
|
|
|
//strip off filename
|
|
lastSlash = ::strrchr(currentDir, kPathDelimiterChar);
|
|
if (lastSlash != NULL)
|
|
lastSlash[0] = '\0';
|
|
|
|
//check qtaccess files
|
|
|
|
while ( true ) //walk backward up the dir tree.
|
|
{
|
|
int curLen = strlen(currentDir) + strlen(sQTAccessFileName) + strlen(kPathDelimiterString);
|
|
|
|
if ( curLen >= maxLen )
|
|
break;
|
|
|
|
::strcat(currentDir, kPathDelimiterString);
|
|
::strcat(currentDir, sQTAccessFileName);
|
|
|
|
QTSS_Object fileObject = NULL;
|
|
if( QTSS_OpenFileObject(currentDir, qtssOpenFileNoFlags, &fileObject) == QTSS_NoErr)
|
|
{
|
|
(void)QTSS_CloseFileObject(fileObject);
|
|
return currentDir;
|
|
}
|
|
|
|
//strip off the "/qtaccess"
|
|
lastSlash = ::strrchr(currentDir, kPathDelimiterChar);
|
|
lastSlash[0] = '\0';
|
|
|
|
//strip of the tailing directory
|
|
lastSlash = ::strrchr(currentDir, kPathDelimiterChar);
|
|
if (lastSlash == NULL)
|
|
break;
|
|
else
|
|
lastSlash[0] = '\0';
|
|
|
|
if ( (lastSlash-currentDir) < movieRootDirLen ) //bail if we start eating our way out of fMovieRootDir
|
|
break;
|
|
}
|
|
|
|
delete[] currentDir;
|
|
return NULL;
|
|
}
|
|
|
|
// allocates memory for outUsersFilePath and outGroupsFilePath - remember to delete
|
|
// returns the auth scheme
|
|
QTSS_AuthScheme QTAccessFile::FindUsersAndGroupsFilesAndAuthScheme(char* inAccessFilePath, QTSS_ActionFlags inAction, char** outUsersFilePath, char** outGroupsFilePath)
|
|
{
|
|
QTSS_AuthScheme authScheme = qtssAuthNone;
|
|
QTSS_ActionFlags currentFlags = qtssActionFlagsRead;
|
|
|
|
if (inAccessFilePath == NULL)
|
|
return authScheme;
|
|
|
|
*outUsersFilePath = NULL;
|
|
*outGroupsFilePath = NULL;
|
|
//Assert(outUsersFilePath == NULL);
|
|
//Assert(outGroupsFilePath == NULL);
|
|
|
|
StrPtrLen accessFileBuf;
|
|
(void)QTSSModuleUtils::ReadEntireFile(inAccessFilePath, &accessFileBuf);
|
|
OSCharArrayDeleter accessFileBufDeleter(accessFileBuf.Ptr);
|
|
|
|
StringParser accessFileParser(&accessFileBuf);
|
|
StrPtrLen line;
|
|
StrPtrLen word;
|
|
|
|
while( accessFileParser.GetDataRemaining() != 0 )
|
|
{
|
|
accessFileParser.GetThruEOL(&line); // Read each line
|
|
StringParser lineParser(&line);
|
|
lineParser.ConsumeWhitespace(); //skip over leading whitespace
|
|
if (lineParser.GetDataRemaining() == 0) // must be an empty line
|
|
continue;
|
|
|
|
char firstChar = lineParser.PeekFast();
|
|
if ( (firstChar == '#') || (firstChar == '\0') )
|
|
continue; //skip over comments and blank lines...
|
|
|
|
lineParser.ConsumeUntilWhitespace(&word);
|
|
|
|
if ( word.Equal("<Limit") ) // a limit line
|
|
{
|
|
currentFlags = qtssActionFlagsNoFlags; // clear to no access
|
|
lineParser.ConsumeWhitespace();
|
|
lineParser.ConsumeUntil( &word, sWhitespaceAndGreaterThanMask); // the flag <limit Read> or <limit Read >
|
|
while (word.Len != 0) // compare each word in the line
|
|
{
|
|
if (word.Equal("WRITE") )
|
|
{
|
|
currentFlags |= inAction & qtssActionFlagsWrite; // accept following lines if inFlags has write
|
|
}
|
|
|
|
if (word.Equal("READ") )
|
|
{
|
|
currentFlags |= inAction & qtssActionFlagsRead; // accept following lines if inFlags has read
|
|
}
|
|
|
|
lineParser.ConsumeWhitespace();
|
|
lineParser.ConsumeUntil(&word, sWhitespaceAndGreaterThanMask);
|
|
}
|
|
continue; //done with limit line
|
|
}
|
|
|
|
if ( word.Equal("</Limit>") )
|
|
currentFlags = qtssActionFlagsRead; // set the current access state to the default of read access
|
|
|
|
if (0 == (currentFlags & inAction))
|
|
continue; // ignore lines because inFlags doesn't match the current access state
|
|
|
|
if (word.Equal("AuthUserFile") )
|
|
{
|
|
lineParser.ConsumeWhitespace();
|
|
lineParser.GetThruEOL(&word);
|
|
StringParser::UnQuote(&word);// if the parsed string is surrounded by quotes then remove them.
|
|
|
|
if(*outUsersFilePath != NULL) // we are encountering the AuthUserFile keyword twice!
|
|
delete[] *outUsersFilePath; // The last one found takes precedence...delete the previous path
|
|
|
|
*outUsersFilePath = word.GetAsCString();
|
|
continue;
|
|
}
|
|
|
|
if (word.Equal("AuthGroupFile") )
|
|
{
|
|
lineParser.ConsumeWhitespace();
|
|
lineParser.GetThruEOL(&word);
|
|
StringParser::UnQuote(&word);// if the parsed string is surrounded by quotes then remove them.
|
|
|
|
if(*outGroupsFilePath != NULL) // we are encountering the AuthGroupFile keyword twice!
|
|
delete[] *outGroupsFilePath; // The last one found takes precedence...delete the previous path
|
|
|
|
*outGroupsFilePath = word.GetAsCString();
|
|
|
|
continue;
|
|
}
|
|
|
|
if (word.Equal("AuthScheme") )
|
|
{
|
|
lineParser.ConsumeWhitespace();
|
|
lineParser.GetThruEOL(&word);
|
|
StringParser::UnQuote(&word);// if the parsed string is surrounded by quotes then remove them.
|
|
|
|
if (word.Equal("basic"))
|
|
authScheme = qtssAuthBasic;
|
|
else if (word.Equal("digest"))
|
|
authScheme = qtssAuthDigest;
|
|
|
|
continue;
|
|
}
|
|
}
|
|
|
|
return authScheme;
|
|
}
|
|
|
|
QTSS_Error QTAccessFile::AuthorizeRequest(QTSS_StandardRTSP_Params* inParams, Bool16 allowNoAccessFiles, QTSS_ActionFlags noAction, QTSS_ActionFlags authorizeAction, Bool16 *outAuthorizedPtr, Bool16 *outAllowAnyUserPtr)
|
|
{
|
|
if ( (NULL == inParams) || (NULL == inParams->inRTSPRequest) || (NULL == outAllowAnyUserPtr) || (NULL == outAuthorizedPtr) )
|
|
return QTSS_RequestFailed;
|
|
|
|
*outAllowAnyUserPtr = false;
|
|
*outAuthorizedPtr = false;
|
|
|
|
QTSS_RTSPRequestObject theRTSPRequest = inParams->inRTSPRequest;
|
|
|
|
// get the type of request
|
|
// Don't touch write requests
|
|
QTSS_ActionFlags action = QTSSModuleUtils::GetRequestActions(theRTSPRequest);
|
|
if(action == qtssActionFlagsNoFlags)
|
|
return QTSS_RequestFailed;
|
|
|
|
if( (action & noAction) != 0)
|
|
return QTSS_NoErr; // we don't handle
|
|
|
|
//get the local file path
|
|
char* pathBuffStr = QTSSModuleUtils::GetLocalPath_Copy(theRTSPRequest);
|
|
OSCharArrayDeleter pathBuffDeleter(pathBuffStr);
|
|
if (NULL == pathBuffStr)
|
|
return QTSS_RequestFailed;
|
|
|
|
//get the root movie directory
|
|
char* movieRootDirStr = QTSSModuleUtils::GetMoviesRootDir_Copy(theRTSPRequest);
|
|
OSCharArrayDeleter movieRootDeleter(movieRootDirStr);
|
|
if (NULL == movieRootDirStr)
|
|
return QTSS_RequestFailed;
|
|
|
|
QTSS_UserProfileObject theUserProfile = QTSSModuleUtils::GetUserProfileObject(theRTSPRequest);
|
|
if (NULL == theUserProfile)
|
|
return QTSS_RequestFailed;
|
|
|
|
char* accessFilePath = QTAccessFile::GetAccessFile_Copy(movieRootDirStr, pathBuffStr);
|
|
OSCharArrayDeleter accessFilePathDeleter(accessFilePath);
|
|
|
|
char* username = QTSSModuleUtils::GetUserName_Copy(theUserProfile);
|
|
OSCharArrayDeleter usernameDeleter(username);
|
|
|
|
UInt32 numGroups = 0;
|
|
char** groupCharPtrArray = QTSSModuleUtils::GetGroupsArray_Copy(theUserProfile, &numGroups);
|
|
OSCharPointerArrayDeleter groupCharPtrArrayDeleter(groupCharPtrArray);
|
|
|
|
StrPtrLen accessFileBuf;
|
|
(void)QTSSModuleUtils::ReadEntireFile(accessFilePath, &accessFileBuf);
|
|
OSCharArrayDeleter accessFileBufDeleter(accessFileBuf.Ptr);
|
|
|
|
if (accessFileBuf.Len == 0 && !allowNoAccessFiles)
|
|
{ accessFileBuf.Set(sAccessValidUser);
|
|
if (DEBUG_QTACCESS)
|
|
qtss_printf("QTAccessFile::AuthorizeRequest SET Accessfile valid user for no accessfile %s\n", sAccessValidUser);
|
|
}
|
|
|
|
if (accessFileBuf.Len == 0 && allowNoAccessFiles)
|
|
{ accessFileBuf.Set(sAccessAnyUser);
|
|
if (DEBUG_QTACCESS)
|
|
qtss_printf("QTAccessFile::AuthorizeRequest SET Accessfile any user for no access file %s\n", sAccessAnyUser);
|
|
}
|
|
|
|
char realmName[kBuffLen] = { 0 };
|
|
StrPtrLen realmNameStr(realmName,kBuffLen -1);
|
|
|
|
//check if this user is allowed to see this movie
|
|
Bool16 allowRequest = this->AccessAllowed(username, groupCharPtrArray, numGroups, &accessFileBuf, authorizeAction,&realmNameStr, outAllowAnyUserPtr );
|
|
debug_printf("accessFile.AccessAllowed for user=%s returned %d\n", username, allowRequest);
|
|
|
|
// Get the auth scheme
|
|
QTSS_AuthScheme theAuthScheme = qtssAuthNone;
|
|
UInt32 len = sizeof(theAuthScheme);
|
|
QTSS_Error theErr = QTSS_GetValue(theRTSPRequest, qtssRTSPReqAuthScheme, 0, (void*)&theAuthScheme, &len);
|
|
Assert(len == sizeof(theAuthScheme));
|
|
if(theErr != QTSS_NoErr)
|
|
return theErr;
|
|
|
|
// If auth scheme is basic and the realm is present in the access file, use it
|
|
if((theAuthScheme == qtssAuthBasic) && (realmNameStr.Ptr[0] != '\0')) //set the realm if we have one
|
|
(void) QTSS_SetValue(theRTSPRequest,qtssRTSPReqURLRealm, 0, realmNameStr.Ptr, ::strlen(realmNameStr.Ptr));
|
|
else // if auth scheme is basic and no realm is present, or if the auth scheme is digest, use the realm from the users file
|
|
{
|
|
char* userRealm = NULL;
|
|
(void) QTSS_GetValueAsString(theUserProfile, qtssUserRealm, 0, &userRealm);
|
|
if(userRealm != NULL)
|
|
{
|
|
OSCharArrayDeleter userRealmDeleter(userRealm);
|
|
(void) QTSS_SetValue(theRTSPRequest,qtssRTSPReqURLRealm, 0, userRealm, ::strlen(userRealm));
|
|
}
|
|
}
|
|
|
|
*outAuthorizedPtr = allowRequest;
|
|
|
|
Bool16 founduser = this->HaveUser(username, NULL);
|
|
Bool16 authContinue = true;
|
|
char nameBuff[256];
|
|
StrPtrLen reqNameStr(nameBuff, kBuffLen);
|
|
StrPtrLen profileNameStr(username);
|
|
theErr = QTSS_GetValue (theRTSPRequest,qtssRTSPReqUserName,0, (void *) reqNameStr.Ptr, &reqNameStr.Len);
|
|
|
|
|
|
if (DEBUG_QTACCESS)
|
|
{ qtss_printf("QTAccessFile::AuthorizeRequest qtaccess profile user =%s ", username);
|
|
reqNameStr.PrintStr("request user=","\n");
|
|
qtss_printf("QTAccessFile::AuthorizeRequest allowRequest=%d founduser=%d authContinue=%d\n", allowRequest, founduser, authContinue);
|
|
}
|
|
if (allowRequest && founduser)
|
|
theErr = QTSSModuleUtils::AuthorizeRequest(theRTSPRequest, &allowRequest, &founduser,&authContinue);
|
|
if (!allowRequest && !founduser)
|
|
theErr = QTSSModuleUtils::AuthorizeRequest(theRTSPRequest, &allowRequest, &founduser,&authContinue);
|
|
|
|
if (DEBUG_QTACCESS)
|
|
{ qtss_printf("QTAccessFile::AuthorizeRequest QTSSModuleUtils::AuthorizeRequest qtaccess profile user =%s ", username);
|
|
reqNameStr.PrintStr("request user=","\n");
|
|
qtss_printf("QTAccessFile::AuthorizeRequest allowRequest=%d founduser=%d authContinue=%d\n", allowRequest, founduser, authContinue);
|
|
}
|
|
|
|
return theErr;
|
|
}
|
|
|
|
|
|
bool DSAccessFile::CheckGroupMembership(const char* inUsername, const char* inGroupName)
|
|
{
|
|
struct passwd *user = NULL;
|
|
struct group *group = NULL;
|
|
#if __MacOSX__
|
|
uuid_t userID;
|
|
uuid_t groupID;
|
|
int isMember = 0;
|
|
#else
|
|
int numGroups = 50;
|
|
gid_t *groupList;
|
|
groupList = (gid_t *) malloc(numGroups * sizeof(gid_t));
|
|
#endif
|
|
|
|
// Look up the user using the POSIX APIs: only care about the UID.
|
|
user = getpwnam(inUsername);
|
|
if ( user == NULL )
|
|
return false;
|
|
#if __MacOSX__
|
|
uuid_clear(userID);
|
|
if ( mbr_uid_to_uuid(user->pw_uid, userID) )
|
|
return false;
|
|
#endif
|
|
// Look up the group using the POSIX APIs: only care about the GID.
|
|
group = getgrnam(inGroupName);
|
|
endgrent();
|
|
if ( group == NULL )
|
|
return false;
|
|
#if __MacOSX__
|
|
uuid_clear(groupID);
|
|
if ( mbr_gid_to_uuid(group->gr_gid, groupID) )
|
|
return false;
|
|
|
|
// In Tiger, group membership is painfully simple: we ask memberd for it!
|
|
// mbr_check_membership() returns 0 on success and error code on failure.
|
|
if ( mbr_check_membership(userID, groupID, &isMember) )
|
|
return false;
|
|
return (bool)isMember;
|
|
#else
|
|
if(getgrouplist(inUsername, user->pw_gid, groupList, &numGroups) == -1) {
|
|
qtss_printf("QTAccessFile::CheckGroupMembership getgrouplist for user %s returned -1 and numGroups = %d", inUsername, numGroups);
|
|
return false;
|
|
}
|
|
for(int i = 0; i < numGroups; i++) {
|
|
if(groupList[i] == group->gr_gid) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
Bool16 DSAccessFile::ValidUser( char*userName, void* extraDataPtr)
|
|
{
|
|
struct passwd *user = getpwnam(userName);
|
|
Bool16 result =true;
|
|
if ( user == NULL )
|
|
{
|
|
return result;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|