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.

527 lines
16 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. password.cxx
  5. Abstract:
  6. password
  7. Author:
  8. Larry Zhu (LZhu) December 1, 2001 Created
  9. Environment:
  10. User Mode
  11. Revision History:
  12. --*/
  13. #include "precomp.hxx"
  14. #pragma hdrstop
  15. #include "password.hxx"
  16. VOID
  17. Usage(
  18. IN PCSTR pszApp
  19. )
  20. {
  21. DebugPrintf(SSPI_ERROR, "\n\nUsage: %s [-p<package>] [-s] [-l] -r "
  22. "-c<client name> -C<client realm> -o<old password> -n<new password>\n"
  23. "Remarks: package default to NTLM, use -s to set password, -l local only\n"
  24. " -r not impernating (self)\n\n", pszApp);
  25. exit(-1);
  26. }
  27. NTSTATUS
  28. MsvChangePasswordUser(
  29. IN HANDLE LogonHandle,
  30. IN ULONG PackageId,
  31. IN BOOLEAN bCacheOnly,
  32. IN UNICODE_STRING* pDomainName,
  33. IN UNICODE_STRING* pUserName,
  34. IN UNICODE_STRING* pOldPassword,
  35. IN UNICODE_STRING* pNewPassword,
  36. IN BOOLEAN bImpersonating
  37. )
  38. {
  39. TNtStatus Status = STATUS_UNSUCCESSFUL;
  40. NTSTATUS SubStatus = STATUS_UNSUCCESSFUL;
  41. MSV1_0_CHANGEPASSWORD_RESPONSE* pResponse = NULL ;
  42. ULONG cbResponseSize;
  43. MSV1_0_CHANGEPASSWORD_REQUEST* pChangeRequest = NULL;
  44. ULONG cbChangeRequestSize;
  45. DebugPrintf(SSPI_LOG, "MsvChangePasswordUser PackageId %d, DomainName %wZ, "
  46. "UserName %wZ, OldPass %wZ, NewPass %wZ, Impersonating %s\n",
  47. PackageId, pDomainName, pUserName, pOldPassword, pNewPassword, bImpersonating ? "true" : "false");
  48. cbChangeRequestSize = ROUND_UP_COUNT(sizeof(MSV1_0_CHANGEPASSWORD_REQUEST), sizeof(DWORD))
  49. + pUserName->Length
  50. + pDomainName->Length
  51. + pOldPassword->Length
  52. + pNewPassword->Length;
  53. pChangeRequest = (MSV1_0_CHANGEPASSWORD_REQUEST*) new CHAR[cbChangeRequestSize];
  54. Status DBGCHK = pChangeRequest ? STATUS_SUCCESS : STATUS_NO_MEMORY;
  55. if (NT_SUCCESS(Status))
  56. {
  57. RtlZeroMemory(pChangeRequest, cbChangeRequestSize);
  58. pChangeRequest->MessageType = bCacheOnly ? MsV1_0ChangeCachedPassword : MsV1_0ChangePassword;
  59. pChangeRequest->AccountName = *pUserName;
  60. pChangeRequest->AccountName.Buffer = (PWSTR) ROUND_UP_POINTER(sizeof(MSV1_0_CHANGEPASSWORD_REQUEST) + (PBYTE) pChangeRequest, sizeof(DWORD));
  61. RtlCopyMemory(
  62. pChangeRequest->AccountName.Buffer,
  63. pUserName->Buffer,
  64. pUserName->Length
  65. );
  66. pChangeRequest->DomainName = *pDomainName;
  67. pChangeRequest->DomainName.Buffer = pChangeRequest->AccountName.Buffer + pChangeRequest->AccountName.Length / sizeof(WCHAR);
  68. RtlCopyMemory(
  69. pChangeRequest->DomainName.Buffer,
  70. pDomainName->Buffer,
  71. pDomainName->Length
  72. );
  73. pChangeRequest->OldPassword = *pOldPassword;
  74. pChangeRequest->OldPassword.Buffer = pChangeRequest->DomainName.Buffer + pChangeRequest->DomainName.Length / sizeof(WCHAR);
  75. RtlCopyMemory(
  76. pChangeRequest->OldPassword.Buffer,
  77. pOldPassword->Buffer,
  78. pOldPassword->Length
  79. );
  80. pChangeRequest->NewPassword = *pNewPassword;
  81. pChangeRequest->NewPassword.Buffer = pChangeRequest->OldPassword.Buffer + pChangeRequest->OldPassword.Length / sizeof(WCHAR);
  82. RtlCopyMemory(
  83. pChangeRequest->NewPassword.Buffer,
  84. pNewPassword->Buffer,
  85. pNewPassword->Length
  86. );
  87. //
  88. // We are running as the caller, so state we are impersonating
  89. //
  90. pChangeRequest->Impersonating = bImpersonating;
  91. DebugPrintf(SSPI_LOG, "Msg type %#x\n", pChangeRequest->MessageType);
  92. Status DBGCHK = LsaCallAuthenticationPackage(
  93. LogonHandle,
  94. PackageId,
  95. pChangeRequest,
  96. cbChangeRequestSize,
  97. (VOID**) &pResponse,
  98. &cbResponseSize,
  99. &SubStatus
  100. );
  101. }
  102. if (NT_SUCCESS(Status))
  103. {
  104. if (pResponse && pResponse->PasswordInfoValid)
  105. {
  106. DebugPrintf(SSPI_LOG, "SubStatus %#x, MinPasswordLength %d, PasswordHistoryLength %d\n",
  107. SubStatus,
  108. pResponse->DomainPasswordInfo.MinPasswordLength,
  109. pResponse->DomainPasswordInfo.PasswordHistoryLength);
  110. DebugPrintSysTimeAsLocalTime(SSPI_LOG, "MaxPasswordAge ", &pResponse->DomainPasswordInfo.MaxPasswordAge);
  111. DebugPrintSysTimeAsLocalTime(SSPI_LOG, "MinPasswordAge ", &pResponse->DomainPasswordInfo.MinPasswordAge);
  112. }
  113. Status DBGCHK = SubStatus;
  114. }
  115. else
  116. {
  117. DebugPrintf(SSPI_LOG, "SubStatus %#x\n", SubStatus);
  118. }
  119. if (pResponse)
  120. {
  121. LsaFreeReturnBuffer(pResponse);
  122. }
  123. if (pChangeRequest)
  124. {
  125. delete [] pChangeRequest;
  126. }
  127. return Status;
  128. }
  129. NTSTATUS
  130. KerbChangePasswordUser(
  131. IN HANDLE LogonHandle,
  132. IN ULONG PackageId,
  133. IN BOOLEAN bImpersonating,
  134. IN UNICODE_STRING* pDomainName,
  135. IN UNICODE_STRING* pUserName,
  136. IN UNICODE_STRING* pOldPassword,
  137. IN UNICODE_STRING* pNewPassword
  138. )
  139. {
  140. TNtStatus Status = STATUS_UNSUCCESSFUL;
  141. NTSTATUS SubStatus = STATUS_UNSUCCESSFUL;
  142. PVOID pResponse = NULL ;
  143. ULONG cbResponseSize;
  144. PKERB_CHANGEPASSWORD_REQUEST pChangeRequest = NULL;
  145. ULONG cbChangeRequestSize;
  146. DebugPrintf(SSPI_LOG, "KerbChangePasswordUser PackageId %d, DomainName %wZ, "
  147. "UserName %wZ, OldPass %wZ, NewPass %wZ, Impersonating %s\n",
  148. PackageId, pDomainName, pUserName, pOldPassword, pNewPassword, bImpersonating ? "true" : "false");
  149. cbChangeRequestSize = ROUND_UP_COUNT(sizeof(KERB_CHANGEPASSWORD_REQUEST), sizeof(DWORD))
  150. + pUserName->Length + pDomainName->Length
  151. + pOldPassword->Length + pNewPassword->Length;
  152. pChangeRequest = (PKERB_CHANGEPASSWORD_REQUEST) new CHAR[cbChangeRequestSize];
  153. Status DBGCHK = pChangeRequest ? STATUS_SUCCESS : STATUS_NO_MEMORY;
  154. if (NT_SUCCESS(Status))
  155. {
  156. RtlZeroMemory(pChangeRequest, cbChangeRequestSize);
  157. pChangeRequest->MessageType = KerbChangePasswordMessage;
  158. pChangeRequest->AccountName = *pUserName;
  159. pChangeRequest->AccountName.Buffer = (PWSTR) ROUND_UP_POINTER(sizeof(KERB_CHANGEPASSWORD_REQUEST) + (PBYTE) pChangeRequest, sizeof(DWORD));
  160. RtlCopyMemory(
  161. pChangeRequest->AccountName.Buffer,
  162. pUserName->Buffer,
  163. pUserName->Length
  164. );
  165. pChangeRequest->DomainName = *pDomainName;
  166. pChangeRequest->DomainName.Buffer = pChangeRequest->AccountName.Buffer + pChangeRequest->AccountName.Length / sizeof(WCHAR);
  167. RtlCopyMemory(
  168. pChangeRequest->DomainName.Buffer,
  169. pDomainName->Buffer,
  170. pDomainName->Length
  171. );
  172. pChangeRequest->OldPassword = *pOldPassword;
  173. pChangeRequest->OldPassword.Buffer = pChangeRequest->DomainName.Buffer + pChangeRequest->DomainName.Length / sizeof(WCHAR);
  174. RtlCopyMemory(
  175. pChangeRequest->OldPassword.Buffer,
  176. pOldPassword->Buffer,
  177. pOldPassword->Length
  178. );
  179. pChangeRequest->NewPassword = *pNewPassword;
  180. pChangeRequest->NewPassword.Buffer = pChangeRequest->OldPassword.Buffer + pChangeRequest->OldPassword.Length / sizeof(WCHAR);
  181. RtlCopyMemory(
  182. pChangeRequest->NewPassword.Buffer,
  183. pNewPassword->Buffer,
  184. pNewPassword->Length
  185. );
  186. //
  187. // We are running as the caller, so state we are impersonating
  188. //
  189. pChangeRequest->Impersonating = bImpersonating;
  190. Status DBGCHK = LsaCallAuthenticationPackage(
  191. LogonHandle,
  192. PackageId,
  193. pChangeRequest,
  194. cbChangeRequestSize,
  195. &pResponse,
  196. &cbResponseSize,
  197. &SubStatus
  198. );
  199. }
  200. if (NT_SUCCESS(Status))
  201. {
  202. Status DBGCHK = SubStatus;
  203. }
  204. else
  205. {
  206. DebugPrintf(SSPI_LOG, "SubStatus %#x\n", SubStatus);
  207. }
  208. if (pResponse)
  209. {
  210. LsaFreeReturnBuffer(pResponse);
  211. }
  212. if (pChangeRequest)
  213. {
  214. delete [] pChangeRequest;
  215. }
  216. return Status;
  217. }
  218. NTSTATUS
  219. KerbSetPasswordUser(
  220. IN HANDLE LogonHandle,
  221. IN ULONG PackageId,
  222. IN UNICODE_STRING* pDomainName,
  223. IN UNICODE_STRING* pUserName,
  224. IN UNICODE_STRING* pNewPassword,
  225. IN OPTIONAL PCredHandle pCredentialsHandle
  226. )
  227. {
  228. TNtStatus Status = STATUS_UNSUCCESSFUL;
  229. NTSTATUS SubStatus = STATUS_UNSUCCESSFUL;
  230. PVOID pResponse = NULL ;
  231. ULONG cbResponseSize = NULL;
  232. PKERB_SETPASSWORD_REQUEST pSetRequest = NULL;
  233. ULONG cbChangeSize;
  234. DebugPrintf(SSPI_LOG, "KerbSetPasswordUser PackageId %d, DomainName %wZ, "
  235. "UserName %wZ, NewPassword %wZ, CredHandle %p\n",
  236. PackageId, pDomainName, pUserName, pNewPassword, pCredentialsHandle);
  237. cbChangeSize = ROUND_UP_COUNT(sizeof(KERB_SETPASSWORD_REQUEST), sizeof(DWORD))
  238. + pUserName->Length + pDomainName->Length + pNewPassword->Length;
  239. pSetRequest = (PKERB_SETPASSWORD_REQUEST) new CHAR [cbChangeSize];
  240. Status DBGCHK = pSetRequest ? STATUS_SUCCESS : STATUS_NO_MEMORY;
  241. if (NT_SUCCESS(Status))
  242. {
  243. RtlZeroMemory(pSetRequest, cbChangeSize);
  244. pSetRequest->MessageType = KerbSetPasswordMessage;
  245. pSetRequest->AccountName = *pUserName;
  246. pSetRequest->AccountName.Buffer = (PWSTR) ROUND_UP_POINTER(sizeof(KERB_SETPASSWORD_REQUEST) + (PBYTE) pSetRequest, sizeof(DWORD));
  247. RtlCopyMemory(
  248. pSetRequest->AccountName.Buffer,
  249. pUserName->Buffer,
  250. pUserName->Length
  251. );
  252. pSetRequest->DomainName = *pDomainName;
  253. pSetRequest->DomainName.Buffer = pSetRequest->AccountName.Buffer + pSetRequest->AccountName.Length / sizeof(WCHAR);
  254. RtlCopyMemory(
  255. pSetRequest->DomainName.Buffer,
  256. pDomainName->Buffer,
  257. pDomainName->Length
  258. );
  259. pSetRequest->Password = *pNewPassword;
  260. pSetRequest->Password.Buffer = pSetRequest->DomainName.Buffer + pSetRequest->DomainName.Length / sizeof(WCHAR);
  261. RtlCopyMemory(
  262. pSetRequest->Password.Buffer,
  263. pNewPassword->Buffer,
  264. pNewPassword->Length
  265. );
  266. if (pCredentialsHandle)
  267. {
  268. pSetRequest->CredentialsHandle = *pCredentialsHandle;
  269. pSetRequest->Flags |= KERB_SETPASS_USE_CREDHANDLE;
  270. }
  271. Status DBGCHK = LsaCallAuthenticationPackage(
  272. LogonHandle,
  273. PackageId,
  274. pSetRequest,
  275. cbChangeSize,
  276. &pResponse,
  277. &cbResponseSize,
  278. &SubStatus
  279. );
  280. }
  281. if (NT_SUCCESS(Status))
  282. {
  283. Status DBGCHK = SubStatus;
  284. }
  285. if (pResponse)
  286. {
  287. LsaFreeReturnBuffer(pResponse);
  288. }
  289. if (pSetRequest)
  290. {
  291. delete [] pSetRequest;
  292. }
  293. return Status;
  294. }
  295. VOID __cdecl
  296. main(
  297. IN INT argc,
  298. IN PSTR argv[]
  299. )
  300. {
  301. TNtStatus Status = STATUS_SUCCESS;
  302. HANDLE LogonHandle = NULL;
  303. ULONG PackageId = -1;
  304. UNICODE_STRING ClientName = {0};
  305. UNICODE_STRING ClientRealm = {0};
  306. UNICODE_STRING OldPassword = {0};
  307. UNICODE_STRING NewPassword = {0};
  308. BOOLEAN bIsSetPassword = FALSE;
  309. BOOLEAN bCacheOnly = FALSE;
  310. BOOLEAN bImpersonating = TRUE;
  311. PCSTR pszPackageName = NTLMSP_NAME_A;
  312. for (INT i = 1; NT_SUCCESS(Status) && (i < argc); i++)
  313. {
  314. if ((*argv[i] == '-') || (*argv[i] == '/'))
  315. {
  316. switch (argv[i][1])
  317. {
  318. case 'c':
  319. Status DBGCHK = CreateUnicodeStringFromAsciiz(argv[i] + 2, &ClientName);
  320. break;
  321. case 'C':
  322. Status DBGCHK = CreateUnicodeStringFromAsciiz(argv[i] + 2, &ClientRealm);
  323. break;
  324. case 'p':
  325. pszPackageName = argv[i] + 2;
  326. break;
  327. case 'o':
  328. Status DBGCHK = CreateUnicodeStringFromAsciiz(argv[i] + 2, &OldPassword);
  329. break;
  330. case 'n':
  331. Status DBGCHK = CreateUnicodeStringFromAsciiz(argv[i] + 2, &NewPassword);
  332. break;
  333. case 'r':
  334. bImpersonating = FALSE;
  335. break;
  336. case 's':
  337. bIsSetPassword = TRUE;
  338. break;
  339. case 'l':
  340. bCacheOnly = TRUE;
  341. break;
  342. case 'h':
  343. case '?':
  344. default:
  345. Usage(argv[0]);
  346. break;
  347. }
  348. }
  349. else
  350. {
  351. Usage(argv[0]);
  352. }
  353. }
  354. if (NT_SUCCESS(Status))
  355. {
  356. Status DBGCHK = GetLsaHandleAndPackageId(
  357. pszPackageName,
  358. &LogonHandle,
  359. &PackageId
  360. );
  361. }
  362. if (NT_SUCCESS(Status))
  363. {
  364. if (0 == _stricmp(NTLMSP_NAME_A, pszPackageName))
  365. {
  366. if (bIsSetPassword)
  367. {
  368. DebugPrintf(SSPI_ERROR, "SetPassword not supported\n");
  369. Status DBGCHK = STATUS_NOT_SUPPORTED;
  370. }
  371. else
  372. {
  373. Status DBGCHK = MsvChangePasswordUser(
  374. LogonHandle,
  375. PackageId,
  376. bCacheOnly,
  377. &ClientRealm,
  378. &ClientName,
  379. &OldPassword,
  380. &NewPassword,
  381. bImpersonating
  382. );
  383. }
  384. }
  385. else if (0 == _stricmp(MICROSOFT_KERBEROS_NAME_A, pszPackageName))
  386. {
  387. if (bIsSetPassword)
  388. {
  389. Status DBGCHK = KerbSetPasswordUser(
  390. LogonHandle,
  391. PackageId,
  392. &ClientRealm,
  393. &ClientName,
  394. &NewPassword,
  395. NULL // no cred handle
  396. );
  397. }
  398. else
  399. {
  400. Status DBGCHK = KerbChangePasswordUser(
  401. LogonHandle,
  402. PackageId,
  403. bImpersonating,
  404. &ClientRealm,
  405. &ClientName,
  406. &OldPassword,
  407. &NewPassword
  408. );
  409. }
  410. }
  411. else
  412. {
  413. DebugPrintf(SSPI_ERROR, "%s not supported\n", pszPackageName);
  414. Status DBGCHK = STATUS_NOT_SUPPORTED;
  415. }
  416. }
  417. if (NT_SUCCESS(Status))
  418. {
  419. DebugPrintf(SSPI_LOG, "Operation succeeded\n");
  420. }
  421. else
  422. {
  423. DebugPrintf(SSPI_ERROR, "Operation failed\n");
  424. }
  425. if (LogonHandle)
  426. {
  427. LsaDeregisterLogonProcess(LogonHandle);
  428. }
  429. RtlFreeUnicodeString(&ClientName);
  430. RtlFreeUnicodeString(&ClientRealm);
  431. RtlFreeUnicodeString(&OldPassword);
  432. RtlFreeUnicodeString(&NewPassword);
  433. }