http_curl.c revision d5dc24eb5fbf0e0feff214c0260cae845721d5fe
1/* 2 * HTTP wrapper for libcurl 3 * Copyright (c) 2012-2013, 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 30 31struct http_ctx { 32 void *ctx; 33 struct xml_node_ctx *xml; 34 CURL *curl; 35 struct curl_slist *curl_hdr; 36 char *svc_address; 37 char *svc_ca_fname; 38 char *svc_username; 39 char *svc_password; 40 char *svc_client_cert; 41 char *svc_client_key; 42 char *curl_buf; 43 size_t curl_buf_len; 44 45 int (*cert_cb)(void *ctx, struct http_cert *cert); 46 void *cert_cb_ctx; 47 48 enum { 49 NO_OCSP, OPTIONAL_OCSP, MANDATORY_OCSP 50 } ocsp; 51 X509 *peer_cert; 52 X509 *peer_issuer; 53 X509 *peer_issuer_issuer; 54 55 const char *last_err; 56}; 57 58 59static void clear_curl(struct http_ctx *ctx) 60{ 61 if (ctx->curl) { 62 curl_easy_cleanup(ctx->curl); 63 ctx->curl = NULL; 64 } 65 if (ctx->curl_hdr) { 66 curl_slist_free_all(ctx->curl_hdr); 67 ctx->curl_hdr = NULL; 68 } 69} 70 71 72static void clone_str(char **dst, const char *src) 73{ 74 os_free(*dst); 75 if (src) 76 *dst = os_strdup(src); 77 else 78 *dst = NULL; 79} 80 81 82static void debug_dump(struct http_ctx *ctx, const char *title, 83 const char *buf, size_t len) 84{ 85 char *txt = os_malloc(len + 1); 86 if (txt == NULL) 87 return; 88 os_memcpy(txt, buf, len); 89 txt[len] = '\0'; 90 while (len > 0) { 91 len--; 92 if (txt[len] == '\r' || txt[len] == '\n') 93 txt[len] = '\0'; 94 } 95 wpa_printf(MSG_MSGDUMP, "%s[%s]", title, txt); 96 os_free(txt); 97} 98 99 100static int curl_cb_debug(CURL *curl, curl_infotype info, char *buf, size_t len, 101 void *userdata) 102{ 103 struct http_ctx *ctx = userdata; 104 switch (info) { 105 case CURLINFO_TEXT: 106 debug_dump(ctx, "CURLINFO_TEXT", buf, len); 107 break; 108 case CURLINFO_HEADER_IN: 109 debug_dump(ctx, "CURLINFO_HEADER_IN", buf, len); 110 break; 111 case CURLINFO_HEADER_OUT: 112 debug_dump(ctx, "CURLINFO_HEADER_OUT", buf, len); 113 break; 114 case CURLINFO_DATA_IN: 115 debug_dump(ctx, "CURLINFO_DATA_IN", buf, len); 116 break; 117 case CURLINFO_DATA_OUT: 118 debug_dump(ctx, "CURLINFO_DATA_OUT", buf, len); 119 break; 120 case CURLINFO_SSL_DATA_IN: 121 wpa_printf(MSG_DEBUG, "debug - CURLINFO_SSL_DATA_IN - %d", 122 (int) len); 123 break; 124 case CURLINFO_SSL_DATA_OUT: 125 wpa_printf(MSG_DEBUG, "debug - CURLINFO_SSL_DATA_OUT - %d", 126 (int) len); 127 break; 128 case CURLINFO_END: 129 wpa_printf(MSG_DEBUG, "debug - CURLINFO_END - %d", 130 (int) len); 131 break; 132 } 133 return 0; 134} 135 136 137static size_t curl_cb_header(void *ptr, size_t size, size_t nmemb, 138 void *userdata) 139{ 140 struct http_ctx *ctx = userdata; 141 debug_dump(ctx, "curl header", ptr, size * nmemb); 142 return size * nmemb; 143} 144 145 146static size_t curl_cb_write(void *ptr, size_t size, size_t nmemb, 147 void *userdata) 148{ 149 struct http_ctx *ctx = userdata; 150 char *n; 151 debug_dump(ctx, "curl write", ptr, size * nmemb); 152 n = os_realloc(ctx->curl_buf, ctx->curl_buf_len + size * nmemb + 1); 153 if (n == NULL) 154 return 0; 155 ctx->curl_buf = n; 156 os_memcpy(n + ctx->curl_buf_len, ptr, size * nmemb); 157 n[ctx->curl_buf_len + size * nmemb] = '\0'; 158 ctx->curl_buf_len += size * nmemb; 159 return size * nmemb; 160} 161 162 163#ifdef EAP_TLS_OPENSSL 164 165static void debug_dump_cert(const char *title, X509 *cert) 166{ 167 BIO *out; 168 char *txt; 169 size_t rlen; 170 171 out = BIO_new(BIO_s_mem()); 172 if (!out) 173 return; 174 175 X509_print_ex(out, cert, XN_FLAG_COMPAT, X509_FLAG_COMPAT); 176 rlen = BIO_ctrl_pending(out); 177 txt = os_malloc(rlen + 1); 178 if (txt) { 179 int res = BIO_read(out, txt, rlen); 180 if (res > 0) { 181 txt[res] = '\0'; 182 wpa_printf(MSG_MSGDUMP, "%s:\n%s", title, txt); 183 } 184 os_free(txt); 185 } 186 BIO_free(out); 187} 188 189 190static void add_alt_name_othername(struct http_ctx *ctx, struct http_cert *cert, 191 OTHERNAME *o) 192{ 193 char txt[100]; 194 int res; 195 struct http_othername *on; 196 ASN1_TYPE *val; 197 198 on = os_realloc_array(cert->othername, cert->num_othername + 1, 199 sizeof(struct http_othername)); 200 if (on == NULL) 201 return; 202 cert->othername = on; 203 on = &on[cert->num_othername]; 204 os_memset(on, 0, sizeof(*on)); 205 206 res = OBJ_obj2txt(txt, sizeof(txt), o->type_id, 1); 207 if (res < 0 || res >= (int) sizeof(txt)) 208 return; 209 210 on->oid = os_strdup(txt); 211 if (on->oid == NULL) 212 return; 213 214 val = o->value; 215 on->data = val->value.octet_string->data; 216 on->len = val->value.octet_string->length; 217 218 cert->num_othername++; 219} 220 221 222static void add_alt_name_dns(struct http_ctx *ctx, struct http_cert *cert, 223 ASN1_STRING *name) 224{ 225 char *buf; 226 char **n; 227 228 buf = NULL; 229 if (ASN1_STRING_to_UTF8((unsigned char **) &buf, name) < 0) 230 return; 231 232 n = os_realloc_array(cert->dnsname, cert->num_dnsname + 1, 233 sizeof(char *)); 234 if (n == NULL) 235 return; 236 237 cert->dnsname = n; 238 n[cert->num_dnsname] = buf; 239 cert->num_dnsname++; 240} 241 242 243static void add_alt_name(struct http_ctx *ctx, struct http_cert *cert, 244 const GENERAL_NAME *name) 245{ 246 switch (name->type) { 247 case GEN_OTHERNAME: 248 add_alt_name_othername(ctx, cert, name->d.otherName); 249 break; 250 case GEN_DNS: 251 add_alt_name_dns(ctx, cert, name->d.dNSName); 252 break; 253 } 254} 255 256 257static void add_alt_names(struct http_ctx *ctx, struct http_cert *cert, 258 GENERAL_NAMES *names) 259{ 260 int num, i; 261 262 num = sk_GENERAL_NAME_num(names); 263 for (i = 0; i < num; i++) { 264 const GENERAL_NAME *name; 265 name = sk_GENERAL_NAME_value(names, i); 266 add_alt_name(ctx, cert, name); 267 } 268} 269 270 271/* RFC 3709 */ 272 273typedef struct { 274 X509_ALGOR *hashAlg; 275 ASN1_OCTET_STRING *hashValue; 276} HashAlgAndValue; 277 278typedef struct { 279 STACK_OF(HashAlgAndValue) *refStructHash; 280 STACK_OF(ASN1_IA5STRING) *refStructURI; 281} LogotypeReference; 282 283typedef struct { 284 ASN1_IA5STRING *mediaType; 285 STACK_OF(HashAlgAndValue) *logotypeHash; 286 STACK_OF(ASN1_IA5STRING) *logotypeURI; 287} LogotypeDetails; 288 289typedef struct { 290 int type; 291 union { 292 ASN1_INTEGER *numBits; 293 ASN1_INTEGER *tableSize; 294 } d; 295} LogotypeImageResolution; 296 297typedef struct { 298 ASN1_INTEGER *type; /* LogotypeImageType ::= INTEGER */ 299 ASN1_INTEGER *fileSize; 300 ASN1_INTEGER *xSize; 301 ASN1_INTEGER *ySize; 302 LogotypeImageResolution *resolution; 303 ASN1_IA5STRING *language; 304} LogotypeImageInfo; 305 306typedef struct { 307 LogotypeDetails *imageDetails; 308 LogotypeImageInfo *imageInfo; 309} LogotypeImage; 310 311typedef struct { 312 ASN1_INTEGER *fileSize; 313 ASN1_INTEGER *playTime; 314 ASN1_INTEGER *channels; 315 ASN1_INTEGER *sampleRate; 316 ASN1_IA5STRING *language; 317} LogotypeAudioInfo; 318 319typedef struct { 320 LogotypeDetails *audioDetails; 321 LogotypeAudioInfo *audioInfo; 322} LogotypeAudio; 323 324typedef struct { 325 STACK_OF(LogotypeImage) *image; 326 STACK_OF(LogotypeAudio) *audio; 327} LogotypeData; 328 329typedef struct { 330 int type; 331 union { 332 LogotypeData *direct; 333 LogotypeReference *indirect; 334 } d; 335} LogotypeInfo; 336 337typedef struct { 338 ASN1_OBJECT *logotypeType; 339 LogotypeInfo *info; 340} OtherLogotypeInfo; 341 342typedef struct { 343 STACK_OF(LogotypeInfo) *communityLogos; 344 LogotypeInfo *issuerLogo; 345 LogotypeInfo *subjectLogo; 346 STACK_OF(OtherLogotypeInfo) *otherLogos; 347} LogotypeExtn; 348 349ASN1_SEQUENCE(HashAlgAndValue) = { 350 ASN1_SIMPLE(HashAlgAndValue, hashAlg, X509_ALGOR), 351 ASN1_SIMPLE(HashAlgAndValue, hashValue, ASN1_OCTET_STRING) 352} ASN1_SEQUENCE_END(HashAlgAndValue); 353 354ASN1_SEQUENCE(LogotypeReference) = { 355 ASN1_SEQUENCE_OF(LogotypeReference, refStructHash, HashAlgAndValue), 356 ASN1_SEQUENCE_OF(LogotypeReference, refStructURI, ASN1_IA5STRING) 357} ASN1_SEQUENCE_END(LogotypeReference); 358 359ASN1_SEQUENCE(LogotypeDetails) = { 360 ASN1_SIMPLE(LogotypeDetails, mediaType, ASN1_IA5STRING), 361 ASN1_SEQUENCE_OF(LogotypeDetails, logotypeHash, HashAlgAndValue), 362 ASN1_SEQUENCE_OF(LogotypeDetails, logotypeURI, ASN1_IA5STRING) 363} ASN1_SEQUENCE_END(LogotypeDetails); 364 365ASN1_CHOICE(LogotypeImageResolution) = { 366 ASN1_IMP(LogotypeImageResolution, d.numBits, ASN1_INTEGER, 1), 367 ASN1_IMP(LogotypeImageResolution, d.tableSize, ASN1_INTEGER, 2) 368} ASN1_CHOICE_END(LogotypeImageResolution); 369 370ASN1_SEQUENCE(LogotypeImageInfo) = { 371 ASN1_IMP_OPT(LogotypeImageInfo, type, ASN1_INTEGER, 0), 372 ASN1_SIMPLE(LogotypeImageInfo, fileSize, ASN1_INTEGER), 373 ASN1_SIMPLE(LogotypeImageInfo, xSize, ASN1_INTEGER), 374 ASN1_SIMPLE(LogotypeImageInfo, ySize, ASN1_INTEGER), 375 ASN1_OPT(LogotypeImageInfo, resolution, LogotypeImageResolution), 376 ASN1_IMP_OPT(LogotypeImageInfo, language, ASN1_IA5STRING, 4), 377} ASN1_SEQUENCE_END(LogotypeImageInfo); 378 379ASN1_SEQUENCE(LogotypeImage) = { 380 ASN1_SIMPLE(LogotypeImage, imageDetails, LogotypeDetails), 381 ASN1_OPT(LogotypeImage, imageInfo, LogotypeImageInfo) 382} ASN1_SEQUENCE_END(LogotypeImage); 383 384ASN1_SEQUENCE(LogotypeAudioInfo) = { 385 ASN1_SIMPLE(LogotypeAudioInfo, fileSize, ASN1_INTEGER), 386 ASN1_SIMPLE(LogotypeAudioInfo, playTime, ASN1_INTEGER), 387 ASN1_SIMPLE(LogotypeAudioInfo, channels, ASN1_INTEGER), 388 ASN1_IMP_OPT(LogotypeAudioInfo, sampleRate, ASN1_INTEGER, 3), 389 ASN1_IMP_OPT(LogotypeAudioInfo, language, ASN1_IA5STRING, 4) 390} ASN1_SEQUENCE_END(LogotypeAudioInfo); 391 392ASN1_SEQUENCE(LogotypeAudio) = { 393 ASN1_SIMPLE(LogotypeAudio, audioDetails, LogotypeDetails), 394 ASN1_OPT(LogotypeAudio, audioInfo, LogotypeAudioInfo) 395} ASN1_SEQUENCE_END(LogotypeAudio); 396 397ASN1_SEQUENCE(LogotypeData) = { 398 ASN1_SEQUENCE_OF_OPT(LogotypeData, image, LogotypeImage), 399 ASN1_IMP_SEQUENCE_OF_OPT(LogotypeData, audio, LogotypeAudio, 1) 400} ASN1_SEQUENCE_END(LogotypeData); 401 402ASN1_CHOICE(LogotypeInfo) = { 403 ASN1_IMP(LogotypeInfo, d.direct, LogotypeData, 0), 404 ASN1_IMP(LogotypeInfo, d.indirect, LogotypeReference, 1) 405} ASN1_CHOICE_END(LogotypeInfo); 406 407ASN1_SEQUENCE(OtherLogotypeInfo) = { 408 ASN1_SIMPLE(OtherLogotypeInfo, logotypeType, ASN1_OBJECT), 409 ASN1_SIMPLE(OtherLogotypeInfo, info, LogotypeInfo) 410} ASN1_SEQUENCE_END(OtherLogotypeInfo); 411 412ASN1_SEQUENCE(LogotypeExtn) = { 413 ASN1_EXP_SEQUENCE_OF_OPT(LogotypeExtn, communityLogos, LogotypeInfo, 0), 414 ASN1_EXP_OPT(LogotypeExtn, issuerLogo, LogotypeInfo, 1), 415 ASN1_EXP_OPT(LogotypeExtn, issuerLogo, LogotypeInfo, 2), 416 ASN1_EXP_SEQUENCE_OF_OPT(LogotypeExtn, otherLogos, OtherLogotypeInfo, 3) 417} ASN1_SEQUENCE_END(LogotypeExtn); 418 419IMPLEMENT_ASN1_FUNCTIONS(LogotypeExtn); 420 421#define sk_LogotypeInfo_num(st) SKM_sk_num(LogotypeInfo, (st)) 422#define sk_LogotypeInfo_value(st, i) SKM_sk_value(LogotypeInfo, (st), (i)) 423#define sk_LogotypeImage_num(st) SKM_sk_num(LogotypeImage, (st)) 424#define sk_LogotypeImage_value(st, i) SKM_sk_value(LogotypeImage, (st), (i)) 425#define sk_LogotypeAudio_num(st) SKM_sk_num(LogotypeAudio, (st)) 426#define sk_LogotypeAudio_value(st, i) SKM_sk_value(LogotypeAudio, (st), (i)) 427#define sk_HashAlgAndValue_num(st) SKM_sk_num(HashAlgAndValue, (st)) 428#define sk_HashAlgAndValue_value(st, i) SKM_sk_value(HashAlgAndValue, (st), (i)) 429#define sk_ASN1_IA5STRING_num(st) SKM_sk_num(ASN1_IA5STRING, (st)) 430#define sk_ASN1_IA5STRING_value(st, i) SKM_sk_value(ASN1_IA5STRING, (st), (i)) 431 432 433static void add_logo(struct http_ctx *ctx, struct http_cert *hcert, 434 HashAlgAndValue *hash, ASN1_IA5STRING *uri) 435{ 436 char txt[100]; 437 int res, len; 438 struct http_logo *n; 439 440 if (hash == NULL || uri == NULL) 441 return; 442 443 res = OBJ_obj2txt(txt, sizeof(txt), hash->hashAlg->algorithm, 1); 444 if (res < 0 || res >= (int) sizeof(txt)) 445 return; 446 447 n = os_realloc_array(hcert->logo, hcert->num_logo + 1, 448 sizeof(struct http_logo)); 449 if (n == NULL) 450 return; 451 hcert->logo = n; 452 n = &hcert->logo[hcert->num_logo]; 453 os_memset(n, 0, sizeof(*n)); 454 455 n->alg_oid = os_strdup(txt); 456 if (n->alg_oid == NULL) 457 return; 458 459 n->hash_len = ASN1_STRING_length(hash->hashValue); 460 n->hash = os_malloc(n->hash_len); 461 if (n->hash == NULL) { 462 os_free(n->alg_oid); 463 return; 464 } 465 os_memcpy(n->hash, ASN1_STRING_data(hash->hashValue), n->hash_len); 466 467 len = ASN1_STRING_length(uri); 468 n->uri = os_malloc(len + 1); 469 if (n->uri == NULL) { 470 os_free(n->alg_oid); 471 os_free(n->hash); 472 return; 473 } 474 os_memcpy(n->uri, ASN1_STRING_data(uri), len); 475 n->uri[len] = '\0'; 476 477 hcert->num_logo++; 478} 479 480 481static void add_logo_direct(struct http_ctx *ctx, struct http_cert *hcert, 482 LogotypeData *data) 483{ 484 int i, num; 485 486 if (data->image == NULL) 487 return; 488 489 num = sk_LogotypeImage_num(data->image); 490 for (i = 0; i < num; i++) { 491 LogotypeImage *image; 492 LogotypeDetails *details; 493 int j, hash_num, uri_num; 494 HashAlgAndValue *found_hash = NULL; 495 496 image = sk_LogotypeImage_value(data->image, i); 497 if (image == NULL) 498 continue; 499 500 details = image->imageDetails; 501 if (details == NULL) 502 continue; 503 504 hash_num = sk_HashAlgAndValue_num(details->logotypeHash); 505 for (j = 0; j < hash_num; j++) { 506 HashAlgAndValue *hash; 507 char txt[100]; 508 int res; 509 hash = sk_HashAlgAndValue_value(details->logotypeHash, 510 j); 511 if (hash == NULL) 512 continue; 513 res = OBJ_obj2txt(txt, sizeof(txt), 514 hash->hashAlg->algorithm, 1); 515 if (res < 0 || res >= (int) sizeof(txt)) 516 continue; 517 if (os_strcmp(txt, "2.16.840.1.101.3.4.2.1") == 0) { 518 found_hash = hash; 519 break; 520 } 521 } 522 523 if (!found_hash) { 524 wpa_printf(MSG_DEBUG, "OpenSSL: No SHA256 hash found for the logo"); 525 continue; 526 } 527 528 uri_num = sk_ASN1_IA5STRING_num(details->logotypeURI); 529 for (j = 0; j < uri_num; j++) { 530 ASN1_IA5STRING *uri; 531 uri = sk_ASN1_IA5STRING_value(details->logotypeURI, j); 532 add_logo(ctx, hcert, found_hash, uri); 533 } 534 } 535} 536 537 538static void add_logo_indirect(struct http_ctx *ctx, struct http_cert *hcert, 539 LogotypeReference *ref) 540{ 541 int j, hash_num, uri_num; 542 543 hash_num = sk_HashAlgAndValue_num(ref->refStructHash); 544 uri_num = sk_ASN1_IA5STRING_num(ref->refStructURI); 545 if (hash_num != uri_num) { 546 wpa_printf(MSG_INFO, "Unexpected LogotypeReference array size difference %d != %d", 547 hash_num, uri_num); 548 return; 549 } 550 551 for (j = 0; j < hash_num; j++) { 552 HashAlgAndValue *hash; 553 ASN1_IA5STRING *uri; 554 hash = sk_HashAlgAndValue_value(ref->refStructHash, j); 555 uri = sk_ASN1_IA5STRING_value(ref->refStructURI, j); 556 add_logo(ctx, hcert, hash, uri); 557 } 558} 559 560 561static void i2r_HashAlgAndValue(HashAlgAndValue *hash, BIO *out, int indent) 562{ 563 int i; 564 const unsigned char *data; 565 566 BIO_printf(out, "%*shashAlg: ", indent, ""); 567 i2a_ASN1_OBJECT(out, hash->hashAlg->algorithm); 568 BIO_printf(out, "\n"); 569 570 BIO_printf(out, "%*shashValue: ", indent, ""); 571 data = hash->hashValue->data; 572 for (i = 0; i < hash->hashValue->length; i++) 573 BIO_printf(out, "%s%02x", i > 0 ? ":" : "", data[i]); 574 BIO_printf(out, "\n"); 575} 576 577static void i2r_LogotypeDetails(LogotypeDetails *details, BIO *out, int indent) 578{ 579 int i, num; 580 581 BIO_printf(out, "%*sLogotypeDetails\n", indent, ""); 582 if (details->mediaType) { 583 BIO_printf(out, "%*smediaType: ", indent, ""); 584 ASN1_STRING_print(out, details->mediaType); 585 BIO_printf(out, "\n"); 586 } 587 588 num = details->logotypeHash ? 589 sk_HashAlgAndValue_num(details->logotypeHash) : 0; 590 for (i = 0; i < num; i++) { 591 HashAlgAndValue *hash; 592 hash = sk_HashAlgAndValue_value(details->logotypeHash, i); 593 i2r_HashAlgAndValue(hash, out, indent); 594 } 595 596 num = details->logotypeURI ? 597 sk_ASN1_IA5STRING_num(details->logotypeURI) : 0; 598 for (i = 0; i < num; i++) { 599 ASN1_IA5STRING *uri; 600 uri = sk_ASN1_IA5STRING_value(details->logotypeURI, i); 601 BIO_printf(out, "%*slogotypeURI: ", indent, ""); 602 ASN1_STRING_print(out, uri); 603 BIO_printf(out, "\n"); 604 } 605} 606 607static void i2r_LogotypeImageInfo(LogotypeImageInfo *info, BIO *out, int indent) 608{ 609 long val; 610 611 BIO_printf(out, "%*sLogotypeImageInfo\n", indent, ""); 612 if (info->type) { 613 val = ASN1_INTEGER_get(info->type); 614 BIO_printf(out, "%*stype: %ld\n", indent, "", val); 615 } else { 616 BIO_printf(out, "%*stype: default (1)\n", indent, ""); 617 } 618 val = ASN1_INTEGER_get(info->xSize); 619 BIO_printf(out, "%*sxSize: %ld\n", indent, "", val); 620 val = ASN1_INTEGER_get(info->ySize); 621 BIO_printf(out, "%*sySize: %ld\n", indent, "", val); 622 if (info->resolution) { 623 BIO_printf(out, "%*sresolution\n", indent, ""); 624 /* TODO */ 625 } 626 if (info->language) { 627 BIO_printf(out, "%*slanguage: ", indent, ""); 628 ASN1_STRING_print(out, info->language); 629 BIO_printf(out, "\n"); 630 } 631} 632 633static void i2r_LogotypeImage(LogotypeImage *image, BIO *out, int indent) 634{ 635 BIO_printf(out, "%*sLogotypeImage\n", indent, ""); 636 if (image->imageDetails) { 637 i2r_LogotypeDetails(image->imageDetails, out, indent + 4); 638 } 639 if (image->imageInfo) { 640 i2r_LogotypeImageInfo(image->imageInfo, out, indent + 4); 641 } 642} 643 644static void i2r_LogotypeData(LogotypeData *data, const char *title, BIO *out, 645 int indent) 646{ 647 int i, num; 648 649 BIO_printf(out, "%*s%s - LogotypeData\n", indent, "", title); 650 651 num = data->image ? sk_LogotypeImage_num(data->image) : 0; 652 for (i = 0; i < num; i++) { 653 LogotypeImage *image = sk_LogotypeImage_value(data->image, i); 654 i2r_LogotypeImage(image, out, indent + 4); 655 } 656 657 num = data->audio ? sk_LogotypeAudio_num(data->audio) : 0; 658 for (i = 0; i < num; i++) { 659 BIO_printf(out, "%*saudio: TODO\n", indent, ""); 660 } 661} 662 663static void i2r_LogotypeReference(LogotypeReference *ref, const char *title, 664 BIO *out, int indent) 665{ 666 int i, hash_num, uri_num; 667 668 BIO_printf(out, "%*s%s - LogotypeReference\n", indent, "", title); 669 670 hash_num = ref->refStructHash ? 671 sk_HashAlgAndValue_num(ref->refStructHash) : 0; 672 uri_num = ref->refStructURI ? 673 sk_ASN1_IA5STRING_num(ref->refStructURI) : 0; 674 if (hash_num != uri_num) { 675 BIO_printf(out, "%*sUnexpected LogotypeReference array size difference %d != %d\n", 676 indent, "", hash_num, uri_num); 677 return; 678 } 679 680 for (i = 0; i < hash_num; i++) { 681 HashAlgAndValue *hash; 682 ASN1_IA5STRING *uri; 683 684 hash = sk_HashAlgAndValue_value(ref->refStructHash, i); 685 i2r_HashAlgAndValue(hash, out, indent); 686 687 uri = sk_ASN1_IA5STRING_value(ref->refStructURI, i); 688 BIO_printf(out, "%*srefStructURI: ", indent, ""); 689 ASN1_STRING_print(out, uri); 690 BIO_printf(out, "\n"); 691 } 692} 693 694static void i2r_LogotypeInfo(LogotypeInfo *info, const char *title, BIO *out, 695 int indent) 696{ 697 switch (info->type) { 698 case 0: 699 i2r_LogotypeData(info->d.direct, title, out, indent); 700 break; 701 case 1: 702 i2r_LogotypeReference(info->d.indirect, title, out, indent); 703 break; 704 } 705} 706 707static void debug_print_logotypeext(LogotypeExtn *logo) 708{ 709 BIO *out; 710 int i, num; 711 int indent = 0; 712 713 out = BIO_new_fp(stdout, BIO_NOCLOSE); 714 if (out == NULL) 715 return; 716 717 if (logo->communityLogos) { 718 num = sk_LogotypeInfo_num(logo->communityLogos); 719 for (i = 0; i < num; i++) { 720 LogotypeInfo *info; 721 info = sk_LogotypeInfo_value(logo->communityLogos, i); 722 i2r_LogotypeInfo(info, "communityLogo", out, indent); 723 } 724 } 725 726 if (logo->issuerLogo) { 727 i2r_LogotypeInfo(logo->issuerLogo, "issuerLogo", out, indent ); 728 } 729 730 if (logo->subjectLogo) { 731 i2r_LogotypeInfo(logo->subjectLogo, "subjectLogo", out, indent); 732 } 733 734 if (logo->otherLogos) { 735 BIO_printf(out, "%*sotherLogos - TODO\n", indent, ""); 736 } 737 738 BIO_free(out); 739} 740 741 742static void add_logotype_ext(struct http_ctx *ctx, struct http_cert *hcert, 743 X509 *cert) 744{ 745 ASN1_OBJECT *obj; 746 int pos; 747 X509_EXTENSION *ext; 748 ASN1_OCTET_STRING *os; 749 LogotypeExtn *logo; 750 const unsigned char *data; 751 int i, num; 752 753 obj = OBJ_txt2obj("1.3.6.1.5.5.7.1.12", 0); 754 if (obj == NULL) 755 return; 756 757 pos = X509_get_ext_by_OBJ(cert, obj, -1); 758 if (pos < 0) { 759 wpa_printf(MSG_INFO, "No logotype extension included"); 760 return; 761 } 762 763 wpa_printf(MSG_INFO, "Parsing logotype extension"); 764 ext = X509_get_ext(cert, pos); 765 if (!ext) { 766 wpa_printf(MSG_INFO, "Could not get logotype extension"); 767 return; 768 } 769 770 os = X509_EXTENSION_get_data(ext); 771 if (os == NULL) { 772 wpa_printf(MSG_INFO, "Could not get logotype extension data"); 773 return; 774 } 775 776 wpa_hexdump(MSG_DEBUG, "logotypeExtn", 777 ASN1_STRING_data(os), ASN1_STRING_length(os)); 778 779 data = ASN1_STRING_data(os); 780 logo = d2i_LogotypeExtn(NULL, &data, ASN1_STRING_length(os)); 781 if (logo == NULL) { 782 wpa_printf(MSG_INFO, "Failed to parse logotypeExtn"); 783 return; 784 } 785 786 if (wpa_debug_level < MSG_INFO) 787 debug_print_logotypeext(logo); 788 789 if (!logo->communityLogos) { 790 wpa_printf(MSG_INFO, "No communityLogos included"); 791 LogotypeExtn_free(logo); 792 return; 793 } 794 795 num = sk_LogotypeInfo_num(logo->communityLogos); 796 for (i = 0; i < num; i++) { 797 LogotypeInfo *info; 798 info = sk_LogotypeInfo_value(logo->communityLogos, i); 799 switch (info->type) { 800 case 0: 801 add_logo_direct(ctx, hcert, info->d.direct); 802 break; 803 case 1: 804 add_logo_indirect(ctx, hcert, info->d.indirect); 805 break; 806 } 807 } 808 809 LogotypeExtn_free(logo); 810} 811 812 813static void parse_cert(struct http_ctx *ctx, struct http_cert *hcert, 814 X509 *cert, GENERAL_NAMES **names) 815{ 816 os_memset(hcert, 0, sizeof(*hcert)); 817 818 *names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); 819 if (*names) 820 add_alt_names(ctx, hcert, *names); 821 822 add_logotype_ext(ctx, hcert, cert); 823} 824 825 826static void parse_cert_free(struct http_cert *hcert, GENERAL_NAMES *names) 827{ 828 unsigned int i; 829 830 for (i = 0; i < hcert->num_dnsname; i++) 831 OPENSSL_free(hcert->dnsname[i]); 832 os_free(hcert->dnsname); 833 834 for (i = 0; i < hcert->num_othername; i++) 835 os_free(hcert->othername[i].oid); 836 os_free(hcert->othername); 837 838 for (i = 0; i < hcert->num_logo; i++) { 839 os_free(hcert->logo[i].alg_oid); 840 os_free(hcert->logo[i].hash); 841 os_free(hcert->logo[i].uri); 842 } 843 os_free(hcert->logo); 844 845 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free); 846} 847 848 849static int validate_server_cert(struct http_ctx *ctx, X509 *cert) 850{ 851 GENERAL_NAMES *names; 852 struct http_cert hcert; 853 int ret; 854 855 if (ctx->cert_cb == NULL) 856 return 0; 857 858 if (0) { 859 BIO *out; 860 out = BIO_new_fp(stdout, BIO_NOCLOSE); 861 X509_print_ex(out, cert, XN_FLAG_COMPAT, X509_FLAG_COMPAT); 862 BIO_free(out); 863 } 864 865 parse_cert(ctx, &hcert, cert, &names); 866 ret = ctx->cert_cb(ctx->cert_cb_ctx, &hcert); 867 parse_cert_free(&hcert, names); 868 869 return ret; 870} 871 872 873void http_parse_x509_certificate(struct http_ctx *ctx, const char *fname) 874{ 875 BIO *in, *out; 876 X509 *cert; 877 GENERAL_NAMES *names; 878 struct http_cert hcert; 879 unsigned int i; 880 881 in = BIO_new_file(fname, "r"); 882 if (in == NULL) { 883 wpa_printf(MSG_ERROR, "Could not read '%s'", fname); 884 return; 885 } 886 887 cert = d2i_X509_bio(in, NULL); 888 BIO_free(in); 889 890 if (cert == NULL) { 891 wpa_printf(MSG_ERROR, "Could not parse certificate"); 892 return; 893 } 894 895 out = BIO_new_fp(stdout, BIO_NOCLOSE); 896 if (out) { 897 X509_print_ex(out, cert, XN_FLAG_COMPAT, 898 X509_FLAG_COMPAT); 899 BIO_free(out); 900 } 901 902 wpa_printf(MSG_INFO, "Additional parsing information:"); 903 parse_cert(ctx, &hcert, cert, &names); 904 for (i = 0; i < hcert.num_othername; i++) { 905 if (os_strcmp(hcert.othername[i].oid, 906 "1.3.6.1.4.1.40808.1.1.1") == 0) { 907 char *name = os_zalloc(hcert.othername[i].len + 1); 908 if (name) { 909 os_memcpy(name, hcert.othername[i].data, 910 hcert.othername[i].len); 911 wpa_printf(MSG_INFO, 912 "id-wfa-hotspot-friendlyName: %s", 913 name); 914 os_free(name); 915 } 916 wpa_hexdump_ascii(MSG_INFO, 917 "id-wfa-hotspot-friendlyName", 918 hcert.othername[i].data, 919 hcert.othername[i].len); 920 } else { 921 wpa_printf(MSG_INFO, "subjAltName[othername]: oid=%s", 922 hcert.othername[i].oid); 923 wpa_hexdump_ascii(MSG_INFO, "unknown othername", 924 hcert.othername[i].data, 925 hcert.othername[i].len); 926 } 927 } 928 parse_cert_free(&hcert, names); 929 930 X509_free(cert); 931} 932 933 934static int curl_cb_ssl_verify(int preverify_ok, X509_STORE_CTX *x509_ctx) 935{ 936 struct http_ctx *ctx; 937 X509 *cert; 938 int err, depth; 939 char buf[256]; 940 X509_NAME *name; 941 const char *err_str; 942 SSL *ssl; 943 SSL_CTX *ssl_ctx; 944 945 ssl = X509_STORE_CTX_get_ex_data(x509_ctx, 946 SSL_get_ex_data_X509_STORE_CTX_idx()); 947 ssl_ctx = ssl->ctx; 948 ctx = SSL_CTX_get_app_data(ssl_ctx); 949 950 wpa_printf(MSG_DEBUG, "curl_cb_ssl_verify"); 951 952 err = X509_STORE_CTX_get_error(x509_ctx); 953 err_str = X509_verify_cert_error_string(err); 954 depth = X509_STORE_CTX_get_error_depth(x509_ctx); 955 cert = X509_STORE_CTX_get_current_cert(x509_ctx); 956 if (!cert) { 957 wpa_printf(MSG_INFO, "No server certificate available"); 958 ctx->last_err = "No server certificate available"; 959 return 0; 960 } 961 962 if (depth == 0) 963 ctx->peer_cert = cert; 964 else if (depth == 1) 965 ctx->peer_issuer = cert; 966 else if (depth == 2) 967 ctx->peer_issuer_issuer = cert; 968 969 name = X509_get_subject_name(cert); 970 X509_NAME_oneline(name, buf, sizeof(buf)); 971 wpa_printf(MSG_INFO, "Server certificate chain - depth=%d err=%d (%s) subject=%s", 972 depth, err, err_str, buf); 973 debug_dump_cert("Server certificate chain - certificate", cert); 974 975 if (depth == 0 && preverify_ok && validate_server_cert(ctx, cert) < 0) 976 return 0; 977 978 if (!preverify_ok) 979 ctx->last_err = "TLS validation failed"; 980 981 return preverify_ok; 982} 983 984 985#ifdef HAVE_OCSP 986 987static void ocsp_debug_print_resp(OCSP_RESPONSE *rsp) 988{ 989 BIO *out; 990 size_t rlen; 991 char *txt; 992 int res; 993 994 out = BIO_new(BIO_s_mem()); 995 if (!out) 996 return; 997 998 OCSP_RESPONSE_print(out, rsp, 0); 999 rlen = BIO_ctrl_pending(out); 1000 txt = os_malloc(rlen + 1); 1001 if (!txt) { 1002 BIO_free(out); 1003 return; 1004 } 1005 1006 res = BIO_read(out, txt, rlen); 1007 if (res > 0) { 1008 txt[res] = '\0'; 1009 wpa_printf(MSG_MSGDUMP, "OpenSSL: OCSP Response\n%s", txt); 1010 } 1011 os_free(txt); 1012 BIO_free(out); 1013} 1014 1015 1016static void tls_show_errors(const char *func, const char *txt) 1017{ 1018 unsigned long err; 1019 1020 wpa_printf(MSG_DEBUG, "OpenSSL: %s - %s %s", 1021 func, txt, ERR_error_string(ERR_get_error(), NULL)); 1022 1023 while ((err = ERR_get_error())) { 1024 wpa_printf(MSG_DEBUG, "OpenSSL: pending error: %s", 1025 ERR_error_string(err, NULL)); 1026 } 1027} 1028 1029 1030static int ocsp_resp_cb(SSL *s, void *arg) 1031{ 1032 struct http_ctx *ctx = arg; 1033 const unsigned char *p; 1034 int len, status, reason; 1035 OCSP_RESPONSE *rsp; 1036 OCSP_BASICRESP *basic; 1037 OCSP_CERTID *id; 1038 ASN1_GENERALIZEDTIME *produced_at, *this_update, *next_update; 1039 X509_STORE *store; 1040 STACK_OF(X509) *certs = NULL; 1041 1042 len = SSL_get_tlsext_status_ocsp_resp(s, &p); 1043 if (!p) { 1044 wpa_printf(MSG_DEBUG, "OpenSSL: No OCSP response received"); 1045 if (ctx->ocsp == MANDATORY_OCSP) 1046 ctx->last_err = "No OCSP response received"; 1047 return (ctx->ocsp == MANDATORY_OCSP) ? 0 : 1; 1048 } 1049 1050 wpa_hexdump(MSG_DEBUG, "OpenSSL: OCSP response", p, len); 1051 1052 rsp = d2i_OCSP_RESPONSE(NULL, &p, len); 1053 if (!rsp) { 1054 wpa_printf(MSG_INFO, "OpenSSL: Failed to parse OCSP response"); 1055 ctx->last_err = "Failed to parse OCSP response"; 1056 return 0; 1057 } 1058 1059 ocsp_debug_print_resp(rsp); 1060 1061 status = OCSP_response_status(rsp); 1062 if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) { 1063 wpa_printf(MSG_INFO, "OpenSSL: OCSP responder error %d (%s)", 1064 status, OCSP_response_status_str(status)); 1065 ctx->last_err = "OCSP responder error"; 1066 return 0; 1067 } 1068 1069 basic = OCSP_response_get1_basic(rsp); 1070 if (!basic) { 1071 wpa_printf(MSG_INFO, "OpenSSL: Could not find BasicOCSPResponse"); 1072 ctx->last_err = "Could not find BasicOCSPResponse"; 1073 return 0; 1074 } 1075 1076 store = SSL_CTX_get_cert_store(s->ctx); 1077 if (ctx->peer_issuer) { 1078 wpa_printf(MSG_DEBUG, "OpenSSL: Add issuer"); 1079 debug_dump_cert("OpenSSL: Issuer certificate", 1080 ctx->peer_issuer); 1081 1082 if (X509_STORE_add_cert(store, ctx->peer_issuer) != 1) { 1083 tls_show_errors(__func__, 1084 "OpenSSL: Could not add issuer to certificate store\n"); 1085 } 1086 certs = sk_X509_new_null(); 1087 if (certs) { 1088 X509 *cert; 1089 cert = X509_dup(ctx->peer_issuer); 1090 if (cert && !sk_X509_push(certs, cert)) { 1091 tls_show_errors( 1092 __func__, 1093 "OpenSSL: Could not add issuer to OCSP responder trust store\n"); 1094 X509_free(cert); 1095 sk_X509_free(certs); 1096 certs = NULL; 1097 } 1098 if (ctx->peer_issuer_issuer) { 1099 X509 *cert; 1100 cert = X509_dup(ctx->peer_issuer_issuer); 1101 if (cert && !sk_X509_push(certs, cert)) { 1102 tls_show_errors( 1103 __func__, 1104 "OpenSSL: Could not add issuer to OCSP responder trust store\n"); 1105 X509_free(cert); 1106 } 1107 } 1108 } 1109 } 1110 1111 status = OCSP_basic_verify(basic, certs, store, OCSP_TRUSTOTHER); 1112 sk_X509_pop_free(certs, X509_free); 1113 if (status <= 0) { 1114 tls_show_errors(__func__, 1115 "OpenSSL: OCSP response failed verification"); 1116 OCSP_BASICRESP_free(basic); 1117 OCSP_RESPONSE_free(rsp); 1118 ctx->last_err = "OCSP response failed verification"; 1119 return 0; 1120 } 1121 1122 wpa_printf(MSG_DEBUG, "OpenSSL: OCSP response verification succeeded"); 1123 1124 if (!ctx->peer_cert) { 1125 wpa_printf(MSG_DEBUG, "OpenSSL: Peer certificate not available for OCSP status check"); 1126 OCSP_BASICRESP_free(basic); 1127 OCSP_RESPONSE_free(rsp); 1128 ctx->last_err = "Peer certificate not available for OCSP status check"; 1129 return 0; 1130 } 1131 1132 if (!ctx->peer_issuer) { 1133 wpa_printf(MSG_DEBUG, "OpenSSL: Peer issuer certificate not available for OCSP status check"); 1134 OCSP_BASICRESP_free(basic); 1135 OCSP_RESPONSE_free(rsp); 1136 ctx->last_err = "Peer issuer certificate not available for OCSP status check"; 1137 return 0; 1138 } 1139 1140 id = OCSP_cert_to_id(NULL, ctx->peer_cert, ctx->peer_issuer); 1141 if (!id) { 1142 wpa_printf(MSG_DEBUG, "OpenSSL: Could not create OCSP certificate identifier"); 1143 OCSP_BASICRESP_free(basic); 1144 OCSP_RESPONSE_free(rsp); 1145 ctx->last_err = "Could not create OCSP certificate identifier"; 1146 return 0; 1147 } 1148 1149 if (!OCSP_resp_find_status(basic, id, &status, &reason, &produced_at, 1150 &this_update, &next_update)) { 1151 wpa_printf(MSG_INFO, "OpenSSL: Could not find current server certificate from OCSP response%s", 1152 (ctx->ocsp == MANDATORY_OCSP) ? "" : 1153 " (OCSP not required)"); 1154 OCSP_BASICRESP_free(basic); 1155 OCSP_RESPONSE_free(rsp); 1156 if (ctx->ocsp == MANDATORY_OCSP) 1157 1158 ctx->last_err = "Could not find current server certificate from OCSP response"; 1159 return (ctx->ocsp == MANDATORY_OCSP) ? 0 : 1; 1160 } 1161 1162 if (!OCSP_check_validity(this_update, next_update, 5 * 60, -1)) { 1163 tls_show_errors(__func__, "OpenSSL: OCSP status times invalid"); 1164 OCSP_BASICRESP_free(basic); 1165 OCSP_RESPONSE_free(rsp); 1166 ctx->last_err = "OCSP status times invalid"; 1167 return 0; 1168 } 1169 1170 OCSP_BASICRESP_free(basic); 1171 OCSP_RESPONSE_free(rsp); 1172 1173 wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status for server certificate: %s", 1174 OCSP_cert_status_str(status)); 1175 1176 if (status == V_OCSP_CERTSTATUS_GOOD) 1177 return 1; 1178 if (status == V_OCSP_CERTSTATUS_REVOKED) 1179 ctx->last_err = "Server certificate has been revoked"; 1180 return 0; 1181 if (ctx->ocsp == MANDATORY_OCSP) { 1182 wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status unknown, but OCSP required"); 1183 ctx->last_err = "OCSP status unknown"; 1184 return 0; 1185 } 1186 wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status unknown, but OCSP was not required, so allow connection to continue"); 1187 return 1; 1188} 1189 1190 1191static SSL_METHOD patch_ssl_method; 1192static const SSL_METHOD *real_ssl_method; 1193 1194static int curl_patch_ssl_new(SSL *s) 1195{ 1196 SSL_CTX *ssl = s->ctx; 1197 int ret; 1198 1199 ssl->method = real_ssl_method; 1200 s->method = real_ssl_method; 1201 1202 ret = s->method->ssl_new(s); 1203 SSL_set_tlsext_status_type(s, TLSEXT_STATUSTYPE_ocsp); 1204 1205 return ret; 1206} 1207 1208#endif /* HAVE_OCSP */ 1209 1210 1211static CURLcode curl_cb_ssl(CURL *curl, void *sslctx, void *parm) 1212{ 1213 struct http_ctx *ctx = parm; 1214 SSL_CTX *ssl = sslctx; 1215 1216 wpa_printf(MSG_DEBUG, "curl_cb_ssl"); 1217 SSL_CTX_set_app_data(ssl, ctx); 1218 SSL_CTX_set_verify(ssl, SSL_VERIFY_PEER, curl_cb_ssl_verify); 1219 1220#ifdef HAVE_OCSP 1221 if (ctx->ocsp != NO_OCSP) { 1222 SSL_CTX_set_tlsext_status_cb(ssl, ocsp_resp_cb); 1223 SSL_CTX_set_tlsext_status_arg(ssl, ctx); 1224 1225 /* 1226 * Use a temporary SSL_METHOD to get a callback on SSL_new() 1227 * from libcurl since there is no proper callback registration 1228 * available for this. 1229 */ 1230 os_memset(&patch_ssl_method, 0, sizeof(patch_ssl_method)); 1231 patch_ssl_method.ssl_new = curl_patch_ssl_new; 1232 real_ssl_method = ssl->method; 1233 ssl->method = &patch_ssl_method; 1234 } 1235#endif /* HAVE_OCSP */ 1236 1237 return CURLE_OK; 1238} 1239 1240#endif /* EAP_TLS_OPENSSL */ 1241 1242 1243static CURL * setup_curl_post(struct http_ctx *ctx, const char *address, 1244 const char *ca_fname, const char *username, 1245 const char *password, const char *client_cert, 1246 const char *client_key) 1247{ 1248 CURL *curl; 1249 1250 wpa_printf(MSG_DEBUG, "Start HTTP client: address=%s ca_fname=%s " 1251 "username=%s", address, ca_fname, username); 1252 1253 curl = curl_easy_init(); 1254 if (curl == NULL) 1255 return NULL; 1256 1257 curl_easy_setopt(curl, CURLOPT_URL, address); 1258 curl_easy_setopt(curl, CURLOPT_POST, 1L); 1259 if (ca_fname) { 1260 curl_easy_setopt(curl, CURLOPT_CAINFO, ca_fname); 1261 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L); 1262#ifdef EAP_TLS_OPENSSL 1263 curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, curl_cb_ssl); 1264 curl_easy_setopt(curl, CURLOPT_SSL_CTX_DATA, ctx); 1265#endif /* EAP_TLS_OPENSSL */ 1266 } else { 1267 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); 1268 } 1269 if (client_cert && client_key) { 1270 curl_easy_setopt(curl, CURLOPT_SSLCERT, client_cert); 1271 curl_easy_setopt(curl, CURLOPT_SSLKEY, client_key); 1272 } 1273 /* TODO: use curl_easy_getinfo() with CURLINFO_CERTINFO to fetch 1274 * information about the server certificate */ 1275 curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L); 1276 curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, curl_cb_debug); 1277 curl_easy_setopt(curl, CURLOPT_DEBUGDATA, ctx); 1278 curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, curl_cb_header); 1279 curl_easy_setopt(curl, CURLOPT_HEADERDATA, ctx); 1280 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_cb_write); 1281 curl_easy_setopt(curl, CURLOPT_WRITEDATA, ctx); 1282 curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); 1283 if (username) { 1284 curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_ANYSAFE); 1285 curl_easy_setopt(curl, CURLOPT_USERNAME, username); 1286 curl_easy_setopt(curl, CURLOPT_PASSWORD, password); 1287 } 1288 1289 return curl; 1290} 1291 1292 1293static int post_init_client(struct http_ctx *ctx, const char *address, 1294 const char *ca_fname, const char *username, 1295 const char *password, const char *client_cert, 1296 const char *client_key) 1297{ 1298 char *pos; 1299 int count; 1300 1301 clone_str(&ctx->svc_address, address); 1302 clone_str(&ctx->svc_ca_fname, ca_fname); 1303 clone_str(&ctx->svc_username, username); 1304 clone_str(&ctx->svc_password, password); 1305 clone_str(&ctx->svc_client_cert, client_cert); 1306 clone_str(&ctx->svc_client_key, client_key); 1307 1308 /* 1309 * Workaround for Apache "Hostname 'FOO' provided via SNI and hostname 1310 * 'foo' provided via HTTP are different. 1311 */ 1312 for (count = 0, pos = ctx->svc_address; count < 3 && pos && *pos; 1313 pos++) { 1314 if (*pos == '/') 1315 count++; 1316 *pos = tolower(*pos); 1317 } 1318 1319 ctx->curl = setup_curl_post(ctx, ctx->svc_address, ca_fname, username, 1320 password, client_cert, client_key); 1321 if (ctx->curl == NULL) 1322 return -1; 1323 1324 return 0; 1325} 1326 1327 1328int soap_init_client(struct http_ctx *ctx, const char *address, 1329 const char *ca_fname, const char *username, 1330 const char *password, const char *client_cert, 1331 const char *client_key) 1332{ 1333 if (post_init_client(ctx, address, ca_fname, username, password, 1334 client_cert, client_key) < 0) 1335 return -1; 1336 1337 ctx->curl_hdr = curl_slist_append(ctx->curl_hdr, 1338 "Content-Type: application/soap+xml"); 1339 ctx->curl_hdr = curl_slist_append(ctx->curl_hdr, "SOAPAction: "); 1340 ctx->curl_hdr = curl_slist_append(ctx->curl_hdr, "Expect:"); 1341 curl_easy_setopt(ctx->curl, CURLOPT_HTTPHEADER, ctx->curl_hdr); 1342 1343 return 0; 1344} 1345 1346 1347int soap_reinit_client(struct http_ctx *ctx) 1348{ 1349 char *address = NULL; 1350 char *ca_fname = NULL; 1351 char *username = NULL; 1352 char *password = NULL; 1353 char *client_cert = NULL; 1354 char *client_key = NULL; 1355 int ret; 1356 1357 clear_curl(ctx); 1358 1359 clone_str(&address, ctx->svc_address); 1360 clone_str(&ca_fname, ctx->svc_ca_fname); 1361 clone_str(&username, ctx->svc_username); 1362 clone_str(&password, ctx->svc_password); 1363 clone_str(&client_cert, ctx->svc_client_cert); 1364 clone_str(&client_key, ctx->svc_client_key); 1365 1366 ret = soap_init_client(ctx, address, ca_fname, username, password, 1367 client_cert, client_key); 1368 os_free(address); 1369 os_free(ca_fname); 1370 os_free(username); 1371 os_free(password); 1372 os_free(client_cert); 1373 os_free(client_key); 1374 return ret; 1375} 1376 1377 1378static void free_curl_buf(struct http_ctx *ctx) 1379{ 1380 os_free(ctx->curl_buf); 1381 ctx->curl_buf = NULL; 1382 ctx->curl_buf_len = 0; 1383} 1384 1385 1386xml_node_t * soap_send_receive(struct http_ctx *ctx, xml_node_t *node) 1387{ 1388 char *str; 1389 xml_node_t *envelope, *ret, *resp, *n; 1390 CURLcode res; 1391 long http = 0; 1392 1393 ctx->last_err = NULL; 1394 1395 wpa_printf(MSG_DEBUG, "SOAP: Sending message"); 1396 envelope = soap_build_envelope(ctx->xml, node); 1397 str = xml_node_to_str(ctx->xml, envelope); 1398 xml_node_free(ctx->xml, envelope); 1399 wpa_printf(MSG_MSGDUMP, "SOAP[%s]", str); 1400 1401 curl_easy_setopt(ctx->curl, CURLOPT_POSTFIELDS, str); 1402 free_curl_buf(ctx); 1403 1404 res = curl_easy_perform(ctx->curl); 1405 if (res != CURLE_OK) { 1406 if (!ctx->last_err) 1407 ctx->last_err = curl_easy_strerror(res); 1408 wpa_printf(MSG_ERROR, "curl_easy_perform() failed: %s", 1409 ctx->last_err); 1410 os_free(str); 1411 free_curl_buf(ctx); 1412 return NULL; 1413 } 1414 os_free(str); 1415 1416 curl_easy_getinfo(ctx->curl, CURLINFO_RESPONSE_CODE, &http); 1417 wpa_printf(MSG_DEBUG, "SOAP: Server response code %ld", http); 1418 if (http != 200) { 1419 ctx->last_err = "HTTP download failed"; 1420 wpa_printf(MSG_INFO, "HTTP download failed - code %ld", http); 1421 free_curl_buf(ctx); 1422 return NULL; 1423 } 1424 1425 if (ctx->curl_buf == NULL) 1426 return NULL; 1427 1428 wpa_printf(MSG_MSGDUMP, "Server response:\n%s", ctx->curl_buf); 1429 resp = xml_node_from_buf(ctx->xml, ctx->curl_buf); 1430 free_curl_buf(ctx); 1431 if (resp == NULL) { 1432 wpa_printf(MSG_INFO, "Could not parse SOAP response"); 1433 ctx->last_err = "Could not parse SOAP response"; 1434 return NULL; 1435 } 1436 1437 ret = soap_get_body(ctx->xml, resp); 1438 if (ret == NULL) { 1439 wpa_printf(MSG_INFO, "Could not get SOAP body"); 1440 ctx->last_err = "Could not get SOAP body"; 1441 return NULL; 1442 } 1443 1444 wpa_printf(MSG_DEBUG, "SOAP body localname: '%s'", 1445 xml_node_get_localname(ctx->xml, ret)); 1446 n = xml_node_copy(ctx->xml, ret); 1447 xml_node_free(ctx->xml, resp); 1448 1449 return n; 1450} 1451 1452 1453struct http_ctx * http_init_ctx(void *upper_ctx, struct xml_node_ctx *xml_ctx) 1454{ 1455 struct http_ctx *ctx; 1456 1457 ctx = os_zalloc(sizeof(*ctx)); 1458 if (ctx == NULL) 1459 return NULL; 1460 ctx->ctx = upper_ctx; 1461 ctx->xml = xml_ctx; 1462 ctx->ocsp = OPTIONAL_OCSP; 1463 1464 curl_global_init(CURL_GLOBAL_ALL); 1465 1466 return ctx; 1467} 1468 1469 1470void http_ocsp_set(struct http_ctx *ctx, int val) 1471{ 1472 if (val == 0) 1473 ctx->ocsp = NO_OCSP; 1474 else if (val == 1) 1475 ctx->ocsp = OPTIONAL_OCSP; 1476 if (val == 2) 1477 ctx->ocsp = MANDATORY_OCSP; 1478} 1479 1480 1481void http_deinit_ctx(struct http_ctx *ctx) 1482{ 1483 clear_curl(ctx); 1484 os_free(ctx->curl_buf); 1485 curl_global_cleanup(); 1486 1487 os_free(ctx->svc_address); 1488 os_free(ctx->svc_ca_fname); 1489 os_free(ctx->svc_username); 1490 os_free(ctx->svc_password); 1491 os_free(ctx->svc_client_cert); 1492 os_free(ctx->svc_client_key); 1493 1494 os_free(ctx); 1495} 1496 1497 1498int http_download_file(struct http_ctx *ctx, const char *url, 1499 const char *fname, const char *ca_fname) 1500{ 1501 CURL *curl; 1502 FILE *f; 1503 CURLcode res; 1504 long http = 0; 1505 1506 ctx->last_err = NULL; 1507 1508 wpa_printf(MSG_DEBUG, "curl: Download file from %s to %s (ca=%s)", 1509 url, fname, ca_fname); 1510 curl = curl_easy_init(); 1511 if (curl == NULL) 1512 return -1; 1513 1514 f = fopen(fname, "wb"); 1515 if (f == NULL) { 1516 curl_easy_cleanup(curl); 1517 return -1; 1518 } 1519 1520 curl_easy_setopt(curl, CURLOPT_URL, url); 1521 if (ca_fname) { 1522 curl_easy_setopt(curl, CURLOPT_CAINFO, ca_fname); 1523 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L); 1524 curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L); 1525 } else { 1526 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); 1527 } 1528 curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, curl_cb_debug); 1529 curl_easy_setopt(curl, CURLOPT_DEBUGDATA, ctx); 1530 curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, curl_cb_header); 1531 curl_easy_setopt(curl, CURLOPT_HEADERDATA, ctx); 1532 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fwrite); 1533 curl_easy_setopt(curl, CURLOPT_WRITEDATA, f); 1534 curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); 1535 1536 res = curl_easy_perform(curl); 1537 if (res != CURLE_OK) { 1538 if (!ctx->last_err) 1539 ctx->last_err = curl_easy_strerror(res); 1540 wpa_printf(MSG_ERROR, "curl_easy_perform() failed: %s", 1541 ctx->last_err); 1542 curl_easy_cleanup(curl); 1543 fclose(f); 1544 return -1; 1545 } 1546 1547 curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http); 1548 wpa_printf(MSG_DEBUG, "curl: Server response code %ld", http); 1549 if (http != 200) { 1550 ctx->last_err = "HTTP download failed"; 1551 wpa_printf(MSG_INFO, "HTTP download failed - code %ld", http); 1552 curl_easy_cleanup(curl); 1553 fclose(f); 1554 return -1; 1555 } 1556 1557 curl_easy_cleanup(curl); 1558 fclose(f); 1559 1560 return 0; 1561} 1562 1563 1564char * http_post(struct http_ctx *ctx, const char *url, const char *data, 1565 const char *content_type, const char *ext_hdr, 1566 const char *ca_fname, 1567 const char *username, const char *password, 1568 const char *client_cert, const char *client_key, 1569 size_t *resp_len) 1570{ 1571 long http = 0; 1572 CURLcode res; 1573 char *ret; 1574 CURL *curl; 1575 struct curl_slist *curl_hdr = NULL; 1576 1577 ctx->last_err = NULL; 1578 wpa_printf(MSG_DEBUG, "curl: HTTP POST to %s", url); 1579 curl = setup_curl_post(ctx, url, ca_fname, username, password, 1580 client_cert, client_key); 1581 if (curl == NULL) 1582 return NULL; 1583 1584 if (content_type) { 1585 char ct[200]; 1586 snprintf(ct, sizeof(ct), "Content-Type: %s", content_type); 1587 curl_hdr = curl_slist_append(curl_hdr, ct); 1588 } 1589 if (ext_hdr) 1590 curl_hdr = curl_slist_append(curl_hdr, ext_hdr); 1591 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_hdr); 1592 1593 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data); 1594 free_curl_buf(ctx); 1595 1596 res = curl_easy_perform(curl); 1597 if (res != CURLE_OK) { 1598 if (!ctx->last_err) 1599 ctx->last_err = curl_easy_strerror(res); 1600 wpa_printf(MSG_ERROR, "curl_easy_perform() failed: %s", 1601 ctx->last_err); 1602 free_curl_buf(ctx); 1603 return NULL; 1604 } 1605 1606 curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http); 1607 wpa_printf(MSG_DEBUG, "curl: Server response code %ld", http); 1608 if (http != 200) { 1609 ctx->last_err = "HTTP POST failed"; 1610 wpa_printf(MSG_INFO, "HTTP POST failed - code %ld", http); 1611 free_curl_buf(ctx); 1612 return NULL; 1613 } 1614 1615 if (ctx->curl_buf == NULL) 1616 return NULL; 1617 1618 ret = ctx->curl_buf; 1619 if (resp_len) 1620 *resp_len = ctx->curl_buf_len; 1621 ctx->curl_buf = NULL; 1622 ctx->curl_buf_len = 0; 1623 1624 wpa_printf(MSG_MSGDUMP, "Server response:\n%s", ret); 1625 1626 return ret; 1627} 1628 1629 1630void http_set_cert_cb(struct http_ctx *ctx, 1631 int (*cb)(void *ctx, struct http_cert *cert), 1632 void *cb_ctx) 1633{ 1634 ctx->cert_cb = cb; 1635 ctx->cert_cb_ctx = cb_ctx; 1636} 1637 1638 1639const char * http_get_err(struct http_ctx *ctx) 1640{ 1641 return ctx->last_err; 1642} 1643