summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2014-05-15 11:16:28 +0000
committerCorinna Vinschen <corinna@vinschen.de>2014-05-15 11:16:28 +0000
commit076a61f0d9bf60c6063b1569004c1daa24f9aa0c (patch)
treebc712d6210cd97372cd32711b4733920b663565e
parentb9ee0bb0786b270726aad94d40ed602b807ba576 (diff)
downloadcygnal-076a61f0d9bf60c6063b1569004c1daa24f9aa0c.tar.gz
cygnal-076a61f0d9bf60c6063b1569004c1daa24f9aa0c.tar.bz2
cygnal-076a61f0d9bf60c6063b1569004c1daa24f9aa0c.zip
* 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.
-rw-r--r--winsup/cygwin/ChangeLog7
-rw-r--r--winsup/cygwin/external.cc55
-rw-r--r--winsup/cygwin/include/sys/cygwin.h4
3 files changed, 65 insertions, 1 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index eb6e6589a..3eeb6ceae 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,10 @@
+2014-05-15 Corinna Vinschen <corinna@vinschen.de>
+
+ * 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.
+
2014-05-14 Corinna Vinschen <corinna@vinschen.de>
* sec_auth.cc (get_server_groups): Call get_logon_server only for
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);
}
diff --git a/winsup/cygwin/include/sys/cygwin.h b/winsup/cygwin/include/sys/cygwin.h
index 17fa12d43..7e344ecab 100644
--- a/winsup/cygwin/include/sys/cygwin.h
+++ b/winsup/cygwin/include/sys/cygwin.h
@@ -149,7 +149,8 @@ typedef enum
CW_ENDENT,
CW_GETNSSSEP,
CW_GETPWSID,
- CW_GETGRSID
+ CW_GETGRSID,
+ CW_CYGNAME_FROM_WINNAME
} cygwin_getinfo_types;
#define CW_LOCK_PINFO CW_LOCK_PINFO
@@ -206,6 +207,7 @@ typedef enum
#define CW_GETNSSSEP CW_GETNSSSEP
#define CW_GETPWSID CW_GETPWSID
#define CW_GETGRSID CW_GETGRSID
+#define CW_CYGNAME_FROM_WINNAME CW_CYGNAME_FROM_WINNAME
/* Token type for CW_SET_EXTERNAL_TOKEN */
enum