passwd: Add option -d to delete a user's password

This commit is contained in:
Ingo Weinhold 2013-09-16 18:01:07 +02:00
parent 032ea9a485
commit 6c346b88e1

View File

@ -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);