luci2: implement password_set call
authorJo-Philipp Wich <jow@openwrt.org>
Mon, 1 Jul 2013 16:07:11 +0000 (18:07 +0200)
committerJo-Philipp Wich <jow@openwrt.org>
Mon, 1 Jul 2013 16:27:24 +0000 (18:27 +0200)
luci2.c

diff --git a/luci2.c b/luci2.c
index e012440..db4aac3 100644 (file)
--- a/luci2.c
+++ b/luci2.c
@@ -22,6 +22,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
+#include <sys/wait.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <dirent.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <dirent.h>
@@ -64,6 +65,17 @@ static const struct blobmsg_policy rpc_sshkey_policy[__RPC_K_MAX] = {
        [RPC_K_KEYS]   = { .name = "keys",   .type = BLOBMSG_TYPE_ARRAY },
 };
 
        [RPC_K_KEYS]   = { .name = "keys",   .type = BLOBMSG_TYPE_ARRAY },
 };
 
+enum {
+       RPC_P_USER,
+       RPC_P_PASSWORD,
+       __RPC_P_MAX
+};
+
+static const struct blobmsg_policy rpc_password_policy[__RPC_P_MAX] = {
+       [RPC_P_USER]     = { .name = "user",     .type = BLOBMSG_TYPE_STRING },
+       [RPC_P_PASSWORD] = { .name = "password", .type = BLOBMSG_TYPE_STRING },
+};
+
 
 static int
 rpc_errno_status(void)
 
 static int
 rpc_errno_status(void)
@@ -515,6 +527,79 @@ rpc_luci2_sshkeys_set(struct ubus_context *ctx, struct ubus_object *obj,
        return 0;
 }
 
        return 0;
 }
 
+static int
+rpc_luci2_password_set(struct ubus_context *ctx, struct ubus_object *obj,
+                       struct ubus_request_data *req, const char *method,
+                       struct blob_attr *msg)
+{
+       pid_t pid;
+       int fd, fds[2];
+       struct stat s;
+       struct blob_attr *tb[__RPC_P_MAX];
+
+       blobmsg_parse(rpc_password_policy, __RPC_P_MAX, tb,
+                     blob_data(msg), blob_len(msg));
+
+       if (!tb[RPC_P_USER] || !tb[RPC_P_PASSWORD])
+               return UBUS_STATUS_INVALID_ARGUMENT;
+
+       if (stat("/usr/bin/passwd", &s))
+               return UBUS_STATUS_NOT_FOUND;
+
+       if (!(s.st_mode & S_IXUSR))
+               return UBUS_STATUS_PERMISSION_DENIED;
+
+       if (pipe(fds))
+               return rpc_errno_status();
+
+       switch ((pid = fork()))
+       {
+       case -1:
+               close(fds[0]);
+               close(fds[1]);
+               return rpc_errno_status();
+
+       case 0:
+               uloop_done();
+
+               dup2(fds[0], 0);
+               close(fds[0]);
+               close(fds[1]);
+
+               if ((fd = open("/dev/null", O_RDWR)) > -1)
+               {
+                       dup2(fd, 1);
+                       dup2(fd, 2);
+                       close(fd);
+               }
+
+               chdir("/");
+
+               if (execl("/usr/bin/passwd", "/usr/bin/passwd",
+                         blobmsg_data(tb[RPC_P_USER]), NULL))
+                       return rpc_errno_status();
+
+       default:
+               close(fds[0]);
+
+               write(fds[1], blobmsg_data(tb[RPC_P_PASSWORD]),
+                             blobmsg_data_len(tb[RPC_P_PASSWORD]) - 1);
+               write(fds[1], "\n", 1);
+
+               usleep(100 * 1000);
+
+               write(fds[1], blobmsg_data(tb[RPC_P_PASSWORD]),
+                             blobmsg_data_len(tb[RPC_P_PASSWORD]) - 1);
+               write(fds[1], "\n", 1);
+
+               close(fds[1]);
+
+               waitpid(pid, NULL, 0);
+
+               return 0;
+       }
+}
+
 
 static FILE *
 dnsmasq_leasefile(void)
 
 static FILE *
 dnsmasq_leasefile(void)
@@ -1049,7 +1134,9 @@ int rpc_luci2_api_init(struct ubus_context *ctx)
                                                  rpc_init_policy),
                UBUS_METHOD_NOARG("sshkeys_get",  rpc_luci2_sshkeys_get),
                UBUS_METHOD("sshkeys_set",        rpc_luci2_sshkeys_set,
                                                  rpc_init_policy),
                UBUS_METHOD_NOARG("sshkeys_get",  rpc_luci2_sshkeys_get),
                UBUS_METHOD("sshkeys_set",        rpc_luci2_sshkeys_set,
-                                                 rpc_sshkey_policy)
+                                                 rpc_sshkey_policy),
+               UBUS_METHOD("password_set",       rpc_luci2_password_set,
+                                                 rpc_password_policy)
        };
 
        static struct ubus_object_type luci2_system_type =
        };
 
        static struct ubus_object_type luci2_system_type =