]> git.ipfire.org Git - network.git/blobdiff - src/networkd/main.c
networkd: Change to a non-privileged user right away
[network.git] / src / networkd / main.c
index 51a9bbab730147b8215ab3703d0da98edfe59387..fbd6c3b9938a070c9714eb3579db4d72a74244a1 100644 (file)
 #                                                                             #
 #############################################################################*/
 
+#include <grp.h>
+#include <pwd.h>
 #include <stddef.h>
+#include <sys/prctl.h>
+#include <sys/types.h>
+#include <unistd.h>
 
 #include "daemon.h"
+#include "logging.h"
+
+static int drop_privileges(const char* user) {
+       struct passwd* passwd = NULL;
+       int r;
+
+       // Fetch the current user
+       uid_t current_uid = getuid();
+
+       // If we have not been launched by root, we will assume that we have already
+       // been launched with a minimal set of privileges.
+       if (current_uid > 0)
+               return 0;
+
+       DEBUG("Dropping privileges...\n");
+
+       // Fetch information about the desired user
+       passwd = getpwnam(user);
+       if (!passwd) {
+               ERROR("Could not find user %s: %m\n", user);
+               return 1;
+       }
+
+       uid_t uid = passwd->pw_uid;
+       gid_t gid = passwd->pw_gid;
+
+       // Change group
+       r = setresgid(gid, gid, gid);
+       if (r) {
+               ERROR("Could not change group to %d: %m\n", gid);
+               return 1;
+       }
+
+       // Set any supplementary groups
+       r = setgroups(0, NULL);
+       if (r) {
+               ERROR("Could not set supplementary groups: %m\n");
+               return 1;
+       }
+
+       // Do not drop any capabilities when we change to the new user
+       r = prctl(PR_SET_KEEPCAPS, 1);
+       if (r) {
+               ERROR("Could not set PR_SET_KEEPCAPS: %m\n");
+               return 1;
+       }
+
+       // Change to the new user
+       r = setresuid(uid, uid, uid);
+       if (r) {
+               ERROR("Could not change user to %d: %m\n", uid);
+               return 1;
+       }
+
+       // Reset PR_SET_KEEPCAPS
+       r = prctl(PR_SET_KEEPCAPS, 0);
+       if (r) {
+               ERROR("Could not set PR_SET_KEEPCAPS: %m\n");
+               return 1;
+       }
+
+       return 0;
+}
 
 int main(int argc, char** argv) {
        struct nw_daemon* daemon = NULL;
        int r;
 
-       // XXX Drop privileges
+       // Drop privileges
+       r = drop_privileges("network");
+       if (r)
+               return r;
 
        // Create the daemon
        r = nw_daemon_create(&daemon);