| 711 | } |
| 712 | |
| 713 | void TSSLSocket::authorize() { |
| 714 | long rc = SSL_get_verify_result(ssl_); |
| 715 | if (rc != X509_V_OK) { // verify authentication result |
| 716 | throw TSSLException(string("SSL_get_verify_result(), ") + X509_verify_cert_error_string(rc)); |
| 717 | } |
| 718 | |
| 719 | X509* cert = SSL_get_peer_certificate(ssl_); |
| 720 | if (cert == nullptr) { |
| 721 | // certificate is not present |
| 722 | if (SSL_get_verify_mode(ssl_) & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) { |
| 723 | throw TSSLException("authorize: required certificate not present"); |
| 724 | } |
| 725 | // certificate was optional: didn't intend to authorize remote |
| 726 | if (server() && access_ != nullptr) { |
| 727 | throw TSSLException("authorize: certificate required for authorization"); |
| 728 | } |
| 729 | return; |
| 730 | } |
| 731 | // certificate is present |
| 732 | if (access_ == nullptr) { |
| 733 | X509_free(cert); |
| 734 | return; |
| 735 | } |
| 736 | // both certificate and access manager are present |
| 737 | |
| 738 | string host; |
| 739 | sockaddr_storage sa; |
| 740 | socklen_t saLength = sizeof(sa); |
| 741 | |
| 742 | if (getpeername(socket_, (sockaddr*)&sa, &saLength) != 0) { |
| 743 | sa.ss_family = AF_UNSPEC; |
| 744 | } |
| 745 | |
| 746 | AccessManager::Decision decision = access_->verify(sa); |
| 747 | |
| 748 | if (decision != AccessManager::SKIP) { |
| 749 | X509_free(cert); |
| 750 | if (decision != AccessManager::ALLOW) { |
| 751 | throw TSSLException("authorize: access denied based on remote IP"); |
| 752 | } |
| 753 | return; |
| 754 | } |
| 755 | |
| 756 | // extract subjectAlternativeName |
| 757 | auto* alternatives |
| 758 | = (STACK_OF(GENERAL_NAME)*)X509_get_ext_d2i(cert, NID_subject_alt_name, nullptr, nullptr); |
| 759 | if (alternatives != nullptr) { |
| 760 | const int count = sk_GENERAL_NAME_num(alternatives); |
| 761 | for (int i = 0; decision == AccessManager::SKIP && i < count; i++) { |
| 762 | const GENERAL_NAME* name = sk_GENERAL_NAME_value(alternatives, i); |
| 763 | if (name == nullptr) { |
| 764 | continue; |
| 765 | } |
| 766 | char* data = (char*)ASN1_STRING_data(name->d.ia5); |
| 767 | int length = ASN1_STRING_length(name->d.ia5); |
| 768 | switch (name->type) { |
| 769 | case GEN_DNS: |
| 770 | if (host.empty()) { |
nothing calls this directly
no test coverage detected