* 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'.
This commit is contained in:
parent
8929e0a70c
commit
e219a2bdf0
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
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)
|
||||
|
|
|
@ -26,59 +26,103 @@ 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))
|
||||
{
|
||||
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)
|
||||
{
|
||||
LPWSTR logon_srv = NULL;
|
||||
LPWKSTA_USER_INFO_1 wui;
|
||||
char buf[256], *env;
|
||||
|
||||
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);
|
||||
/* 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->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])
|
||||
{
|
||||
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, "\\");
|
||||
}
|
||||
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);
|
||||
if (!buf[0])
|
||||
strcat (strcpy (buf, getenv ("SYSTEMDRIVE")), "\\");
|
||||
setenv ("HOMEPATH", buf + 2, 1);
|
||||
buf[2] = '\0';
|
||||
setenv ("HOMEDRIVE", buf, 1);
|
||||
NetApiBufferFree (ui);
|
||||
}
|
||||
else if (! GetUserName (pi->username, &username_len))
|
||||
strcpy (pi->username, "unknown");
|
||||
if (!lookup_name (pi->username, pi->logsrv, pi->psid))
|
||||
{
|
||||
debug_printf ("myself->psid = NULL");
|
||||
pi->psid = NULL;
|
||||
}
|
||||
else if (allow_ntsec)
|
||||
debug_printf ("Domain: %s, Logon Server: %s, Windows Username: %s",
|
||||
pi->domain, pi->logsrv, pi->username);
|
||||
NetApiBufferFree (wui);
|
||||
}
|
||||
if (allow_ntsec)
|
||||
{
|
||||
/* 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)
|
||||
{
|
||||
extern BOOL get_pw_sid (PSID, struct passwd*);
|
||||
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))
|
||||
{
|
||||
|
@ -88,24 +132,23 @@ internal_getlogin (struct pinfo *pi)
|
|||
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 */
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue