1 /* 2 * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 #include <errno.h> 7 #include <pwd.h> 8 #include <shadow.h> 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <string.h> 12 #include <termios.h> 13 #include <unistd.h> 14 15 #include <OS.h> 16 17 #include <RegistrarDefs.h> 18 #include <user_group.h> 19 #include <util/KMessage.h> 20 21 #include <AutoDeleter.h> 22 23 #include "multiuser_utils.h" 24 25 26 extern const char *__progname; 27 28 29 static const char* kUsage = 30 "Usage: %s [ <user name> ]\n" 31 ; 32 33 static void 34 print_usage_and_exit(bool error) 35 { 36 fprintf(error ? stderr : stdout, kUsage, __progname); 37 exit(error ? 1 : 0); 38 } 39 40 41 int 42 main(int argc, const char* const* argv) 43 { 44 if (argc > 2) 45 print_usage_and_exit(true); 46 47 const char* user = NULL; 48 if (argc == 2) 49 user = argv[1]; 50 51 if (geteuid() != 0) { 52 fprintf(stderr, "Error: You need to be root.\n"); 53 exit(1); 54 } 55 56 // this is a set-uid tool -- get the real UID 57 uid_t uid = getuid(); 58 59 // get the passwd entry 60 struct passwd* passwd; 61 if (user != NULL) { 62 passwd = getpwnam(user); 63 if (passwd == NULL) { 64 fprintf(stderr, "Error: No user with name \"%s\".\n", user); 65 exit(1); 66 } 67 68 if (uid != 0 && passwd->pw_uid != uid) { 69 fprintf(stderr, "Error: Only root can change the passwd for other " 70 "users.\n"); 71 exit(1); 72 } 73 } else { 74 passwd = getpwuid(uid); 75 if (passwd == NULL) { 76 fprintf(stderr, "Error: Ugh! Couldn't get passwd entry for uid " 77 "%d.\n", uid); 78 exit(1); 79 } 80 81 user = passwd->pw_name; 82 } 83 84 // if not root, the user needs to authenticate 85 if (uid != 0) { 86 if (authenticate_user("old password: ", passwd, getspnam(user), 1, 87 false) != B_OK) { 88 exit(1); 89 } 90 } 91 92 // read new password 93 char password[LINE_MAX]; 94 if (read_password("new password: ", password, sizeof(password), false) 95 != B_OK) { 96 exit(1); 97 } 98 99 if (strlen(password) >= MAX_SHADOW_PWD_PASSWORD_LEN) { 100 fprintf(stderr, "Error: The password is too long.\n"); 101 exit(1); 102 } 103 104 // read password again 105 char repeatedPassword[LINE_MAX]; 106 if (read_password("repeat new password: ", repeatedPassword, 107 sizeof(repeatedPassword), false) != B_OK) { 108 exit(1); 109 } 110 111 // passwords need to match 112 if (strcmp(password, repeatedPassword) != 0) { 113 fprintf(stderr, "Error: passwords don't match\n"); 114 exit(1); 115 } 116 117 memset(repeatedPassword, 0, sizeof(repeatedPassword)); 118 119 // crypt it 120 char* encryptedPassword; 121 if (strlen(password) > 0) { 122 encryptedPassword = crypt(password, user); 123 memset(password, 0, sizeof(password)); 124 } else 125 encryptedPassword = password; 126 127 // prepare request for the registrar 128 KMessage message(BPrivate::B_REG_UPDATE_USER); 129 if (message.AddInt32("uid", passwd->pw_uid) != B_OK 130 || message.AddString("password", "x") != B_OK 131 || message.AddString("shadow password", encryptedPassword) != B_OK) { 132 fprintf(stderr, "Error: Out of memory!\n"); 133 exit(1); 134 } 135 136 // send the request 137 KMessage reply; 138 status_t error = send_authentication_request_to_registrar(message, reply); 139 if (error != B_OK) { 140 fprintf(stderr, "Error: Failed to create user: %s\n", strerror(error)); 141 exit(1); 142 } 143 144 return 0; 145 } 146