2 * Copyright 2008-2013, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
19 #include <RegistrarDefs.h>
20 #include <user_group.h>
21 #include <util/KMessage.h>
23 #include <AutoDeleter.h>
25 #include "multiuser_utils.h"
28 extern const char *__progname
;
31 static const char* kUsage
=
32 "Usage: %s [ <options> ] [ <user name> ]\n"
33 "Change the password of the specified user.\n"
37 " Delete the password for the specified user.\n"
39 " Print usage info.\n"
43 print_usage_and_exit(bool error
)
45 fprintf(error
? stderr
: stdout
, kUsage
, __progname
);
51 main(int argc
, const char* const* argv
)
53 bool deletePassword
= false;
56 static struct option sLongOptions
[] = {
57 { "help", no_argument
, 0, 'h' },
61 opterr
= 0; // don't print errors
62 int c
= getopt_long(argc
, (char**)argv
, "dh", sLongOptions
, NULL
);
69 deletePassword
= true;
73 print_usage_and_exit(false);
77 print_usage_and_exit(true);
82 if (optind
+ 1 < argc
)
83 print_usage_and_exit(true);
85 const char* user
= optind
< argc
? argv
[optind
] : NULL
;
88 fprintf(stderr
, "Error: You need to be root.\n");
92 // this is a set-uid tool -- get the real UID
97 fprintf(stderr
, "Error: Only root can delete users' passwords.\n");
102 fprintf(stderr
, "Error: A user must be specified.\n");
107 // get the passwd entry
108 struct passwd
* passwd
;
110 passwd
= getpwnam(user
);
111 if (passwd
== NULL
) {
112 fprintf(stderr
, "Error: No user with name \"%s\".\n", user
);
116 if (uid
!= 0 && passwd
->pw_uid
!= uid
) {
117 fprintf(stderr
, "Error: Only root can change the passwd for other "
122 passwd
= getpwuid(uid
);
123 if (passwd
== NULL
) {
124 fprintf(stderr
, "Error: Ugh! Couldn't get passwd entry for uid "
129 user
= passwd
->pw_name
;
132 // if not root, the user needs to authenticate
134 if (authenticate_user("old password: ", passwd
, getspnam(user
), 1,
140 char password
[LINE_MAX
];
141 char* encryptedPassword
;
143 if (deletePassword
) {
145 encryptedPassword
= password
;
148 if (read_password("new password: ", password
, sizeof(password
), false)
153 if (strlen(password
) >= MAX_SHADOW_PWD_PASSWORD_LEN
) {
154 fprintf(stderr
, "Error: The password is too long.\n");
158 // read password again
159 char repeatedPassword
[LINE_MAX
];
160 if (read_password("repeat new password: ", repeatedPassword
,
161 sizeof(repeatedPassword
), false) != B_OK
) {
165 // passwords need to match
166 if (strcmp(password
, repeatedPassword
) != 0) {
167 fprintf(stderr
, "Error: passwords don't match\n");
171 memset(repeatedPassword
, 0, sizeof(repeatedPassword
));
174 encryptedPassword
= crypt(password
, user
);
175 memset(password
, 0, sizeof(password
));
178 // prepare request for the registrar
179 KMessage
message(BPrivate::B_REG_UPDATE_USER
);
180 if (message
.AddInt32("uid", passwd
->pw_uid
) != B_OK
181 || message
.AddInt32("last changed", time(NULL
)) != B_OK
182 || message
.AddString("password", "x") != B_OK
183 || message
.AddString("shadow password", encryptedPassword
) != B_OK
) {
184 fprintf(stderr
, "Error: Out of memory!\n");
190 status_t error
= send_authentication_request_to_registrar(message
, reply
);
192 fprintf(stderr
, "Error: Failed to create user: %s\n", strerror(error
));