void CEsperEngine::MsgGetStatus (const SArchonMessage &Msg, const CHexeSecurityCtx *pSecurityCtx) // MsgGetStatus // // Arc.getStatus { // Ask the connections for a status CEsperConnection::SStatus Status; m_Connections.GetStatus(&Status); // Compose into a struct CComplexStruct *pResult = new CComplexStruct; pResult->SetElement(CString("Esper/connectionActive"), CDatum(Status.iActive)); pResult->SetElement(CString("Esper/connectionCount"), CDatum(Status.iTotalObjects)); pResult->SetElement(CString("Esper/connectionsIdle"), CDatum(Status.iIdle)); pResult->SetElement(CString("Esper/connectionsReading"), CDatum(Status.iWaitingForRead)); pResult->SetElement(CString("Esper/connectionsWriting"), CDatum(Status.iWaitingForWrite)); // Done m_pProcess->SendMessageReply(MSG_REPLY_DATA, CDatum(pResult), Msg); }
CDatum CHyperionScheduler::GetTaskList (void) // GetTaskList // // Returns a list of tasks { CSmartLock Lock(m_cs); int i; CComplexArray *pResult = new CComplexArray; for (i = 0; i < m_Tasks.GetCount(); i++) { CComplexStruct *pTask = new CComplexStruct; pTask->SetElement(FIELD_NAME, m_Tasks[i].sName); pTask->SetElement(FIELD_STATUS, (m_Tasks[i].bRunning ? STATUS_RUNNING : STATUS_READY)); pTask->SetElement(FIELD_LAST_RAN_ON, m_Tasks[i].LastRun); pTask->SetElement(FIELD_WILL_RUN_ON, m_Tasks[i].NextRun); pTask->SetElement(FIELD_RUN_FREQUENCY, m_Tasks[i].iInterval); pResult->Append(CDatum(pTask)); } return CDatum(pResult); }
void CAeonView::CreateSecondaryData (const CTableDimensions &PrimaryDims, const CRowKey &PrimaryKey, CDatum dFullData, SEQUENCENUMBER RowID, CDatum *retdData) // CreateSecondaryData // // Creates the data for a secondary view row. { int i, j; CComplexStruct *pData = new CComplexStruct; // If the list of columns is empty then we just add the primary key if (m_Columns.GetCount() == 0) pData->SetElement(FIELD_PRIMARY_KEY, PrimaryKey.AsDatum(PrimaryDims)); // Otherwise we add all the fields listed in the columns array else { for (i = 0; i < m_Columns.GetCount(); i++) { // The special string "primaryKey" means that we insert the // primary key as a special field. if (strEquals(m_Columns[i], FIELD_PRIMARY_KEY)) pData->SetElement(FIELD_PRIMARY_KEY, PrimaryKey.AsDatum(PrimaryDims)); // The special string "*" means that we insert all existing // fields. else if (strEquals(m_Columns[i], STR_ALL_COLUMNS)) { for (j = 0; j < dFullData.GetCount(); j++) { CDatum dKey = dFullData.GetKey(j); CDatum dValue = dFullData.GetElement(j); if (!dValue.IsNil()) pData->SetElement(dKey, dValue); } } // Add the field by name. else { CDatum dColData = dFullData.GetElement(m_Columns[i]); if (!dColData.IsNil()) pData->SetElement(m_Columns[i], dColData); } } } // Done *retdData = CDatum(pData); }
CDatum CAeonView::DebugDump (void) const // DebugDump // // Returns data about the view. { int i; CComplexStruct *pData = new CComplexStruct; pData->SetElement(FIELD_RECOVERY_FILESPEC, m_Recovery.GetFilespec()); CComplexArray *pSegments = new CComplexArray; for (i = 0; i < m_Segments.GetCount(); i++) pSegments->Append(m_Segments[i]->DebugDump()); pData->SetElement(FIELD_SEGMENTS, CDatum(pSegments)); return CDatum(pData); }
bool CUserInfoSession::UpdateLoginFailure (void) // UpdateLoginFailure // // Update the user record with the most recent failure { // Set our state m_iState = stateWaitingForFailureUpdate; // Mutate the record to set the login date CComplexStruct *pRecord = new CComplexStruct; pRecord->SetElement(FIELD_LOGIN_FAILURE_COUNT, CDatum((int)1)); CComplexStruct *pMutation = new CComplexStruct; pMutation->SetElement(FIELD_LAST_LOGIN_FAILURE_ON, MUTATE_DATE_MODIFIED); pMutation->SetElement(FIELD_LOGIN_FAILURE_COUNT, MUTATE_INCREMENT); // Create a payload CComplexArray *pPayload = new CComplexArray; pPayload->Insert(USERS_TABLE_NAME); pPayload->Insert(m_sUsernameKey); pPayload->Insert(CDatum(pRecord)); pPayload->Insert(CDatum(pMutation)); // Send message ISessionHandler::SendMessageCommand(ADDRESS_AEON_COMMAND, MSG_AEON_MUTATE, GenerateAddress(PORT_CRYPTOSAUR_COMMAND), CDatum(pPayload), MESSAGE_TIMEOUT); // Expect reply return true; }
void CMnemosynthDb::GenerateEndpointList (CDatum *retdList) // GenerateEndpointList // // Returns data about all endpoints { CSmartLock Lock(m_cs); int i; CComplexArray *pList = new CComplexArray; for (i = 0; i < m_Endpoints.GetCount(); i++) { CComplexStruct *pData = new CComplexStruct; pData->SetElement(FIELD_ID, m_Endpoints[i].sName); pData->SetElement(FIELD_SEQ_RECV, m_Endpoints[i].dwSeqRecv); pData->SetElement(FIELD_SEQ_SENT, m_Endpoints[i].dwSeqSent); pList->Append(CDatum(pData)); } *retdList = CDatum(pList); }
CDatum CUserInfoSession::CreateSanitizedUserRecord (CDatum dRecord) // CreateSanitizedUserRecord // // Creates a user record suitable for returning to clients. In partincular, // we remove the authentication information. { int i; // Create a destination CComplexStruct *pDest = new CComplexStruct; // Copy all appropriate fields for (i = 0; i < dRecord.GetCount(); i++) { // If this is an auth field, then skip it if (strEquals(dRecord.GetKey(i), FIELD_AUTH_DESC)) ; else if (strEndsWith(dRecord.GetKey(i), FIELD_AUTH_DESC_SUFFIX)) ; // Otherwise, copy it else pDest->SetElement(dRecord.GetKey(i), dRecord.GetElement(i)); } // Done return CDatum(pDest); }
void CMnemosynthDb::GenerateDelta (TArray<SMnemosynthUpdate> *retUpdates, CDatum *retdLocalUpdates) // GenerateDelta // // Generates a list of changes since the last time we called this { CSmartLock Lock(m_cs); int i, j; // Edge conditions if (m_Endpoints.GetCount() == 0) { *retdLocalUpdates = CDatum(); return; } // If we are not the central module, then we only need to // generate a list of updates made by our own endpoint // (and send it to our central module). if (!m_pProcess->IsCentralModule()) { if (GetLocalEndpoint().dwSeqRecv > GetLocalEndpoint().dwSeqSent) { SMnemosynthUpdate *pUpdate = retUpdates->Insert(); pUpdate->sDestEndpoint = strPattern("%s/CentralModule", m_pProcess->GetMachineName()); // Generate a payload for our updates CComplexArray *pEntries = new CComplexArray; for (i = 0; i < m_Collections.GetCount(); i++) { const CString &sCollection = m_Collections.GetKey(i); SCollection *pCollection = &m_Collections[i]; for (j = 0; j < pCollection->Entries.GetCount(); j++) { SEntry *pEntry = &pCollection->Entries[j]; if (pEntry->dwOwnerID == 0 && pEntry->dwSequence > GetLocalEndpoint().dwSeqSent) { CDatum dEntry = GenerateEntry(i, pCollection->Entries.GetKey(j), pEntry); pEntries->Insert(dEntry); // If this entry is Nil then we can deleted. (We don't // need it as a deletion stub since we just composed // the update. If this message gets lost we need to // resend everything). if (pCollection->Entries.GetValue(j).dValue.IsNil()) { pCollection->Entries.Delete(j); j--; } } } } // Create the payload CComplexStruct *pPayload = new CComplexStruct; pPayload->SetElement(STR_COLLECTIONS, GenerateCollectionsArray()); pPayload->SetElement(STR_ENDPOINT, GetLocalEndpoint().sName); pPayload->SetElement(STR_ENTRIES, CDatum(pEntries)); pPayload->SetElement(FIELD_PROCESS_ID, CDatum(GetLocalEndpoint().dwProcessID)); // Add it CDatum dLocalUpdates = CDatum(pPayload); pUpdate->Payloads.Insert(dLocalUpdates); // Return it *retdLocalUpdates = dLocalUpdates; } else *retdLocalUpdates = CDatum(); } // Otherwise, loop over all endpoints and generate a different // update entry for each one that we need to handle else { bool bFullUpdateNeeded = false; for (i = 1; i < m_Endpoints.GetCount(); i++) if (m_Endpoints[i].bFullUpdate) { bFullUpdateNeeded = true; break; } // Collections CDatum dCollections = GenerateCollectionsArray(); // We end up creating one or two arrays of deltas. The first // array has all the changes since we last generated a delta // (this is used for endpoints that we updated last time). // // The second array has a full set of data (this is for new // endpoints). TArray<CComplexArray *> UpdateEntries; TArray<CComplexArray *> FullEntries; TArray<CDatum> UpdatePayloads; TArray<CDatum> FullPayloads; UpdateEntries.InsertEmpty(m_Endpoints.GetCount()); UpdatePayloads.InsertEmpty(m_Endpoints.GetCount()); if (bFullUpdateNeeded) { FullEntries.InsertEmpty(m_Endpoints.GetCount()); FullPayloads.InsertEmpty(m_Endpoints.GetCount()); } for (i = 0; i < m_Endpoints.GetCount(); i++) { UpdateEntries[i] = new CComplexArray; CComplexStruct *pStruct = new CComplexStruct; pStruct->SetElement(STR_COLLECTIONS, dCollections); pStruct->SetElement(STR_ENDPOINT, m_Endpoints[i].sName); pStruct->SetElement(STR_ENTRIES, CDatum(UpdateEntries[i])); pStruct->SetElement(FIELD_PROCESS_ID, CDatum(m_Endpoints[i].dwProcessID)); UpdatePayloads[i] = CDatum(pStruct); if (bFullUpdateNeeded) { FullEntries[i] = new CComplexArray; pStruct = new CComplexStruct; pStruct->SetElement(STR_COLLECTIONS, dCollections); pStruct->SetElement(STR_ENDPOINT, m_Endpoints[i].sName); pStruct->SetElement(STR_ENTRIES, CDatum(FullEntries[i])); pStruct->SetElement(FIELD_PROCESS_ID, CDatum(m_Endpoints[i].dwProcessID)); FullPayloads[i] = CDatum(pStruct); } } // Loop over all entries in the database and add them to the // appropriate payload arrays for (i = 0; i < m_Collections.GetCount(); i++) { const CString &sCollection = m_Collections.GetKey(i); SCollection *pCollection = &m_Collections[i]; for (j = 0; j < pCollection->Entries.GetCount(); j++) { SEntry *pEntry = &pCollection->Entries[j]; // Get the endpoint for the owner of this collection int iOwner = FindEndpointIndex(pEntry->dwOwnerID); if (iOwner == -1) continue; // Add to the update array if (pEntry->dwSequence > m_Endpoints[iOwner].dwSeqSent) { CDatum dEntry = GenerateEntry(i, pCollection->Entries.GetKey(j), pEntry); UpdateEntries[iOwner]->Insert(dEntry); #ifdef DEBUG_MNEMOSYNTH printf("[CMnemosynthDb::GenerateDelta]: Endpoint %s %x\n", (LPSTR)m_Endpoints[iOwner].sName, m_Endpoints[iOwner].dwSeqSent); #endif } // Add to full array, if necessary if (bFullUpdateNeeded) { // Don't bother inserting Nil entries (since this is a full // update). if (!pEntry->dValue.IsNil()) { CDatum dEntry = GenerateEntry(i, pCollection->Entries.GetKey(j), pEntry); FullEntries[iOwner]->Insert(dEntry); } } // If this entry is Nil then we can deleted. (We don't // need it as a deletion stub since we just composed // the update. If this message gets lost we need to // resend everything). if (pEntry->dValue.IsNil()) { pCollection->Entries.Delete(j); j--; } } } // Now iterate over all destination endpoints for (i = 1; i < m_Endpoints.GetCount(); i++) { SEndpoint *pDestEndpoint = &m_Endpoints[i]; #ifdef DEBUG_MNEMOSYNTH printf("[CMnemosynthDb::GenerateDelta]: Composing for endpoint %s %s%s.\n", (LPSTR)pDestEndpoint->sName, (pDestEndpoint->bCentralModule ? "CentralModule " : ""), (pDestEndpoint->bLocalMachine ? "local" : "")); #endif // If this is a local module, then send it any updates // for everything except itself if (pDestEndpoint->bLocalMachine && !pDestEndpoint->bCentralModule) { SMnemosynthUpdate *pUpdate = NULL; for (j = 0; j < m_Endpoints.GetCount(); j++) if (i != j) { // If we have no update entries, then skip. if (!pDestEndpoint->bFullUpdate && UpdatePayloads[j].GetElement(STR_ENTRIES).GetCount() == 0) continue; // Add an update entry if (pUpdate == NULL) { pUpdate = retUpdates->Insert(); pUpdate->sDestEndpoint = pDestEndpoint->sName; } if (pDestEndpoint->bFullUpdate) pUpdate->Payloads.Insert(FullPayloads[j]); else pUpdate->Payloads.Insert(UpdatePayloads[j]); } } // Otherwise, if this is a foreign central module, then // send it any updates for all local endpoints else if (pDestEndpoint->bCentralModule && !pDestEndpoint->bLocalMachine) { SMnemosynthUpdate *pUpdate = NULL; #ifdef DEBUG_MNEMOSYNTH if (pDestEndpoint->bFullUpdate) printf("[CMnemosynthDb::GenerateDelta]: Composing FULL update for %s\n", (LPSTR)pDestEndpoint->sName); else printf("[CMnemosynthDb::GenerateDelta]: Composing DIFF update for %s\n", (LPSTR)pDestEndpoint->sName); #endif for (j = 0; j < m_Endpoints.GetCount(); j++) if (m_Endpoints[j].bLocalMachine) { // If we have no update entries, then skip. if (!pDestEndpoint->bFullUpdate && UpdatePayloads[j].GetElement(STR_ENTRIES).GetCount() == 0) continue; #ifdef DEBUG_MNEMOSYNTH printf("[CMnemosynthDb::GenerateDelta]: Updates from %s\n", (LPSTR)m_Endpoints[j].sName); #endif // Add an update entry if (pUpdate == NULL) { pUpdate = retUpdates->Insert(); pUpdate->sDestEndpoint = pDestEndpoint->sName; } if (pDestEndpoint->bFullUpdate) pUpdate->Payloads.Insert(FullPayloads[j]); else pUpdate->Payloads.Insert(UpdatePayloads[j]); } } } // Local updates *retdLocalUpdates = UpdatePayloads[0]; } // Reset for (i = 0; i < m_Endpoints.GetCount(); i++) { m_Endpoints[i].dwSeqSent = m_Endpoints[i].dwSeqRecv; m_Endpoints[i].bFullUpdate = false; } m_ModifiedEvent.Reset(); }
bool CUserInfoSession::OnProcessMessage (const SArchonMessage &Msg) // OnProcessMessage // // We received a reply from Aeon { int i; // If this is an error, then we return the error back to the client if (IsError(Msg)) { SendMessageReplyError(MSG_ERROR_UNABLE_TO_COMPLY, Msg.dPayload); return false; } // If we're waiting for the user record, then see if we can process it now. if (m_iState == stateWaitingForUserRecord) { // Cryptosaur.getUser if (strEquals(GetOriginalMsg().sMsg, MSG_CRYPTOSAUR_GET_USER)) { CDatum dUserData = Msg.dPayload; // If the user does not exist, then we return Nil if (dUserData.IsNil()) { SendMessageReply(MSG_REPLY_DATA, CDatum()); return false; } // Generate a sanitized user record CComplexStruct *pReply = new CComplexStruct; pReply->SetElement(FIELD_USERNAME, dUserData.GetElement(FIELD_USERNAME)); // Sanitize rights CDatum dRights = dUserData.GetElement(FIELD_RIGHTS); if (!m_sScope.IsEmpty()) { CComplexArray *pRights = new CComplexArray; for (i = 0; i < dRights.GetCount(); i++) if (strStartsWith(dRights.GetElement(i), m_sScope)) pRights->Insert(dRights.GetElement(i)); pReply->SetElement(FIELD_RIGHTS, CDatum(pRights)); } else pReply->SetElement(FIELD_RIGHTS, dRights); // Done SendMessageReply(MSG_REPLY_DATA, CDatum(pReply)); return false; } // If we get back nil then the user does not exist. else if (Msg.dPayload.IsNil()) { SendMessageReplyError(MSG_ERROR_DOES_NOT_EXIST, strPattern(ERR_UNKNOWN_USERNAME, m_sUsername)); return false; } // Otherwise, we handle the result based on the original message else if (strEquals(GetOriginalMsg().sMsg, MSG_CRYPTOSAUR_CHECK_PASSWORD_SHA1)) { // Get the parameters from the original message CDatum dChallenge = GetOriginalMsg().dPayload.GetElement(1); CDatum dResponse = GetOriginalMsg().dPayload.GetElement(2); // Get the password has from the response CDatum dAuthDesc = Msg.dPayload.GetElement(FIELD_AUTH_DESC); CDatum dPasswordHash = dAuthDesc.GetElement(FIELD_CREDENTIALS); // Create a response to the challenge based on the password hash that // we have stored. CDatum dCorrect = CAI1Protocol::CreateSHAPasswordChallengeResponse(dPasswordHash, dChallenge); // Compare the correct response to the actual if ((const CIPInteger &)dResponse == (const CIPInteger &)dCorrect) return UpdateLoginSuccess(stateWaitingForSuccessUpdate); else return UpdateLoginFailure(); } // Cryptosaur.hasRights else if (strEquals(GetOriginalMsg().sMsg, MSG_CRYPTOSAUR_HAS_RIGHTS)) { CDatum dRights = Msg.dPayload.GetElement(FIELD_RIGHTS); CDatum dRightsRequired = m_dPayload.GetElement(1); // Get the rights from the user CAttributeList Rights; dRights.AsAttributeList(&Rights); // Check for (i = 0; i < dRightsRequired.GetCount(); i++) { if (!Rights.HasAttribute(dRightsRequired.GetElement(i))) { SendMessageReply(MSG_REPLY_DATA, CDatum()); return false; } } // We have all rights SendMessageReply(MSG_REPLY_DATA, CDatum(CDatum::constTrue)); return false; } // Cryptosaur.loginUser else if (strEquals(GetOriginalMsg().sMsg, MSG_CRYPTOSAUR_LOGIN_USER)) { // Get the parameters from the original message CDatum dRequestAuthDesc = GetOriginalMsg().dPayload.GetElement(1); CDatum dCredentials = dRequestAuthDesc.GetElement(FIELD_CREDENTIALS); CDatum dChallengeCredentials = dRequestAuthDesc.GetElement(FIELD_CHALLENGE_CREDENTIALS); CDatum dPassword = dRequestAuthDesc.GetElement(FIELD_PASSWORD); m_bActual = !dRequestAuthDesc.GetElement(FIELD_ACTUAL).IsNil(); if (!dRequestAuthDesc.GetElement(FIELD_AUTH_TOKEN_INFINITE).IsNil()) m_dwAuthTokenLifetime = 0; else { m_dwAuthTokenLifetime = (DWORD)(int)dRequestAuthDesc.GetElement(FIELD_AUTH_TOKEN_LIFETIME); if (m_dwAuthTokenLifetime == 0) m_dwAuthTokenLifetime = DEFAULT_AUTH_TOKEN_TIMEOUT; } // If we're not actual and have no scope, then we can't continue if (!m_bActual && m_sScope.IsEmpty()) { SendMessageReplyError(MSG_ERROR_UNABLE_TO_COMPLY, ERR_SCOPE_REQUIRED); return false; } // User data CDatum dUserData = Msg.dPayload; CDatum dAuthDesc; if (m_bActual) dAuthDesc = dUserData.GetElement(FIELD_AUTH_DESC); else dAuthDesc = dUserData.GetElement(strPattern("%s%s", m_sScope, FIELD_AUTH_DESC)); // If we have no authdesc, then we can't continue. This is likely // because the client is in a sandbox that the user has not registered // with. We treat it the same as a username/password failure. if (dAuthDesc.IsNil()) { SendMessageReplyError(MSG_ERROR_DOES_NOT_EXIST, ERR_INVALID_USERNAME_OR_PASSWORD); return false; } // If we've failed more than 5 consecutive times, we may need to delay // the next login attempt. if ((int)dUserData.GetElement(FIELD_LOGIN_FAILURE_COUNT) > MAX_LOGIN_ATTEMPTS) { CDateTime LastLoginFailure = dUserData.GetElement(FIELD_LAST_LOGIN_FAILURE_ON); CTimeSpan TimeSinceLastFailure = timeSpan(LastLoginFailure, CDateTime(CDateTime::Now)); // If it has not been at least 1 hour, we return an error. if (TimeSinceLastFailure.Days() == 0 && TimeSinceLastFailure.Seconds() < LOGIN_TIMEOUT) { // Timeout SendMessageReplyError(MSG_ERROR_DOES_NOT_EXIST, ERR_FAILURE_TIMEOUT); return false; } } // If we have straight credentials, then just compare bool bSuccess; if (!dCredentials.IsNil()) bSuccess = ((const CIPInteger &)dCredentials == (const CIPInteger &)dAuthDesc.GetElement(FIELD_CREDENTIALS)); // Otherwise, we compare against the challenge else if (!dChallengeCredentials.IsNil()) { // Get the challenge. If not provided then we get it from the user // record. CDatum dChallenge = GetOriginalMsg().dPayload.GetElement(2); if (dChallenge.IsNil()) { // Get the expiration time of the challenge const CDateTime &Expires = dAuthDesc.GetElement(FIELD_CHALLENGE_EXPIRATION); if (Expires < CDateTime(CDateTime::Now)) { SendMessageReplyError(MSG_ERROR_DOES_NOT_EXIST, ERR_INVALID_USERNAME_OR_PASSWORD); return false; } dChallenge = dAuthDesc.GetElement(FIELD_CHALLENGE); } // Create a response to the challenge based on the password hash that // we have stored. CDatum dCorrectChallenge = CAI1Protocol::CreateSHAPasswordChallengeResponse( dAuthDesc.GetElement(FIELD_CREDENTIALS), dChallenge ); bSuccess = ((const CIPInteger &)dChallengeCredentials == (const CIPInteger &)dCorrectChallenge); } // Otherwise we expect a clear text password else if (!dPassword.IsNil()) { // We have to hash the password to compare with credentials. CIPInteger Credentials; CCryptosaurInterface::CreateCredentials(dUserData.GetElement(FIELD_USERNAME), dPassword, &Credentials); // Compare bSuccess = (Credentials == (const CIPInteger &)dAuthDesc.GetElement(FIELD_CREDENTIALS)); } else bSuccess = false; // Success or failure if (bSuccess) return UpdateLoginSuccess(stateWaitingForCredentials); else return UpdateLoginFailure(); } // Can never get here. else { ASSERT(false); return false; } } // Otherwise, if we're waiting for the user record update, then continue else if (m_iState == stateWaitingForSuccessUpdate) { // Since we succeeded, we send the user sanitized user record back. SendMessageReply(MSG_REPLY_DATA, CreateSanitizedUserRecord(Msg.dPayload)); return false; } // If we're waiting for credentials, compose them else if (m_iState == stateWaitingForCredentials) { // The mutation returns the full record CDatum dUserData = Msg.dPayload; // Compute the result CComplexStruct *pAuthToken = new CComplexStruct; pAuthToken->SetElement(FIELD_USERNAME, dUserData.GetElement(FIELD_USERNAME)); pAuthToken->SetElement(FIELD_RIGHTS, dUserData.GetElement(FIELD_RIGHTS)); if (!m_bActual) pAuthToken->SetElement(FIELD_SCOPE, m_sScope); CDatum dAuthToken = m_pEngine->GenerateAuthToken(CDatum(pAuthToken), m_dwAuthTokenLifetime); // Compose a basic user record CComplexStruct *pReply = new CComplexStruct; pReply->SetElement(FIELD_AUTH_TOKEN, dAuthToken); pReply->SetElement(FIELD_RIGHTS, dUserData.GetElement(FIELD_RIGHTS)); pReply->SetElement(FIELD_USERNAME, dUserData.GetElement(FIELD_USERNAME)); // Send the reply SendMessageReply(MSG_REPLY_DATA, CDatum(pReply)); // Done return false; } // Otherwise, failure else if (m_iState == stateWaitingForFailureUpdate) { CDatum dUserData = Msg.dPayload; // If we've exceeded our limit, log it int iAttempts = (int)dUserData.GetElement(FIELD_LOGIN_FAILURE_COUNT); if (iAttempts > MAX_LOGIN_ATTEMPTS) GetProcessCtx()->Log(MSG_LOG_INFO, strPattern(ERR_USERNAME_TIMEOUT, m_sUsername, iAttempts)); // Send a failure SendMessageReplyError(MSG_ERROR_DOES_NOT_EXIST, ERR_INVALID_USERNAME_OR_PASSWORD); return false; } // Can never get here else { ASSERT(false); return false; } }
void CExarchEngine::MsgAddModule (const SArchonMessage &Msg, const CHexeSecurityCtx *pSecurityCtx) // MsgAddModule // // Exarch.addModule [{machineName}] {filePath} [{debug}] { CSmartLock Lock(m_cs); CString sError; // Must be admin service if (!ValidateSandboxAdmin(Msg, pSecurityCtx)) return; // Get parameters bool bHasMachineName = (Msg.dPayload.GetCount() >= 2 && !strEndsWith(strToLower(Msg.dPayload.GetElement(0)), STR_EXE_SUFFIX)); int iArg = 0; CString sMachineName = (bHasMachineName ? Msg.dPayload.GetElement(iArg++) : NULL_STR); CString sModuleFilePath = Msg.dPayload.GetElement(iArg++); CDatum dDebug = Msg.dPayload.GetElement(iArg++); // If we have a machine name, try to parse it in case the user gave us // a partial name. if (bHasMachineName) { if (!ParseMachineName(sMachineName, &sMachineName)) { SendMessageReplyError(MSG_ERROR_UNABLE_TO_COMPLY, strPattern("Unknown machine: %s", sMachineName), Msg); return; } } // If this is not for our machine, then we need to send a message to the // other machine. if (!sMachineName.IsEmpty() && !strEqualsNoCase(GetMachineName(), sMachineName)) { CString sAddress = GenerateMachineAddress(sMachineName, ADDRESS_EXARCH_COMMAND); if (sAddress.IsEmpty()) { SendMessageReplyError(MSG_ERROR_UNABLE_TO_COMPLY, strPattern("Unable to generate address for: %s", sMachineName), Msg); return; } StartSession(Msg, new CAddModuleSession(this, sAddress, sModuleFilePath)); } // Otherwise, we add a local module else { // Add the module CString sModuleName; if (!AddModule(sModuleFilePath, strEqualsNoCase(dDebug, FIELD_DEBUG), &sModuleName, &sError)) { SendMessageReplyError(MSG_ERROR_UNABLE_TO_COMPLY, sError, Msg); return; } // Add it to our list of modules CComplexArray *pModuleList = new CComplexArray(m_dMachineConfig.GetElement(FIELD_MODULES)); pModuleList->Append(CDatum(sModuleName)); CComplexStruct *pConfig = new CComplexStruct(m_dMachineConfig); pConfig->SetElement(FIELD_MODULES, CDatum(pModuleList)); m_dMachineConfig = CDatum(pConfig); // Save it WriteConfig(); // Done SendMessageReply(MSG_OK, CDatum(), Msg); } }
bool CAeonInterface::ParseFilePath (const CString &sFilePath, const CString &sRoot, int iOffset, const CDateTime &IfModifiedAfter, CString *retsAddr, CString *retsMsg, CDatum *retdPayload) // ParseFilePath // // Parses a filePath of the form: // // @Aeon.command/Arc.services/TransPackage.ars // /Arc.services/TransPackage.ars // ./TransPackage.ars // // Returns FALSE if error. { char *pPos = sFilePath.GetParsePointer(); char *pPosEnd = pPos + sFilePath.GetLength(); // Create a fileDownloadDesc to specify that we not read more than 100K // at a time (so that we don't overload our IPC buffer). CComplexStruct *pFDDesc = new CComplexStruct; pFDDesc->SetElement(FIELD_PARTIAL_MAX_SIZE, 100000); pFDDesc->SetElement(FIELD_PARTIAL_POS, iOffset); if (IfModifiedAfter.IsValid()) pFDDesc->SetElement(FIELD_IF_MODIFIED_AFTER, IfModifiedAfter); CDatum dFileDownloadDesc(pFDDesc); // If the path starts with @ then this is an absolute path CString sParsedPath; if (*pPos == '@') { // LATER return false; } // Is this a service namespace? else if (*pPos == '#') { CString sNamespace; if (!CTranspaceInterface::ParseAddress(sFilePath, &sNamespace)) return false; // Compose a proper download command payload CComplexArray *pPayload = new CComplexArray; pPayload->Append(sFilePath); pPayload->Append(sFilePath); pPayload->Append(dFileDownloadDesc); CDatum dPayload(pPayload); // Parse the service endpoint CString sService(sNamespace.GetParsePointer() + 1); // Encode into the proper payload CComplexArray *pPayload2 = new CComplexArray; pPayload2->Append(sService); pPayload2->Append(MSG_TRANSPACE_DOWNLOAD); pPayload2->Append(dPayload); // Done *retsAddr = ADDRESS_HYPERION_COMMAND; *retsMsg = MSG_HYPERION_SERVICE_MSG; *retdPayload = CDatum(pPayload2); return true; } // If it starts with a slash then it is an Aeon path else if (*pPos == '/') { sParsedPath = sFilePath; *retsAddr = ADDR_AEON; *retsMsg = MSG_AEON_FILE_DOWNLOAD; // Generate a message for Aeon to load the file CComplexArray *pPayload = new CComplexArray; pPayload->Insert(sParsedPath); pPayload->Insert(dFileDownloadDesc); // Done *retdPayload = CDatum(pPayload); } // If it starts with a ./ then this is a relative path else if (*pPos == '.') { pPos++; if (pPos == pPosEnd || *pPos != '/') return false; // Root must be valid if (sRoot.IsEmpty()) return false; // If the root already ends in '/' then skip. if (*(sRoot.GetParsePointer() + sRoot.GetLength() - 1) == '/') pPos++; sParsedPath = sRoot + CString(pPos); *retsAddr = ADDR_AEON; *retsMsg = MSG_AEON_FILE_DOWNLOAD; // Generate a message for Aeon to load the file CComplexArray *pPayload = new CComplexArray; pPayload->Insert(sParsedPath); pPayload->Insert(dFileDownloadDesc); // Done *retdPayload = CDatum(pPayload); } // Otherwise this is a relative path. else { // Root must be valid if (sRoot.IsEmpty()) return false; // Add '/' separator if (*(sRoot.GetParsePointer() + sRoot.GetLength() - 1) == '/') sParsedPath = sRoot + sFilePath; else sParsedPath = sRoot + SEPARATOR_SLASH, sFilePath; *retsAddr = ADDR_AEON; *retsMsg = MSG_AEON_FILE_DOWNLOAD; // Generate a message for Aeon to load the file CComplexArray *pPayload = new CComplexArray; pPayload->Insert(sParsedPath); pPayload->Insert(dFileDownloadDesc); // Done *retdPayload = CDatum(pPayload); } return true; }