Add userdel
This commit is contained in:
@@ -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 ;
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright 2013, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include <getopt.h>
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <OS.h>
|
||||
|
||||
#include <RegistrarDefs.h>
|
||||
#include <user_group.h>
|
||||
#include <util/KMessage.h>
|
||||
|
||||
#include "multiuser_utils.h"
|
||||
|
||||
|
||||
extern const char *__progname;
|
||||
|
||||
|
||||
static const char* kUsage =
|
||||
"Usage: %s [ <options> ] <user name>\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;
|
||||
}
|
||||
@@ -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<uid_t, User*>::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);
|
||||
}
|
||||
|
||||
@@ -35,6 +35,10 @@ private:
|
||||
status_t _InitGroupDB();
|
||||
status_t _InitShadowPwdDB();
|
||||
|
||||
void _InvalidatePasswdDBReply();
|
||||
void _InvalidateGroupDBReply();
|
||||
void _InvalidateShadowPwdDBReply();
|
||||
|
||||
private:
|
||||
port_id fRequestPort;
|
||||
thread_id fRequestThread;
|
||||
|
||||
Reference in New Issue
Block a user