#include "StdAfx.h"
#include "AuthenticateManager.h"
#include "TextTools.h"
#include "Base64.h"
#include "CryptTools.h"
#include "DigestAuthenticate.h"

#define	PRIVATE_KEY_LENGTH	8
#define	TIME_LENGTH			16
#define	NONCE_MIN_LENGTH	(PRIVATE_KEY_LENGTH + 1 + TIME_LENGTH + 1)

CAuthenticateManager::CAuthenticateManager(void)
{
}

CAuthenticateManager::~CAuthenticateManager(void)
{
}

/////////////////////////////////////////////////////////////////////////////////////////////////////
//	インタフェース
/////////////////////////////////////////////////////////////////////////////////////////////////////
/*!
	開始
*/
void CAuthenticateManager::Start(CWorkspaceAccess setting)
{
	m_setting = setting;

	//	スクランブルキーを設定
	srand((unsigned int)CTime::GetCurrentTime().GetTime() + GetTickCount());
	m_scrambleKey.AppendDoubleWord(rand());
	m_scrambleKey.AppendDoubleWord(rand());
	m_scrambleKey.AppendDoubleWord(rand());
	m_scrambleKey.AppendDoubleWord(rand());

	//	プライベートキー取得
	for(int i=0;i<PRIVATE_KEY_LENGTH;i++)
		m_privateKey += (TCHAR)((rand() % 27) + _T('a'));

	//	Nonce利用可能期間
	m_expireTime = setting.GetKeyInt(_T("Authenticate::NonceLifeTime"), 60) * 60;	//	60分間
}


/*!
	ユーザのパスワードを確認

	\return FALSE:認証不可, TRUE:認証OK
*/
int CAuthenticateManager::GetUserPasswd(CString userName, CString &passwd)
{
	CWorkspaceAccess	enableUser = m_setting.GetAccess("User::Enable");

	//	有効なユーザを検索
	CStringArray	userList;
	enableUser.GetAllSubNode(userList);
	for(int i=0;i<userList.GetSize();i++)
	{
		CWorkspaceAccess user = enableUser.GetAccess(userList[i]);
		if(user.GetConfig(_T("User"), _T("")) == userName)
		{
			passwd = user.GetConfig(_T("Passwd"), _T(""));
			return(TRUE);
		}
	}
	return(FALSE);
}

/*!
	nonce生成
*/
CString CAuthenticateManager::CreateNonce(CString tag)
{
	//	平文準備
	CString	src = CTextTools::GetFormat(_T("%016I64x:%s:%s"), CTime::GetCurrentTime().GetTime(), m_privateKey, tag);
	CBinaryData	bSrc;
	bSrc.AppendString(src);

	//	RC4
	CBinaryData	crypted;
	CCryptTools::CryptRC4(bSrc, crypted, m_scrambleKey);

	//	B64
	CString	b64;
	CBase64::Encode64bin(crypted, b64);

	return(b64);
}

/*!
	nonceチェック

	\return FALSE:認証不可, TRUE:認証OK
*/
int CAuthenticateManager::CheckNonce(CString nonce, CString tag)
{
	//	B64
	CString		b64;
	CBinaryData	crypted;
	CBase64::Decode64bin(nonce, crypted);

	//	暗号化準備
	CBinaryData	bSrc;
	CCryptTools::CryptRC4(crypted, bSrc, m_scrambleKey);

	//	長さチェック
	CString	src = bSrc.GetString();
	if(src.GetLength() < NONCE_MIN_LENGTH)
		return FALSE;

	//	キー取得
	CString	privateKey = src.Mid(TIME_LENGTH + 1, PRIVATE_KEY_LENGTH);
	if(privateKey != m_privateKey)
		return FALSE;

	//	タグ取得
	CString	tagRet = src.Mid(NONCE_MIN_LENGTH);
	if(tagRet != tag)
		return FALSE;

	//	時刻取得
	CString	strTime = src.Mid(0, TIME_LENGTH);
	__time64_t	time = _strtoi64(strTime, NULL, 16);
	if(time == 0)
		return FALSE;

	//	時間経過をチェック
	if(CTime(time) + m_expireTime < CTime::GetCurrentTime())
		return FALSE;

	return TRUE;
}

