aesm_http_msg.cpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. /*
  2. * Copyright (C) 2011-2017 Intel Corporation. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * * Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * * Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in
  12. * the documentation and/or other materials provided with the
  13. * distribution.
  14. * * Neither the name of Intel Corporation nor the names of its
  15. * contributors may be used to endorse or promote products derived
  16. * from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  21. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  22. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  23. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  24. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  28. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. *
  30. */
  31. #include <string>
  32. #include "aesm_encode.h"
  33. #include "oal.h"
  34. #include "se_wrapper.h"
  35. #include "prof_fun.h"
  36. #include "aesm_proxy_type.h"
  37. #include "endpoint_select_info.h"
  38. #include "util.h"
  39. #include <curl/curl.h>
  40. #ifndef INTERNET_DEFAULT_HTTP_PORT
  41. #define INTERNET_DEFAULT_HTTP_PORT 80
  42. #endif
  43. #define AESM_DEFAULT_CONN_TIME_OUT 1000
  44. #define AESM_DEFAULT_TIME_OUT 10000
  45. bool is_curl_initialized_succ(void);//network is available only when curl library is successfully initialized
  46. typedef struct _network_malloc_info_t{
  47. char *base;
  48. uint32_t size;
  49. }network_malloc_info_t;
  50. static size_t write_callback(void *ptr, size_t size, size_t nmemb, void *stream)
  51. {
  52. network_malloc_info_t* s=reinterpret_cast<network_malloc_info_t *>(stream);
  53. uint32_t start=0;
  54. if(s->base==NULL){
  55. if(UINT32_MAX/size<nmemb){
  56. return 0;//buffer overflow
  57. }
  58. s->base = reinterpret_cast<char *>(malloc(size*nmemb));
  59. s->size = static_cast<uint32_t>(size*nmemb);
  60. if(s->base==NULL){
  61. AESM_DBG_ERROR("malloc error in write callback fun");
  62. return 0;
  63. }
  64. }else{
  65. uint32_t newsize = s->size+static_cast<uint32_t>(size*nmemb);
  66. if((UINT32_MAX-s->size)/size<nmemb){
  67. return 0;//buffer overflow
  68. }
  69. char *p=reinterpret_cast<char *>(malloc(newsize));
  70. if(p == NULL){
  71. free(s->base);
  72. s->base = NULL;
  73. AESM_DBG_ERROR("malloc error in write callback fun");
  74. return 0;
  75. }
  76. memcpy_s(p, newsize, s->base, s->size);
  77. free(s->base);
  78. start = s->size;
  79. s->base = p;
  80. s->size = newsize;
  81. }
  82. memcpy_s(s->base +start, s->size-start, ptr, size*nmemb);
  83. return nmemb;
  84. }
  85. static ae_error_t http_network_init(CURL **curl, const char *url, bool is_ocsp)
  86. {
  87. CURLcode cc = CURLE_OK;
  88. UNUSED(is_ocsp);
  89. AESM_DBG_TRACE("http init for url %s",url);
  90. if(!is_curl_initialized_succ()){
  91. AESM_DBG_ERROR("libcurl not initialized");
  92. return AE_FAILURE;//fatal error that libcurl could not be initialized
  93. }
  94. if(NULL == url){
  95. AESM_DBG_ERROR("NULL url");
  96. return AE_FAILURE;
  97. }
  98. std::string url_path = url;
  99. uint32_t proxy_type;
  100. char proxy_url[MAX_PATH];
  101. EndpointSelectionInfo::instance().get_proxy(proxy_type, proxy_url);
  102. *curl = curl_easy_init();
  103. if(!*curl){
  104. AESM_DBG_ERROR("fail to init curl handle");
  105. return AE_FAILURE;
  106. }
  107. if((cc=curl_easy_setopt(*curl, CURLOPT_URL, url_path.c_str()))!=CURLE_OK){
  108. AESM_DBG_ERROR("fail error code %d in set url %s",(int)cc, url_path.c_str());
  109. curl_easy_cleanup(*curl);
  110. return AE_FAILURE;
  111. }
  112. (void)curl_easy_setopt(*curl, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
  113. //setting proxy now
  114. if(proxy_type == AESM_PROXY_TYPE_DIRECT_ACCESS){
  115. AESM_DBG_TRACE("use no proxy");
  116. (void)curl_easy_setopt(*curl, CURLOPT_NOPROXY , "*");
  117. }else if(proxy_type == AESM_PROXY_TYPE_MANUAL_PROXY){
  118. AESM_DBG_TRACE("use manual proxy %s",proxy_url);
  119. (void)curl_easy_setopt(*curl, CURLOPT_PROXY, proxy_url);
  120. }
  121. return AE_SUCCESS;
  122. }
  123. static ae_error_t http_network_send_data(CURL *curl, const char *req_msg, uint32_t msg_size, char **resp_msg, uint32_t& resp_size, http_methods_t method, bool is_ocsp)
  124. {
  125. AESM_DBG_TRACE("send data method=%d",method);
  126. struct curl_slist *headers=NULL;
  127. struct curl_slist *tmp=NULL;
  128. ae_error_t ae_ret = AE_SUCCESS;
  129. CURLcode cc=CURLE_OK;
  130. int num_bytes = 0;
  131. long resp_code = 0;
  132. if(is_ocsp){
  133. tmp = curl_slist_append(headers, "Accept: application/ocsp-response");
  134. if(tmp==NULL){
  135. AESM_DBG_ERROR("fail in add accept ocsp-response header");
  136. ae_ret = AE_FAILURE;
  137. goto fini;
  138. }
  139. headers = tmp;
  140. tmp = curl_slist_append(headers, "Content-Type: application/ocsp-request");
  141. if(tmp == NULL){
  142. AESM_DBG_ERROR("fail in add content type ocsp-request");
  143. ae_ret = AE_FAILURE;
  144. goto fini;
  145. }
  146. headers=tmp;
  147. AESM_DBG_TRACE("ocsp request");
  148. }
  149. char buf[50];
  150. num_bytes = snprintf(buf,sizeof(buf), "Content-Length: %u", (unsigned int)msg_size);
  151. if(num_bytes<0 || num_bytes>=(int)sizeof(buf)){
  152. AESM_DBG_ERROR("fail to prepare string Content-Length");
  153. ae_ret = AE_FAILURE;
  154. goto fini;
  155. }
  156. tmp = curl_slist_append(headers, buf);
  157. if(tmp == NULL){
  158. AESM_DBG_ERROR("fail to add content-length header");
  159. ae_ret = AE_FAILURE;
  160. goto fini;
  161. }
  162. headers=tmp;
  163. if((cc=curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers))!=CURLE_OK){
  164. AESM_DBG_ERROR("fail to set http header:%d",(int)cc);
  165. ae_ret = AE_FAILURE;
  166. goto fini;
  167. }
  168. if(method == POST){
  169. if((cc=curl_easy_setopt(curl, CURLOPT_POSTFIELDS, req_msg))!=CURLE_OK){
  170. AESM_DBG_ERROR("fail to set POST fields:%d",(int)cc);
  171. ae_ret = AE_FAILURE;
  172. goto fini;
  173. }
  174. if((cc=curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, msg_size))!=CURLE_OK){
  175. AESM_DBG_ERROR("fail to set POST fields size:%d",(int)cc);
  176. ae_ret = AE_FAILURE;
  177. goto fini;
  178. }
  179. }
  180. if((cc=curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback))!=CURLE_OK){
  181. AESM_DBG_ERROR("Fail to set callback function:%d",(int)cc);
  182. ae_ret = AE_FAILURE;
  183. goto fini;
  184. }
  185. network_malloc_info_t malloc_info;
  186. malloc_info.base=NULL;
  187. malloc_info.size = 0;
  188. if((cc=curl_easy_setopt(curl, CURLOPT_WRITEDATA, reinterpret_cast<void *>(&malloc_info)))!=CURLE_OK){
  189. AESM_DBG_ERROR("fail to set write back function parameter:%d",(int)cc);
  190. ae_ret = AE_FAILURE;
  191. goto fini;
  192. }
  193. if((cc=curl_easy_perform(curl))!=CURLE_OK){
  194. if(malloc_info.base){
  195. free(malloc_info.base);
  196. }
  197. AESM_DBG_ERROR("fail in connect:%d",(int)cc);
  198. ae_ret = OAL_NETWORK_UNAVAILABLE_ERROR;
  199. goto fini;
  200. }
  201. // Check HTTP response code
  202. // For example, if the remote file does not exist, curl may return CURLE_OK but the http response code
  203. // indicates an error has occured
  204. if((cc=curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &resp_code))!=CURLE_OK || resp_code>=400){
  205. AESM_DBG_ERROR("Response code error:%d", resp_code);
  206. if(malloc_info.base){
  207. free(malloc_info.base);
  208. }
  209. ae_ret = AE_FAILURE;
  210. goto fini;
  211. }
  212. *resp_msg = malloc_info.base;
  213. resp_size = malloc_info.size;
  214. AESM_DBG_TRACE("get response size=%d",resp_size);
  215. ae_ret = AE_SUCCESS;
  216. fini:
  217. if(headers!=NULL){
  218. curl_slist_free_all(headers);
  219. }
  220. return ae_ret;
  221. }
  222. static void http_network_fini(CURL *curl)
  223. {
  224. if(curl!=NULL)
  225. curl_easy_cleanup(curl);
  226. }
  227. ae_error_t aesm_network_send_receive(const char *server_url, const uint8_t *req, uint32_t req_size,
  228. uint8_t **p_resp, uint32_t *p_resp_size, http_methods_t method, bool is_ocsp)
  229. {
  230. AESM_PROFILE_FUN;
  231. ae_error_t ret= AE_SUCCESS;
  232. CURL *curl = NULL;
  233. ret = http_network_init(&curl, server_url, is_ocsp);
  234. if(ret != AE_SUCCESS){
  235. goto ret_point;
  236. }
  237. ret = http_network_send_data(curl, reinterpret_cast<const char *>(req), req_size,
  238. reinterpret_cast<char **>(p_resp), *p_resp_size, method, is_ocsp);
  239. ret_point:
  240. http_network_fini(curl);
  241. return ret;
  242. }
  243. void aesm_free_network_response_buffer(uint8_t *resp)
  244. {
  245. if(resp!=NULL)free(resp);
  246. }