From a0092f35c5560ab26dbab5e0fbd8a4de51b27528 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 21 May 2008 00:20:28 -0400 Subject: [PATCH] Only allow root clients to talk to daemon We don't want normal users on the system to be able to manipulate plymouth. This will be especially important later when we run plymouth for post-bootup reasons. This patch checks peer credentials and sends back a NAK to clients who aren't root. --- TODO | 1 - src/libply/ply-utils.c | 39 +++++++++++++++++++++++++++++++++++++++ src/libply/ply-utils.h | 4 ++++ src/ply-boot-protocol.h | 1 + src/ply-boot-server.c | 29 +++++++++++++++++++++++++++++ 5 files changed, 73 insertions(+), 1 deletion(-) diff --git a/TODO b/TODO index 756dfd2..b100d37 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,3 @@ - fix the tests so that they work better with "make check" - Allow plymouth to be started from nash instead of the other way around - Drop all the make ram disk and copy code. That was just to make bolting things on easier. We can integrate now. -- check peer credentials on client to make sure it's not running unprivileged diff --git a/src/libply/ply-utils.c b/src/libply/ply-utils.c index 58a3862..910b571 100644 --- a/src/libply/ply-utils.c +++ b/src/libply/ply-utils.c @@ -103,6 +103,7 @@ static int ply_open_unix_socket (const char *path) { int fd; + const int should_pass_credentials = true; assert (path != NULL); @@ -120,6 +121,15 @@ ply_open_unix_socket (const char *path) return -1; } + if (setsockopt (fd, SOL_SOCKET, SO_PASSCRED, + &should_pass_credentials, sizeof (should_pass_credentials)) < 0) + { + ply_save_errno (); + close (fd); + ply_restore_errno (); + return -1; + } + return fd; } @@ -232,6 +242,35 @@ ply_listen_to_unix_socket (const char *path, return fd; } +bool +ply_get_credentials_from_fd (int fd, + pid_t *pid, + uid_t *uid, + gid_t *gid) +{ + struct ucred credentials; + socklen_t credential_size; + + credential_size = sizeof (credentials); + if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &credentials, + &credential_size) < 0) + return false; + + if (credential_size < sizeof (credentials)) + return false; + + if (pid != NULL) + *pid = credentials.pid; + + if (uid != NULL) + *uid = credentials.uid; + + if (gid != NULL) + *gid = credentials.gid; + + return true; +} + int ply_create_unix_socket (const char *path) { diff --git a/src/libply/ply-utils.h b/src/libply/ply-utils.h index 91d01ca..3e2265a 100644 --- a/src/libply/ply-utils.h +++ b/src/libply/ply-utils.h @@ -48,6 +48,10 @@ int ply_connect_to_unix_socket (const char *path, bool is_abstract); int ply_listen_to_unix_socket (const char *path, bool is_abstract); +bool ply_get_credentials_from_fd (int fd, + pid_t *pid, + uid_t *uid, + gid_t *gid); bool ply_write (int fd, const void *buffer, diff --git a/src/ply-boot-protocol.h b/src/ply-boot-protocol.h index 5dc0877..16fce7c 100644 --- a/src/ply-boot-protocol.h +++ b/src/ply-boot-protocol.h @@ -30,6 +30,7 @@ #define PLY_BOOT_PROTOCOL_REQUEST_TYPE_PASSWORD "*" #define PLY_BOOT_PROTOCOL_REQUEST_TYPE_SHOW_SPLASH "$" #define PLY_BOOT_PROTOCOL_RESPONSE_TYPE_ACK "\x6" +#define PLY_BOOT_PROTOCOL_RESPONSE_TYPE_NAK "\x15" #define PLY_BOOT_PROTOCOL_RESPONSE_TYPE_ANSWER "\x2" #endif /* PLY_BOOT_PROTOCOL_H */ diff --git a/src/ply-boot-server.c b/src/ply-boot-server.c index d34d04a..517a31b 100644 --- a/src/ply-boot-server.c +++ b/src/ply-boot-server.c @@ -169,6 +169,17 @@ ply_boot_connection_read_request (ply_boot_connection_t *connection, return true; } +static bool +ply_boot_connection_is_from_root (ply_boot_connection_t *connection) +{ + uid_t uid; + + if (!ply_get_credentials_from_fd (connection->fd, NULL, &uid, NULL)) + return false; + + return uid == 0; +} + static void ply_boot_connection_on_request (ply_boot_connection_t *connection) { @@ -185,6 +196,18 @@ ply_boot_connection_on_request (ply_boot_connection_t *connection) &command, &argument)) return; + if (!ply_boot_connection_is_from_root (connection)) + { + ply_error ("request came from non-root user"); + + if (!ply_write (connection->fd, + PLY_BOOT_PROTOCOL_RESPONSE_TYPE_NAK, + strlen (PLY_BOOT_PROTOCOL_RESPONSE_TYPE_ACK))) + ply_error ("could not write bytes: %m"); + + return; + } + if (strcmp (command, PLY_BOOT_PROTOCOL_REQUEST_TYPE_UPDATE) == 0) { if (server->update_handler != NULL) @@ -238,6 +261,12 @@ ply_boot_connection_on_request (ply_boot_connection_t *connection) else if (strcmp (command, PLY_BOOT_PROTOCOL_REQUEST_TYPE_PING) != 0) { ply_error ("received unknown command '%s' from client", command); + + if (!ply_write (connection->fd, + PLY_BOOT_PROTOCOL_RESPONSE_TYPE_NAK, + strlen (PLY_BOOT_PROTOCOL_RESPONSE_TYPE_ACK))) + ply_error ("could not write bytes: %m"); + return; }