202 lines
5.6 KiB
C++
202 lines
5.6 KiB
C++
/*
|
|
* This file is a part of Winix
|
|
* and is distributed under the 2-Clause BSD licence.
|
|
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
|
*/
|
|
|
|
/*
|
|
* Copyright (c) 2014-2018, Tomasz Sowa
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright notice,
|
|
* this list of conditions and the following disclaimer.
|
|
*
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
*/
|
|
|
|
#ifndef headerfile_winix_core_sessionidmanager
|
|
#define headerfile_winix_core_sessionidmanager
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
#include <ctime>
|
|
#include <fstream>
|
|
#include "base64.h"
|
|
#include "space/space.h"
|
|
#include "aes.h"
|
|
#include "winixbase.h"
|
|
|
|
|
|
|
|
namespace Winix
|
|
{
|
|
|
|
|
|
/*
|
|
* this class is used to encode/decode the session cookie
|
|
* in which there is a session id and a session's index
|
|
*
|
|
* session index is incremented each time a request comes to this session
|
|
*
|
|
* format of the encoded token:
|
|
* 1 byte - algorithm type, currently only one algorithm: 'a'
|
|
* 1 byte - an AES keys pair index
|
|
* ---- below everything is encoded by AES (two 128 bits blocks, first block
|
|
* is encoded by the first key and the second block is encoded by the second key) ------
|
|
* 1 byte - top padding value
|
|
* 1 byte - bottom padding value
|
|
* 1 byte - top padding size
|
|
* 1 byte - bottom padding size
|
|
* 5-9 bytes - top padding
|
|
* 8 bytes - the session id
|
|
* 4 bytes - the session index
|
|
* 5-9 bytes - bottom padding (bottom_padding_size = 14 - top_padding_size)
|
|
* 1 byte - the sum of all previous bytes
|
|
* 1 byte - the xor of all previous bytes (with the previous sum too)
|
|
*
|
|
* and at the end everyting is base64 encoded
|
|
*
|
|
*
|
|
*/
|
|
class SessionIdManager : public WinixBase
|
|
{
|
|
public:
|
|
|
|
SessionIdManager();
|
|
|
|
/*
|
|
* initialization
|
|
* this method takes about 1MB memory more (for AES key expansions)
|
|
* if you do not need the session cookie to be enrypted then don't call this method
|
|
*
|
|
*/
|
|
void Init(const std::wstring & keys_file);
|
|
|
|
/*
|
|
* how often a new AES key pairs should be generated
|
|
*/
|
|
void SetKeyRenewTime(time_t renew_time);
|
|
|
|
/*
|
|
* encode/decode the session cookie
|
|
* make sure the Init() method is called first
|
|
*/
|
|
bool EncodeToken(size_t id, unsigned int index, time_t cur_utc_time, std::wstring & token);
|
|
bool DecodeToken(const std::wstring & token, size_t & id, unsigned int & index);
|
|
|
|
|
|
private:
|
|
|
|
bool was_inited;
|
|
char algorithm_type;
|
|
std::string string_token, string_token_base64;
|
|
std::vector<std::string> key_tab1, key_tab2;
|
|
size_t key_index;
|
|
time_t last_key_generated;
|
|
time_t key_renew_time;
|
|
Tito::Base64 base64;
|
|
size_t key_tab_size;
|
|
std::ofstream out_file;
|
|
std::string tmp_key_base64_encoded;
|
|
std::wstring key_file_name;
|
|
std::string file_name_ascii;
|
|
std::vector<Tito::AES> aes1, aes2;
|
|
|
|
bool ReadKeysFromFile(const wchar_t * file);
|
|
bool ReadKeysFromFile(const std::wstring & file);
|
|
bool SaveKeysToFile(const wchar_t * file);
|
|
bool SaveKeysToFile(const std::wstring & file);
|
|
void ReadKey(const wchar_t * name, PT::Space & space, std::vector<std::string> & dest_key);
|
|
bool AreKeysCorrect(size_t index);
|
|
void GenerateKeys(size_t index, time_t cur_utc_time);
|
|
void CheckKeys(time_t cur_utc_time);
|
|
void GenerateKey(std::string & key, time_t cur_utc_time);
|
|
void SaveKeysToFile(std::vector<std::string> & keys);
|
|
void InitializeAesKeys();
|
|
void RandPadding(size_t & pad_top_size, char & pad_top_value, size_t & pad_bottom_size, char & pad_bottom_value);
|
|
void AppendSum(std::string & str);
|
|
void AppendXor(std::string & str);
|
|
void CopyString(const std::string & in, std::wstring & out);
|
|
void CopyString(const std::wstring & in, std::string & out);
|
|
bool Encode(std::string & str);
|
|
bool DecodeTokenA(size_t & id, unsigned int & index);
|
|
bool IsPaddingCorrect(const char * str, size_t len, char val);
|
|
bool CheckControlSums(const char * str);
|
|
void InitializeAesKeys(size_t index);
|
|
bool DecodeAES(const char * str, size_t key);
|
|
|
|
template<typename Value>
|
|
void Append(std::string & str, Value val);
|
|
|
|
template<typename Value>
|
|
void Read(const char * str, Value & val);
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename Value>
|
|
void SessionIdManager::Append(std::string & str, Value val)
|
|
{
|
|
int move = sizeof(Value) * 8 - 8;
|
|
int v;
|
|
|
|
do
|
|
{
|
|
if( move > 0 )
|
|
v = ((val >> move) & 0xff);
|
|
else
|
|
v = val & 0xff;
|
|
|
|
str += (unsigned char)v;
|
|
move -= 8;
|
|
}
|
|
while( move >= 0 );
|
|
}
|
|
|
|
|
|
|
|
template<typename Value>
|
|
void SessionIdManager::Read(const char * str, Value & val)
|
|
{
|
|
val = 0;
|
|
|
|
for(size_t i=0 ; i<sizeof(Value) ; ++i)
|
|
{
|
|
val = val << 8;
|
|
val = val | (unsigned char)str[i];
|
|
}
|
|
}
|
|
|
|
|
|
} // namespace Winix
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|