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.

349 lines
11 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. forcemigrate.c
  5. Abstract:
  6. forcemigrate.c
  7. Author:
  8. Jason Garms (jasong) 27 October 2000
  9. --*/
  10. #include <shared.h>
  11. //+---------------------------------------------------------------------------------------------------------
  12. //
  13. // Prototypes
  14. //
  15. //+---------------------------------------------------------------------------------------------------------
  16. DWORD
  17. MigratePassword();
  18. DWORD
  19. ListAll();
  20. VOID
  21. DumpCmd();
  22. //+---------------------------------------------------------------------------------------------------------
  23. //
  24. // Globals
  25. //
  26. //+---------------------------------------------------------------------------------------------------------
  27. BOOL g_QuietMode = FALSE;
  28. WCHAR g_TempString[MAX_STRING] = {0};
  29. WCHAR g_ErrorString[MAX_STRING] = {0};
  30. WCHAR g_FailureLocation[MAX_STRING] = {0};
  31. BOOL g_RemoteOperation = FALSE;
  32. WCHAR g_RemoteComputerName[MAX_STRING] = {0};
  33. DWORD g_RunningUsersCreds = 0;
  34. DWORD g_CheckNT4Also = 0;
  35. //+---------------------------------------------------------------------------------------------------------
  36. //
  37. // Functions
  38. //
  39. //+---------------------------------------------------------------------------------------------------------
  40. int
  41. __cdecl
  42. wmain(
  43. int argc,
  44. WCHAR *argv[]
  45. )
  46. {
  47. DWORD dwCommandPosition=1;
  48. DWORD dwRetCode=ERROR_SUCCESS;
  49. // parse the command line params and act on them
  50. // if there's fewer than 2 params, it's not a valid call
  51. if (argc < 2) {
  52. dwRetCode = ERROR_BAD_ARGUMENTS;
  53. goto cleanup;
  54. }
  55. // check to see quietmode is enabled and set global flag
  56. // and increment commandposition pointer, but only if there
  57. // are more arguments to our right, otherwise, it's invalid
  58. // usage
  59. if (!wcscmp(argv[dwCommandPosition], L"-q")) {
  60. g_QuietMode = 1;
  61. dwCommandPosition++;
  62. }
  63. if ((DWORD)argc <= (dwCommandPosition)) {
  64. dwRetCode = ERROR_BAD_ARGUMENTS;
  65. goto cleanup;
  66. }
  67. // check to see if we should try the running user's credentials as well
  68. if (!wcscmp(argv[dwCommandPosition], L"-r")) {
  69. g_RunningUsersCreds = 1;
  70. dwCommandPosition++;
  71. }
  72. if ((DWORD)argc <= (dwCommandPosition)) {
  73. dwRetCode = ERROR_BAD_ARGUMENTS;
  74. goto cleanup;
  75. }
  76. // check to see if we should run against NT4 as well
  77. if (!wcscmp(argv[dwCommandPosition], L"-nt4")) {
  78. g_CheckNT4Also = 1;
  79. dwCommandPosition++;
  80. }
  81. if ((DWORD)argc <= (dwCommandPosition)) {
  82. dwRetCode = ERROR_BAD_ARGUMENTS;
  83. goto cleanup;
  84. }
  85. // check to see if a UNC machine name is passed in for
  86. // remote operation and set the approprite globals
  87. // if there is a UNC path here, then increment commandposition
  88. // pointer, but only if there's more arguments to our right,
  89. // otherwise it's invalid usage.
  90. if ((*(argv[dwCommandPosition]) != '\\')) {
  91. dwRetCode = ERROR_BAD_ARGUMENTS;
  92. goto cleanup;
  93. }
  94. // make sure there's actually some chars to the right of the \\s
  95. if (wcslen(argv[dwCommandPosition])<=2) {
  96. dwRetCode = ERROR_BAD_ARGUMENTS;
  97. goto cleanup;
  98. }
  99. // make sure the machine name fits in our buffer
  100. if (wcslen(argv[dwCommandPosition]) >= MAX_STRING) {
  101. dwRetCode = ERROR_BAD_ARGUMENTS;
  102. goto cleanup;
  103. }
  104. g_RemoteOperation = TRUE;
  105. wcsncpy(g_RemoteComputerName,
  106. argv[dwCommandPosition],
  107. wcslen(argv[dwCommandPosition]));
  108. dwRetCode = MigratePassword();
  109. cleanup:
  110. if (dwRetCode == ERROR_BAD_ARGUMENTS) {
  111. DumpCmd();
  112. }
  113. return dwRetCode;
  114. }
  115. DWORD
  116. MigratePassword()
  117. {
  118. WCHAR UserName[MAX_STRING];
  119. WCHAR DomainName[MAX_STRING];
  120. WCHAR Password[MAX_STRING];
  121. WCHAR ConCat[MAX_STRING];
  122. DWORD dwRetCode = ERROR_SUCCESS;
  123. NETRESOURCE NetResource = {0};
  124. DWORD dwMachineVerNumber = 0;
  125. // Connect to the remote machine to obtain the username, domain, and password
  126. // Make sure it's a Win2k box
  127. dwMachineVerNumber = GetMajorNTVersion(g_RemoteComputerName);
  128. switch (dwMachineVerNumber) {
  129. case 3:
  130. case 4:
  131. if ((dwMachineVerNumber == 4) && (g_CheckNT4Also)) {
  132. break;
  133. } else {
  134. wprintf(L"%s: Error, target is running NT4 and -nt4 option not selected\n", g_RemoteComputerName);
  135. dwRetCode = ERROR_OLD_WIN_VERSION;
  136. goto cleanup;
  137. }
  138. case 5:
  139. break;
  140. default:
  141. wprintf(L"%s: Error target's machine version is invalid\n", g_RemoteComputerName);
  142. dwRetCode = ERROR_OLD_WIN_VERSION;
  143. goto cleanup;
  144. }
  145. wsprintf(g_TempString, L"%s: Beginning Migration: System is running NT%d\n", g_RemoteComputerName, dwMachineVerNumber);
  146. wsprintf(g_TempString, L"%s: DefaultPassword : (reg does not exist)\n", g_RemoteComputerName);
  147. //
  148. // Get the DefaultPassword
  149. //
  150. dwRetCode = GetRegValueSZ(L"DefaultPassword", Password);
  151. switch (dwRetCode) {
  152. // catch this case and continue
  153. case ERROR_FILE_NOT_FOUND:
  154. wsprintf(g_TempString, L"%s: DefaultPassword : (reg does not exist)\n", g_RemoteComputerName);
  155. DisplayMessage(g_TempString);
  156. goto cleanup;
  157. // On success, print the regkey and continue to next item
  158. case ERROR_SUCCESS:
  159. if (!wcscmp(Password, L"")) {
  160. dwRetCode = ERROR_FILE_NOT_FOUND;
  161. wsprintf(g_TempString, L"%s: DefaultPassword : (exists, but is empty)\n", g_RemoteComputerName);
  162. DisplayMessage(g_TempString);
  163. break;
  164. }
  165. wsprintf(g_TempString, L"%s: DefaultPassword : %s\n", g_RemoteComputerName, Password);
  166. DisplayMessage(g_TempString);
  167. break;
  168. // catch all the generic errors and end program
  169. default:
  170. wsprintf(g_TempString, L"DefaultPassword : Failed to query regkey: %s\n", GetErrorString(dwRetCode));
  171. wprintf(L"Flag 3\n", dwRetCode);
  172. goto cleanup;
  173. }
  174. //
  175. // Get the username
  176. //
  177. dwRetCode = GetRegValueSZ(L"DefaultUserName", UserName);
  178. switch (dwRetCode) {
  179. // catch this case and continue
  180. case ERROR_FILE_NOT_FOUND:
  181. wsprintf(g_TempString, L"%s: DefaultUserName : (does not exist)\n", g_RemoteComputerName);
  182. DisplayMessage(g_TempString);
  183. goto cleanup;
  184. // On success, print the regkey and continue to next item
  185. case ERROR_SUCCESS:
  186. wsprintf(g_TempString, L"%s: DefaultUserName : %s\n", g_RemoteComputerName, UserName);
  187. DisplayMessage(g_TempString);
  188. break;
  189. // catch all the generic errors and end program
  190. default:
  191. wsprintf(g_TempString, L"%s: DefaultUserName : Failed to query regkey: %s\n", g_RemoteComputerName, GetErrorString(dwRetCode));
  192. DisplayMessage(g_TempString);
  193. goto cleanup;
  194. }
  195. //
  196. // Get the DefaultDomainName
  197. //
  198. dwRetCode = GetRegValueSZ(L"DefaultDomainName", DomainName);
  199. switch (dwRetCode) {
  200. // catch this case and continue
  201. case ERROR_FILE_NOT_FOUND:
  202. wsprintf(g_TempString, L"%s: DefaultDomainName: (does not exist)\n", g_RemoteComputerName);
  203. DisplayMessage(g_TempString);
  204. goto cleanup;
  205. // On success, print the regkey and continue to next item
  206. case ERROR_SUCCESS:
  207. wsprintf(g_TempString, L"%s: DefaultDomainName: %s\n", g_RemoteComputerName, DomainName);
  208. DisplayMessage(g_TempString);
  209. break;
  210. // catch all the generic errors and end program
  211. default:
  212. wsprintf(g_TempString, L"%s: DefaultDomainName: Failed to query regkey: %s\n", g_RemoteComputerName, GetErrorString(dwRetCode));
  213. DisplayMessage(g_TempString);
  214. goto cleanup;
  215. }
  216. if ((wcslen(DomainName) + wcslen(UserName)) >= MAX_STRING) {
  217. dwRetCode = ERROR_BUFFER_OVERFLOW;
  218. goto cleanup;
  219. }
  220. wcscpy(ConCat, DomainName);
  221. wcscat(ConCat, L"\\");
  222. wcscat(ConCat, UserName);
  223. NetResource.lpRemoteName = g_RemoteComputerName;
  224. dwRetCode = WNetAddConnection2(
  225. &NetResource, // connection details
  226. Password, // password
  227. ConCat, // user name
  228. 0); // connection options
  229. if (dwRetCode != ERROR_SUCCESS) {
  230. if (!g_RunningUsersCreds) {
  231. wprintf(L"%s: Could not logon as %s using password %s\n", g_RemoteComputerName, ConCat, Password);
  232. goto cleanup;
  233. } else {
  234. wprintf(L"Trying with your own credentials\n");
  235. dwRetCode = WNetAddConnection2(
  236. &NetResource, // connection details
  237. NULL, // password
  238. NULL, // user name
  239. 0); // connection options
  240. if (dwRetCode != ERROR_SUCCESS) {
  241. wprintf(L"%s: Could not logon you or as %s using password %s\n", g_RemoteComputerName, ConCat, Password);
  242. goto cleanup;
  243. }
  244. }
  245. }
  246. // Set the DefaultPassword LSAsecret to the value we retrieved from the registry
  247. dwRetCode = SetSecret(Password, 0);
  248. if (dwRetCode != ERROR_SUCCESS) {
  249. wsprintf(g_TempString, L"%s: Migrate Failed: Could not set DefaultPassword LSASecret: %s\n", g_RemoteComputerName, GetErrorString(dwRetCode));
  250. DisplayMessage(g_TempString);
  251. wsprintf(g_TempString, L"%s: This is probably because the user is not the admin of the local machine\n", g_RemoteComputerName);
  252. DisplayMessage(g_TempString);
  253. goto cleanup;
  254. }
  255. // Delete the DefaultPassword registry key
  256. dwRetCode = ClearRegPassword();
  257. if (dwRetCode != ERROR_SUCCESS) {
  258. wsprintf(g_TempString, L"%s: Migrate Failed: Could not delete DefaultPassword RegKey: %s\n", g_RemoteComputerName, GetErrorString(dwRetCode));
  259. DisplayMessage(g_TempString);
  260. goto cleanup;
  261. }
  262. wsprintf(g_TempString, L"%s: Password migrated from Registry to LSASecret\n", g_RemoteComputerName);
  263. DisplayMessage(g_TempString);
  264. cleanup:
  265. if (dwRetCode != ERROR_SUCCESS) {
  266. wsprintf(g_TempString, L"%s: Migrate Failed ---------\n", g_RemoteComputerName);
  267. DisplayMessage(g_TempString);
  268. } else {
  269. wsprintf(g_TempString, L"%s: Migrate Success !!!!!!!!!\n", g_RemoteComputerName);
  270. DisplayMessage(g_TempString);
  271. }
  272. return dwRetCode;
  273. }
  274. VOID
  275. DumpCmd()
  276. {
  277. wprintf(L"FORCEMIGRATE v0.1: Copyright 2000, Microsoft Corporation\n\n");
  278. wprintf(L"DESCRIPTION:\n");
  279. wprintf(L" Force migrates DefaultPassword cleartext to LSASecret\n");
  280. wprintf(L"USAGE:\n");
  281. wprintf(L" FORCEMIGRATE [-q] [-r] [-nt4] \\\\machine\n");
  282. wprintf(L" -q Enable quiet mode, which supresses all output\n");
  283. wprintf(L" -r Try with current user's creds as well as DefaultPassword\n");
  284. wprintf(L" -nt4 Run against NT4 boxes as well\n");
  285. wprintf(L" \\machine If specified, the UNC name of the machine to configure\n");
  286. } // DumpCmd