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