Fix passwd getting error 1265 when running on newer Windows
On Windows 8.1 and later, the NetUserChangePassword call apparently doesn't accept the usual "\\server" string anymore, but requires to use the "domain" instead, otherwise it emits en error code 1265, ERROR_DOWNGRADE_DETECTED. Since this is accepted by pre-8.1 as well, use the domain indiscriminately when calling NetUserChangePassword from passwd(1). While at it, do some minor cleanup in passwd.c. Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
parent
abd37f0c79
commit
472e5439e7
|
@ -84,3 +84,6 @@ Bug Fixes
|
||||||
|
|
||||||
- Fix off_t typedef on 64-bit.
|
- Fix off_t typedef on 64-bit.
|
||||||
Addresses: https://sourceware.org/ml/newlib/2016/msg01028.html
|
Addresses: https://sourceware.org/ml/newlib/2016/msg01028.html
|
||||||
|
|
||||||
|
- Fix weird problem running passwd on newer Windows versions.
|
||||||
|
Addresses: https://cygwin.com/ml/cygwin/2016-08/msg00608.html
|
||||||
|
|
|
@ -113,57 +113,57 @@ EvalRet (int ret, const char *user)
|
||||||
}
|
}
|
||||||
|
|
||||||
PUSER_INFO_3
|
PUSER_INFO_3
|
||||||
GetPW (char *user, int print_win_name, LPWSTR *server)
|
GetPW (char *user, int print_win_name, LPWSTR *server, LPWSTR domain)
|
||||||
{
|
{
|
||||||
char usr_buf[UNLEN + 1];
|
char usr_buf[UNLEN + 1];
|
||||||
WCHAR name[UNLEN + 1];
|
WCHAR name[UNLEN + 1];
|
||||||
DWORD ret;
|
DWORD ret;
|
||||||
PUSER_INFO_3 ui;
|
PUSER_INFO_3 ui;
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
char *domain = (char *) alloca (INTERNET_MAX_HOST_NAME_LENGTH + 1);
|
char dom[INTERNET_MAX_HOST_NAME_LENGTH + 1];
|
||||||
|
|
||||||
/* Get the Win32 username and a suitable server. */
|
/* Get the Win32 username and a suitable server. */
|
||||||
if ((pw = getpwnam (user)))
|
pw = getpwnam (user);
|
||||||
|
if (!pw)
|
||||||
{
|
{
|
||||||
cygwin_internal (CW_EXTRACT_DOMAIN_AND_USER, pw, domain, usr_buf);
|
EvalRet (NERR_UserNotFound, user);
|
||||||
if (strcasecmp (pw->pw_name, usr_buf))
|
return NULL;
|
||||||
{
|
}
|
||||||
/* Hack to avoid problem with LookupAccountSid after impersonation */
|
|
||||||
if (strcasecmp (usr_buf, "SYSTEM"))
|
|
||||||
{
|
|
||||||
user = usr_buf;
|
|
||||||
if (print_win_name)
|
|
||||||
printf ("Windows username : %s\n", user);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!*server)
|
|
||||||
{
|
|
||||||
PDOMAIN_CONTROLLER_INFOW dci;
|
|
||||||
char machine[INTERNET_MAX_HOST_NAME_LENGTH + 1];
|
|
||||||
DWORD mlen = sizeof machine;
|
|
||||||
WCHAR wdom[INTERNET_MAX_HOST_NAME_LENGTH + 1];
|
|
||||||
|
|
||||||
/* If we can't fetch the local machine name, or if the machine name
|
cygwin_internal (CW_EXTRACT_DOMAIN_AND_USER, pw, dom, usr_buf);
|
||||||
is not the same as the user's domain name, try to fetch the DC via
|
/* Hack to avoid problem with LookupAccountSid after impersonation
|
||||||
DsGetDcName. Otherwise, just stick to a NULL servername, since
|
using the simple NtCreateToken method. */
|
||||||
that's the same as using the local machine. */
|
if (strcasecmp (pw->pw_name, usr_buf) && strcasecmp (usr_buf, "SYSTEM"))
|
||||||
if (!GetComputerNameExA (ComputerNameNetBIOS, machine, &mlen)
|
{
|
||||||
|| strcasecmp (domain, machine) != 0)
|
user = usr_buf;
|
||||||
{
|
if (print_win_name)
|
||||||
mbstowcs (wdom, domain, INTERNET_MAX_HOST_NAME_LENGTH + 1);
|
printf ("Windows username : %s\n", user);
|
||||||
if (!DsGetDcNameW (NULL, wdom, NULL, NULL, DS_IS_FLAT_NAME, &dci))
|
|
||||||
*server = dci->DomainControllerName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
mbstowcs (name, user, UNLEN + 1);
|
mbstowcs (name, user, UNLEN + 1);
|
||||||
|
mbstowcs (domain, dom, INTERNET_MAX_HOST_NAME_LENGTH + 1);
|
||||||
|
if (!*server)
|
||||||
|
{
|
||||||
|
PDOMAIN_CONTROLLER_INFOW dci;
|
||||||
|
WCHAR machine[INTERNET_MAX_HOST_NAME_LENGTH + 1];
|
||||||
|
DWORD mlen = INTERNET_MAX_HOST_NAME_LENGTH + 1;
|
||||||
|
|
||||||
|
/* If the machine name is not the same as the user's domain name we're
|
||||||
|
in a domain. Fetch the DC via DsGetDcName. Otherwise, just stick
|
||||||
|
to a NULL servername, since that's the same as using the local
|
||||||
|
machine. */
|
||||||
|
if ((!GetComputerNameExW (ComputerNameNetBIOS, machine, &mlen)
|
||||||
|
|| wcscasecmp (domain, machine) != 0)
|
||||||
|
&& !DsGetDcNameW (NULL, domain, NULL, NULL, DS_IS_FLAT_NAME, &dci))
|
||||||
|
*server = dci->DomainControllerName;
|
||||||
|
}
|
||||||
|
|
||||||
ret = NetUserGetInfo (*server, name, 3, (void *) &ui);
|
ret = NetUserGetInfo (*server, name, 3, (void *) &ui);
|
||||||
return EvalRet (ret, user) ? NULL : ui;
|
return EvalRet (ret, user) ? NULL : ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ChangePW (const char *user, PCWSTR name, const char *oldpwd, const char *pwd,
|
ChangePW (const char *user, PCWSTR domain, PCWSTR name, const char *oldpwd,
|
||||||
int justcheck, LPCWSTR server)
|
const char *pwd, int justcheck, PCWSTR server)
|
||||||
{
|
{
|
||||||
WCHAR oldpass[512], pass[512];
|
WCHAR oldpass[512], pass[512];
|
||||||
DWORD ret;
|
DWORD ret;
|
||||||
|
@ -179,7 +179,11 @@ ChangePW (const char *user, PCWSTR name, const char *oldpwd, const char *pwd,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mbstowcs (oldpass, oldpwd, 512);
|
mbstowcs (oldpass, oldpwd, 512);
|
||||||
ret = NetUserChangePassword (server, name, oldpass, pass);
|
/* NetUserChangePassword has changed between W7 and W8.1. For some
|
||||||
|
reason it doesn't accept the usual "\\server" servername anymore,
|
||||||
|
rather you have to use the domain name as server parameter, otherwise
|
||||||
|
you suffer an error 1265, ERROR_DOWNGRADE_DETECTED. */
|
||||||
|
ret = NetUserChangePassword (domain, name, oldpass, pass);
|
||||||
}
|
}
|
||||||
if (justcheck && ret != ERROR_INVALID_PASSWORD)
|
if (justcheck && ret != ERROR_INVALID_PASSWORD)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -189,7 +193,7 @@ ChangePW (const char *user, PCWSTR name, const char *oldpwd, const char *pwd,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PrintPW (PUSER_INFO_3 ui, LPCWSTR server)
|
PrintPW (PUSER_INFO_3 ui, PCWSTR server)
|
||||||
{
|
{
|
||||||
time_t t = time (NULL) - ui->usri3_password_age;
|
time_t t = time (NULL) - ui->usri3_password_age;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -230,7 +234,7 @@ PrintPW (PUSER_INFO_3 ui, LPCWSTR server)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
SetModals (int xarg, int narg, int iarg, int Larg, LPCWSTR server)
|
SetModals (int xarg, int narg, int iarg, int Larg, PCWSTR server)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
PUSER_MODALS_INFO_0 mi;
|
PUSER_MODALS_INFO_0 mi;
|
||||||
|
@ -379,7 +383,9 @@ int
|
||||||
main (int argc, char **argv)
|
main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
char *logonserver;
|
char *logonserver;
|
||||||
char user[UNLEN + 1], oldpwd[_PASSWORD_LEN + 1], newpwd[_PASSWORD_LEN + 1];
|
char user[UNLEN + 1];
|
||||||
|
WCHAR domain[INTERNET_MAX_HOST_NAME_LENGTH + 1];
|
||||||
|
char oldpwd[_PASSWORD_LEN + 1], newpwd[_PASSWORD_LEN + 1];
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
int opt;
|
int opt;
|
||||||
|
@ -604,7 +610,7 @@ main (int argc, char **argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ui = GetPW (user, 1, &server);
|
ui = GetPW (user, 1, &server, domain);
|
||||||
if (!ui)
|
if (!ui)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
@ -652,7 +658,7 @@ main (int argc, char **argv)
|
||||||
if (!caller_is_admin ())
|
if (!caller_is_admin ())
|
||||||
{
|
{
|
||||||
strcpy (oldpwd, getpass ("Old password: "));
|
strcpy (oldpwd, getpass ("Old password: "));
|
||||||
if (ChangePW (user, ui->usri3_name, oldpwd, oldpwd, 1, server))
|
if (ChangePW (user, domain, ui->usri3_name, oldpwd, oldpwd, 1, server))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -661,8 +667,8 @@ main (int argc, char **argv)
|
||||||
strcpy (newpwd, getpass ("New password: "));
|
strcpy (newpwd, getpass ("New password: "));
|
||||||
if (strcmp (newpwd, getpass ("Re-enter new password: ")))
|
if (strcmp (newpwd, getpass ("Re-enter new password: ")))
|
||||||
eprint (0, "Password is not identical.");
|
eprint (0, "Password is not identical.");
|
||||||
else if (!ChangePW (user, ui->usri3_name, *oldpwd ? oldpwd : NULL,
|
else if (!ChangePW (user, domain, ui->usri3_name,
|
||||||
newpwd, 0, server))
|
*oldpwd ? oldpwd : NULL, newpwd, 0, server))
|
||||||
ret = 1;
|
ret = 1;
|
||||||
if (!ret && cnt < 2)
|
if (!ret && cnt < 2)
|
||||||
eprint (0, "Try again.");
|
eprint (0, "Try again.");
|
||||||
|
|
Loading…
Reference in New Issue