1 /* 2 * HTTP wrapper for libcurl 3 * Copyright (c) 2012-2014, Qualcomm Atheros, Inc. 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9 #include "includes.h" 10 #include <curl/curl.h> 11 #ifdef EAP_TLS_OPENSSL 12 #include <openssl/ssl.h> 13 #include <openssl/asn1.h> 14 #include <openssl/asn1t.h> 15 #include <openssl/x509v3.h> 16 17 #ifdef SSL_set_tlsext_status_type 18 #ifndef OPENSSL_NO_TLSEXT 19 #define HAVE_OCSP 20 #include <openssl/err.h> 21 #include <openssl/ocsp.h> 22 #endif /* OPENSSL_NO_TLSEXT */ 23 #endif /* SSL_set_tlsext_status_type */ 24 #endif /* EAP_TLS_OPENSSL */ 25 26 #include "common.h" 27 #include "xml-utils.h" 28 #include "http-utils.h" 29 #ifdef EAP_TLS_OPENSSL 30 #include "crypto/tls_openssl.h" 31 #endif /* EAP_TLS_OPENSSL */ 32 33 34 struct http_ctx { 35 void *ctx; 36 struct xml_node_ctx *xml; 37 CURL *curl; 38 struct curl_slist *curl_hdr; 39 char *svc_address; 40 char *curl_buf; 41 size_t curl_buf_len; 42 43 enum { 44 NO_OCSP, OPTIONAL_OCSP, MANDATORY_OCSP 45 } ocsp; 46 X509 *peer_cert; 47 X509 *peer_issuer; 48 X509 *peer_issuer_issuer; 49 50 const char *last_err; 51 const char *url; 52 }; 53 54 clear_curl(struct http_ctx * ctx)55 static void clear_curl(struct http_ctx *ctx) 56 { 57 if (ctx->curl) { 58 curl_easy_cleanup(ctx->curl); 59 ctx->curl = NULL; 60 } 61 if (ctx->curl_hdr) { 62 curl_slist_free_all(ctx->curl_hdr); 63 ctx->curl_hdr = NULL; 64 } 65 } 66 67 debug_dump(struct http_ctx * ctx,const char * title,const char * buf,size_t len)68 static void debug_dump(struct http_ctx *ctx, const char *title, 69 const char *buf, size_t len) 70 { 71 char *txt; 72 size_t i; 73 74 for (i = 0; i < len; i++) { 75 if (buf[i] < 32 && buf[i] != '\t' && buf[i] != '\n' && 76 buf[i] != '\r') { 77 wpa_hexdump_ascii(MSG_MSGDUMP, title, buf, len); 78 return; 79 } 80 } 81 82 txt = os_malloc(len + 1); 83 if (txt == NULL) 84 return; 85 os_memcpy(txt, buf, len); 86 txt[len] = '\0'; 87 while (len > 0) { 88 len--; 89 if (txt[len] == '\n' || txt[len] == '\r') 90 txt[len] = '\0'; 91 else 92 break; 93 } 94 wpa_printf(MSG_MSGDUMP, "%s[%s]", title, txt); 95 os_free(txt); 96 } 97 98 curl_cb_debug(CURL * curl,curl_infotype info,char * buf,size_t len,void * userdata)99 static int curl_cb_debug(CURL *curl, curl_infotype info, char *buf, size_t len, 100 void *userdata) 101 { 102 struct http_ctx *ctx = userdata; 103 switch (info) { 104 case CURLINFO_TEXT: 105 debug_dump(ctx, "CURLINFO_TEXT", buf, len); 106 break; 107 case CURLINFO_HEADER_IN: 108 debug_dump(ctx, "CURLINFO_HEADER_IN", buf, len); 109 break; 110 case CURLINFO_HEADER_OUT: 111 debug_dump(ctx, "CURLINFO_HEADER_OUT", buf, len); 112 break; 113 case CURLINFO_DATA_IN: 114 debug_dump(ctx, "CURLINFO_DATA_IN", buf, len); 115 break; 116 case CURLINFO_DATA_OUT: 117 debug_dump(ctx, "CURLINFO_DATA_OUT", buf, len); 118 break; 119 case CURLINFO_SSL_DATA_IN: 120 wpa_printf(MSG_DEBUG, "debug - CURLINFO_SSL_DATA_IN - %d", 121 (int) len); 122 break; 123 case CURLINFO_SSL_DATA_OUT: 124 wpa_printf(MSG_DEBUG, "debug - CURLINFO_SSL_DATA_OUT - %d", 125 (int) len); 126 break; 127 case CURLINFO_END: 128 wpa_printf(MSG_DEBUG, "debug - CURLINFO_END - %d", 129 (int) len); 130 break; 131 } 132 return 0; 133 } 134 135 curl_cb_write(void * ptr,size_t size,size_t nmemb,void * userdata)136 static size_t curl_cb_write(void *ptr, size_t size, size_t nmemb, 137 void *userdata) 138 { 139 struct http_ctx *ctx = userdata; 140 char *n; 141 n = os_realloc(ctx->curl_buf, ctx->curl_buf_len + size * nmemb + 1); 142 if (n == NULL) 143 return 0; 144 ctx->curl_buf = n; 145 os_memcpy(n + ctx->curl_buf_len, ptr, size * nmemb); 146 n[ctx->curl_buf_len + size * nmemb] = '\0'; 147 ctx->curl_buf_len += size * nmemb; 148 return size * nmemb; 149 } 150 151 152 #ifdef EAP_TLS_OPENSSL 153 debug_dump_cert(const char * title,X509 * cert)154 static void debug_dump_cert(const char *title, X509 *cert) 155 { 156 BIO *out; 157 char *txt; 158 size_t rlen; 159 160 out = BIO_new(BIO_s_mem()); 161 if (!out) 162 return; 163 164 X509_print_ex(out, cert, XN_FLAG_COMPAT, X509_FLAG_COMPAT); 165 rlen = BIO_ctrl_pending(out); 166 txt = os_malloc(rlen + 1); 167 if (txt) { 168 int res = BIO_read(out, txt, rlen); 169 if (res > 0) { 170 txt[res] = '\0'; 171 wpa_printf(MSG_MSGDUMP, "%s:\n%s", title, txt); 172 } 173 os_free(txt); 174 } 175 BIO_free(out); 176 } 177 178 curl_cb_ssl_verify(int preverify_ok,X509_STORE_CTX * x509_ctx)179 static int curl_cb_ssl_verify(int preverify_ok, X509_STORE_CTX *x509_ctx) 180 { 181 struct http_ctx *ctx; 182 X509 *cert; 183 int err, depth; 184 char buf[256]; 185 X509_NAME *name; 186 const char *err_str; 187 SSL *ssl; 188 SSL_CTX *ssl_ctx; 189 190 ssl = X509_STORE_CTX_get_ex_data(x509_ctx, 191 SSL_get_ex_data_X509_STORE_CTX_idx()); 192 ssl_ctx = SSL_get_SSL_CTX(ssl); 193 ctx = SSL_CTX_get_app_data(ssl_ctx); 194 195 wpa_printf(MSG_DEBUG, "curl_cb_ssl_verify, preverify_ok: %d", 196 preverify_ok); 197 198 err = X509_STORE_CTX_get_error(x509_ctx); 199 err_str = X509_verify_cert_error_string(err); 200 depth = X509_STORE_CTX_get_error_depth(x509_ctx); 201 cert = X509_STORE_CTX_get_current_cert(x509_ctx); 202 if (!cert) { 203 wpa_printf(MSG_INFO, "No server certificate available"); 204 ctx->last_err = "No server certificate available"; 205 return 0; 206 } 207 208 if (depth == 0) 209 ctx->peer_cert = cert; 210 else if (depth == 1) 211 ctx->peer_issuer = cert; 212 else if (depth == 2) 213 ctx->peer_issuer_issuer = cert; 214 215 name = X509_get_subject_name(cert); 216 X509_NAME_oneline(name, buf, sizeof(buf)); 217 wpa_printf(MSG_INFO, "Server certificate chain - depth=%d err=%d (%s) subject=%s", 218 depth, err, err_str, buf); 219 debug_dump_cert("Server certificate chain - certificate", cert); 220 221 #ifdef OPENSSL_IS_BORINGSSL 222 if (depth == 0 && ctx->ocsp != NO_OCSP && preverify_ok) { 223 enum ocsp_result res; 224 225 res = check_ocsp_resp(ssl_ctx, ssl, cert, ctx->peer_issuer, 226 ctx->peer_issuer_issuer); 227 if (res == OCSP_REVOKED) { 228 preverify_ok = 0; 229 wpa_printf(MSG_INFO, "OCSP: certificate revoked"); 230 if (err == X509_V_OK) 231 X509_STORE_CTX_set_error( 232 x509_ctx, X509_V_ERR_CERT_REVOKED); 233 } else if (res != OCSP_GOOD && (ctx->ocsp == MANDATORY_OCSP)) { 234 preverify_ok = 0; 235 wpa_printf(MSG_INFO, 236 "OCSP: bad certificate status response"); 237 } 238 } 239 #endif /* OPENSSL_IS_BORINGSSL */ 240 241 if (!preverify_ok) 242 ctx->last_err = "TLS validation failed"; 243 244 return preverify_ok; 245 } 246 247 248 #ifdef HAVE_OCSP 249 ocsp_debug_print_resp(OCSP_RESPONSE * rsp)250 static void ocsp_debug_print_resp(OCSP_RESPONSE *rsp) 251 { 252 BIO *out; 253 size_t rlen; 254 char *txt; 255 int res; 256 257 out = BIO_new(BIO_s_mem()); 258 if (!out) 259 return; 260 261 OCSP_RESPONSE_print(out, rsp, 0); 262 rlen = BIO_ctrl_pending(out); 263 txt = os_malloc(rlen + 1); 264 if (!txt) { 265 BIO_free(out); 266 return; 267 } 268 269 res = BIO_read(out, txt, rlen); 270 if (res > 0) { 271 txt[res] = '\0'; 272 wpa_printf(MSG_MSGDUMP, "OpenSSL: OCSP Response\n%s", txt); 273 } 274 os_free(txt); 275 BIO_free(out); 276 } 277 278 tls_show_errors(const char * func,const char * txt)279 static void tls_show_errors(const char *func, const char *txt) 280 { 281 unsigned long err; 282 283 wpa_printf(MSG_DEBUG, "OpenSSL: %s - %s %s", 284 func, txt, ERR_error_string(ERR_get_error(), NULL)); 285 286 while ((err = ERR_get_error())) { 287 wpa_printf(MSG_DEBUG, "OpenSSL: pending error: %s", 288 ERR_error_string(err, NULL)); 289 } 290 } 291 292 ocsp_resp_cb(SSL * s,void * arg)293 static int ocsp_resp_cb(SSL *s, void *arg) 294 { 295 struct http_ctx *ctx = arg; 296 const unsigned char *p; 297 int len, status, reason, res; 298 OCSP_RESPONSE *rsp; 299 OCSP_BASICRESP *basic; 300 OCSP_CERTID *id; 301 ASN1_GENERALIZEDTIME *produced_at, *this_update, *next_update; 302 X509_STORE *store; 303 STACK_OF(X509) *certs = NULL; 304 305 len = SSL_get_tlsext_status_ocsp_resp(s, &p); 306 if (!p) { 307 wpa_printf(MSG_DEBUG, "OpenSSL: No OCSP response received"); 308 if (ctx->ocsp == MANDATORY_OCSP) 309 ctx->last_err = "No OCSP response received"; 310 return (ctx->ocsp == MANDATORY_OCSP) ? 0 : 1; 311 } 312 313 wpa_hexdump(MSG_DEBUG, "OpenSSL: OCSP response", p, len); 314 315 rsp = d2i_OCSP_RESPONSE(NULL, &p, len); 316 if (!rsp) { 317 wpa_printf(MSG_INFO, "OpenSSL: Failed to parse OCSP response"); 318 ctx->last_err = "Failed to parse OCSP response"; 319 return 0; 320 } 321 322 ocsp_debug_print_resp(rsp); 323 324 status = OCSP_response_status(rsp); 325 if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) { 326 wpa_printf(MSG_INFO, "OpenSSL: OCSP responder error %d (%s)", 327 status, OCSP_response_status_str(status)); 328 ctx->last_err = "OCSP responder error"; 329 return 0; 330 } 331 332 basic = OCSP_response_get1_basic(rsp); 333 if (!basic) { 334 wpa_printf(MSG_INFO, "OpenSSL: Could not find BasicOCSPResponse"); 335 ctx->last_err = "Could not find BasicOCSPResponse"; 336 return 0; 337 } 338 339 store = SSL_CTX_get_cert_store(SSL_get_SSL_CTX(s)); 340 if (ctx->peer_issuer) { 341 wpa_printf(MSG_DEBUG, "OpenSSL: Add issuer"); 342 debug_dump_cert("OpenSSL: Issuer certificate", 343 ctx->peer_issuer); 344 345 if (X509_STORE_add_cert(store, ctx->peer_issuer) != 1) { 346 tls_show_errors(__func__, 347 "OpenSSL: Could not add issuer to certificate store"); 348 } 349 certs = sk_X509_new_null(); 350 if (certs) { 351 X509 *cert; 352 cert = X509_dup(ctx->peer_issuer); 353 if (cert && !sk_X509_push(certs, cert)) { 354 tls_show_errors( 355 __func__, 356 "OpenSSL: Could not add issuer to OCSP responder trust store"); 357 X509_free(cert); 358 sk_X509_free(certs); 359 certs = NULL; 360 } 361 if (certs && ctx->peer_issuer_issuer) { 362 cert = X509_dup(ctx->peer_issuer_issuer); 363 if (cert && !sk_X509_push(certs, cert)) { 364 tls_show_errors( 365 __func__, 366 "OpenSSL: Could not add issuer's issuer to OCSP responder trust store"); 367 X509_free(cert); 368 } 369 } 370 } 371 } 372 373 status = OCSP_basic_verify(basic, certs, store, OCSP_TRUSTOTHER); 374 sk_X509_pop_free(certs, X509_free); 375 if (status <= 0) { 376 tls_show_errors(__func__, 377 "OpenSSL: OCSP response failed verification"); 378 OCSP_BASICRESP_free(basic); 379 OCSP_RESPONSE_free(rsp); 380 ctx->last_err = "OCSP response failed verification"; 381 return 0; 382 } 383 384 wpa_printf(MSG_DEBUG, "OpenSSL: OCSP response verification succeeded"); 385 386 if (!ctx->peer_cert) { 387 wpa_printf(MSG_DEBUG, "OpenSSL: Peer certificate not available for OCSP status check"); 388 OCSP_BASICRESP_free(basic); 389 OCSP_RESPONSE_free(rsp); 390 ctx->last_err = "Peer certificate not available for OCSP status check"; 391 return 0; 392 } 393 394 if (!ctx->peer_issuer) { 395 wpa_printf(MSG_DEBUG, "OpenSSL: Peer issuer certificate not available for OCSP status check"); 396 OCSP_BASICRESP_free(basic); 397 OCSP_RESPONSE_free(rsp); 398 ctx->last_err = "Peer issuer certificate not available for OCSP status check"; 399 return 0; 400 } 401 402 id = OCSP_cert_to_id(EVP_sha256(), ctx->peer_cert, ctx->peer_issuer); 403 if (!id) { 404 wpa_printf(MSG_DEBUG, 405 "OpenSSL: Could not create OCSP certificate identifier (SHA256)"); 406 OCSP_BASICRESP_free(basic); 407 OCSP_RESPONSE_free(rsp); 408 ctx->last_err = "Could not create OCSP certificate identifier"; 409 return 0; 410 } 411 412 res = OCSP_resp_find_status(basic, id, &status, &reason, &produced_at, 413 &this_update, &next_update); 414 if (!res) { 415 id = OCSP_cert_to_id(NULL, ctx->peer_cert, ctx->peer_issuer); 416 if (!id) { 417 wpa_printf(MSG_DEBUG, 418 "OpenSSL: Could not create OCSP certificate identifier (SHA1)"); 419 OCSP_BASICRESP_free(basic); 420 OCSP_RESPONSE_free(rsp); 421 ctx->last_err = 422 "Could not create OCSP certificate identifier"; 423 return 0; 424 } 425 426 res = OCSP_resp_find_status(basic, id, &status, &reason, 427 &produced_at, &this_update, 428 &next_update); 429 } 430 431 if (!res) { 432 wpa_printf(MSG_INFO, "OpenSSL: Could not find current server certificate from OCSP response%s", 433 (ctx->ocsp == MANDATORY_OCSP) ? "" : 434 " (OCSP not required)"); 435 OCSP_CERTID_free(id); 436 OCSP_BASICRESP_free(basic); 437 OCSP_RESPONSE_free(rsp); 438 if (ctx->ocsp == MANDATORY_OCSP) 439 440 ctx->last_err = "Could not find current server certificate from OCSP response"; 441 return (ctx->ocsp == MANDATORY_OCSP) ? 0 : 1; 442 } 443 OCSP_CERTID_free(id); 444 445 if (!OCSP_check_validity(this_update, next_update, 5 * 60, -1)) { 446 tls_show_errors(__func__, "OpenSSL: OCSP status times invalid"); 447 OCSP_BASICRESP_free(basic); 448 OCSP_RESPONSE_free(rsp); 449 ctx->last_err = "OCSP status times invalid"; 450 return 0; 451 } 452 453 OCSP_BASICRESP_free(basic); 454 OCSP_RESPONSE_free(rsp); 455 456 wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status for server certificate: %s", 457 OCSP_cert_status_str(status)); 458 459 if (status == V_OCSP_CERTSTATUS_GOOD) 460 return 1; 461 if (status == V_OCSP_CERTSTATUS_REVOKED) { 462 ctx->last_err = "Server certificate has been revoked"; 463 return 0; 464 } 465 if (ctx->ocsp == MANDATORY_OCSP) { 466 wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status unknown, but OCSP required"); 467 ctx->last_err = "OCSP status unknown"; 468 return 0; 469 } 470 wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status unknown, but OCSP was not required, so allow connection to continue"); 471 return 1; 472 } 473 474 475 #if OPENSSL_VERSION_NUMBER < 0x10100000L 476 static SSL_METHOD patch_ssl_method; 477 static const SSL_METHOD *real_ssl_method; 478 curl_patch_ssl_new(SSL * s)479 static int curl_patch_ssl_new(SSL *s) 480 { 481 SSL_CTX *ssl = SSL_get_SSL_CTX(s); 482 int ret; 483 484 ssl->method = real_ssl_method; 485 s->method = real_ssl_method; 486 487 ret = s->method->ssl_new(s); 488 SSL_set_tlsext_status_type(s, TLSEXT_STATUSTYPE_ocsp); 489 490 return ret; 491 } 492 #endif /* OpenSSL < 1.1.0 */ 493 494 #endif /* HAVE_OCSP */ 495 496 curl_cb_ssl(CURL * curl,void * sslctx,void * parm)497 static CURLcode curl_cb_ssl(CURL *curl, void *sslctx, void *parm) 498 { 499 struct http_ctx *ctx = parm; 500 SSL_CTX *ssl = sslctx; 501 502 wpa_printf(MSG_DEBUG, "curl_cb_ssl"); 503 SSL_CTX_set_app_data(ssl, ctx); 504 SSL_CTX_set_verify(ssl, SSL_VERIFY_PEER, curl_cb_ssl_verify); 505 506 #ifdef HAVE_OCSP 507 if (ctx->ocsp != NO_OCSP) { 508 SSL_CTX_set_tlsext_status_cb(ssl, ocsp_resp_cb); 509 SSL_CTX_set_tlsext_status_arg(ssl, ctx); 510 511 #if OPENSSL_VERSION_NUMBER < 0x10100000L 512 /* 513 * Use a temporary SSL_METHOD to get a callback on SSL_new() 514 * from libcurl since there is no proper callback registration 515 * available for this. 516 */ 517 os_memset(&patch_ssl_method, 0, sizeof(patch_ssl_method)); 518 patch_ssl_method.ssl_new = curl_patch_ssl_new; 519 real_ssl_method = ssl->method; 520 ssl->method = &patch_ssl_method; 521 #endif /* OpenSSL < 1.1.0 */ 522 } 523 #endif /* HAVE_OCSP */ 524 525 return CURLE_OK; 526 } 527 528 #endif /* EAP_TLS_OPENSSL */ 529 530 setup_curl_post(struct http_ctx * ctx,const char * address,const char * ca_fname,const char * username,const char * password,const char * client_cert,const char * client_key)531 static CURL * setup_curl_post(struct http_ctx *ctx, const char *address, 532 const char *ca_fname, const char *username, 533 const char *password, const char *client_cert, 534 const char *client_key) 535 { 536 CURL *curl; 537 #ifdef EAP_TLS_OPENSSL 538 const char *extra = " tls=openssl"; 539 #else /* EAP_TLS_OPENSSL */ 540 const char *extra = ""; 541 #endif /* EAP_TLS_OPENSSL */ 542 543 wpa_printf(MSG_DEBUG, "Start HTTP client: address=%s ca_fname=%s " 544 "username=%s%s", address, ca_fname, username, extra); 545 546 curl = curl_easy_init(); 547 if (curl == NULL) 548 return NULL; 549 550 curl_easy_setopt(curl, CURLOPT_URL, address); 551 curl_easy_setopt(curl, CURLOPT_POST, 1L); 552 if (ca_fname) { 553 curl_easy_setopt(curl, CURLOPT_CAINFO, ca_fname); 554 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L); 555 #ifdef EAP_TLS_OPENSSL 556 curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, curl_cb_ssl); 557 curl_easy_setopt(curl, CURLOPT_SSL_CTX_DATA, ctx); 558 #if defined(OPENSSL_IS_BORINGSSL) || (OPENSSL_VERSION_NUMBER >= 0x10100000L) 559 /* For now, using the CURLOPT_SSL_VERIFYSTATUS option only 560 * with BoringSSL since the OpenSSL specific callback hack to 561 * enable OCSP is not available with BoringSSL. The OCSP 562 * implementation within libcurl is not sufficient for the 563 * Hotspot 2.0 OSU needs, so cannot use this with OpenSSL. 564 */ 565 if (ctx->ocsp != NO_OCSP) 566 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYSTATUS, 1L); 567 #endif /* OPENSSL_IS_BORINGSSL */ 568 #endif /* EAP_TLS_OPENSSL */ 569 } else { 570 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); 571 } 572 if (client_cert && client_key) { 573 curl_easy_setopt(curl, CURLOPT_SSLCERT, client_cert); 574 curl_easy_setopt(curl, CURLOPT_SSLKEY, client_key); 575 } 576 /* TODO: use curl_easy_getinfo() with CURLINFO_CERTINFO to fetch 577 * information about the server certificate */ 578 curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L); 579 curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, curl_cb_debug); 580 curl_easy_setopt(curl, CURLOPT_DEBUGDATA, ctx); 581 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_cb_write); 582 curl_easy_setopt(curl, CURLOPT_WRITEDATA, ctx); 583 curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); 584 if (username) { 585 curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_ANYSAFE); 586 curl_easy_setopt(curl, CURLOPT_USERNAME, username); 587 curl_easy_setopt(curl, CURLOPT_PASSWORD, password); 588 } 589 590 return curl; 591 } 592 593 free_curl_buf(struct http_ctx * ctx)594 static void free_curl_buf(struct http_ctx *ctx) 595 { 596 os_free(ctx->curl_buf); 597 ctx->curl_buf = NULL; 598 ctx->curl_buf_len = 0; 599 } 600 601 http_init_ctx(void * upper_ctx,struct xml_node_ctx * xml_ctx)602 struct http_ctx * http_init_ctx(void *upper_ctx, struct xml_node_ctx *xml_ctx) 603 { 604 struct http_ctx *ctx; 605 606 ctx = os_zalloc(sizeof(*ctx)); 607 if (ctx == NULL) 608 return NULL; 609 ctx->ctx = upper_ctx; 610 ctx->xml = xml_ctx; 611 ctx->ocsp = OPTIONAL_OCSP; 612 613 curl_global_init(CURL_GLOBAL_ALL); 614 615 return ctx; 616 } 617 618 http_ocsp_set(struct http_ctx * ctx,int val)619 void http_ocsp_set(struct http_ctx *ctx, int val) 620 { 621 if (val == 0) 622 ctx->ocsp = NO_OCSP; 623 else if (val == 1) 624 ctx->ocsp = OPTIONAL_OCSP; 625 if (val == 2) 626 ctx->ocsp = MANDATORY_OCSP; 627 } 628 629 http_deinit_ctx(struct http_ctx * ctx)630 void http_deinit_ctx(struct http_ctx *ctx) 631 { 632 clear_curl(ctx); 633 os_free(ctx->curl_buf); 634 curl_global_cleanup(); 635 636 os_free(ctx->svc_address); 637 638 os_free(ctx); 639 } 640 641 http_download_file(struct http_ctx * ctx,const char * url,const char * fname,const char * ca_fname)642 int http_download_file(struct http_ctx *ctx, const char *url, 643 const char *fname, const char *ca_fname) 644 { 645 CURL *curl; 646 FILE *f = NULL; 647 CURLcode res; 648 long http = 0; 649 int ret = -1; 650 651 ctx->last_err = NULL; 652 ctx->url = url; 653 654 wpa_printf(MSG_DEBUG, "curl: Download file from %s to %s (ca=%s)", 655 url, fname, ca_fname); 656 curl = curl_easy_init(); 657 if (curl == NULL) 658 goto fail; 659 660 f = fopen(fname, "wb"); 661 if (!f) 662 goto fail; 663 664 curl_easy_setopt(curl, CURLOPT_URL, url); 665 if (ca_fname) { 666 curl_easy_setopt(curl, CURLOPT_CAINFO, ca_fname); 667 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L); 668 curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L); 669 } else { 670 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); 671 } 672 curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, curl_cb_debug); 673 curl_easy_setopt(curl, CURLOPT_DEBUGDATA, ctx); 674 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fwrite); 675 curl_easy_setopt(curl, CURLOPT_WRITEDATA, f); 676 curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); 677 678 res = curl_easy_perform(curl); 679 if (res != CURLE_OK) { 680 if (!ctx->last_err) 681 ctx->last_err = curl_easy_strerror(res); 682 wpa_printf(MSG_ERROR, "curl_easy_perform() failed: %s", 683 ctx->last_err); 684 goto fail; 685 } 686 687 curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http); 688 wpa_printf(MSG_DEBUG, "curl: Server response code %ld", http); 689 if (http != 200) { 690 ctx->last_err = "HTTP download failed"; 691 wpa_printf(MSG_INFO, "HTTP download failed - code %ld", http); 692 goto fail; 693 } 694 695 ret = 0; 696 697 fail: 698 ctx->url = NULL; 699 if (curl) 700 curl_easy_cleanup(curl); 701 if (f) 702 fclose(f); 703 704 return ret; 705 } 706 707 http_post(struct http_ctx * ctx,const char * url,const char * data,const char * content_type,const char * ext_hdr,const char * ca_fname,const char * username,const char * password,const char * client_cert,const char * client_key,size_t * resp_len)708 char * http_post(struct http_ctx *ctx, const char *url, const char *data, 709 const char *content_type, const char *ext_hdr, 710 const char *ca_fname, 711 const char *username, const char *password, 712 const char *client_cert, const char *client_key, 713 size_t *resp_len) 714 { 715 long http = 0; 716 CURLcode res; 717 char *ret = NULL; 718 CURL *curl; 719 struct curl_slist *curl_hdr = NULL; 720 721 ctx->last_err = NULL; 722 ctx->url = url; 723 wpa_printf(MSG_DEBUG, "curl: HTTP POST to %s", url); 724 curl = setup_curl_post(ctx, url, ca_fname, username, password, 725 client_cert, client_key); 726 if (curl == NULL) 727 goto fail; 728 729 if (content_type) { 730 char ct[200]; 731 snprintf(ct, sizeof(ct), "Content-Type: %s", content_type); 732 curl_hdr = curl_slist_append(curl_hdr, ct); 733 } 734 if (ext_hdr) 735 curl_hdr = curl_slist_append(curl_hdr, ext_hdr); 736 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_hdr); 737 738 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data); 739 free_curl_buf(ctx); 740 741 res = curl_easy_perform(curl); 742 if (res != CURLE_OK) { 743 if (!ctx->last_err) 744 ctx->last_err = curl_easy_strerror(res); 745 wpa_printf(MSG_ERROR, "curl_easy_perform() failed: %s", 746 ctx->last_err); 747 goto fail; 748 } 749 750 curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http); 751 wpa_printf(MSG_DEBUG, "curl: Server response code %ld", http); 752 if (http != 200) { 753 ctx->last_err = "HTTP POST failed"; 754 wpa_printf(MSG_INFO, "HTTP POST failed - code %ld", http); 755 goto fail; 756 } 757 758 if (ctx->curl_buf == NULL) 759 goto fail; 760 761 ret = ctx->curl_buf; 762 if (resp_len) 763 *resp_len = ctx->curl_buf_len; 764 ctx->curl_buf = NULL; 765 ctx->curl_buf_len = 0; 766 767 wpa_printf(MSG_MSGDUMP, "Server response:\n%s", ret); 768 769 fail: 770 free_curl_buf(ctx); 771 ctx->url = NULL; 772 return ret; 773 } 774 775 http_get_err(struct http_ctx * ctx)776 const char * http_get_err(struct http_ctx *ctx) 777 { 778 return ctx->last_err; 779 } 780