#include "stdafx.h" // Hack due to MFC project strangeness #define _WIN32_WINNT 0x0500 #include #include "interface.h" /* * This method computes the MD5 hash of the secret, text and destination * address. It should be clear how this can be extended to other hash * algorithms and arbitrary data. */ char* computeMD5Hash(const char* secret, const char* type, const char* content, const char* text, const char* destaddr) { // Needed to get the hash right since this media type has no netcn or netct const char* pad = "00000"; // Variables used during the hashing process HCRYPTPROV cryptoProvider; HCRYPTHASH rawHash; // Get the cryptographic provider for MD5 hashing // NOTE: This call could (potentially) fail and this should be checked for CryptAcquireContext(&cryptoProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); // Create an object that will perform the hash // NOTE: This call could (potentially) fail and this should be checked for CryptCreateHash(cryptoProvider, CALG_MD5, 0, 0, &rawHash); // Feed data into the hash // NOTE: These calls could (potentially) fail and this should be checked for CryptHashData(rawHash, (unsigned char*)secret, strlen(secret), 0); CryptHashData(rawHash, (unsigned char*)type, strlen(type), 0); CryptHashData(rawHash, (unsigned char*)content, strlen(content), 0); CryptHashData(rawHash, (unsigned char*)text, strlen(text), 0); CryptHashData(rawHash, (unsigned char*)pad, strlen(pad), 0); CryptHashData(rawHash, (unsigned char*)destaddr, strlen(destaddr), 0); // Extract the hash data // NOTE: This call could (potentially) fail and this should be checked for DWORD hashLength = 16; //(MD5 length) unsigned char* hashData = new unsigned char[hashLength]; CryptGetHashParam(rawHash, HP_HASHVAL, hashData, &hashLength, 0); // Create a hex-encoded string of the hash bytes char lut[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; char* hash = new char[33]; for(int i = 0; i < 16; i++) { hash[2 * i] = lut[(hashData[i] & 0xF0) >> 4]; hash[2 * i + 1] = lut[hashData[i] & 0x0F]; } hash[32] = '\0'; // After processing, cryptoProvider and hasher must be released. if(rawHash) { CryptDestroyHash(rawHash); } if(cryptoProvider) { CryptReleaseContext(cryptoProvider, 0); } delete[] hashData; return hash; } /* * This method performs the actual HTTP request that sends the SMS. It also * contains the information that is used to form the request. */ char* send_picture_message(char* destaddr) { const char* host = "proxy1.liv.haysystems.com"; const int port = 80; const char* action = "sendnok"; const char* client_id = ""; const char* type = "pg"; const char* content = "50340a232043726561746564206279205061696e74205368" \ "6f702050726f20370a37322032380a0000000000000000000003ffffffffffffff00000" \ "000000000000000e0000000000000000338000000000000000cee00000000000000131b" \ "01f81f8fe7c0006c06c0600618630000f001e0600630230000e000e0600630030000e00" \ "0e0600618030000e000e060061c030000e000e060060f030000e000e07ffe07830000e0" \ "00e0600601c30000e000e0600600e30000e000e0600600730000e000e0600600730000e" \ "000e0600620730080f001e0600630e301807c07c1f81fbf87ff801f1f00000000000000" \ "0ffe0000000000000003f80000000000000000e00000000000000000000000000000000" \ "00003ffffffffffffff000000000000000000"; const char* text = "this is a test message"; const char* url_encoded_text = "this+is+a+test+message"; const char* secret = ""; char* hash = computeMD5Hash(secret, type, content, text, destaddr); // Format the URL/request int buffer_size = strlen(action) + strlen(client_id) + strlen(destaddr) + strlen(type) + strlen(content) + strlen(url_encoded_text) + strlen(hash) + 80; const char* pattern = "GET /%s/?client_id=%s&destaddr=%s&type=%s" \ "&content=%s&text=%s&key=%s HTTP/1.0\r\n\r\n"; char* buffer = new char[buffer_size]; sprintf(buffer, pattern, action, client_id, destaddr, type, content, url_encoded_text, hash); // Clean up delete[] hash; // Create the socket CSocket socket; socket.Create(); // Try to connect to the server if(!socket.Connect(host, port)) { MessageBox(NULL, "unable to connect, check settings", "Error", MB_OK); } // These variables are used during the request and response code int bytesToIO = strlen(buffer); int totalBytesIOd = 0; int bytesIOd = 0; // Send the request while(totalBytesIOd < bytesToIO && (bytesIOd = socket.Send(buffer + totalBytesIOd, bytesToIO - totalBytesIOd, 0)) > 0) { totalBytesIOd += bytesIOd; } // If any errors occurred in the read process, bytesIOd will be SOCKET_ERROR // and appropriate action should be taken // Re-allocate the buffer for storing the response delete[] buffer; buffer = new char[4096]; // Receive the response bytesIOd = 0; totalBytesIOd = 0; while(totalBytesIOd < 4096 && (bytesIOd = socket.Receive(buffer + totalBytesIOd, 4096 - totalBytesIOd, 0)) > 0) { totalBytesIOd += bytesIOd; } // If any errors occurred in the read process, bytesIOd will be SOCKET_ERROR // and appropriate action should be taken // NULL-terminate the response we've read buffer[totalBytesIOd] = '\0'; // Close the socket socket.Close(); // Return the result of the request return buffer; }