Преглед на файлове

LoginServer: Process logins and start SystemServer in user mode

Peter Elliott преди 3 години
родител
ревизия
e3ed7f76c5
променени са 2 файла, в които са добавени 104 реда и са изтрити 0 реда
  1. 3 0
      Base/etc/SystemServer.ini
  2. 101 0
      Userland/Services/LoginServer/main.cpp

+ 3 - 0
Base/etc/SystemServer.ini

@@ -166,3 +166,6 @@ KeepAlive=0
 [SystemServer]
 Arguments=--user
 User=anon
+
+#[LoginServer]
+#User=root

+ 101 - 0
Userland/Services/LoginServer/main.cpp

@@ -4,14 +4,115 @@
  * SPDX-License-Identifier: BSD-2-Clause
  */
 
+#include <LibCore/Account.h>
 #include <LibGUI/Application.h>
 #include <Services/LoginServer/LoginWindow.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+static void child_process(Core::Account const& account)
+{
+    if (!account.login()) {
+        dbgln("failed to switch users: {}", strerror(errno));
+        exit(1);
+    }
+
+    setenv("HOME", account.home_directory().characters(), true);
+    pid_t rc = setsid();
+    if (rc == -1) {
+        dbgln("failed to setsid: {}", strerror(errno));
+        exit(1);
+    }
+    dbgln("login with sid={}", rc);
+
+    execlp("/bin/SystemServer", "SystemServer", "--user", nullptr);
+    dbgln("failed to exec SystemServer --user: {}", strerror(errno));
+    exit(127);
+}
+
+static void login(Core::Account const& account, LoginWindow& window)
+{
+    pid_t pid = fork();
+    if (pid == 0)
+        child_process(account);
+
+    int wstatus;
+    pid_t rc = waitpid(pid, &wstatus, 0);
+    if (rc == -1)
+        dbgln("waitpid failed: {}", strerror(errno));
+    if (rc != 0)
+        dbgln("SystemServer exited with non-zero status: {}", rc);
+
+    window.show();
+}
 
 int main(int argc, char** argv)
 {
     auto app = GUI::Application::construct(argc, argv);
 
+    if (pledge("stdio recvfd sendfd rpath exec proc id", nullptr) < 0) {
+        perror("pledge");
+        return 1;
+    }
+
+    if (unveil("/home", "r") < 0) {
+        perror("unveil");
+        return 1;
+    }
+
+    if (unveil("/etc/passwd", "r") < 0) {
+        perror("unveil");
+        return 1;
+    }
+
+    if (unveil("/etc/shadow", "r") < 0) {
+        perror("unveil");
+        return 1;
+    }
+
+    if (unveil("/etc/group", "r") < 0) {
+        perror("unveil");
+        return 1;
+    }
+
+    if (unveil("/bin/SystemServer", "x") < 0) {
+        perror("unveil");
+        return 1;
+    }
+
+    if (unveil("/res", "r") < 0) {
+        perror("unveil");
+        return 1;
+    }
+
+    unveil(nullptr, nullptr);
+
     auto window = LoginWindow::construct();
+    window->on_submit = [&]() {
+        auto username = window->username();
+        auto password = Core::SecretString::take_ownership(window->password().to_byte_buffer());
+
+        window->set_password("");
+
+        auto account = Core::Account::from_name(username.characters());
+        if (account.is_error()) {
+            dbgln("failed graphical login for user {}: {}", username, account.error());
+            return;
+        }
+
+        if (!account.value().authenticate(password)) {
+            dbgln("failed graphical login for user {}: invalid password", username);
+            return;
+        }
+
+        window->set_username("");
+        window->hide();
+
+        login(account.value(), *window);
+    };
+
     window->show();
 
     return app->exec();