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.

474 lines
12 KiB

  1. //+-----------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (c) Microsoft Corporation 1992 - 1999
  6. //
  7. // File: changepw.cxx
  8. //
  9. // Contents: Code for KerbSetPassword and KerbChangePassword
  10. //
  11. //
  12. // History: 24-May-1999 MikeSw Created
  13. //
  14. //------------------------------------------------------------------------
  15. #include <nt.h>
  16. #include <ntrtl.h>
  17. #include <nturtl.h>
  18. #include <windows.h>
  19. #include <sspi.h>
  20. #include <ntsecapi.h>
  21. #include <align.h>
  22. #include <dsgetdc.h>
  23. #include <kerbcli.h>
  24. //+-------------------------------------------------------------------------
  25. //
  26. // Function: KerbChangePasswordUserEx
  27. //
  28. // Synopsis: Changes a users password. If the user is logged on,
  29. // it also updates the in-memory password.
  30. //
  31. // Effects:
  32. //
  33. // Arguments:
  34. //
  35. // Requires:
  36. //
  37. // Returns:
  38. //
  39. // Notes:
  40. //
  41. //
  42. //--------------------------------------------------------------------------
  43. NTSTATUS
  44. KerbChangePasswordUser(
  45. IN LPWSTR DomainName,
  46. IN LPWSTR UserName,
  47. IN LPWSTR OldPassword,
  48. IN LPWSTR NewPassword
  49. )
  50. {
  51. NTSTATUS Status;
  52. STRING Name;
  53. HANDLE LogonHandle = NULL;
  54. ULONG PackageId;
  55. PVOID Response = NULL ;
  56. ULONG ResponseSize;
  57. NTSTATUS SubStatus;
  58. PKERB_CHANGEPASSWORD_REQUEST ChangeRequest = NULL;
  59. ULONG ChangeSize;
  60. UNICODE_STRING User,Domain,OldPass,NewPass;
  61. Status = LsaConnectUntrusted(
  62. &LogonHandle
  63. );
  64. if (!NT_SUCCESS(Status))
  65. {
  66. goto Cleanup;
  67. }
  68. RtlInitString(
  69. &Name,
  70. MICROSOFT_KERBEROS_NAME_A
  71. );
  72. Status = LsaLookupAuthenticationPackage(
  73. LogonHandle,
  74. &Name,
  75. &PackageId
  76. );
  77. if (!NT_SUCCESS(Status))
  78. {
  79. goto Cleanup;
  80. }
  81. RtlInitUnicodeString(
  82. &User,
  83. UserName
  84. );
  85. RtlInitUnicodeString(
  86. &Domain,
  87. DomainName
  88. );
  89. RtlInitUnicodeString(
  90. &OldPass,
  91. OldPassword
  92. );
  93. RtlInitUnicodeString(
  94. &NewPass,
  95. NewPassword
  96. );
  97. if ( OldPass.Length > (127*sizeof(WCHAR)) ||
  98. NewPass.Length > (127*sizeof(WCHAR)) )
  99. {
  100. Status = STATUS_NAME_TOO_LONG;
  101. goto Cleanup;
  102. }
  103. ChangeSize = ROUND_UP_COUNT(sizeof(KERB_CHANGEPASSWORD_REQUEST),4)+
  104. User.Length +
  105. Domain.Length +
  106. OldPass.Length +
  107. NewPass.Length ;
  108. ChangeRequest = (PKERB_CHANGEPASSWORD_REQUEST) LocalAlloc(LMEM_ZEROINIT, ChangeSize );
  109. if (NULL == ChangeRequest)
  110. {
  111. goto Cleanup;
  112. }
  113. ChangeRequest->MessageType = KerbChangePasswordMessage;
  114. ChangeRequest->AccountName = User;
  115. ChangeRequest->AccountName.Buffer = (LPWSTR) ROUND_UP_POINTER(sizeof(KERB_CHANGEPASSWORD_REQUEST) + (PBYTE) ChangeRequest,4);
  116. RtlCopyMemory(
  117. ChangeRequest->AccountName.Buffer,
  118. User.Buffer,
  119. User.Length
  120. );
  121. ChangeRequest->DomainName = Domain;
  122. ChangeRequest->DomainName.Buffer = ChangeRequest->AccountName.Buffer + ChangeRequest->AccountName.Length / sizeof(WCHAR);
  123. RtlCopyMemory(
  124. ChangeRequest->DomainName.Buffer,
  125. Domain.Buffer,
  126. Domain.Length
  127. );
  128. ChangeRequest->OldPassword = OldPass;
  129. ChangeRequest->OldPassword.Buffer = ChangeRequest->DomainName.Buffer + ChangeRequest->DomainName.Length / sizeof(WCHAR);
  130. RtlCopyMemory(
  131. ChangeRequest->OldPassword.Buffer,
  132. OldPass.Buffer,
  133. OldPass.Length
  134. );
  135. ChangeRequest->NewPassword = NewPass;
  136. ChangeRequest->NewPassword.Buffer = ChangeRequest->OldPassword.Buffer + ChangeRequest->OldPassword.Length / sizeof(WCHAR);
  137. RtlCopyMemory(
  138. ChangeRequest->NewPassword.Buffer,
  139. NewPass.Buffer,
  140. NewPass.Length
  141. );
  142. //
  143. // We are running as the caller, so state we are impersonating
  144. //
  145. ChangeRequest->Impersonating = TRUE;
  146. Status = LsaCallAuthenticationPackage(
  147. LogonHandle,
  148. PackageId,
  149. ChangeRequest,
  150. ChangeSize,
  151. &Response,
  152. &ResponseSize,
  153. &SubStatus
  154. );
  155. if (!NT_SUCCESS(Status) || !NT_SUCCESS(SubStatus))
  156. {
  157. if (NT_SUCCESS(Status))
  158. {
  159. Status = SubStatus;
  160. }
  161. goto Cleanup;
  162. }
  163. Cleanup:
  164. if (LogonHandle != NULL)
  165. {
  166. LsaDeregisterLogonProcess(LogonHandle);
  167. }
  168. if (Response != NULL)
  169. {
  170. LsaFreeReturnBuffer(Response);
  171. }
  172. if (ChangeRequest != NULL)
  173. {
  174. LocalFree(ChangeRequest);
  175. }
  176. return(Status);
  177. }
  178. //+-------------------------------------------------------------------------
  179. //
  180. // Function: KerbSetPasswordUserEx
  181. //
  182. // Synopsis: Sets a password for a user in the specified domain
  183. //
  184. // Effects:
  185. //
  186. // Arguments:
  187. //
  188. // Requires:
  189. //
  190. // Returns:
  191. //
  192. // Notes:
  193. //
  194. //
  195. //--------------------------------------------------------------------------
  196. NTSTATUS
  197. KerbSetPasswordUserEx(
  198. IN LPWSTR DomainName,
  199. IN LPWSTR UserName,
  200. IN LPWSTR NewPassword,
  201. IN OPTIONAL PCredHandle CredentialsHandle,
  202. IN OPTIONAL LPWSTR KdcAddress
  203. )
  204. {
  205. NTSTATUS Status;
  206. STRING Name;
  207. HANDLE LogonHandle = NULL;
  208. ULONG PackageId;
  209. PVOID Response = NULL;
  210. ULONG ResponseSize;
  211. KERB_PROTOCOL_MESSAGE_TYPE MessageType = KerbSetPasswordMessage;
  212. NTSTATUS SubStatus;
  213. PKERB_SETPASSWORD_EX_REQUEST SetRequest = NULL;
  214. ULONG ChangeSize;
  215. UNICODE_STRING User, Domain, NewPass, KdcAddr, ClientName, ClientRealm;
  216. // If you supply a KdcAddress, you must supply name type
  217. if (ARGUMENT_PRESENT(KdcAddress))
  218. {
  219. MessageType = KerbSetPasswordExMessage;
  220. RtlInitUnicodeString(
  221. &KdcAddr,
  222. KdcAddress
  223. );
  224. }
  225. else
  226. {
  227. RtlInitUnicodeString(
  228. &KdcAddr,
  229. NULL
  230. );
  231. }
  232. Status = LsaConnectUntrusted(
  233. &LogonHandle
  234. );
  235. if (!NT_SUCCESS(Status))
  236. {
  237. goto Cleanup;
  238. }
  239. RtlInitString(
  240. &Name,
  241. MICROSOFT_KERBEROS_NAME_A
  242. );
  243. Status = LsaLookupAuthenticationPackage(
  244. LogonHandle,
  245. &Name,
  246. &PackageId
  247. );
  248. if (!NT_SUCCESS(Status))
  249. {
  250. goto Cleanup;
  251. }
  252. RtlInitUnicodeString(
  253. &User,
  254. UserName
  255. );
  256. RtlInitUnicodeString(
  257. &Domain,
  258. DomainName
  259. );
  260. RtlInitUnicodeString(
  261. &NewPass,
  262. NewPassword
  263. );
  264. // These aren't used here (yet)
  265. RtlInitUnicodeString(
  266. &ClientName,
  267. NULL
  268. );
  269. RtlInitUnicodeString(
  270. &ClientRealm,
  271. NULL
  272. );
  273. if ( NewPass.Length > (127 * sizeof(WCHAR)) )
  274. {
  275. Status = STATUS_NAME_TOO_LONG;
  276. goto Cleanup;
  277. }
  278. ChangeSize = ROUND_UP_COUNT(sizeof(KERB_SETPASSWORD_EX_REQUEST),4)+
  279. User.Length +
  280. Domain.Length +
  281. NewPass.Length +
  282. KdcAddr.Length +
  283. ClientName.Length +
  284. ClientRealm.Length;
  285. SetRequest = (PKERB_SETPASSWORD_EX_REQUEST) LocalAlloc(LMEM_ZEROINIT, ChangeSize );
  286. if (NULL == SetRequest)
  287. {
  288. goto Cleanup;
  289. }
  290. SetRequest->MessageType = MessageType;
  291. SetRequest->KdcAddressType = DS_UNKNOWN_ADDRESS_TYPE;
  292. SetRequest->AccountRealm = Domain;
  293. SetRequest->AccountRealm.Buffer = (LPWSTR) ROUND_UP_POINTER(sizeof(KERB_SETPASSWORD_EX_REQUEST) + (PBYTE) SetRequest,4);
  294. RtlCopyMemory(
  295. SetRequest->AccountRealm.Buffer,
  296. Domain.Buffer,
  297. Domain.Length
  298. );
  299. SetRequest->AccountName = User;
  300. SetRequest->AccountName.Buffer = SetRequest->AccountRealm.Buffer + SetRequest->AccountRealm.Length / sizeof(WCHAR);
  301. RtlCopyMemory(
  302. SetRequest->AccountName.Buffer,
  303. User.Buffer,
  304. User.Length
  305. );
  306. SetRequest->Password = NewPass;
  307. SetRequest->Password.Buffer = SetRequest->AccountName.Buffer + SetRequest->AccountName.Length / sizeof(WCHAR);
  308. RtlCopyMemory(
  309. SetRequest->Password.Buffer,
  310. NewPass.Buffer,
  311. NewPass.Length
  312. );
  313. // Not yet implemented
  314. SetRequest->ClientRealm = ClientRealm;
  315. SetRequest->ClientRealm.Buffer = SetRequest->Password.Buffer + SetRequest->Password.Length / sizeof(WCHAR);
  316. RtlCopyMemory(
  317. SetRequest->ClientRealm.Buffer,
  318. ClientRealm.Buffer,
  319. ClientRealm.Length
  320. );
  321. SetRequest->ClientName = ClientName;
  322. SetRequest->ClientName.Buffer = SetRequest->ClientRealm.Buffer + SetRequest->ClientRealm.Length / sizeof(WCHAR);
  323. RtlCopyMemory(
  324. SetRequest->ClientName.Buffer,
  325. ClientName.Buffer,
  326. ClientName.Length
  327. );
  328. //
  329. SetRequest->KdcAddress = KdcAddr;
  330. SetRequest->KdcAddress.Buffer = SetRequest->ClientRealm.Buffer + SetRequest->ClientRealm.Length / sizeof(WCHAR);
  331. RtlCopyMemory(
  332. SetRequest->KdcAddress.Buffer,
  333. KdcAddr.Buffer,
  334. KdcAddr.Length
  335. );
  336. if (ARGUMENT_PRESENT(CredentialsHandle))
  337. {
  338. SetRequest->CredentialsHandle = *CredentialsHandle;
  339. SetRequest->Flags |= KERB_SETPASS_USE_CREDHANDLE;
  340. }
  341. Status = LsaCallAuthenticationPackage(
  342. LogonHandle,
  343. PackageId,
  344. SetRequest,
  345. ChangeSize,
  346. &Response,
  347. &ResponseSize,
  348. &SubStatus
  349. );
  350. if (!NT_SUCCESS(Status) || !NT_SUCCESS(SubStatus))
  351. {
  352. if (NT_SUCCESS(Status))
  353. {
  354. Status = SubStatus;
  355. }
  356. goto Cleanup;
  357. }
  358. Cleanup:
  359. if (LogonHandle != NULL)
  360. {
  361. LsaDeregisterLogonProcess(LogonHandle);
  362. }
  363. if (Response != NULL)
  364. {
  365. LsaFreeReturnBuffer(Response);
  366. }
  367. if (SetRequest != NULL)
  368. {
  369. LocalFree(SetRequest);
  370. }
  371. return(Status);
  372. }
  373. //+-------------------------------------------------------------------------
  374. //
  375. // Function: KerbSetPasswordUser
  376. //
  377. // Synopsis: Sets a password for a user in the specified domain
  378. //
  379. // Effects:
  380. //
  381. // Arguments:
  382. //
  383. // Requires:
  384. //
  385. // Returns:
  386. //
  387. // Notes:
  388. //
  389. //
  390. //--------------------------------------------------------------------------
  391. NTSTATUS
  392. KerbSetPasswordUser(
  393. IN LPWSTR DomainName,
  394. IN LPWSTR UserName,
  395. IN LPWSTR NewPassword,
  396. IN OPTIONAL PCredHandle CredentialsHandle
  397. )
  398. {
  399. return(KerbSetPasswordUserEx(
  400. DomainName,
  401. UserName,
  402. NewPassword,
  403. CredentialsHandle,
  404. NULL
  405. ));
  406. }