* 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> 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 * 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 (GetSecurityDescriptorDacl, 16, advapi32)
LoadDLLfunc (GetSecurityDescriptorGroup, 12, advapi32) LoadDLLfunc (GetSecurityDescriptorGroup, 12, advapi32)
LoadDLLfunc (GetSecurityDescriptorOwner, 12, advapi32) LoadDLLfunc (GetSecurityDescriptorOwner, 12, advapi32)
LoadDLLfunc (GetSidIdentifierAuthority, 4, advapi32)
LoadDLLfunc (GetSidSubAuthority, 8, advapi32) LoadDLLfunc (GetSidSubAuthority, 8, advapi32)
LoadDLLfunc (GetSidSubAuthorityCount, 4, advapi32) LoadDLLfunc (GetSidSubAuthorityCount, 4, advapi32)
LoadDLLfunc (GetTokenInformation, 20, advapi32) LoadDLLfunc (GetTokenInformation, 20, advapi32)
@ -1170,6 +1171,7 @@ LoadDLLfunc (OpenProcessToken, 12, advapi32)
LoadDLLfunc (RegCloseKey, 4, advapi32) LoadDLLfunc (RegCloseKey, 4, advapi32)
LoadDLLfunc (RegCreateKeyExA, 36, advapi32) LoadDLLfunc (RegCreateKeyExA, 36, advapi32)
LoadDLLfunc (RegDeleteKeyA, 8, advapi32) LoadDLLfunc (RegDeleteKeyA, 8, advapi32)
LoadDLLfunc (RegLoadKeyA, 12, advapi32)
LoadDLLfunc (RegEnumKeyExA, 32, advapi32) LoadDLLfunc (RegEnumKeyExA, 32, advapi32)
LoadDLLfunc (RegOpenKeyExA, 20, advapi32) LoadDLLfunc (RegOpenKeyExA, 20, advapi32)
LoadDLLfunc (RegQueryValueExA, 24, advapi32) LoadDLLfunc (RegQueryValueExA, 24, advapi32)

View File

@ -177,3 +177,57 @@ reg_key::~reg_key ()
RegCloseKey (key); RegCloseKey (key);
key_is_invalid = 1; 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_ALL (CONTAINER_INHERIT_ACE|OBJECT_INHERIT_ACE)
#define INHERIT_ONLY (INHERIT_ONLY_ACE|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 PSID
get_sid (PSID psid, DWORD s, DWORD cnt, DWORD *r) 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 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 sid_buf[256];
char *t; char *t;
@ -85,13 +104,13 @@ get_pw_sid (PSID sid, struct passwd *pw)
if (!sp) if (!sp)
return FALSE; return FALSE;
return get_ssid (sid, ++sp) != NULL; return convert_string_sid_to_sid (sid, ++sp) != NULL;
} }
BOOL BOOL
get_gr_sid (PSID sid, struct group *gr) 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 PSID
@ -103,7 +122,7 @@ get_admin_sid ()
if (!admin_sid) if (!admin_sid)
{ {
admin_sid = (PSID) admin_sid_buf; 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; return admin_sid;
} }
@ -117,7 +136,7 @@ get_system_sid ()
if (!system_sid) if (!system_sid)
{ {
system_sid = (PSID) system_sid_buf; 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; return system_sid;
} }
@ -131,7 +150,7 @@ get_creator_owner_sid ()
if (!owner_sid) if (!owner_sid)
{ {
owner_sid = (PSID) owner_sid_buf; 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; return owner_sid;
} }
@ -145,7 +164,7 @@ get_world_sid ()
if (!world_sid) if (!world_sid)
{ {
world_sid = (PSID) world_sid_buf; 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; return world_sid;
} }

View File

@ -252,6 +252,10 @@ public:
~reg_key (); ~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 ********/
/* Mount table entry */ /* Mount table entry */

View File

@ -543,6 +543,13 @@ skip_arg_parsing:
if (myself->impersonated && myself->token != INVALID_HANDLE_VALUE) if (myself->impersonated && myself->token != INVALID_HANDLE_VALUE)
seteuid (myself->orig_uid); 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, rc = CreateProcessAsUser (hToken,
real_path, /* image name - with full path */ real_path, /* image name - with full path */
one_line.buf, /* what was passed to exec */ 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->ctty = myself->ctty;
child->umask = myself->umask; child->umask = myself->umask;
child->process_state |= PID_INITIALIZING; child->process_state |= PID_INITIALIZING;
memcpy (child->username, myself->username, MAX_USER_NAME); if (!hToken && !myself->token)
child->psid = myself->psid; {
memcpy (child->sidbuf, myself->sidbuf, 40); memcpy (child->username, myself->username, MAX_USER_NAME);
memcpy (child->logsrv, myself->logsrv, 256); child->psid = myself->psid;
memcpy (child->domain, myself->domain, MAX_COMPUTERNAME_LENGTH+1); memcpy (child->sidbuf, myself->sidbuf, 40);
memcpy (child->logsrv, myself->logsrv, 256);
memcpy (child->domain, myself->domain, MAX_COMPUTERNAME_LENGTH+1);
}
subproc_init (); subproc_init ();
ret = spawn_guts (hToken, path, argv, envp, child, mode); ret = spawn_guts (hToken, path, argv, envp, child, mode);
if (ret == -1) if (ret == -1)

View File

@ -26,92 +26,135 @@ extern int group_in_memory_p;
char * char *
internal_getlogin (struct pinfo *pi) internal_getlogin (struct pinfo *pi)
{ {
DWORD username_len = MAX_USER_NAME;
if (! pi) if (! pi)
api_fatal ("pinfo pointer is NULL!\n"); 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) if (os_being_run == winNT)
{ {
LPWKSTA_USER_INFO_1 ui; LPWKSTA_USER_INFO_1 wui;
if (allow_ntsec && !NetWkstaUserGetInfo (NULL, 1, (LPBYTE *)&ui)) 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, wcstombs (pi->username, wui->wkui1_username,
ui->wkui1_logon_domain, (wcslen (wui->wkui1_username) + 1) * sizeof (WCHAR));
(wcslen (ui->wkui1_logon_domain) + 1) * sizeof (WCHAR)); wcstombs (pi->logsrv, wui->wkui1_logon_server,
debug_printf ("Domain: %s", pi->domain); (wcslen (wui->wkui1_logon_server) + 1) * sizeof (WCHAR));
wcstombs (pi->logsrv, wcstombs (pi->domain, wui->wkui1_logon_domain,
ui->wkui1_logon_server, (wcslen (wui->wkui1_logon_domain) + 1) * sizeof (WCHAR));
(wcslen (ui->wkui1_logon_server) + 1) * sizeof (WCHAR)); /* Save values in environment */
if (! *pi->logsrv) if (strcasecmp (pi->username, "SYSTEM")
&& pi->domain[0] && pi->logsrv[0])
{ {
LPWSTR logon_srv = NULL; LPUSER_INFO_3 ui = NULL;
WCHAR wbuf[256];
if (!NetGetDCName (NULL, strcat (strcpy (buf, "\\\\"), pi->logsrv);
ui->wkui1_logon_domain, setenv ("USERNAME", pi->username, 1);
(LPBYTE *)&logon_srv)) setenv ("LOGONSERVER", buf, 1);
wcstombs (pi->logsrv, setenv ("USERDOMAIN", pi->domain, 1);
logon_srv, // filter leading double backslashes /* HOMEDRIVE and HOMEPATH are wrong most of the time, too,
(wcslen (logon_srv) + 1) * sizeof (WCHAR)); after changing user context! */
if (logon_srv) mbstowcs (wbuf, buf, 256);
NetApiBufferFree (logon_srv); if (!NetUserGetInfo (NULL, wui->wkui1_username, 3, (LPBYTE *)&ui)
debug_printf ("DC Server: %s", pi->logsrv); || !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 ("Domain: %s, Logon Server: %s, Windows Username: %s",
debug_printf ("Logon Server: %s", pi->logsrv); pi->domain, pi->logsrv, pi->username);
wcstombs (pi->username, NetApiBufferFree (wui);
ui->wkui1_username,
(wcslen (ui->wkui1_username) + 1) * sizeof (WCHAR));
debug_printf ("Windows Username: %s", pi->username);
NetApiBufferFree (ui);
} }
else if (! GetUserName (pi->username, &username_len)) if (allow_ntsec)
strcpy (pi->username, "unknown");
if (!lookup_name (pi->username, pi->logsrv, pi->psid))
{ {
debug_printf ("myself->psid = NULL"); /* Try to get the SID from localhost first. This can only
pi->psid = NULL; be done if a domain is given because there's a chance that
} a local and a domain user may have the same name. */
else if (allow_ntsec) int ret = 0;
{
extern BOOL get_pw_sid (PSID, struct passwd*);
struct passwd *pw;
char psidbuf[40];
PSID psid = (PSID) psidbuf;
while ((pw = getpwent ()) != NULL) if (pi->domain[0])
if (get_pw_sid (psid, pw) && EqualSid (pi->psid, psid)) {
{ /* Concat DOMAIN\USERNAME for the next lookup */
strcpy (pi->username, pw->pw_name); strcat (strcat (strcpy (buf, pi->domain), "\\"), pi->username);
break; if (!(ret = lookup_name (buf, NULL, (PSID) pi->sidbuf)))
} debug_printf ("Couldn't retrieve SID locally!");
endpwent (); }
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 ("Cygwins Username: %s", pi->username);
{
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);
return pi->username; return pi->username;
} }
void void
uinfo_init () uinfo_init ()
{ {
char *username;
struct passwd *p; struct passwd *p;
myself->psid = (PSID) myself->sidbuf; /* If psid is non null, the process is forked or spawned from
if ((p = getpwnam (internal_getlogin (myself))) != NULL) 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 /* 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) if (!group_in_memory_p)
read_etc_group (); read_etc_group ();
myself->uid = p->pw_uid; myself->uid = p->pw_uid;
myself->gid = p->pw_gid; myself->gid = p->pw_gid;
@ -197,7 +240,7 @@ dummy_autoload (void)
{ {
LoadDLLinit (netapi32) LoadDLLinit (netapi32)
LoadDLLfunc (NetWkstaUserGetInfo, 12, netapi32) LoadDLLfunc (NetWkstaUserGetInfo, 12, netapi32)
LoadDLLfunc (NetGetDCName, 12, netapi32) LoadDLLfunc (NetUserGetInfo, 16, netapi32)
LoadDLLfunc (NetApiBufferFree, 4, netapi32) LoadDLLfunc (NetApiBufferFree, 4, netapi32)
} }
} }

View File

@ -429,7 +429,10 @@ extern BOOL allow_ntsec;
/* `lookup_name' should be called instead of LookupAccountName. /* `lookup_name' should be called instead of LookupAccountName.
* logsrv may be NULL, in this case only the local system is used for lookup. * 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! */ * 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); unsigned long __stdcall hash_path_name (unsigned long hash, const char *name);
void __stdcall nofinalslash (const char *src, char *dst); void __stdcall nofinalslash (const char *src, char *dst);