From 6c346b88e1134f09024879a85f358ea4992023dd Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Mon, 16 Sep 2013 18:01:07 +0200 Subject: [PATCH] passwd: Add option -d to delete a user's password --- src/bin/multiuser/passwd.cpp | 124 ++++++++++++++++++++++++----------- 1 file changed, 87 insertions(+), 37 deletions(-) diff --git a/src/bin/multiuser/passwd.cpp b/src/bin/multiuser/passwd.cpp index 58d86208b7..bd12bec15d 100644 --- a/src/bin/multiuser/passwd.cpp +++ b/src/bin/multiuser/passwd.cpp @@ -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. */ #include +#include #include #include #include @@ -28,8 +29,15 @@ extern const char *__progname; static const char* kUsage = -"Usage: %s [ ]\n" -; + "Usage: %s [ ] [ ]\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 print_usage_and_exit(bool error) @@ -42,12 +50,39 @@ print_usage_and_exit(bool error) int 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); - const char* user = NULL; - if (argc == 2) - user = argv[1]; + const char* user = optind < argc ? argv[optind] : NULL; if (geteuid() != 0) { 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 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 struct passwd* passwd; if (user != NULL) { @@ -90,40 +137,43 @@ main(int argc, const char* const* argv) } } - // read new password 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; - 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); memset(password, 0, sizeof(password)); - } else - encryptedPassword = password; + } // prepare request for the registrar KMessage message(BPrivate::B_REG_UPDATE_USER);