Fork of mbed-http

Fork of mbed-http by sandbox

Committer:
Jan Jongboom
Date:
Tue Mar 28 13:33:14 2017 +0200
Revision:
10:b017c7d2cf23
Parent:
7:2e3eedb9ca5c
Child:
11:96e4dcb9c0c2
Don't rely on strlen for request length, as it prevents sending \0 over the line. Patch via https://developer.mbed.org/users/ihere1/code/mbed-http/rev/ec9b75c349aa

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Jan Jongboom 0:910f5949759f 1 /*
Jan Jongboom 0:910f5949759f 2 * PackageLicenseDeclared: Apache-2.0
Jan Jongboom 0:910f5949759f 3 * Copyright (c) 2017 ARM Limited
Jan Jongboom 0:910f5949759f 4 *
Jan Jongboom 0:910f5949759f 5 * Licensed under the Apache License, Version 2.0 (the "License");
Jan Jongboom 0:910f5949759f 6 * you may not use this file except in compliance with the License.
Jan Jongboom 0:910f5949759f 7 * You may obtain a copy of the License at
Jan Jongboom 0:910f5949759f 8 *
Jan Jongboom 0:910f5949759f 9 * http://www.apache.org/licenses/LICENSE-2.0
Jan Jongboom 0:910f5949759f 10 *
Jan Jongboom 0:910f5949759f 11 * Unless required by applicable law or agreed to in writing, software
Jan Jongboom 0:910f5949759f 12 * distributed under the License is distributed on an "AS IS" BASIS,
Jan Jongboom 0:910f5949759f 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Jan Jongboom 0:910f5949759f 14 * See the License for the specific language governing permissions and
Jan Jongboom 0:910f5949759f 15 * limitations under the License.
Jan Jongboom 0:910f5949759f 16 */
Jan Jongboom 0:910f5949759f 17
Jan Jongboom 0:910f5949759f 18 #ifndef _MBED_HTTPS_REQUEST_H_
Jan Jongboom 0:910f5949759f 19 #define _MBED_HTTPS_REQUEST_H_
Jan Jongboom 0:910f5949759f 20
Jan Jongboom 0:910f5949759f 21 /* Change to a number between 1 and 4 to debug the TLS connection */
Jan Jongboom 0:910f5949759f 22 #define DEBUG_LEVEL 0
Jan Jongboom 0:910f5949759f 23
Jan Jongboom 0:910f5949759f 24 #include <string>
Jan Jongboom 0:910f5949759f 25 #include <vector>
Jan Jongboom 0:910f5949759f 26 #include <map>
Jan Jongboom 0:910f5949759f 27 #include "http_parser.h"
Jan Jongboom 0:910f5949759f 28 #include "http_response.h"
Jan Jongboom 0:910f5949759f 29 #include "http_request_builder.h"
Jan Jongboom 0:910f5949759f 30 #include "http_response_parser.h"
Jan Jongboom 0:910f5949759f 31 #include "http_parsed_url.h"
Jan Jongboom 0:910f5949759f 32
Jan Jongboom 0:910f5949759f 33 #include "mbedtls/platform.h"
Jan Jongboom 0:910f5949759f 34 #include "mbedtls/ssl.h"
Jan Jongboom 0:910f5949759f 35 #include "mbedtls/entropy.h"
Jan Jongboom 0:910f5949759f 36 #include "mbedtls/ctr_drbg.h"
Jan Jongboom 0:910f5949759f 37 #include "mbedtls/error.h"
Jan Jongboom 0:910f5949759f 38
Jan Jongboom 0:910f5949759f 39 #if DEBUG_LEVEL > 0
Jan Jongboom 0:910f5949759f 40 #include "mbedtls/debug.h"
Jan Jongboom 0:910f5949759f 41 #endif
Jan Jongboom 0:910f5949759f 42
Jan Jongboom 0:910f5949759f 43 /**
Jan Jongboom 0:910f5949759f 44 * \brief HttpsRequest implements the logic for interacting with HTTPS servers.
Jan Jongboom 0:910f5949759f 45 */
Jan Jongboom 0:910f5949759f 46 class HttpsRequest {
Jan Jongboom 0:910f5949759f 47 public:
Jan Jongboom 0:910f5949759f 48 /**
Jan Jongboom 0:910f5949759f 49 * HttpsRequest Constructor
Jan Jongboom 0:910f5949759f 50 * Initializes the TCP socket, sets up event handlers and flags.
Jan Jongboom 0:910f5949759f 51 *
Jan Jongboom 0:910f5949759f 52 * @param[in] net_iface The network interface
Jan Jongboom 0:910f5949759f 53 * @param[in] ssl_ca_pem String containing the trusted CAs
Jan Jongboom 0:910f5949759f 54 * @param[in] method HTTP method to use
Jan Jongboom 0:910f5949759f 55 * @param[in] url URL to the resource
Jan Jongboom 0:910f5949759f 56 * @param[in] body_callback Callback on which to retrieve chunks of the response body.
Jan Jongboom 0:910f5949759f 57 If not set, the complete body will be allocated on the HttpResponse object,
Jan Jongboom 0:910f5949759f 58 which might use lots of memory.
Jan Jongboom 0:910f5949759f 59 */
Jan Jongboom 0:910f5949759f 60 HttpsRequest(NetworkInterface* net_iface,
Jan Jongboom 0:910f5949759f 61 const char* ssl_ca_pem,
Jan Jongboom 0:910f5949759f 62 http_method method,
Jan Jongboom 0:910f5949759f 63 const char* url,
Jan Jongboom 0:910f5949759f 64 Callback<void(const char *at, size_t length)> body_callback = 0)
Jan Jongboom 0:910f5949759f 65 {
Jan Jongboom 0:910f5949759f 66 _parsed_url = new ParsedUrl(url);
Jan Jongboom 0:910f5949759f 67 _body_callback = body_callback;
Jan Jongboom 0:910f5949759f 68 _tcpsocket = new TCPSocket(net_iface);
Jan Jongboom 0:910f5949759f 69 _request_builder = new HttpRequestBuilder(method, _parsed_url);
Jan Jongboom 0:910f5949759f 70 _response = NULL;
Jan Jongboom 0:910f5949759f 71 _debug = false;
Jan Jongboom 0:910f5949759f 72 _ssl_ca_pem = ssl_ca_pem;
Jan Jongboom 0:910f5949759f 73
Jan Jongboom 0:910f5949759f 74 DRBG_PERS = "mbed TLS helloword client";
Jan Jongboom 0:910f5949759f 75
Jan Jongboom 0:910f5949759f 76 mbedtls_entropy_init(&_entropy);
Jan Jongboom 0:910f5949759f 77 mbedtls_ctr_drbg_init(&_ctr_drbg);
Jan Jongboom 0:910f5949759f 78 mbedtls_x509_crt_init(&_cacert);
Jan Jongboom 0:910f5949759f 79 mbedtls_ssl_init(&_ssl);
Jan Jongboom 0:910f5949759f 80 mbedtls_ssl_config_init(&_ssl_conf);
Jan Jongboom 0:910f5949759f 81 }
Jan Jongboom 0:910f5949759f 82
Jan Jongboom 0:910f5949759f 83 /**
Jan Jongboom 0:910f5949759f 84 * HttpsRequest Destructor
Jan Jongboom 0:910f5949759f 85 */
Jan Jongboom 0:910f5949759f 86 ~HttpsRequest() {
Jan Jongboom 0:910f5949759f 87 mbedtls_entropy_free(&_entropy);
Jan Jongboom 0:910f5949759f 88 mbedtls_ctr_drbg_free(&_ctr_drbg);
Jan Jongboom 0:910f5949759f 89 mbedtls_x509_crt_free(&_cacert);
Jan Jongboom 0:910f5949759f 90 mbedtls_ssl_free(&_ssl);
Jan Jongboom 0:910f5949759f 91 mbedtls_ssl_config_free(&_ssl_conf);
Jan Jongboom 0:910f5949759f 92
Jan Jongboom 0:910f5949759f 93 if (_request_builder) {
Jan Jongboom 0:910f5949759f 94 delete _request_builder;
Jan Jongboom 0:910f5949759f 95 }
Jan Jongboom 0:910f5949759f 96
Jan Jongboom 0:910f5949759f 97 if (_tcpsocket) {
Jan Jongboom 0:910f5949759f 98 delete _tcpsocket;
Jan Jongboom 0:910f5949759f 99 }
Jan Jongboom 0:910f5949759f 100
Jan Jongboom 0:910f5949759f 101 if (_parsed_url) {
Jan Jongboom 0:910f5949759f 102 delete _parsed_url;
Jan Jongboom 0:910f5949759f 103 }
Jan Jongboom 0:910f5949759f 104
Jan Jongboom 0:910f5949759f 105 if (_response) {
Jan Jongboom 0:910f5949759f 106 delete _response;
Jan Jongboom 0:910f5949759f 107 }
Jan Jongboom 0:910f5949759f 108
Jan Jongboom 0:910f5949759f 109 // @todo: free DRBG_PERS ?
Jan Jongboom 0:910f5949759f 110 }
Jan Jongboom 0:910f5949759f 111
Jan Jongboom 0:910f5949759f 112 /**
Jan Jongboom 0:910f5949759f 113 * Execute the HTTPS request.
Jan Jongboom 0:910f5949759f 114 *
Jan Jongboom 0:910f5949759f 115 * @param[in] body Pointer to the request body
Jan Jongboom 0:910f5949759f 116 * @param[in] body_size Size of the request body
Jan Jongboom 0:910f5949759f 117 * @return An HttpResponse pointer on success, or NULL on failure.
Jan Jongboom 0:910f5949759f 118 * See get_error() for the error code.
Jan Jongboom 0:910f5949759f 119 */
Jan Jongboom 0:910f5949759f 120 HttpResponse* send(const void* body = NULL, nsapi_size_t body_size = 0) {
Jan Jongboom 0:910f5949759f 121 /* Initialize the flags */
Jan Jongboom 0:910f5949759f 122 /*
Jan Jongboom 0:910f5949759f 123 * Initialize TLS-related stuf.
Jan Jongboom 0:910f5949759f 124 */
Jan Jongboom 0:910f5949759f 125 int ret;
Jan Jongboom 0:910f5949759f 126 if ((ret = mbedtls_ctr_drbg_seed(&_ctr_drbg, mbedtls_entropy_func, &_entropy,
Jan Jongboom 0:910f5949759f 127 (const unsigned char *) DRBG_PERS,
Jan Jongboom 0:910f5949759f 128 sizeof (DRBG_PERS))) != 0) {
Jan Jongboom 0:910f5949759f 129 print_mbedtls_error("mbedtls_crt_drbg_init", ret);
Jan Jongboom 0:910f5949759f 130 _error = ret;
Jan Jongboom 0:910f5949759f 131 return NULL;
Jan Jongboom 0:910f5949759f 132 }
Jan Jongboom 0:910f5949759f 133
Jan Jongboom 0:910f5949759f 134 if ((ret = mbedtls_x509_crt_parse(&_cacert, (const unsigned char *)_ssl_ca_pem,
Jan Jongboom 0:910f5949759f 135 strlen(_ssl_ca_pem) + 1)) != 0) {
Jan Jongboom 0:910f5949759f 136 print_mbedtls_error("mbedtls_x509_crt_parse", ret);
Jan Jongboom 0:910f5949759f 137 _error = ret;
Jan Jongboom 0:910f5949759f 138 return NULL;
Jan Jongboom 0:910f5949759f 139 }
Jan Jongboom 0:910f5949759f 140
Jan Jongboom 0:910f5949759f 141 if ((ret = mbedtls_ssl_config_defaults(&_ssl_conf,
Jan Jongboom 0:910f5949759f 142 MBEDTLS_SSL_IS_CLIENT,
Jan Jongboom 0:910f5949759f 143 MBEDTLS_SSL_TRANSPORT_STREAM,
Jan Jongboom 0:910f5949759f 144 MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
Jan Jongboom 0:910f5949759f 145 print_mbedtls_error("mbedtls_ssl_config_defaults", ret);
Jan Jongboom 0:910f5949759f 146 _error = ret;
Jan Jongboom 0:910f5949759f 147 return NULL;
Jan Jongboom 0:910f5949759f 148 }
Jan Jongboom 0:910f5949759f 149
Jan Jongboom 0:910f5949759f 150 mbedtls_ssl_conf_ca_chain(&_ssl_conf, &_cacert, NULL);
Jan Jongboom 0:910f5949759f 151 mbedtls_ssl_conf_rng(&_ssl_conf, mbedtls_ctr_drbg_random, &_ctr_drbg);
Jan Jongboom 0:910f5949759f 152
Jan Jongboom 0:910f5949759f 153 /* It is possible to disable authentication by passing
Jan Jongboom 0:910f5949759f 154 * MBEDTLS_SSL_VERIFY_NONE in the call to mbedtls_ssl_conf_authmode()
Jan Jongboom 0:910f5949759f 155 */
Jan Jongboom 0:910f5949759f 156 mbedtls_ssl_conf_authmode(&_ssl_conf, MBEDTLS_SSL_VERIFY_REQUIRED);
Jan Jongboom 0:910f5949759f 157
Jan Jongboom 0:910f5949759f 158 #if DEBUG_LEVEL > 0
Jan Jongboom 0:910f5949759f 159 mbedtls_ssl_conf_verify(&_ssl_conf, my_verify, NULL);
Jan Jongboom 0:910f5949759f 160 mbedtls_ssl_conf_dbg(&_ssl_conf, my_debug, NULL);
Jan Jongboom 0:910f5949759f 161 mbedtls_debug_set_threshold(DEBUG_LEVEL);
Jan Jongboom 0:910f5949759f 162 #endif
Jan Jongboom 0:910f5949759f 163
Jan Jongboom 0:910f5949759f 164 if ((ret = mbedtls_ssl_setup(&_ssl, &_ssl_conf)) != 0) {
Jan Jongboom 0:910f5949759f 165 print_mbedtls_error("mbedtls_ssl_setup", ret);
Jan Jongboom 0:910f5949759f 166 _error = ret;
Jan Jongboom 0:910f5949759f 167 return NULL;
Jan Jongboom 0:910f5949759f 168 }
Jan Jongboom 0:910f5949759f 169
Jan Jongboom 0:910f5949759f 170 mbedtls_ssl_set_hostname(&_ssl, _parsed_url->host());
Jan Jongboom 0:910f5949759f 171
Jan Jongboom 0:910f5949759f 172 mbedtls_ssl_set_bio(&_ssl, static_cast<void *>(_tcpsocket),
Jan Jongboom 0:910f5949759f 173 ssl_send, ssl_recv, NULL );
Jan Jongboom 0:910f5949759f 174
Jan Jongboom 0:910f5949759f 175 /* Connect to the server */
Jan Jongboom 0:910f5949759f 176 if (_debug) mbedtls_printf("Connecting to %s:%d\r\n", _parsed_url->host(), _parsed_url->port());
Jan Jongboom 0:910f5949759f 177 ret = _tcpsocket->connect(_parsed_url->host(), _parsed_url->port());
Jan Jongboom 0:910f5949759f 178 if (ret != NSAPI_ERROR_OK) {
Jan Jongboom 0:910f5949759f 179 if (_debug) mbedtls_printf("Failed to connect\r\n");
Jan Jongboom 0:910f5949759f 180 onError(_tcpsocket, -1);
Jan Jongboom 0:910f5949759f 181 return NULL;
Jan Jongboom 0:910f5949759f 182 }
Jan Jongboom 0:910f5949759f 183
Jan Jongboom 0:910f5949759f 184 /* Start the handshake, the rest will be done in onReceive() */
Jan Jongboom 0:910f5949759f 185 if (_debug) mbedtls_printf("Starting the TLS handshake...\r\n");
Jan Jongboom 0:910f5949759f 186 ret = mbedtls_ssl_handshake(&_ssl);
Jan Jongboom 0:910f5949759f 187 if (ret < 0) {
Jan Jongboom 0:910f5949759f 188 if (ret != MBEDTLS_ERR_SSL_WANT_READ &&
Jan Jongboom 0:910f5949759f 189 ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
Jan Jongboom 0:910f5949759f 190 print_mbedtls_error("mbedtls_ssl_handshake", ret);
Jan Jongboom 0:910f5949759f 191 onError(_tcpsocket, -1);
Jan Jongboom 0:910f5949759f 192 }
Jan Jongboom 0:910f5949759f 193 else {
Jan Jongboom 0:910f5949759f 194 _error = ret;
Jan Jongboom 0:910f5949759f 195 }
Jan Jongboom 0:910f5949759f 196 return NULL;
Jan Jongboom 0:910f5949759f 197 }
Jan Jongboom 0:910f5949759f 198
Jan Jongboom 10:b017c7d2cf23 199 size_t request_size = 0;
Jan Jongboom 10:b017c7d2cf23 200 char* request = _request_builder->build(body, body_size, request_size);
Jan Jongboom 0:910f5949759f 201
Jan Jongboom 0:910f5949759f 202 ret = mbedtls_ssl_write(&_ssl, (const unsigned char *) request, request_size);
Jan Jongboom 0:910f5949759f 203
Jan Jongboom 0:910f5949759f 204 free(request);
Jan Jongboom 0:910f5949759f 205
Jan Jongboom 0:910f5949759f 206 if (ret < 0) {
Jan Jongboom 0:910f5949759f 207 if (ret != MBEDTLS_ERR_SSL_WANT_READ &&
Jan Jongboom 0:910f5949759f 208 ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
Jan Jongboom 0:910f5949759f 209 print_mbedtls_error("mbedtls_ssl_write", ret);
Jan Jongboom 0:910f5949759f 210 onError(_tcpsocket, -1 );
Jan Jongboom 0:910f5949759f 211 }
Jan Jongboom 0:910f5949759f 212 else {
Jan Jongboom 0:910f5949759f 213 _error = ret;
Jan Jongboom 0:910f5949759f 214 }
Jan Jongboom 0:910f5949759f 215 return NULL;
Jan Jongboom 0:910f5949759f 216 }
Jan Jongboom 0:910f5949759f 217
Jan Jongboom 0:910f5949759f 218 /* It also means the handshake is done, time to print info */
Jan Jongboom 0:910f5949759f 219 if (_debug) mbedtls_printf("TLS connection to %s:%d established\r\n", _parsed_url->host(), _parsed_url->port());
Jan Jongboom 0:910f5949759f 220
Jan Jongboom 0:910f5949759f 221 const uint32_t buf_size = 1024;
Jan Jongboom 0:910f5949759f 222 char *buf = new char[buf_size];
Jan Jongboom 0:910f5949759f 223 mbedtls_x509_crt_info(buf, buf_size, "\r ",
Jan Jongboom 0:910f5949759f 224 mbedtls_ssl_get_peer_cert(&_ssl));
Jan Jongboom 0:910f5949759f 225 if (_debug) mbedtls_printf("Server certificate:\r\n%s\r", buf);
Jan Jongboom 0:910f5949759f 226
Jan Jongboom 0:910f5949759f 227 uint32_t flags = mbedtls_ssl_get_verify_result(&_ssl);
Jan Jongboom 0:910f5949759f 228 if( flags != 0 )
Jan Jongboom 0:910f5949759f 229 {
Jan Jongboom 0:910f5949759f 230 mbedtls_x509_crt_verify_info(buf, buf_size, "\r ! ", flags);
Jan Jongboom 0:910f5949759f 231 if (_debug) mbedtls_printf("Certificate verification failed:\r\n%s\r\r\n", buf);
Jan Jongboom 0:910f5949759f 232 }
Jan Jongboom 0:910f5949759f 233 else {
Jan Jongboom 0:910f5949759f 234 if (_debug) mbedtls_printf("Certificate verification passed\r\n\r\n");
Jan Jongboom 0:910f5949759f 235 }
Jan Jongboom 0:910f5949759f 236
Jan Jongboom 0:910f5949759f 237 // Create a response object
Jan Jongboom 0:910f5949759f 238 _response = new HttpResponse();
Jan Jongboom 0:910f5949759f 239 // And a response parser
Jan Jongboom 0:910f5949759f 240 HttpResponseParser parser(_response, _body_callback);
Jan Jongboom 0:910f5949759f 241
Jan Jongboom 0:910f5949759f 242 // Set up a receive buffer (on the heap)
Jan Jongboom 0:910f5949759f 243 uint8_t* recv_buffer = (uint8_t*)malloc(HTTP_RECEIVE_BUFFER_SIZE);
Jan Jongboom 0:910f5949759f 244
Jan Jongboom 0:910f5949759f 245 /* Read data out of the socket */
Jan Jongboom 0:910f5949759f 246 while ((ret = mbedtls_ssl_read(&_ssl, (unsigned char *) recv_buffer, HTTP_RECEIVE_BUFFER_SIZE)) > 0) {
Jan Jongboom 0:910f5949759f 247 // Don't know if this is actually needed, but OK
Jan Jongboom 0:910f5949759f 248 size_t _bpos = static_cast<size_t>(ret);
Jan Jongboom 0:910f5949759f 249 recv_buffer[_bpos] = 0;
Jan Jongboom 0:910f5949759f 250
Jan Jongboom 0:910f5949759f 251 size_t nparsed = parser.execute((const char*)recv_buffer, _bpos);
Jan Jongboom 0:910f5949759f 252 if (nparsed != _bpos) {
Jan Jongboom 0:910f5949759f 253 print_mbedtls_error("parser_error", nparsed);
Jan Jongboom 0:910f5949759f 254 // parser error...
Jan Jongboom 0:910f5949759f 255 _error = -2101;
Jan Jongboom 0:910f5949759f 256 free(recv_buffer);
Jan Jongboom 0:910f5949759f 257 return NULL;
Jan Jongboom 0:910f5949759f 258 }
Jan Jongboom 6:112d72c60e07 259
Jan Jongboom 7:2e3eedb9ca5c 260 if (_response->is_message_complete()) {
Jan Jongboom 0:910f5949759f 261 break;
Jan Jongboom 0:910f5949759f 262 }
Jan Jongboom 0:910f5949759f 263 }
Jan Jongboom 0:910f5949759f 264 if (ret < 0) {
Jan Jongboom 0:910f5949759f 265 if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
Jan Jongboom 0:910f5949759f 266 print_mbedtls_error("mbedtls_ssl_read", ret);
Jan Jongboom 0:910f5949759f 267 onError(_tcpsocket, -1 );
Jan Jongboom 0:910f5949759f 268 }
Jan Jongboom 0:910f5949759f 269 else {
Jan Jongboom 0:910f5949759f 270 _error = ret;
Jan Jongboom 0:910f5949759f 271 }
Jan Jongboom 0:910f5949759f 272 free(recv_buffer);
Jan Jongboom 0:910f5949759f 273 return NULL;
Jan Jongboom 0:910f5949759f 274 }
Jan Jongboom 0:910f5949759f 275
Jan Jongboom 0:910f5949759f 276 parser.finish();
Jan Jongboom 0:910f5949759f 277
Jan Jongboom 0:910f5949759f 278 _tcpsocket->close();
Jan Jongboom 0:910f5949759f 279 free(recv_buffer);
Jan Jongboom 0:910f5949759f 280
Jan Jongboom 0:910f5949759f 281 return _response;
Jan Jongboom 0:910f5949759f 282 }
Jan Jongboom 0:910f5949759f 283
Jan Jongboom 0:910f5949759f 284 /**
Jan Jongboom 0:910f5949759f 285 * Closes the TCP socket
Jan Jongboom 0:910f5949759f 286 */
Jan Jongboom 0:910f5949759f 287 void close() {
Jan Jongboom 0:910f5949759f 288 _tcpsocket->close();
Jan Jongboom 0:910f5949759f 289 }
Jan Jongboom 0:910f5949759f 290
Jan Jongboom 0:910f5949759f 291 /**
Jan Jongboom 0:910f5949759f 292 * Set a header for the request.
Jan Jongboom 0:910f5949759f 293 *
Jan Jongboom 0:910f5949759f 294 * The 'Host' and 'Content-Length' headers are set automatically.
Jan Jongboom 0:910f5949759f 295 * Setting the same header twice will overwrite the previous entry.
Jan Jongboom 0:910f5949759f 296 *
Jan Jongboom 0:910f5949759f 297 * @param[in] key Header key
Jan Jongboom 0:910f5949759f 298 * @param[in] value Header value
Jan Jongboom 0:910f5949759f 299 */
Jan Jongboom 0:910f5949759f 300 void set_header(string key, string value) {
Jan Jongboom 0:910f5949759f 301 _request_builder->set_header(key, value);
Jan Jongboom 0:910f5949759f 302 }
Jan Jongboom 0:910f5949759f 303
Jan Jongboom 0:910f5949759f 304 /**
Jan Jongboom 0:910f5949759f 305 * Get the error code.
Jan Jongboom 0:910f5949759f 306 *
Jan Jongboom 0:910f5949759f 307 * When send() fails, this error is set.
Jan Jongboom 0:910f5949759f 308 */
Jan Jongboom 0:910f5949759f 309 nsapi_error_t get_error() {
Jan Jongboom 0:910f5949759f 310 return _error;
Jan Jongboom 0:910f5949759f 311 }
Jan Jongboom 0:910f5949759f 312
Jan Jongboom 0:910f5949759f 313 /**
Jan Jongboom 0:910f5949759f 314 * Set the debug flag.
Jan Jongboom 0:910f5949759f 315 *
Jan Jongboom 0:910f5949759f 316 * If this flag is set, debug information from mbed TLS will be logged to stdout.
Jan Jongboom 0:910f5949759f 317 */
Jan Jongboom 0:910f5949759f 318 void set_debug(bool debug) {
Jan Jongboom 0:910f5949759f 319 _debug = debug;
Jan Jongboom 0:910f5949759f 320 }
Jan Jongboom 0:910f5949759f 321
Jan Jongboom 0:910f5949759f 322 protected:
Jan Jongboom 0:910f5949759f 323 /**
Jan Jongboom 0:910f5949759f 324 * Helper for pretty-printing mbed TLS error codes
Jan Jongboom 0:910f5949759f 325 */
Jan Jongboom 0:910f5949759f 326 static void print_mbedtls_error(const char *name, int err) {
Jan Jongboom 0:910f5949759f 327 char buf[128];
Jan Jongboom 0:910f5949759f 328 mbedtls_strerror(err, buf, sizeof (buf));
Jan Jongboom 0:910f5949759f 329 mbedtls_printf("%s() failed: -0x%04x (%d): %s\r\n", name, -err, err, buf);
Jan Jongboom 0:910f5949759f 330 }
Jan Jongboom 0:910f5949759f 331
Jan Jongboom 0:910f5949759f 332 #if DEBUG_LEVEL > 0
Jan Jongboom 0:910f5949759f 333 /**
Jan Jongboom 0:910f5949759f 334 * Debug callback for mbed TLS
Jan Jongboom 0:910f5949759f 335 * Just prints on the USB serial port
Jan Jongboom 0:910f5949759f 336 */
Jan Jongboom 0:910f5949759f 337 static void my_debug(void *ctx, int level, const char *file, int line,
Jan Jongboom 0:910f5949759f 338 const char *str)
Jan Jongboom 0:910f5949759f 339 {
Jan Jongboom 0:910f5949759f 340 const char *p, *basename;
Jan Jongboom 0:910f5949759f 341 (void) ctx;
Jan Jongboom 0:910f5949759f 342
Jan Jongboom 0:910f5949759f 343 /* Extract basename from file */
Jan Jongboom 0:910f5949759f 344 for(p = basename = file; *p != '\0'; p++) {
Jan Jongboom 0:910f5949759f 345 if(*p == '/' || *p == '\\') {
Jan Jongboom 0:910f5949759f 346 basename = p + 1;
Jan Jongboom 0:910f5949759f 347 }
Jan Jongboom 0:910f5949759f 348 }
Jan Jongboom 0:910f5949759f 349
Jan Jongboom 0:910f5949759f 350 if (_debug) {
Jan Jongboom 0:910f5949759f 351 mbedtls_printf("%s:%04d: |%d| %s", basename, line, level, str);
Jan Jongboom 0:910f5949759f 352 }
Jan Jongboom 0:910f5949759f 353 }
Jan Jongboom 0:910f5949759f 354
Jan Jongboom 0:910f5949759f 355 /**
Jan Jongboom 0:910f5949759f 356 * Certificate verification callback for mbed TLS
Jan Jongboom 0:910f5949759f 357 * Here we only use it to display information on each cert in the chain
Jan Jongboom 0:910f5949759f 358 */
Jan Jongboom 0:910f5949759f 359 static int my_verify(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags)
Jan Jongboom 0:910f5949759f 360 {
Jan Jongboom 0:910f5949759f 361 const uint32_t buf_size = 1024;
Jan Jongboom 0:910f5949759f 362 char *buf = new char[buf_size];
Jan Jongboom 0:910f5949759f 363 (void) data;
Jan Jongboom 0:910f5949759f 364
Jan Jongboom 0:910f5949759f 365 if (_debug) mbedtls_printf("\nVerifying certificate at depth %d:\n", depth);
Jan Jongboom 0:910f5949759f 366 mbedtls_x509_crt_info(buf, buf_size - 1, " ", crt);
Jan Jongboom 0:910f5949759f 367 if (_debug) mbedtls_printf("%s", buf);
Jan Jongboom 0:910f5949759f 368
Jan Jongboom 0:910f5949759f 369 if (*flags == 0)
Jan Jongboom 0:910f5949759f 370 if (_debug) mbedtls_printf("No verification issue for this certificate\n");
Jan Jongboom 0:910f5949759f 371 else
Jan Jongboom 0:910f5949759f 372 {
Jan Jongboom 0:910f5949759f 373 mbedtls_x509_crt_verify_info(buf, buf_size, " ! ", *flags);
Jan Jongboom 0:910f5949759f 374 if (_debug) mbedtls_printf("%s\n", buf);
Jan Jongboom 0:910f5949759f 375 }
Jan Jongboom 0:910f5949759f 376
Jan Jongboom 0:910f5949759f 377 delete[] buf;
Jan Jongboom 0:910f5949759f 378 return 0;
Jan Jongboom 0:910f5949759f 379 }
Jan Jongboom 0:910f5949759f 380 #endif
Jan Jongboom 0:910f5949759f 381
Jan Jongboom 0:910f5949759f 382 /**
Jan Jongboom 0:910f5949759f 383 * Receive callback for mbed TLS
Jan Jongboom 0:910f5949759f 384 */
Jan Jongboom 0:910f5949759f 385 static int ssl_recv(void *ctx, unsigned char *buf, size_t len) {
Jan Jongboom 0:910f5949759f 386 int recv = -1;
Jan Jongboom 0:910f5949759f 387 TCPSocket *socket = static_cast<TCPSocket *>(ctx);
Jan Jongboom 0:910f5949759f 388 recv = socket->recv(buf, len);
Jan Jongboom 0:910f5949759f 389
Jan Jongboom 0:910f5949759f 390 if (NSAPI_ERROR_WOULD_BLOCK == recv) {
Jan Jongboom 0:910f5949759f 391 return MBEDTLS_ERR_SSL_WANT_READ;
Jan Jongboom 0:910f5949759f 392 }
Jan Jongboom 0:910f5949759f 393 else if (recv < 0) {
Jan Jongboom 0:910f5949759f 394 return -1;
Jan Jongboom 0:910f5949759f 395 }
Jan Jongboom 0:910f5949759f 396 else {
Jan Jongboom 0:910f5949759f 397 return recv;
Jan Jongboom 0:910f5949759f 398 }
Jan Jongboom 0:910f5949759f 399 }
Jan Jongboom 0:910f5949759f 400
Jan Jongboom 0:910f5949759f 401 /**
Jan Jongboom 0:910f5949759f 402 * Send callback for mbed TLS
Jan Jongboom 0:910f5949759f 403 */
Jan Jongboom 0:910f5949759f 404 static int ssl_send(void *ctx, const unsigned char *buf, size_t len) {
Jan Jongboom 0:910f5949759f 405 int size = -1;
Jan Jongboom 0:910f5949759f 406 TCPSocket *socket = static_cast<TCPSocket *>(ctx);
Jan Jongboom 0:910f5949759f 407 size = socket->send(buf, len);
Jan Jongboom 0:910f5949759f 408
Jan Jongboom 0:910f5949759f 409 if(NSAPI_ERROR_WOULD_BLOCK == size) {
Jan Jongboom 0:910f5949759f 410 return len;
Jan Jongboom 0:910f5949759f 411 }
Jan Jongboom 0:910f5949759f 412 else if (size < 0){
Jan Jongboom 0:910f5949759f 413 return -1;
Jan Jongboom 0:910f5949759f 414 }
Jan Jongboom 0:910f5949759f 415 else {
Jan Jongboom 0:910f5949759f 416 return size;
Jan Jongboom 0:910f5949759f 417 }
Jan Jongboom 0:910f5949759f 418 }
Jan Jongboom 0:910f5949759f 419
Jan Jongboom 0:910f5949759f 420 void onError(TCPSocket *s, int error) {
Jan Jongboom 0:910f5949759f 421 s->close();
Jan Jongboom 0:910f5949759f 422 _error = error;
Jan Jongboom 0:910f5949759f 423 }
Jan Jongboom 0:910f5949759f 424
Jan Jongboom 0:910f5949759f 425 protected:
Jan Jongboom 0:910f5949759f 426 TCPSocket* _tcpsocket;
Jan Jongboom 0:910f5949759f 427
Jan Jongboom 0:910f5949759f 428 Callback<void(const char *at, size_t length)> _body_callback;
Jan Jongboom 0:910f5949759f 429 ParsedUrl* _parsed_url;
Jan Jongboom 0:910f5949759f 430 HttpRequestBuilder* _request_builder;
Jan Jongboom 0:910f5949759f 431 HttpResponse* _response;
Jan Jongboom 0:910f5949759f 432 const char *DRBG_PERS;
Jan Jongboom 0:910f5949759f 433 const char *_ssl_ca_pem;
Jan Jongboom 0:910f5949759f 434
Jan Jongboom 0:910f5949759f 435 nsapi_error_t _error;
Jan Jongboom 0:910f5949759f 436 bool _debug;
Jan Jongboom 0:910f5949759f 437
Jan Jongboom 0:910f5949759f 438 mbedtls_entropy_context _entropy;
Jan Jongboom 0:910f5949759f 439 mbedtls_ctr_drbg_context _ctr_drbg;
Jan Jongboom 0:910f5949759f 440 mbedtls_x509_crt _cacert;
Jan Jongboom 0:910f5949759f 441 mbedtls_ssl_context _ssl;
Jan Jongboom 0:910f5949759f 442 mbedtls_ssl_config _ssl_conf;
Jan Jongboom 0:910f5949759f 443 };
Jan Jongboom 0:910f5949759f 444
Jan Jongboom 0:910f5949759f 445 #endif // _MBED_HTTPS_REQUEST_H_