* 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:
Corinna Vinschen 2000-06-19 17:36:30 +00:00
parent 8929e0a70c
commit e219a2bdf0
8 changed files with 238 additions and 74 deletions

View File

@ -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

View File

@ -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)

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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 */

View File

@ -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)

View File

@ -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)
}
}

View File

@ -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);