* 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:
		| @@ -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); | ||||
|     } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user