#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* text, const char* destaddr) { // 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*)text, strlen(text), 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_sms(char* destaddr) { const char* host = "sms.haysystems.com"; const int port = 80; const char* action = "sendtxt"; const char* client_id = ""; const char* text = "this is a test message"; const char* urlEncodedText = "this+is+a+test+message"; const char* secret = ""; char* hash = computeMD5Hash(secret, text, destaddr); // Format the URL/request char* buffer = new char[strlen(urlEncodedText) + 1024]; sprintf(buffer, "GET /%s/?client_id=%s&text=%s&destaddr=%s&key=%s HTTP/1.0\r\n\r\n", action, client_id, urlEncodedText, destaddr, 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; }