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