]> sourceware.org Git - newlib-cygwin.git/blame - winsup/utils/passwd.c
* Merge in cygwin-64bit-branch.
[newlib-cygwin.git] / winsup / utils / passwd.c
CommitLineData
1fd5e000
CF
1/* passwd.c: Changing passwords and managing account information
2
61522196
CV
3 Copyright 1999, 2000, 2001, 2002, 2003, 2005, 2008, 2009, 2011, 2012,
4 2013 Red Hat, Inc.
1fd5e000
CF
5
6 Written by Corinna Vinschen <corinna.vinschen@cityweb.de>
7
8This file is part of Cygwin.
9
10This software is a copyrighted work licensed under the terms of the
11Cygwin license. Please consult the file "CYGWIN_LICENSE" for
12details. */
13
94a23f48
CV
14#include <windows.h>
15#include <wininet.h>
16#include <lmaccess.h>
17#include <lmerr.h>
18#include <lmcons.h>
19#include <lmapibuf.h>
20
1fd5e000
CF
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24#include <unistd.h>
61522196 25#include <inttypes.h>
1fd5e000
CF
26#include <getopt.h>
27#include <pwd.h>
94a23f48 28#include <sys/cygwin.h>
92b499ac 29#include <cygwin/version.h>
1fd5e000
CF
30#include <sys/types.h>
31#include <time.h>
d8655020 32#include <errno.h>
35aeac58
CV
33#include <locale.h>
34#include <wchar.h>
1fd5e000 35
1fd5e000
CF
36#define USER_PRIV_ADMIN 2
37
f59faec4
CV
38static char *prog_name;
39
40static struct option longopts[] =
41{
1f4e5e15
CV
42 {"cannot-change", no_argument, NULL, 'c'},
43 {"can-change", no_argument, NULL, 'C'},
4fa0a398 44 {"logonserver", required_argument, NULL, 'd'},
1f4e5e15
CV
45 {"never-expires", no_argument, NULL, 'e'},
46 {"expires", no_argument, NULL, 'E'},
f59faec4
CV
47 {"help", no_argument, NULL, 'h' },
48 {"inactive", required_argument, NULL, 'i'},
49 {"lock", no_argument, NULL, 'l'},
50 {"minage", required_argument, NULL, 'n'},
1f4e5e15
CV
51 {"pwd-not-required", no_argument, NULL, 'p'},
52 {"pwd-required", no_argument, NULL, 'P'},
f59faec4 53 {"unlock", no_argument, NULL, 'u'},
92b499ac 54 {"version", no_argument, NULL, 'V'},
f59faec4
CV
55 {"maxage", required_argument, NULL, 'x'},
56 {"length", required_argument, NULL, 'L'},
57 {"status", no_argument, NULL, 'S'},
d8655020 58 { "reg-store-pwd", no_argument, NULL, 'R'},
f59faec4
CV
59 {NULL, 0, NULL, 0}
60};
61
a442c9cd 62static char opts[] = "cCd:eEhi:ln:pPuvVx:L:SR";
1fd5e000
CF
63
64int
65eprint (int with_name, const char *fmt, ...)
66{
67 va_list ap;
68
69 if (with_name)
f59faec4 70 fprintf(stderr, "%s: ", prog_name);
1fd5e000
CF
71 va_start (ap, fmt);
72 vfprintf (stderr, fmt, ap);
73 va_end (ap);
74 fprintf(stderr, "\n");
75 return 1;
76}
77
78int
79EvalRet (int ret, const char *user)
80{
81 switch (ret)
82 {
83 case NERR_Success:
84 return 0;
85
86 case ERROR_ACCESS_DENIED:
87 if (! user)
1b23b30b 88 eprint (0, "You may not change password expiry information.");
1fd5e000 89 else
1b23b30b 90 eprint (0, "You may not change the password for %s.", user);
1fd5e000
CF
91 break;
92
93 eprint (0, "Bad password: Invalid.");
94 break;
95
96 case NERR_PasswordTooShort:
97 eprint (0, "Bad password: Too short.");
98 break;
99
100 case NERR_UserNotFound:
101 eprint (1, "unknown user %s", user);
102 break;
103
104 case ERROR_INVALID_PASSWORD:
105 case NERR_BadPassword:
106 eprint (0, "Incorrect password for %s.", user);
107 eprint (0, "The password for %s is unchanged.", user);
108 break;
109
110 default:
111 eprint (1, "unrecoverable error %d", ret);
112 break;
113 }
114 return 1;
115}
116
117PUSER_INFO_3
4fa0a398 118GetPW (char *user, int print_win_name, LPCWSTR server)
1fd5e000 119{
94a23f48 120 char usr_buf[UNLEN + 1];
35aeac58 121 WCHAR name[UNLEN + 1];
1fd5e000
CF
122 DWORD ret;
123 PUSER_INFO_3 ui;
94a23f48
CV
124 struct passwd *pw;
125 char *domain = (char *) alloca (INTERNET_MAX_HOST_NAME_LENGTH + 1);
1b23b30b 126
94a23f48
CV
127 /* Try getting a Win32 username in case the user edited /etc/passwd */
128 if ((pw = getpwnam (user)))
129 {
130 cygwin_internal (CW_EXTRACT_DOMAIN_AND_USER, pw, domain, usr_buf);
131 if (strcasecmp (pw->pw_name, usr_buf))
132 {
133 /* Hack to avoid problem with LookupAccountSid after impersonation */
134 if (strcasecmp (usr_buf, "SYSTEM"))
135 {
136 user = usr_buf;
137 if (print_win_name)
138 printf ("Windows username : %s\n", user);
139 }
140 }
141 }
35aeac58 142 mbstowcs (name, user, UNLEN + 1);
4fa0a398 143 ret = NetUserGetInfo (server, name, 3, (void *) &ui);
1fd5e000
CF
144 return EvalRet (ret, user) ? NULL : ui;
145}
146
147int
4fa0a398
CV
148ChangePW (const char *user, const char *oldpwd, const char *pwd, int justcheck,
149 LPCWSTR server)
1fd5e000 150{
35aeac58 151 WCHAR name[UNLEN + 1], oldpass[512], pass[512];
1fd5e000
CF
152 DWORD ret;
153
35aeac58
CV
154 mbstowcs (name, user, UNLEN + 1);
155 mbstowcs (pass, pwd, 512);
1fd5e000
CF
156 if (! oldpwd)
157 {
158 USER_INFO_1003 ui;
159
160 ui.usri1003_password = pass;
4fa0a398 161 ret = NetUserSetInfo (server, name, 1003, (LPBYTE) &ui, NULL);
1fd5e000
CF
162 }
163 else
164 {
35aeac58 165 mbstowcs (oldpass, oldpwd, 512);
4fa0a398 166 ret = NetUserChangePassword (server, name, oldpass, pass);
1fd5e000 167 }
97832962
CV
168 if (justcheck && ret != ERROR_INVALID_PASSWORD)
169 return 0;
170 if (! EvalRet (ret, user) && ! justcheck)
1fd5e000
CF
171 {
172 eprint (0, "Password changed.");
173 }
174 return ret;
175}
176
177void
4fa0a398 178PrintPW (PUSER_INFO_3 ui, LPCWSTR server)
1fd5e000
CF
179{
180 time_t t = time (NULL) - ui->usri3_password_age;
181 int ret;
182 PUSER_MODALS_INFO_0 mi;
183
1f4e5e15 184 printf ("Account disabled : %s",
1b23b30b 185 (ui->usri3_flags & UF_ACCOUNTDISABLE) ? "yes\n" : "no\n");
02bd05e3 186 printf ("Password not required : %s",
1b23b30b 187 (ui->usri3_flags & UF_PASSWD_NOTREQD) ? "yes\n" : "no\n");
1f4e5e15 188 printf ("User can't change password : %s",
1b23b30b 189 (ui->usri3_flags & UF_PASSWD_CANT_CHANGE) ? "yes\n" : "no\n");
1f4e5e15 190 printf ("Password never expires : %s",
1b23b30b 191 (ui->usri3_flags & UF_DONT_EXPIRE_PASSWD) ? "yes\n" : "no\n");
1f4e5e15
CV
192 printf ("Password expired : %s",
193 (ui->usri3_password_expired) ? "yes\n" : "no\n");
194 printf ("Latest password change : %s", ctime(&t));
4fa0a398 195 ret = NetUserModalsGet (server, 0, (void *) &mi);
1fd5e000
CF
196 if (! ret)
197 {
1f4e5e15 198 if (mi->usrmod0_max_passwd_age == TIMEQ_FOREVER)
1b23b30b 199 mi->usrmod0_max_passwd_age = 0;
1f4e5e15 200 if (mi->usrmod0_min_passwd_age == TIMEQ_FOREVER)
1b23b30b 201 mi->usrmod0_min_passwd_age = 0;
1f4e5e15 202 if (mi->usrmod0_force_logoff == TIMEQ_FOREVER)
1b23b30b 203 mi->usrmod0_force_logoff = 0;
1fd5e000 204 if (ui->usri3_priv == USER_PRIV_ADMIN)
1b23b30b 205 mi->usrmod0_min_passwd_len = 0;
1f4e5e15 206 printf ("\nSystem password settings:\n");
61522196
CV
207 printf ("Max. password age %" PRIu32 " days\n",
208 (unsigned int) (mi->usrmod0_max_passwd_age / ONE_DAY));
209 printf ("Min. password age %" PRIu32 " days\n",
210 (unsigned int) (mi->usrmod0_min_passwd_age / ONE_DAY));
211 printf ("Force logout after %" PRIu32 " days\n",
212 (unsigned int) (mi->usrmod0_force_logoff / ONE_DAY));
213 printf ("Min. password length: %" PRIu32 "\n",
214 (unsigned int) mi->usrmod0_min_passwd_len);
1fd5e000
CF
215 }
216}
217
218int
4fa0a398 219SetModals (int xarg, int narg, int iarg, int Larg, LPCWSTR server)
1fd5e000
CF
220{
221 int ret;
222 PUSER_MODALS_INFO_0 mi;
223
4fa0a398 224 ret = NetUserModalsGet (server, 0, (void *) &mi);
1fd5e000
CF
225 if (! ret)
226 {
227 if (xarg == 0)
228 mi->usrmod0_max_passwd_age = TIMEQ_FOREVER;
229 else if (xarg > 0)
230 mi->usrmod0_max_passwd_age = xarg * ONE_DAY;
231
232 if (narg == 0)
233 {
234 mi->usrmod0_min_passwd_age = TIMEQ_FOREVER;
235 mi->usrmod0_password_hist_len = 0;
236 }
237 else if (narg > 0)
238 mi->usrmod0_min_passwd_age = narg * ONE_DAY;
239
240 if (iarg == 0)
241 mi->usrmod0_force_logoff = TIMEQ_FOREVER;
242 else if (iarg > 0)
243 mi->usrmod0_force_logoff = iarg * ONE_DAY;
244
245 if (Larg >= 0)
246 mi->usrmod0_min_passwd_len = Larg;
247
4fa0a398 248 ret = NetUserModalsSet (server, 0, (LPBYTE) mi, NULL);
1fd5e000
CF
249 NetApiBufferFree (mi);
250 }
251 return EvalRet (ret, NULL);
252}
253
1f4e5e15 254static void usage (FILE * stream, int status) __attribute__ ((noreturn));
f59faec4
CV
255static void
256usage (FILE * stream, int status)
1fd5e000 257{
f59faec4 258 fprintf (stream, ""
1f4e5e15 259 "Usage: %s [OPTION] [USER]\n"
92b499ac 260 "\n"
1f4e5e15 261 "Change USER's password or password attributes.\n"
f59faec4
CV
262 "\n"
263 "User operations:\n"
1f4e5e15
CV
264 " -l, --lock lock USER's account.\n"
265 " -u, --unlock unlock USER's account.\n"
266 " -c, --cannot-change USER can't change password.\n"
267 " -C, --can-change USER can change password.\n"
268 " -e, --never-expires USER's password never expires.\n"
269 " -E, --expires USER's password expires according to system's\n"
270 " password aging rule.\n"
271 " -p, --pwd-not-required no password required for USER.\n"
272 " -P, --pwd-required password is required for USER.\n"
d8655020
CV
273 " -R, --reg-store-pwd enter password to store it in the registry for\n"
274 " later usage by services to be able to switch\n"
275 " to this user context with network credentials.\n"
f59faec4
CV
276 "\n"
277 "System operations:\n"
1f4e5e15
CV
278 " -i, --inactive NUM set NUM of days before inactive accounts are disabled\n"
279 " (inactive accounts are those with expired passwords).\n"
280 " -n, --minage DAYS set system minimum password age to DAYS days.\n"
281 " -x, --maxage DAYS set system maximum password age to DAYS days.\n"
282 " -L, --length LEN set system minimum password length to LEN.\n"
f59faec4
CV
283 "\n"
284 "Other options:\n"
4fa0a398 285 " -d, --logonserver SERVER connect to SERVER (e.g. domain controller).\n"
6199f417
CV
286 " Default server is the local system, unless\n"
287 " changing the current user, in which case the\n"
288 " default is the content of $LOGONSERVER.\n"
1f4e5e15
CV
289 " -S, --status display password status for USER (locked, expired,\n"
290 " etc.) plus global system password settings.\n"
291 " -h, --help output usage information and exit.\n"
92b499ac 292 " -V, --version output version information and exit.\n"
1f4e5e15
CV
293 "\n"
294 "If no option is given, change USER's password. If no user name is given,\n"
295 "operate on current user. System operations must not be mixed with user\n"
d8655020
CV
296 "operations. Don't specify a USER when triggering a system operation.\n"
297 "\n"
298 "Don't specify a user or any other option together with the -R option.\n"
7ffaa17c
CV
299 "Non-Admin users can only store their password if cygserver is running\n"
300 "as service under the SYSTEM account.\n"
d8655020
CV
301 "Note that storing even obfuscated passwords in the registry is not overly\n"
302 "secure. Use this feature only if the machine is adequately locked down.\n"
303 "Don't use this feature if you don't need network access within a remote\n"
304 "session. You can delete your stored password by using `passwd -R' and\n"
92b499ac 305 "specifying an empty password.\n\n", prog_name);
f59faec4
CV
306 exit (status);
307}
308
0e0f5748
CV
309static int
310caller_is_admin ()
311{
312 static int is_admin = -1;
313 HANDLE token;
314 DWORD size;
315 PTOKEN_GROUPS grps;
316 SID_IDENTIFIER_AUTHORITY nt_auth = {SECURITY_NT_AUTHORITY};
1b23b30b 317 PSID admin_grp;
0e0f5748
CV
318 DWORD i;
319
320 if (is_admin == -1)
321 {
322 is_admin = 0;
323 if (OpenProcessToken (GetCurrentProcess (), TOKEN_READ, &token))
324 {
325 GetTokenInformation (token, TokenGroups, NULL, 0, &size);
326 grps = (PTOKEN_GROUPS) alloca (size);
327 if (!GetTokenInformation(token, TokenGroups, grps, size, &size)
328 || !AllocateAndInitializeSid (&nt_auth, 2,
329 SECURITY_BUILTIN_DOMAIN_RID,
330 DOMAIN_ALIAS_RID_ADMINS,
331 0, 0, 0, 0, 0, 0, &admin_grp))
332 is_admin = 0;
333 else
334 {
335 for (i = 0; i < grps->GroupCount; ++i)
336 if (EqualSid (admin_grp, grps->Groups[i].Sid)
337 && (grps->Groups[i].Attributes
338 & (SE_GROUP_ENABLED | SE_GROUP_USE_FOR_DENY_ONLY))
339 == SE_GROUP_ENABLED)
340 {
341 is_admin = 1;
342 break;
343 }
344 FreeSid (admin_grp);
345 }
346 CloseHandle (token);
347 }
348 }
349 return is_admin;
350}
351
f59faec4
CV
352static void
353print_version ()
354{
92b499ac 355 printf ("passwd (cygwin) %d.%d.%d\n"
1b23b30b
CF
356 "Password Utility\n"
357 "Copyright (C) 1999 - %s Red Hat, Inc.\n"
358 "This is free software; see the source for copying conditions. There is NO\n"
92b499ac 359 "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n",
1b23b30b
CF
360 CYGWIN_VERSION_DLL_MAJOR / 1000,
361 CYGWIN_VERSION_DLL_MAJOR % 1000,
362 CYGWIN_VERSION_DLL_MINOR,
363 strrchr (__DATE__, ' ') + 1);
1fd5e000
CF
364}
365
366int
367main (int argc, char **argv)
368{
92b499ac 369 char *logonserver;
d8655020 370 char user[UNLEN + 1], oldpwd[_PASSWORD_LEN + 1], newpwd[_PASSWORD_LEN + 1];
1fd5e000
CF
371 int ret = 0;
372 int cnt = 0;
35aeac58 373 int opt;
1fd5e000
CF
374 int Larg = -1;
375 int xarg = -1;
376 int narg = -1;
377 int iarg = -1;
378 int lopt = 0;
379 int uopt = 0;
1f4e5e15
CV
380 int copt = 0;
381 int Copt = 0;
382 int eopt = 0;
383 int Eopt = 0;
384 int popt = 0;
385 int Popt = 0;
1fd5e000 386 int Sopt = 0;
d8655020 387 int Ropt = 0;
0e0f5748
CV
388 PUSER_INFO_3 ui;
389 int myself = 0;
4fa0a398 390 LPWSTR server = NULL;
1fd5e000 391
92b499ac 392 prog_name = program_invocation_short_name;
1fd5e000 393
73535010
CV
394 /* Use locale from environment. If not set or set to "C", use UTF-8. */
395 setlocale (LC_CTYPE, "");
396 if (!strcmp (setlocale (LC_CTYPE, NULL), "C"))
397 setlocale (LC_CTYPE, "en_US.UTF-8");
f59faec4 398 while ((opt = getopt_long (argc, argv, opts, longopts, NULL)) != EOF)
1fd5e000
CF
399 switch (opt)
400 {
f59faec4
CV
401 case 'h':
402 usage (stdout, 0);
1b23b30b 403 break;
f59faec4
CV
404
405 case 'i':
d8655020 406 if (lopt || uopt || copt || Copt || eopt || Eopt || popt || Popt || Sopt || Ropt)
1f4e5e15 407 usage (stderr, 1);
f59faec4
CV
408 if ((iarg = atoi (optarg)) < 0 || iarg > 999)
409 return eprint (1, "Force logout time must be between 0 and 999.");
1b23b30b 410 break;
f59faec4
CV
411
412 case 'l':
d8655020 413 if (xarg >= 0 || narg >= 0 || iarg >= 0 || Larg >= 0 || uopt || Sopt || Ropt)
f59faec4
CV
414 usage (stderr, 1);
415 lopt = 1;
1b23b30b 416 break;
1fd5e000
CF
417
418 case 'n':
d8655020 419 if (lopt || uopt || copt || Copt || eopt || Eopt || popt || Popt || Sopt || Ropt)
1f4e5e15 420 usage (stderr, 1);
1fd5e000
CF
421 if ((narg = atoi (optarg)) < 0 || narg > 999)
422 return eprint (1, "Minimum password age must be between 0 and 999.");
423 if (xarg >= 0 && narg > xarg)
424 return eprint (1, "Minimum password age must be less than "
1b23b30b
CF
425 "maximum password age.");
426 break;
1fd5e000 427
f59faec4 428 case 'u':
d8655020 429 if (xarg >= 0 || narg >= 0 || iarg >= 0 || Larg >= 0 || lopt || Sopt || Ropt)
f59faec4
CV
430 usage (stderr, 1);
431 uopt = 1;
1b23b30b 432 break;
1fd5e000 433
1f4e5e15 434 case 'c':
d8655020 435 if (xarg >= 0 || narg >= 0 || iarg >= 0 || Larg >= 0 || Sopt || Ropt)
1f4e5e15
CV
436 usage (stderr, 1);
437 copt = 1;
1b23b30b 438 break;
1f4e5e15
CV
439
440 case 'C':
d8655020 441 if (xarg >= 0 || narg >= 0 || iarg >= 0 || Larg >= 0 || Sopt || Ropt)
1f4e5e15
CV
442 usage (stderr, 1);
443 Copt = 1;
1b23b30b 444 break;
1f4e5e15 445
4fa0a398 446 case 'd':
1b23b30b 447 {
d8655020
CV
448 if (Ropt)
449 usage (stderr, 1);
4fa0a398
CV
450 char *tmpbuf = alloca (strlen (optarg) + 3);
451 tmpbuf[0] = '\0';
452 if (*optarg != '\\')
453 strcpy (tmpbuf, "\\\\");
454 strcat (tmpbuf, optarg);
35aeac58
CV
455 size_t len = mbstowcs (NULL, tmpbuf, 0);
456 if (len > 0 && len != (size_t) -1)
457 mbstowcs (server = alloca ((len + 1) * sizeof (wchar_t)),
458 tmpbuf, len + 1);
4fa0a398
CV
459 }
460 break;
461
1f4e5e15 462 case 'e':
d8655020 463 if (xarg >= 0 || narg >= 0 || iarg >= 0 || Larg >= 0 || Sopt || Ropt)
1f4e5e15
CV
464 usage (stderr, 1);
465 eopt = 1;
1b23b30b 466 break;
1f4e5e15
CV
467
468 case 'E':
d8655020 469 if (xarg >= 0 || narg >= 0 || iarg >= 0 || Larg >= 0 || Sopt || Ropt)
1f4e5e15
CV
470 usage (stderr, 1);
471 Eopt = 1;
1b23b30b 472 break;
1f4e5e15
CV
473
474 case 'p':
d8655020 475 if (xarg >= 0 || narg >= 0 || iarg >= 0 || Larg >= 0 || Sopt || Ropt)
1f4e5e15
CV
476 usage (stderr, 1);
477 popt = 1;
1b23b30b 478 break;
1f4e5e15
CV
479
480 case 'P':
d8655020 481 if (xarg >= 0 || narg >= 0 || iarg >= 0 || Larg >= 0 || Sopt || Ropt)
1f4e5e15
CV
482 usage (stderr, 1);
483 Popt = 1;
1b23b30b 484 break;
1f4e5e15 485
92b499ac 486 case 'V':
a442c9cd
CV
487 case 'v': /* Keep this option for historrical reasons,
488 but don't advertize it. */
f59faec4 489 print_version ();
1b23b30b
CF
490 exit (0);
491 break;
1fd5e000 492
f59faec4 493 case 'x':
d8655020 494 if (lopt || uopt || copt || Copt || eopt || Eopt || popt || Popt || Sopt || Ropt)
1f4e5e15 495 usage (stderr, 1);
f59faec4
CV
496 if ((xarg = atoi (optarg)) < 0 || xarg > 999)
497 return eprint (1, "Maximum password age must be between 0 and 999.");
498 if (narg >= 0 && xarg < narg)
499 return eprint (1, "Maximum password age must be greater than "
1b23b30b
CF
500 "minimum password age.");
501 break;
1fd5e000 502
f59faec4 503 case 'L':
d8655020 504 if (lopt || uopt || copt || Copt || eopt || Eopt || popt || Popt || Sopt || Ropt)
1f4e5e15 505 usage (stderr, 1);
f59faec4
CV
506 if ((Larg = atoi (optarg)) < 0 || Larg > LM20_PWLEN)
507 return eprint (1, "Minimum password length must be between "
1b23b30b
CF
508 "0 and %d.", LM20_PWLEN);
509 break;
1fd5e000
CF
510
511 case 'S':
1f4e5e15 512 if (xarg >= 0 || narg >= 0 || iarg >= 0 || Larg >= 0 || lopt || uopt
d8655020 513 || copt || Copt || eopt || Eopt || popt || Popt || Ropt)
f59faec4 514 usage (stderr, 1);
1fd5e000 515 Sopt = 1;
1b23b30b 516 break;
1fd5e000 517
d8655020
CV
518 case 'R':
519 if (xarg >= 0 || narg >= 0 || iarg >= 0 || Larg >= 0 || lopt || uopt
520 || copt || Copt || eopt || Eopt || popt || Popt || Sopt
521 || server)
522 usage (stderr, 1);
523 Ropt = 1;
1b23b30b 524 break;
d8655020 525
1fd5e000 526 default:
1b23b30b 527 fprintf (stderr, "Try `%s --help' for more information.\n", prog_name);
92b499ac 528 return 1;
1fd5e000 529 }
4fa0a398 530
d8655020
CV
531 if (Ropt)
532 {
ff73fd1e 533 const char *username = NULL;
d8655020 534 if (optind < argc)
ff73fd1e
CV
535 {
536 username = argv[optind++];
537 if (!strcmp (username, getlogin ()))
538 username = NULL;
539 else if (!caller_is_admin ())
540 return eprint (0, "You may not change the password for %s.", user);
541
542 if (optind < argc)
543 usage (stderr, 1);
544 }
545 char *text1 = (char *) alloca ((username ? strlen (username) + 2 : 4)
546 + sizeof ("Enter current password: "));
547 char *text2 = (char *) alloca ((username ? strlen (username) + 2 : 4)
548 + sizeof ("Re-enter current password: "));
549 sprintf (text1, "Enter %s%s current password: ",
550 username ?: "your", username ? "'s" : "");
551 sprintf (text2, "Re-enter %s%s current password: ",
552 username ?: "your", username ? "'s" : "");
d8655020
CV
553 printf (
554"This functionality stores a password in the registry for usage by services\n"
555"which need to change the user context and require network access. Typical\n"
556"applications are interactive remote logons using sshd, cron task, etc.\n"
557"This password will always tried first when any privileged application is\n"
558"about to switch the user context.\n\n"
559"Note that storing even obfuscated passwords in the registry is not overly\n"
560"secure. Use this feature only if the machine is adequately locked down.\n"
561"Don't use this feature if you don't need network access within a remote\n"
8d12bd32 562"session.\n\n"
ff73fd1e
CV
563"You can delete the stored password by specifying an empty password.\n\n");
564 strcpy (newpwd, getpass (text1));
565 if (strcmp (newpwd, getpass (text2)))
1b23b30b 566 eprint (0, "Password is not identical.");
ff73fd1e 567 else if (cygwin_internal (CW_SET_PRIV_KEY, newpwd, username))
d8655020
CV
568 return eprint (0, "Storing password failed: %s", strerror (errno));
569 return 0;
570 }
571
1fd5e000
CF
572 if (Larg >= 0 || xarg >= 0 || narg >= 0 || iarg >= 0)
573 {
574 if (optind < argc)
1b23b30b 575 usage (stderr, 1);
4fa0a398 576 return SetModals (xarg, narg, iarg, Larg, server);
1fd5e000
CF
577 }
578
579 strcpy (user, optind >= argc ? getlogin () : argv[optind]);
580
0e0f5748 581 /* Changing password for calling user? Use logonserver for user as well. */
6199f417 582 if (!server && optind >= argc)
0e0f5748
CV
583 {
584 myself = 1;
585 if ((logonserver = getenv ("LOGONSERVER")))
586 {
587 size_t len = mbstowcs (NULL, logonserver, 0);
588 if (len > 0 && len != (size_t) -1)
589 mbstowcs (server = alloca ((len + 1) * sizeof (wchar_t)),
590 logonserver, len + 1);
591 }
592 }
1fd5e000 593
4fa0a398 594 ui = GetPW (user, 1, server);
1fd5e000
CF
595 if (! ui)
596 return 1;
597
1f4e5e15 598 if (lopt || uopt || copt || Copt || eopt || Eopt || popt || Popt || Sopt)
1fd5e000 599 {
02bd05e3
CV
600 USER_INFO_1008 uif;
601
02bd05e3 602 uif.usri1008_flags = ui->usri3_flags;
1fd5e000 603 if (lopt)
1b23b30b 604 {
1fd5e000 605 if (ui->usri3_priv == USER_PRIV_ADMIN)
94a23f48 606 return eprint (0, "Locking an admin account is disallowed.");
1b23b30b
CF
607 uif.usri1008_flags |= UF_ACCOUNTDISABLE;
608 }
1fd5e000 609 if (uopt)
1b23b30b 610 uif.usri1008_flags &= ~UF_ACCOUNTDISABLE;
1f4e5e15 611 if (copt)
1b23b30b 612 uif.usri1008_flags |= UF_PASSWD_CANT_CHANGE;
1f4e5e15 613 if (Copt)
1b23b30b 614 uif.usri1008_flags &= ~UF_PASSWD_CANT_CHANGE;
1f4e5e15 615 if (eopt)
1b23b30b 616 uif.usri1008_flags |= UF_DONT_EXPIRE_PASSWD;
1f4e5e15 617 if (Eopt)
1b23b30b 618 uif.usri1008_flags &= ~UF_DONT_EXPIRE_PASSWD;
1f4e5e15 619 if (popt)
1b23b30b 620 uif.usri1008_flags |= UF_PASSWD_NOTREQD;
1f4e5e15 621 if (Popt)
1b23b30b 622 uif.usri1008_flags &= ~UF_PASSWD_NOTREQD;
1f4e5e15
CV
623
624 if (lopt || uopt || copt || Copt || eopt || Eopt || popt || Popt)
1fd5e000 625 {
1b23b30b
CF
626 ret = NetUserSetInfo (server, ui->usri3_name, 1008, (LPBYTE) &uif,
627 NULL);
628 return EvalRet (ret, NULL);
1fd5e000
CF
629 }
630 // Sopt
4fa0a398 631 PrintPW (ui, server);
1fd5e000
CF
632 return 0;
633 }
634
0e0f5748 635 if (!caller_is_admin () && !myself)
1fd5e000
CF
636 return eprint (0, "You may not change the password for %s.", user);
637
638 eprint (0, "Enter the new password (minimum of 5, maximum of 8 characters).");
639 eprint (0, "Please use a combination of upper and lower case letters and numbers.");
640
deb2b467 641 oldpwd[0] = '\0';
0e0f5748 642 if (!caller_is_admin ())
1fd5e000
CF
643 {
644 strcpy (oldpwd, getpass ("Old password: "));
4fa0a398 645 if (ChangePW (user, oldpwd, oldpwd, 1, server))
1b23b30b 646 return 1;
1fd5e000
CF
647 }
648
649 do
650 {
651 strcpy (newpwd, getpass ("New password: "));
652 if (strcmp (newpwd, getpass ("Re-enter new password: ")))
1b23b30b 653 eprint (0, "Password is not identical.");
4fa0a398 654 else if (! ChangePW (user, *oldpwd ? oldpwd : NULL, newpwd, 0, server))
1b23b30b 655 ret = 1;
1fd5e000 656 if (! ret && cnt < 2)
1b23b30b 657 eprint (0, "Try again.");
1fd5e000
CF
658 }
659 while (! ret && ++cnt < 3);
660 return ! ret;
661}
This page took 0.332617 seconds and 5 git commands to generate.