inline void ParseAuthNameAndPassword(StrPtrLen *codedStrPtr, StrPtrLen* namePtr, StrPtrLen* passwordPtr) { if (!codedStrPtr || (codedStrPtr->Len >= kAuthNameAndPasswordBuffSize) ) { return; } StrPtrLen codedLineStr; StrPtrLen nameAndPassword; memset(decodedLine,0,kAuthNameAndPasswordBuffSize); memset(codedLine,0,kAuthNameAndPasswordBuffSize); memcpy (codedLine,codedStrPtr->Ptr,codedStrPtr->Len); codedLineStr.Set((char*) codedLine, codedStrPtr->Len); (void) Base64decode(decodedLine, codedLineStr.Ptr); nameAndPassword.Set((char*) decodedLine, strlen(decodedLine)); StringParser parsedNameAndPassword(&nameAndPassword); parsedNameAndPassword.ConsumeUntil(namePtr,':'); parsedNameAndPassword.ConsumeLength(NULL, 1); // password can have whitespace, so read until the end of the line, not just until whitespace parsedNameAndPassword.ConsumeUntil(passwordPtr, StringParser::sEOLMask); namePtr->Ptr[namePtr->Len]= 0; passwordPtr->Ptr[passwordPtr->Len]= 0; //qtss_printf("decoded nameAndPassword="******"decoded name="); PRINT_STR(namePtr); //qtss_printf("decoded password="); PRINT_STR(passwordPtr); return; };
QTSS_Error RTSPRequest::ParseBasicHeader(StringParser *inParsedAuthLinePtr) { QTSS_Error theErr = QTSS_NoErr; fAuthScheme = qtssAuthBasic; StrPtrLen authWord; inParsedAuthLinePtr->ConsumeWhitespace(); inParsedAuthLinePtr->ConsumeUntilWhitespace(&authWord); if (0 == authWord.Len ) return theErr; char* encodedStr = authWord.GetAsCString(); OSCharArrayDeleter encodedStrDeleter(encodedStr); char *decodedAuthWord = NEW char[Base64decode_len(encodedStr) + 1]; OSCharArrayDeleter decodedAuthWordDeleter(decodedAuthWord); (void) Base64decode(decodedAuthWord, encodedStr); StrPtrLen nameAndPassword; nameAndPassword.Set(decodedAuthWord, ::strlen(decodedAuthWord)); StrPtrLen name(""); StrPtrLen password(""); StringParser parsedNameAndPassword(&nameAndPassword); parsedNameAndPassword.ConsumeUntil(&name,':'); parsedNameAndPassword.ConsumeLength(NULL, 1); parsedNameAndPassword.GetThruEOL(&password); // Set the qtssRTSPReqUserName and qtssRTSPReqUserPassword attributes in the Request object (void) this->SetValue(qtssRTSPReqUserName, 0, name.Ptr , name.Len, QTSSDictionary::kDontObeyReadOnly); (void) this->SetValue(qtssRTSPReqUserPassword, 0, password.Ptr , password.Len, QTSSDictionary::kDontObeyReadOnly); // Also set the qtssUserName attribute in the qtssRTSPReqUserProfile object attribute of the Request Object (void) fUserProfile.SetValue(qtssUserName, 0, name.Ptr, name.Len, QTSSDictionary::kDontObeyReadOnly); return theErr; }
QTSS_Error Initialize(QTSS_Initialize_Params* inParams) { // Setup module utils QTSSModuleUtils::Initialize(inParams->inMessages, inParams->inServer, inParams->inErrorLogStream); sAccessLogPrefs = QTSSModuleUtils::GetModulePrefsObject(QTSSModuleUtils::GetModuleObjectByName("QTSSAccessLogModule")); sReflectorPrefs = QTSSModuleUtils::GetModulePrefsObject(QTSSModuleUtils::GetModuleObjectByName("QTSSReflectorModule")); sPrefs = QTSSModuleUtils::GetModulePrefsObject(inParams->inModule); // This module may not be present, so be careful... QTSS_ModuleObject theSvrControlModule = QTSSModuleUtils::GetModuleObjectByName("QTSSSvrControlModule"); if (theSvrControlModule != NULL) sSvrControlPrefs = QTSSModuleUtils::GetModulePrefsObject(theSvrControlModule); sServer = inParams->inServer; sServerPrefs = inParams->inPrefs; sStartupTime = ::time(NULL); sDefaultURLStr.Delete(); sDefaultURLStr.Set(QTSSModuleUtils::GetStringAttribute(sPrefs, sDefaultURLPrefName, sDefaultURL)); return QTSS_NoErr; }
SDPContainer* QTSS3GPPModuleUtils::Get3GPPSDPFeatureListCopy(ResizeableStringFormatter &buffer) { SDPContainer* resultList = NEW SDPContainer; StrPtrLen theLinePtr; if (s3gppEnabled) { if (s3gppRateAdaptationEnabled) { buffer.Put(s3gppBitRateAdaptationSDPStr); buffer.Put((SInt32)s3gppRateAdaptationReportFrequency); buffer.PutEOL(); theLinePtr.Set(buffer.GetBufPtr(), buffer.GetBytesWritten()); resultList->AddHeaderLine(&theLinePtr); buffer.Reset(); } } return resultList; }
void AccessChecker::GetAccessFileInfo(const char* inQTAccessDir) { Assert( fAccessFile != NULL); const int kBufLen = 2048; char buf[kBufLen]; StrPtrLen bufLine; ::qtss_printf("QTSSDemoODAuthModule: File Info\n"); while ( std::fgets(buf, kBufLen, fAccessFile) != NULL ) { bufLine.Set(buf, strlen(buf)); StringParser bufParser(&bufLine); //skip over leading whitespace bufParser.ConsumeUntil(NULL, StringParser::sWhitespaceMask); //skip over comments and blank lines... if ( (bufParser.GetDataRemaining() == 0) || (bufParser[0] == '#') || (bufParser[0] == '\0') ) continue; StrPtrLen word; bufParser.ConsumeWord(&word); bufParser.ConsumeWhitespace(); if ( word.Equal("AuthName") ) //realm name { bufParser.GetThruEOL(&word); fRealmHeader = word.Ptr; } else if ( word.Equal("AuthUserFile" ) ) //users name { char filePath[kBufLen]; bufParser.GetThruEOL(&word); if (word.Ptr[0] == '/') //absolute path { std::memcpy(filePath, word.Ptr, word.Len); filePath[word.Len] = '\0'; } else { std::snprintf(filePath, sizeof(filePath), "%s/%s", inQTAccessDir, word.Ptr); } fUsersFile = std::fopen(filePath, "r"); } else if ( word.Equal("AuthGroupFile") ) //groups name { char filePath[kBufLen]; bufParser.GetThruEOL(&word); if (word.Ptr[0] == '/') //absolute path { std::memcpy(filePath, word.Ptr, word.Len); filePath[word.Len] = '\0'; } else { std::snprintf(filePath, sizeof(filePath), "%s/%s", inQTAccessDir, word.Ptr); } fGroupsFile = std::fopen(filePath, "r"); } } if (fUsersFile == NULL) { fUsersFile = std::fopen(fUsersFilePath.c_str(), "r"); } if (fGroupsFile == NULL) { fGroupsFile = std::fopen(fGroupsFilePath.c_str(), "r"); } }
bool AccessChecker::CheckUserAccess(const char* inUsername) { ::qtss_printf("In QTSSDemoODAuthModule: Check User Access - start\n"); const int kBufLen = 2048; char buf[kBufLen]; StrPtrLen bufLine; if ( fAccessFile == NULL ) return false; std::rewind(fAccessFile); while ( std::fgets(buf, kBufLen, fAccessFile) != NULL ) { bufLine.Set(buf, strlen(buf)); StringParser bufParser(&bufLine); //skip over leading whitespace bufParser.ConsumeUntil(NULL, StringParser::sWhitespaceMask); //skip over comments and blank lines... if ((bufParser.GetDataRemaining() == 0) || (bufParser[0] == '#') || (bufParser[0] == '\0') ) continue; StrPtrLen word; bufParser.ConsumeWord(&word); if ( word.Equal("require") ) { bufParser.ConsumeWhitespace(); bufParser.ConsumeWord(&word); if ( word.Equal("user") ) { while (word.Len != 0) { bufParser.ConsumeWhitespace(); bufParser.ConsumeWord(&word); if (word.Equal(inUsername)) { ::qtss_printf("QTSSDemoODAuthModule in CheckUserAccess() : user %s found\n", inUsername); return true; } } } else if (word.Equal("valid-user")) { ::qtss_printf("QTSSDemoODAuthModule in CheckUserAccess(): valid-user\n"); return true; } else if ( word.Equal("group") ) { while (word.Len != 0) { bufParser.ConsumeWhitespace(); bufParser.ConsumeWord(&word); if ( this->CheckGroupMembership(inUsername, word.GetAsCString()) ) { ::qtss_printf("QTSSDemoODAuthModule in CheckUserAccess(): user is part of %s group\n", word.GetAsCString()); return true; } } } } } return false; }
QTSS_Error RelaySession::SetupRelaySession(SourceInfo* inInfo) { QTSS_Error theErr = QTSS_NoErr; theErr = this->SetupReflectorSession(inInfo, NULL); if (theErr != QTSS_NoErr) return theErr; // create the reflector session object for this session UInt32 outIndex = 0; fRelaySessionObject = NULL; theErr = QTSS_LockObject(relayModuleAttributesObject); Assert(theErr == QTSS_NoErr); theErr = QTSS_CreateObjectValue (relayModuleAttributesObject , sRelaySessionObjectID, qtssRelaySessionObjectType, &outIndex, &fRelaySessionObject); Assert(theErr == QTSS_NoErr); if (fRelaySessionObject == NULL) return theErr; // set the values for all the static attributes in this session char* relayName = inInfo->Name(); // name of the relay if (relayName != NULL) theErr = QTSS_SetValue (fRelaySessionObject, sRelayName, 0, (void*)relayName, ::strlen(relayName)); else theErr = QTSS_SetValue (fRelaySessionObject, sRelayName, 0, (void*)sEmptyStr.Ptr, sEmptyStr.Len); Assert(theErr == QTSS_NoErr); StrPtrLen sourceStr; // type of source if (inInfo->IsRTSPSourceInfo()) { if (((RTSPSourceInfo*)inInfo)->IsAnnounce()) sourceStr.Set(sAnnouncedSourceStr.Ptr, sAnnouncedSourceStr.Len); else sourceStr.Set(sRTSPSourceStr.Ptr, sRTSPSourceStr.Len); } else sourceStr.Set(sUDPSourceStr.Ptr, sUDPSourceStr.Len); theErr = QTSS_SetValue (fRelaySessionObject, sSourceType, 0, (void*)sourceStr.Ptr, sourceStr.Len); Assert(theErr == QTSS_NoErr); char theIPAddrBuf[20]; StrPtrLen theIPAddr(theIPAddrBuf, 20); struct in_addr theSrcAddr; // source ip address theSrcAddr.s_addr = htonl(inInfo->GetStreamInfo(0)->fSrcIPAddr); SocketUtils::ConvertAddrToString(theSrcAddr, &theIPAddr); theErr = QTSS_SetValue (fRelaySessionObject, sSourceIPAddr, 0, (void*)theIPAddr.Ptr, theIPAddr.Len); Assert(theErr == QTSS_NoErr); struct in_addr theDestAddr; // dest (of source) ip address theDestAddr.s_addr = htonl(inInfo->GetStreamInfo(0)->fDestIPAddr); SocketUtils::ConvertAddrToString(theDestAddr, &theIPAddr); theErr = QTSS_SetValue (fRelaySessionObject, sSourceInIPAddr, 0, (void*)theIPAddr.Ptr, theIPAddr.Len); Assert(theErr == QTSS_NoErr); for (UInt32 index = 0; index < (inInfo->GetNumStreams()); index++) // source udp ports { UInt16 udpPort = inInfo->GetStreamInfo(index)->fPort; theErr = QTSS_SetValue (fRelaySessionObject, sSourceUDPPorts, index, &udpPort, sizeof(udpPort)); Assert(theErr == QTSS_NoErr); } if (inInfo->IsRTSPSourceInfo()) { RTSPSourceInfo* rtspInfo = (RTSPSourceInfo*)inInfo; if (!rtspInfo->IsAnnounce()) { UInt16 rtspPort = (UInt16) rtspInfo->GetHostPort(); char* username = rtspInfo->GetUsername(); char* password = rtspInfo->GetPassword(); theErr = QTSS_SetValue (fRelaySessionObject, sSourceRTSPPort, 0, &rtspPort, sizeof(rtspPort)); // source rtsp port Assert(theErr == QTSS_NoErr); theErr = QTSS_SetValue (fRelaySessionObject, sSourceUsername, 0, username, sizeof(username)); // source username Assert(theErr == QTSS_NoErr); theErr = QTSS_SetValue (fRelaySessionObject, sSourcePassword, 0, password, sizeof(password)); // source password Assert(theErr == QTSS_NoErr); } char* url = rtspInfo->GetSourceURL(); theErr = QTSS_SetValue (fRelaySessionObject, sSourceURL, 0, url, ::strlen(url)); Assert(theErr == QTSS_NoErr); // source url } UInt16 ttl = inInfo->GetStreamInfo(0)->fTimeToLive; theErr = QTSS_SetValue (fRelaySessionObject, sSourceTTL, 0, &ttl, sizeof(ttl)); // source ttl Assert(theErr == QTSS_NoErr); theErr = QTSS_UnlockObject(relayModuleAttributesObject); Assert(theErr == QTSS_NoErr); return QTSS_NoErr; }
RelayOutput::RelayOutput(SourceInfo* inInfo, UInt32 inWhichOutput, RelaySession* inRelaySession, Bool16 isRTSPSourceInfo) : fRelaySession(inRelaySession), fOutputSocket(NULL, Socket::kNonBlockingSocketType), fNumStreams(inRelaySession->GetSourceInfo()->GetNumStreams()), // use the reflector session's source info fOutputInfo(*inInfo->GetOutputInfo(inWhichOutput)), fQueueElem(), fFormatter(&fHTMLBuf[0], kMaxHTMLSize), fPacketsPerSecond(0), fBitsPerSecond(0), fLastUpdateTime(0), fTotalPacketsSent(0), fTotalBytesSent(0), fLastPackets(0), fLastBytes(0), fClientSocket(NULL), fClient(NULL), fDoingAnnounce(false), fValid(true), fOutgoingSDP(NULL), fAnnounceTask(NULL), fRTSPOutputInfo(NULL) { Assert(fNumStreams > 0); fQueueElem.SetEnclosingObject(this); fStreamCookieArray = NEW void*[fNumStreams]; fTrackIDArray = NEW UInt32[fNumStreams]; fOutputInfo.fPortArray = NEW UInt16[fNumStreams];//copy constructor doesn't do this ::memset(fOutputInfo.fPortArray, 0, fNumStreams * sizeof(UInt16)); // create a bookmark for each stream we'll reflect this->InititializeBookmarks(inRelaySession->GetNumStreams()); // Copy out all the track IDs for each stream for (UInt32 x = 0; x < fNumStreams; x++) { fTrackIDArray[x] = inRelaySession->GetSourceInfo()->GetStreamInfo(x)->fTrackID; fStreamCookieArray[x] = inRelaySession->GetStreamCookie(fTrackIDArray[x]); } // Copy the contents of the output port array if (inInfo->GetOutputInfo(inWhichOutput)->fPortArray != NULL) { UInt32 copySize = fNumStreams; if (fOutputInfo.fNumPorts < fNumStreams) copySize = fOutputInfo.fNumPorts; ::memcpy(fOutputInfo.fPortArray, inInfo->GetOutputInfo(inWhichOutput)->fPortArray, copySize * sizeof(UInt16)); } else if (fOutputInfo.fBasePort != 0) { for (UInt32 y = 0; y < fNumStreams; y++) fOutputInfo.fPortArray[y] = (UInt16)(fOutputInfo.fBasePort + (y * 2)); } OS_Error err = BindSocket(); if (err != OS_NoErr) { fValid = false; return; } RTSPOutputInfo* rtspInfo = NULL; if (isRTSPSourceInfo) { // in the case of the announce source info, the passed in source info will have the new // output information, but only the session's source info will have the sdp and url. RTSPSourceInfo* rtspSourceInfo = (RTSPSourceInfo *)(inInfo); Assert(rtspSourceInfo != NULL); RTSPSourceInfo* sessionSourceInfo = (RTSPSourceInfo *)(inRelaySession->GetSourceInfo()); Assert(sessionSourceInfo != NULL); rtspInfo = rtspSourceInfo->GetRTSPOutputInfo(inWhichOutput); if (rtspInfo->fIsAnnounced) { fRTSPOutputInfo = NEW RTSPOutputInfo(); fRTSPOutputInfo->Copy(*rtspInfo); fDoingAnnounce = true; // set up rtsp socket and client fClientSocket = new TCPClientSocket(Socket::kNonBlockingSocketType); fClient = new RTSPClient(fClientSocket, false, RelaySession::sRelayUserAgent); // set up the outgoing socket fClientSocket->Set(fOutputInfo.fDestAddr, rtspInfo->fAnnouncePort); int sndBufSize = 32 * 1024; int rcvBufSize = 1024; fClientSocket->SetOptions(sndBufSize, rcvBufSize); // set up the client object StrPtrLen url; if ((rtspInfo->fDestURl != NULL) && (strlen(rtspInfo->fDestURl) > 0)) url.Set(rtspInfo->fDestURl); else url.Set(sessionSourceInfo->GetSourceURL()); fClient->Set(url); fClient->SetTransportMode(RTSPClient::kPushMode); fClient->SetName(rtspInfo->fUserName); fClient->SetPassword(rtspInfo->fPassword); UInt32 len; fOutgoingSDP = sessionSourceInfo->GetAnnounceSDP(fOutputInfo.fDestAddr, &len); fAnnounceState = kSendingAnnounce; fCurrentSetup = 0; fAnnounceTask = new RelayAnnouncer(this); // this will now go and run the async announce fAnnounceTask->Signal(Task::kStartEvent); } } // Write the Output HTML // Looks like: Relaying to: 229.49.52.102, Ports: 16898 16900 Time to live: 15 static StrPtrLen sHTMLStart("Relaying to: "); static StrPtrLen sPorts(", Ports: "); static StrPtrLen sTimeToLive(" Time to live: "); static StrPtrLen sHTMLEnd("<BR>"); // First, format the destination addr as a dotted decimal string char theIPAddrBuf[20]; StrPtrLen theIPAddr(theIPAddrBuf, 20); struct in_addr theAddr; theAddr.s_addr = htonl(fOutputInfo.fDestAddr); SocketUtils::ConvertAddrToString(theAddr, &theIPAddr); // Begin writing the HTML fFormatter.Put(sHTMLStart); fFormatter.Put(theIPAddr); fFormatter.Put(sPorts); for (UInt32 y = 0; y < fNumStreams; y++) { // Write all the destination ports fFormatter.Put(fOutputInfo.fPortArray[y]); fFormatter.PutSpace(); } if (SocketUtils::IsMulticastIPAddr(inInfo->GetOutputInfo(inWhichOutput)->fDestAddr)) { // Put the time to live if this is a multicast destination fFormatter.Put(sTimeToLive); fFormatter.Put(fOutputInfo.fTimeToLive); } fFormatter.Put(sHTMLEnd); // Setup the StrPtrLen to point to the right stuff fOutputInfoHTML.Ptr = fFormatter.GetBufPtr(); fOutputInfoHTML.Len = fFormatter.GetCurrentOffset(); OSMutexLocker locker(&sQueueMutex); sRelayOutputQueue.EnQueue(&fQueueElem); SetupRelayOutputObject(rtspInfo); }
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; }
void UserAgentParser::Parse(StrPtrLen *inStream) { StrPtrLen tempID; StrPtrLen tempData; StringParser parser(inStream); StrPtrLen startFields; memset(&fFieldData, 0, sizeof(fFieldData)); parser.ConsumeUntil(&startFields, '('); // search for '(' if not found does nothing // parse through everything between the '(' and ')'. while (startFields.Len != 0) { //stop when we reach an empty line. tempID.Set(NULL, 0); tempData.Set(NULL, 0); parser.ConsumeLength(NULL, 1); // step past '(' or ';' if not found or at end of line does nothing parser.ConsumeWhitespace(); // search for non-white space if not found does nothing parser.ConsumeUntil(&tempID, sEOLWhitespaceEqualMask); // search for end of id (whitespace or =)if not found does nothing if (tempID.Len == 0) break; parser.ConsumeUntil(NULL, '='); // find the '=' parser.ConsumeLength(NULL, 1); // step past if not found or at end of line does nothing parser.ConsumeUntil(&tempData, sEOLSemicolonCloseParenMask); // search for end of data if not found does nothing if (tempData.Len == 0) break; StrPtrLen testID; UInt32 fieldID; for (short testField = 0; testField < UserAgentParser::eNumAttributes; testField++) { testID.Set(sFieldIDs[testField].fFieldName, sFieldIDs[testField].fLen); fieldID = sFieldIDs[testField].fID; if ((fFieldData[fieldID].fFound == false) && testID.Equal(tempID)) { fFieldData[fieldID].fData = tempData; fFieldData[fieldID].fFound = true; } } } // If we parsed the OS field but not the OSVer field then check and see if // the OS field contains the OS version. If it does copy it from there. // (e.g. 'os=Mac%209.2.2' or 'os=Windows%20NT%204.0'.) if (fFieldData[eOs].fFound && !fFieldData[eOsver].fFound) { UInt16 len = (UInt16)fFieldData[eOs].fData.Len; char* cp = (char*)fFieldData[eOs].fData.Ptr; // skip up to the blank space if it exists. // (i.e. the blank is URL encoded as '%20') while (*cp != '%') { len--; if (*cp == '\0' || len == 0) { // no blank space...so we're all done. return; } cp++; } // skip over the blank space. cp += 3; len -= 3; // the remaining string is the OS version. fFieldData[eOsver].fData.Set(cp, len); fFieldData[eOsver].fFound = true; // and truncate the version from the OS field. fFieldData[eOs].fData.Len -= len + 3; } }
QTSS_Error RTSPRequest::SendDigestChallenge(UInt32 qop, StrPtrLen *nonce, StrPtrLen* opaque) { QTSS_Error theErr = QTSS_NoErr; char challengeBuf[kAuthChallengeHeaderBufSize]; ResizeableStringFormatter challengeFormatter(challengeBuf, kAuthChallengeHeaderBufSize); StrPtrLen realm; char *prefRealmPtr = NULL; StrPtrLen *realmPtr = this->GetValue(qtssRTSPReqURLRealm); // Get auth realm set by the module if(realmPtr->Len > 0) { realm = *realmPtr; } else { // If module hasn't set the realm QTSServerInterface* theServer = QTSServerInterface::GetServer(); // get the realm from prefs prefRealmPtr = theServer->GetPrefs()->GetAuthorizationRealm(); // allocates memory Assert(prefRealmPtr != NULL); if (prefRealmPtr != NULL){ realm.Set(prefRealmPtr, strlen(prefRealmPtr)); } else { realm = sDefaultRealm; } } // Creating the Challenge header challengeFormatter.Put(sAuthDigestStr); // [Digest] challengeFormatter.PutSpace(); // [Digest ] challengeFormatter.Put(sRealmStr); // [Digest realm] challengeFormatter.Put(sEqualQuote); // [Digest realm="] challengeFormatter.Put(realm); // [Digest realm="somerealm] challengeFormatter.Put(sQuoteCommaSpace); // [Digest realm="somerealm", ] if(this->GetStale()) { challengeFormatter.Put(sStaleTrue); // [Digest realm="somerealm", stale="true", ] } challengeFormatter.Put(sNonceStr); // [Digest realm="somerealm", nonce] challengeFormatter.Put(sEqualQuote); // [Digest realm="somerealm", nonce="] challengeFormatter.Put(*nonce); // [Digest realm="somerealm", nonce="19723343a9fd75e019723343a9fd75e0] challengeFormatter.PutChar('"'); // [Digest realm="somerealm", nonce="19723343a9fd75e019723343a9fd75e0"] challengeFormatter.PutTerminator(); // [Digest realm="somerealm", nonce="19723343a9fd75e019723343a9fd75e0"\0] StrPtrLen challengePtr(challengeFormatter.GetBufPtr(), challengeFormatter.GetBytesWritten() - 1); this->SetValue(qtssRTSPReqDigestChallenge, 0, challengePtr.Ptr, challengePtr.Len, QTSSDictionary::kDontObeyReadOnly); RTSPSessionInterface* thisRTSPSession = this->GetSession(); if (thisRTSPSession) { (void)thisRTSPSession->SetValue(qtssRTSPSesLastDigestChallenge, 0, challengePtr.Ptr, challengePtr.Len,QTSSDictionary::kDontObeyReadOnly); } fStatus = qtssClientUnAuthorized; this->SetResponseKeepAlive(true); this->AppendHeader(qtssWWWAuthenticateHeader, &challengePtr); this->SendHeader(); // deleting the memory that was allocated in GetPrefs call above if (prefRealmPtr != NULL) { delete[] prefRealmPtr; } return theErr; }
QTSS_Error RTSPRequest::SendBasicChallenge(void) { QTSS_Error theErr = QTSS_NoErr; char *prefRealmPtr = NULL; do { char realmBuff[kRealmBuffSize] = "Basic realm=\""; StrPtrLen challenge(realmBuff); StrPtrLen whichRealm; // Get the module's realm StrPtrLen moduleRealm; theErr = this->GetValuePtr(qtssRTSPReqURLRealm, 0, (void **) &moduleRealm.Ptr, &moduleRealm.Len); if ( (QTSS_NoErr == theErr) && (moduleRealm.Len > 0) ) { whichRealm = moduleRealm; } else { theErr = QTSS_NoErr; // Get the default realm from the config file or use the static default if config realm is not found QTSServerInterface* theServer = QTSServerInterface::GetServer(); prefRealmPtr = theServer->GetPrefs()->GetAuthorizationRealm(); // allocates memory Assert(prefRealmPtr != NULL); if (prefRealmPtr != NULL) { whichRealm.Set(prefRealmPtr, strlen(prefRealmPtr)); } else { whichRealm = sDefaultRealm; } } int realmLen = whichRealm.Len + challenge.Len + 2; // add 2 based on double quote char + end of string 0x00 if (realmLen > kRealmBuffSize) // The realm is too big so use the default realm { Assert(0); whichRealm = sDefaultRealm; } memcpy(&challenge.Ptr[challenge.Len],whichRealm.Ptr,whichRealm.Len); int newLen = challenge.Len + whichRealm.Len; challenge.Ptr[newLen] = '"'; // add the terminating "" this was accounted for with the size check above challenge.Ptr[newLen + 1] = 0;// add the 0 terminator this was accounted for with the size check above challenge.Len = newLen +1; // set the real size of the string excluding the 0. #if (0) { // test code char test[256]; memcpy(test,sDefaultRealm.Ptr,sDefaultRealm.Len); test[sDefaultRealm.Len] = 0; qtss_printf("the static realm =%s \n",test); OSCharArrayDeleter prefDeleter(QTSServerInterface::GetServer()->GetPrefs()->GetAuthorizationRealm()); memcpy(test,prefDeleter.GetObject(),strlen(prefDeleter.GetObject())); test[strlen(prefDeleter.GetObject())] = 0; qtss_printf("the Pref realm =%s \n",test); memcpy(test,moduleRealm.Ptr,moduleRealm.Len); test[moduleRealm.Len] = 0; qtss_printf("the moduleRealm =%s \n",test); memcpy(test,whichRealm.Ptr,whichRealm.Len); test[whichRealm.Len] = 0; qtss_printf("the challenge realm =%s \n",test); memcpy(test,challenge.Ptr,challenge.Len); test[challenge.Len] = 0; qtss_printf("the challenge string =%s len = %"_S32BITARG_"\n",test, challenge.Len); } #endif fStatus = qtssClientUnAuthorized; this->SetResponseKeepAlive(true); this->AppendHeader(qtssWWWAuthenticateHeader, &challenge); this->SendHeader(); } while (false); if (prefRealmPtr != NULL) { delete[] prefRealmPtr; } return theErr; }
int RtspRequest::ParseRtspURI(StringParser &parser)//string& sRtspURI { //read in the complete URL, set it to be the qtssAbsoluteURLParam StrPtrLen theAbsURL; //StringParser parser(StrPtrLen((char*)sRtspURI.c_str())); // RTSPRequestInterface::sPathURLStopConditions stop on ? as well as sURLStopConditions parser.ConsumeUntil(&theAbsURL, sURLStopConditions ); // set qtssRTSPReqAbsoluteURL to the URL throught the path component; will be : <protocol>://<host-addr>/<path> //this->SetVal(qtssRTSPReqAbsoluteURL, &theAbsURL); StringParser urlParser(&theAbsURL); //we always should have a slash before the uri. //If not, that indicates this is a full URI. Also, this could be a '*' OPTIONS request if ((*theAbsURL.Ptr != '/') && (*theAbsURL.Ptr != '*')) { //if it is a full URL, store the host name off in a separate parameter StrPtrLen theRTSPString; urlParser.ConsumeLength(&theRTSPString, 7); //consume "rtsp://" //assign the host field here to the proper QTSS param StrPtrLen theHost; urlParser.ConsumeUntil(&theHost, '/'); //fHeaderDictionary.SetVal(qtssHostHeader, &theHost); ///save host } // don't allow non-aggregate operations indicated by a url/media track=id // might need this for rate adapt if (qtssSetupMethod != fMethod && qtssOptionsMethod != fMethod && qtssSetParameterMethod != fMethod) // any method not a setup, options, or setparameter is not allowed to have a "/trackID=" in the url. if (qtssSetupMethod != m_Method) // any method not a setup is not allowed to have a "/trackID=" in the url. { StrPtrLenDel tempCStr(theAbsURL.GetAsCString()); StrPtrLen nonaggregate(tempCStr.FindString("/trackID=")); if (nonaggregate.Len > 0) // check for non-aggregate method and return error return -1;//QTSSModuleUtils::SendErrorResponse(this, qtssClientAggregateOptionAllowed, qtssMsgBadRTSPMethod, &theAbsURL); } // In case there is no URI at all... we have to fake it. static char* sSlashURI = "/"; //whatever is in this position in the URL must be the URI. Store that //in the qtssURLParam. Confused? StrPtrLen theURLParam; UInt32 uriLen = urlParser.GetDataReceivedLen() - urlParser.GetDataParsedLen(); if (uriLen > 0) ///this->SetVal(qtssRTSPReqURI, urlParser.GetCurrentPosition(), urlParser.GetDataReceivedLen() - urlParser.GetDataParsedLen()); theURLParam.Set(urlParser.GetCurrentPosition(), urlParser.GetDataReceivedLen() - urlParser.GetDataParsedLen()); else // // This might happen if there is nothing after the host at all, not even // a '/'. This is legal (RFC 2326, Sec 3.2). If so, just pretend that there // is a '/' ///this->SetVal(qtssRTSPReqURI, sSlashURI, 1); theURLParam.Set(sSlashURI, 1); // parse the query string from the url if present. // init qtssRTSPReqQueryString dictionary to an empty string StrPtrLen queryString; ///this->SetVal(qtssRTSPReqQueryString, queryString.Ptr, queryString.Len); if ( parser.GetDataRemaining() > 0 ) { if ( parser.PeekFast() == '?' ) { // we've got some CGI param parser.ConsumeLength(&queryString, 1); // toss '?' // consume the rest of the line.. parser.ConsumeUntilWhitespace(&queryString); ///this->SetVal(qtssRTSPReqQueryString, queryString.Ptr, queryString.Len); } } // // If the is a '*', return right now because '*' is not a path // so the below functions don't make any sense. if ((*theAbsURL.Ptr == '*') && (theAbsURL.Len == 1)) { //this->SetValue(qtssRTSPReqFilePath, 0, theAbsURL.Ptr, theAbsURL.Len, QTSSDictionary::kDontObeyReadOnly); strncpy(m_sFilePath, theAbsURL.Ptr, theAbsURL.Len); return 0;//QTSS_NoErr; } //path strings are statically allocated. Therefore, if they are longer than //this length we won't be able to handle the request. //StrPtrLen* theURLParam = this->GetValue(qtssRTSPReqURI); if (theURLParam.Len > RTSP_FILE_PATH_LEN_MAX) return -1; //QTSSModuleUtils::SendErrorResponse(this, qtssClientBadRequest, qtssMsgURLTooLong, theURLParam); //decode the URL, put the result in the separate buffer for the file path, //set the file path StrPtrLen to the proper value SInt32 theBytesWritten = StringTranslator::DecodeURL(theURLParam.Ptr, theURLParam.Len, m_sFilePath, RTSP_FILE_PATH_LEN_MAX); //if negative, an error occurred, reported as an QTSS_Error //we also need to leave room for a terminator. if ((theBytesWritten < 0) || (theBytesWritten == RTSP_FILE_PATH_LEN_MAX)) { return -1;//QTSSModuleUtils::SendErrorResponse(this, qtssClientBadRequest, qtssMsgURLInBadFormat, theURLParam); } // Convert from a / delimited path to a local file system path ///StringTranslator::DecodePath(m_sFilePath, theBytesWritten); //setup the proper QTSS param m_sFilePath[theBytesWritten] = '\0'; //this->SetVal(qtssRTSPReqFilePath, fFilePath, theBytesWritten); //this->SetValue(qtssRTSPReqFilePath, 0, fFilePath, theBytesWritten, QTSSDictionary::kDontObeyReadOnly); if (qtssSetupMethod == m_Method) { StrPtrLen thePathPtr(m_sFilePath); char *trackStr = thePathPtr.FindString("/trackID="); if (trackStr != NULL && *trackStr != 0) { *trackStr = 0; // terminate the string. //thePathPtr.Len = ::strlen(thePathPtr.Ptr); } } return 0;//QTSS_NoErr; }