s4:lib/tls: split out tstream_tls_verify_peer() helper
authorStefan Metzmacher <metze@samba.org>
Mon, 12 Feb 2024 11:02:13 +0000 (12:02 +0100)
committerAndrew Bartlett <abartlet@samba.org>
Tue, 23 Apr 2024 23:50:33 +0000 (23:50 +0000)
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15621

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
source4/lib/tls/tls_tstream.c

index 8b6d89b802abcd96877ea648cb829a3b8ea5e595..55303c89ca0dd8a0d0121e39014e29bf65c41632 100644 (file)
@@ -1101,6 +1101,76 @@ static NTSTATUS tstream_tls_prepare_gnutls(struct tstream_tls_params *_tlsp,
        return NT_STATUS_OK;
 }
 
+static NTSTATUS tstream_tls_verify_peer(struct tstream_tls *tlss)
+{
+       unsigned int status = UINT32_MAX;
+       bool ip = true;
+       const char *hostname = NULL;
+       int ret;
+
+       if (tlss->verify_peer == TLS_VERIFY_PEER_NO_CHECK) {
+               return NT_STATUS_OK;
+       }
+
+       if (tlss->peer_name != NULL) {
+               ip = is_ipaddress(tlss->peer_name);
+       }
+
+       if (!ip) {
+               hostname = tlss->peer_name;
+       }
+
+       if (tlss->verify_peer == TLS_VERIFY_PEER_CA_ONLY) {
+               hostname = NULL;
+       }
+
+       if (tlss->verify_peer >= TLS_VERIFY_PEER_CA_AND_NAME) {
+               if (hostname == NULL) {
+                       DEBUG(1,("TLS %s - no hostname available for "
+                                "verify_peer[%s] and peer_name[%s]\n",
+                                __location__,
+                                tls_verify_peer_string(tlss->verify_peer),
+                                tlss->peer_name));
+                       return NT_STATUS_IMAGE_CERT_REVOKED;
+               }
+       }
+
+       ret = gnutls_certificate_verify_peers3(tlss->tls_session,
+                                              hostname,
+                                              &status);
+       if (ret != GNUTLS_E_SUCCESS) {
+               return gnutls_error_to_ntstatus(ret,
+                       NT_STATUS_CRYPTO_SYSTEM_INVALID);
+       }
+
+       if (status != 0) {
+               DEBUG(1,("TLS %s - check failed for "
+                        "verify_peer[%s] and peer_name[%s] "
+                        "status 0x%x (%s%s%s%s%s%s%s%s)\n",
+                        __location__,
+                        tls_verify_peer_string(tlss->verify_peer),
+                        tlss->peer_name,
+                        status,
+                        status & GNUTLS_CERT_INVALID ? "invalid " : "",
+                        status & GNUTLS_CERT_REVOKED ? "revoked " : "",
+                        status & GNUTLS_CERT_SIGNER_NOT_FOUND ?
+                               "signer_not_found " : "",
+                        status & GNUTLS_CERT_SIGNER_NOT_CA ?
+                               "signer_not_ca " : "",
+                        status & GNUTLS_CERT_INSECURE_ALGORITHM ?
+                               "insecure_algorithm " : "",
+                        status & GNUTLS_CERT_NOT_ACTIVATED ?
+                               "not_activated " : "",
+                        status & GNUTLS_CERT_EXPIRED ?
+                               "expired " : "",
+                        status & GNUTLS_CERT_UNEXPECTED_OWNER ?
+                               "unexpected_owner " : ""));
+               return NT_STATUS_IMAGE_CERT_REVOKED;
+       }
+
+       return NT_STATUS_OK;
+}
+
 struct tstream_tls_connect_state {
        struct tstream_context *tls_stream;
 };
@@ -1416,6 +1486,7 @@ static void tstream_tls_retry_handshake(struct tstream_context *stream)
                tstream_context_data(stream,
                struct tstream_tls);
        struct tevent_req *req = tlss->handshake.req;
+       NTSTATUS status;
        int ret;
 
        if (tlss->error != 0) {
@@ -1444,72 +1515,16 @@ static void tstream_tls_retry_handshake(struct tstream_context *stream)
                return;
        }
 
-       if (tlss->verify_peer >= TLS_VERIFY_PEER_CA_ONLY) {
-               unsigned int status = UINT32_MAX;
-               bool ip = true;
-               const char *hostname = NULL;
-
-               if (tlss->peer_name != NULL) {
-                       ip = is_ipaddress(tlss->peer_name);
-               }
-
-               if (!ip) {
-                       hostname = tlss->peer_name;
-               }
-
-               if (tlss->verify_peer == TLS_VERIFY_PEER_CA_ONLY) {
-                       hostname = NULL;
-               }
-
-               if (tlss->verify_peer >= TLS_VERIFY_PEER_CA_AND_NAME) {
-                       if (hostname == NULL) {
-                               DEBUG(1,("TLS %s - no hostname available for "
-                                        "verify_peer[%s] and peer_name[%s]\n",
-                                        __location__,
-                                        tls_verify_peer_string(tlss->verify_peer),
-                                        tlss->peer_name));
-                               tlss->error = EINVAL;
-                               tevent_req_error(req, tlss->error);
-                               return;
-                       }
-               }
-
-               ret = gnutls_certificate_verify_peers3(tlss->tls_session,
-                                                      hostname,
-                                                      &status);
-               if (ret != GNUTLS_E_SUCCESS) {
-                       DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
-                       tlss->error = EIO;
-                       tevent_req_error(req, tlss->error);
-                       return;
-               }
-
-               if (status != 0) {
-                       DEBUG(1,("TLS %s - check failed for "
-                                "verify_peer[%s] and peer_name[%s] "
-                                "status 0x%x (%s%s%s%s%s%s%s%s)\n",
-                                __location__,
-                                tls_verify_peer_string(tlss->verify_peer),
-                                tlss->peer_name,
-                                status,
-                                status & GNUTLS_CERT_INVALID ? "invalid " : "",
-                                status & GNUTLS_CERT_REVOKED ? "revoked " : "",
-                                status & GNUTLS_CERT_SIGNER_NOT_FOUND ?
-                                       "signer_not_found " : "",
-                                status & GNUTLS_CERT_SIGNER_NOT_CA ?
-                                       "signer_not_ca " : "",
-                                status & GNUTLS_CERT_INSECURE_ALGORITHM ?
-                                       "insecure_algorithm " : "",
-                                status & GNUTLS_CERT_NOT_ACTIVATED ?
-                                       "not_activated " : "",
-                                status & GNUTLS_CERT_EXPIRED ?
-                                       "expired " : "",
-                                status & GNUTLS_CERT_UNEXPECTED_OWNER ?
-                                       "unexpected_owner " : ""));
-                       tlss->error = EINVAL;
-                       tevent_req_error(req, tlss->error);
-                       return;
-               }
+       status = tstream_tls_verify_peer(tlss);
+       if (NT_STATUS_EQUAL(status, NT_STATUS_IMAGE_CERT_REVOKED)) {
+               tlss->error = EINVAL;
+               tevent_req_error(req, tlss->error);
+               return;
+       }
+       if (!NT_STATUS_IS_OK(status)) {
+               tlss->error = EIO;
+               tevent_req_error(req, tlss->error);
+               return;
        }
 
        if (tlss->push.subreq != NULL || tlss->pull.subreq != NULL) {