* autoload.cc (CreateProfile): Import.
(LoadUserProfileW): Import. * registry.cc (get_registry_hive_path): Move to sec_auth.cc. (load_registry_hive): Remove. * registry.h (get_registry_hive_path): Drop declaration. (load_registry_hive): Ditto. * sec_auth.cc (get_user_profile_directory): Moved from registry.cc and renamed. Take third parameter with buffer length. (load_user_profile): New function taking over for load_registry_hive. Use official functions to load profile. If profile is missing, create it on Vista and later. * security.h (get_user_profile_directory): Declare. (load_user_profile): Declare. * syscalls.cc (seteuid32): Replace call to load_registry_hive with call to load_user_profile. * uinfo.cc (cygheap_user::env_userprofile): Replace call to get_registry_hive_path with call to get_user_profile_directory.
This commit is contained in:
@ -20,10 +20,13 @@ details. */
|
||||
#include "fhandler.h"
|
||||
#include "dtable.h"
|
||||
#include "cygheap.h"
|
||||
#include "registry.h"
|
||||
#include "ntdll.h"
|
||||
#include "tls_pbuf.h"
|
||||
#include <lm.h>
|
||||
#include <iptypes.h>
|
||||
#include <wininet.h>
|
||||
#include <userenv.h>
|
||||
#include "cyglsa.h"
|
||||
#include "cygserver_setpwd.h"
|
||||
#include <cygwin/version.h>
|
||||
@ -172,6 +175,113 @@ cygwin_logon_user (const struct passwd *pw, const char *password)
|
||||
return hToken;
|
||||
}
|
||||
|
||||
/* The buffer path points to should be at least MAX_PATH bytes. */
|
||||
PWCHAR
|
||||
get_user_profile_directory (PCWSTR sidstr, PWCHAR path, SIZE_T path_len)
|
||||
{
|
||||
if (!sidstr || !path)
|
||||
return NULL;
|
||||
|
||||
UNICODE_STRING buf;
|
||||
tmp_pathbuf tp;
|
||||
tp.u_get (&buf);
|
||||
NTSTATUS status;
|
||||
|
||||
RTL_QUERY_REGISTRY_TABLE tab[2] = {
|
||||
{ NULL, RTL_QUERY_REGISTRY_NOEXPAND | RTL_QUERY_REGISTRY_DIRECT
|
||||
| RTL_QUERY_REGISTRY_REQUIRED,
|
||||
L"ProfileImagePath", &buf, REG_NONE, NULL, 0 },
|
||||
{ NULL, 0, NULL, NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
WCHAR key[wcslen (sidstr) + 16];
|
||||
wcpcpy (wcpcpy (key, L"ProfileList\\"), sidstr);
|
||||
status = RtlQueryRegistryValues (RTL_REGISTRY_WINDOWS_NT, key, tab,
|
||||
NULL, NULL);
|
||||
if (!NT_SUCCESS (status) || buf.Length == 0)
|
||||
{
|
||||
debug_printf ("ProfileImagePath for %W not found, status %y", sidstr,
|
||||
status);
|
||||
return NULL;
|
||||
}
|
||||
ExpandEnvironmentStringsW (buf.Buffer, path, path_len);
|
||||
debug_printf ("ProfileImagePath for %W: %W", sidstr, path);
|
||||
return path;
|
||||
}
|
||||
|
||||
/* The CreateProfile prototype is for some reason missing in our w32api headers,
|
||||
even though it's defined upstream since Dec-2013. */
|
||||
extern "C" {
|
||||
HRESULT WINAPI CreateProfile (LPCWSTR pszUserSid, LPCWSTR pszUserName,
|
||||
LPWSTR pszProfilePath, DWORD cchProfilePath);
|
||||
}
|
||||
|
||||
/* Load user profile if it's not already loaded. If the user profile doesn't
|
||||
exist on the machine, and if we're running Vista or later, try to create it.
|
||||
|
||||
Return a handle to the loaded user registry hive only if it got actually
|
||||
loaded here, not if it already existed. There's no reliable way to know
|
||||
when to unload the hive yet, so we're leaking this registry handle for now.
|
||||
TODO: Try to find a way to reliably unload the user profile again. */
|
||||
HANDLE
|
||||
load_user_profile (HANDLE token, struct passwd *pw, cygpsid &usersid)
|
||||
{
|
||||
WCHAR domain[DNLEN + 1];
|
||||
WCHAR username[UNLEN + 1];
|
||||
WCHAR sid[128];
|
||||
HKEY hkey;
|
||||
WCHAR userpath[MAX_PATH];
|
||||
PROFILEINFOW pi;
|
||||
WCHAR server[INTERNET_MAX_HOST_NAME_LENGTH + 3];
|
||||
NET_API_STATUS nas = NERR_UserNotFound;
|
||||
PUSER_INFO_3 ui;
|
||||
|
||||
extract_nt_dom_user (pw, domain, username);
|
||||
usersid.string (sid);
|
||||
debug_printf ("user: <%W> <%W>", username, sid);
|
||||
/* Check if user hive is already loaded. */
|
||||
if (!RegOpenKeyExW (HKEY_USERS, sid, 0, KEY_READ, &hkey))
|
||||
{
|
||||
debug_printf ("User registry hive for %W already exists", username);
|
||||
RegCloseKey (hkey);
|
||||
return NULL;
|
||||
}
|
||||
/* Check if the local profile dir has already been created. */
|
||||
if (!get_user_profile_directory (sid, userpath, MAX_PATH))
|
||||
{
|
||||
/* No, try to create it. This function exists only on Vista and later. */
|
||||
HRESULT res = CreateProfile (sid, username, userpath, MAX_PATH);
|
||||
if (res != S_OK)
|
||||
{
|
||||
/* If res is 1 (S_FALSE), autoloading failed (XP or 2K3). */
|
||||
if (res != S_FALSE)
|
||||
debug_printf ("CreateProfile, HRESULT %x", res);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
/* Fill PROFILEINFO */
|
||||
memset (&pi, 0, sizeof pi);
|
||||
pi.dwSize = sizeof pi;
|
||||
pi.dwFlags = PI_NOUI;
|
||||
pi.lpUserName = username;
|
||||
/* Check if user has a roaming profile and fill in lpProfilePath, if so. */
|
||||
if (get_logon_server (domain, server, DS_IS_FLAT_NAME))
|
||||
{
|
||||
nas = NetUserGetInfo (server, username, 3, (PBYTE *) &ui);
|
||||
if (NetUserGetInfo (server, username, 3, (PBYTE *) &ui) != NERR_Success)
|
||||
debug_printf ("NetUserGetInfo, %u", nas);
|
||||
else if (ui->usri3_profile && *ui->usri3_profile)
|
||||
pi.lpProfilePath = ui->usri3_profile;
|
||||
}
|
||||
|
||||
if (!LoadUserProfileW (token, &pi))
|
||||
debug_printf ("LoadUserProfileW, %E");
|
||||
/* Free buffer created by NetUserGetInfo */
|
||||
if (nas == NERR_Success)
|
||||
NetApiBufferFree (ui);
|
||||
return pi.hProfile;
|
||||
}
|
||||
|
||||
HANDLE
|
||||
lsa_open_policy (PWCHAR server, ACCESS_MASK access)
|
||||
{
|
||||
|
Reference in New Issue
Block a user