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.

345 lines
9.1 KiB

  1. /*++
  2. Managing user privileges can be achieved programmatically using the
  3. following steps:
  4. 1. Open the policy on the target machine with LsaOpenPolicy(). To grant
  5. privileges, open the policy with POLICY_CREATE_ACCOUNT and
  6. POLICY_LOOKUP_NAMES access. To revoke privileges, open the policy with
  7. POLICY_LOOKUP_NAMES access.
  8. 2. Obtain a SID (security identifier) representing the user/group of
  9. interest. The LookupAccountName() and LsaLookupNames() APIs can obtain a
  10. SID from an account name.
  11. 3. Call LsaAddAccountRights() to grant privileges to the user(s)
  12. represented by the supplied SID.
  13. 4. Call LsaRemoveAccountRights() to revoke privileges from the user(s)
  14. represented by the supplied SID.
  15. 5. Close the policy with LsaClose().
  16. To successfully grant and revoke privileges, the caller needs to be an
  17. administrator on the target system.
  18. The LSA API LsaEnumerateAccountRights() can be used to determine which
  19. privileges have been granted to an account.
  20. The LSA API LsaEnumerateAccountsWithUserRight() can be used to determine
  21. which accounts have been granted a specified privilege.
  22. Documentation and header files for these LSA APIs is provided in the
  23. Windows 32 SDK in the MSTOOLS\SECURITY directory.
  24. NOTE: These LSA APIs are currently implemented as Unicode only.
  25. This sample will grant the privilege SeServiceLogonRight to the account
  26. specified on argv[1].
  27. This sample is dependant on these import libs
  28. advapi32.lib (for LsaXxx)
  29. user32.lib (for wsprintf)
  30. This sample will work properly compiled ANSI or Unicode.
  31. You can use domain\account as argv[1]. For instance, mydomain\scott will
  32. grant the privilege to the mydomain domain account scott.
  33. The optional target machine is specified as argv[2], otherwise, the
  34. account database is updated on the local machine.
  35. The LSA APIs used by this sample are Unicode only.
  36. Use LsaRemoveAccountRights() to remove account rights.
  37. Scott Field (sfield) 12-Jul-95
  38. --*/
  39. #ifndef UNICODE
  40. #define UNICODE
  41. #endif // UNICODE
  42. #include <windows.h>
  43. #include <stdio.h>
  44. #include <ntsecapi.h>
  45. #include <shlwapi.h>
  46. #ifndef STATUS_SUCCESS
  47. #define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
  48. #endif
  49. NTSTATUS
  50. OpenPolicy(
  51. LPWSTR ServerName, // machine to open policy on (Unicode)
  52. DWORD DesiredAccess, // desired access to policy
  53. PLSA_HANDLE PolicyHandle // resultant policy handle
  54. );
  55. LPTSTR
  56. ConvertTimeToString(
  57. LARGE_INTEGER time // Kerberos time value
  58. );
  59. void
  60. InitLsaString(
  61. PLSA_UNICODE_STRING LsaString, // destination
  62. LPWSTR String // source (Unicode)
  63. );
  64. void
  65. DisplayNtStatus(
  66. LPSTR szAPI, // pointer to function name (ANSI)
  67. NTSTATUS Status // NTSTATUS error value
  68. );
  69. void
  70. DisplayWinError(
  71. LPSTR szAPI, // pointer to function name (ANSI)
  72. DWORD WinError // DWORD WinError
  73. );
  74. #define RTN_OK 0
  75. #define RTN_USAGE 1
  76. #define RTN_ERROR 13
  77. static LPCTSTR dt_output_dhms = TEXT("%d %s %02d:%02d:%02d");
  78. static LPCTSTR dt_day_plural = TEXT("days");
  79. static LPCTSTR dt_day_singular = TEXT("day");
  80. static LPCTSTR dt_output_donly = TEXT("%d %s");
  81. static LPCTSTR dt_output_hms = TEXT("%d:%02d:%02d");
  82. LPTSTR
  83. ConvertTimeToString(
  84. LARGE_INTEGER time
  85. )
  86. {
  87. int days, hours, minutes, seconds;
  88. DWORD tt;
  89. static TCHAR buf2[40];
  90. #define TPS (10*1000*1000)
  91. DWORD dt = (long)(time.QuadPart / TPS);
  92. days = (int) (dt / (24*3600l));
  93. tt = dt % (24*3600l);
  94. hours = (int) (tt / 3600);
  95. tt %= 3600;
  96. minutes = (int) (tt / 60);
  97. seconds = (int) (tt % 60);
  98. if (days) {
  99. if (hours || minutes || seconds) {
  100. wnsprintf(buf2, sizeof(buf2)/sizeof(buf2[0]),
  101. dt_output_dhms, days,
  102. (days > 1) ? dt_day_plural : dt_day_singular,
  103. hours, minutes, seconds);
  104. }
  105. else {
  106. wnsprintf(buf2, sizeof(buf2)/sizeof(buf2[0]),
  107. dt_output_donly, days,
  108. (days > 1) ? dt_day_plural : dt_day_singular);
  109. }
  110. }
  111. else {
  112. wnsprintf(buf2, sizeof(buf2)/sizeof(buf2[0]),
  113. dt_output_hms, hours, minutes, seconds);
  114. }
  115. return(buf2);
  116. }
  117. int _cdecl main(
  118. int argc,
  119. char *argv[]
  120. )
  121. {
  122. LSA_HANDLE PolicyHandle;
  123. WCHAR wComputerName[256]=L""; // static machine name buffer
  124. NTSTATUS Status;
  125. int iRetVal=RTN_ERROR; // assume error from main
  126. PPOLICY_DOMAIN_KERBEROS_TICKET_INFO KerbInfo;
  127. if (argc > 2)
  128. {
  129. fprintf(stderr,"Usage: %s [TargetMachine]\n",
  130. argv[0]);
  131. return RTN_USAGE;
  132. }
  133. //
  134. // Pick up machine name on argv[2], if appropriate
  135. // assumes source is ANSI. Resultant string is Unicode.
  136. //
  137. if (argc == 2)
  138. wnsprintf(wComputerName, sizeof(wComputerName)/sizeof(wComputerName[0]),
  139. L"%hS", argv[1]);
  140. //
  141. // Default is to use the LOGONSERVER
  142. //
  143. if (argc==1)
  144. {
  145. GetEnvironmentVariable(
  146. L"LOGONSERVER",
  147. wComputerName,
  148. sizeof(wComputerName)/sizeof(wComputerName[0]));
  149. }
  150. //
  151. // Open the policy on the target machine.
  152. //
  153. if((Status=OpenPolicy(
  154. wComputerName, // target machine
  155. MAXIMUM_ALLOWED,
  156. &PolicyHandle // resultant policy handle
  157. )) != STATUS_SUCCESS) {
  158. DisplayNtStatus("OpenPolicy", Status);
  159. return RTN_ERROR;
  160. }
  161. //
  162. // Get the Kerberos policy
  163. //
  164. if ((Status=LsaQueryDomainInformationPolicy(
  165. PolicyHandle,
  166. PolicyDomainKerberosTicketInformation,
  167. &KerbInfo)) != STATUS_SUCCESS)
  168. {
  169. DisplayNtStatus("LsaQueryDomainInformationPolicy", Status);
  170. return RTN_ERROR;
  171. }
  172. //
  173. // Print out the Kerberos information
  174. //
  175. printf("Authentication options: 0x%x\n", KerbInfo->AuthenticationOptions);
  176. printf("MaxServiceTicketAge: %S\n",
  177. ConvertTimeToString(KerbInfo->MaxServiceTicketAge));
  178. printf("MaxTicketAge: %S\n", ConvertTimeToString(KerbInfo->MaxTicketAge));
  179. printf("MaxRenewAge: %S\n", ConvertTimeToString(KerbInfo->MaxRenewAge));
  180. printf("MaxClockSkew: %S\n", ConvertTimeToString(KerbInfo->MaxClockSkew));
  181. //
  182. // Free buffer
  183. //
  184. LsaFreeMemory(KerbInfo);
  185. //
  186. // Close the policy handle.
  187. //
  188. LsaClose(PolicyHandle);
  189. return iRetVal;
  190. }
  191. void
  192. InitLsaString(
  193. PLSA_UNICODE_STRING LsaString,
  194. LPWSTR String
  195. )
  196. {
  197. DWORD StringLength;
  198. if (String == NULL) {
  199. LsaString->Buffer = NULL;
  200. LsaString->Length = 0;
  201. LsaString->MaximumLength = 0;
  202. return;
  203. }
  204. StringLength = wcslen(String);
  205. LsaString->Buffer = String;
  206. LsaString->Length = (USHORT) StringLength * sizeof(WCHAR);
  207. LsaString->MaximumLength=(USHORT)(StringLength+1) * sizeof(WCHAR);
  208. }
  209. NTSTATUS
  210. OpenPolicy(
  211. LPWSTR ServerName,
  212. DWORD DesiredAccess,
  213. PLSA_HANDLE PolicyHandle
  214. )
  215. {
  216. LSA_OBJECT_ATTRIBUTES ObjectAttributes;
  217. LSA_UNICODE_STRING ServerString;
  218. PLSA_UNICODE_STRING Server = NULL;
  219. //
  220. // Always initialize the object attributes to all zeroes.
  221. //
  222. ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
  223. if (ServerName != NULL) {
  224. //
  225. // Make a LSA_UNICODE_STRING out of the LPWSTR passed in
  226. //
  227. InitLsaString(&ServerString, ServerName);
  228. Server = &ServerString;
  229. }
  230. //
  231. // Attempt to open the policy.
  232. //
  233. return LsaOpenPolicy(
  234. Server,
  235. &ObjectAttributes,
  236. DesiredAccess,
  237. PolicyHandle
  238. );
  239. }
  240. void
  241. DisplayNtStatus(
  242. LPSTR szAPI,
  243. NTSTATUS Status
  244. )
  245. {
  246. //
  247. // Convert the NTSTATUS to Winerror. Then call DisplayWinError().
  248. //
  249. DisplayWinError(szAPI, LsaNtStatusToWinError(Status));
  250. }
  251. void
  252. DisplayWinError(
  253. LPSTR szAPI,
  254. DWORD WinError
  255. )
  256. {
  257. LPSTR MessageBuffer;
  258. DWORD dwBufferLength;
  259. if(dwBufferLength = FormatMessageA(
  260. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  261. FORMAT_MESSAGE_FROM_SYSTEM,
  262. NULL,
  263. WinError,
  264. GetUserDefaultLangID(),
  265. (LPSTR) &MessageBuffer,
  266. 0,
  267. NULL
  268. ))
  269. {
  270. DWORD dwBytesWritten; // unused
  271. //
  272. // Output message string on stderr.
  273. //
  274. WriteFile(
  275. GetStdHandle(STD_ERROR_HANDLE),
  276. MessageBuffer,
  277. dwBufferLength,
  278. &dwBytesWritten,
  279. NULL
  280. );
  281. //
  282. // Free the buffer allocated by the system.
  283. //
  284. LocalFree(MessageBuffer);
  285. }
  286. }