Beispiel #1
0
void CSpaceObject::UpdateTradeExtended (const CTimeSpan &ExtraTime)

//	UpdateTradeExtended
//
//	Update trade after a long time.

	{
	//	Refresh inventory, if necessary

	CTradingDesc *pTradeOverride = GetTradeDescOverride();
	CDesignType *pType = GetType();
	CTradingDesc *pTrade = (pType ? pType->GetTradingDesc() : NULL);
	if ((pTrade || pTradeOverride) && ExtraTime.Days() > 0 && !IsAbandoned())
		{
		//	Compute the percent of the inventory that need to refresh

		int iRefreshPercent;
		if (ExtraTime.Days() >= DAYS_TO_REFRESH_INVENTORY)
			iRefreshPercent = 100;
		else
			iRefreshPercent = 100 * ExtraTime.Days() / DAYS_TO_REFRESH_INVENTORY;

		//	Do it

		if (pTradeOverride)
			pTradeOverride->RefreshInventory(this, iRefreshPercent);

		if (pTrade)
			pTrade->RefreshInventory(this, iRefreshPercent);
		}
	}
Beispiel #2
0
const CTimeSpan operator- (const CTimeSpan &op1, const CTimeSpan &op2)

//	Operator -
//
//	Subtract op2 from op1 (op1 must be greater than op2)

	{
	LONGLONG time1 = (op1.Days() * SECONDS_PER_DAY * 1000) + op1.Milliseconds();
	LONGLONG time2 = (op2.Days() * SECONDS_PER_DAY * 1000) + op2.Milliseconds();
	LONGLONG result = (time1 >= time2 ? time1 - time2 : time2 - time1);

	return CTimeSpan((int)(result / (SECONDS_PER_DAY * 1000)), (int)(result % (SECONDS_PER_DAY * 1000)));
	}
Beispiel #3
0
CTimeDate timeAddTime (const CTimeDate &StartTime, const CTimeSpan &Addition)

//	timeAddTime
//
//	Adds a timespan to a timedate

	{
	int iDaysSince1AD = StartTime.DaysSince1AD();
	int iMillisecondsSinceMidnight = StartTime.MillisecondsSinceMidnight();

	//	Add

	iDaysSince1AD += Addition.Days();
	iMillisecondsSinceMidnight += Addition.MillisecondsSinceMidnight();
	if (iMillisecondsSinceMidnight >= SECONDS_PER_DAY * 1000)
		{
		iDaysSince1AD++;
		iMillisecondsSinceMidnight -= SECONDS_PER_DAY * 1000;
		}

	return CTimeDate(iDaysSince1AD, iMillisecondsSinceMidnight);
	}
Beispiel #4
0
CTimeDate timeSubtractTime (const CTimeDate &StartTime, const CTimeSpan &Subtraction)

//	timeSubtractTime
//
//	Subtracts time from timedate

	{
	int iDaysSince1AD = StartTime.DaysSince1AD();
	int iMillisecondsSinceMidnight = StartTime.MillisecondsSinceMidnight();

	//	Add

	iDaysSince1AD -= Subtraction.Days();
	if (Subtraction.MillisecondsSinceMidnight() > iMillisecondsSinceMidnight)
		{
		iMillisecondsSinceMidnight += SECONDS_PER_DAY * 1000;
		iDaysSince1AD--;
		}
	
	iMillisecondsSinceMidnight -= Subtraction.MillisecondsSinceMidnight();

	return CTimeDate(iDaysSince1AD, iMillisecondsSinceMidnight);
	}
Beispiel #5
0
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;
		}
	}