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.

628 lines
17 KiB

  1. /*
  2. File: user.c
  3. Handles routemon options to get and set RAS user properties.
  4. */
  5. #include "precomp.h"
  6. #define NT40_BUILD_NUMBER 1381
  7. const WCHAR pszBuildNumPath[] =
  8. L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion";
  9. const WCHAR pszBuildVal[] = L"CurrentBuildNumber";
  10. //
  11. // Defines a macro to perform string copies to
  12. // unicode strings regardless of the UNICODE setting.
  13. //
  14. #if defined( UNICODE ) || defined( _UNICODE )
  15. #define UserStrcpy(dst, src) wcscpy((dst), (src));
  16. #else
  17. #define UserStrcpy(dst, src) mbstowcs((dst), (src), strlen((src)));
  18. #endif
  19. //
  20. // Defines structure of parameters that can be sent to
  21. // a User api's.
  22. //
  23. typedef struct _USER_PARAMS {
  24. PWCHAR pszMachine; // Given machine
  25. DWORD dwToken; // Token designating the desired command
  26. WCHAR pszAccount[1024]; // The account in question
  27. BOOL bPolicySpecified; // Whether policy given on cmd line
  28. DWORD dwTokenPolicy; // Specifies the token for the callback policy
  29. RAS_USER_0 UserInfo; // Buffer to hold user info
  30. } USER_PARAMS, * PUSER_PARAMS;
  31. //
  32. // Determines the role of the given computer (NTW, NTS, NTS DC, etc.)
  33. //
  34. DWORD UserGetMachineRole(
  35. IN PWCHAR pszMachine,
  36. OUT DSROLE_MACHINE_ROLE * peRole)
  37. {
  38. PDSROLE_PRIMARY_DOMAIN_INFO_BASIC pGlobalDomainInfo = NULL;
  39. DWORD dwErr;
  40. if (!peRole)
  41. return ERROR_INVALID_PARAMETER;
  42. //
  43. // Get the name of the domain this machine is a member of
  44. //
  45. __try {
  46. dwErr = DsRoleGetPrimaryDomainInformation(
  47. pszMachine,
  48. DsRolePrimaryDomainInfoBasic,
  49. (LPBYTE *)&pGlobalDomainInfo );
  50. if (dwErr != NO_ERROR)
  51. return dwErr;
  52. *peRole = pGlobalDomainInfo->MachineRole;
  53. }
  54. __finally {
  55. if (pGlobalDomainInfo)
  56. DsRoleFreeMemory (pGlobalDomainInfo);
  57. }
  58. return NO_ERROR;
  59. }
  60. //
  61. // Determines the build number of a given machine
  62. //
  63. DWORD UserGetNtosBuildNumber(
  64. IN PWCHAR pszMachine,
  65. OUT LPDWORD lpdwBuild)
  66. {
  67. WCHAR pszComputer[1024], pszBuf[64];
  68. HKEY hkBuild = NULL, hkMachine = NULL;
  69. DWORD dwErr, dwType = REG_SZ, dwSize = sizeof(pszBuf);
  70. __try {
  71. if (pszMachine) {
  72. if (*pszMachine != L'\\')
  73. wsprintfW(pszComputer, L"\\\\%s", pszMachine);
  74. else
  75. wcscpy(pszComputer, pszMachine);
  76. dwErr = RegConnectRegistryW (pszComputer,
  77. HKEY_LOCAL_MACHINE,
  78. &hkMachine);
  79. if (dwErr != ERROR_SUCCESS)
  80. return dwErr;
  81. }
  82. else
  83. hkMachine = HKEY_LOCAL_MACHINE;
  84. // Open the build number key
  85. dwErr = RegOpenKeyExW ( hkMachine,
  86. pszBuildNumPath,
  87. 0,
  88. KEY_READ,
  89. &hkBuild);
  90. if (dwErr != ERROR_SUCCESS)
  91. return dwErr;
  92. // Get the value
  93. dwErr = RegQueryValueExW ( hkBuild,
  94. pszBuildVal,
  95. NULL,
  96. &dwType,
  97. (LPBYTE)pszBuf,
  98. &dwSize);
  99. if (dwErr != ERROR_SUCCESS)
  100. return dwErr;
  101. *lpdwBuild = (DWORD) _wtoi(pszBuf);
  102. }
  103. __finally {
  104. if (hkMachine && pszMachine)
  105. RegCloseKey(hkMachine);
  106. if (hkBuild)
  107. RegCloseKey(hkBuild);
  108. }
  109. return NO_ERROR;
  110. }
  111. //
  112. // Returns a static error message
  113. //
  114. PWCHAR UserError (DWORD dwErr) {
  115. static WCHAR pszRet[512];
  116. ZeroMemory(pszRet, sizeof(pszRet));
  117. FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM,
  118. NULL,
  119. dwErr,
  120. 0,
  121. pszRet,
  122. sizeof(pszRet) / sizeof(WCHAR),
  123. NULL);
  124. return pszRet;
  125. }
  126. //
  127. // Displays usage and returns a generic error.
  128. //
  129. DWORD UserUsage(
  130. IN HINSTANCE hInst,
  131. IN PROUTEMON_PARAMS pRmParams,
  132. IN PROUTEMON_UTILS pUtils)
  133. {
  134. pUtils->put_msg (hInst,
  135. MSG_USER_HELP,
  136. pRmParams->pszProgramName);
  137. return ERROR_CAN_NOT_COMPLETE;
  138. }
  139. //
  140. // Parses the register command line and fills
  141. // the parameters accordingly.
  142. //
  143. DWORD UserParse (
  144. IN int argc,
  145. IN TCHAR *argv[],
  146. IN PROUTEMON_PARAMS pRmParams,
  147. IN PROUTEMON_UTILS pUtils,
  148. IN BOOL bLoad,
  149. OUT USER_PARAMS * pParams)
  150. {
  151. DWORD dwSize, dwErr;
  152. BOOL bValidCmd = FALSE;
  153. HINSTANCE hInst = GetModuleHandle(NULL);
  154. TCHAR buf[MAX_TOKEN];
  155. // Initialize the return val
  156. ZeroMemory(pParams, sizeof(USER_PARAMS));
  157. // Parse out the name of the computer
  158. if (pRmParams->wszRouterName[0])
  159. pParams->pszMachine = (PWCHAR)&(pRmParams->wszRouterName[0]);
  160. // Make sure some command was issued
  161. if (argc == 0)
  162. return UserUsage(hInst, pRmParams, pUtils);
  163. // Parse out the command
  164. if (_tcsicmp(argv[0], GetString (hInst, TOKEN_ENABLE, buf))==0) {
  165. pParams->dwToken = TOKEN_ENABLE;
  166. if (argc == 1)
  167. return UserUsage(hInst, pRmParams, pUtils);
  168. UserStrcpy(pParams->pszAccount, argv[1]);
  169. // Optional setting of callback policy and number
  170. if (argc > 2) {
  171. pParams->bPolicySpecified = TRUE;
  172. if (_tcsicmp(argv[2], GetString (hInst, TOKEN_NONE, buf))==0)
  173. pParams->dwTokenPolicy = TOKEN_NONE;
  174. else if (_tcsicmp(argv[2], GetString (hInst, TOKEN_CALLER, buf))==0)
  175. pParams->dwTokenPolicy = TOKEN_CALLER;
  176. else if (_tcsicmp(argv[2], GetString (hInst, TOKEN_ADMIN, buf))==0)
  177. pParams->dwTokenPolicy = TOKEN_ADMIN;
  178. if ((pParams->dwTokenPolicy == TOKEN_ADMIN) &&
  179. (argc < 3))
  180. {
  181. return UserUsage(hInst, pRmParams, pUtils);
  182. }
  183. else if (pParams->dwTokenPolicy == TOKEN_ADMIN) {
  184. UserStrcpy(pParams->UserInfo.wszPhoneNumber, argv[3]);
  185. }
  186. }
  187. }
  188. else if (_tcsicmp(argv[0], GetString (hInst, TOKEN_DISABLE, buf))==0) {
  189. pParams->dwToken = TOKEN_DISABLE;
  190. if (argc == 1)
  191. return UserUsage(hInst, pRmParams, pUtils);
  192. UserStrcpy(pParams->pszAccount, argv[1]);
  193. }
  194. else if (_tcsicmp(argv[0], GetString (hInst, TOKEN_SHOW, buf))==0) {
  195. pParams->dwToken = TOKEN_SHOW;
  196. if (argc == 1)
  197. return UserUsage(hInst, pRmParams, pUtils);
  198. UserStrcpy(pParams->pszAccount, argv[1]);
  199. }
  200. else if (_tcsicmp(argv[0], GetString (hInst, TOKEN_UPGRADE, buf))==0) {
  201. pParams->dwToken = TOKEN_UPGRADE;
  202. }
  203. else
  204. return UserUsage(hInst, pRmParams, pUtils);
  205. return NO_ERROR;
  206. }
  207. //
  208. // Cleans up any User parameters
  209. //
  210. DWORD UserCleanup (
  211. IN PUSER_PARAMS pParams)
  212. {
  213. if (pParams->pszMachine)
  214. free(pParams->pszMachine);
  215. return NO_ERROR;
  216. }
  217. //
  218. // Gets user info
  219. //
  220. DWORD UserGetInfo (
  221. IN PWCHAR lpszServer,
  222. IN PWCHAR lpszUser,
  223. IN DWORD dwLevel,
  224. OUT LPBYTE lpbBuffer)
  225. {
  226. DWORD dwErr, dwBuild;
  227. // Find out the OS of the given machine.
  228. dwErr = UserGetNtosBuildNumber(
  229. lpszServer,
  230. &dwBuild);
  231. if (dwErr != NO_ERROR)
  232. return dwErr;
  233. // If the target machine is nt4, use nt4 userparms
  234. if (dwBuild <= NT40_BUILD_NUMBER) {
  235. return MprAdminUserGetInfo(
  236. lpszServer,
  237. lpszUser,
  238. dwLevel,
  239. lpbBuffer);
  240. }
  241. // Otherwise, use SDO's
  242. else {
  243. HANDLE hServer, hUser;
  244. dwErr = MprAdminUserServerConnect(
  245. lpszServer,
  246. TRUE,
  247. &hServer);
  248. if (dwErr != NO_ERROR)
  249. return dwErr;
  250. dwErr = MprAdminUserOpen(
  251. hServer,
  252. lpszUser,
  253. &hUser);
  254. if (dwErr != NO_ERROR) {
  255. MprAdminUserServerDisconnect(hServer);
  256. return dwErr;
  257. }
  258. dwErr = MprAdminUserRead(
  259. hUser,
  260. dwLevel,
  261. lpbBuffer);
  262. if (dwErr != NO_ERROR) {
  263. MprAdminUserClose(hUser);
  264. MprAdminUserServerDisconnect(hServer);
  265. return dwErr;
  266. }
  267. MprAdminUserClose(hUser);
  268. MprAdminUserServerDisconnect(hServer);
  269. }
  270. return NO_ERROR;
  271. }
  272. //
  273. // Sets user info
  274. //
  275. DWORD UserSetInfo (
  276. IN PWCHAR lpszServer,
  277. IN PWCHAR lpszUser,
  278. IN DWORD dwLevel,
  279. OUT LPBYTE lpbBuffer)
  280. {
  281. DWORD dwErr, dwBuild;
  282. // Find out the OS of the given machine.
  283. dwErr = UserGetNtosBuildNumber(
  284. lpszServer,
  285. &dwBuild);
  286. if (dwErr != NO_ERROR)
  287. return dwErr;
  288. // If the target machine is nt4, use nt4 userparms
  289. if (dwBuild <= NT40_BUILD_NUMBER) {
  290. return MprAdminUserSetInfo(
  291. lpszServer,
  292. lpszUser,
  293. dwLevel,
  294. lpbBuffer);
  295. }
  296. // Otherwise, use SDO's
  297. else {
  298. HANDLE hServer, hUser;
  299. dwErr = MprAdminUserServerConnect(
  300. lpszServer,
  301. TRUE,
  302. &hServer);
  303. if (dwErr != NO_ERROR)
  304. return dwErr;
  305. dwErr = MprAdminUserOpen(
  306. hServer,
  307. lpszUser,
  308. &hUser);
  309. if (dwErr != NO_ERROR) {
  310. MprAdminUserServerDisconnect(hServer);
  311. return dwErr;
  312. }
  313. dwErr = MprAdminUserWrite(
  314. hUser,
  315. dwLevel,
  316. lpbBuffer);
  317. if (dwErr != NO_ERROR) {
  318. MprAdminUserClose(hUser);
  319. MprAdminUserServerDisconnect(hServer);
  320. return dwErr;
  321. }
  322. MprAdminUserClose(hUser);
  323. MprAdminUserServerDisconnect(hServer);
  324. }
  325. return NO_ERROR;
  326. }
  327. //
  328. // Enables or disables a user
  329. //
  330. DWORD UserEnableDisable(
  331. IN PROUTEMON_PARAMS pRmParams,
  332. IN PROUTEMON_UTILS pUtils,
  333. IN PUSER_PARAMS pParams)
  334. {
  335. DWORD dwErr;
  336. // Read in the old user properties if all the options
  337. // weren't specified on the command line.
  338. if (pParams->dwTokenPolicy != TOKEN_ADMIN) {
  339. dwErr = UserGetInfo(
  340. pParams->pszMachine,
  341. pParams->pszAccount,
  342. 0,
  343. (LPBYTE)&(pParams->UserInfo));
  344. if (dwErr != NO_ERROR)
  345. return dwErr;
  346. }
  347. // Set the dialin policy
  348. if (pParams->dwToken == TOKEN_ENABLE)
  349. pParams->UserInfo.bfPrivilege |= RASPRIV_DialinPrivilege;
  350. else
  351. pParams->UserInfo.bfPrivilege &= ~RASPRIV_DialinPrivilege;
  352. // Set the callback policy. The callback number will already
  353. // be set through the parsing.
  354. if (pParams->bPolicySpecified) {
  355. // Initialize
  356. pParams->UserInfo.bfPrivilege &= ~RASPRIV_NoCallback;
  357. pParams->UserInfo.bfPrivilege &= ~RASPRIV_CallerSetCallback;
  358. pParams->UserInfo.bfPrivilege &= ~RASPRIV_AdminSetCallback;
  359. // Set
  360. if (pParams->dwTokenPolicy == TOKEN_NONE)
  361. pParams->UserInfo.bfPrivilege |= RASPRIV_NoCallback;
  362. else if (pParams->dwTokenPolicy == TOKEN_CALLER)
  363. pParams->UserInfo.bfPrivilege |= RASPRIV_CallerSetCallback;
  364. else
  365. pParams->UserInfo.bfPrivilege |= RASPRIV_AdminSetCallback;
  366. }
  367. // Otherwise, initialize the display token
  368. else {
  369. if (pParams->UserInfo.bfPrivilege & RASPRIV_NoCallback)
  370. pParams->dwTokenPolicy = TOKEN_NONE;
  371. else if (pParams->UserInfo.bfPrivilege & RASPRIV_CallerSetCallback)
  372. pParams->dwTokenPolicy = TOKEN_CALLER;
  373. else
  374. pParams->dwTokenPolicy = TOKEN_ADMIN;
  375. }
  376. // Commit the changes to the system
  377. dwErr = UserSetInfo(
  378. pParams->pszMachine,
  379. pParams->pszAccount,
  380. 0,
  381. (LPBYTE)&(pParams->UserInfo));
  382. if (dwErr != NO_ERROR)
  383. return dwErr;
  384. // Print out the results
  385. {
  386. HINSTANCE hInst = GetModuleHandle(NULL);
  387. TCHAR buf1[MAX_TOKEN], buf2[MAX_TOKEN];
  388. DWORD dwYesNo;
  389. dwYesNo = (pParams->dwToken == TOKEN_ENABLE) ? VAL_YES : VAL_NO;
  390. pUtils->put_msg(
  391. hInst,
  392. MSG_USER_ENABLEDISABLE_SUCCESS,
  393. pParams->pszAccount,
  394. GetString (hInst, dwYesNo, buf1),
  395. GetString (hInst, pParams->dwTokenPolicy, buf2),
  396. pParams->UserInfo.wszPhoneNumber
  397. );
  398. }
  399. return NO_ERROR;
  400. }
  401. //
  402. // Shows a user
  403. //
  404. DWORD UserShow(
  405. IN PROUTEMON_PARAMS pRmParams,
  406. IN PROUTEMON_UTILS pUtils,
  407. IN PUSER_PARAMS pParams)
  408. {
  409. DWORD dwErr;
  410. dwErr = UserGetInfo(
  411. pParams->pszMachine,
  412. pParams->pszAccount,
  413. 0,
  414. (LPBYTE)&(pParams->UserInfo));
  415. if (dwErr != NO_ERROR)
  416. return dwErr;
  417. // Print out the results
  418. {
  419. HINSTANCE hInst = GetModuleHandle(NULL);
  420. TCHAR buf1[MAX_TOKEN], buf2[MAX_TOKEN];
  421. DWORD dwTknEnable, dwTknPolicy;
  422. dwTknEnable = (pParams->UserInfo.bfPrivilege & RASPRIV_DialinPrivilege) ?
  423. VAL_YES :
  424. VAL_NO;
  425. if (pParams->UserInfo.bfPrivilege & RASPRIV_NoCallback)
  426. dwTknPolicy = TOKEN_NONE;
  427. else if (pParams->UserInfo.bfPrivilege & RASPRIV_CallerSetCallback)
  428. dwTknPolicy = TOKEN_CALLER;
  429. else
  430. dwTknPolicy = TOKEN_ADMIN;
  431. pUtils->put_msg(
  432. hInst,
  433. MSG_USER_SHOW_SUCCESS,
  434. pParams->pszAccount,
  435. GetString (hInst, dwTknEnable, buf1),
  436. GetString (hInst, dwTknPolicy, buf2),
  437. pParams->UserInfo.wszPhoneNumber
  438. );
  439. }
  440. return NO_ERROR;
  441. }
  442. //
  443. // Upgrades a user
  444. //
  445. DWORD UserUpgrade(
  446. IN PROUTEMON_PARAMS pRmParams,
  447. IN PROUTEMON_UTILS pUtils,
  448. IN PUSER_PARAMS pParams)
  449. {
  450. BOOL bLocal = FALSE;
  451. DWORD dwErr, dwBuild;
  452. DSROLE_MACHINE_ROLE eRole;
  453. // Determine whether this should be local or
  454. // domain upgrade.
  455. dwErr = UserGetNtosBuildNumber(pParams->pszMachine, &dwBuild);
  456. if (dwErr != NO_ERROR)
  457. return dwErr;
  458. // You can upgrade nt4->nt4
  459. if (dwBuild <= NT40_BUILD_NUMBER)
  460. return ERROR_CAN_NOT_COMPLETE;
  461. // Find out the role of the machine
  462. dwErr = UserGetMachineRole(pParams->pszMachine, &eRole);
  463. if (dwErr != NO_ERROR)
  464. return dwErr;
  465. // Now we know whether we're local
  466. bLocal = ((eRole != DsRole_RoleBackupDomainController) &&
  467. (eRole != DsRole_RolePrimaryDomainController));
  468. // Upgrade the users
  469. dwErr = MprAdminUpgradeUsers(pParams->pszMachine, bLocal);
  470. if (dwErr != NO_ERROR)
  471. return dwErr;
  472. // Print out the results
  473. {
  474. HINSTANCE hInst = GetModuleHandle(NULL);
  475. TCHAR buf[MAX_TOKEN];
  476. DWORD dwToken;
  477. dwToken = (bLocal) ? VAL_LOCAL : VAL_DOMAIN;
  478. pUtils->put_msg(
  479. hInst,
  480. MSG_USER_UPGRADE_SUCCESS,
  481. GetString(hInst, dwToken, buf)
  482. );
  483. }
  484. return NO_ERROR;
  485. }
  486. //
  487. // The User functionality engine
  488. //
  489. DWORD UserEngine (
  490. IN PROUTEMON_PARAMS pRmParams,
  491. IN PROUTEMON_UTILS pUtils,
  492. IN PUSER_PARAMS pParams)
  493. {
  494. DWORD dwErr;
  495. HINSTANCE hInst = GetModuleHandle(NULL);
  496. switch (pParams->dwToken) {
  497. case TOKEN_ENABLE:
  498. case TOKEN_DISABLE:
  499. return UserEnableDisable(pRmParams, pUtils, pParams);
  500. case TOKEN_SHOW:
  501. return UserShow(pRmParams, pUtils, pParams);
  502. case TOKEN_UPGRADE:
  503. return UserUpgrade(pRmParams, pUtils, pParams);
  504. }
  505. return NO_ERROR;
  506. }
  507. //
  508. // Handles requests register a ras server in a domain
  509. // or to deregister a ras server in a domain or to query
  510. // whether a given ras server is registered in a given domain.
  511. //
  512. DWORD APIENTRY
  513. UserMonitor (
  514. IN int argc,
  515. IN TCHAR *argv[],
  516. IN PROUTEMON_PARAMS params,
  517. IN PROUTEMON_UTILS utils
  518. )
  519. {
  520. DWORD dwErr;
  521. USER_PARAMS UserParams;
  522. dwErr = UserParse (
  523. argc,
  524. argv,
  525. params,
  526. utils,
  527. TRUE,
  528. &UserParams);
  529. if (dwErr != NO_ERROR)
  530. return NO_ERROR;
  531. dwErr = UserEngine (params, utils, &UserParams);
  532. UserCleanup(&UserParams);
  533. return dwErr;
  534. }