From e9d9ac713ffa301240e7a2e113bb0d5bb70082f8 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Mon, 16 Sep 2013 15:49:36 +0200 Subject: [PATCH] Add userdel --- build/jam/images/HaikuImage | 2 +- build/jam/images/HaikuImageBootstrap | 2 +- headers/private/app/RegistrarDefs.h | 2 + src/bin/multiuser/Jamfile | 2 + src/bin/multiuser/userdel.cpp | 98 +++++++++++++++++++ .../registrar/AuthenticationManager.cpp | 87 ++++++++++++++-- src/servers/registrar/AuthenticationManager.h | 4 + 7 files changed, 188 insertions(+), 9 deletions(-) create mode 100644 src/bin/multiuser/userdel.cpp diff --git a/build/jam/images/HaikuImage b/build/jam/images/HaikuImage index fc8429aa74..a58a7f8222 100644 --- a/build/jam/images/HaikuImage +++ b/build/jam/images/HaikuImage @@ -37,7 +37,7 @@ SYSTEM_BIN = [ FFilterByBuildFeatures tac tail tcpdump tcptester tee telnet telnetd test timeout top touch tr traceroute translate trash true truncate tsort tty uname unchop unexpand unmount uniq unlink unshar unzip unzipsfx - updatedb uptime urlwrapper useradd uudecode uuencode + updatedb uptime urlwrapper useradd userdel uudecode uuencode vdir version vmstat waitfor watch wc wget whoami writembr@x86 xargs xres yes diff --git a/build/jam/images/HaikuImageBootstrap b/build/jam/images/HaikuImageBootstrap index 1cf9810114..71e5cca30d 100644 --- a/build/jam/images/HaikuImageBootstrap +++ b/build/jam/images/HaikuImageBootstrap @@ -37,7 +37,7 @@ SYSTEM_BIN = [ FFilterByBuildFeatures tac tail tcpdump tcptester tee telnet telnetd test timeout top touch tr traceroute trash true truncate tsort tty uname unchop unexpand unmount uniq unlink unshar unzip unzipsfx - updatedb uptime urlwrapper useradd uudecode uuencode + updatedb uptime urlwrapper useradd userdel uudecode uuencode vdir version vmstat waitfor watch wc wget whoami writembr@x86 xargs xres yes diff --git a/headers/private/app/RegistrarDefs.h b/headers/private/app/RegistrarDefs.h index c5144e2f91..ea3d20a70c 100644 --- a/headers/private/app/RegistrarDefs.h +++ b/headers/private/app/RegistrarDefs.h @@ -121,7 +121,9 @@ enum { B_REG_GET_GROUP = 'rggr', B_REG_GET_USER_GROUPS = 'rgug', B_REG_UPDATE_USER = 'ruus', + B_REG_DELETE_USER = 'rdus', B_REG_UPDATE_GROUP = 'rugr', + B_REG_DELETE_GROUP = 'rdgr', }; // B_REG_MIME_SET_PARAM "which" constants diff --git a/src/bin/multiuser/Jamfile b/src/bin/multiuser/Jamfile index 6a4bc30513..24f3232f29 100644 --- a/src/bin/multiuser/Jamfile +++ b/src/bin/multiuser/Jamfile @@ -15,5 +15,7 @@ BinCommand passwd : passwd.cpp : libmultiuser_utils.a ; BinCommand useradd : useradd.cpp : libmultiuser_utils.a ; +BinCommand userdel : userdel.cpp ; + # set set-uid bit on passwd MODE on passwd = 04755 ; diff --git a/src/bin/multiuser/userdel.cpp b/src/bin/multiuser/userdel.cpp new file mode 100644 index 0000000000..c31cff0df3 --- /dev/null +++ b/src/bin/multiuser/userdel.cpp @@ -0,0 +1,98 @@ +/* + * Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include "multiuser_utils.h" + + +extern const char *__progname; + + +static const char* kUsage = + "Usage: %s [ ] \n" + "Deletes the specified user.\n" + "\n" + "Options:\n" + " -h, --help\n" + " Print usage info.\n" + ; + +static void +print_usage_and_exit(bool error) +{ + fprintf(error ? stderr : stdout, kUsage, __progname); + exit(error ? 1 : 0); +} + + +int +main(int argc, const char* const* argv) +{ + while (true) { + static struct option sLongOptions[] = { + { "help", no_argument, 0, 'h' }, + { 0, 0, 0, 0 } + }; + + opterr = 0; // don't print errors + int c = getopt_long(argc, (char**)argv, "h", sLongOptions, NULL); + if (c == -1) + break; + + + switch (c) { + case 'h': + print_usage_and_exit(false); + break; + + default: + print_usage_and_exit(true); + break; + } + } + + if (optind != argc - 1) + print_usage_and_exit(true); + + const char* user = argv[optind]; + + if (geteuid() != 0) { + fprintf(stderr, "Error: Only root may delete users.\n"); + exit(1); + } + + if (getpwnam(user) == NULL) { + fprintf(stderr, "Error: User \"%s\" doesn't exists.\n", user); + exit(1); + } + + // prepare request for the registrar + KMessage message(BPrivate::B_REG_DELETE_USER); + if (message.AddString("name", user) != B_OK) { + fprintf(stderr, "Error: Out of memory!\n"); + exit(1); + } + + // send the request + KMessage reply; + status_t error = send_authentication_request_to_registrar(message, reply); + if (error != B_OK) { + fprintf(stderr, "Error: Failed to delete user: %s\n", strerror(error)); + exit(1); + } + + return 0; +} diff --git a/src/servers/registrar/AuthenticationManager.cpp b/src/servers/registrar/AuthenticationManager.cpp index d841ad7632..a3fe86a973 100644 --- a/src/servers/registrar/AuthenticationManager.cpp +++ b/src/servers/registrar/AuthenticationManager.cpp @@ -435,6 +435,12 @@ public: return B_OK; } + void RemoveUser(User* user) + { + fUsersByID.erase(fUsersByID.find(user->UID())); + fUsersByName.erase(fUsersByName.find(user->Name())); + } + User* UserByID(uid_t uid) const { map::const_iterator it = fUsersByID.find(uid); @@ -721,7 +727,7 @@ AuthenticationManager::_RequestThread() if (error == B_OK) { message.SendReply(fPasswdDBReply, -1, -1, 0, registrarTeam); } else { - fPasswdDBReply->SetTo(1); + _InvalidatePasswdDBReply(); KMessage reply(error); message.SendReply(&reply, -1, -1, 0, registrarTeam); } @@ -752,7 +758,7 @@ AuthenticationManager::_RequestThread() if (error == B_OK) { message.SendReply(fGroupDBReply, -1, -1, 0, registrarTeam); } else { - fGroupDBReply->SetTo(1); + _InvalidateGroupDBReply(); KMessage reply(error); message.SendReply(&reply, -1, -1, 0, registrarTeam); } @@ -789,7 +795,7 @@ AuthenticationManager::_RequestThread() message.SendReply(fShadowPwdDBReply, -1, -1, 0, registrarTeam); } else { - fShadowPwdDBReply->SetTo(1); + _InvalidateShadowPwdDBReply(); KMessage reply(error); message.SendReply(&reply, -1, -1, 0, registrarTeam); } @@ -915,7 +921,7 @@ AuthenticationManager::_RequestThread() error = B_BAD_VALUE; } - // only can change anything + // only root can change anything if (error == B_OK && !isRoot) error = EPERM; @@ -951,8 +957,8 @@ AuthenticationManager::_RequestThread() if (error == B_OK) { fUserDB->AddUser(user); fUserDB->WriteToDisk(); - fPasswdDBReply->SetTo(1); - fShadowPwdDBReply->SetTo(1); + _InvalidatePasswdDBReply(); + _InvalidateShadowPwdDBReply(); } } catch (...) { error = B_NO_MEMORY; @@ -971,13 +977,59 @@ AuthenticationManager::_RequestThread() break; } + + case B_REG_DELETE_USER: + { + // find user + User* user = NULL; + int32 uid; + const char* name; + + if (message.FindInt32("uid", &uid) == B_OK) { + user = fUserDB->UserByID(uid); + } else if (message.FindString("name", &name) == B_OK) { + user = fUserDB->UserByName(name); + } else { + error = B_BAD_VALUE; + } + + if (error == B_OK && user == NULL) + error = ENOENT; + + // only root can change anything + if (error == B_OK && !isRoot) + error = EPERM; + + // apply the change + if (error == B_OK) { + fUserDB->RemoveUser(user); + fUserDB->WriteToDisk(); + _InvalidatePasswdDBReply(); + _InvalidateShadowPwdDBReply(); + } + + // send reply + KMessage reply; + reply.SetWhat(error); + message.SendReply(&reply, -1, -1, 0, registrarTeam); + + break; + } + case B_REG_UPDATE_GROUP: debug_printf("B_REG_UPDATE_GROUP done: currently unsupported!\n"); break; + + case B_REG_DELETE_GROUP: + { + debug_printf( + "B_REG_DELETE_GROUP done: currently unsupported!\n"); + break; + } + default: debug_printf("REG: invalid message: %" B_PRIu32 "\n", message.What()); - } } } @@ -1132,3 +1184,24 @@ AuthenticationManager::_InitShadowPwdDB() return B_OK; } + + +void +AuthenticationManager::_InvalidatePasswdDBReply() +{ + fPasswdDBReply->SetTo(1); +} + + +void +AuthenticationManager::_InvalidateGroupDBReply() +{ + fGroupDBReply->SetTo(1); +} + + +void +AuthenticationManager::_InvalidateShadowPwdDBReply() +{ + fShadowPwdDBReply->SetTo(1); +} diff --git a/src/servers/registrar/AuthenticationManager.h b/src/servers/registrar/AuthenticationManager.h index ef435008de..849cd526b8 100644 --- a/src/servers/registrar/AuthenticationManager.h +++ b/src/servers/registrar/AuthenticationManager.h @@ -35,6 +35,10 @@ private: status_t _InitGroupDB(); status_t _InitShadowPwdDB(); + void _InvalidatePasswdDBReply(); + void _InvalidateGroupDBReply(); + void _InvalidateShadowPwdDBReply(); + private: port_id fRequestPort; thread_id fRequestThread;