passwd: Add option -d to delete a user's password
This commit is contained in:
parent
032ea9a485
commit
6c346b88e1
@ -1,9 +1,10 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. All Rights Reserved.
|
* Copyright 2008-2013, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <getopt.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <shadow.h>
|
#include <shadow.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -28,8 +29,15 @@ extern const char *__progname;
|
|||||||
|
|
||||||
|
|
||||||
static const char* kUsage =
|
static const char* kUsage =
|
||||||
"Usage: %s [ <user name> ]\n"
|
"Usage: %s [ <options> ] [ <user name> ]\n"
|
||||||
;
|
"Deletes the specified user.\n"
|
||||||
|
"\n"
|
||||||
|
"Options:\n"
|
||||||
|
" -d\n"
|
||||||
|
" Delete the password for the specified user.\n"
|
||||||
|
" -h, --help\n"
|
||||||
|
" Print usage info.\n"
|
||||||
|
;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
print_usage_and_exit(bool error)
|
print_usage_and_exit(bool error)
|
||||||
@ -42,12 +50,39 @@ print_usage_and_exit(bool error)
|
|||||||
int
|
int
|
||||||
main(int argc, const char* const* argv)
|
main(int argc, const char* const* argv)
|
||||||
{
|
{
|
||||||
if (argc > 2)
|
bool deletePassword = false;;
|
||||||
|
|
||||||
|
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, "dh", sLongOptions, NULL);
|
||||||
|
if (c == -1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
switch (c) {
|
||||||
|
case 'd':
|
||||||
|
deletePassword = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'h':
|
||||||
|
print_usage_and_exit(false);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
print_usage_and_exit(true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optind + 1 < argc)
|
||||||
print_usage_and_exit(true);
|
print_usage_and_exit(true);
|
||||||
|
|
||||||
const char* user = NULL;
|
const char* user = optind < argc ? argv[optind] : NULL;
|
||||||
if (argc == 2)
|
|
||||||
user = argv[1];
|
|
||||||
|
|
||||||
if (geteuid() != 0) {
|
if (geteuid() != 0) {
|
||||||
fprintf(stderr, "Error: You need to be root.\n");
|
fprintf(stderr, "Error: You need to be root.\n");
|
||||||
@ -57,6 +92,18 @@ main(int argc, const char* const* argv)
|
|||||||
// this is a set-uid tool -- get the real UID
|
// this is a set-uid tool -- get the real UID
|
||||||
uid_t uid = getuid();
|
uid_t uid = getuid();
|
||||||
|
|
||||||
|
if (deletePassword) {
|
||||||
|
if (uid != 0) {
|
||||||
|
fprintf(stderr, "Error: Only root can delete users' passwords.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user == NULL) {
|
||||||
|
fprintf(stderr, "Error: A user must be specified.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// get the passwd entry
|
// get the passwd entry
|
||||||
struct passwd* passwd;
|
struct passwd* passwd;
|
||||||
if (user != NULL) {
|
if (user != NULL) {
|
||||||
@ -90,40 +137,43 @@ main(int argc, const char* const* argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// read new password
|
|
||||||
char password[LINE_MAX];
|
char password[LINE_MAX];
|
||||||
if (read_password("new password: ", password, sizeof(password), false)
|
|
||||||
!= B_OK) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strlen(password) >= MAX_SHADOW_PWD_PASSWORD_LEN) {
|
|
||||||
fprintf(stderr, "Error: The password is too long.\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// read password again
|
|
||||||
char repeatedPassword[LINE_MAX];
|
|
||||||
if (read_password("repeat new password: ", repeatedPassword,
|
|
||||||
sizeof(repeatedPassword), false) != B_OK) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// passwords need to match
|
|
||||||
if (strcmp(password, repeatedPassword) != 0) {
|
|
||||||
fprintf(stderr, "Error: passwords don't match\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(repeatedPassword, 0, sizeof(repeatedPassword));
|
|
||||||
|
|
||||||
// crypt it
|
|
||||||
char* encryptedPassword;
|
char* encryptedPassword;
|
||||||
if (strlen(password) > 0) {
|
|
||||||
|
if (deletePassword) {
|
||||||
|
password[0] = '\0';
|
||||||
|
encryptedPassword = password;
|
||||||
|
} else {
|
||||||
|
// read new password
|
||||||
|
if (read_password("new password: ", password, sizeof(password), false)
|
||||||
|
!= B_OK) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen(password) >= MAX_SHADOW_PWD_PASSWORD_LEN) {
|
||||||
|
fprintf(stderr, "Error: The password is too long.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// read password again
|
||||||
|
char repeatedPassword[LINE_MAX];
|
||||||
|
if (read_password("repeat new password: ", repeatedPassword,
|
||||||
|
sizeof(repeatedPassword), false) != B_OK) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// passwords need to match
|
||||||
|
if (strcmp(password, repeatedPassword) != 0) {
|
||||||
|
fprintf(stderr, "Error: passwords don't match\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(repeatedPassword, 0, sizeof(repeatedPassword));
|
||||||
|
|
||||||
|
// crypt it
|
||||||
encryptedPassword = crypt(password, user);
|
encryptedPassword = crypt(password, user);
|
||||||
memset(password, 0, sizeof(password));
|
memset(password, 0, sizeof(password));
|
||||||
} else
|
}
|
||||||
encryptedPassword = password;
|
|
||||||
|
|
||||||
// prepare request for the registrar
|
// prepare request for the registrar
|
||||||
KMessage message(BPrivate::B_REG_UPDATE_USER);
|
KMessage message(BPrivate::B_REG_UPDATE_USER);
|
||||||
|
Loading…
Reference in New Issue
Block a user