diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2014-05-15 15:16:28 +0400 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2014-05-15 15:16:28 +0400 |
commit | 076a61f0d9bf60c6063b1569004c1daa24f9aa0c (patch) | |
tree | bc712d6210cd97372cd32711b4733920b663565e /winsup/cygwin/external.cc | |
parent | b9ee0bb0786b270726aad94d40ed602b807ba576 (diff) |
* external.cc (cygwin_internal): Implement CW_CYGNAME_FROM_WINNAME.
Add lengthy comment to explain what we do and why.
* include/sys/cygwin.h (cygwin_getinfo_types): Add
CW_CYGNAME_FROM_WINNAME.
Diffstat (limited to 'winsup/cygwin/external.cc')
-rw-r--r-- | winsup/cygwin/external.cc | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/winsup/cygwin/external.cc b/winsup/cygwin/external.cc index 8eec5b1db..4480375be 100644 --- a/winsup/cygwin/external.cc +++ b/winsup/cygwin/external.cc @@ -619,6 +619,61 @@ cygwin_internal (cygwin_getinfo_types t, ...) } break; + case CW_CYGNAME_FROM_WINNAME: + { + /* This functionality has been added mainly for sshd. Sshd + calls getpwnam() with the username of the non-privileged + user used for privilege separation. This is usually a + fixed string "sshd". However, when using usernames from + the Windows DBs, it's no safe bet anymore if the username + is "sshd", it could also be "DOMAIN+sshd". So what we do + here is this: + + Sshd calls cygwin_internal (CW_CYGNAME_FROM_WINNAME, + "sshd", + username_buffer, + sizeof username_buffer); + + If this call succeeds, sshd expects the correct Cygwin + username of the unprivileged sshd account in username_buffer. + + The below code checks for a Windows username matching the + incoming username, and then fetches the Cygwin username with + the matching SID. This is our username used for privsep then. + + Of course, other applications with similar needs can use the + same method. */ + const char *winname = va_arg (arg, const char *); + char *buffer = va_arg (arg, char *); + size_t buflen = va_arg (arg, size_t); + + if (!winname || !buffer || !buflen) + break; + + PWCHAR name; + if (!sys_mbstowcs_alloc (&name, HEAP_BUF, winname)) + break; + + cygsid sid; + DWORD slen = SECURITY_MAX_SID_SIZE; + WCHAR dom[DNLEN + 1]; + DWORD dlen = DNLEN + 1; + SID_NAME_USE acc_type; + + if (!LookupAccountNameW (NULL, name, sid, &slen, dom, &dlen, + &acc_type)) + break; + + struct passwd *pw = internal_getpwsid (sid); + if (!pw) + break; + + buffer[0] = '\0'; + strncat (buffer, pw->pw_name, buflen - 1); + res = 0; + } + break; + default: set_errno (ENOSYS); } |