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
path: root/winsup
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2000-06-19 21:36:30 +0400
committerCorinna Vinschen <corinna@vinschen.de>2000-06-19 21:36:30 +0400
commite219a2bdf05f480fff06c6f4866a79bab784450d (patch)
tree8d08ffd6c382b25c54e7ca8009a04ad62df3684f /winsup
parent8929e0a70cbe243d566fa29f21f00c5bfa8e7be8 (diff)
* dcrt0.cc: Add load statements for `GetSidIdentifierAuthority'
and `RegLoadKeyA'. * registry.cc (get_registry_hive_path): New function. (load_registry_hive): Ditto. * security.cc (convert_sid_to_string_sid): New function. (get_ssid): Renamed to `convert_string_sid_to_sid'. (get_pw_sid): Call `convert_string_sid_to_sid' instead of `get_ssid'. (get_gr_sid): Ditto. (get_admin_sid): Ditto. (get_system_sid): Ditto. (get_creator_owner_sid): Ditto. (get_world_sid): Ditto. * shared.h: New prototypes for `get_registry_hive_path' and `load_registry_hive'. * spawn.cc (spawn_guts): Set child->psid to NULL to force calling `internal_getlogin' from child process in case of changing user context. Call `load_registry_hive' in case of changing user context. (_spawnve): Copy user infos only if user context remains the same. * uinfo.cc: Add load statement for `NetUserGetInfo'. Remove load statement for `NetGetDCName'. (internal_getlogin): Rewrite to speed up process startup and to correct user environment in case user context changes. (uinfo_init): Call internal_getlogin only if myself->psid is NULL, that is user context changes. * winsup.h: Add prototypes for `convert_sid_to_string_sid', `convert_string_sid_to_sid' and `get_pw_sid'.
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/ChangeLog29
-rw-r--r--winsup/cygwin/dcrt0.cc2
-rw-r--r--winsup/cygwin/registry.cc54
-rw-r--r--winsup/cygwin/security.cc33
-rw-r--r--winsup/cygwin/shared.h4
-rw-r--r--winsup/cygwin/spawn.cc20
-rw-r--r--winsup/cygwin/uinfo.cc169
-rw-r--r--winsup/cygwin/winsup.h5
8 files changed, 240 insertions, 76 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index b6d09af27..601ac2585 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,32 @@
+Mon Jun 19 19:35:00 2000 Corinna Vinschen <corinna@vinschen.de>
+
+ * dcrt0.cc: Add load statements for `GetSidIdentifierAuthority'
+ and `RegLoadKeyA'.
+ * registry.cc (get_registry_hive_path): New function.
+ (load_registry_hive): Ditto.
+ * security.cc (convert_sid_to_string_sid): New function.
+ (get_ssid): Renamed to `convert_string_sid_to_sid'.
+ (get_pw_sid): Call `convert_string_sid_to_sid' instead of `get_ssid'.
+ (get_gr_sid): Ditto.
+ (get_admin_sid): Ditto.
+ (get_system_sid): Ditto.
+ (get_creator_owner_sid): Ditto.
+ (get_world_sid): Ditto.
+ * shared.h: New prototypes for `get_registry_hive_path' and
+ `load_registry_hive'.
+ * spawn.cc (spawn_guts): Set child->psid to NULL to force calling
+ `internal_getlogin' from child process in case of changing user context.
+ Call `load_registry_hive' in case of changing user context.
+ (_spawnve): Copy user infos only if user context remains the same.
+ * uinfo.cc: Add load statement for `NetUserGetInfo'.
+ Remove load statement for `NetGetDCName'.
+ (internal_getlogin): Rewrite to speed up process startup
+ and to correct user environment in case user context changes.
+ (uinfo_init): Call internal_getlogin only if myself->psid is NULL,
+ that is user context changes.
+ * winsup.h: Add prototypes for `convert_sid_to_string_sid',
+ `convert_string_sid_to_sid' and `get_pw_sid'.
+
Sun Jun 18 13:42:50 2000 Christopher Faylor <cgf@cygnus.com>
* fhandler.h (set_name): Don't use 'unix' as name since this is defined
diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc
index 302207cec..801016a31 100644
--- a/winsup/cygwin/dcrt0.cc
+++ b/winsup/cygwin/dcrt0.cc
@@ -1152,6 +1152,7 @@ LoadDLLfunc (GetLengthSid, 4, advapi32)
LoadDLLfunc (GetSecurityDescriptorDacl, 16, advapi32)
LoadDLLfunc (GetSecurityDescriptorGroup, 12, advapi32)
LoadDLLfunc (GetSecurityDescriptorOwner, 12, advapi32)
+LoadDLLfunc (GetSidIdentifierAuthority, 4, advapi32)
LoadDLLfunc (GetSidSubAuthority, 8, advapi32)
LoadDLLfunc (GetSidSubAuthorityCount, 4, advapi32)
LoadDLLfunc (GetTokenInformation, 20, advapi32)
@@ -1170,6 +1171,7 @@ LoadDLLfunc (OpenProcessToken, 12, advapi32)
LoadDLLfunc (RegCloseKey, 4, advapi32)
LoadDLLfunc (RegCreateKeyExA, 36, advapi32)
LoadDLLfunc (RegDeleteKeyA, 8, advapi32)
+LoadDLLfunc (RegLoadKeyA, 12, advapi32)
LoadDLLfunc (RegEnumKeyExA, 32, advapi32)
LoadDLLfunc (RegOpenKeyExA, 20, advapi32)
LoadDLLfunc (RegQueryValueExA, 24, advapi32)
diff --git a/winsup/cygwin/registry.cc b/winsup/cygwin/registry.cc
index 47092f576..31ee183da 100644
--- a/winsup/cygwin/registry.cc
+++ b/winsup/cygwin/registry.cc
@@ -177,3 +177,57 @@ reg_key::~reg_key ()
RegCloseKey (key);
key_is_invalid = 1;
}
+
+char *
+get_registry_hive_path (const PSID psid, char *path)
+{
+ char sid[256];
+ char key[256];
+ HKEY hkey;
+
+ if (!psid || !path)
+ return NULL;
+ convert_sid_to_string_sid (psid, sid);
+ strcpy (key,"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\");
+ strcat (key, sid);
+ if (!RegOpenKeyExA (HKEY_LOCAL_MACHINE, key, 0, KEY_READ, &hkey))
+ {
+ char buf[256];
+ DWORD type, siz;
+
+ key[0] = '\0';
+ if (!RegQueryValueExA (hkey, "ProfileImagePath", 0, &type,
+ (BYTE *)buf, (siz = 256, &siz)))
+ ExpandEnvironmentStringsA (buf, key, 256);
+ RegCloseKey (hkey);
+ if (key[0])
+ return strcpy (path, key);
+ }
+ return NULL;
+}
+
+void
+load_registry_hive (PSID psid)
+{
+ char sid[256];
+ char path[256];
+ HKEY hkey;
+
+ if (!psid)
+ return;
+ /* Check if user hive already exists */
+ if (!RegOpenKeyExA (HKEY_LOCAL_MACHINE, convert_sid_to_string_sid (psid, sid),
+ 0, KEY_READ, &hkey))
+ {
+ debug_printf ("User registry hive for %s already exists", sid);
+ RegCloseKey (hkey);
+ return;
+ }
+ if (get_registry_hive_path (psid, path))
+ {
+ strcat (path, "\\NTUSER.DAT");
+ if (RegLoadKeyA (HKEY_USERS, sid, path))
+ debug_printf ("Loading user registry hive for %s failed: %E", sid);
+ }
+}
+
diff --git a/winsup/cygwin/security.cc b/winsup/cygwin/security.cc
index c468235fc..3dc6c5777 100644
--- a/winsup/cygwin/security.cc
+++ b/winsup/cygwin/security.cc
@@ -41,6 +41,25 @@ SID_IDENTIFIER_AUTHORITY sid_auth[] = {
#define INHERIT_ALL (CONTAINER_INHERIT_ACE|OBJECT_INHERIT_ACE)
#define INHERIT_ONLY (INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE|OBJECT_INHERIT_ACE)
+char *
+convert_sid_to_string_sid (PSID psid, char *sid_str)
+{
+ char t[32];
+ DWORD i;
+
+ if (!psid || !sid_str)
+ return NULL;
+ strcpy (sid_str, "S-1-");
+ sprintf(t, "%u", GetSidIdentifierAuthority (psid)->Value[5]);
+ strcat (sid_str, t);
+ for (i = 0; i < *GetSidSubAuthorityCount (psid); ++i)
+ {
+ sprintf(t, "-%lu", *GetSidSubAuthority (psid, i));
+ strcat (sid_str, t);
+ }
+ return sid_str;
+}
+
PSID
get_sid (PSID psid, DWORD s, DWORD cnt, DWORD *r)
{
@@ -56,7 +75,7 @@ get_sid (PSID psid, DWORD s, DWORD cnt, DWORD *r)
}
PSID
-get_ssid (PSID psid, const char *sid_str)
+convert_string_sid_to_sid (PSID psid, const char *sid_str)
{
char sid_buf[256];
char *t;
@@ -85,13 +104,13 @@ get_pw_sid (PSID sid, struct passwd *pw)
if (!sp)
return FALSE;
- return get_ssid (sid, ++sp) != NULL;
+ return convert_string_sid_to_sid (sid, ++sp) != NULL;
}
BOOL
get_gr_sid (PSID sid, struct group *gr)
{
- return get_ssid (sid, gr->gr_passwd) != NULL;
+ return convert_string_sid_to_sid (sid, gr->gr_passwd) != NULL;
}
PSID
@@ -103,7 +122,7 @@ get_admin_sid ()
if (!admin_sid)
{
admin_sid = (PSID) admin_sid_buf;
- get_ssid (admin_sid, "S-1-5-32-544");
+ convert_string_sid_to_sid (admin_sid, "S-1-5-32-544");
}
return admin_sid;
}
@@ -117,7 +136,7 @@ get_system_sid ()
if (!system_sid)
{
system_sid = (PSID) system_sid_buf;
- get_ssid (system_sid, "S-1-5-18");
+ convert_string_sid_to_sid (system_sid, "S-1-5-18");
}
return system_sid;
}
@@ -131,7 +150,7 @@ get_creator_owner_sid ()
if (!owner_sid)
{
owner_sid = (PSID) owner_sid_buf;
- get_ssid (owner_sid, "S-1-3-0");
+ convert_string_sid_to_sid (owner_sid, "S-1-3-0");
}
return owner_sid;
}
@@ -145,7 +164,7 @@ get_world_sid ()
if (!world_sid)
{
world_sid = (PSID) world_sid_buf;
- get_ssid (world_sid, "S-1-1-0");
+ convert_string_sid_to_sid (world_sid, "S-1-1-0");
}
return world_sid;
}
diff --git a/winsup/cygwin/shared.h b/winsup/cygwin/shared.h
index 1b594d5d7..1c959eca8 100644
--- a/winsup/cygwin/shared.h
+++ b/winsup/cygwin/shared.h
@@ -252,6 +252,10 @@ public:
~reg_key ();
};
+/* Evaluates path to the directory of the local user registry hive */
+char *__stdcall get_registry_hive_path (const PSID psid, char *path);
+void __stdcall load_registry_hive (PSID psid);
+
/******** Mount Table ********/
/* Mount table entry */
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
index 65e3bd665..7225c5377 100644
--- a/winsup/cygwin/spawn.cc
+++ b/winsup/cygwin/spawn.cc
@@ -543,6 +543,13 @@ skip_arg_parsing:
if (myself->impersonated && myself->token != INVALID_HANDLE_VALUE)
seteuid (myself->orig_uid);
+ /* Set child->psid to NULL to force calling internal_getlogin()
+ from child process. */
+ child->psid = NULL;
+
+ /* Load users registry hive. */
+ load_registry_hive (sid);
+
rc = CreateProcessAsUser (hToken,
real_path, /* image name - with full path */
one_line.buf, /* what was passed to exec */
@@ -837,11 +844,14 @@ _spawnve (HANDLE hToken, int mode, const char *path, const char *const *argv,
child->ctty = myself->ctty;
child->umask = myself->umask;
child->process_state |= PID_INITIALIZING;
- memcpy (child->username, myself->username, MAX_USER_NAME);
- child->psid = myself->psid;
- memcpy (child->sidbuf, myself->sidbuf, 40);
- memcpy (child->logsrv, myself->logsrv, 256);
- memcpy (child->domain, myself->domain, MAX_COMPUTERNAME_LENGTH+1);
+ if (!hToken && !myself->token)
+ {
+ memcpy (child->username, myself->username, MAX_USER_NAME);
+ child->psid = myself->psid;
+ memcpy (child->sidbuf, myself->sidbuf, 40);
+ memcpy (child->logsrv, myself->logsrv, 256);
+ memcpy (child->domain, myself->domain, MAX_COMPUTERNAME_LENGTH+1);
+ }
subproc_init ();
ret = spawn_guts (hToken, path, argv, envp, child, mode);
if (ret == -1)
diff --git a/winsup/cygwin/uinfo.cc b/winsup/cygwin/uinfo.cc
index 4e4a0c459..c2ca4e3f7 100644
--- a/winsup/cygwin/uinfo.cc
+++ b/winsup/cygwin/uinfo.cc
@@ -26,92 +26,135 @@ extern int group_in_memory_p;
char *
internal_getlogin (struct pinfo *pi)
{
- DWORD username_len = MAX_USER_NAME;
-
if (! pi)
api_fatal ("pinfo pointer is NULL!\n");
+ DWORD username_len = MAX_USER_NAME;
+ if (! GetUserName (pi->username, &username_len))
+ strcpy (pi->username, "unknown");
if (os_being_run == winNT)
{
- LPWKSTA_USER_INFO_1 ui;
- if (allow_ntsec && !NetWkstaUserGetInfo (NULL, 1, (LPBYTE *)&ui))
+ LPWKSTA_USER_INFO_1 wui;
+ char buf[256], *env;
+
+ /* First trying to get logon info from environment */
+ buf[0] = '\0';
+ if ((env = getenv ("USERNAME")) != NULL)
+ strcpy (buf, env);
+ if ((env = getenv ("LOGONSERVER")) != NULL)
+ strcpy (pi->logsrv, env + 2); /* filter leading double backslashes */
+ if ((env = getenv ("USERDOMAIN")) != NULL)
+ strcpy (pi->domain, env);
+ /* Trust only if usernames are identical */
+ if (!strcasecmp (pi->username, buf) && pi->domain[0] && pi->logsrv[0])
+ debug_printf ("Domain: %s, Logon Server: %s", pi->domain, pi->logsrv);
+ /* If that failed, try to get that info from NetBIOS */
+ else if (!NetWkstaUserGetInfo (NULL, 1, (LPBYTE *)&wui))
{
- wcstombs (pi->domain,
- ui->wkui1_logon_domain,
- (wcslen (ui->wkui1_logon_domain) + 1) * sizeof (WCHAR));
- debug_printf ("Domain: %s", pi->domain);
- wcstombs (pi->logsrv,
- ui->wkui1_logon_server,
- (wcslen (ui->wkui1_logon_server) + 1) * sizeof (WCHAR));
- if (! *pi->logsrv)
+ wcstombs (pi->username, wui->wkui1_username,
+ (wcslen (wui->wkui1_username) + 1) * sizeof (WCHAR));
+ wcstombs (pi->logsrv, wui->wkui1_logon_server,
+ (wcslen (wui->wkui1_logon_server) + 1) * sizeof (WCHAR));
+ wcstombs (pi->domain, wui->wkui1_logon_domain,
+ (wcslen (wui->wkui1_logon_domain) + 1) * sizeof (WCHAR));
+ /* Save values in environment */
+ if (strcasecmp (pi->username, "SYSTEM")
+ && pi->domain[0] && pi->logsrv[0])
{
- LPWSTR logon_srv = NULL;
-
- if (!NetGetDCName (NULL,
- ui->wkui1_logon_domain,
- (LPBYTE *)&logon_srv))
- wcstombs (pi->logsrv,
- logon_srv, // filter leading double backslashes
- (wcslen (logon_srv) + 1) * sizeof (WCHAR));
- if (logon_srv)
- NetApiBufferFree (logon_srv);
- debug_printf ("DC Server: %s", pi->logsrv);
+ LPUSER_INFO_3 ui = NULL;
+ WCHAR wbuf[256];
+
+ strcat (strcpy (buf, "\\\\"), pi->logsrv);
+ setenv ("USERNAME", pi->username, 1);
+ setenv ("LOGONSERVER", buf, 1);
+ setenv ("USERDOMAIN", pi->domain, 1);
+ /* HOMEDRIVE and HOMEPATH are wrong most of the time, too,
+ after changing user context! */
+ mbstowcs (wbuf, buf, 256);
+ if (!NetUserGetInfo (NULL, wui->wkui1_username, 3, (LPBYTE *)&ui)
+ || !NetUserGetInfo (wbuf,wui->wkui1_username,3,(LPBYTE *)&ui))
+ {
+ wcstombs (buf, ui->usri3_home_dir, 256);
+ if (!buf[0])
+ {
+ wcstombs (buf, ui->usri3_home_dir_drive, 256);
+ if (buf[0])
+ strcat (buf, "\\");
+ }
+ if (!buf[0])
+ strcat (strcpy (buf, getenv ("SYSTEMDRIVE")), "\\");
+ setenv ("HOMEPATH", buf + 2, 1);
+ buf[2] = '\0';
+ setenv ("HOMEDRIVE", buf, 1);
+ NetApiBufferFree (ui);
+ }
}
- else
- debug_printf ("Logon Server: %s", pi->logsrv);
- wcstombs (pi->username,
- ui->wkui1_username,
- (wcslen (ui->wkui1_username) + 1) * sizeof (WCHAR));
- debug_printf ("Windows Username: %s", pi->username);
- NetApiBufferFree (ui);
+ debug_printf ("Domain: %s, Logon Server: %s, Windows Username: %s",
+ pi->domain, pi->logsrv, pi->username);
+ NetApiBufferFree (wui);
}
- else if (! GetUserName (pi->username, &username_len))
- strcpy (pi->username, "unknown");
- if (!lookup_name (pi->username, pi->logsrv, pi->psid))
+ if (allow_ntsec)
{
- debug_printf ("myself->psid = NULL");
- pi->psid = NULL;
- }
- else if (allow_ntsec)
- {
- extern BOOL get_pw_sid (PSID, struct passwd*);
- struct passwd *pw;
- char psidbuf[40];
- PSID psid = (PSID) psidbuf;
-
- while ((pw = getpwent ()) != NULL)
- if (get_pw_sid (psid, pw) && EqualSid (pi->psid, psid))
- {
- strcpy (pi->username, pw->pw_name);
- break;
- }
- endpwent ();
+ /* Try to get the SID from localhost first. This can only
+ be done if a domain is given because there's a chance that
+ a local and a domain user may have the same name. */
+ int ret = 0;
+
+ if (pi->domain[0])
+ {
+ /* Concat DOMAIN\USERNAME for the next lookup */
+ strcat (strcat (strcpy (buf, pi->domain), "\\"), pi->username);
+ if (!(ret = lookup_name (buf, NULL, (PSID) pi->sidbuf)))
+ debug_printf ("Couldn't retrieve SID locally!");
+ }
+ if (!ret && !(ret = lookup_name(pi->username, pi->logsrv,
+ (PSID)pi->sidbuf)))
+ debug_printf ("Couldn't retrieve SID from '%s'!", pi->logsrv);
+ if (ret)
+ {
+ struct passwd *pw;
+ char psidbuf[40];
+ PSID psid = (PSID) psidbuf;
+
+ pi->psid = (PSID) pi->sidbuf;
+ if (strcasecmp (pi->username, "SYSTEM")
+ && pi->domain[0] && pi->logsrv[0])
+ {
+ if (get_registry_hive_path (pi->psid, buf))
+ setenv ("USERPROFILE", buf, 1);
+ }
+ while ((pw = getpwent ()) != NULL)
+ if (get_pw_sid (psid, pw) && EqualSid (pi->psid, psid))
+ {
+ strcpy (pi->username, pw->pw_name);
+ break;
+ }
+ endpwent ();
+ }
}
}
- else
- {
- debug_printf ("myself->psid = NULL");
- pi->psid = NULL;
- if (! GetUserName (pi->username, &username_len))
- strcpy (pi->username, "unknown");
- }
- debug_printf ("Cygwins Username: %s\n", pi->username);
+ debug_printf ("Cygwins Username: %s", pi->username);
return pi->username;
}
void
uinfo_init ()
{
+ char *username;
struct passwd *p;
- myself->psid = (PSID) myself->sidbuf;
- if ((p = getpwnam (internal_getlogin (myself))) != NULL)
+ /* If psid is non null, the process is forked or spawned from
+ another cygwin process without changing the user context.
+ So all user infos in myself as well as the environment are
+ (perhaps) valid. */
+ username = myself->psid ? myself->username : internal_getlogin (myself);
+ if ((p = getpwnam (username)) != NULL)
{
/* calling getpwnam assures us that /etc/password has been
- read in, but we can't be sure about /etc/group */
+ read in, but we can't be sure about /etc/group */
if (!group_in_memory_p)
- read_etc_group ();
+ read_etc_group ();
myself->uid = p->pw_uid;
myself->gid = p->pw_gid;
@@ -197,7 +240,7 @@ dummy_autoload (void)
{
LoadDLLinit (netapi32)
LoadDLLfunc (NetWkstaUserGetInfo, 12, netapi32)
-LoadDLLfunc (NetGetDCName, 12, netapi32)
+LoadDLLfunc (NetUserGetInfo, 16, netapi32)
LoadDLLfunc (NetApiBufferFree, 4, netapi32)
}
}
diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h
index db7774b48..f9569f2aa 100644
--- a/winsup/cygwin/winsup.h
+++ b/winsup/cygwin/winsup.h
@@ -429,7 +429,10 @@ extern BOOL allow_ntsec;
/* `lookup_name' should be called instead of LookupAccountName.
* logsrv may be NULL, in this case only the local system is used for lookup.
* The buffer for ret_sid (40 Bytes) has to be allocated by the caller! */
-BOOL __stdcall lookup_name (const char *name, const char *logsrv, PSID ret_sid);
+BOOL __stdcall lookup_name (const char *, const char *, PSID);
+char *__stdcall convert_sid_to_string_sid (PSID, char *);
+PSID __stdcall convert_string_sid_to_sid (PSID, const char *);
+BOOL __stdcall get_pw_sid (PSID, struct passwd *);
unsigned long __stdcall hash_path_name (unsigned long hash, const char *name);
void __stdcall nofinalslash (const char *src, char *dst);