2 * Copyright 2008-2013, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
20 #include <RegistrarDefs.h>
21 #include <user_group.h>
22 #include <util/KMessage.h>
24 #include <AutoDeleter.h>
26 #include "multiuser_utils.h"
29 extern const char *__progname
;
32 static const char* kUsage
=
33 "Usage: %s [ <options> ] [ <user name> ]\n"
34 "Change the password of the specified user.\n"
38 " Delete the password for the specified user.\n"
40 " Print usage info.\n"
44 print_usage_and_exit(bool error
)
46 fprintf(error
? stderr
: stdout
, kUsage
, __progname
);
52 main(int argc
, const char* const* argv
)
54 bool deletePassword
= false;
57 static struct option sLongOptions
[] = {
58 { "help", no_argument
, 0, 'h' },
62 opterr
= 0; // don't print errors
63 int c
= getopt_long(argc
, (char**)argv
, "dh", sLongOptions
, NULL
);
70 deletePassword
= true;
74 print_usage_and_exit(false);
78 print_usage_and_exit(true);
83 if (optind
+ 1 < argc
)
84 print_usage_and_exit(true);
86 const char* user
= optind
< argc
? argv
[optind
] : NULL
;
89 fprintf(stderr
, "Error: You need to be root.\n");
93 // this is a set-uid tool -- get the real UID
98 fprintf(stderr
, "Error: Only root can delete users' passwords.\n");
103 fprintf(stderr
, "Error: A user must be specified.\n");
108 // get the passwd entry
109 struct passwd
* passwd
;
111 passwd
= getpwnam(user
);
112 if (passwd
== NULL
) {
113 fprintf(stderr
, "Error: No user with name \"%s\".\n", user
);
117 if (uid
!= 0 && passwd
->pw_uid
!= uid
) {
118 fprintf(stderr
, "Error: Only root can change the passwd for other "
123 passwd
= getpwuid(uid
);
124 if (passwd
== NULL
) {
125 fprintf(stderr
, "Error: Ugh! Couldn't get passwd entry for uid "
130 user
= passwd
->pw_name
;
133 // if not root, the user needs to authenticate
135 if (authenticate_user("old password: ", passwd
, getspnam(user
), 1,
141 char password
[LINE_MAX
];
142 char* encryptedPassword
;
144 if (deletePassword
) {
146 encryptedPassword
= password
;
149 if (read_password("new password: ", password
, sizeof(password
), false)
154 if (strlen(password
) >= MAX_SHADOW_PWD_PASSWORD_LEN
) {
155 fprintf(stderr
, "Error: The password is too long.\n");
159 // read password again
160 char repeatedPassword
[LINE_MAX
];
161 if (read_password("repeat new password: ", repeatedPassword
,
162 sizeof(repeatedPassword
), false) != B_OK
) {
166 // passwords need to match
167 if (strcmp(password
, repeatedPassword
) != 0) {
168 fprintf(stderr
, "Error: passwords don't match\n");
172 memset(repeatedPassword
, 0, sizeof(repeatedPassword
));
175 encryptedPassword
= crypt(password
, NULL
);
176 memset(password
, 0, sizeof(password
));
179 // prepare request for the registrar
180 KMessage
message(BPrivate::B_REG_UPDATE_USER
);
181 if (message
.AddInt32("uid", passwd
->pw_uid
) != B_OK
182 || message
.AddInt32("last changed", time(NULL
)) != B_OK
183 || message
.AddString("password", "x") != B_OK
184 || message
.AddString("shadow password", encryptedPassword
) != B_OK
) {
185 fprintf(stderr
, "Error: Failed to construct message!\n");
191 status_t error
= send_authentication_request_to_registrar(message
, reply
);
193 fprintf(stderr
, "Error: Failed to set the password: %s\n",