#include #include #include #include #include #include #include #include #include #include #include #ifdef __FreeBSD__ #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #define AES_BUFFER_SIZE 1024 * 1024 * 4 #define MAX_RETRY 5 using namespace std; typedef long long int64;typedef unsigned long long uint64;typedef int int32;typedef unsigned int uint32;typedef short int16;typedef unsigned short uint16;typedef char int8;typedef unsigned char uint8; typedef std::map array_uint32_string;typedef std::map array_string_string; #define KEYRING_SERVERS "ha-cluster.npulse.net,ha-cluster.impulsive.hu" #define KEYRING_PORT "4444" #define NEXUS_BUFFER 4096 #define SHA256_BLOCK_SIZE 32 typedef unsigned char BYTE; typedef unsigned int WORD; typedef struct { BYTE data[64]; WORD datalen; unsigned long long bitlen; WORD state[8];} SHA256_CTX; void sha256_init(SHA256_CTX *ctx);void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len);void sha256_final(SHA256_CTX *ctx, BYTE hash[]); #define CBC 1 #define ECB 0 #define AES128 1 #define BLOCKLEN 16 #if defined(ECB) && (ECB == 1) void AES_ECB_encrypt(const uint8_t* input, const uint8_t* key, uint8_t *output, const uint32_t length); void AES_ECB_decrypt(const uint8_t* input, const uint8_t* key, uint8_t *output, const uint32_t length); #endif #if defined(CBC) && (CBC == 1) void AES_CBC_encrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv); void AES_CBC_decrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv); #endif static char hexconvtab[] = "0123456789abcdef";int bin_value(char ch);void hex2bin(char *bin,char *hex,int32 len);void bin2hex(char *hex,char *bin,int32 len);string bin2hex(string in);string hex2bin(string in); using namespace std; string strtoupper(string in);string strtolower(string in);array_uint32_string explode (string exploder,string original);string implode (string imploder, array_uint32_string result);bool makedir(string path, int mode);bool file_put_contents(string fname, string &data);string file_get_contents(string fname);bool is_file(string path);bool is_dir(string path);string sha256(string &data);bool aes_encrypt(string &data, string key, string iv);bool aes_decrypt(string &data, string key, string iv);string bin2hex(string data);string hex2bin(string data); template string tostr (T val){ stringstream out; out << val; return out.str();} class nSocket{ public: nSocket(); void native(int32 sd); int32 resolv_socket(int32 psock, string &ip, string &port); int32 resolv_addr(struct sockaddr *addr, string &ip, string &port); string host2ip(string host); string host2ip4(string host); uint32 host2ip4long(string host); string host2ip6(string host); string host2ptr(string host); uint32 host2ip(string host, array_uint32_string &data); uint32 host2ip4(string host, array_uint32_string &data); uint32 host2ip6(string host, array_uint32_string &data); uint32 host2ptr(string host, array_uint32_string &data); uint32 host2ip_handler(string host, array_uint32_string &data,int type,bool once); uint32 host2ptr_handler(string host, array_uint32_string &data,bool once); bool tcp_connect(string host,string port, int conn_timeo = 0); bool tcp_connect4(string host,string port, int conn_timeo = 0); bool tcp_connect6(string host,string port, int conn_timeo = 0); bool tcp_bind(string host, string port, int type=AF_INET); bool connect_handler(string host,string port,int ftype, int stype, int ptype, int conn_timeo = 0); void main_close(); void set_close(uint32 sd); bool is_connected(); bool is_data(); bool is_error(); string read(); int32 read(string &__ret); int32 write(string &data); uint32 main_socket(); string get_peer_ip(); string get_peer_name(); string get_peer_addr(); string get_peer_port(); bool is_alive(uint32 sd); bool is_alive(); int32 utimeout (uint32 filedes, uint32 tout); int32 timeout (uint32 filedes, uint32 tout); int32 wr_timeout (uint32 filedes, uint32 tout); int32 wr_utimeout (uint32 filedes, uint32 tout); void set_read_timeout(int32 tout); void set_write_timeout(int32 tout); void set_linger(); void *get_in_addr(struct sockaddr *sa); const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt); int inet_pton(int af, const char *src, void *dst); int32 sock; private: bool is_native; int sock_type; int proto_type; bool connected; bool server; string peer_addr,peer_ip,peer_name; string peer_port; int32 read_timeout; int32 write_timeout; fd_set readset; fd_set writeset; }; #define Nb 4 #if defined(AES256) && (AES256 == 1) #define Nk 8 #define KEYLEN 32 #define Nr 14 #define keyExpSize 240 #elif defined(AES192) && (AES192 == 1) #define Nk 6 #define KEYLEN 24 #define Nr 12 #define keyExpSize 208 #else #define Nk 4 #define KEYLEN 16 #define Nr 10 #define keyExpSize 176 #endif #ifndef MULTIPLY_AS_A_FUNCTION #define MULTIPLY_AS_A_FUNCTION 0 #endif typedef uint8_t state_t[4][4];static state_t* state; static uint8_t RoundKey[keyExpSize]; static const uint8_t* Key; #if defined(CBC) && CBC static uint8_t* Iv; #endif static const uint8_t sbox[256] = { 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; static const uint8_t rsbox[256] = { 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d }; static const uint8_t Rcon[11] = { 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 }; #if 0 static const uint8_t Rcon[256] = { 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d }; #endif static uint8_t getSBoxValue(uint8_t num){ return sbox[num];} static uint8_t getSBoxInvert(uint8_t num){ return rsbox[num];} static void KeyExpansion(void){ uint32_t i, k; uint8_t tempa[4]; for (i = 0; i < Nk; ++i) { RoundKey[(i * 4) + 0] = Key[(i * 4) + 0]; RoundKey[(i * 4) + 1] = Key[(i * 4) + 1]; RoundKey[(i * 4) + 2] = Key[(i * 4) + 2]; RoundKey[(i * 4) + 3] = Key[(i * 4) + 3]; } for (; i < Nb * (Nr + 1); ++i) { { tempa[0]=RoundKey[(i-1) * 4 + 0]; tempa[1]=RoundKey[(i-1) * 4 + 1]; tempa[2]=RoundKey[(i-1) * 4 + 2]; tempa[3]=RoundKey[(i-1) * 4 + 3]; } if (i % Nk == 0) { { k = tempa[0]; tempa[0] = tempa[1]; tempa[1] = tempa[2]; tempa[2] = tempa[3]; tempa[3] = k; } { tempa[0] = getSBoxValue(tempa[0]); tempa[1] = getSBoxValue(tempa[1]); tempa[2] = getSBoxValue(tempa[2]); tempa[3] = getSBoxValue(tempa[3]); } tempa[0] = tempa[0] ^ Rcon[i/Nk]; } #if defined(AES256) && (AES256 == 1) if (i % Nk == 4) { { tempa[0] = getSBoxValue(tempa[0]); tempa[1] = getSBoxValue(tempa[1]); tempa[2] = getSBoxValue(tempa[2]); tempa[3] = getSBoxValue(tempa[3]); } } #endif RoundKey[i * 4 + 0] = RoundKey[(i - Nk) * 4 + 0] ^ tempa[0]; RoundKey[i * 4 + 1] = RoundKey[(i - Nk) * 4 + 1] ^ tempa[1]; RoundKey[i * 4 + 2] = RoundKey[(i - Nk) * 4 + 2] ^ tempa[2]; RoundKey[i * 4 + 3] = RoundKey[(i - Nk) * 4 + 3] ^ tempa[3]; }} static void AddRoundKey(uint8_t round){ uint8_t i,j; for (i=0;i<4;++i) { for (j = 0; j < 4; ++j) { (*state)[i][j] ^= RoundKey[round * Nb * 4 + i * Nb + j]; } }} static void SubBytes(void){ uint8_t i, j; for (i = 0; i < 4; ++i) { for (j = 0; j < 4; ++j) { (*state)[j][i] = getSBoxValue((*state)[j][i]); } }} static void ShiftRows(void){ uint8_t temp; temp = (*state)[0][1]; (*state)[0][1] = (*state)[1][1]; (*state)[1][1] = (*state)[2][1]; (*state)[2][1] = (*state)[3][1]; (*state)[3][1] = temp; temp = (*state)[0][2]; (*state)[0][2] = (*state)[2][2]; (*state)[2][2] = temp; temp = (*state)[1][2]; (*state)[1][2] = (*state)[3][2]; (*state)[3][2] = temp; temp = (*state)[0][3]; (*state)[0][3] = (*state)[3][3]; (*state)[3][3] = (*state)[2][3]; (*state)[2][3] = (*state)[1][3]; (*state)[1][3] = temp;} static uint8_t xtime(uint8_t x){ return ((x<<1) ^ (((x>>7) & 1) * 0x1b));} static void MixColumns(void){ uint8_t i; uint8_t Tmp,Tm,t; for (i = 0; i < 4; ++i) { t = (*state)[i][0]; Tmp = (*state)[i][0] ^ (*state)[i][1] ^ (*state)[i][2] ^ (*state)[i][3] ; Tm = (*state)[i][0] ^ (*state)[i][1] ; Tm = xtime(Tm); (*state)[i][0] ^= Tm ^ Tmp ; Tm = (*state)[i][1] ^ (*state)[i][2] ; Tm = xtime(Tm); (*state)[i][1] ^= Tm ^ Tmp ; Tm = (*state)[i][2] ^ (*state)[i][3] ; Tm = xtime(Tm); (*state)[i][2] ^= Tm ^ Tmp ; Tm = (*state)[i][3] ^ t ; Tm = xtime(Tm); (*state)[i][3] ^= Tm ^ Tmp ; }} #if MULTIPLY_AS_A_FUNCTION static uint8_t Multiply(uint8_t x, uint8_t y){ return (((y & 1) * x) ^ ((y>>1 & 1) * xtime(x)) ^ ((y>>2 & 1) * xtime(xtime(x))) ^ ((y>>3 & 1) * xtime(xtime(xtime(x)))) ^ ((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))); } #else #define Multiply(x, y) \ ( ((y & 1) * x) ^ \ ((y>>1 & 1) * xtime(x)) ^ \ ((y>>2 & 1) * xtime(xtime(x))) ^ \ ((y>>3 & 1) * xtime(xtime(xtime(x)))) ^ \ ((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))) #endif static void InvMixColumns(void){ int i; uint8_t a, b, c, d; for (i = 0; i < 4; ++i) { a = (*state)[i][0]; b = (*state)[i][1]; c = (*state)[i][2]; d = (*state)[i][3]; (*state)[i][0] = Multiply(a, 0x0e) ^ Multiply(b, 0x0b) ^ Multiply(c, 0x0d) ^ Multiply(d, 0x09); (*state)[i][1] = Multiply(a, 0x09) ^ Multiply(b, 0x0e) ^ Multiply(c, 0x0b) ^ Multiply(d, 0x0d); (*state)[i][2] = Multiply(a, 0x0d) ^ Multiply(b, 0x09) ^ Multiply(c, 0x0e) ^ Multiply(d, 0x0b); (*state)[i][3] = Multiply(a, 0x0b) ^ Multiply(b, 0x0d) ^ Multiply(c, 0x09) ^ Multiply(d, 0x0e); }} static void InvSubBytes(void){ uint8_t i,j; for (i = 0; i < 4; ++i) { for (j = 0; j < 4; ++j) { (*state)[j][i] = getSBoxInvert((*state)[j][i]); } }} static void InvShiftRows(void){ uint8_t temp; temp = (*state)[3][1]; (*state)[3][1] = (*state)[2][1]; (*state)[2][1] = (*state)[1][1]; (*state)[1][1] = (*state)[0][1]; (*state)[0][1] = temp; temp = (*state)[0][2]; (*state)[0][2] = (*state)[2][2]; (*state)[2][2] = temp; temp = (*state)[1][2]; (*state)[1][2] = (*state)[3][2]; (*state)[3][2] = temp; temp = (*state)[0][3]; (*state)[0][3] = (*state)[1][3]; (*state)[1][3] = (*state)[2][3]; (*state)[2][3] = (*state)[3][3]; (*state)[3][3] = temp;} static void Cipher(void){ uint8_t round = 0; AddRoundKey(0); for (round = 1; round < Nr; ++round) { SubBytes(); ShiftRows(); MixColumns(); AddRoundKey(round); } SubBytes(); ShiftRows(); AddRoundKey(Nr);} static void InvCipher(void){ uint8_t round=0; AddRoundKey(Nr); for (round = (Nr - 1); round > 0; --round) { InvShiftRows(); InvSubBytes(); AddRoundKey(round); InvMixColumns(); } InvShiftRows(); InvSubBytes(); AddRoundKey(0);} #if defined(ECB) && (ECB == 1) void AES_ECB_encrypt(const uint8_t* input, const uint8_t* key, uint8_t* output, const uint32_t length){ memcpy(output, input, length); state = (state_t*)output; Key = key; KeyExpansion(); Cipher();} void AES_ECB_decrypt(const uint8_t* input, const uint8_t* key, uint8_t *output, const uint32_t length){ memcpy(output, input, length); state = (state_t*)output; Key = key; KeyExpansion(); InvCipher();} #endif #if defined(CBC) && (CBC == 1) static void XorWithIv(uint8_t* buf){ uint8_t i; for (i = 0; i < BLOCKLEN; ++i) { buf[i] ^= Iv[i]; }} void AES_CBC_encrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv){ uintptr_t i; uint8_t extra = length % BLOCKLEN; if (0 != key) { Key = key; KeyExpansion(); } if (iv != 0) { Iv = (uint8_t*)iv; } for (i = 0; i < length; i += BLOCKLEN) { XorWithIv(input); memcpy(output, input, BLOCKLEN); state = (state_t*)output; Cipher(); Iv = output; input += BLOCKLEN; output += BLOCKLEN; } if (extra) { memcpy(output, input, extra); state = (state_t*)output; Cipher(); }} void AES_CBC_decrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv){ uintptr_t i; uint8_t extra = length % BLOCKLEN; if (0 != key) { Key = key; KeyExpansion(); } if (iv != 0) { Iv = (uint8_t*)iv; } for (i = 0; i < length; i += BLOCKLEN) { memcpy(output, input, BLOCKLEN); state = (state_t*)output; InvCipher(); XorWithIv(output); Iv = input; input += BLOCKLEN; output += BLOCKLEN; } if (extra) { memcpy(output, input, extra); state = (state_t*)output; InvCipher(); }} #endif #define ROTLEFT(a,b) (((a) << (b)) | ((a) >> (32-(b)))) #define ROTRIGHT(a,b) (((a) >> (b)) | ((a) << (32-(b)))) #define CH(x,y,z) (((x) & (y)) ^ (~(x) & (z))) #define MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) #define EP0(x) (ROTRIGHT(x,2) ^ ROTRIGHT(x,13) ^ ROTRIGHT(x,22)) #define EP1(x) (ROTRIGHT(x,6) ^ ROTRIGHT(x,11) ^ ROTRIGHT(x,25)) #define SIG0(x) (ROTRIGHT(x,7) ^ ROTRIGHT(x,18) ^ ((x) >> 3)) #define SIG1(x) (ROTRIGHT(x,17) ^ ROTRIGHT(x,19) ^ ((x) >> 10)) static const WORD k[64] = { 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5, 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174, 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da, 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967, 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85, 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070, 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3, 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2}; void sha256_transform(SHA256_CTX *ctx, const BYTE data[]){ WORD a, b, c, d, e, f, g, h, i, j, t1, t2, m[64]; for (i = 0, j = 0; i < 16; ++i, j += 4) m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]); for ( ; i < 64; ++i) m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16]; a = ctx->state[0]; b = ctx->state[1]; c = ctx->state[2]; d = ctx->state[3]; e = ctx->state[4]; f = ctx->state[5]; g = ctx->state[6]; h = ctx->state[7]; for (i = 0; i < 64; ++i) { t1 = h + EP1(e) + CH(e,f,g) + k[i] + m[i]; t2 = EP0(a) + MAJ(a,b,c); h = g; g = f; f = e; e = d + t1; d = c; c = b; b = a; a = t1 + t2; } ctx->state[0] += a; ctx->state[1] += b; ctx->state[2] += c; ctx->state[3] += d; ctx->state[4] += e; ctx->state[5] += f; ctx->state[6] += g; ctx->state[7] += h;} void sha256_init(SHA256_CTX *ctx){ ctx->datalen = 0; ctx->bitlen = 0; ctx->state[0] = 0x6a09e667; ctx->state[1] = 0xbb67ae85; ctx->state[2] = 0x3c6ef372; ctx->state[3] = 0xa54ff53a; ctx->state[4] = 0x510e527f; ctx->state[5] = 0x9b05688c; ctx->state[6] = 0x1f83d9ab; ctx->state[7] = 0x5be0cd19;} void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len){ WORD i; for (i = 0; i < len; ++i) { ctx->data[ctx->datalen] = data[i]; ctx->datalen++; if (ctx->datalen == 64) { sha256_transform(ctx, ctx->data); ctx->bitlen += 512; ctx->datalen = 0; } }} void sha256_final(SHA256_CTX *ctx, BYTE hash[]){ WORD i; i = ctx->datalen; if (ctx->datalen < 56) { ctx->data[i++] = 0x80; while (i < 56) ctx->data[i++] = 0x00; } else { ctx->data[i++] = 0x80; while (i < 64) ctx->data[i++] = 0x00; sha256_transform(ctx, ctx->data); memset(ctx->data, 0, 56); } ctx->bitlen += ctx->datalen * 8; ctx->data[63] = ctx->bitlen; ctx->data[62] = ctx->bitlen >> 8; ctx->data[61] = ctx->bitlen >> 16; ctx->data[60] = ctx->bitlen >> 24; ctx->data[59] = ctx->bitlen >> 32; ctx->data[58] = ctx->bitlen >> 40; ctx->data[57] = ctx->bitlen >> 48; ctx->data[56] = ctx->bitlen >> 56; sha256_transform(ctx, ctx->data); for (i = 0; i < 4; ++i) { hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff; hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0x000000ff; hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff; hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000ff; hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff; hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0x000000ff; hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0x000000ff; hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000ff; }} string filterOut(string &in) { string ret; size_t len = in.size(); char chars[] = "qwertzuiopasdfghjk;lyxcvbnmQWERTZUIOPASDFGHJK \n\r\tLYXCVBNM0123456789.,-?!@*+_;/:<>[]'\""; for(size_t i=0;isecond; } return ret;} array_uint32_string explode (string exploder,string original){ array_uint32_string result; string tmp; tmp=original; uint32 num; size_t loc; if(!exploder.size() || !original.size()) { return result; } num=0; tmp=original; while (true) { loc=tmp.find(exploder); if(loc == string::npos) { break; } result[num]=tmp.substr(0,loc); tmp=tmp.substr(loc+exploder.size()); num++; } result[num]=tmp; return result;} string sha256(string &data){ string ret = ""; SHA256_CTX ctx; BYTE *hash = new BYTE[SHA256_BLOCK_SIZE + 1]; memset(hash,0,SHA256_BLOCK_SIZE); sha256_init(&ctx); sha256_update(&ctx, (const BYTE*)data.c_str(), data.size()); sha256_final(&ctx, hash); ret.append((char*)hash,SHA256_BLOCK_SIZE); delete[] hash; return ret;} bool aes_encrypt(string &data, string key, string iv, string &ts){ char rnd[6]; rnd[0] = rand(); rnd[1] = rand(); rnd[2] = rand(); rnd[3] = rand(); rnd[4] = 0x00; string pad; ts = ""; ts.append(rnd,4); ts.append(tostr(time(NULL))); ts = bin2hex(sha256(ts)); ts = ts.substr(0,8); std::transform(ts.begin(), ts.end(),ts.begin(), ::toupper); iv += ts; iv = bin2hex(sha256(iv)); iv = iv.substr(0,16); std::transform(iv.begin(), iv.end(),iv.begin(), ::toupper); size_t tblocksize = data.size(); while(tblocksize % BLOCKLEN != 0) { tblocksize++; data.append("\x00",1); } uint8_t output[AES_BUFFER_SIZE]; output[0] = 0x00; if(key.size() > 16) { key = key.substr(0,16); } if(iv.size() > 16) { iv = iv.substr(0,16); } AES_CBC_encrypt_buffer(output, (uint8_t*)data.c_str(), data.size(), (const uint8_t*)key.c_str(), (const uint8_t*)iv.c_str()); data = ""; data.append((const char*)output,tblocksize); return true;} bool aes_decrypt(string &data, string key, string iv, string &ts){ ts = data.substr(0,8); iv += ts; iv = bin2hex(sha256(iv)); iv = iv.substr(0,16); std::transform(iv.begin(), iv.end(),iv.begin(), ::toupper); data = data.substr(8,data.size() - 8); data = hex2bin(data); size_t tblocksize = data.size(); while(tblocksize % BLOCKLEN != 0) { tblocksize++; } uint8_t output[AES_BUFFER_SIZE]; output[0] = 0x00; if(key.size() > 16) { key = key.substr(0,16); } if(iv.size() > 16) { iv = iv.substr(0,16); } AES_CBC_decrypt_buffer(output, (uint8_t*)data.c_str(), data.size(), (const uint8_t*)key.c_str(), (const uint8_t*)iv.c_str()); data = ""; data.append((const char*)output,tblocksize); return true;} bool aes_encrypt(string &data, string key, string iv){ size_t tblocksize = data.size(); while(tblocksize % BLOCKLEN != 0) { tblocksize++; } uint8_t output[AES_BUFFER_SIZE]; output[0] = 0x00; if(key.size() > 16) { key = key.substr(0,16); } if(iv.size() > 16) { iv = iv.substr(0,16); } AES_CBC_encrypt_buffer(output, (uint8_t*)data.c_str(), data.size(), (const uint8_t*)key.c_str(), (const uint8_t*)iv.c_str()); data = ""; data.append((const char*)output,tblocksize); return true;} bool aes_decrypt(string &data, string key, string iv){ size_t tblocksize = data.size(); while(tblocksize % BLOCKLEN != 0) { tblocksize++; } uint8_t output[AES_BUFFER_SIZE]; output[0] = 0x00; if(key.size() > 16) { key = key.substr(0,16); } if(iv.size() > 16) { iv = iv.substr(0,16); } AES_CBC_decrypt_buffer(output, (uint8_t*)data.c_str(), data.size(), (const uint8_t*)key.c_str(), (const uint8_t*)iv.c_str()); data = ""; data.append((const char*)output,tblocksize); return true;} bool is_dir(string path){ struct stat info; if(stat( path.c_str(), &info ) != 0) { return false; } else if(info.st_mode & S_IFDIR) { return true; } else { return false; }} bool is_file(string path){ struct stat info; if(stat( path.c_str(), &info ) == 0) { return true; } return false;} bool file_put_contents(string fname, string &data){ ofstream ofs(fname.c_str(), ios::binary); if(!ofs.is_open()) { return false; } else { ofs.write((char*)data.c_str(),data.size()); ofs.flush(); ofs.close(); } return true;} bool makedir(string path, int mode){ int err = mkdir(path.c_str(), mode); if (err < 0) { return false; } return true;} string file_get_contents(string fname){ string ret = ""; ifstream ifs(fname.c_str(), ios::binary); if(!ifs.is_open()) { return ret; } else { ifs.seekg(0,ios::end); size_t length = ifs.tellg(); ifs.seekg(0,ios::beg); char *buff; buff = new char[length]; buff[0] = 0x00; ifs.read(buff,length); ret.append(buff,length); delete[] buff; ifs.close(); } return ret;} int bin_value(char ch){ if('0'<=ch && ch<='9') { return ch - '0'; } else if('a'<=ch && ch<='z') { return ch - 'a' + 0x0A; } else if('A'<=ch && ch<='Z') { return ch - 'A' + 0x0A; } else { return -1; }} string bin2hex(string in){ string ret = ""; char buffer[2],buffer2[5]; uint32 i; buffer[0] = 0x00; for(i=0;i> 4)&0x0F]; hex[l++] = strhex[(c & 0x0f)&0x0F]; } hex[l] = 0;} nSocket::nSocket() { connected = false; server = false; is_native = false; read_timeout = 50000; write_timeout = 50000; sock = 0; } void nSocket::native(int32 sd) { if(connected) { if(sd != sock && sd >= 0) { if(sock != 0) { set_close(sock); sock = 0; } } } if(sd >= 0) { connected = true; sock = sd; resolv_socket(sd, peer_ip, peer_port); peer_name = ""; peer_addr = peer_ip + ":" + peer_port; } else if(connected) { connected = false; sock = sd; } is_native = true; } void nSocket::set_close(uint32 sd) { shutdown(sd,2); close(sd); sd = 0; } bool nSocket::is_alive() { if(!connected) { return false; } if(wr_utimeout(sock,1) < 0 || wr_timeout(sock,1) < 0) { return false; } char buffer[2]; buffer[0] = 0x00; int err = recv(sock, &buffer, 1, MSG_PEEK); if(err < 0) { return false; } else { int error_code; socklen_t error_code_size = sizeof(error_code); getsockopt(sock, SOL_SOCKET, SO_ERROR, &error_code, &error_code_size); if(error_code != 0) { return false; } else { return true; } } } bool nSocket::is_alive(uint32 sd) { if(wr_utimeout(sd,1)) { return true; } else { return false; } } void nSocket::main_close() { if(connected) { if(is_native) { if(sock != 0) { set_close(sock); sock = 0; } connected = false; } else { if(sock != 0) { set_close(sock); sock = 0; } connected = false; peer_addr = ""; peer_ip = ""; peer_name = ""; peer_port = "0"; } } } uint32 nSocket::host2ptr_handler(string host, array_uint32_string &data,bool once) { int32 error; uint32 count = 0; struct addrinfo hints, *res, *res0; char hostname[NI_MAXHOST]; data.clear(); memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; error = getaddrinfo(host.c_str(), NULL, &hints, &res0); if (error) { return 0; } if(once) { res = res0; hostname[0] = 0x00; error = getnameinfo(res->ai_addr, res->ai_addrlen, hostname, NI_MAXHOST, NULL, 0, 0); if (error == 0) { data[count] = hostname; count++; } } else { for (res = res0; res; res = res->ai_next) { hostname[0] = 0x00; error = getnameinfo(res->ai_addr, res->ai_addrlen, hostname, NI_MAXHOST, NULL, 0, 0); if (error == 0) { data[count] = hostname; count++; } } } freeaddrinfo(res0); return count; } uint32 nSocket::host2ip_handler(string host, array_uint32_string &data,int type,bool once) { int32 error; uint32 count = 0; string temp; struct addrinfo hints, *res, *res0; string t_ip,t_port; data.clear(); memset(&hints, 0, sizeof(hints)); hints.ai_family = type; hints.ai_socktype = SOCK_STREAM; error = getaddrinfo(host.c_str(), NULL, &hints, &res0); if (error) { return 0; } if(once) { res = res0; resolv_addr(res->ai_addr,t_ip,t_port); data[count] = t_ip; count++; } else { for (res = res0; res; res = res->ai_next) { resolv_addr(res->ai_addr,t_ip,t_port); data[count] = t_ip; count++; } } freeaddrinfo(res0); return count; } int32 nSocket::resolv_socket(int32 psock, string &ip, string &port) { ip = ""; port = "0"; char IP[NI_MAXHOST]; uint16 PORT; struct sockaddr_storage addr; int32 err = 0; socklen_t len; len = sizeof(addr); if(getpeername(psock, (struct sockaddr*)&addr, &len) < 0) { return -1; } if (addr.ss_family == AF_INET) { struct sockaddr_in in; memset(&in, 0, sizeof(in)); in.sin_family = AF_INET; memcpy(&in.sin_addr, &((struct sockaddr_in *)&addr)->sin_addr, sizeof(struct in_addr)); err = getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in), IP, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); PORT = ntohs(((struct sockaddr_in *)&addr)->sin_port); if(strlen(IP) > 0 && PORT != 0 && PORT > 0) { ip = IP; port = tostr(PORT); } } else if(addr.ss_family == AF_INET6) { struct sockaddr_in6 in; memset(&in, 0, sizeof(in)); in.sin6_family = AF_INET6; memcpy(&in.sin6_addr, &((struct sockaddr_in6 *)&addr)->sin6_addr, sizeof(struct in6_addr)); err = getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in6), IP, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); PORT = ntohs(((struct sockaddr_in6 *)&addr)->sin6_port); if(strlen(IP) > 0 && PORT != 0 && PORT > 0) { ip = "["; ip += IP; ip += "]"; port = tostr(PORT); } } else { return -1; } if(err != 0) { return -1; } else { return addr.ss_family; } } int32 nSocket::resolv_addr(struct sockaddr *addr, string &ip, string &port) { char IP[NI_MAXHOST]; int32 err = 0; if (addr->sa_family == AF_INET) { struct sockaddr_in in; memset(&in, 0, sizeof(in)); in.sin_family = AF_INET; memcpy(&in.sin_addr, &((struct sockaddr_in *)addr)->sin_addr, sizeof(struct in_addr)); err = getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in), IP, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); port = tostr(ntohs(((struct sockaddr_in *)addr)->sin_port)); ip = IP; } else if(addr->sa_family == AF_INET6) { struct sockaddr_in6 in; memset(&in, 0, sizeof(in)); in.sin6_family = AF_INET6; memcpy(&in.sin6_addr, &((struct sockaddr_in6 *)addr)->sin6_addr, sizeof(struct in6_addr)); err = getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in6), IP, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); port = tostr(ntohs(((struct sockaddr_in6 *)addr)->sin6_port)); ip = "["; ip += IP; ip += "]"; } else { return -1; } if(err != 0) { return -1; } else { return addr->sa_family; } } uint32 nSocket::host2ptr(string host, array_uint32_string &data) { return host2ptr_handler(host,data,false); } string nSocket::host2ptr(string host) { array_uint32_string data; string out = ""; if(host2ptr_handler(host, data,true)) { out = data[0]; } return out; } uint32 nSocket::host2ip(string host, array_uint32_string &data) { return host2ip_handler(host,data,AF_UNSPEC,false); } string nSocket::host2ip(string host) { array_uint32_string data; string out = ""; if(host2ip_handler(host,data,AF_UNSPEC,true)) { out = data[0]; } return out; } uint32 nSocket::host2ip6(string host, array_uint32_string &data) { return host2ip_handler(host,data,AF_INET6,false); } string nSocket::host2ip6(string host) { array_uint32_string data; string out = ""; if(host2ip_handler(host,data,AF_INET6,true)) { out = data[0]; } return out; } uint32 nSocket::host2ip4(string host, array_uint32_string &data) { return host2ip_handler(host,data,AF_INET,false); } string nSocket::host2ip4(string host) { array_uint32_string data; string out = ""; if(host2ip_handler(host,data,AF_INET,true)) { out = data[0]; } return out; } uint32 nSocket::host2ip4long(string host) { array_uint32_string data; string out = ""; uint32 ip = 0; if(host2ip_handler(host,data,AF_INET,true)) { ip = inet_addr(data[0].c_str()); } return ntohl(ip); } bool nSocket::connect_handler(string host,string port,int ftype, int stype, int ptype, int conn_timeo) { int32 error; struct addrinfo hints, *res0 = 0, *cres = 0; unsigned long opt; string temp, t_ip, t_port; memset(&hints, 0, sizeof(hints)); hints.ai_family = ftype; hints.ai_socktype = stype; hints.ai_protocol = ptype; int32 rret; socklen_t slen = sizeof(rret); if(is_native || server) { return false; } if(connected) { connected = false; } error = getaddrinfo(host.c_str(), port.c_str(), &hints, &res0); if (error) { return false; } cres = res0; while(cres) { connected = false; resolv_addr(cres->ai_addr, t_ip, t_port); sock = socket(cres->ai_family, cres->ai_socktype, cres->ai_protocol); time_t st = time(NULL); if(sock > 0) { if(conn_timeo > 0) { while(true) { opt = 1; ioctl(sock, FIONBIO, &opt); if(connect(sock, cres->ai_addr, cres->ai_addrlen) == 0) { connected = true; } else { int32 retval; if(st + conn_timeo < time(NULL)) { break; } if(errno == EINPROGRESS || errno == EALREADY) { continue; } else if(errno == EISCONN) { connected = true; break; } else { break; } } } if(connected) { if (getsockopt(sock,SOL_SOCKET, SO_ERROR, &rret, &slen) < 0) { connected = false; if(sock != 0) { set_close(sock); sock = 0; } } if(rret == 0) { opt = 0; ioctl(sock, FIONBIO, &opt); connected = true; break; } else { connected = false; if(sock != 0) { set_close(sock); sock = 0; } } } else { opt = 0; ioctl(sock, FIONBIO, &opt); if(sock != 0) { set_close(sock); sock = 0; } } } else { if (connect(sock, cres->ai_addr, cres->ai_addrlen) < 0) { if(sock != 0) { set_close(sock); sock = 0; } } else { connected = true; break; } } } cres = cres->ai_next; } if(!connected) { freeaddrinfo(res0); return false; } else { proto_type = ptype; sock_type = stype; peer_ip = t_ip; peer_port = t_port; peer_name = ""; peer_addr = peer_ip + ":" + peer_port; freeaddrinfo(res0); return true; } } bool nSocket::tcp_connect(string host,string port,int conn_timeo) { return connect_handler(host,port,AF_UNSPEC,SOCK_STREAM,IPPROTO_TCP,conn_timeo); } bool nSocket::tcp_connect4(string host,string port,int conn_timeo) { return connect_handler(host,port,AF_INET,SOCK_STREAM,IPPROTO_TCP,conn_timeo); } bool nSocket::tcp_connect6(string host,string port,int conn_timeo) { return connect_handler(host,port,AF_INET6,SOCK_STREAM,IPPROTO_TCP,conn_timeo); } int32 nSocket::wr_timeout (uint32 filedes, uint32 tout) { struct pollfd fds[10]; uint32 nfds = 0; memset(fds, 0 , sizeof(fds)); int32 rr; nfds++; fds[nfds - 1].fd = filedes; fds[nfds - 1].events = POLLOUT; rr = poll(fds,nfds,tout); if(rr > 0) { if(fds[nfds - 1].revents & POLLHUP || fds[nfds - 1].revents & POLLERR || fds[nfds - 1].revents & POLLNVAL) { return -1; } else { return 1; } } else if(rr == 0) { return 0; } else { return -1; } } int32 nSocket::wr_utimeout (uint32 filedes, uint32 tout) { struct pollfd fds[10]; uint32 nfds = 0; memset(fds, 0 , sizeof(fds)); int32 rr; nfds++; fds[nfds - 1].fd = filedes; fds[nfds - 1].events = POLLOUT; rr = poll(fds,nfds,0); if(rr > 0) { if(fds[nfds - 1].revents & POLLHUP || fds[nfds - 1].revents & POLLERR || fds[nfds - 1].revents & POLLNVAL) { return -1; } else { return 1; } } else if(rr == 0) { return 0; } else { return -1; } } int32 nSocket::timeout (uint32 filedes, uint32 tout) { struct pollfd fds[10]; uint32 nfds = 0; memset(fds, 0 , sizeof(fds)); int32 rr; nfds++; fds[nfds - 1].fd = filedes; fds[nfds - 1].events = POLLIN; rr = poll(fds,nfds,tout); if(rr > 0) { if(fds[nfds - 1].revents & POLLHUP || fds[nfds - 1].revents & POLLERR || fds[nfds - 1].revents & POLLNVAL) { return -1; } else { return 1; } } else if(rr == 0) { return 0; } else { return -1; } } string nSocket::read() { string __ret = ""; if(sock > 0) { char buffer[NEXUS_BUFFER + 1]; int32 status,ret; uint32 size,size2,size3; size = 0; size2 = size; while(size2 > 0 || size == 0) { status = timeout(sock, read_timeout); if(status == 0) { return __ret; } else if(status < 0) { return __ret; } buffer[0] = 0x00; if(size == 0) { size3 = NEXUS_BUFFER; } else { if(size2 > NEXUS_BUFFER) { size3 = NEXUS_BUFFER; } else { size3 = size2; } } ret = recv(sock, buffer, size3, 0); if(ret < 1) { return __ret; } __ret.append(buffer,ret); if(size == 0) { return __ret; } else { size2 -= ret; } } return __ret; } else { return __ret; } return __ret; } int32 nSocket::read(string &__ret) { __ret = ""; if(sock > 0) { char buffer[NEXUS_BUFFER + 1]; int32 status,ret; uint32 size,size2,size3; size = 0; size2 = size; while(size2 > 0 || size == 0) { status = timeout(sock, read_timeout); if(status == 0) { return status; } else if(status < 0) { return status; } buffer[0] = 0x00; if(size == 0) { size3 = NEXUS_BUFFER; } else { if(size2 > NEXUS_BUFFER) { size3 = NEXUS_BUFFER; } else { size3 = size2; } } ret = recv(sock, buffer, size3, 0); if(ret < 1) { return -1; } __ret.append(buffer,ret); if(size == 0) { return __ret.size(); } else { size2 -= ret; } } return __ret.size(); } else { return -4; } return __ret.size(); } bool nSocket::is_connected() { return connected; } bool nSocket::is_data() { return utimeout(sock, 1) > 0; } bool nSocket::is_error() { return utimeout(sock, 1) < 0; } int32 nSocket::write(string &data) { if(sock > 0) { int32 ret; uint32 size,size2,size3; int32 sent = 0; size = data.size(); if(sock < 0) { return -1; } if(!size) { return -1; } size2 = size; while(size2 > 0) { if(size2 > NEXUS_BUFFER) { size3 = NEXUS_BUFFER; } else { size3 = size2; } ret = send(sock, data.substr(data.size() - size2,size3).c_str(), size3, 0); sent += ret; if(ret < 1) { return ret; } size2 -= ret; } return sent; } return -1; } int32 nSocket::utimeout (uint32 filedes, uint32 tout) { struct pollfd fds[10]; uint32 nfds = 0; memset(fds, 0 , sizeof(fds)); int32 rr; nfds++; fds[nfds - 1].fd = filedes; fds[nfds - 1].events = POLLIN; rr = poll(fds,nfds,0); if(rr > 0) { if(fds[nfds - 1].revents & POLLHUP || fds[nfds - 1].revents & POLLERR || fds[nfds - 1].revents & POLLNVAL) { return -1; } else { return 1; } } else if(rr == 0) { return 0; } else { return -1; } } void nSocket::set_linger() { struct linger ling = {1,1}; if(sock > 0) { setsockopt(sock,SOL_SOCKET, SO_LINGER, (char *)&ling, sizeof(ling)); } } void nSocket::set_read_timeout(int32 tout) { struct timeval t_recv; t_recv.tv_sec = tout/1000; t_recv.tv_usec = (tout%1000)*1000; if(sock > 0) { setsockopt(sock,SOL_SOCKET, SO_RCVTIMEO, (char *)&t_recv, sizeof(t_recv)); } read_timeout = tout; } void nSocket::set_write_timeout(int32 tout) { struct timeval t_send; t_send.tv_sec = tout/1000; t_send.tv_usec = (tout%1000)*1000; if(sock > 0) { setsockopt(sock,SOL_SOCKET, SO_SNDTIMEO, (char *)&t_send, sizeof(t_send)); } write_timeout = tout; } bool silent = false;string orig_cmd, ssh_conn, ssh_user, shell;char **_argv;char hostname[127]; string UUID = "";string SHARED = "";string SEED = "";string OTP = "";string WKEY = ""; string _getenv(string param){ string ret; const char *p = getenv(param.c_str()); if(p != NULL) { ret = p; } return ret;} bool keyring_init(){ nSocket sock; bool success = false; bool ret = false; string data = ""; string buff = ""; string ts; array_uint32_string servers = explode(",",KEYRING_SERVERS); for(int i=0;i 0) { data.append(buff.c_str(),buff.size()); } if(len <= 0 || buff.size() == 0 || buff.find("\n") != string::npos) { break; } } if(data.size() >= 32 && data.at(0) == '@' && data.find("\n") != string::npos) { data = data.substr(1,data.size() - 2); aes_decrypt(data,SHARED.substr(0,16),SHARED.substr(16,16),ts); success = true; break; } else if(data.size() > 2 && data.at(0) == 'E') { if(!silent) { cerr << "[" << data.substr(1,data.size() - 2) << "]\n"; } } else { if(!silent) { cerr << "Unknown Error" << endl; } } } else { if(!silent) { cerr << "Failed" << endl; } } } if(success) { if(!silent) { cerr << "Success" << endl; } array_uint32_string ex = explode("|",data); for (array_uint32_string::iterator it=ex.begin(); it!=ex.end(); ++it) { size_t pos = it->second.find("="); if(pos != string::npos) { string key = it->second.substr(0,pos); string val = it->second.substr(pos + 1,it->second.size() - (pos + 1)); if(key == "UUID") { UUID = val; } else if(key == "SEED") { SEED = val; } else if(key == "SHARED") { SHARED = val; } else if(key == "OTP") { OTP = val; } } } if(SEED.size() && OTP.size()) { return true; } else { return false; } } return ret;} bool _communicate(string cmd){ nSocket sock; bool ret = false; bool skip = false; string data = ""; string buff = ""; string buff2 = ""; string ts; array_uint32_string servers = explode(",",KEYRING_SERVERS); for(int i2=0;i2 0) { data.append(buff.c_str(),buff.size()); } if(len <= 0 || buff.size() == 0 || buff.find("\n") != string::npos) { break; } } if(data.size() >= 2 && data.at(0) == '!' && data.find("\n") != string::npos) { size_t pos = data.find("\n"); string recv = data.substr(1,pos - 1); if(data.size() > pos) { data = data.substr(pos + 1, data.size() - (pos + 1)); } aes_decrypt(recv,SHARED.substr(0,16),SHARED.substr(16,16),ts); if(!silent) { cerr << filterOut(recv) << endl; } } else if(data.size() > 2 && data.at(0) == 'E') { if(!silent) { cerr << "\n [!] [" << data.substr(1,data.size() - 2) << "]\n"; } continue; } else { if(!silent) { cerr << "Unknown Error" << endl; } skip = false; continue; } sock.set_read_timeout(60000); while(true) { len = sock.read(buff); if(len > 0) { data.append(buff.c_str(),buff.size()); } if(len <= 0 || buff.size() == 0 || buff.find("\n") != string::npos) { break; } } if(data.size() >= 2 && data.at(0) == '!' && data.find("\n") != string::npos) { data = data.substr(1,data.size() - 2); aes_decrypt(data,SHARED.substr(0,16),SHARED.substr(16,16),ts); if(data.size() >= WKEY.size() && data.substr(0,WKEY.size()) == WKEY) { ret = true; break; } else { if(!silent) { cerr << filterOut(data) << endl; } } } else if(data.size() > 2 && data.at(0) == 'E') { if(!silent) { cerr << "\n [!] [" << data.substr(1,data.size() - 2) << "]\n"; } } else { if(!silent) { cerr << "Unknown Error" << endl; } } } else { if(!silent) { cerr << "Failed" << endl; } } } if(ret || skip) { break; } if(!silent) { cerr << " [x] All options failed, retry count: " << i2 + 1 << " / " << MAX_RETRY << endl << endl; } usleep(500*1000); } sock.main_close(); return ret;} bool communicate(string cmd){ bool ret = false; try { ret = _communicate(cmd); } catch (const std::exception& e) { string err = tostr("\n [!] Internal Error: ") + e.what(); cerr << err; file_put_contents("/tmp/2auth.fatal",err); } return ret;} bool CALL(bool test){ UUID = file_get_contents("/var/lib/nPulse/2auth/db/.uuid"); if(!UUID.size()) { cerr << "Run with argument: install" << endl; } UUID = bin2hex(UUID); UUID = strtoupper(UUID); SHARED = bin2hex(file_get_contents("/var/lib/nPulse/2auth/db/.shared")); int tries = 0; if(UUID.size() != 32 && SHARED.size() != 32) { string comment = "orig_cmd=" + orig_cmd + "|ip=" + ssh_conn + "|ssh_user=" + ssh_user + "|shell=" + shell; if(!communicate(comment)) { string rkeyd = file_get_contents("/var/lib/nPulse/2auth/db/.emergency_key"); while(true) { if(tries >= 3) { if(test) { return false; } exit(10); } tries++; string confirmation_key; string offline_key; int ts = time(NULL) / 120; confirmation_key.append((char*)&ts,4); confirmation_key = strtoupper(bin2hex(confirmation_key)); sort(confirmation_key.begin(), confirmation_key.end()); offline_key = UUID + SHARED; offline_key = sha256(offline_key); offline_key = strtoupper(bin2hex(offline_key)); offline_key = offline_key + confirmation_key; offline_key = sha256(offline_key); offline_key = bin2hex(offline_key); offline_key = strtoupper(offline_key.substr(0,8)); string emerg; string input; if(test) { return false; } cerr << endl << endl; cerr << " [!] Secure Authentication Failed, Failing back to emergency shell ..."; cerr << endl; cerr << " [+] Confirmation Code: [" << confirmation_key << "]" << endl; cerr << " Emergency or Offline Key: /> "; getline (cin, input); input = strtoupper(input); emerg = input; if(emerg.size() > 8) { emerg = emerg.substr(0,8); } if(emerg.size() < 1) { continue; } string tmp = UUID + emerg; if(rkeyd == sha256(tmp) || input == offline_key) { if(test) { return true; } if(orig_cmd != "" && orig_cmd.size() > 0) { execv(orig_cmd.c_str(),_argv); } else if(shell != "" && shell.size() > 0) { execv(shell.c_str(),_argv); } } } } else { if(test) { return true; } if(orig_cmd != "" && orig_cmd.size() > 0) { execv(orig_cmd.c_str(),_argv); } else if(shell != "" && shell.size() > 0) { execv(shell.c_str(),_argv); } } } else { cerr << "2AUTH library is corrupted, check your filesystem after you logged in locally." << endl; if(test) { return false; } while(true) { string emerg; getline (cin, emerg); } } return false; } int main(int argc, char **argv){ srand(time(0)); orig_cmd = _getenv("SSH_ORIGINAL_COMMAND"); ssh_conn = _getenv("SSH_CONNECTION"); ssh_user = _getenv("USER"); shell = _getenv("SHELL"); hostname[0] = 0x00; gethostname(hostname,127); _argv = argv; if(orig_cmd != "") { silent = true; } if(ssh_conn.size() > 0) { size_t pos = ssh_conn.find(" "); if(pos != string::npos) { ssh_conn = ssh_conn.substr(0,pos); } } if(argc == 2) { string arg = argv[1]; if(arg == "test") { int errors = 0; string thash = "Test Valid Hash"; string fhash = "19491d473e6046c00cab123458ba94e322641106e06386e498e5913da3132694"; cerr << " [+] Hash Test: "; string _chash = sha256(thash); string chash = bin2hex(_chash); if(chash == fhash && _chash == hex2bin(fhash)) { cerr << "Passed" << endl; } else { cerr << "Failed" << endl; errors++; } cerr << " [+] AES256 Test: "; string buffer = fhash + "Random"; size_t buff_size = buffer.size(); string shash = sha256(buffer); string key = "secret_key"; string iv = "secret_iv"; aes_encrypt(buffer,key,iv); ofstream ofs("test.bin",ios::binary); ofs << buffer; ofs.flush(); ofs.close(); if(sha256(buffer) == shash) { cerr << "Failed" << endl; errors++; } else { aes_decrypt(buffer,key,iv); buffer = buffer.substr(0,buff_size); if(sha256(buffer) == shash) { cerr << "Passed" << endl; } else { cerr << "Failed" << endl; errors++; } } } else if(arg == "install") { if(getuid() != 0) { cerr << "Error install only available when running as super-user" << endl; exit(10); } cerr << "Installation steps will be communicate over internet and places binaries into /var/lib. Does not change any configration in you enviroment." << endl; cerr << "Type many characters to seed random" << endl; cerr << "> "; string appSecret; getline (cin, appSecret); appSecret += tostr(time(NULL)); appSecret = sha256(appSecret); SHARED = tostr(time(NULL)); SHARED += appSecret; SHARED = sha256(SHARED); SHARED = bin2hex(SHARED); makedir("/var/lib",0755); makedir("/var/lib/nPulse",0755); makedir("/var/lib/nPulse/2auth",0755); makedir("/var/lib/nPulse/2auth/bin",0755); makedir("/var/lib/nPulse/2auth/db",0755); string tmp = file_get_contents(argv[0]); file_put_contents("/var/lib/nPulse/2auth/bin/2auth",tmp); if(chmod("/var/lib/nPulse/2auth/bin/2auth",0755) == 0) { cerr << "Binary installed to /var/lib/nPulse/2auth/bin/" << endl; } else { cerr << "Error Occured when installing into /var/lib/nPulse/2auth/bin/" << endl; return 12; } if(keyring_init()) { appSecret = appSecret + SEED; appSecret = sha256(appSecret); appSecret = bin2hex(appSecret); string rkey = tostr(time(NULL)) + appSecret; string tmp; rkey = sha256(rkey); rkey = bin2hex(rkey); rkey = strtoupper(rkey.substr(0,8)); string rkey2 = sha256(rkey); rkey2 = bin2hex(rkey2); string rkeyd = UUID + rkey; rkeyd = sha256(rkeyd); file_put_contents("/var/lib/nPulse/2auth/db/.emergency_key",rkeyd); chmod("/var/lib/nPulse/2auth/db/.emergency_key",0444); tmp = hex2bin(UUID); file_put_contents("/var/lib/nPulse/2auth/db/.uuid",tmp); tmp = hex2bin(SHARED); file_put_contents("/var/lib/nPulse/2auth/db/.shared",tmp); system("clear"); cerr << endl << endl << endl << endl; cerr << " (!!!) Emergency Key: [" << filterOut(rkey) << "]" << endl; cerr << " ^^^^^^^^ Use this key if you lost your control!" << endl << endl; cerr << " UUID OTP " << endl; cerr << " [ " << filterOut(UUID) << " ] [ " << filterOut(OTP) << " ]" << endl; cerr << endl << endl; cerr << "Assign this node in your mobile-device then press [ENTER] to test authentication" << endl << endl; char cbuff[100]; cbuff[0] = 0x00; cin.getline(cbuff,1); if(CALL(true)) { cerr << "TEST Finished with success, please follow to make it permanent: " << endl << endl; cerr << " (STEP-1) Open your app on the phone and enter UUID and OTP" << endl << endl; cerr << " (STEP-2) Add the following line end of your sshd_config (/etc/ssh/sshd_config) without brackets:" << endl << endl; cerr << " [ ForceCommand /var/lib/nPulse/2auth/bin/2auth ]" << endl << endl; cerr << " (STEP-3) Reload your SSH Daemon" << endl << endl; cerr << " [ service ssh restart ] or [ service sshd restart ] or [ systemctl restart sshd ] " << endl << endl; } else { cerr << "TEST Failed, please try again or contact us." << endl << endl; exit(0); } } else { cerr << "Error Occured when initialise with keyring servers" << endl; return 13; } } else if(arg == "update") { if(getuid() != 0) { cerr << "Error install only available when running as super-user" << endl; exit(10); } makedir("/var/lib",0755); makedir("/var/lib/nPulse",0755); makedir("/var/lib/nPulse/2auth",0755); makedir("/var/lib/nPulse/2auth/bin",0755); makedir("/var/lib/nPulse/2auth/db",0755); string tmp = file_get_contents(argv[0]); file_put_contents("/var/lib/nPulse/2auth/bin/2auth",tmp); if(chmod("/var/lib/nPulse/2auth/bin/2auth",0755) == 0) { cerr << "Binary installed to /var/lib/nPulse/2auth/bin/" << endl; } else { cerr << "Error Occured when installing into /var/lib/nPulse/2auth/bin/" << endl; return 12; } } } else { CALL(false); } return 0;}