* 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.
This commit is contained in:
Corinna Vinschen
2014-05-15 11:16:28 +00:00
parent b9ee0bb078
commit 076a61f0d9
3 changed files with 65 additions and 1 deletions

View File

@ -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);
}