luci-base: set password also for rpcd user
authorChristian Korber <redacted>
Tue, 28 Apr 2026 07:19:30 +0000 (09:19 +0200)
committerPaul Donald <redacted>
Wed, 3 Jun 2026 10:49:07 +0000 (13:49 +0300)
This change allows the root user to change also rpcd logins via
administration tab in system. This changes `setPassword` in a way that
existing calls to it fall back to change unix passwords.

The goal of this commit is to prepare the environment to add password
policy (password length, valid property, special characters, etc)
to the administration tab.

Signed-off-by: Christian Korber <redacted>
modules/luci-base/root/usr/share/rpcd/ucode/luci

index 57a96da14100cf3c4a01c314184506287181ce4c..de6a769bbdc484ef99b78150397be0858148533e 100644 (file)
@@ -46,6 +46,69 @@ function callPackageVersionCheck(pkg) {
        return version;
 }
 
+function set_new_pwd(user, pwd) {
+       const ctx = cursor();
+       let cmd, fd, value;
+
+       cmd = sprintf('/usr/sbin/uhttpd -m %s', shellquote(pwd));
+       fd = popen(cmd);
+       value = trim(fd.read('line'));
+
+       fd.close();
+
+       ctx.foreach('rpcd', 'login', s => {
+               if (s.username == user) {
+                       ctx.set('rpcd', s['.name'], 'password', value);
+                       ctx.commit();
+               }
+       });
+}
+
+function check_oldpwd(user, pwd) {
+       let cmd, fd, value;
+       const ctx = cursor();
+       let valid = false;
+
+       cmd = sprintf('/usr/sbin/uhttpd -m %s', shellquote(pwd));
+       fd = popen(cmd);
+       value = trim(fd.read('line'));
+       fd.close();
+
+       ctx.foreach('rpcd', 'login', s => {
+               if (s.username == user && s.password == value)
+                       valid = true;
+       });
+
+       return valid;
+}
+
+function check_user(source, entry) {
+       let found = false;
+
+       switch (source) {
+               case 'unix': {
+                       const fd = open('/etc/passwd');
+
+                       for (let line = fd.read('line'); length(line); line = fd.read('line')) {
+                               let user = split(line, /:/)[0];
+                               if (user == entry)
+                                       found = true;
+                       }
+                       break;
+               }
+
+               case 'rpcd': {
+                       const ctx = cursor();
+                       ctx.foreach('rpcd', 'login', s => {
+                               if (s.username == entry)
+                                       found = true;
+                               });
+               }
+               break;
+       }
+       return found;
+}
+
 const methods = {
        getVersion: {
                call: function(request) {
@@ -469,14 +532,58 @@ const methods = {
        },
 
        setPassword: {
-               args: { username: 'root', password: 'password' },
+               args: {
+                       username: 'root',
+                       password: 'password',
+                       oldpassword: '',
+                       rpcd: false,
+               },
                call: function(request) {
-                       const u = shellquote(request.args.username);
-                       const p = shellquote(request.args.password);
+                       const user = request.args.username;
+                       const pwd = request.args.password;
+                       const oldpwd = request.args.oldpassword;
+                       const type = request.args.rpcd == true ? 'rpcd' : 'unix';
+                       const known_user = check_user(type, user);
+                       const uci = cursor();
 
-                       return {
-                               result: system(`(echo ${p}; sleep 1; echo ${p}) | /bin/busybox passwd ${u} >/dev/null 2>&1`) == 0
-                       };
+                       if (type == 'unix') {
+                               const u = shellquote(user);
+                               const p = shellquote(pwd);
+
+                               return {
+                                       result: system(`(echo ${p}; sleep 1; echo ${p}) | /bin/busybox passwd ${u} >/dev/null 2>&1`) == 0
+                               };
+                       }
+
+                       if (!access('/usr/sbin/uhttpd', 'x'))
+                               return { 
+                                       result: 0 ,
+                                       msg: "uhttpd not installed"
+                               };
+
+                       if (known_user) {
+                               if (!oldpwd)
+                                       return { result: 0 };
+
+                               /*
+                               * check if login is valid
+                               */
+                               if (!check_oldpwd(user, oldpwd))
+                                       return { result: 0 };
+                       } else {
+                               /*
+                                * create user to keep logic of luci-app-acl
+                                */
+                               const sid = uci.add('rpcd', 'login');
+                               uci.set('rpcd', sid, 'username', user);
+                               uci.commit('rpcd');
+                       }
+
+                       /*
+                        * encrypt password and assign it to rpcd login
+                        */
+                        set_new_pwd(user, pwd);
+                        return { result: 1 };
                }
        },
 
git clone https://git.99rst.org/PROJECT