Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2008-11-26 13:18:10 +0300
committerCorinna Vinschen <corinna@vinschen.de>2008-11-26 13:18:10 +0300
commit51303cbd0c22d81d20d99934c71474809e72fa1a (patch)
tree778b92b9b93a2137dd8b4dab3651185aae2b9129
parent4163e9fbdb410867b4e5536ed02ac6fad938bb00 (diff)
* Makefile.in (DLL_OFILES): Add setlsapwd.o.
* cygserver.h (CYGWIN_SERVER_VERSION_API): Bump. (request_code_t): Define CYGSERVER_REQUEST_SETPWD request type. * cygserver_msg.h (client_request_msg::retval): Use default value of -1 for retval if msglen is 0. * cygserver_sem.h (client_request_sem::retval): Ditto. * cygserver_shm.h (client_request_shm::retval): Ditto. * cygserver_setpwd.h: New file. * external.cc (cygwin_internal): Implement new CW_SET_PRIV_KEY type. * sec_auth.cc (open_local_policy): Make externally available. Get ACCESS_MASK as argument. (create_token): Accommodate change to open_local_policy. (lsaauth): Ditto. (lsaprivkeyauth): New function fetching token by retrieving password stored in Cygwin or Interix LSA private data area and calling LogonUser with it. * security.h (lsaprivkeyauth): Declare. (open_local_policy): Declare. * setlsapwd.cc: New file implementing setting LSA private data password using LsaStorePrivateData or by calling cygserver if available. * syscalls.cc (seteuid32): Add workaround to get the original token when switching back to the original privileged user, even if setgroups group list is still active. Add long comment to explain why. Call lsaprivkeyauth first, only if that fails call lsaauth or create_token. * include/cygwin/version.h: Bump API minor number. * include/sys/cygwin.h (cygwin_getinfo_types): Add CW_SET_PRIV_KEY.
-rw-r--r--winsup/cygwin/ChangeLog30
-rw-r--r--winsup/cygwin/Makefile.in10
-rw-r--r--winsup/cygwin/cygserver.h5
-rw-r--r--winsup/cygwin/cygserver_msg.h4
-rw-r--r--winsup/cygwin/cygserver_sem.h4
-rw-r--r--winsup/cygwin/cygserver_setpwd.h53
-rw-r--r--winsup/cygwin/cygserver_shm.h4
-rw-r--r--winsup/cygwin/external.cc6
-rw-r--r--winsup/cygwin/include/cygwin/version.h3
-rw-r--r--winsup/cygwin/include/sys/cygwin.h3
-rw-r--r--winsup/cygwin/sec_auth.cc85
-rw-r--r--winsup/cygwin/security.h4
-rw-r--r--winsup/cygwin/setlsapwd.cc90
-rw-r--r--winsup/cygwin/syscalls.cc54
14 files changed, 323 insertions, 32 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 31d74eed0..ddb11d82a 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,33 @@
+2008-11-26 Corinna Vinschen <corinna@vinschen.de>
+
+ * Makefile.in (DLL_OFILES): Add setlsapwd.o.
+ * cygserver.h (CYGWIN_SERVER_VERSION_API): Bump.
+ (request_code_t): Define CYGSERVER_REQUEST_SETPWD request type.
+ * cygserver_msg.h (client_request_msg::retval): Use default value of -1
+ for retval if msglen is 0.
+ * cygserver_sem.h (client_request_sem::retval): Ditto.
+ * cygserver_shm.h (client_request_shm::retval): Ditto.
+ * cygserver_setpwd.h: New file.
+ * external.cc (cygwin_internal): Implement new CW_SET_PRIV_KEY type.
+ * sec_auth.cc (open_local_policy): Make externally available.
+ Get ACCESS_MASK as argument.
+ (create_token): Accommodate change to open_local_policy.
+ (lsaauth): Ditto.
+ (lsaprivkeyauth): New function fetching token by retrieving
+ password stored in Cygwin or Interix LSA private data area and
+ calling LogonUser with it.
+ * security.h (lsaprivkeyauth): Declare.
+ (open_local_policy): Declare.
+ * setlsapwd.cc: New file implementing setting LSA private data password
+ using LsaStorePrivateData or by calling cygserver if available.
+ * syscalls.cc (seteuid32): Add workaround to get the original token
+ when switching back to the original privileged user, even if
+ setgroups group list is still active. Add long comment to explain why.
+ Call lsaprivkeyauth first, only if that fails call lsaauth or
+ create_token.
+ * include/cygwin/version.h: Bump API minor number.
+ * include/sys/cygwin.h (cygwin_getinfo_types): Add CW_SET_PRIV_KEY.
+
2008-11-21 Corinna Vinschen <corinna@vinschen.de>
* fhandler_floppy.cc (fhandler_dev_floppy::raw_read): Drop
diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in
index d6f6bb1ce..49baebc96 100644
--- a/winsup/cygwin/Makefile.in
+++ b/winsup/cygwin/Makefile.in
@@ -141,11 +141,11 @@ DLL_OFILES:=assert.o autoload.o bsdlib.o ctype.o cxx.o cygheap.o cygthread.o \
nftw.o ntea.o passwd.o path.o pinfo.o pipe.o poll.o posix_ipc.o \
pthread.o random.o regcomp.o regerror.o regexec.o regfree.o registry.o \
resource.o rexec.o rcmd.o scandir.o sched.o sec_acl.o sec_auth.o \
- sec_helper.o security.o select.o sem.o shared.o shm.o sigfe.o signal.o \
- sigproc.o smallprint.o spawn.o strace.o strfuncs.o strptime.o strsep.o \
- strsig.o sync.o syscalls.o sysconf.o syslog.o termios.o thread.o \
- timer.o times.o tls_pbuf.o tty.o uinfo.o uname.o wait.o wincap.o \
- window.o winf.o xsique.o \
+ sec_helper.o security.o select.o sem.o setlsapwd.o shared.o shm.o \
+ sigfe.o signal.o sigproc.o smallprint.o spawn.o strace.o strfuncs.o \
+ strptime.o strsep.o strsig.o sync.o syscalls.o sysconf.o syslog.o \
+ termios.o thread.o timer.o times.o tls_pbuf.o tty.o uinfo.o uname.o \
+ wait.o wincap.o window.o winf.o xsique.o \
$(EXTRA_DLL_OFILES) $(EXTRA_OFILES) $(MALLOC_OFILES) $(MT_SAFE_OBJECTS)
GMON_OFILES:=gmon.o mcount.o profil.o
diff --git a/winsup/cygwin/cygserver.h b/winsup/cygwin/cygserver.h
index 09ab78a9f..b549ed006 100644
--- a/winsup/cygwin/cygserver.h
+++ b/winsup/cygwin/cygserver.h
@@ -1,6 +1,6 @@
/* cygserver.h
- Copyright 2001, 2002, 2003, 2004 Red Hat Inc.
+ Copyright 2001, 2002, 2003, 2004, 2008 Red Hat Inc.
Written by Egor Duda <deo@logos-m.ru>
@@ -20,7 +20,7 @@ details. */
#endif
#define CYGWIN_SERVER_VERSION_MAJOR 1
-#define CYGWIN_SERVER_VERSION_API 3
+#define CYGWIN_SERVER_VERSION_API 4
#define CYGWIN_SERVER_VERSION_MINOR 0
#define CYGWIN_SERVER_VERSION_PATCH 0
@@ -51,6 +51,7 @@ protected:
CYGSERVER_REQUEST_MSG,
CYGSERVER_REQUEST_SEM,
CYGSERVER_REQUEST_SHM,
+ CYGSERVER_REQUEST_SETPWD,
CYGSERVER_REQUEST_LAST
} request_code_t;
diff --git a/winsup/cygwin/cygserver_msg.h b/winsup/cygwin/cygserver_msg.h
index 7fbb12cab..37616bb1d 100644
--- a/winsup/cygwin/cygserver_msg.h
+++ b/winsup/cygwin/cygserver_msg.h
@@ -1,6 +1,6 @@
/* cygserver_msg.h: Single unix specification IPC interface for Cygwin.
- Copyright 2003 Red Hat, Inc.
+ Copyright 2003, 2008 Red Hat, Inc.
This file is part of Cygwin.
@@ -75,7 +75,7 @@ public:
client_request_msg (int, const void *, size_t, int); // msgsnd
#endif
- int retval () const { return _parameters.out.ret; }
+ int retval () const { return msglen () ? _parameters.out.ret : -1; }
ssize_t rcvval () const { return _parameters.out.rcv; }
};
diff --git a/winsup/cygwin/cygserver_sem.h b/winsup/cygwin/cygserver_sem.h
index 225d8f215..fdf6f8c39 100644
--- a/winsup/cygwin/cygserver_sem.h
+++ b/winsup/cygwin/cygserver_sem.h
@@ -1,6 +1,6 @@
/* cygserver_sem.h: Single unix specification IPC interface for Cygwin.
- Copyright 2003 Red Hat, Inc.
+ Copyright 2003, 2008 Red Hat, Inc.
This file is part of Cygwin.
@@ -71,7 +71,7 @@ public:
client_request_sem (int, struct sembuf *, size_t); // semop
#endif
- int retval () const { return _parameters.out.ret; }
+ int retval () const { return msglen () ? _parameters.out.ret : -1; }
};
#ifndef __INSIDE_CYGWIN__
diff --git a/winsup/cygwin/cygserver_setpwd.h b/winsup/cygwin/cygserver_setpwd.h
new file mode 100644
index 000000000..94ee2998d
--- /dev/null
+++ b/winsup/cygwin/cygserver_setpwd.h
@@ -0,0 +1,53 @@
+/* cygserver_setpwd.h: Set LSA private data password for current user.
+
+ Copyright 2008 Red Hat, Inc.
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+#ifndef __CYGSERVER_SETPWD_H__
+#define __CYGSERVER_SETPWD_H__
+
+#include <sys/types.h>
+#include "cygserver.h"
+
+#define CYGWIN_LSA_KEY_PREFIX L"L$CYGWIN_"
+
+#ifndef __INSIDE_CYGWIN__
+class transport_layer_base;
+class process_cache;
+#endif
+
+class client_request_setpwd : public client_request
+{
+ friend class client_request;
+
+private:
+ union
+ {
+ struct
+ {
+ WCHAR passwd[256];
+ } in;
+ } _parameters;
+
+#ifndef __INSIDE_CYGWIN__
+ client_request_setpwd ();
+ virtual void serve (transport_layer_base *, process_cache *);
+#endif
+
+public:
+
+#ifdef __INSIDE_CYGWIN__
+ client_request_setpwd (PUNICODE_STRING);
+#endif
+};
+
+#ifdef __INSIDE_CYGWIN__
+unsigned long setlsapwd (const char *passwd);
+#endif
+
+#endif /* __CYGSERVER_SETPWD_H__ */
diff --git a/winsup/cygwin/cygserver_shm.h b/winsup/cygwin/cygserver_shm.h
index 2948f6725..baa3e052a 100644
--- a/winsup/cygwin/cygserver_shm.h
+++ b/winsup/cygwin/cygserver_shm.h
@@ -1,6 +1,6 @@
/* cygserver_shm.h: Single unix specification IPC interface for Cygwin.
- Copyright 2003 Red Hat, Inc.
+ Copyright 2003, 2008 Red Hat, Inc.
This file is part of Cygwin.
@@ -78,7 +78,7 @@ public:
client_request_shm (proc *); // shmfork
#endif
- int retval () const { return _parameters.out.ret; }
+ int retval () const { return msglen () ? _parameters.out.ret : -1; }
void *ptrval () const { return (void *)_parameters.out.ptr; }
vm_object_t objval () const { return _parameters.out.obj; }
};
diff --git a/winsup/cygwin/external.cc b/winsup/cygwin/external.cc
index 675d8b066..b880e07fb 100644
--- a/winsup/cygwin/external.cc
+++ b/winsup/cygwin/external.cc
@@ -25,6 +25,7 @@ details. */
#include "cygtls.h"
#include "child_info.h"
#include "environ.h"
+#include "cygserver_setpwd.h"
#include <unistd.h>
#include <stdlib.h>
#include <wchar.h>
@@ -357,6 +358,11 @@ cygwin_internal (cygwin_getinfo_types t, ...)
dos_file_warning = va_arg (arg, int);
}
break;
+ case CW_SET_PRIV_KEY:
+ {
+ const char *passwd = va_arg (arg, const char *);
+ return setlsapwd (passwd);
+ }
default:
break;
diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h
index 268f99db7..ef332ce23 100644
--- a/winsup/cygwin/include/cygwin/version.h
+++ b/winsup/cygwin/include/cygwin/version.h
@@ -335,12 +335,13 @@ details. */
186: Remove ancient V8 regexp functions. Also eliminate old crt0 interface
which provided its own user_data structure.
187: Export cfmakeraw.
+ 188: Export CW_SET_PRIV_KEY.
*/
/* Note that we forgot to bump the api for ualarm, strtoll, strtoull */
#define CYGWIN_VERSION_API_MAJOR 0
-#define CYGWIN_VERSION_API_MINOR 187
+#define CYGWIN_VERSION_API_MINOR 188
/* 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 1ba18597d..8c1101051 100644
--- a/winsup/cygwin/include/sys/cygwin.h
+++ b/winsup/cygwin/include/sys/cygwin.h
@@ -140,7 +140,8 @@ typedef enum
CW_DEBUG_SELF,
CW_SYNC_WINENV,
CW_CYGTLS_PADSIZE,
- CW_SET_DOS_FILE_WARNING
+ CW_SET_DOS_FILE_WARNING,
+ CW_SET_PRIV_KEY
} cygwin_getinfo_types;
#define CW_NEXTPID 0x80000000 /* or with pid to get next one */
diff --git a/winsup/cygwin/sec_auth.cc b/winsup/cygwin/sec_auth.cc
index 3f7a082b2..138131744 100644
--- a/winsup/cygwin/sec_auth.cc
+++ b/winsup/cygwin/sec_auth.cc
@@ -27,6 +27,7 @@ details. */
#include <iptypes.h>
#include "pwdgrp.h"
#include "cyglsa.h"
+#include "cygserver_setpwd.h"
#include <cygwin/version.h>
extern "C" void
@@ -150,13 +151,13 @@ str2uni_cat (UNICODE_STRING &tgt, const char *srcstr)
tgt.Length = tgt.MaximumLength = 0;
}
-static LSA_HANDLE
-open_local_policy ()
+HANDLE
+open_local_policy (ACCESS_MASK access)
{
LSA_OBJECT_ATTRIBUTES oa = { 0, 0, 0, 0, 0, 0 };
- LSA_HANDLE lsa = INVALID_HANDLE_VALUE;
+ HANDLE lsa = INVALID_HANDLE_VALUE;
- NTSTATUS ret = LsaOpenPolicy (NULL, &oa, POLICY_EXECUTE, &lsa);
+ NTSTATUS ret = LsaOpenPolicy (NULL, &oa, access, &lsa);
if (ret != STATUS_SUCCESS)
__seterrno_from_win_error (LsaNtStatusToWinError (ret));
return lsa;
@@ -785,7 +786,7 @@ create_token (cygsid &usersid, user_groups &new_groups, struct passwd *pw)
push_self_privilege (SE_CREATE_TOKEN_PRIVILEGE, true);
/* Open policy object. */
- if ((lsa = open_local_policy ()) == INVALID_HANDLE_VALUE)
+ if ((lsa = open_local_policy (POLICY_EXECUTE)) == INVALID_HANDLE_VALUE)
goto out;
/* User, owner, primary group. */
@@ -963,7 +964,7 @@ lsaauth (cygsid &usersid, user_groups &new_groups, struct passwd *pw)
}
/* Open policy object. */
- if ((lsa = open_local_policy ()) == INVALID_HANDLE_VALUE)
+ if ((lsa = open_local_policy (POLICY_EXECUTE)) == INVALID_HANDLE_VALUE)
goto out;
/* Create origin. */
@@ -1172,3 +1173,75 @@ out:
debug_printf ("%p = lsaauth ()", user_token);
return user_token;
}
+
+#define SFU_LSA_KEY_SUFFIX L"_microsoft_sfu_utility"
+
+HANDLE
+lsaprivkeyauth (struct passwd *pw)
+{
+ NTSTATUS status;
+ HANDLE lsa = INVALID_HANDLE_VALUE;
+ HANDLE token = NULL;
+ WCHAR sid[256];
+ WCHAR domain[MAX_DOMAIN_NAME_LEN + 1];
+ WCHAR user[UNLEN + 1];
+ WCHAR key_name[MAX_DOMAIN_NAME_LEN + UNLEN + wcslen (SFU_LSA_KEY_SUFFIX) + 2];
+ UNICODE_STRING key;
+ PUNICODE_STRING data;
+ cygsid psid;
+
+ push_self_privilege (SE_TCB_PRIVILEGE, true);
+
+ /* Open policy object. */
+ if ((lsa = open_local_policy (POLICY_GET_PRIVATE_INFORMATION))
+ == INVALID_HANDLE_VALUE)
+ goto out;
+
+ /* Needed for Interix key and LogonUser. */
+ extract_nt_dom_user (pw, domain, user);
+
+ /* First test for a Cygwin entry. */
+ if (psid.getfrompw (pw) && psid.string (sid))
+ {
+ wcpcpy (wcpcpy (key_name, CYGWIN_LSA_KEY_PREFIX), sid);
+ RtlInitUnicodeString (&key, key_name);
+ status = LsaRetrievePrivateData (lsa, &key, &data);
+ if (!NT_SUCCESS (status))
+ {
+ /* No Cygwin key, try Interix key. */
+ if (!*domain)
+ goto out;
+ __small_swprintf (key_name, L"%W_%W%W",
+ domain, user, SFU_LSA_KEY_SUFFIX);
+ RtlInitUnicodeString (&key, key_name);
+ status = LsaRetrievePrivateData (lsa, &key, &data);
+ if (!NT_SUCCESS (status))
+ goto out;
+ }
+ }
+
+ /* The key is not 0-terminated. */
+ PWCHAR passwd = (PWCHAR) alloca (data->Length + sizeof (WCHAR));
+ *wcpncpy (passwd, data->Buffer, data->Length / sizeof (WCHAR)) = L'\0';
+ LsaFreeMemory (data);
+ debug_printf ("Try logon for %W\\%W", domain, user);
+ if (!LogonUserW (user, domain, passwd, LOGON32_LOGON_INTERACTIVE,
+ LOGON32_PROVIDER_DEFAULT, &token))
+ {
+ __seterrno ();
+ token = NULL;
+ }
+ else if (!SetHandleInformation (token,
+ HANDLE_FLAG_INHERIT,
+ HANDLE_FLAG_INHERIT))
+ {
+ __seterrno ();
+ CloseHandle (token);
+ token = NULL;
+ }
+
+out:
+ close_local_policy (lsa);
+ pop_self_privilege ();
+ return token;
+}
diff --git a/winsup/cygwin/security.h b/winsup/cygwin/security.h
index 27a2d0046..0f194bade 100644
--- a/winsup/cygwin/security.h
+++ b/winsup/cygwin/security.h
@@ -370,6 +370,8 @@ void __stdcall str2uni_cat (_UNICODE_STRING &, const char *) __attribute__ ((reg
HANDLE create_token (cygsid &usersid, user_groups &groups, struct passwd * pw);
/* LSA authentication function. */
HANDLE lsaauth (cygsid &, user_groups &, struct passwd *);
+/* LSA private key storage authentication, same as when using service logons. */
+HANDLE lsaprivkeyauth (struct passwd *pw);
/* Verify an existing token */
bool verify_token (HANDLE token, cygsid &usersid, user_groups &groups, bool *pintern = NULL);
/* Get groups of a user */
@@ -380,6 +382,8 @@ void extract_nt_dom_user (const struct passwd *pw, PWCHAR domain, PWCHAR user);
/* Get default logonserver for a domain. */
bool get_logon_server (PWCHAR domain, PWCHAR wserver, bool rediscovery);
+HANDLE open_local_policy (ACCESS_MASK access);
+
/* sec_helper.cc: Security helper functions. */
int set_privilege (HANDLE token, DWORD privilege, bool enable);
void set_cygwin_privileges (HANDLE token);
diff --git a/winsup/cygwin/setlsapwd.cc b/winsup/cygwin/setlsapwd.cc
new file mode 100644
index 000000000..34284afd3
--- /dev/null
+++ b/winsup/cygwin/setlsapwd.cc
@@ -0,0 +1,90 @@
+/* setlsapwd.cc: Set LSA private data password for current user.
+
+ Copyright 2008 Red Hat, Inc.
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+#include "winsup.h"
+#include "shared_info.h"
+#include "cygerrno.h"
+#include "path.h"
+#include "fhandler.h"
+#include "dtable.h"
+#include "cygheap.h"
+#include "security.h"
+#include "cygserver_setpwd.h"
+#include "ntdll.h"
+#include <ntsecapi.h>
+#include <stdlib.h>
+#include <wchar.h>
+
+#ifdef USE_SERVER
+/*
+ * client_request_setpwd Constructor
+ */
+
+client_request_setpwd::client_request_setpwd (PUNICODE_STRING passwd)
+ : client_request (CYGSERVER_REQUEST_SETPWD, &_parameters, sizeof (_parameters))
+{
+ memset (_parameters.in.passwd, 0, sizeof _parameters.in.passwd);
+ if (passwd->Length > 0 && passwd->Length < 256 * sizeof (WCHAR))
+ wcpncpy (_parameters.in.passwd, passwd->Buffer, 255);
+
+ msglen (sizeof (_parameters.in));
+}
+
+#endif /* USE_SERVER */
+
+unsigned long
+setlsapwd (const char *passwd)
+{
+ unsigned long ret = (unsigned long) -1;
+ HANDLE lsa = INVALID_HANDLE_VALUE;
+ WCHAR sid[128];
+ WCHAR key_name[128 + wcslen (CYGWIN_LSA_KEY_PREFIX)];
+ PWCHAR data_buf = NULL;
+ UNICODE_STRING key;
+ UNICODE_STRING data;
+
+ wcpcpy (wcpcpy (key_name, CYGWIN_LSA_KEY_PREFIX),
+ cygheap->user.get_windows_id (sid));
+ RtlInitUnicodeString (&key, key_name);
+ if (!passwd || ! *passwd
+ || sys_mbstowcs_alloc (&data_buf, HEAP_NOTHEAP, passwd))
+ {
+ NTSTATUS status = STATUS_ACCESS_DENIED;
+
+ memset (&data, 0, sizeof data);
+ if (data_buf)
+ RtlInitUnicodeString (&data, data_buf);
+ /* First try it locally. Works for admin accounts. */
+ if ((lsa = open_local_policy (POLICY_CREATE_SECRET))
+ != INVALID_HANDLE_VALUE)
+ {
+ status = LsaStorePrivateData (lsa, &key, data.Length ? &data : NULL);
+ if (NT_SUCCESS (status))
+ ret = 0;
+ LsaClose (lsa);
+ }
+ if (ret)
+#ifdef USE_SERVER
+ {
+ /* If that fails, ask cygserver. */
+ client_request_setpwd request (&data);
+ if (request.make_request () == -1 || request.error_code ())
+ set_errno (request.error_code ());
+ else
+ ret = 0;
+ }
+#else
+ __seterrno_from_nt_status (status);
+#endif
+ if (data_buf)
+ free (data_buf);
+ }
+ return ret;
+}
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 9b39f7712..4590c37a8 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -2493,7 +2493,23 @@ seteuid32 (__uid32_t uid)
cygheap->user.deimpersonate ();
/* Verify if the process token is suitable. */
- if (verify_token (hProcToken, usersid, groups))
+ /* TODO, CV 2008-11-25: The check against saved_sid is a kludge and a
+ shortcut. We must check if it's really feasible in the long run.
+ The reason to add this shortcut is this: sshd switches back to the
+ privileged user running sshd at least twice in the process of
+ authentication. It calls seteuid first, then setegid. Due to this
+ order, the setgroups group list is still active when calling seteuid
+ and verify_token treats the original token of the privileged user as
+ insufficient. This in turn results in creating a new user token for
+ the privileged user instead of using the orignal token. This can have
+ unfortunate side effects. The created token has different group
+ memberships, different user rights, and misses possible network
+ credentials.
+ Therefore we try this shortcut now. When switching back to the
+ privileged user, we probably always want a correct (aka original)
+ user token for this privileged user, not only in sshd. */
+ if ((uid == cygheap->user.saved_uid && usersid == cygheap->user.saved_sid ())
+ || verify_token (hProcToken, usersid, groups))
new_token = hProcToken;
/* Verify if the external token is suitable */
else if (cygheap->user.external_token != NO_IMPERSONATION
@@ -2514,19 +2530,35 @@ seteuid32 (__uid32_t uid)
debug_printf ("Found token %d", new_token);
- /* If no impersonation token is available, try to
- authenticate using NtCreateToken () or LSA authentication. */
+ /* If no impersonation token is available, try to authenticate using
+ LSA private data stored password, LSA authentication using our own
+ LSA module, or, as last chance, NtCreateToken. */
if (new_token == INVALID_HANDLE_VALUE)
{
- if (!(new_token = lsaauth (usersid, groups, pw_new)))
- {
- debug_printf ("lsaauth failed, try create_token.");
- new_token = create_token (usersid, groups, pw_new);
- if (new_token == INVALID_HANDLE_VALUE)
+ new_token = lsaprivkeyauth (pw_new);
+ if (new_token)
+ {
+ /* We have to verify this token since settings in /etc/group
+ might render it unusable im terms of group membership. */
+ if (!verify_token (new_token, usersid, groups))
{
- debug_printf ("create_token failed, bail out of here");
- cygheap->user.reimpersonate ();
- return -1;
+ CloseHandle (new_token);
+ new_token = NULL;
+ }
+ }
+ if (!new_token)
+ {
+ debug_printf ("lsaprivkeyauth failed, try lsaauth.");
+ if (!(new_token = lsaauth (usersid, groups, pw_new)))
+ {
+ debug_printf ("lsaauth failed, try create_token.");
+ new_token = create_token (usersid, groups, pw_new);
+ if (new_token == INVALID_HANDLE_VALUE)
+ {
+ debug_printf ("create_token failed, bail out of here");
+ cygheap->user.reimpersonate ();
+ return -1;
+ }
}
}