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.

210 lines
5.3 KiB

  1. #include <stdio.h>
  2. #include <nt.h>
  3. #include <ntsam.h>
  4. #include <ntlsa.h>
  5. #include <ntrtl.h>
  6. #include <string.h>
  7. VOID AddUser(LPSTR, LPSTR);
  8. VOID
  9. __cdecl main(USHORT argc, PCHAR *argv)
  10. {
  11. if (argc != 3) {
  12. printf("Usage: AddUser <username> <password>\n");
  13. return;
  14. }
  15. AddUser(argv[1], argv[2]);
  16. return;
  17. }
  18. VOID
  19. AddUser(
  20. LPSTR UserName,
  21. LPSTR Password
  22. )
  23. {
  24. HANDLE ServerHandle = NULL;
  25. HANDLE DomainHandle = NULL;
  26. HANDLE UserHandle = NULL;
  27. LSA_HANDLE LsaHandle = NULL;
  28. ACCESS_MASK ServerAccessMask, DomainAccessMask;
  29. OBJECT_ATTRIBUTES ObjectAttributes;
  30. PPOLICY_ACCOUNT_DOMAIN_INFO PolicyAccountDomainInfo = NULL;
  31. STRING AccountNameAnsi;
  32. STRING AnsiPassword;
  33. UNICODE_STRING AccountName;
  34. UNICODE_STRING UnicodePassword;
  35. USER_SET_PASSWORD_INFORMATION pi;
  36. ULONG UserRid;
  37. NTSTATUS NtStatus;
  38. USHORT ControlInformation = USER_NORMAL_ACCOUNT;
  39. //
  40. // Get the Account domain SID from LSA
  41. //
  42. InitializeObjectAttributes( &ObjectAttributes, NULL, 0, 0, NULL );
  43. NtStatus = LsaOpenPolicy(NULL,
  44. &ObjectAttributes,
  45. POLICY_ALL_ACCESS,
  46. &LsaHandle);
  47. if (NtStatus == STATUS_ACCESS_DENIED) {
  48. printf("You must be logged on as admin to use this command\n");
  49. return;
  50. }
  51. else if (!NT_SUCCESS(NtStatus)) {
  52. //cleanup and exit
  53. printf("Couldn't open Lsa Policy database, rc = 0x%x\n", NtStatus);
  54. goto cleanupandexit;
  55. }
  56. NtStatus = LsaQueryInformationPolicy(LsaHandle,
  57. PolicyAccountDomainInformation,
  58. &PolicyAccountDomainInfo);
  59. if (!NT_SUCCESS(NtStatus)) {
  60. //cleanup and exit
  61. printf("Couldn't query Lsa Policy database, rc = 0x%x\n", NtStatus);
  62. goto cleanupandexit;
  63. }
  64. //
  65. // Connect to SAM
  66. //
  67. ServerAccessMask = SAM_SERVER_ALL_ACCESS;
  68. InitializeObjectAttributes( &ObjectAttributes, NULL, 0, 0, NULL );
  69. NtStatus = SamConnect(
  70. NULL, // ServerName (Local machine)
  71. &ServerHandle,
  72. ServerAccessMask,
  73. &ObjectAttributes
  74. );
  75. if (!NT_SUCCESS(NtStatus)) {
  76. //cleanup and exit
  77. printf("Couldn't connect to SAM, rc = 0x%x\n", NtStatus);
  78. goto cleanupandexit;
  79. }
  80. //
  81. // Open the account domain
  82. //
  83. DomainAccessMask = DOMAIN_ALL_ACCESS;
  84. NtStatus = SamOpenDomain(
  85. ServerHandle,
  86. DomainAccessMask,
  87. PolicyAccountDomainInfo->DomainSid,
  88. &DomainHandle
  89. );
  90. if (!NT_SUCCESS(NtStatus)) {
  91. //cleanup and exit
  92. printf("Couldn't open account domain, rc = 0x%x\n", NtStatus);
  93. goto cleanupandexit;
  94. }
  95. //
  96. // Create the User
  97. //
  98. RtlInitString( &AccountNameAnsi, UserName );
  99. NtStatus = RtlAnsiStringToUnicodeString( &AccountName, &AccountNameAnsi,
  100. TRUE );
  101. if (!NT_SUCCESS(NtStatus)) {
  102. //cleanup and exit
  103. printf("RtlAnsiStringToUnicodeString failed, rc = 0x%x\n", NtStatus);
  104. goto cleanupandexit;
  105. }
  106. UserRid = 0;
  107. UserHandle = NULL;
  108. NtStatus = SamCreateUserInDomain(
  109. DomainHandle,
  110. &AccountName,
  111. USER_ALL_ACCESS,
  112. &UserHandle,
  113. &UserRid
  114. );
  115. RtlFreeUnicodeString( &AccountName );
  116. if (NtStatus == STATUS_USER_EXISTS) {
  117. printf("User %s already exists\n", UserName);
  118. goto cleanupandexit;
  119. }
  120. else if (!NT_SUCCESS(NtStatus)) {
  121. //cleanup and exit
  122. printf("Couldn't create user, rc = 0x%x\n", NtStatus);
  123. goto cleanupandexit;
  124. }
  125. //
  126. // Create the cleartext UNICODE password and write it out.
  127. //
  128. RtlInitString(&AnsiPassword, Password);
  129. NtStatus = RtlAnsiStringToUnicodeString( &UnicodePassword, &AnsiPassword,
  130. TRUE );
  131. if (!NT_SUCCESS(NtStatus)) {
  132. //cleanup and exit
  133. printf("RtlAnsiStringToUnicodeString failed, rc = 0x%x\n", NtStatus);
  134. goto cleanupandexit;
  135. }
  136. pi.Password = UnicodePassword;
  137. pi.PasswordExpired = FALSE;
  138. NtStatus = SamSetInformationUser(
  139. UserHandle,
  140. UserSetPasswordInformation,
  141. &pi
  142. );
  143. RtlFreeUnicodeString(&UnicodePassword);
  144. if (!NT_SUCCESS(NtStatus)) {
  145. //cleanup and exit
  146. printf("Couldn't set password for user, rc = 0x%x\n", NtStatus);
  147. goto cleanupandexit;
  148. }
  149. //
  150. // Now make the user account active
  151. //
  152. NtStatus = SamSetInformationUser(
  153. UserHandle,
  154. UserControlInformation,
  155. &ControlInformation
  156. );
  157. if (!NT_SUCCESS(NtStatus)) {
  158. //cleanup and exit
  159. printf("Couldn't activate the user account, rc = 0x%x\n", NtStatus);
  160. goto cleanupandexit;
  161. }
  162. cleanupandexit:
  163. if (PolicyAccountDomainInfo) {
  164. LsaFreeMemory(PolicyAccountDomainInfo);
  165. }
  166. if (UserHandle) {
  167. NtClose(UserHandle);
  168. }
  169. if (DomainHandle) {
  170. NtClose(DomainHandle);
  171. }
  172. if (ServerHandle) {
  173. NtClose(ServerHandle);
  174. }
  175. if (LsaHandle) {
  176. NtClose(LsaHandle);
  177. }
  178. return;
  179. }