aboutsummaryrefslogtreecommitdiff
path: root/winsup
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2000-06-16 19:36:07 +0000
committerCorinna Vinschen <corinna@vinschen.de>2000-06-16 19:36:07 +0000
commit64b3062937b791faafddc02e9d38102a75b37a7a (patch)
tree48895becfe9d6a9816a99573c1dd716878d67fa4 /winsup
parent3875d9e65223107ecc5ee8ce7f6510e092779da9 (diff)
downloadnewlib-64b3062937b791faafddc02e9d38102a75b37a7a.zip
newlib-64b3062937b791faafddc02e9d38102a75b37a7a.tar.gz
newlib-64b3062937b791faafddc02e9d38102a75b37a7a.tar.bz2
* cygwin.din: Define symbols for `cygwin_logon_user' and
`cygwin_set_impersonation_token'. * dcrt0.cc (dll_crt0_1): Eliminate superfluous conditional statements. Add load statements for `ImpersonateLoggedOnUser', `LogonUserA' and `RevertToSelf'. * fork.cc (fork): Care for correct impersonation of parent and child process. * security.cc (cygwin_set_impersonation_token): New function. (cygwin_logon_user): Ditto. shared.h (class pinfo): New members `orig_uid', `orig_gid', `real_uid' nad `real_gid'. spawn.cc (spawn_guts): Care for impersonation when starting child process in a different user context. * syscalls.cc (setgid): Call `setegid' now. Set real_gid. (setuid): Call `seteuid' now. Set real_uid. (seteuid): Functionality moved from setuid to here. Care for correct impersonation. (setegid): Functionality moved from setgid to here. * uinfo.cc (uinfo_init): Initialization of additional pinfo members. (getuid): Return real uid. (getgid): Return real gid. (geteuid): Return effective uid. (getegid): Return effective gid. include/sys/cygwin.h: Add prototypes for `cygwin_logon_user' and `cygwin_set_impersonation_token'. include/cygwin/version.h: Bumb API minor version to 22.
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/ChangeLog31
-rw-r--r--winsup/cygwin/cygwin.din2
-rw-r--r--winsup/cygwin/dcrt0.cc8
-rw-r--r--winsup/cygwin/fork.cc34
-rw-r--r--winsup/cygwin/include/cygwin/version.h7
-rw-r--r--winsup/cygwin/include/sys/cygwin.h3
-rw-r--r--winsup/cygwin/security.cc67
-rw-r--r--winsup/cygwin/shared.h9
-rw-r--r--winsup/cygwin/spawn.cc11
-rw-r--r--winsup/cygwin/syscalls.cc84
-rw-r--r--winsup/cygwin/uinfo.cc13
11 files changed, 233 insertions, 36 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index a9e3980..3324b61 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,34 @@
+Thu Jun 16 20:55:00 2000 Corinna Vinschen <corinna@vinschen.de>
+
+ * cygwin.din: Define symbols for `cygwin_logon_user' and
+ `cygwin_set_impersonation_token'.
+ * dcrt0.cc (dll_crt0_1): Eliminate superfluous conditional
+ statements.
+ Add load statements for `ImpersonateLoggedOnUser', `LogonUserA'
+ and `RevertToSelf'.
+ * fork.cc (fork): Care for correct impersonation of parent
+ and child process.
+ * security.cc (cygwin_set_impersonation_token): New function.
+ (cygwin_logon_user): Ditto.
+ shared.h (class pinfo): New members `orig_uid', `orig_gid',
+ `real_uid' nad `real_gid'.
+ spawn.cc (spawn_guts): Care for impersonation when starting
+ child process in a different user context.
+ * syscalls.cc (setgid): Call `setegid' now. Set real_gid.
+ (setuid): Call `seteuid' now. Set real_uid.
+ (seteuid): Functionality moved from setuid to here. Care for
+ correct impersonation.
+ (setegid): Functionality moved from setgid to here.
+ * uinfo.cc (uinfo_init): Initialization of additional pinfo
+ members.
+ (getuid): Return real uid.
+ (getgid): Return real gid.
+ (geteuid): Return effective uid.
+ (getegid): Return effective gid.
+ include/sys/cygwin.h: Add prototypes for `cygwin_logon_user' and
+ `cygwin_set_impersonation_token'.
+ include/cygwin/version.h: Bumb API minor version to 22.
+
Thu Jun 15 18:12:36 2000 Christopher Faylor <cgf@cygnus.com>
* path.cc (chdir): Don't set cache to offending chdir. Change comment
diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din
index a8c0006..84f7519 100644
--- a/winsup/cygwin/cygwin.din
+++ b/winsup/cygwin/cygwin.din
@@ -988,6 +988,8 @@ cygwin32_posix_to_win32_path_list = cygwin_posix_to_win32_path_list
cygwin32_split_path = cygwin_split_path
cygwin_winpid_to_pid
cygwin32_winpid_to_pid = cygwin_winpid_to_pid
+cygwin_logon_user
+cygwin_set_impersonation_token
realpath
reent_data DATA
getenv
diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc
index 4b87905..302207c 100644
--- a/winsup/cygwin/dcrt0.cc
+++ b/winsup/cygwin/dcrt0.cc
@@ -763,10 +763,9 @@ dll_crt0_1 ()
/* Flush signals and ensure that signal thread is up and running. Can't
do this for noncygwin case since the signal thread is blocked due to
LoadLibrary serialization. */
- if (!dynamically_loaded)
- sig_send (NULL, __SIGFLUSH); /* also initializes uid, gid */
+ sig_send (NULL, __SIGFLUSH); /* also initializes uid, gid */
- if (user_data->main && !dynamically_loaded)
+ if (user_data->main)
exit (user_data->main (argc, argv, *user_data->envptr));
}
@@ -1157,10 +1156,12 @@ LoadDLLfunc (GetSidSubAuthority, 8, advapi32)
LoadDLLfunc (GetSidSubAuthorityCount, 4, advapi32)
LoadDLLfunc (GetTokenInformation, 20, advapi32)
LoadDLLfunc (GetUserNameA, 8, advapi32)
+LoadDLLfunc (ImpersonateLoggedOnUser, 4, advapi32)
LoadDLLfunc (InitializeAcl, 12, advapi32)
LoadDLLfunc (InitializeSecurityDescriptor, 8, advapi32)
LoadDLLfunc (InitializeSid, 12, advapi32)
LoadDLLfunc (IsValidSid, 4, advapi32)
+LoadDLLfunc (LogonUserA, 24, advapi32)
LoadDLLfunc (LookupAccountNameA, 28, advapi32)
LoadDLLfunc (LookupAccountSidA, 28, advapi32)
LoadDLLfunc (LookupPrivilegeValueA, 12, advapi32)
@@ -1175,6 +1176,7 @@ LoadDLLfunc (RegQueryValueExA, 24, advapi32)
LoadDLLfunc (RegSetValueExA, 24, advapi32)
LoadDLLfunc (RegisterEventSourceA, 8, advapi32)
LoadDLLfunc (ReportEventA, 36, advapi32)
+LoadDLLfunc (RevertToSelf, 0, advapi32)
LoadDLLfunc (SetKernelObjectSecurity, 12, advapi32)
LoadDLLfunc (SetSecurityDescriptorDacl, 16, advapi32)
LoadDLLfunc (SetSecurityDescriptorGroup, 12, advapi32)
diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc
index baa5a95..b024802 100644
--- a/winsup/cygwin/fork.cc
+++ b/winsup/cygwin/fork.cc
@@ -363,10 +363,16 @@ fork ()
goto cleanup;
}
+ /* Remove impersonation */
+ uid_t uid = geteuid();
+ if (myself->impersonated && myself->token != INVALID_HANDLE_VALUE)
+ seteuid (myself->orig_uid);
+
+ char sa_buf[1024];
rc = CreateProcessA (myself->progname, /* image to run */
myself->progname, /* what we send in arg0 */
- &sec_none_nih, /* process security attrs */
- &sec_none_nih, /* thread security attrs */
+ allow_ntsec ? sec_user (sa_buf) : &sec_none_nih,
+ allow_ntsec ? sec_user (sa_buf) : &sec_none_nih,
TRUE, /* inherit handles from parent */
c_flags,
NULL, /* environment filled in later */
@@ -384,9 +390,16 @@ fork ()
ForceCloseHandle(subproc_ready);
ForceCloseHandle(forker_finished);
subproc_ready = forker_finished = NULL;
+ /* Restore impersonation */
+ if (myself->impersonated && myself->token != INVALID_HANDLE_VALUE)
+ seteuid (uid);
return -1;
}
+ /* Restore impersonation */
+ if (myself->impersonated && myself->token != INVALID_HANDLE_VALUE)
+ seteuid (uid);
+
ProtectHandle (pi.hThread);
/* Protect the handle but name it similarly to the way it will
be called in subproc handling. */
@@ -410,6 +423,12 @@ fork ()
memcpy (child->sidbuf, myself->sidbuf, 40);
memcpy (child->logsrv, myself->logsrv, 256);
memcpy (child->domain, myself->domain, MAX_COMPUTERNAME_LENGTH+1);
+ child->token = myself->token;
+ child->impersonated = myself->impersonated;
+ child->orig_uid = myself->orig_uid;
+ child->orig_gid = myself->orig_gid;
+ child->real_uid = myself->real_uid;
+ child->real_gid = myself->real_gid;
set_child_mmap_ptr (child);
/* Wait for subproc to initialize itself. */
@@ -494,6 +513,17 @@ fork ()
debug_printf ("self %p, pid %d, ppid %d",
myself, x, myself ? myself->ppid : -1);
+ /* Restore the inheritance state as in parent
+ Don't call setuid here! The flags are already set. */
+ if (myself->impersonated)
+ {
+ debug_printf ("Impersonation of child, token: %d", myself->token);
+ if (myself->token == INVALID_HANDLE_VALUE)
+ RevertToSelf (); // probably not needed
+ else if (!ImpersonateLoggedOnUser (myself->token))
+ system_printf ("Impersonate for forked child failed: %E");
+ }
+
sync_with_parent ("after longjmp.", TRUE);
ProtectHandle (hParent);
diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h
index ffa17d0..2143bbb 100644
--- a/winsup/cygwin/include/cygwin/version.h
+++ b/winsup/cygwin/include/cygwin/version.h
@@ -106,10 +106,15 @@ details. */
19: Export fchown, lchown, lacl
20: regsub, inet_network
21: incompatible change to stdio cr/lf and buffering
+ 22: Export cygwin_logon_user, cygwin_set_impersonation_token.
+ geteuid, getegid return effective uid/gid.
+ getuid, getgid return real uid/gid.
+ seteuid, setegid set only effective uid/gid.
+ setuid, setgid set effective and real uid/gid.
*/
#define CYGWIN_VERSION_API_MAJOR 0
-#define CYGWIN_VERSION_API_MINOR 21
+#define CYGWIN_VERSION_API_MINOR 22
/* There is also a compatibity version number associated with the
shared memory regions. It is incremented when incompatible
diff --git a/winsup/cygwin/include/sys/cygwin.h b/winsup/cygwin/include/sys/cygwin.h
index ff891cc..6354f0f 100644
--- a/winsup/cygwin/include/sys/cygwin.h
+++ b/winsup/cygwin/include/sys/cygwin.h
@@ -31,6 +31,9 @@ extern int cygwin_conv_to_full_posix_path (const char *, char *);
extern int cygwin_posix_path_list_p (const char *);
extern void cygwin_split_path (const char *, char *, char *);
+extern HANDLE cygwin_logon_user (const struct passwd *, const char *);
+extern void cygwin_set_impersonation_token (const HANDLE);
+
#ifdef _GNU_H_WINDOWS32_BASE
/* included if <windows.h> is included */
extern int cygwin32_attach_handle_to_fd (char *, int, HANDLE, int, int);
diff --git a/winsup/cygwin/security.cc b/winsup/cygwin/security.cc
index 8537a6d..c468235 100644
--- a/winsup/cygwin/security.cc
+++ b/winsup/cygwin/security.cc
@@ -374,6 +374,73 @@ got_it:
return TRUE;
}
+extern "C"
+void
+cygwin_set_impersonation_token (const HANDLE hToken)
+{
+ debug_printf ("set_impersonation_token (%d)", hToken);
+ if (myself->token != hToken)
+ {
+ if (myself->token != INVALID_HANDLE_VALUE)
+ CloseHandle (myself->token);
+ myself->token = hToken;
+ myself->impersonated = FALSE;
+ }
+}
+
+extern "C"
+HANDLE
+cygwin_logon_user (const struct passwd *pw, const char *password)
+{
+ if (os_being_run != winNT)
+ {
+ set_errno (ENOSYS);
+ return INVALID_HANDLE_VALUE;
+ }
+ if (!pw)
+ {
+ set_errno (EINVAL);
+ return INVALID_HANDLE_VALUE;
+ }
+
+ char *c, *nt_user, *nt_domain = NULL;
+ char usernamebuf[256];
+ HANDLE hToken;
+
+ strcpy (usernamebuf, pw->pw_name);
+ if (pw->pw_gecos)
+ {
+ if ((c = strstr (pw->pw_gecos, "U-")) != NULL &&
+ (c == pw->pw_gecos || c[-1] == ','))
+ {
+ usernamebuf[0] = '\0';
+ strncat (usernamebuf, c + 2, 255);
+ if ((c = strchr (usernamebuf, ',')) != NULL)
+ *c = '\0';
+ }
+ }
+ nt_user = usernamebuf;
+ if ((c = strchr (nt_user, '\\')) != NULL)
+ {
+ nt_domain = nt_user;
+ *c = '\0';
+ nt_user = c + 1;
+ }
+ if (! LogonUserA (nt_user, nt_domain, (char *) password,
+ LOGON32_LOGON_INTERACTIVE,
+ LOGON32_PROVIDER_DEFAULT,
+ &hToken)
+ || !SetHandleInformation (hToken,
+ HANDLE_FLAG_INHERIT,
+ HANDLE_FLAG_INHERIT))
+ {
+ __seterrno ();
+ return INVALID_HANDLE_VALUE;
+ }
+ debug_printf ("%d = logon_user(%s,...)", hToken, pw->pw_name);
+ return hToken;
+}
+
/* read_sd reads a security descriptor from a file.
In case of error, -1 is returned and errno is set.
If sd_buf is too small, 0 is returned and sd_size
diff --git a/winsup/cygwin/shared.h b/winsup/cygwin/shared.h
index 5c6eff5..1b594d5 100644
--- a/winsup/cygwin/shared.h
+++ b/winsup/cygwin/shared.h
@@ -93,6 +93,15 @@ class pinfo
char logsrv[256]; /* Logon server, may be fully qualified DNS name */
char domain[MAX_COMPUTERNAME_LENGTH+1]; /* Logon domain of the user */
+ /* token is needed if sexec should be called. It can be set by a call
+ to `set_impersonation_token()'. */
+ HANDLE token;
+ BOOL impersonated;
+ uid_t orig_uid; /* Remains intact also after impersonation */
+ uid_t orig_gid; /* Ditto */
+ uid_t real_uid; /* Remains intact on seteuid, replaced by setuid */
+ gid_t real_gid; /* Ditto */
+
/* Non-zero if process was stopped by a signal. */
char stopsig;
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
index 1ff08e4..65e3bd6 100644
--- a/winsup/cygwin/spawn.cc
+++ b/winsup/cygwin/spawn.cc
@@ -503,6 +503,9 @@ skip_arg_parsing:
/* Preallocated buffer for `sec_user' call */
char sa_buf[1024];
+ if (!hToken && myself->token != INVALID_HANDLE_VALUE)
+ hToken = myself->token;
+
if (hToken)
{
/* allow the child to interact with our window station/desktop */
@@ -535,6 +538,11 @@ skip_arg_parsing:
else
system_printf ("GetTokenInformation: %E");
+ /* Remove impersonation */
+ uid_t uid = geteuid();
+ if (myself->impersonated && myself->token != INVALID_HANDLE_VALUE)
+ seteuid (myself->orig_uid);
+
rc = CreateProcessAsUser (hToken,
real_path, /* image name - with full path */
one_line.buf, /* what was passed to exec */
@@ -550,6 +558,9 @@ skip_arg_parsing:
0, /* use current drive/directory */
&si,
&pi);
+ /* Restore impersonation */
+ if (myself->impersonated && myself->token != INVALID_HANDLE_VALUE)
+ seteuid (uid);
}
else
rc = CreateProcessA (real_path, /* image name - with full path */
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index d2eeab0..6c40cc1 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -1797,30 +1797,31 @@ extern "C"
int
setgid (gid_t gid)
{
- if (os_being_run == winNT)
- {
- if (gid != (gid_t) -1)
- {
- if (!getgrgid (gid))
- {
- set_errno (EINVAL);
- return -1;
- }
- myself->gid = gid;
- }
- }
- else
- set_errno (ENOSYS);
- return 0;
+ int ret = setegid (gid);
+ if (!ret)
+ myself->real_gid = myself->gid;
+ return ret;
}
-extern char *internal_getlogin (struct pinfo *pi);
-
/* setuid: POSIX 4.2.2.1 */
extern "C"
int
setuid (uid_t uid)
{
+ int ret = seteuid (uid);
+ if (!ret)
+ myself->real_uid = myself->uid;
+ debug_printf ("real: %d, effective: %d", myself->real_uid, myself->uid);
+ return ret;
+}
+
+extern char *internal_getlogin (struct pinfo *pi);
+
+/* seteuid: standards? */
+extern "C"
+int
+seteuid (uid_t uid)
+{
if (os_being_run == winNT)
{
if (uid != (uid_t) -1)
@@ -1832,11 +1833,35 @@ setuid (uid_t uid)
return -1;
}
+ if (uid != myself->uid)
+ if (uid == myself->orig_uid)
+ {
+ debug_printf ("RevertToSelf() (uid == orig_uid, token=%d)",
+ myself->token);
+ RevertToSelf();
+ if (myself->token != INVALID_HANDLE_VALUE)
+ myself->impersonated = FALSE;
+ }
+ else if (!myself->impersonated)
+ {
+ debug_printf ("Impersonate(uid == %d)", uid);
+ RevertToSelf();
+ if (myself->token != INVALID_HANDLE_VALUE)
+ if (!ImpersonateLoggedOnUser (myself->token))
+ system_printf ("Impersonate(%d) in set(e)uid failed: %E",
+ myself->token);
+ else
+ myself->impersonated = TRUE;
+ }
+
struct pinfo pi;
pi.psid = (PSID) pi.sidbuf;
struct passwd *pw_cur = getpwnam (internal_getlogin (&pi));
if (pw_cur != pw_new)
{
+ debug_printf ("Diffs!!! token: %d, cur: %d, new: %d, orig: %d",
+ myself->token, pw_cur->pw_uid,
+ pw_new->pw_uid, myself->orig_uid);
set_errno (EPERM);
return -1;
}
@@ -1849,23 +1874,30 @@ setuid (uid_t uid)
}
else
set_errno (ENOSYS);
+ debug_printf ("real: %d, effective: %d", myself->real_uid, myself->uid);
return 0;
}
-/* seteuid: standards? */
-extern "C"
-int
-seteuid (uid_t uid)
-{
- return setuid (uid);
-}
-
/* setegid: from System V. */
extern "C"
int
setegid (gid_t gid)
{
- return setgid (gid);
+ if (os_being_run == winNT)
+ {
+ if (gid != (gid_t) -1)
+ {
+ if (!getgrgid (gid))
+ {
+ set_errno (EINVAL);
+ return -1;
+ }
+ myself->gid = gid;
+ }
+ }
+ else
+ set_errno (ENOSYS);
+ return 0;
}
/* chroot: privileged Unix system call. */
diff --git a/winsup/cygwin/uinfo.cc b/winsup/cygwin/uinfo.cc
index 90bb727..b50f155 100644
--- a/winsup/cygwin/uinfo.cc
+++ b/winsup/cygwin/uinfo.cc
@@ -126,6 +126,11 @@ uinfo_init ()
myself->uid = DEFAULT_UID;
myself->gid = DEFAULT_GID;
}
+ /* Set to non impersonated value. */
+ myself->token = INVALID_HANDLE_VALUE;
+ myself->impersonated = TRUE;
+ myself->orig_uid = myself->real_uid = myself->uid;
+ myself->orig_gid = myself->real_gid = myself->gid;
}
extern "C" char *
@@ -143,25 +148,25 @@ getlogin (void)
extern "C" uid_t
getuid (void)
{
- return myself->uid;
+ return myself->real_uid;
}
extern "C" gid_t
getgid (void)
{
- return myself->gid;
+ return myself->real_gid;
}
extern "C" uid_t
geteuid (void)
{
- return getuid ();
+ return myself->uid;
}
extern "C" gid_t
getegid (void)
{
- return getgid ();
+ return myself->gid;
}
/* Not quite right - cuserid can change, getlogin can't */