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