Leaked source code of windows server 2003
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.

444 lines
12 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. optlogon.c
  5. Abstract:
  6. This module contains the shared rountines for the optimized logon.
  7. Author:
  8. Cenk Ergan (cenke) - 2001/05/07
  9. Environment:
  10. User Mode
  11. --*/
  12. #include <nt.h>
  13. #include <ntrtl.h>
  14. #include <nturtl.h>
  15. #include <windows.h>
  16. #include <ginacomn.h>
  17. //
  18. // The registry values under ProfileList\%UserSidString% checked when
  19. // determining if we should logon by cached credentials by default.
  20. //
  21. #define GC_PROFILE_LIST_PATH L"Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList"
  22. #define GC_NEXT_LOGON_CACHEABLE_VALUE_NAME L"NextLogonCacheable"
  23. #define GC_SYNC_LOGON_SCRIPT_VALUE_NAME L"RunLogonScriptSync"
  24. #define GC_OPTIMIZED_LOGON_VALUE_NAME L"OptimizedLogonStatus"
  25. /***************************************************************************\
  26. * GcCheckIfProfileAllowsCachedLogon
  27. *
  28. * Returns whether profile settings are not compatible with doing fast-cached
  29. * logons every logon, e.g. roaming profile, remote home directory etc.
  30. *
  31. * History:
  32. * 03-23-01 Cenke Created
  33. \***************************************************************************/
  34. DWORD
  35. GcCheckIfProfileAllowsCachedLogon(
  36. PUNICODE_STRING HomeDirectory,
  37. PUNICODE_STRING ProfilePath,
  38. PWCHAR UserSidString,
  39. PDWORD NextLogonCacheable
  40. )
  41. {
  42. DWORD ErrorCode;
  43. DWORD LogonCacheable;
  44. DWORD UserPreference;
  45. //
  46. // Start with the assumption that the logon is not cacheable.
  47. //
  48. ErrorCode = ERROR_SUCCESS;
  49. LogonCacheable = FALSE;
  50. //
  51. // Is the home directory on the network (i.e. a UNC path)?
  52. //
  53. if (HomeDirectory &&
  54. HomeDirectory->Length > 4 &&
  55. GcIsUNCPath(HomeDirectory->Buffer)) {
  56. goto cleanup;
  57. }
  58. //
  59. // Is the profile path on the network (i.e. a UNC path)?
  60. //
  61. if (ProfilePath &&
  62. ProfilePath->Length > 4 &&
  63. GcIsUNCPath(ProfilePath->Buffer)) {
  64. //
  65. // Check if the user has explicitly requested his roaming profile to
  66. // be local on this machine.
  67. //
  68. UserPreference = GcGetUserPreferenceValue(UserSidString);
  69. //
  70. // If user preference is not 0, then the roaming user profile is not
  71. // set to be local on this machine: we can't do optimized logon.
  72. //
  73. if (UserPreference) {
  74. goto cleanup;
  75. }
  76. }
  77. //
  78. // The logon is cacheable.
  79. //
  80. LogonCacheable = TRUE;
  81. cleanup:
  82. if (ErrorCode == ERROR_SUCCESS) {
  83. *NextLogonCacheable = LogonCacheable;
  84. }
  85. return ErrorCode;
  86. }
  87. /***************************************************************************\
  88. * GcCheckIfLogonScriptsRunSync
  89. *
  90. * Returns whether logons scripts are to be run synchronously.
  91. * Default is asynchronous.
  92. *
  93. * History:
  94. * 04-25-01 Cenke Created
  95. \***************************************************************************/
  96. BOOL
  97. GcCheckIfLogonScriptsRunSync(
  98. PWCHAR UserSidString
  99. )
  100. {
  101. DWORD ErrorCode;
  102. BOOL bSync = FALSE;
  103. ErrorCode = GcAccessProfileListUserSetting(UserSidString,
  104. FALSE,
  105. GC_SYNC_LOGON_SCRIPT_VALUE_NAME,
  106. &(DWORD)bSync);
  107. if (ErrorCode != ERROR_SUCCESS) {
  108. bSync = FALSE;
  109. }
  110. return bSync;
  111. }
  112. /***************************************************************************\
  113. * GcAccessProfileListUserSetting
  114. *
  115. * Queries or sets a DWORD value for the specified user under the local
  116. * machine profile list key.
  117. *
  118. * History:
  119. * 05-01-01 Cenke Created
  120. \***************************************************************************/
  121. DWORD
  122. GcAccessProfileListUserSetting (
  123. PWCHAR UserSidString,
  124. BOOL SetValue,
  125. PWCHAR ValueName,
  126. PDWORD Value
  127. )
  128. {
  129. HKEY ProfileListKey;
  130. HKEY UserProfileKey;
  131. ULONG Result;
  132. DWORD ErrorCode;
  133. DWORD ValueType;
  134. DWORD Size;
  135. //
  136. // Initialize locals.
  137. //
  138. UserProfileKey = NULL;
  139. ProfileListKey = NULL;
  140. //
  141. // Open the ProfileList registry key.
  142. //
  143. Result = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  144. GC_PROFILE_LIST_PATH,
  145. 0,
  146. KEY_READ,
  147. &ProfileListKey);
  148. if (Result != ERROR_SUCCESS) {
  149. ErrorCode = Result;
  150. goto cleanup;
  151. }
  152. //
  153. // Open the user's profile key under the ProfileList key using user's SID.
  154. //
  155. Result = RegOpenKeyEx(ProfileListKey,
  156. UserSidString,
  157. 0,
  158. KEY_READ | KEY_WRITE,
  159. &UserProfileKey);
  160. if (Result != ERROR_SUCCESS) {
  161. ErrorCode = Result;
  162. goto cleanup;
  163. }
  164. if (SetValue) {
  165. //
  166. // Set the value.
  167. //
  168. Result = RegSetValueEx(UserProfileKey,
  169. ValueName,
  170. 0,
  171. REG_DWORD,
  172. (BYTE *) Value,
  173. sizeof(DWORD));
  174. if (Result != ERROR_SUCCESS) {
  175. ErrorCode = Result;
  176. goto cleanup;
  177. }
  178. } else {
  179. //
  180. // Query the value.
  181. //
  182. Size = sizeof(DWORD);
  183. Result = RegQueryValueEx(UserProfileKey,
  184. ValueName,
  185. 0,
  186. &ValueType,
  187. (BYTE *) Value,
  188. &Size);
  189. if (Result != ERROR_SUCCESS) {
  190. ErrorCode = Result;
  191. goto cleanup;
  192. }
  193. }
  194. //
  195. // We are done.
  196. //
  197. ErrorCode = ERROR_SUCCESS;
  198. cleanup:
  199. if (ProfileListKey) {
  200. RegCloseKey(ProfileListKey);
  201. }
  202. if (UserProfileKey) {
  203. RegCloseKey(UserProfileKey);
  204. }
  205. return ErrorCode;
  206. }
  207. /***************************************************************************\
  208. * GcGetNextLogonCacheable
  209. *
  210. * Returns whether we are allowed to perform a cached logon at the next logon.
  211. * For instance, if last time we logged on using cached credentials, our attempt
  212. * at background logon failed for a reason (e.g. password expired) we want to
  213. * force the user to hit the network logon path to deal with.
  214. *
  215. * History:
  216. * 03-23-01 Cenke Created
  217. \***************************************************************************/
  218. DWORD
  219. GcGetNextLogonCacheable(
  220. PWCHAR UserSidString,
  221. PDWORD NextLogonCacheable
  222. )
  223. {
  224. DWORD ErrorCode;
  225. ErrorCode = GcAccessProfileListUserSetting(UserSidString,
  226. FALSE,
  227. GC_NEXT_LOGON_CACHEABLE_VALUE_NAME,
  228. NextLogonCacheable);
  229. return ErrorCode;
  230. }
  231. /***************************************************************************\
  232. * GcSetNextLogonCacheable
  233. *
  234. * Sets whether we are allowed to perform a cached logon at the next logon.
  235. * For instance, if after logging on the user with cached credentials our attempt
  236. * at background logon fails for a reason (e.g. password expired) we want to
  237. * force the user to hit the network logon path to deal with.
  238. *
  239. * History:
  240. * 03-23-01 Cenke Created
  241. \***************************************************************************/
  242. DWORD
  243. GcSetNextLogonCacheable(
  244. PWCHAR UserSidString,
  245. DWORD NextLogonCacheable
  246. )
  247. {
  248. DWORD ErrorCode;
  249. ErrorCode = GcAccessProfileListUserSetting(UserSidString,
  250. TRUE,
  251. GC_NEXT_LOGON_CACHEABLE_VALUE_NAME,
  252. &NextLogonCacheable);
  253. return ErrorCode;
  254. }
  255. /***************************************************************************\
  256. * GcSetOptimizedLogonStatus
  257. *
  258. * Saves optimized logon status for the user in the profile list.
  259. *
  260. * History:
  261. * 03-23-01 Cenke Created
  262. \***************************************************************************/
  263. DWORD
  264. GcSetOptimizedLogonStatus(
  265. PWCHAR UserSidString,
  266. DWORD OptimizedLogonStatus
  267. )
  268. {
  269. DWORD ErrorCode;
  270. ErrorCode = GcAccessProfileListUserSetting(UserSidString,
  271. TRUE,
  272. GC_OPTIMIZED_LOGON_VALUE_NAME,
  273. &OptimizedLogonStatus);
  274. return ErrorCode;
  275. }
  276. /***************************************************************************\
  277. * GcGetUserPreferenceValue
  278. *
  279. * Gets user preference flags on whether the user's roaming profile is set
  280. * to be local on this machine.
  281. *
  282. * History:
  283. * 05-01-01 Cenke Copied from gina\userenv\profile.cpp
  284. \***************************************************************************/
  285. #define SYSTEM_POLICIES_KEY TEXT("Software\\Policies\\Microsoft\\Windows\\System")
  286. #define PROFILE_LOCALONLY TEXT("LocalProfile")
  287. #define USER_PREFERENCE TEXT("UserPreference")
  288. #define USERINFO_LOCAL 0
  289. #define USERINFO_UNDEFINED 99
  290. const TCHAR c_szBAK[] = TEXT(".bak");
  291. DWORD
  292. GcGetUserPreferenceValue(
  293. LPTSTR SidString
  294. )
  295. {
  296. TCHAR LocalProfileKey[MAX_PATH];
  297. DWORD RegErr, dwType, dwSize, dwTmpVal, dwRetVal = USERINFO_UNDEFINED;
  298. LPTSTR lpEnd;
  299. HKEY hkeyProfile, hkeyPolicy;
  300. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  301. SYSTEM_POLICIES_KEY,
  302. 0, KEY_READ,
  303. &hkeyPolicy) == ERROR_SUCCESS) {
  304. dwSize = sizeof(dwTmpVal);
  305. RegQueryValueEx(hkeyPolicy,
  306. PROFILE_LOCALONLY,
  307. NULL, &dwType,
  308. (LPBYTE) &dwTmpVal,
  309. &dwSize);
  310. RegCloseKey (hkeyPolicy);
  311. if (dwTmpVal == 1) {
  312. dwRetVal = USERINFO_LOCAL;
  313. return dwRetVal;
  314. }
  315. }
  316. if (SidString != NULL) {
  317. //
  318. // Query for the UserPreference value
  319. //
  320. lstrcpy(LocalProfileKey, GC_PROFILE_LIST_PATH);
  321. lpEnd = GcCheckSlash (LocalProfileKey);
  322. lstrcpy(lpEnd, SidString);
  323. RegErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  324. LocalProfileKey,
  325. 0,
  326. KEY_READ,
  327. &hkeyProfile);
  328. if (RegErr == ERROR_SUCCESS) {
  329. dwSize = sizeof(dwRetVal);
  330. RegQueryValueEx(hkeyProfile,
  331. USER_PREFERENCE,
  332. NULL,
  333. &dwType,
  334. (LPBYTE) &dwRetVal,
  335. &dwSize);
  336. RegCloseKey (hkeyProfile);
  337. }
  338. lstrcat(LocalProfileKey, c_szBAK);
  339. RegErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  340. LocalProfileKey,
  341. 0,
  342. KEY_READ,
  343. &hkeyProfile);
  344. if (RegErr == ERROR_SUCCESS) {
  345. dwSize = sizeof(dwRetVal);
  346. RegQueryValueEx(hkeyProfile,
  347. USER_PREFERENCE,
  348. NULL,
  349. &dwType,
  350. (LPBYTE) &dwRetVal,
  351. &dwSize);
  352. RegCloseKey (hkeyProfile);
  353. }
  354. }
  355. return dwRetVal;
  356. }