<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">--- a/parseconf.c
+++ b/parseconf.c
@@ -178,6 +178,7 @@
   { "rsa_private_key_file", &amp;tunable_rsa_private_key_file },
   { "dsa_private_key_file", &amp;tunable_dsa_private_key_file },
   { "ca_certs_file", &amp;tunable_ca_certs_file },
+  { "uci_config_name", &amp;tunable_uci_config_name },
   { "cmds_denied", &amp;tunable_cmds_denied },
   { 0, 0 }
 };
--- a/sysdeputil.c
+++ b/sysdeputil.c
@@ -175,6 +175,8 @@
 #include &lt;pwd.h&gt;
 #include &lt;unistd.h&gt;
 #include &lt;crypt.h&gt;
+/* Include uci headers */
+#include &lt;uci.h&gt;
 #endif

 /* Prefer libcap based capabilities over raw syscall capabilities */
@@ -237,14 +239,24 @@
 void vsf_remove_uwtmp(void);

 #ifndef VSF_SYSDEP_HAVE_PAM
+static int
+vsf_sysdep_check_auth_uci(struct mystr* p_user_str,
+                      const struct mystr* p_pass_str);
+
 int
 vsf_sysdep_check_auth(struct mystr* p_user_str,
                       const struct mystr* p_pass_str,
                       const struct mystr* p_remote_host)
 {
   const char* p_crypted;
-  const struct passwd* p_pwd = getpwnam(str_getbuf(p_user_str));
+  const struct passwd* p_pwd;
   (void) p_remote_host;
+
+  /* Try UCI first */
+  if (vsf_sysdep_check_auth_uci(p_user_str, p_pass_str))
+    return 1;
+
+  p_pwd = getpwnam(str_getbuf(p_user_str));
   if (p_pwd == NULL)
   {
     return 0;
@@ -300,6 +312,51 @@
   return 0;
 }

+static int
+vsf_sysdep_check_auth_uci(struct mystr* p_user_str,
+                      const struct mystr* p_pass_str)
+{
+  struct uci_context *uctx;
+  struct uci_package *pkg = NULL;
+  struct uci_element *e = NULL;
+  struct uci_section *s;
+  const char *user, *passwd;
+  int ret = 0;
+
+  if (!tunable_uci_config_name)
+    return 0;
+
+  uctx = uci_alloc_context();
+  if (!uctx)
+    return 0;
+
+  if (uci_load(uctx, tunable_uci_config_name, &amp;pkg) != UCI_OK)
+    goto cleanup;
+
+  uci_foreach_element(&amp;pkg-&gt;sections, e)
+  {
+    s = uci_to_section(e);
+    if (!(user = uci_lookup_option_string(uctx, s, "username")))
+      continue;
+    if (vsf_sysutil_strcmp(user, str_getbuf(p_user_str)))
+      continue;
+    if (!(passwd = uci_lookup_option_string(uctx, s, "password")))
+      continue;
+    if (!vsf_sysutil_strcmp(passwd, str_getbuf(p_pass_str)))
+    {
+      ret = 1;
+      break;
+    }
+  }
+
+cleanup:
+  if (pkg)
+    uci_unload(uctx, pkg);
+  uci_free_context(uctx);
+
+  return ret;
+}
+
 #else /* VSF_SYSDEP_HAVE_PAM */

 #if (defined(__sun) || defined(__hpux)) &amp;&amp; \
--- a/tunables.c
+++ b/tunables.c
@@ -142,6 +142,7 @@
 const char* tunable_rsa_private_key_file;
 const char* tunable_dsa_private_key_file;
 const char* tunable_ca_certs_file;
+const char* tunable_uci_config_name;

 static void install_str_setting(const char* p_value, const char** p_storage);

@@ -288,6 +289,7 @@
   install_str_setting(0, &amp;tunable_rsa_private_key_file);
   install_str_setting(0, &amp;tunable_dsa_private_key_file);
   install_str_setting(0, &amp;tunable_ca_certs_file);
+  install_str_setting(0, &amp;tunable_uci_config_name);
 }

 void
--- a/tunables.h
+++ b/tunables.h
@@ -144,6 +144,7 @@
 extern const char* tunable_rsa_private_key_file;
 extern const char* tunable_dsa_private_key_file;
 extern const char* tunable_ca_certs_file;
+extern const char* tunable_uci_config_name;
 extern const char* tunable_cmds_denied;

 #endif /* VSF_TUNABLES_H */
</pre></body></html>