diff --color -ruN pam_u2f-1.2.0-ori/pam-u2f.c pam_u2f-1.2.0-patched/pam-u2f.c
--- pam_u2f-1.2.0-ori/pam-u2f.c	2021-09-17 10:56:56.000000000 +0200
+++ pam_u2f-1.2.0-patched/pam-u2f.c	2025-01-16 14:05:42.606675279 +0100
@@ -176,7 +176,7 @@
   char *default_authfile;
   char *default_authfile_dir;
   int pgu_ret, gpn_ret;
-  int retval = PAM_IGNORE;
+  int retval = PAM_ABORT;
   device_t *devices = NULL;
   unsigned n_devices = 0;
   int openasuser = 0;
@@ -195,8 +195,9 @@
 
       if (gethostname(buffer + strlen(DEFAULT_ORIGIN_PREFIX),
                       BUFSIZE - strlen(DEFAULT_ORIGIN_PREFIX)) == -1) {
-        DBG("Unable to get host name");
-        goto done;
+          DBG("Unable to get host name");
+          retval = PAM_SYSTEM_ERR;  
+          goto done;
       }
     } else {
       strcpy(buffer, SSH_ORIGIN);
@@ -204,8 +205,9 @@
     DBG("Origin not specified, using \"%s\"", buffer);
     cfg->origin = strdup(buffer);
     if (!cfg->origin) {
-      DBG("Unable to allocate memory");
-      goto done;
+        DBG("Unable to allocate memory");
+        retval = PAM_BUF_ERR;
+        goto done;
     } else {
       should_free_origin = 1;
     }
@@ -216,8 +218,9 @@
         cfg->origin);
     cfg->appid = strdup(cfg->origin);
     if (!cfg->appid) {
-      DBG("Unable to allocate memory")
-      goto done;
+        DBG("Unable to allocate memory");
+        retval = PAM_BUF_ERR;
+        goto done;
     } else {
       should_free_appid = 1;
     }
@@ -235,7 +238,7 @@
   devices = calloc(cfg->max_devs, sizeof(device_t));
   if (!devices) {
     DBG("Unable to allocate memory");
-    retval = PAM_IGNORE;
+    retval = PAM_BUF_ERR;
     goto done;
   }
 
@@ -253,7 +256,7 @@
       pw->pw_dir[0] != '/') {
     DBG("Unable to retrieve credentials for user %s, (%s)", user,
         strerror(errno));
-    retval = PAM_USER_UNKNOWN;
+    retval = PAM_SYSTEM_ERR;
     goto done;
   }
 
@@ -280,7 +283,7 @@
 
       if (!buf) {
         DBG("Unable to allocate memory");
-        retval = PAM_IGNORE;
+        retval = PAM_BUF_ERR;
         goto done;
       }
 
@@ -296,7 +299,7 @@
 
       if (!buf) {
         DBG("Unable to allocate memory");
-        retval = PAM_IGNORE;
+        retval = PAM_BUF_ERR;
         goto done;
       }
 
@@ -326,7 +329,7 @@
 
       if (!buf) {
         DBG("Unable to allocate memory");
-        retval = PAM_IGNORE;
+        retval = PAM_BUF_ERR;
         goto done;
       }
 
@@ -347,7 +350,7 @@
     DBG("Dropping privileges");
     if (pam_modutil_drop_priv(pamh, &privs, pw)) {
       DBG("Unable to switch user to uid %i", pw->pw_uid);
-      retval = PAM_IGNORE;
+      retval = PAM_SYSTEM_ERR;
       goto done;
     }
     DBG("Switched to uid %i", pw->pw_uid);
@@ -357,32 +360,14 @@
   if (openasuser) {
     if (pam_modutil_regain_priv(pamh, &privs)) {
       DBG("could not restore privileges");
-      retval = PAM_IGNORE;
+      retval = PAM_SYSTEM_ERR;
       goto done;
     }
     DBG("Restored privileges");
   }
 
-  if (retval != 1) {
-    // for nouserok; make sure errors in get_devices_from_authfile don't
-    // result in valid devices
-    n_devices = 0;
-  }
-
-  if (n_devices == 0) {
-    if (cfg->nouserok) {
-      DBG("Found no devices but nouserok specified. Skipping authentication");
-      retval = PAM_SUCCESS;
+  if (retval != PAM_SUCCESS) {
       goto done;
-    } else if (retval != 1) {
-      DBG("Unable to get devices from file %s", cfg->auth_file);
-      retval = PAM_AUTHINFO_UNAVAIL;
-      goto done;
-    } else {
-      DBG("Found no devices. Aborting.");
-      retval = PAM_AUTHINFO_UNAVAIL;
-      goto done;
-    }
   }
 
   // Determine the full path for authpending_file in order to emit touch request
@@ -446,14 +431,6 @@
     }
   }
 
-  if (retval != 1) {
-    DBG("do_authentication returned %d", retval);
-    retval = PAM_AUTH_ERR;
-    goto done;
-  }
-
-  retval = PAM_SUCCESS;
-
 done:
   free_devices(devices, n_devices);
 
diff --color -ruN pam_u2f-1.2.0-ori/tests/get_devices.c pam_u2f-1.2.0-patched/tests/get_devices.c
--- pam_u2f-1.2.0-ori/tests/get_devices.c	2021-09-10 11:23:30.000000000 +0200
+++ pam_u2f-1.2.0-patched/tests/get_devices.c	2025-01-16 14:26:14.721447459 +0100
@@ -44,7 +44,7 @@
 
   rc = get_devices_from_authfile(&cfg, username /* not used for SSH format */,
                                  dev, &n_devs);
-  assert(rc == 1);
+  assert(rc == PAM_SUCCESS);
   assert(n_devs == 1);
   assert(strcmp(dev[0].coseType, "es256") == 0);
   assert(strcmp(dev[0].attributes, "+presence") == 0);
@@ -65,7 +65,7 @@
   cfg.auth_file = "credentials/new_.cred";
   cfg.sshformat = 0;
   rc = get_devices_from_authfile(&cfg, username, dev, &n_devs);
-  assert(rc == 1);
+  assert(rc == PAM_SUCCESS);
   assert(n_devs == 1);
 
   assert(strcmp(dev[0].coseType, "es256") == 0);
@@ -89,7 +89,7 @@
   cfg.auth_file = "credentials/new_-V.cred";
   cfg.sshformat = 0;
   rc = get_devices_from_authfile(&cfg, username, dev, &n_devs);
-  assert(rc == 1);
+  assert(rc == PAM_SUCCESS);
   assert(n_devs == 1);
 
   assert(strcmp(dev[0].coseType, "es256") == 0);
@@ -113,7 +113,7 @@
   cfg.auth_file = "credentials/new_-N.cred";
   cfg.sshformat = 0;
   rc = get_devices_from_authfile(&cfg, username, dev, &n_devs);
-  assert(rc == 1);
+  assert(rc == PAM_SUCCESS);
   assert(n_devs == 1);
 
   assert(strcmp(dev[0].coseType, "es256") == 0);
@@ -138,7 +138,7 @@
   cfg.auth_file = "credentials/new_-V-N.cred";
   cfg.sshformat = 0;
   rc = get_devices_from_authfile(&cfg, username, dev, &n_devs);
-  assert(rc == 1);
+  assert(rc == PAM_SUCCESS);
   assert(n_devs == 1);
 
   assert(strcmp(dev[0].coseType, "es256") == 0);
@@ -162,7 +162,7 @@
   cfg.auth_file = "credentials/new_-P.cred";
   cfg.sshformat = 0;
   rc = get_devices_from_authfile(&cfg, username, dev, &n_devs);
-  assert(rc == 1);
+  assert(rc == PAM_SUCCESS);
   assert(n_devs == 1);
 
   assert(strcmp(dev[0].coseType, "es256") == 0);
@@ -186,7 +186,7 @@
   cfg.auth_file = "credentials/new_-P-V.cred";
   cfg.sshformat = 0;
   rc = get_devices_from_authfile(&cfg, username, dev, &n_devs);
-  assert(rc == 1);
+  assert(rc == PAM_SUCCESS);
   assert(n_devs == 1);
 
   assert(strcmp(dev[0].coseType, "es256") == 0);
@@ -209,7 +209,7 @@
   cfg.auth_file = "credentials/new_-P-N.cred";
   cfg.sshformat = 0;
   rc = get_devices_from_authfile(&cfg, username, dev, &n_devs);
-  assert(rc == 1);
+  assert(rc == PAM_SUCCESS);
   assert(n_devs == 1);
 
   assert(strcmp(dev[0].coseType, "es256") == 0);
@@ -233,7 +233,7 @@
   cfg.auth_file = "credentials/new_-P-V-N.cred";
   cfg.sshformat = 0;
   rc = get_devices_from_authfile(&cfg, username, dev, &n_devs);
-  assert(rc == 1);
+  assert(rc == PAM_SUCCESS);
   assert(n_devs == 1);
 
   assert(strcmp(dev[0].coseType, "es256") == 0);
@@ -257,7 +257,7 @@
   cfg.auth_file = "credentials/new_-r.cred";
   cfg.sshformat = 0;
   rc = get_devices_from_authfile(&cfg, username, dev, &n_devs);
-  assert(rc == 1);
+  assert(rc == PAM_SUCCESS);
   assert(n_devs == 1);
 
   assert(strcmp(dev[0].coseType, "es256") == 0);
@@ -279,7 +279,7 @@
   cfg.auth_file = "credentials/new_-r-V.cred";
   cfg.sshformat = 0;
   rc = get_devices_from_authfile(&cfg, username, dev, &n_devs);
-  assert(rc == 1);
+  assert(rc == PAM_SUCCESS);
   assert(n_devs == 1);
 
   assert(strcmp(dev[0].coseType, "es256") == 0);
@@ -301,7 +301,7 @@
   cfg.auth_file = "credentials/new_-r-N.cred";
   cfg.sshformat = 0;
   rc = get_devices_from_authfile(&cfg, username, dev, &n_devs);
-  assert(rc == 1);
+  assert(rc == PAM_SUCCESS);
   assert(n_devs == 1);
 
   assert(strcmp(dev[0].coseType, "es256") == 0);
@@ -322,7 +322,7 @@
   cfg.auth_file = "credentials/new_-r-V-N.cred";
   cfg.sshformat = 0;
   rc = get_devices_from_authfile(&cfg, username, dev, &n_devs);
-  assert(rc == 1);
+  assert(rc == PAM_SUCCESS);
   assert(n_devs == 1);
 
   assert(strcmp(dev[0].coseType, "es256") == 0);
@@ -343,7 +343,7 @@
   cfg.auth_file = "credentials/new_-r-P.cred";
   cfg.sshformat = 0;
   rc = get_devices_from_authfile(&cfg, username, dev, &n_devs);
-  assert(rc == 1);
+  assert(rc == PAM_SUCCESS);
   assert(n_devs == 1);
 
   assert(strcmp(dev[0].coseType, "es256") == 0);
@@ -364,7 +364,7 @@
   cfg.auth_file = "credentials/new_-r-P-V.cred";
   cfg.sshformat = 0;
   rc = get_devices_from_authfile(&cfg, username, dev, &n_devs);
-  assert(rc == 1);
+  assert(rc == PAM_SUCCESS);
   assert(n_devs == 1);
 
   assert(strcmp(dev[0].coseType, "es256") == 0);
@@ -385,7 +385,7 @@
   cfg.auth_file = "credentials/new_-r-P-N.cred";
   cfg.sshformat = 0;
   rc = get_devices_from_authfile(&cfg, username, dev, &n_devs);
-  assert(rc == 1);
+  assert(rc == PAM_SUCCESS);
   assert(n_devs == 1);
 
   assert(strcmp(dev[0].coseType, "es256") == 0);
@@ -406,7 +406,7 @@
   cfg.auth_file = "credentials/new_-r-P-V-N.cred";
   cfg.sshformat = 0;
   rc = get_devices_from_authfile(&cfg, username, dev, &n_devs);
-  assert(rc == 1);
+  assert(rc == PAM_SUCCESS);
   assert(n_devs == 1);
 
   assert(strcmp(dev[0].coseType, "es256") == 0);
@@ -428,7 +428,7 @@
   cfg.auth_file = "credentials/new_double_.cred";
   cfg.sshformat = 0;
   rc = get_devices_from_authfile(&cfg, username, dev, &n_devs);
-  assert(rc == 1);
+  assert(rc == PAM_SUCCESS);
   assert(n_devs == 2);
 
   assert(strcmp(dev[0].coseType, "es256") == 0);
@@ -466,7 +466,7 @@
   cfg.auth_file = "credentials/new_double_-V.cred";
   cfg.sshformat = 0;
   rc = get_devices_from_authfile(&cfg, username, dev, &n_devs);
-  assert(rc == 1);
+  assert(rc == PAM_SUCCESS);
   assert(n_devs == 2);
 
   assert(strcmp(dev[0].coseType, "es256") == 0);
@@ -505,7 +505,7 @@
   cfg.auth_file = "credentials/new_double_-N.cred";
   cfg.sshformat = 0;
   rc = get_devices_from_authfile(&cfg, username, dev, &n_devs);
-  assert(rc == 1);
+  assert(rc == PAM_SUCCESS);
   assert(n_devs == 2);
 
   assert(strcmp(dev[0].coseType, "es256") == 0);
@@ -544,7 +544,7 @@
   cfg.auth_file = "credentials/new_double_-V-N.cred";
   cfg.sshformat = 0;
   rc = get_devices_from_authfile(&cfg, username, dev, &n_devs);
-  assert(rc == 1);
+  assert(rc == PAM_SUCCESS);
   assert(n_devs == 2);
 
   assert(strcmp(dev[0].coseType, "es256") == 0);
@@ -582,7 +582,7 @@
   cfg.auth_file = "credentials/new_double_-P.cred";
   cfg.sshformat = 0;
   rc = get_devices_from_authfile(&cfg, username, dev, &n_devs);
-  assert(rc == 1);
+  assert(rc == PAM_SUCCESS);
   assert(n_devs == 2);
 
   assert(strcmp(dev[0].coseType, "es256") == 0);
@@ -622,7 +622,7 @@
   cfg.auth_file = "credentials/new_double_-P-V.cred";
   cfg.sshformat = 0;
   rc = get_devices_from_authfile(&cfg, username, dev, &n_devs);
-  assert(rc == 1);
+  assert(rc == PAM_SUCCESS);
   assert(n_devs == 2);
 
   assert(strcmp(dev[0].coseType, "es256") == 0);
@@ -661,7 +661,7 @@
   cfg.auth_file = "credentials/new_double_-P-N.cred";
   cfg.sshformat = 0;
   rc = get_devices_from_authfile(&cfg, username, dev, &n_devs);
-  assert(rc == 1);
+  assert(rc == PAM_SUCCESS);
   assert(n_devs == 2);
 
   assert(strcmp(dev[0].coseType, "es256") == 0);
@@ -700,7 +700,7 @@
   cfg.auth_file = "credentials/new_double_-P-V-N.cred";
   cfg.sshformat = 0;
   rc = get_devices_from_authfile(&cfg, username, dev, &n_devs);
-  assert(rc == 1);
+  assert(rc == PAM_SUCCESS);
   assert(n_devs == 2);
 
   assert(strcmp(dev[0].coseType, "es256") == 0);
@@ -739,7 +739,7 @@
   cfg.auth_file = "credentials/new_double_-r.cred";
   cfg.sshformat = 0;
   rc = get_devices_from_authfile(&cfg, username, dev, &n_devs);
-  assert(rc == 1);
+  assert(rc == PAM_SUCCESS);
   assert(n_devs == 2);
 
   assert(strcmp(dev[0].coseType, "es256") == 0);
@@ -773,7 +773,7 @@
   cfg.auth_file = "credentials/new_double_-r-V.cred";
   cfg.sshformat = 0;
   rc = get_devices_from_authfile(&cfg, username, dev, &n_devs);
-  assert(rc == 1);
+  assert(rc == PAM_SUCCESS);
   assert(n_devs == 2);
 
   assert(strcmp(dev[0].coseType, "es256") == 0);
@@ -808,7 +808,7 @@
   cfg.auth_file = "credentials/new_double_-r-N.cred";
   cfg.sshformat = 0;
   rc = get_devices_from_authfile(&cfg, username, dev, &n_devs);
-  assert(rc == 1);
+  assert(rc == PAM_SUCCESS);
   assert(n_devs == 2);
 
   assert(strcmp(dev[0].coseType, "es256") == 0);
@@ -843,7 +843,7 @@
   cfg.auth_file = "credentials/new_double_-r-V-N.cred";
   cfg.sshformat = 0;
   rc = get_devices_from_authfile(&cfg, username, dev, &n_devs);
-  assert(rc == 1);
+  assert(rc == PAM_SUCCESS);
   assert(n_devs == 2);
 
   assert(strcmp(dev[0].coseType, "es256") == 0);
@@ -877,7 +877,7 @@
   cfg.auth_file = "credentials/new_double_-r-P.cred";
   cfg.sshformat = 0;
   rc = get_devices_from_authfile(&cfg, username, dev, &n_devs);
-  assert(rc == 1);
+  assert(rc == PAM_SUCCESS);
   assert(n_devs == 2);
 
   assert(strcmp(dev[0].coseType, "es256") == 0);
@@ -912,7 +912,7 @@
   cfg.auth_file = "credentials/new_double_-r-P-V.cred";
   cfg.sshformat = 0;
   rc = get_devices_from_authfile(&cfg, username, dev, &n_devs);
-  assert(rc == 1);
+  assert(rc == PAM_SUCCESS);
   assert(n_devs == 2);
 
   assert(strcmp(dev[0].coseType, "es256") == 0);
@@ -946,7 +946,7 @@
   cfg.auth_file = "credentials/new_double_-r-P-N.cred";
   cfg.sshformat = 0;
   rc = get_devices_from_authfile(&cfg, username, dev, &n_devs);
-  assert(rc == 1);
+  assert(rc == PAM_SUCCESS);
   assert(n_devs == 2);
 
   assert(strcmp(dev[0].coseType, "es256") == 0);
@@ -980,7 +980,7 @@
   cfg.auth_file = "credentials/new_double_-r-P-V-N.cred";
   cfg.sshformat = 0;
   rc = get_devices_from_authfile(&cfg, username, dev, &n_devs);
-  assert(rc == 1);
+  assert(rc == PAM_SUCCESS);
   assert(n_devs == 2);
 
   assert(strcmp(dev[0].coseType, "es256") == 0);
@@ -1017,7 +1017,7 @@
   cfg.auth_file = "credentials/new_mixed_12.cred";
   cfg.sshformat = 0;
   rc = get_devices_from_authfile(&cfg, username, dev, &n_devs);
-  assert(rc == 1);
+  assert(rc == PAM_SUCCESS);
   assert(n_devs == 2);
 
   assert(strcmp(dev[0].coseType, "es256") == 0);
@@ -1056,7 +1056,7 @@
   cfg.auth_file = "credentials/new_mixed_1-P2.cred";
   cfg.sshformat = 0;
   rc = get_devices_from_authfile(&cfg, username, dev, &n_devs);
-  assert(rc == 1);
+  assert(rc == PAM_SUCCESS);
   assert(n_devs == 2);
 
   assert(strcmp(dev[0].coseType, "es256") == 0);
@@ -1095,7 +1095,7 @@
   cfg.auth_file = "credentials/new_mixed_-P12.cred";
   cfg.sshformat = 0;
   rc = get_devices_from_authfile(&cfg, username, dev, &n_devs);
-  assert(rc == 1);
+  assert(rc == PAM_SUCCESS);
   assert(n_devs == 2);
 
   assert(strcmp(dev[0].coseType, "es256") == 0);
@@ -1133,7 +1133,7 @@
   cfg.auth_file = "credentials/new_mixed_-P1-P2.cred";
   cfg.sshformat = 0;
   rc = get_devices_from_authfile(&cfg, username, dev, &n_devs);
-  assert(rc == 1);
+  assert(rc == PAM_SUCCESS);
   assert(n_devs == 2);
 
   assert(strcmp(dev[0].coseType, "es256") == 0);
@@ -1172,7 +1172,7 @@
   cfg.sshformat = 0;
 
   rc = get_devices_from_authfile(&cfg, username, dev, &n_devs);
-  assert(rc == 1);
+  assert(rc == PAM_SUCCESS);
   assert(n_devs == 1);
   assert(strcmp(dev[0].coseType, "es256") == 0);
   assert(strcmp(dev[0].attributes, "+presence") == 0);
diff --color -ruN pam_u2f-1.2.0-ori/util.c pam_u2f-1.2.0-patched/util.c
--- pam_u2f-1.2.0-ori/util.c	2021-09-17 11:16:51.000000000 +0200
+++ pam_u2f-1.2.0-patched/util.c	2025-01-16 14:42:41.987661479 +0100
@@ -797,7 +797,7 @@
                               device_t *devices, unsigned *n_devs) {
 
   char *buf = NULL;
-  int retval = 0;
+  int r = PAM_AUTHINFO_UNAVAIL;
   int fd = -1;
   struct stat st;
   struct passwd *pw = NULL, pw_s;
@@ -812,6 +812,9 @@
 
   fd = open(cfg->auth_file, O_RDONLY | O_CLOEXEC | O_NOCTTY);
   if (fd < 0) {
+    if (errno == ENOENT) {
+      r = PAM_IGNORE;
+    }
     if (cfg->debug)
       D(cfg->debug_file, "Cannot open file: %s (%s)", cfg->auth_file,
         strerror(errno));
@@ -831,9 +834,9 @@
     goto err;
   }
 
-  if (st.st_size == 0) {
+  if ((st.st_mode & (S_IWGRP | S_IWOTH)) != 0) {
     if (cfg->debug)
-      D(cfg->debug_file, "File %s is empty", cfg->auth_file);
+      D(cfg->debug_file, "File %s has insecure permissions", cfg->auth_file);
     goto err;
   }
   opwfile_size = st.st_size;
@@ -873,21 +876,19 @@
   }
 
   if (cfg->sshformat == 0) {
-    retval = parse_native_format(cfg, username, buf, opwfile, devices, n_devs);
+    if (parse_native_format(cfg, username, buf, opwfile, devices, n_devs) != 1) {
+      goto err;
+    }
   } else {
-    retval = parse_ssh_format(cfg, buf, DEVSIZE * cfg->max_devs, opwfile,
-                              opwfile_size, devices, n_devs);
-  }
-
-  if (retval != 1) {
-    // NOTE(adma): error message is logged by the previous function
-    goto err;
+    if (parse_ssh_format(cfg, buf, DEVSIZE * cfg->max_devs, opwfile, opwfile_size, devices, n_devs) != 1) {
+      goto err;
+    }
   }
 
   if (cfg->debug)
     D(cfg->debug_file, "Found %d device(s) for user %s", *n_devs, username);
 
-  retval = 1;
+  r = PAM_SUCCESS;
   goto out;
 
 err:
@@ -909,7 +910,7 @@
   if (fd != -1)
     close(fd);
 
-  return retval;
+  return r;
 }
 
 void free_devices(device_t *devices, const unsigned n_devs) {
@@ -1312,7 +1313,7 @@
   fido_dev_t **authlist = NULL;
   int cued = 0;
   int r;
-  int retval = -2;
+  int retval = PAM_AUTH_ERR;
   size_t ndevs = 0;
   size_t ndevs_prev = 0;
   unsigned i = 0;
@@ -1361,8 +1362,6 @@
 
   i = 0;
   while (i < n_devs) {
-    retval = -2;
-
     if (cfg->debug)
       D(cfg->debug_file, "Attempting authentication with device number %d",
         i + 1);
@@ -1440,7 +1439,7 @@
           }
           r = fido_assert_verify(assert, 0, pk.type, pk.ptr);
           if (r == FIDO_OK) {
-            retval = 1;
+            retval = PAM_SUCCESS;
             goto out;
           }
         }
@@ -1574,7 +1573,7 @@
   char *b64_challenge = NULL;
   char prompt[MAX_PROMPT_LEN];
   char buf[MAX_PROMPT_LEN];
-  int retval = -2;
+  int retval = PAM_AUTH_ERR;
   int n;
   int r;
   unsigned i = 0;
@@ -1649,8 +1648,6 @@
            "Please pass the challenge(s) above to fido2-assert, and "
            "paste the results in the prompt below.");
 
-  retval = -1;
-
   for (i = 0; i < n_devs; ++i) {
     n = snprintf(prompt, sizeof(prompt), "Response #%d: ", i + 1);
     if (n <= 0 || (size_t) n >= sizeof(prompt)) {
@@ -1667,7 +1664,7 @@
 
     r = fido_assert_verify(assert[i], 0, pk[i].type, pk[i].ptr);
     if (r == FIDO_OK) {
-      retval = 1;
+      retval = PAM_SUCCESS;
       break;
     }
   }
