LSASecurityControl.pas 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. {
  2. License Agreement
  3. This content is subject to the Mozilla Public License Version 1.1 (the "License");
  4. You may not use this plugin except in compliance with the License. You may
  5. obtain a copy of the License at http://www.mozilla.org/MPL.
  6. Alternatively, you may redistribute this library, use and/or modify it
  7. under the terms of the GNU Lesser General Public License as published
  8. by the Free Software Foundation; either version 2.1 of the License,
  9. or (at your option) any later version. You may obtain a copy
  10. of the LGPL at www.gnu.org/copyleft.
  11. Software distributed under the License is distributed on an "AS IS" basis,
  12. WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  13. for the specific language governing rights and limitations under the License.
  14. The original code is LSASecurityControl.pas, released April 16, 2007.
  15. The initial developer of the original code is Rainer Döpke
  16. (Formerly: Rainer Budde) (https://www.speed-soft.de).
  17. SimpleSC - NSIS Service Control Plugin is written, published and maintained by
  18. Rainer Döpke (rainer@speed-soft.de).
  19. }
  20. unit LSASecurityControl;
  21. interface
  22. uses
  23. Winapi.Windows;
  24. function GrantPrivilege(AccountName: String; PrivilegeName: String): Integer;
  25. function RemovePrivilege(AccountName: String; PrivilegeName: String): Integer;
  26. function EnablePrivilege(PrivilegeName: String): Integer;
  27. function DisablePrivilege(PrivilegeName: String): Integer;
  28. implementation
  29. type
  30. LSA_HANDLE = Pointer;
  31. TLSAHandle = LSA_HANDLE;
  32. LSA_UNICODE_STRING = record
  33. Length: Word;
  34. MaximumLength: Word;
  35. Buffer: PWideChar;
  36. end;
  37. TLSAUnicodeString = LSA_UNICODE_STRING;
  38. PLSAUnicodeString = ^TLSAUnicodeString;
  39. LSA_OBJECT_ATTRIBUTES = record
  40. Length: ULONG;
  41. RootDirectory: THandle;
  42. ObjectName: PLSAUnicodeString;
  43. Attributes: ULONG;
  44. SecurityDescriptor: Pointer;
  45. SecurityQualityOfService: Pointer;
  46. end;
  47. TLsaObjectAttributes = LSA_OBJECT_ATTRIBUTES;
  48. PLsaObjectAttributes = ^TLsaObjectAttributes;
  49. function LsaOpenPolicy(SystemName: PLSAUnicodeString; var ObjectAttributes: TLsaObjectAttributes; DesiredAccess: ACCESS_MASK; var PolicyHandle: LSA_HANDLE): DWORD; stdcall; external 'advapi32.dll';
  50. function LsaAddAccountRights(PolicyHandle: LSA_HANDLE; AccountSid: PSID; UserRights: PLSAUnicodeString; CountOfRights: ULONG): DWORD; stdcall; external 'advapi32.dll';
  51. function LsaRemoveAccountRights(PolicyHandle: LSA_HANDLE; AccountSid: PSID; AllRights: Boolean; UserRights: PLSAUnicodeString; CountOfRights: ULONG): DWORD; stdcall; external 'advapi32.dll';
  52. function LsaClose(ObjectHandle: LSA_HANDLE): DWORD; stdcall; external 'advapi32.dll';
  53. function GetAccountSid(const AccountName: String; var Sid: PSID): Integer;
  54. var
  55. DomainSize: LongWord;
  56. SidSize: LongWord;
  57. Domain: String;
  58. Use: SID_NAME_USE;
  59. begin
  60. Result := 0;
  61. SidSize := 0;
  62. DomainSize := 0;
  63. if not LookupAccountName(nil, PChar(AccountName), nil, SidSize, nil, DomainSize, Use) and (GetLastError = ERROR_INSUFFICIENT_BUFFER) then
  64. begin
  65. SetLength(Domain, DomainSize);
  66. Sid := AllocMem(SidSize);
  67. if not LookupAccountName(nil, PChar(AccountName), Sid, SidSize, PChar(Domain), DomainSize, Use) then
  68. begin
  69. Result := GetLastError;
  70. FreeMem(Sid);
  71. Sid := nil;
  72. end;
  73. end
  74. else
  75. Result := GetLastError;
  76. end;
  77. function GrantPrivilege(AccountName: String; PrivilegeName: String): Integer;
  78. const
  79. UNICODE_NULL = WCHAR(0);
  80. POLICY_CREATE_ACCOUNT = $00000010;
  81. POLICY_LOOKUP_NAMES = $00000800;
  82. var
  83. SID: PSID;
  84. PolicyHandle: TLSAHandle;
  85. LSAPrivilegeName: TLSAUnicodeString;
  86. LSAObjectAttributes: TLsaObjectAttributes;
  87. pwszPrivilegeName: PWideChar;
  88. PrivilegeNameLength: Cardinal;
  89. Status: DWORD;
  90. begin
  91. Result := 0;
  92. GetMem(pwszPrivilegeName, Length(PrivilegeName) * SizeOf(WideChar) + 1);
  93. StringToWideChar(PrivilegeName, pwszPrivilegeName, Length(PrivilegeName) * SizeOf(WideChar) + 1);
  94. ZeroMemory(@LSAObjectAttributes, SizeOf(TLsaObjectAttributes));
  95. PrivilegeNameLength := Length(pwszPrivilegeName);
  96. if PrivilegeNameLength > 0 then
  97. begin
  98. Result := GetAccountSid(AccountName, SID);
  99. if Result = 0 then
  100. begin
  101. LSAPrivilegeName.Length := PrivilegeNameLength * SizeOf(WideChar);
  102. LSAPrivilegeName.MaximumLength := LSAPrivilegeName.Length + SizeOf(UNICODE_NULL);
  103. LSAPrivilegeName.Buffer := pwszPrivilegeName;
  104. Status := LsaOpenPolicy(nil, LSAObjectAttributes, POLICY_LOOKUP_NAMES or POLICY_CREATE_ACCOUNT, PolicyHandle);
  105. try
  106. if Status = 0 then
  107. Result := LsaAddAccountRights(PolicyHandle, Sid, @LSAPrivilegeName, 1)
  108. else
  109. Result := Status;
  110. finally
  111. LsaClose(PolicyHandle);
  112. end;
  113. end;
  114. end;
  115. FreeMem(pwszPrivilegeName);
  116. end;
  117. function RemovePrivilege(AccountName: String; PrivilegeName: String): Integer;
  118. const
  119. UNICODE_NULL = WCHAR(0);
  120. POLICY_CREATE_ACCOUNT = $00000010;
  121. POLICY_LOOKUP_NAMES = $00000800;
  122. var
  123. SID: PSID;
  124. PolicyHandle: TLSAHandle;
  125. LSAPrivilegeName: TLSAUnicodeString;
  126. LSAObjectAttributes: TLsaObjectAttributes;
  127. pwszPrivilegeName: PWideChar;
  128. PrivilegeNameLength: Cardinal;
  129. Status: DWORD;
  130. begin
  131. Result := 0;
  132. GetMem(pwszPrivilegeName, Length(PrivilegeName) * SizeOf(WideChar) + 1);
  133. StringToWideChar(PrivilegeName, pwszPrivilegeName, Length(PrivilegeName) * SizeOf(WideChar) + 1);
  134. ZeroMemory(@LSAObjectAttributes, SizeOf(TLsaObjectAttributes));
  135. PrivilegeNameLength := Length(pwszPrivilegeName);
  136. if PrivilegeNameLength > 0 then
  137. begin
  138. Result := GetAccountSid(AccountName, SID);
  139. if Result = 0 then
  140. begin
  141. LSAPrivilegeName.Length := PrivilegeNameLength * SizeOf(WideChar);
  142. LSAPrivilegeName.MaximumLength := LSAPrivilegeName.Length + SizeOf(UNICODE_NULL);
  143. LSAPrivilegeName.Buffer := pwszPrivilegeName;
  144. Status := LsaOpenPolicy(nil, LSAObjectAttributes, POLICY_LOOKUP_NAMES or POLICY_CREATE_ACCOUNT, PolicyHandle);
  145. try
  146. if Status = 0 then
  147. Result := LsaRemoveAccountRights(PolicyHandle, Sid, False, @LSAPrivilegeName, 1)
  148. else
  149. Result := Status;
  150. finally
  151. LsaClose(PolicyHandle);
  152. end;
  153. end;
  154. end;
  155. FreeMem(pwszPrivilegeName);
  156. end;
  157. function EnablePrivilege(PrivilegeName: String): Integer;
  158. var
  159. TokenHandle: THandle;
  160. TokenPrivileges: TOKEN_PRIVILEGES;
  161. PreviousState: TOKEN_PRIVILEGES;
  162. ReturnLength: Cardinal;
  163. begin
  164. Result := 0;
  165. if OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, TokenHandle) then
  166. begin
  167. try
  168. if LookupPrivilegeValue(nil, PWideChar(PrivilegeName), TokenPrivileges.Privileges[0].Luid) then
  169. begin
  170. TokenPrivileges.PrivilegeCount := 1;
  171. TokenPrivileges.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
  172. if not AdjustTokenPrivileges(TokenHandle, False, TokenPrivileges, SizeOf(TokenPrivileges), PreviousState, ReturnLength) then
  173. Result := System.GetLastError;
  174. end
  175. else
  176. Result := System.GetLastError;
  177. finally
  178. CloseHandle(TokenHandle);
  179. end;
  180. end
  181. else
  182. Result := System.GetLastError;
  183. end;
  184. function DisablePrivilege(PrivilegeName: String): Integer;
  185. var
  186. TokenHandle: THandle;
  187. TokenPrivileges: TOKEN_PRIVILEGES;
  188. PreviousState: TOKEN_PRIVILEGES;
  189. ReturnLength: Cardinal;
  190. begin
  191. Result := 0;
  192. if OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, TokenHandle) then
  193. begin
  194. try
  195. if LookupPrivilegeValue(nil, PWideChar(PrivilegeName), TokenPrivileges.Privileges[0].Luid) then
  196. begin
  197. TokenPrivileges.PrivilegeCount := 1;
  198. TokenPrivileges.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
  199. if not AdjustTokenPrivileges(TokenHandle, False, TokenPrivileges, SizeOf(TokenPrivileges), PreviousState, ReturnLength) then
  200. Result := System.GetLastError;
  201. end
  202. else
  203. Result := System.GetLastError;
  204. finally
  205. CloseHandle(TokenHandle);
  206. end;
  207. end
  208. else
  209. Result := System.GetLastError;
  210. end;
  211. end.