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.

503 lines
18 KiB

  1. // --------------------------------------------------------------------------
  2. // Module Name: LogonIPC.cpp
  3. //
  4. // Copyright (c) 1999, Microsoft Corporation
  5. //
  6. // Class that implements communication between an external process and the
  7. // GINA logon dialog.
  8. //
  9. // History: 1999-08-20 vtan created
  10. // 2000-01-31 vtan moved from Neptune to Whistler
  11. // --------------------------------------------------------------------------
  12. #include "priv.h"
  13. #include "limits.h"
  14. #include "LogonIPC.h"
  15. #include "GinaIPC.h"
  16. // --------------------------------------------------------------------------
  17. // CLogonIPC::CLogonIPC
  18. //
  19. // Arguments: <none>
  20. //
  21. // Returns: <none>
  22. //
  23. // Purpose: Initializes the CLogonIPC class.
  24. //
  25. // History: 1999-08-20 vtan created
  26. // --------------------------------------------------------------------------
  27. CLogonIPC::CLogonIPC (void) :
  28. _iLogonAttemptCount(0),
  29. _hwndLogonService(NULL)
  30. {
  31. }
  32. // --------------------------------------------------------------------------
  33. // CLogonIPC::~CLogonIPC
  34. //
  35. // Arguments: <none>
  36. //
  37. // Returns: <none>
  38. //
  39. // Purpose: Releases any resources used by the CLogonIPC class.
  40. //
  41. // History: 1999-08-20 vtan created
  42. // --------------------------------------------------------------------------
  43. CLogonIPC::~CLogonIPC (void)
  44. {
  45. }
  46. // --------------------------------------------------------------------------
  47. // CLogonIPC::IsLogonServiceAvailable
  48. //
  49. // Arguments: <none>
  50. //
  51. // Returns: bool = Presence or abscence.
  52. //
  53. // Purpose: Finds out if the window providing logon service in GINA is
  54. // available. The determination is not performed statically but
  55. // rather dynamically which allows this class to be hosted by
  56. // the actual window providing the service as well.
  57. //
  58. // History: 1999-08-20 vtan created
  59. // --------------------------------------------------------------------------
  60. bool CLogonIPC::IsLogonServiceAvailable (void)
  61. {
  62. _hwndLogonService = FindWindow(NULL, TEXT("GINA Logon"));
  63. return(_hwndLogonService != NULL);
  64. }
  65. // --------------------------------------------------------------------------
  66. // CLogonIPC::IsUserLoggedOn
  67. //
  68. // Arguments: pwszUsername = User name.
  69. // pwszDomain = User domain.
  70. //
  71. // Returns: bool = Presence or abscence.
  72. //
  73. // Purpose: Finds out if the given user is logged onto the system. You
  74. // may pass a NULL pwszDomain for the local machine.
  75. //
  76. // History: 1999-08-20 vtan created
  77. // --------------------------------------------------------------------------
  78. bool CLogonIPC::IsUserLoggedOn (const WCHAR *pwszUsername, const WCHAR *pwszDomain)
  79. {
  80. LOGONIPC_USERID logonIPCUserID;
  81. PackageIdentification(pwszUsername, pwszDomain, &logonIPCUserID);
  82. return(SendToLogonService(LOGON_QUERY_LOGGED_ON, &logonIPCUserID, sizeof(logonIPCUserID), true));
  83. }
  84. // --------------------------------------------------------------------------
  85. // CLogonIPC::LogUserOn
  86. //
  87. // Arguments: pwszUsername = User name.
  88. // pwszDomain = User domain.
  89. // pwszPassword = User password. This is passed clear text.
  90. // Once encoded the password buffer is
  91. // zeroed. This function owns the memory that
  92. // you pass in.
  93. //
  94. // Returns: bool = Success or failure.
  95. //
  96. // Purpose: Attempts to log the user with the given credentials onto the
  97. // system. The password buffer is owned by this function for the
  98. // purpose of clearing it once encoded. Failed logon attempts
  99. // cause a counter to be incremented and a subsequent delay using
  100. // that counter is done to slow dictionary attacks.
  101. //
  102. // History: 1999-08-20 vtan created
  103. // --------------------------------------------------------------------------
  104. bool CLogonIPC::LogUserOn (const WCHAR *pwszUsername, const WCHAR *pwszDomain, WCHAR *pwszPassword)
  105. {
  106. bool fResult;
  107. UNICODE_STRING passwordString;
  108. LOGONIPC_CREDENTIALS logonIPCCredentials;
  109. PackageIdentification(pwszUsername, pwszDomain, &logonIPCCredentials.userID);
  110. // Limit the password to 127 characters. RtlRunEncodeUnicodeString
  111. // does not support strings greater than 127 characters.
  112. //
  113. // REVIEW (jeffreys) I don't think that's true.
  114. StringCchCopyNEx(logonIPCCredentials.wszPassword, ARRAYSIZE(logonIPCCredentials.wszPassword), pwszPassword, 127, NULL, NULL, STRSAFE_FILL_BEHIND_NULL);
  115. ZeroMemory(pwszPassword, (lstrlen(pwszPassword) + 1) * sizeof(WCHAR));
  116. logonIPCCredentials.iPasswordLength = lstrlen(logonIPCCredentials.wszPassword);
  117. logonIPCCredentials.ucPasswordSeed = 0;
  118. passwordString.Buffer = logonIPCCredentials.wszPassword;
  119. passwordString.Length = (USHORT)(logonIPCCredentials.iPasswordLength * sizeof(WCHAR));
  120. passwordString.MaximumLength = sizeof(logonIPCCredentials.wszPassword);
  121. RtlRunEncodeUnicodeString(&logonIPCCredentials.ucPasswordSeed, &passwordString);
  122. fResult = SendToLogonService(LOGON_LOGON_USER, &logonIPCCredentials, sizeof(logonIPCCredentials), false);
  123. if (!fResult)
  124. {
  125. Sleep(_iLogonAttemptCount * 1000);
  126. if (_iLogonAttemptCount < 5)
  127. {
  128. _iLogonAttemptCount++;
  129. }
  130. }
  131. return fResult;
  132. }
  133. // --------------------------------------------------------------------------
  134. // CLogonIPC::LogUserOff
  135. //
  136. // Arguments: pwszUsername = User name.
  137. // pwszDomain = User domain.
  138. //
  139. // Returns: bool = Success or failure.
  140. //
  141. // Purpose: Attempts to log the given user off the system. This will fail
  142. // if they aren't logged on.
  143. //
  144. // History: 1999-08-20 vtan created
  145. // --------------------------------------------------------------------------
  146. bool CLogonIPC::LogUserOff (const WCHAR *pwszUsername, const WCHAR *pwszDomain)
  147. {
  148. LOGONIPC_USERID logonIPCUserID;
  149. PackageIdentification(pwszUsername, pwszDomain, &logonIPCUserID);
  150. return(SendToLogonService(LOGON_LOGOFF_USER, &logonIPCUserID, sizeof(logonIPCUserID), true));
  151. }
  152. // --------------------------------------------------------------------------
  153. // CLogonIPC::TestBlankPassword
  154. //
  155. // Arguments: pwszUsername = User name.
  156. // pwszDomain = User domain.
  157. //
  158. // Returns: bool = Success or failure.
  159. //
  160. // Purpose: Attempts to log the given user on the system with a blank
  161. // password. The token is then dump and failure/success returned.
  162. //
  163. // History: 2000-03-09 vtan created
  164. // --------------------------------------------------------------------------
  165. bool CLogonIPC::TestBlankPassword (const WCHAR *pwszUsername, const WCHAR *pwszDomain)
  166. {
  167. LOGONIPC_USERID logonIPCUserID;
  168. PackageIdentification(pwszUsername, pwszDomain, &logonIPCUserID);
  169. return(SendToLogonService(LOGON_TEST_BLANK_PASSWORD, &logonIPCUserID, sizeof(logonIPCUserID), true));
  170. }
  171. // --------------------------------------------------------------------------
  172. // CLogonIPC::TestInteractiveLogonAllowed
  173. //
  174. // Arguments: pwszUsername = User name.
  175. // pwszDomain = User domain.
  176. //
  177. // Returns: bool
  178. //
  179. // Purpose: Test whether the user has interactive logon rights to this
  180. // machine. The presence of SeDenyInteractiveLogonRight
  181. // determines this - NOT the presence of SeInteractiveLogonRight.
  182. //
  183. // History: 2000-08-15 vtan created
  184. // --------------------------------------------------------------------------
  185. bool CLogonIPC::TestInteractiveLogonAllowed (const WCHAR *pwszUsername, const WCHAR *pwszDomain)
  186. {
  187. LOGONIPC_USERID logonIPCUserID;
  188. PackageIdentification(pwszUsername, pwszDomain, &logonIPCUserID);
  189. return(SendToLogonService(LOGON_TEST_INTERACTIVE_LOGON_ALLOWED, &logonIPCUserID, sizeof(logonIPCUserID), true));
  190. }
  191. // --------------------------------------------------------------------------
  192. // CLogonIPC::TestEjectAllowed
  193. //
  194. // Arguments: <none>
  195. //
  196. // Returns: bool = Success or failure.
  197. //
  198. // Purpose: Tests whether the computer is ejectable (docked laptop).
  199. //
  200. // History: 2001-01-10 vtan created
  201. // --------------------------------------------------------------------------
  202. bool CLogonIPC::TestEjectAllowed (void)
  203. {
  204. LOGONIPC logonIPC;
  205. return(SendToLogonService(LOGON_TEST_EJECT_ALLOWED, &logonIPC, sizeof(logonIPC), true));
  206. }
  207. // --------------------------------------------------------------------------
  208. // CLogonIPC::TestShutdownAllowed
  209. //
  210. // Arguments: <none>
  211. //
  212. // Returns: bool = Success or failure.
  213. //
  214. // Purpose: Tests whether the computer can be shut down.
  215. //
  216. // History: 2001-02-22 vtan created
  217. // --------------------------------------------------------------------------
  218. bool CLogonIPC::TestShutdownAllowed (void)
  219. {
  220. LOGONIPC logonIPC;
  221. return(SendToLogonService(LOGON_TEST_SHUTDOWN_ALLOWED, &logonIPC, sizeof(logonIPC), true));
  222. }
  223. // --------------------------------------------------------------------------
  224. // CLogonIPC::TurnOffComputer
  225. //
  226. // Arguments: <none>
  227. //
  228. // Returns: bool = Success or failure.
  229. //
  230. // Purpose: Brings up the "Turn Off Computer" dialog and allows the user
  231. // to choose what to do.
  232. //
  233. // History: 2000-04-20 vtan created
  234. // --------------------------------------------------------------------------
  235. bool CLogonIPC::TurnOffComputer (void)
  236. {
  237. LOGONIPC logonIPC;
  238. return(SendToLogonService(LOGON_TURN_OFF_COMPUTER, &logonIPC, sizeof(logonIPC), false));
  239. }
  240. // --------------------------------------------------------------------------
  241. // CLogonIPC::EjectComputer
  242. //
  243. // Arguments: <none>
  244. //
  245. // Returns: bool = Success or failure.
  246. //
  247. // Purpose: Ejects the computer (docked laptop).
  248. //
  249. // History: 2001-01-10 vtan created
  250. // --------------------------------------------------------------------------
  251. bool CLogonIPC::EjectComputer (void)
  252. {
  253. LOGONIPC logonIPC;
  254. return(SendToLogonService(LOGON_EJECT_COMPUTER, &logonIPC, sizeof(logonIPC), true));
  255. }
  256. // --------------------------------------------------------------------------
  257. // CLogonIPC::SignalUIHostFailure
  258. //
  259. // Arguments: <none>
  260. //
  261. // Returns: bool
  262. //
  263. // Purpose: Called when the UI host has an error that it cannot recover
  264. // from. This signals msgina to fall back to classic mode.
  265. //
  266. // History: 2000-03-09 vtan created
  267. // --------------------------------------------------------------------------
  268. bool CLogonIPC::SignalUIHostFailure (void)
  269. {
  270. LOGONIPC logonIPC;
  271. return(SendToLogonService(LOGON_SIGNAL_UIHOST_FAILURE, &logonIPC, sizeof(logonIPC), true));
  272. }
  273. // --------------------------------------------------------------------------
  274. // CLogonIPC::AllowExternalCredentials
  275. //
  276. // Arguments: <none>
  277. //
  278. // Returns: bool = Success or failure.
  279. //
  280. // Purpose:
  281. //
  282. // History: 2000-06-26 vtan created
  283. // --------------------------------------------------------------------------
  284. bool CLogonIPC::AllowExternalCredentials (void)
  285. {
  286. LOGONIPC logonIPC;
  287. return(SendToLogonService(LOGON_ALLOW_EXTERNAL_CREDENTIALS, &logonIPC, sizeof(logonIPC), true));
  288. }
  289. // --------------------------------------------------------------------------
  290. // CLogonIPC::RequestExternalCredentials
  291. //
  292. // Arguments: <none>
  293. //
  294. // Returns: bool
  295. //
  296. // Purpose:
  297. //
  298. // History: 2000-06-26 vtan created
  299. // --------------------------------------------------------------------------
  300. bool CLogonIPC::RequestExternalCredentials (void)
  301. {
  302. LOGONIPC logonIPC;
  303. return(SendToLogonService(LOGON_REQUEST_EXTERNAL_CREDENTIALS, &logonIPC, sizeof(logonIPC), true));
  304. }
  305. // --------------------------------------------------------------------------
  306. // CLogonIPC::PackageIdentification
  307. //
  308. // Arguments: pwszUsername = User name.
  309. // pwszDomain = User domain.
  310. // pIdentification = Pointer to a LOGONIPC_USERID struct
  311. // which is masked as void* to allow
  312. // LogonIPC.h to not expose this detail.
  313. //
  314. // Returns: <none>
  315. //
  316. // Purpose: Takes the user name and domain and packages them into the
  317. // given struct. If no domain is given the a zero length string
  318. // is used which indicates to the logon service provider that
  319. // the local machine is desired.
  320. //
  321. // Now parses the user name given. If the user has "\" then it
  322. // is assumed to be of the form "DOMAIN\USER". If the user has
  323. // "@" then it is assumed to be a UPN name.
  324. //
  325. // History: 1999-08-20 vtan created
  326. // 2000-06-27 vtan added UPN and DOMAIN parsing support
  327. // --------------------------------------------------------------------------
  328. void CLogonIPC::PackageIdentification (const WCHAR *pwszUsername, const WCHAR *pwszDomain, void *pIdentification)
  329. {
  330. LPTSTR psz;
  331. LOGONIPC_USERID *pLogonIPCUserID;
  332. pLogonIPCUserID = reinterpret_cast<LOGONIPC_USERID*>(pIdentification);
  333. pLogonIPCUserID->wszUsername[0] = L'\0';
  334. pLogonIPCUserID->wszDomain[0] = L'\0';
  335. psz = StrChrW(pwszUsername, L'\\');
  336. if (psz)
  337. {
  338. // stuff after the '\' is the username
  339. StringCchCopyW(pLogonIPCUserID->wszUsername, ARRAYSIZE(pLogonIPCUserID->wszUsername), psz + 1);
  340. // stuff before the '\' is the domain name
  341. StringCchCopyNW(pLogonIPCUserID->wszDomain, ARRAYSIZE(pLogonIPCUserID->wszDomain), pwszUsername, psz - pwszUsername);
  342. }
  343. else
  344. {
  345. StringCchCopyW(pLogonIPCUserID->wszUsername, ARRAYSIZE(pLogonIPCUserID->wszUsername), pwszUsername);
  346. }
  347. }
  348. // --------------------------------------------------------------------------
  349. // CLogonIPC::SendToLogonService
  350. //
  351. // Arguments: wQueryType = What type of service we are interested in.
  352. // pData = Pointer to the data.
  353. // wDataSize = Size of the data.
  354. // fBlock = Block message pump or not.
  355. //
  356. // Returns: bool = Success or failure.
  357. //
  358. // Purpose: Takes the package data and sends the message to the logon
  359. // service provider and receives the result. The logon service
  360. // provider started this process and reads this process' memory
  361. // directly (like a debugger would).
  362. //
  363. // This function should block the message pump because if it
  364. // processes another state change message while waiting for a
  365. // response it could destroy data.
  366. //
  367. // History: 1999-08-20 vtan created
  368. // 2001-06-22 vtan changed to SendMessageTimeout
  369. // 2001-06-28 vtan added block parameter
  370. // --------------------------------------------------------------------------
  371. bool CLogonIPC::SendToLogonService (WORD wQueryType, void *pData, WORD wDataSize, bool fBlock)
  372. {
  373. bool fResult;
  374. fResult = IsLogonServiceAvailable();
  375. if (fResult)
  376. {
  377. DWORD_PTR dwResult;
  378. reinterpret_cast<LOGONIPC*>(pData)->fResult = false;
  379. // WARNING: Danger Will Robinson.
  380. // Do NOT change INT_MAX to INFINITE. INT_MAX is a SIGNED number.
  381. // INFINITE is an UNSIGNED number. Despite the SDK and prototype
  382. // of SendMessageTimeout this timeout value is a SIGNED number.
  383. // Passing in an unsigned number causes the timeout to be
  384. // ignored and the function returns with a timeout.
  385. (LRESULT)SendMessageTimeout(_hwndLogonService,
  386. WM_LOGONSERVICEREQUEST,
  387. MAKEWPARAM(wDataSize, wQueryType),
  388. reinterpret_cast<LPARAM>(pData),
  389. fBlock ? SMTO_BLOCK : SMTO_NORMAL,
  390. INT_MAX, // See above warning.
  391. &dwResult);
  392. fResult = (reinterpret_cast<LOGONIPC*>(pData)->fResult != FALSE);
  393. }
  394. return(fResult);
  395. }
  396. // --------------------------------------------------------------------------
  397. // CLogonIPC::PostToLogonService
  398. //
  399. // Arguments: wQueryType = What type of service we are interested in.
  400. // pData = Pointer to the data.
  401. // wDataSize = Size of the data.
  402. //
  403. // Returns: <none>
  404. //
  405. // Purpose: Takes the package data and posts the message to the logon
  406. // service provider and receives the result. The logon service
  407. // provider started this process and reads this process' memory
  408. // directly (like a debugger would).
  409. //
  410. // History: 1999-11-26 vtan created
  411. // --------------------------------------------------------------------------
  412. void CLogonIPC::PostToLogonService (WORD wQueryType, void *pData, WORD wDataSize)
  413. {
  414. if (IsLogonServiceAvailable())
  415. {
  416. TBOOL(PostMessage(_hwndLogonService, WM_LOGONSERVICEREQUEST, MAKEWPARAM(wDataSize, wQueryType), reinterpret_cast<LPARAM>(pData)));
  417. }
  418. }