diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2009-03-23 16:37:49 +0000 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2009-03-23 16:37:49 +0000 |
commit | 0e0f5748e0aaeb910dc074bed7fa3509897e982a (patch) | |
tree | 09dcb80e9c73dc235e37107a3e5db9e1ae1ababb /winsup/utils | |
parent | 7d2e8c04f21294840159ca8f7393eb713487f8a4 (diff) | |
download | cygnal-0e0f5748e0aaeb910dc074bed7fa3509897e982a.tar.gz cygnal-0e0f5748e0aaeb910dc074bed7fa3509897e982a.tar.bz2 cygnal-0e0f5748e0aaeb910dc074bed7fa3509897e982a.zip |
* passwd.c (caller_is_admin): New function to test if calling user
is an administrator by inspecting user token.
(main): Drop fetching caller info from logonserver. Only fetch
server from environment when trying to change password for own
account. Drop admin check entirely in case of doing account
maintainance. Otherwise replace check for admin by result of
caller_is_admin call.
Diffstat (limited to 'winsup/utils')
-rw-r--r-- | winsup/utils/ChangeLog | 10 | ||||
-rw-r--r-- | winsup/utils/passwd.c | 78 |
2 files changed, 69 insertions, 19 deletions
diff --git a/winsup/utils/ChangeLog b/winsup/utils/ChangeLog index 2dc2c2349..31b18e5e0 100644 --- a/winsup/utils/ChangeLog +++ b/winsup/utils/ChangeLog @@ -1,3 +1,13 @@ +2009-03-23 Corinna Vinschen <corinna@vinschen.de> + + * passwd.c (caller_is_admin): New function to test if calling user + is an administrator by inspecting user token. + (main): Drop fetching caller info from logonserver. Only fetch + server from environment when trying to change password for own + account. Drop admin check entirely in case of doing account + maintainance. Otherwise replace check for admin by result of + caller_is_admin call. + 2009-03-22 Corinna Vinschen <corinna@vinschen.de> * passwd.c (main): Always get logonserver from environment and diff --git a/winsup/utils/passwd.c b/winsup/utils/passwd.c index 1f04fb63c..3616848ab 100644 --- a/winsup/utils/passwd.c +++ b/winsup/utils/passwd.c @@ -303,6 +303,49 @@ usage (FILE * stream, int status) exit (status); } +static int +caller_is_admin () +{ + static int is_admin = -1; + HANDLE token; + DWORD size; + PTOKEN_GROUPS grps; + SID_IDENTIFIER_AUTHORITY nt_auth = {SECURITY_NT_AUTHORITY}; + PSID admin_grp; + DWORD i; + + if (is_admin == -1) + { + is_admin = 0; + if (OpenProcessToken (GetCurrentProcess (), TOKEN_READ, &token)) + { + GetTokenInformation (token, TokenGroups, NULL, 0, &size); + grps = (PTOKEN_GROUPS) alloca (size); + if (!GetTokenInformation(token, TokenGroups, grps, size, &size) + || !AllocateAndInitializeSid (&nt_auth, 2, + SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, + 0, 0, 0, 0, 0, 0, &admin_grp)) + is_admin = 0; + else + { + for (i = 0; i < grps->GroupCount; ++i) + if (EqualSid (admin_grp, grps->Groups[i].Sid) + && (grps->Groups[i].Attributes + & (SE_GROUP_ENABLED | SE_GROUP_USE_FOR_DENY_ONLY)) + == SE_GROUP_ENABLED) + { + is_admin = 1; + break; + } + FreeSid (admin_grp); + } + CloseHandle (token); + } + } + return is_admin; +} + static void print_version () { @@ -348,8 +391,8 @@ main (int argc, char **argv) int Popt = 0; int Sopt = 0; int Ropt = 0; - PUSER_INFO_3 ui, li; - LPWSTR my_server = NULL; + PUSER_INFO_3 ui; + int myself = 0; LPWSTR server = NULL; prog_name = strrchr (argv[0], '/'); @@ -518,16 +561,6 @@ main (int argc, char **argv) return 0; } - if ((logonserver = getenv ("LOGONSERVER"))) - { - size_t len = mbstowcs (NULL, logonserver, 0); - if (len > 0 && len != (size_t) -1) - mbstowcs (my_server = alloca ((len + 1) * sizeof (wchar_t)), - logonserver, len + 1); - if (!server) - server = my_server; - } - if (Larg >= 0 || xarg >= 0 || narg >= 0 || iarg >= 0) { if (optind < argc) @@ -537,9 +570,18 @@ main (int argc, char **argv) strcpy (user, optind >= argc ? getlogin () : argv[optind]); - li = GetPW (getlogin (), 0, my_server); - if (! li) - return 1; + /* Changing password for calling user? Use logonserver for user as well. */ + if (!server && optind < argc) + { + myself = 1; + if ((logonserver = getenv ("LOGONSERVER"))) + { + size_t len = mbstowcs (NULL, logonserver, 0); + if (len > 0 && len != (size_t) -1) + mbstowcs (server = alloca ((len + 1) * sizeof (wchar_t)), + logonserver, len + 1); + } + } ui = GetPW (user, 1, server); if (! ui) @@ -549,8 +591,6 @@ main (int argc, char **argv) { USER_INFO_1008 uif; - if (li->usri3_priv != USER_PRIV_ADMIN) - return eprint (0, "You have no maintenance privileges."); uif.usri1008_flags = ui->usri3_flags; if (lopt) { @@ -584,14 +624,14 @@ main (int argc, char **argv) return 0; } - if (li->usri3_priv != USER_PRIV_ADMIN && strcmp (getlogin (), user)) + if (!caller_is_admin () && !myself) return eprint (0, "You may not change the password for %s.", user); eprint (0, "Enter the new password (minimum of 5, maximum of 8 characters)."); eprint (0, "Please use a combination of upper and lower case letters and numbers."); oldpwd[0] = '\0'; - if (li->usri3_priv != USER_PRIV_ADMIN) + if (!caller_is_admin ()) { strcpy (oldpwd, getpass ("Old password: ")); if (ChangePW (user, oldpwd, oldpwd, 1, server)) |