Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "RESTClient.h"
- #include "Hash.h"
- //#include <curl/curl.h>
- #include <string.h>
- #include <string>
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netdb.h>
- #include <netinet/in.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <openssl/ssl.h>
- #include <openssl/err.h>
- #include <fstream>
- #include <openssl/bio.h>
- #include <openssl/err.h>
- #include <openssl/pem.h>
- #include <openssl/x509.h>
- #include <openssl/x509_vfy.h>
- #include "Settings.h""
- #include "LoginEngine.h"
- #include "Utilities.h"
- #define MAXSZ 2048
- #define USE_JSON
- #ifdef USE_JSON
- #define CONTENT_TYPE "application/json"
- #else
- #define CONTENT_TYPE "application/x-www-form-urlencoded"
- #endif
- static void RestLog(const char* format, ...)
- {
- static FILE *g_sfpLogFile = NULL;
- if(!g_sfpLogFile && CSettings::GetInstance()->m_bLoggingEnabled)
- {
- g_sfpLogFile = fopen("/media/EyeballSDKLogs/rest.log", "w");
- if(g_sfpLogFile){
- fprintf(g_sfpLogFile, "=========== Log file opened for rest api calls (" __DATE__ ")============\n");
- }
- }
- va_list argptr;
- va_start(argptr, format);
- if(g_sfpLogFile){
- fprintf(g_sfpLogFile, "[%s] ", SGetTimeInMS().c_str());
- vfprintf(g_sfpLogFile, format, argptr);
- fflush(g_sfpLogFile);
- }
- vfprintf(stdout, format, argptr);
- va_end(argptr);
- }
- #define printf(...) RestLog(__VA_ARGS__)
- static size_t WriteDataCallback(char *ptr, size_t size, size_t nmemb, void *userdata)
- {
- std::string* pResponse = (std::string*)userdata;
- size_t total = size * nmemb;
- for (size_t i = 0; i < total; ++i)
- pResponse->push_back(*ptr++);
- return total;
- }
- #if 0
- int RESTClient::BlockingRequest(const std::string& strRequestUrl, std::string& strResponse, long nTimeout)
- {
- int nRet = 0;
- CURL *pCurlHandle;
- CURLcode res;
- curl_global_init(CURL_GLOBAL_DEFAULT);
- pCurlHandle = curl_easy_init();
- if(pCurlHandle) {
- curl_easy_setopt(pCurlHandle, CURLOPT_URL, strRequestUrl.c_str());
- curl_easy_setopt(pCurlHandle, CURLOPT_CONNECTTIMEOUT, nTimeout);
- curl_easy_setopt(pCurlHandle, CURLOPT_WRITEFUNCTION, WriteDataCallback);
- strResponse = "";
- curl_easy_setopt(pCurlHandle, CURLOPT_WRITEDATA, &strResponse);
- curl_easy_setopt(pCurlHandle, CURLOPT_SSL_VERIFYPEER, 0L); // skip ssl peer verification !!
- curl_easy_setopt(pCurlHandle, CURLOPT_SSL_VERIFYHOST, 0L); // skip ssl host verification !!
- /* Perform the request, res will get the return code */
- res = curl_easy_perform(pCurlHandle);
- /* Check for errors */
- if(res != CURLE_OK){
- nRet = -1;
- fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
- }
- curl_easy_cleanup(pCurlHandle);
- }
- curl_global_cleanup();
- return nRet;
- }
- #endif
- // Start of functions for sending HTTPS request
- int OpenConnection(const char *hostname, int port, int nTimeout)
- { int sd;
- struct hostent *host;
- struct sockaddr_in addr;
- if ( (host = gethostbyname(hostname)) == NULL )
- {
- printf("Error retrieving DNS information.\n");
- return -1;
- }
- sd = socket(PF_INET, SOCK_STREAM, 0);
- if(sd < 0)
- {
- printf("Error creating socket\n");
- return -1;
- }
- struct timeval timeout;
- timeout.tv_sec = 2;
- timeout.tv_usec = 0;
- if(setsockopt(sd, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof timeout) < 0)
- {
- printf("setsockopt failed\n");
- return -1;
- }
- timeout.tv_sec = nTimeout;
- timeout.tv_usec = 0;
- if(setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof timeout) < 0)
- {
- printf("setsockopt failed\n");
- return -1;
- }
- bzero(&addr, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_port = htons(port);
- addr.sin_addr.s_addr = *(long*)(host->h_addr);
- if ( connect(sd, (struct sockaddr*)&addr, sizeof(addr)) != 0 )
- {
- close(sd);
- perror(hostname);
- return -1;
- }
- return sd;
- }
- SSL_CTX* InitCTX(void)
- { const SSL_METHOD *method;
- SSL_CTX *ctx;
- OpenSSL_add_all_algorithms(); /* Load cryptos, et.al. */
- SSL_load_error_strings(); /* Bring in and register error messages */
- ERR_load_BIO_strings();
- ERR_load_crypto_strings();
- method = SSLv3_client_method(); /* Create new client-method instance */
- ctx = SSL_CTX_new(method); /* Create new context */
- if ( ctx == NULL )
- {
- ERR_print_errors_fp(stderr);
- return NULL;
- }
- return ctx;
- }
- void ShowCerts(SSL* ssl)
- {
- X509 *cert;
- char *line;
- cert = SSL_get_peer_certificate(ssl); /* get the server's certificate */
- if ( cert != NULL )
- {
- printf("Server certificates:\n");
- line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
- printf("Subject: %s\n", line);
- free(line); /* free the malloc'ed string */
- line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
- printf("Issuer: %s\n", line);
- free(line); /* free the malloc'ed string */
- X509_free(cert); /* free the malloc'ed certificate copy */
- }
- else
- printf("No certificates.\n");
- }
- // End of Functions for HTTPS
- int RESTClient::BlockingRequest(const std::string& strRequestUrl, std::string& strResponse, long nTimout)
- {
- printf(" --- Blocking Request Called\n");
- strResponse = "";
- std::string strHost = "", strUri = "";
- std::string strPort = "";
- int nPort = 80;
- bool bSecuredProtocol = false;
- int pos = 7; // http:// skipped
- if(strRequestUrl[4] == 's')
- {
- bSecuredProtocol = true;
- pos = 8;
- }
- if(pos >= strRequestUrl.size()){
- printf("http or https not found in the request url %s\n", strRequestUrl.c_str());
- return -1;
- }
- while(pos < strRequestUrl.size() && ( strRequestUrl[pos] != ':' && strRequestUrl[pos] != '/') ){
- strHost.push_back(strRequestUrl[pos++]);
- }
- if(pos == strRequestUrl.size()){
- printf("http or https found at the end of the request url %s\n", strRequestUrl.c_str());
- return -1;
- }
- // Port number is determined
- if(strRequestUrl[pos] == ':')
- {
- pos++;
- while(pos < strRequestUrl.size() && strRequestUrl[pos] != '/')
- strPort.push_back(strRequestUrl[pos++]);
- nPort = atoi( strPort.c_str() );
- }
- if(pos == strRequestUrl.size()){
- printf("http or https found still at the end of the request url %s\n", strRequestUrl.c_str());
- return -1;
- }
- strUri = strRequestUrl.substr(pos);
- printf("Blocking Request host: %s %s %d\n", bSecuredProtocol ? "https" : "http", strHost.c_str(), nPort);
- printf("Blocking Request request: %s\n", strUri.c_str());
- int ret;
- if(bSecuredProtocol == false)
- ret = BlockingRequest_HTTP(strHost, strUri, nPort, strResponse, nTimout);
- else
- ret = BlockingRequest_HTTPS(strHost, strUri, nPort, strResponse, nTimout);
- printf("Response: %s\n", strResponse.c_str());
- std::string end_of_header = "\r\n\r\n";
- size_t pos_of_end_of_header = strResponse.find(end_of_header);
- if(pos_of_end_of_header != std::string::npos){
- strResponse = strResponse.substr(pos_of_end_of_header + end_of_header.size());
- }
- else{
- strResponse = "";
- return -1;
- }
- return ret;
- }
- int RESTClient::BlockingRequest_HTTP(const std::string &hst, std::string &org_uri, int nPort, std::string &response, long nTimeout)
- {
- printf("host: %s\nuri = %s\n", hst.c_str(), org_uri.c_str());
- const char *hstname = hst.c_str(), *uri, *myReq;
- struct hostent *host = gethostbyname(hstname);
- std::string sUri = org_uri.substr(0, org_uri.find("?"));
- std::string sReq = org_uri.substr(org_uri.find("?") + 1);
- uri = ( sUri.c_str() );
- #ifdef USE_JSON
- char szJsonReq[MAXSZ];
- ParseIntoJson(sReq, szJsonReq);
- myReq = szJsonReq;
- #else
- myReq = ( sReq.c_str() );
- #endif
- if( (host == NULL) )
- {
- printf("Error retrieving DNS information.\n");
- return -1;
- }
- struct sockaddr_in client;
- memset(&client, 0, sizeof client);
- client.sin_family = AF_INET;
- client.sin_port = htons(nPort);
- memcpy(&client.sin_addr, host->h_addr, host->h_length);
- int sock = socket(AF_INET, SOCK_STREAM, 0);
- if(sock < 0)
- {
- printf("Error creating socket\n");
- return -1;
- }
- struct timeval timeout;
- timeout.tv_sec = 2;
- timeout.tv_usec = 0;
- if(setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof timeout) < 0)
- {
- printf("setsockopt failed\n");
- return -1;
- }
- timeout.tv_sec = nTimeout;
- timeout.tv_usec = 0;
- if(setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof timeout) < 0)
- {
- printf("setsockopt failed\n");
- return -1;
- }
- int conn = connect(sock, (struct sockaddr *)&client, sizeof client);
- if(conn>=0)
- {
- printf("Sending HTTP Request\n");
- char sendline[MAXSZ + 1], recvline[MAXSZ + 1];
- int n;
- sprintf(sendline,
- "POST %s HTTP/1.0\r\n"
- "Host: %s:%d\r\n"
- "Content-Type: "CONTENT_TYPE"\r\n"
- "Content-Length: %d\r\n"
- "\r\n"
- "%s\r\n"
- "\r\n\r\n", uri, hstname, nPort, strlen(myReq), myReq);
- if( (send(sock, sendline, strlen(sendline), 0)) != (strlen(sendline)) )
- {
- printf("Error sending request\n");
- return -1;
- }
- while( (n = recv(sock, recvline, MAXSZ, 0)) > 0 )
- {
- recvline[n] = '\0';
- response += recvline;
- }
- }
- close(sock);
- return 0;
- }
- #define CASSERT(X, ...) \
- if(!X) { \
- printf(__VA_ARGS__); \
- return false; \
- }
- bool VerifiyCertificate(SSL *ssl) {
- OpenSSL_add_all_algorithms();
- ERR_load_BIO_strings();
- ERR_load_crypto_strings();
- X509_STORE *store = NULL;
- X509_STORE_CTX *vrfy_ctx = NULL;
- int ret;
- /* get the server's certificate */
- X509 *server_cert = SSL_get_peer_certificate(ssl);
- const char *path = "/foo/bar/ss.pem";
- FILE *fp = fopen(path, "r");
- if(!fp) return false;
- fseek(fp, 0, SEEK_END);
- size_t size = ftell(fp);
- char *cert_data = new char[size];
- rewind(fp);
- fread(cert_data, sizeof(char), size, fp);
- fclose(fp);
- store = X509_STORE_new();
- CASSERT(store != NULL, "Error creating X509_STORE_CTX object\n");
- vrfy_ctx = X509_STORE_CTX_new();
- ret = X509_STORE_load_locations(store, cert_data, NULL);
- CASSERT(ret == 1, "Error loading CA cert or chain file\n");
- X509_STORE_set_flags(store, 0);
- X509_STORE_CTX_init(vrfy_ctx, store, server_cert, NULL);
- ret = X509_verify_cert(vrfy_ctx);
- X509_free(server_cert);
- delete [] cert_data;
- X509_STORE_CTX_free(vrfy_ctx);
- X509_STORE_free(store);
- return ret == 1;
- }
- int RESTClient::BlockingRequest_HTTPS(const std::string &hst, std::string &org_uri, int nPort, std::string &response, long nTimeout)
- {
- // https://202.53.167.179:4443/restapi/setup.php?service=getSensorHistory&user_id=moshiur&baby_id=baby3
- // https://202.53.167.179:4443/restapi/test.php
- SSL_CTX *ctx;
- int server;
- SSL *ssl;
- int bytes;
- const char *hostname, *uri, *myReq;
- hostname = hst.c_str();
- response = "";
- std::string sUri = org_uri.substr(0, org_uri.find("?"));
- std::string sReq = org_uri.substr(org_uri.find("?") + 1);
- uri = ( sUri.c_str() );
- #ifdef USE_JSON
- char szJsonReq[MAXSZ];
- ParseIntoJson(sReq, szJsonReq);
- myReq = szJsonReq;
- #else
- myReq = ( sReq.c_str() );
- #endif
- printf("URI: %s // myReq: %s\n", uri, myReq);
- SSL_library_init();
- ctx = InitCTX();
- if(ctx == NULL){
- printf("Init of ssl context failed\n");
- return -1;
- }
- server = OpenConnection(hostname, nPort, nTimeout);
- ssl = SSL_new(ctx); /* create new SSL connection state */
- SSL_set_fd(ssl, server); /* attach the socket descriptor */
- int SSL_connect_ret = SSL_connect(ssl);
- printf("SSL_connect_ret = %d reason = %d\n", SSL_connect_ret, SSL_get_error(ssl,SSL_connect_ret));
- if (SSL_connect_ret == -1 ) /* perform the connection */
- ERR_print_errors_fp(stderr);
- else
- {
- char buf[MAXSZ + 1], msg[MAXSZ + 1];
- sprintf(msg,
- "POST %s HTTP/1.0\r\n"
- "Host: %s:%d\r\n"
- "Content-Type: "CONTENT_TYPE"\r\n"
- #ifdef EPHEMERAL_SECURITY
- "Client-Secret: %s\r\n"
- "Client-ID: %s\r\n"
- #endif
- "Content-Length: %d\r\n"
- "\r\n"
- "%s\r\n"
- "\r\n\r\n", uri, hostname, nPort
- #ifdef EPHEMERAL_SECURITY
- , CreateClientSecretHeader(myReq).c_str(), CSettings::GetInstance()->m_sUsername.c_str()
- #endif
- , strlen(myReq), myReq);
- printf("Connected with %s encryption\n", SSL_get_cipher(ssl));
- ShowCerts(ssl); /* get any certs */
- // TODO: certificate verification
- if(VerifiyCertificate(ssl)) {
- printf("Certificate verification success.\n")
- } else {
- printf("Certificate verification failed.\n");
- close(server);
- break;
- }
- int nError = SSL_write(ssl, msg, strlen(msg)); /* encrypt & send message */
- if(nError < 1)
- printf("SSL write returned = %d reason = %d\n", nError, SSL_get_error(ssl,nError));
- while( (bytes = SSL_read(ssl, buf, sizeof(buf))) > 0) { /* get reply & decrypt */
- buf[bytes] = '\0';
- response += buf;
- }
- SSL_free(ssl); /* release connection state */
- }
- printf("///// DONE SENDING USING HTTPS ////////\n");
- close(server); /* close socket */
- SSL_CTX_free(ctx); /* release context */
- #ifdef EPHEMERAL_SECURITY
- std::string sStatus = ParseValueForKey(response, "status");
- if(sStatus == "failed")
- {
- std::string sReason = ParseValueForKey(response, "reason");
- if(sReason == "Credential expired")
- {
- printf("Ephemeral credentials expired\n");
- if(!LoginEngine::GetInstance()->GetEphemeralCredentials())
- {
- printf("Forcefully logging out\n");
- LoginEngine::GetInstance()->xmppLogout();
- LoginEngine::GetInstance()->handleXmppLoginResponse(-1);
- }
- }
- }
- #endif
- return 0;
- }
- int RESTClient::ParseIntoJson(const std::string& strSrc, char* pcDest)
- {
- const char *pcSrc = strSrc.c_str();
- *pcDest++ = '{';
- *pcDest++ = '\"';
- while(*pcSrc != '\0')
- {
- if(*pcSrc == '&')
- {
- *pcDest++ = '\"';
- *pcDest++ = ',';
- *pcDest++ = '\"';
- }
- else if(*pcSrc == '=')
- {
- *pcDest++ = '\"';
- *pcDest++ = ':';
- *pcDest++ = '\"';
- }
- else
- {
- *pcDest++ = *pcSrc;
- }
- pcSrc ++;
- }
- *pcDest++ = '\"';
- *pcDest++ = '}';
- *pcDest = '\0';
- return strlen(pcDest);
- }
- // assuming, the json has the format = { "key1" : "value1", "key2": "value2" ... }
- std::string RESTClient::ParseValueForKey(const std::string& strJson, const std::string strKey)
- {
- size_t pos = ToLower(strJson).find("\"" + ToLower(strKey) + "\"");
- if(pos == string::npos)
- return "";
- pos += strKey.size() + 2;
- while(pos < strJson.size() && strJson[pos] != ':')
- ++pos;
- if(pos == strJson.size())
- return "";
- ++pos;
- while(pos < strJson.size() && strJson[pos] != '"')
- ++pos;
- if(pos == strJson.size())
- return "";
- ++pos;
- std::string ret = "";
- while(pos < strJson.size() && strJson[pos] != '"')
- ret += strJson[pos++];
- if(pos == strJson.size())
- return "";
- return ret;
- }
- std::string RESTClient::CreateClientSecretHeader(const std::string &sMsg)
- {
- string sUsername = CSettings::GetInstance()->m_sUsername;
- string sPassword = CSettings::GetInstance()->m_sPassword;
- string sDomain = CSettings::GetInstance()->m_sXmppDomain;
- string sHash_md5 = GenerateHash_md5((sUsername + ':' + sDomain + ':' + sPassword).c_str());
- string sHash_sha256 = GenerateHash_sha256((sHash_md5 + ':' + sMsg).c_str());
- return sHash_sha256;
- }
- #if 0
- int RESTClient::NonBlockingRequest(const std::string& strRequestUrl, long nTimout, void (*ResponseCallback) (std::string strResponse, void* args))
- {
- }
- #endif
Advertisement
Add Comment
Please, Sign In to add comment