void* client_thread(void* arg) { BankSocketThread* bankSocketThread = (BankSocketThread*) arg; Bank* bank = bankSocketThread->bank; BankSession* bankSession = new BankSession(); bankSession->state = 0; bankSession->bank = bank; bankSession->key = 0; long int csock = (long int)*(bankSocketThread->csock); printf("[bank] client ID #%ld connected\n", csock); //input loop int length; char packet[1024]; bool fatalError = false; std::vector<std::string> tokens; while(1) { fatalError = false; tokens.clear(); if(!listenPacket(csock, packet)) { printf("[bank] fail to read packet\n"); break; } if(!bankSession->key) { if(bankSession->state != 0) { printf("[error] Unexpected state\n"); break; } for(unsigned int i = 0; i < bank->keys.size(); ++i) { if(bank->keysInUse[i]) { continue; } if(decryptPacket((char*)packet,bank->keys[i]) && std::string(packet).substr(0,9) == "handshake") { bankSession->key = bank->keys[i]; bank->keysInUse[i] = true; break; } } if(!bankSession->key) { printf("[error] Key not found.\n"); break; } } else { if(!decryptPacket((char*)packet, bankSession->key)) { printf("[error] Invalid key\n"); break; } } //Parse the packet //std::string strPacket = packet; split(std::string(packet),',', tokens); //We should get something, if not ignore this packet if(tokens.size() < 1) { continue; } if(tokens[0] == "logout") { bankSession->endSession(); break; } //Now we're compare what we go to what state we expect to be in switch(bankSession->state) { case 0: case 1: if(tokens.size() == 2 && tokens[0] == "handshake" && tokens[1].size() == 128) { bankSession->atmNonce = tokens[1]; bankSession->bankNonce = makeHash(randomString(128)); if(bankSession->bankNonce.size() == 0) { printf("Unexpected error\n"); fatalError = true; break; } buildPacket(packet, "handshakeResponse," + bankSession->atmNonce + "," + bankSession->bankNonce); if(!encryptPacket((char*)packet,bankSession->key)) { printf("Unexpected error\n"); fatalError = true; break; } if(!sendPacket(csock, packet)) { printf("Unexpected error\n"); fatalError = true; break; } bankSession->state = 2; } break; //Expecting a login case 2: if(!bankSession->validateNonce(std::string(packet))) { printf("Unexpected error\n"); fatalError = true; break; } if(tokens.size() == 5 && tokens[0] == "login" && tokens[1].size() == 128) { //Now we'll try to find the account //bankSession->account = bank->tryLoginHash(tokens[1]); bankSession->account = bank->getAccountByName(tokens[2]); if(!bankSession->account || !bankSession->account->tryHash(tokens[1])) { //Failed login //TODO Blacklist hash bankSession->error = true; //printf("[notice] Failed login!\n"); } bankSession->account->inUse = true; bankSession->state = 5; if(!bankSession->sendP(csock,packet, "ack")) { printf("Unexpected error!\n"); fatalError = true; break; } } break; case 5: bool returnBalance = false; bankSession->state = 4; if(bankSession->error) { returnBalance = false; } else if(tokens.size() == 3 && tokens[0] == "balance") { returnBalance = true; } else if(tokens.size() == 4 && tokens[0] == "withdraw" && isDouble(tokens[1])) { double amount = atof(tokens[1].c_str()); if(!bankSession->account->Withdraw(amount)) { printf("[error] Failed withdraw\n"); returnBalance = false; bankSession->error = true; } returnBalance = true; } else if(tokens.size() == 5 && tokens[0] == "transfer" && !isDouble(tokens[1]) && isDouble(tokens[2])) { Account* accountTo = bank->getAccountByName(tokens[1]); double amount = atof(tokens[2].c_str()); if(!bankSession->account->Transfer(amount, accountTo)) { printf("[error] Failed transfer\n"); returnBalance = false; bankSession->error = true; } returnBalance = true; } if(bankSession->error) { bankSession->sendP(csock, packet, "denied"); } else if(returnBalance) { char moneyStr[256]; sprintf(moneyStr,"%.2Lf",bankSession->account->getBalance()); bankSession->sendP(csock, packet, std::string(moneyStr)); } //Reset back to initial state bankSession->endSession(); break; } if(fatalError) { bankSession->endSession(); break; } } bankSession->endSession(); printf("[bank] client ID #%ld disconnected\n", csock); close(csock); delete bankSession; return NULL; }
void* console_thread(void* arg) { BankSocketThread* bankSocketThread = (BankSocketThread*) arg; Bank* bank = bankSocketThread->bank; //Let's generate our keys for(unsigned int i = 1; i <= 50; ++i) { byte* key = new byte[CryptoPP::AES::DEFAULT_KEYLENGTH]; generateRandomKey(to_string((int)i),key, CryptoPP::AES::DEFAULT_KEYLENGTH); bank->keys.push_back(key); bank->keysInUse.push_back(false); } //Create Accounts Account* new_account = new Account(); //Alice new_account->createAccount(std::string("alice"), 1, std::string("123456"), bank->appSalt); new_account->Deposit(100); bank->addAccount(new_account); //Bob new_account = new Account(); new_account->createAccount(std::string("bob"), 2, std::string("234567"), bank->appSalt); new_account->Deposit(50); bank->addAccount(new_account); //Eve new_account = new Account(); new_account->createAccount(std::string("eve"), 3, std::string("345678"), bank->appSalt); new_account->Deposit(0); bank->addAccount(new_account); char buf[80]; while(1) { printf("bank> "); fgets(buf, 79, stdin); buf[strlen(buf)-1] = '\0'; //trim off trailing newline std::vector<std::string> tokens; split(buf,' ',tokens); if(tokens.size() <= 0) { printf("Invalid input\n"); continue; } if(tokens[0] == "balance") { if(tokens.size() != 2) { printf("Invalid input\n"); continue; } Account* current_account = bank->getAccountByName(tokens[1]); if(!current_account) { printf("Invalid account\n"); continue; } printf("Balance: %.2Lf\n", current_account->getBalance()); continue; } if(tokens[0] == "deposit") { if(tokens.size() != 3) { printf("Invalid input\n"); continue; } long double amount = atof(tokens[2].c_str()); if(amount <= 0) { printf("Invalid amount\n"); continue; } Account* current_account = bank->getAccountByName(tokens[1]); if(!current_account) { printf("Invalid account\n"); continue; } if(current_account->Deposit(amount)) { long double cur_balance = current_account->getBalance(); printf("Money deposited!\nNew balance: %.2Lf\n", cur_balance); } else { printf("Error depositing money!\n"); } continue; } } }