Commit 38dd8ec5e3 for openssl.org

commit 38dd8ec5e3be47325b09f08abdef5dbebe89100f
Author: Dr. David von Oheimb <dev@ddvo.net>
Date:   Thu Jun 18 19:29:20 2026 +0200

    Fix get_cert_by_subject_ex() to gracefully handle broken symlinks (but not on Windows)

    Also gloss over errors reading cert/CRL contents from existing symlinked files.

    Fixes #23882

    Reviewed-by: Andrew Dinh <andrewd@openssl.org>
    Reviewed-by: Tomas Mraz <tomas@openssl.foundation>
    MergeDate: Wed Aug 19 19:29:03 2026
    (Merged from https://github.com/openssl/openssl/pull/31594)

diff --git a/crypto/x509/by_dir.c b/crypto/x509/by_dir.c
index d9a3e986e9..e93ab4d47f 100644
--- a/crypto/x509/by_dir.c
+++ b/crypto/x509/by_dir.c
@@ -228,7 +228,7 @@ static int get_cert_by_subject_ex(X509_LOOKUP *xl, X509_LOOKUP_TYPE type,
         X509 st_x509;
         X509_CRL crl;
     } data;
-    int ok = 0;
+    int res, ok = 0;
     int i, j, k;
     unsigned long h;
     BUF_MEM *b = NULL;
@@ -320,25 +320,35 @@ static int get_cert_by_subject_ex(X509_LOOKUP *xl, X509_LOOKUP_TYPE type,
             }
 #ifndef OPENSSL_NO_POSIX_IO
 #ifdef _WIN32
+#define lstat _stat
 #define stat _stat
 #endif
             {
                 struct stat st;
-                if (stat(b->data, &st) < 0)
-                    break;
-            }
+                if (lstat(b->data, &st) < 0)
+                    break; /* file does not exist, not even a symlink */
+#ifndef _WIN32
+                if (stat(b->data, &st) < 0) {
+                    k++;
+                    continue; /* symlink is broken: following it went wrong */
+                }
 #endif
-            /* found one. */
-            if (type == X509_LU_X509) {
-                if ((X509_load_cert_file_ex(xl, b->data, ent->dir_type, libctx,
-                        propq))
-                    == 0)
-                    break;
-            } else if (type == X509_LU_CRL) {
-                if ((X509_load_crl_file(xl, b->data, ent->dir_type)) == 0)
-                    break;
             }
+#endif
+            res = 0;
+            ERR_set_mark();
+            if (type == X509_LU_X509)
+                res = X509_load_cert_file_ex(xl, b->data, ent->dir_type, libctx, propq);
+            else if (type == X509_LU_CRL)
+                res = X509_load_crl_file(xl, b->data, ent->dir_type);
             /* else case will caught higher up */
+            ERR_pop_to_mark();
+            /* unless OPENSSL_NO_POSIX_IO, gracefully skip found file if cert/CRL fails to load. */
+#ifndef OPENSSL_NO_POSIX_IO
+            res = 1;
+#endif
+            if (res == 0)
+                break;
             k++;
         }