diff options
Diffstat (limited to 'mobicore/rootpa/Code/Common/seclient.c')
-rw-r--r-- | mobicore/rootpa/Code/Common/seclient.c | 245 |
1 files changed, 138 insertions, 107 deletions
diff --git a/mobicore/rootpa/Code/Common/seclient.c b/mobicore/rootpa/Code/Common/seclient.c index e95cbc9..e08a7c7 100644 --- a/mobicore/rootpa/Code/Common/seclient.c +++ b/mobicore/rootpa/Code/Common/seclient.c @@ -3,35 +3,35 @@ Copyright © Trustonic Limited 2013 All rights reserved. -Redistribution and use in source and binary forms, with or without modification, +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the Trustonic Limited nor the names of its contributors - may be used to endorse or promote products derived from this software + 3. Neither the name of the Trustonic Limited nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include <string.h> #include <stdlib.h> -#include <stdbool.h> +#include <wrapper.h> #include <time.h> #include <math.h> @@ -68,11 +68,36 @@ OF THE POSSIBILITY OF SUCH DAMAGE. static char certificatePath_[CERT_PATH_MAX_LEN]; static char certificateFilePath_[CERT_PATH_MAX_LEN]; static long int SE_CONNECTION_DEFAULT_TIMEOUT=58L; // timeout after 58 seconds -static int MAX_ATTEMPTS=30; -static const struct timespec SLEEPTIME={0,300*1000*1000}; // 0.3 seconds --> 30x0.3 = 9 seconds +static int MAX_ATTEMPTS=30; //30x0.3 = 9 seconds +#ifdef WIN32 + static const DWORD SLEEPTIME_MS=300; // 0.3 seconds +#else + static const struct timespec SLEEPTIME={0,300*1000*1000}; // 0.3 seconds +#endif rootpaerror_t httpCommunicate(const char* const inputP, const char** linkP, const char** relP, const char** commandP, httpMethod_t method); +#ifdef WIN32 + + char* strcasestr(char const *s, char const *find) + { + char* pos; + char* ret; + char* ls=_strdup(s); + char* lfind=_strdup(find); + + ls=_strlwr(ls); + lfind=_strlwr(lfind); + pos = strstr(ls, lfind); + ret = pos == NULL ? NULL : (char *)(s + (pos-ls)); + free(ls); + free(lfind); + return ret; + } + + +#endif + rootpaerror_t httpPostAndReceiveCommand(const char* const inputP, const char** linkP, const char** relP, const char** commandP) { LOGD("httpPostAndReceiveCommand %ld", (long int) inputP); @@ -104,14 +129,14 @@ rootpaerror_t httpDeleteAndReceiveCommand(const char** linkP, const char** relP, } -typedef struct +typedef struct { char* memoryP; size_t size; } MemoryStruct; + - -typedef struct +typedef struct { char* linkP; size_t linkSize; @@ -119,7 +144,7 @@ typedef struct size_t relSize; } HeaderStruct; -typedef struct +typedef struct { const char* responseP; size_t size; @@ -135,7 +160,7 @@ static size_t readResponseCallback(void *ptr, size_t size, size_t nmemb, void *u LOGD(">>readResponseCallback %d %d %d\n", (int) totalSize, (int) rspP->size, rspP->offset); if(rspP->offset>=rspP->size) return 0; - + if(totalSize<((rspP->size))) { readSize=totalSize; @@ -152,32 +177,32 @@ static size_t readResponseCallback(void *ptr, size_t size, size_t nmemb, void *u LOGD("<<readResponseCallback %d %d %d\n", (int) readSize, (int) rspP->size, rspP->offset); return readSize; } - + static size_t writeMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp) { size_t realsize = size * nmemb; MemoryStruct* mem = (MemoryStruct *)userp; - - mem->memoryP = realloc(mem->memoryP, mem->size + realsize + 1); + mem->memoryP = (char*)realloc(mem->memoryP, mem->size + realsize + 1); if (mem->memoryP == NULL) { - /* out of memory! */ + /* out of memory! */ LOGE("not enough memory (realloc returned NULL)\n"); return 0; // returning anything different from what was passed to this function indicates an error } - + memcpy(&(mem->memoryP[mem->size]), contents, realsize); mem->size += realsize; mem->memoryP[mem->size] = 0; - + return realsize; } - + #ifdef __DEBUG int debug_function (CURL * curl_handle, curl_infotype info, char* debugMessageP, size_t debugMessageSize, void * extrabufferP) { if(debugMessageP!=NULL && debugMessageSize!=0) { - char* msgP=malloc(debugMessageSize+1); + char* msgP=(char*)malloc(debugMessageSize+1); + if(NULL==msgP)return 0; memcpy(msgP, debugMessageP, debugMessageSize); msgP[debugMessageSize]=0; LOGD("curl: %d %s",info, msgP); @@ -193,20 +218,20 @@ int debug_function (CURL * curl_handle, curl_infotype info, char* debugMessageP, bool copyHeader(void *contents, size_t length, char** headerP) { - *headerP = malloc(length + 1); + *headerP = (char *)malloc(length + 1); if (*headerP == NULL) { - /* out of memory! */ + /* out of memory! */ LOGE("not enough memory (malloc returned NULL)\n"); return false; } - + memcpy(*headerP , contents, length); - (*headerP)[length] = 0; + (*headerP)[length] = 0; return true; } // -// The header format is as follow +// The header format is as follow // Link <https://se.cgbe.trustonic.com:8443/activity/00000000-4455-6677-8899-aabbccddeeff>;rel="http://10.0.2.2/relation/system_info" // parse out uri's specified in Link and rel // @@ -219,11 +244,11 @@ bool updateLinkAndRel(HeaderStruct* memP, void* ptr) startP=strcasestr((char*) ptr, "Link"); if(NULL==startP) return false; - + startP=strstr(startP,"<"); if(NULL==startP) return false; startP++; - + endP=strstr(startP,">"); if(NULL==endP) return false; @@ -239,14 +264,14 @@ bool updateLinkAndRel(HeaderStruct* memP, void* ptr) if(NULL==startP) { return true; - } + } startP+=5; // sizeof "rel=" - + endP=strstr(startP,"\""); if(NULL==endP) { - return true; - } + return true; + } memP->relSize=endP-startP; if(copyHeader(startP, memP->relSize, &(memP->relP))==false) { @@ -281,27 +306,27 @@ void setCertPath(const char* localPathP, const char* certPathP) { memset(certificatePath_, 0, CERT_PATH_MAX_LEN); memset(certificateFilePath_, 0, CERT_PATH_MAX_LEN); - - if (certPathP!=NULL && (strlen(certPathP)+1)<CERT_PATH_MAX_LEN) + + if (certPathP!=NULL && (strlen(certPathP)+1)<CERT_PATH_MAX_LEN) { - strcpy(certificatePath_, certPathP); + strlcpy(certificatePath_, certPathP, sizeof(certificatePath_)); } - - if (localPathP!=NULL && (strlen(localPathP)+1+sizeof(CECERT_FILENAME))<CERT_PATH_MAX_LEN) + + if (localPathP!=NULL && (strlen(localPathP)+1+sizeof(CECERT_FILENAME))<CERT_PATH_MAX_LEN) { - strcpy(certificateFilePath_, localPathP); - strcat(certificateFilePath_, "/"); + strlcpy(certificateFilePath_, localPathP,sizeof(certificateFilePath_)); + strlcat(certificateFilePath_, "/",sizeof(certificateFilePath_)); } - strcat(certificateFilePath_, CECERT_FILENAME); + strlcat(certificateFilePath_, CECERT_FILENAME,sizeof(certificateFilePath_)); } // // TODO-refactor: saveCertFile is duplicate from saveFile in xmlMessageHandler.c, move these to common place // void saveCertFile(char* filePath, char* fileContent) { - LOGD(">>saveCertFile %s", filePath); FILE* fh; - if ((fh = fopen(filePath, "w")) != NULL) // recreating the file every time, this is not the most efficient way, but ensures + LOGD(">>saveCertFile %s", filePath); + if ((fh = fopen(filePath, "w")) != NULL) // recreating the file every time, this is not the most efficient way, but ensures { // the file is updated in case rootpa and the required content is updated fprintf(fh, "%s", fileContent); fclose(fh); @@ -315,19 +340,21 @@ void saveCertFile(char* filePath, char* fileContent) bool setBasicOpt(CURL* curl_handle, MemoryStruct* chunkP, HeaderStruct* headerChunkP, const char* linkP, struct curl_slist* headerListP) { + long int se_connection_timeout=SE_CONNECTION_DEFAULT_TIMEOUT; + if(curl_easy_setopt(curl_handle, CURLOPT_URL, linkP)!=CURLE_OK) { LOGE("curl_easy_setopt CURLOPT_URL failed"); return false; } - + /* reading response to memory instead of file */ if(curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, writeMemoryCallback)!=CURLE_OK) { LOGE("curl_easy_setopt CURLOPT_WRITEFUNCTION failed"); return false; } - + if(curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, writeHeaderCallback)!=CURLE_OK) { LOGE("curl_easy_setopt CURLOPT_HEADERFUNCTION failed"); @@ -352,9 +379,9 @@ bool setBasicOpt(CURL* curl_handle, MemoryStruct* chunkP, HeaderStruct* headerCh LOGE("curl_easy_setopt CURLOPT_HTTPHEADER failed"); return false; } - + /* some servers don't like requests that are made without a user-agent - field, so we provide one */ + field, so we provide one */ if(curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "rpa/1.0")!=CURLE_OK) { LOGE("curl_easy_setopt CURLOPT_USERAGENT failed"); @@ -369,7 +396,7 @@ bool setBasicOpt(CURL* curl_handle, MemoryStruct* chunkP, HeaderStruct* headerCh saveCertFile(certificateFilePath_, CA_CERTIFICATES); - + LOGD("curl_easy_setopt CURLOPT_CAINFO %s", certificateFilePath_); if(curl_easy_setopt(curl_handle, CURLOPT_CAINFO, certificateFilePath_)!=CURLE_OK) { @@ -382,19 +409,18 @@ bool setBasicOpt(CURL* curl_handle, MemoryStruct* chunkP, HeaderStruct* headerCh { LOGE("curl_easy_setopt CURLOPT_CAPATH failed"); return false; - } + } - long int se_connection_timeout=SE_CONNECTION_DEFAULT_TIMEOUT; #ifdef __DEBUG curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1L); - curl_easy_setopt(curl_handle, CURLOPT_DEBUGFUNCTION, debug_function); - + curl_easy_setopt(curl_handle, CURLOPT_DEBUGFUNCTION, debug_function); + if(strncmp(linkP, NONEXISTENT_TEST_URL, shorter(strlen(NONEXISTENT_TEST_URL), strlen(linkP)))==0) { se_connection_timeout=3L; // reducing the connection timeout for testing purposes MAX_ATTEMPTS=1; // this is for testint code, we are using nonexitent url here so no unncessary attempts LOGD("setBasicOpt timeout set to %ld", se_connection_timeout); - } + } #endif if(curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, se_connection_timeout)!=CURLE_OK) @@ -404,7 +430,7 @@ bool setBasicOpt(CURL* curl_handle, MemoryStruct* chunkP, HeaderStruct* headerCh } /** libcurl uses the http_proxy and https_proxy environment variables for proxy settings. - That variable is set in the OS specific wrapper. These are left here in order to make + That variable is set in the OS specific wrapper. These are left here in order to make this comment earier to be found in searches. curl_easy_setopt(curl_handle,CURLOPT_PROXY, "http://proxyaddress"); @@ -412,7 +438,7 @@ bool setBasicOpt(CURL* curl_handle, MemoryStruct* chunkP, HeaderStruct* headerCh curl_easy_setopt(curl_handle,CURLOPT_PROXYUSERNAME, "read_proxy_username"); curl_easy_setopt(curl_handle,CURLOPT_PROXYPASSWORD, "read_proxy_password"); */ - + return true; } @@ -420,6 +446,7 @@ bool setBasicOpt(CURL* curl_handle, MemoryStruct* chunkP, HeaderStruct* headerCh bool setPutOpt(CURL* curl_handle, ResponseStruct* responseChunk) { + long chunkSize=responseChunk->size; LOGD(">>setPutOpt"); if (curl_easy_setopt(curl_handle, CURLOPT_READFUNCTION, readResponseCallback)!=CURLE_OK) { @@ -445,13 +472,13 @@ bool setPutOpt(CURL* curl_handle, ResponseStruct* responseChunk) return false; } - long s=responseChunk->size; - if (curl_easy_setopt(curl_handle, CURLOPT_INFILESIZE, s)!=CURLE_OK) + + if (curl_easy_setopt(curl_handle, CURLOPT_INFILESIZE, chunkSize)!=CURLE_OK) { LOGE("curl_easy_setopt CURLOPT_INFILESIZE_LARGE failed"); return false; } - + LOGD("<<setPutOpt"); return true; } @@ -459,14 +486,14 @@ bool setPutOpt(CURL* curl_handle, ResponseStruct* responseChunk) bool setPostOpt(CURL* curl_handle, const char* inputP) { LOGD(">>setPostOpt %ld %d", (long int) inputP, inputP?(int)strlen(inputP):0); - + if (curl_easy_setopt(curl_handle, CURLOPT_POST, 1L)!=CURLE_OK) { LOGE("curl_easy_setopt CURLOPT_POST failed"); return false; } - if(NULL==inputP) + if(NULL==inputP) { if (curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDSIZE, 0L)!=CURLE_OK) { @@ -474,7 +501,7 @@ bool setPostOpt(CURL* curl_handle, const char* inputP) return false; } } - + if (curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, (void*) inputP)!=CURLE_OK) { LOGE("curl_easy_setopt CURLOPT_POSTFIELDS failed"); @@ -539,6 +566,14 @@ rootpaerror_t httpCommunicate(const char * const inputP, const char** linkP, con time_t endtime=0; int timediff=0; + ResponseStruct responseChunk; + MemoryStruct chunk; + HeaderStruct headerChunk; + headerChunk.linkSize = 0; + headerChunk.relSize = 0; + headerChunk.linkP = NULL; + headerChunk.relP = NULL; + LOGD(">>httpCommunicate"); if(NULL==linkP || NULL==relP || NULL==commandP || NULL==*linkP) { @@ -548,17 +583,8 @@ rootpaerror_t httpCommunicate(const char * const inputP, const char** linkP, con *commandP=NULL; *relP=NULL; - ResponseStruct responseChunk; - - HeaderStruct headerChunk; - headerChunk.linkSize = 0; - headerChunk.relSize = 0; - headerChunk.linkP = NULL; - headerChunk.relP = NULL; - - MemoryStruct chunk; - chunk.size = 0; /* no data at this point */ - chunk.memoryP = malloc(1); /* will be grown as needed by the realloc above */ + chunk.size = 0; /* no data at this point */ + chunk.memoryP = (char *)malloc(1); /* will be grown as needed by the realloc above */ if(NULL==chunk.memoryP) { return ROOTPA_ERROR_OUT_OF_MEMORY; @@ -566,7 +592,7 @@ rootpaerror_t httpCommunicate(const char * const inputP, const char** linkP, con chunk.memoryP[0]=0; LOGD("HTTP method %d", method); - + //Process HTTP methods if(method == httpMethod_PUT) { @@ -609,24 +635,28 @@ rootpaerror_t httpCommunicate(const char * const inputP, const char** linkP, con } } - /* disable Expect: 100-continue since it creates problems with some proxies, it is only related to post but we do it here for simplicity */ + /* disable Expect: 100-continue since it creates problems with some proxies, it is only related to post but we do it here for simplicity */ httpHeaderP = curl_slist_append(httpHeaderP, "Expect:"); httpHeaderP = curl_slist_append(httpHeaderP, "Content-Type: application/vnd.mcorecm+xml;v=1.0"); - httpHeaderP = curl_slist_append(httpHeaderP, "Accept: application/vnd.mcorecm+xml;v=1.0"); + httpHeaderP = curl_slist_append(httpHeaderP, "Accept: application/vnd.mcorecm+xml;v=1.0"); if(setBasicOpt(curl_handle_, &chunk, &headerChunk, *linkP, httpHeaderP)==false) { LOGE("setBasicOpt failed"); free(chunk.memoryP); - return ROOTPA_ERROR_NETWORK; + return ROOTPA_ERROR_NETWORK; } - begintime=time(NULL); + begintime=time(NULL); while(curlRet!=CURLE_OK && attempts++ < MAX_ATTEMPTS) { curlRet=curl_easy_perform(curl_handle_); LOGD("curl_easy_perform %ld %d", curlRet, attempts ); if(CURLE_OK==curlRet) break; +#ifdef WIN32 + Sleep(SLEEPTIME_MS); +#else nanosleep(&SLEEPTIME,NULL); +#endif endtime=time(NULL); timediff=(int)ceil(difftime(endtime, begintime)); LOGD("timediff (ceil) %d", timediff); @@ -638,37 +668,37 @@ rootpaerror_t httpCommunicate(const char * const inputP, const char** linkP, con } curl_easy_getinfo (curl_handle_, CURLINFO_RESPONSE_CODE, &http_code); - if(curlRet!=CURLE_OK) + if(curlRet!=CURLE_OK) { LOGE("curl_easy_perform failed %ld", curlRet); free(chunk.memoryP); free(headerChunk.linkP); free(headerChunk.relP); - curl_easy_reset(curl_handle_); + curl_easy_reset(curl_handle_); return ROOTPA_ERROR_NETWORK; } - + LOGD("http return code from SE %ld", (long int) http_code); - if ((200 <= http_code && http_code < 300)) + if ((200 <= http_code && http_code < 300)) { - ret=ROOTPA_OK; + ret=ROOTPA_OK; } - else if (HTTP_CODE_BAD_REQUEST == http_code || - HTTP_CODE_METHOD_NOT_ALLOWED == http_code || - HTTP_CODE_NOT_ACCEPTABLE == http_code || - HTTP_CODE_CONFLICT == http_code || + else if (HTTP_CODE_BAD_REQUEST == http_code || + HTTP_CODE_METHOD_NOT_ALLOWED == http_code || + HTTP_CODE_NOT_ACCEPTABLE == http_code || + HTTP_CODE_CONFLICT == http_code || HTTP_CODE_LENGTH_REQUIRED == http_code || HTTP_CODE_TOO_LONG == http_code || HTTP_CODE_UNSUPPORTED_MEDIA == http_code || HTTP_CODE_INVALID_DATA == http_code || - HTTP_CODE_INTERNAL_ERROR == http_code || + HTTP_CODE_INTERNAL_ERROR == http_code || HTTP_CODE_HTTP_VERSION == http_code) { LOGE("SE returned http error %ld", (long int) http_code); ret=ROOTPA_ERROR_INTERNAL; } else if(HTTP_CODE_MOVED == http_code || // new URL would be in Location: header but RootPA does not support in currently (unless libcurl supports it transparently) - HTTP_CODE_REQUEST_TIMEOUT == http_code || + HTTP_CODE_REQUEST_TIMEOUT == http_code || HTTP_CODE_SERVICE_UNAVAILABLE == http_code) { LOGE("SE returned http error %ld", (long int) http_code); @@ -678,7 +708,7 @@ rootpaerror_t httpCommunicate(const char * const inputP, const char** linkP, con { LOGE("SE returned http error %ld", (long int) http_code); ret=ROOTPA_ERROR_SE_CMP_VERSION; - } + } else if (HTTP_CODE_FAILED_DEPENDENCY == http_code) { LOGE("SE returned http error %ld", (long int) http_code); @@ -687,26 +717,27 @@ rootpaerror_t httpCommunicate(const char * const inputP, const char** linkP, con else if (HTTP_CODE_NOT_FOUND == http_code) { LOGE("SE returned http error %ld", (long int) http_code); - ret=ROOTPA_ERROR_ILLEGAL_ARGUMENT; // since the arguments (spid, in some cases uuid) for the URL are received from the client, - // this can be returned. It is also possible that suid is wrong (corrupted in device or info + ret=ROOTPA_ERROR_ILLEGAL_ARGUMENT; // since the arguments (spid, in some cases uuid) for the URL are received from the client, + // this can be returned. It is also possible that suid is wrong (corrupted in device or info // from device binding missing from SE, but we can not detect that easily. } else { LOGE("unexpected http return code from SE %ld", (long int)http_code); - ret=ROOTPA_ERROR_NETWORK; + ret=ROOTPA_ERROR_NETWORK; } - - /* cleanup curl stuff */ - + + /* cleanup curl stuff */ + *commandP=chunk.memoryP; // this needs to be freed by client *linkP=headerChunk.linkP; // this needs to be freed by client *relP=headerChunk.relP; // this needs to be freed by client - if (httpHeaderP) curl_slist_free_all(httpHeaderP); // since we disabled some headers + if (httpHeaderP) curl_slist_free_all(httpHeaderP); // since we disabled some headers curl_easy_reset(curl_handle_); LOGD("%lu bytes retrieved\n", (long)chunk.size); - - LOGD("<<httpCommunicate %d %ld %ld", (int) ret, (long int) http_code, (long int) curlRet); + + LOGD("<<httpCommunicate %d %ld %ld", (int) ret, (long int) http_code, (long int) curlRet); return ret; } + |