Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

469 lines
12 KiB

  1. /*+
  2. *
  3. * Microsoft Windows
  4. * Copyright (C) Microsoft Corporation, 1997 - 1998.
  5. *
  6. * Name : seclogon.cxx
  7. * Author:Jeffrey Richter (v-jeffrr)
  8. *
  9. * Abstract:
  10. * This is the service DLL for Secondary Logon Service
  11. * This service supports the CreateProcessWithLogon API implemented
  12. * in advapi32.dll
  13. *
  14. * Revision History:
  15. * PraeritG 10/8/97 To integrate this in to services.exe
  16. *
  17. -*/
  18. #define STRICT
  19. #include <Windows.h>
  20. #include <userenv.h>
  21. #include <lm.h>
  22. #include <dsgetdc.h>
  23. #include <sddl.h>
  24. PTOKEN_USER
  25. SlpGetTokenUser(
  26. HANDLE TokenHandle,
  27. PLUID AuthenticationId OPTIONAL
  28. )
  29. /*++
  30. Routine Description:
  31. This routine returns the TOKEN_USER structure for the
  32. current user, and optionally, the AuthenticationId from his
  33. token.
  34. Arguments:
  35. AuthenticationId - Supplies an optional pointer to return the
  36. AuthenticationId.
  37. Return Value:
  38. On success, returns a pointer to a TOKEN_USER structure.
  39. On failure, returns NULL. Call GetLastError() for more
  40. detailed error information.
  41. --*/
  42. {
  43. ULONG ReturnLength;
  44. TOKEN_STATISTICS TokenStats;
  45. PTOKEN_USER pTokenUser = NULL;
  46. BOOLEAN b = FALSE;
  47. if(!GetTokenInformation (
  48. TokenHandle,
  49. TokenUser,
  50. NULL,
  51. 0,
  52. &ReturnLength
  53. ))
  54. {
  55. pTokenUser = (PTOKEN_USER)HeapAlloc( GetProcessHeap(), 0,
  56. ReturnLength );
  57. if (pTokenUser) {
  58. if ( GetTokenInformation (
  59. TokenHandle,
  60. TokenUser,
  61. pTokenUser,
  62. ReturnLength,
  63. &ReturnLength
  64. ))
  65. {
  66. if (AuthenticationId) {
  67. if(GetTokenInformation (
  68. TokenHandle,
  69. TokenStatistics,
  70. (PVOID)&TokenStats,
  71. sizeof( TOKEN_STATISTICS ),
  72. &ReturnLength
  73. ))
  74. {
  75. *AuthenticationId = TokenStats.AuthenticationId;
  76. b = TRUE;
  77. }
  78. } else {
  79. //
  80. // We're done, mark that everything worked
  81. //
  82. b = TRUE;
  83. }
  84. }
  85. if (!b) {
  86. //
  87. // Something failed, clean up what we were going to return
  88. //
  89. HeapFree( GetProcessHeap(), 0, pTokenUser );
  90. pTokenUser = NULL;
  91. }
  92. }
  93. }
  94. return( pTokenUser );
  95. }
  96. DWORD
  97. SlpGetUserName(
  98. IN HANDLE TokenHandle,
  99. OUT LPTSTR UserName,
  100. IN OUT PDWORD UserNameLen,
  101. OUT LPTSTR DomainName,
  102. IN OUT PDWORD DomNameLen
  103. )
  104. /*++
  105. Routine Description:
  106. This routine is the LSA Server worker routine for the LsaGetUserName
  107. API.
  108. WARNING: This routine allocates memory for its output. The caller is
  109. responsible for freeing this memory after use. See description of the
  110. Names parameter.
  111. Arguments:
  112. UserName - Receives name of the current user.
  113. DomainName - Optionally receives domain name of the current user.
  114. Return Values:
  115. NTSTATUS - Standard Nt Result Code
  116. STATUS_SUCCESS - The call completed successfully and all Sids have
  117. been translated to names.
  118. STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources
  119. such as memory to complete the call.
  120. --*/
  121. {
  122. LUID LogonId;
  123. PTOKEN_USER TokenUserInformation = NULL;
  124. SID_NAME_USE Use;
  125. //
  126. // Let's see if we're trying to look up the currently logged on
  127. // user.
  128. //
  129. //
  130. // TokenUserInformation from this call must be freed by calling
  131. // HeapFree().
  132. //
  133. TokenUserInformation = SlpGetTokenUser( TokenHandle, &LogonId );
  134. if ( TokenUserInformation ) {
  135. //
  136. // Simply do LookupAccountSid...
  137. //
  138. if(LookupAccountSid(NULL, TokenUserInformation->User.Sid,
  139. UserName, UserNameLen, DomainName, DomNameLen,
  140. &Use))
  141. {
  142. HeapFree( GetProcessHeap(), 0, TokenUserInformation );
  143. return ERROR_SUCCESS;
  144. }
  145. HeapFree( GetProcessHeap(), 0, TokenUserInformation );
  146. return GetLastError();
  147. }
  148. HeapFree( GetProcessHeap(), 0, TokenUserInformation );
  149. return GetLastError();
  150. }
  151. BOOL
  152. SlpIsDomainUser(
  153. HANDLE Token,
  154. PBOOLEAN IsDomain
  155. )
  156. /*++
  157. Routine Description:
  158. Determines if the current user is logged on to a domain account
  159. or a local machine account.
  160. Arguments:
  161. IsDomain - Returns TRUE if the current user is logged on to a domain
  162. account, FALSE otherwise.
  163. Return Value:
  164. TRUE on success, FALSE on failure.
  165. --*/
  166. {
  167. TCHAR UserName[MAX_PATH];
  168. DWORD UserNameLen = MAX_PATH;
  169. TCHAR Domain[MAX_PATH];
  170. DWORD DomNameLen = MAX_PATH;
  171. DWORD Status;
  172. WCHAR pwszMachineName[(MAX_COMPUTERNAME_LENGTH + 1) * sizeof( WCHAR )];
  173. DWORD nSize = MAX_COMPUTERNAME_LENGTH + 1;
  174. BOOL b = FALSE;
  175. *IsDomain = FALSE;
  176. Status = SlpGetUserName( Token, UserName, &UserNameLen,
  177. Domain, &DomNameLen );
  178. if (Status == ERROR_SUCCESS) {
  179. if (GetComputerName ( pwszMachineName, &nSize )) {
  180. *IsDomain = (lstrcmp( pwszMachineName, Domain ) != 0);
  181. b = TRUE;
  182. }
  183. }
  184. return( b );
  185. }
  186. BOOL
  187. SlpLoadUserProfile(
  188. IN HANDLE hToken,
  189. OUT PHANDLE hProfile
  190. )
  191. /*++
  192. Routine Description:
  193. This routine attempts to determine if the user's profile is loaded,
  194. and if it is not, loads it.
  195. Callers are expected to call SlpUnloadUserProfile() during their cleanup.
  196. Arguments:
  197. hToken - Returns a handle to the user's token.
  198. hProfile - Returns a handle to the user's profile.
  199. Return Value:
  200. TRUE if the profile is already loaded or if this routine loads it successfully,
  201. FALSE otherwise.
  202. --*/
  203. {
  204. BOOLEAN b = FALSE;
  205. BOOLEAN DomainUser;
  206. BOOL fReturn = FALSE;
  207. TCHAR lpDomainName[MAX_PATH];
  208. DWORD DomNameLen = MAX_PATH;
  209. LPWSTR lpServerName = NULL;
  210. PUSER_INFO_3 lpUserInfo;
  211. TCHAR lpUserName[MAX_PATH];
  212. DWORD UserNameLen = MAX_PATH;
  213. DWORD rc = ERROR_SUCCESS;
  214. LPWSTR SidString = NULL;
  215. NTSTATUS Status;
  216. DWORD dwResult;
  217. PDOMAIN_CONTROLLER_INFO DomainControllerInfo = NULL;
  218. *hProfile = NULL;
  219. //
  220. // First, see if the profile is loaded. If it is,
  221. // make a simple call to LoadUserProfile just to refcount it
  222. // and return.
  223. //
  224. Status = SlpGetUserName(
  225. hToken,
  226. lpUserName,
  227. &UserNameLen,
  228. lpDomainName,
  229. &DomNameLen
  230. );
  231. if (Status == ERROR_SUCCESS) {
  232. PTOKEN_USER TokenInfo = SlpGetTokenUser( hToken, NULL );
  233. if (TokenInfo != NULL) {
  234. PSID UserSid = TokenInfo->User.Sid;
  235. if(ConvertSidToStringSid( UserSid, &SidString ))
  236. {
  237. LONG lRet;
  238. HKEY phKeyCurrentUser;
  239. //
  240. // Impersonate the user before doing this.
  241. //
  242. if (ImpersonateLoggedOnUser(hToken)) {
  243. lRet = RegOpenKeyExW(
  244. HKEY_USERS,
  245. SidString,
  246. 0, // dwOptions
  247. MAXIMUM_ALLOWED,
  248. &phKeyCurrentUser
  249. );
  250. RevertToSelf();
  251. }
  252. else {
  253. lRet = GetLastError();
  254. if (ERROR_SUCCESS == lRet) {
  255. lRet = ERROR_INTERNAL_ERROR;
  256. }
  257. }
  258. LocalFree(SidString);
  259. if (ERROR_SUCCESS == lRet) {
  260. //
  261. // The profile is loaded. Ref it so it doesn't disappear.
  262. //
  263. PROFILEINFO pi;
  264. ZeroMemory (&pi, sizeof(pi));
  265. pi.dwSize = sizeof(pi);
  266. pi.lpUserName = lpUserName;
  267. fReturn = LoadUserProfile (hToken, &pi);
  268. if (!fReturn) {
  269. rc = GetLastError();
  270. } else {
  271. *hProfile = pi.hProfile;
  272. }
  273. RegCloseKey( phKeyCurrentUser );
  274. } else {
  275. //
  276. // The profile is not loaded. Load it.
  277. //
  278. if (SlpIsDomainUser( hToken, &DomainUser )) {
  279. if (DomainUser) {
  280. //
  281. // Determine the name of the DC for this domain
  282. //
  283. if (ImpersonateLoggedOnUser(hToken)) {
  284. if (ERROR_SUCCESS == (dwResult = DsGetDcName
  285. (NULL,
  286. lpDomainName,
  287. NULL,
  288. NULL,
  289. 0,
  290. &DomainControllerInfo
  291. ))) {
  292. lpServerName = DomainControllerInfo->DomainControllerName;
  293. b = TRUE;
  294. } else {
  295. SetLastError(dwResult);
  296. }
  297. RevertToSelf();
  298. }
  299. } else {
  300. lpServerName = NULL;
  301. b = TRUE;
  302. }
  303. }
  304. if (b) {
  305. //
  306. // Impersonate the user to get the information
  307. //
  308. if (ImpersonateLoggedOnUser(hToken)) {
  309. Status = NetUserGetInfo( lpServerName, lpUserName, 3, (LPBYTE *)&lpUserInfo );
  310. // we must revert before calling LoadUserProfile
  311. RevertToSelf();
  312. } else {
  313. Status = GetLastError();
  314. if (ERROR_SUCCESS == Status) {
  315. Status = ERROR_INTERNAL_ERROR;
  316. }
  317. }
  318. if (Status == ERROR_SUCCESS) {
  319. PROFILEINFO pi;
  320. ZeroMemory (&pi, sizeof(pi));
  321. pi.dwSize = sizeof(pi);
  322. pi.lpUserName = lpUserName;
  323. pi.lpProfilePath = lpUserInfo->usri3_profile;
  324. fReturn = LoadUserProfile (hToken, &pi);
  325. if (fReturn) {
  326. *hProfile = pi.hProfile;
  327. }
  328. NetApiBufferFree( lpUserInfo );
  329. }
  330. }
  331. }
  332. }
  333. }
  334. if(TokenInfo)
  335. {
  336. HeapFree( GetProcessHeap(), 0, TokenInfo );
  337. }
  338. }
  339. if (lpServerName) {
  340. NetApiBufferFree( DomainControllerInfo );
  341. }
  342. return( fReturn );
  343. }