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.

568 lines
14 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. security.cpp
  5. Abstract:
  6. Environment:
  7. WIN32 User Mode
  8. Author:
  9. Vlad Sadovsky (vlads) 19-Apr-1998
  10. --*/
  11. //
  12. // Precompiled header
  13. //
  14. #include "precomp.h"
  15. #pragma hdrstop
  16. #include <nt.h>
  17. #include <ntrtl.h>
  18. #include <nturtl.h>
  19. #include "sti_ci.h"
  20. #include <sti.h>
  21. #include <stiregi.h>
  22. #include <stilib.h>
  23. #include <stiapi.h>
  24. #include <stisvc.h>
  25. #include <eventlog.h>
  26. #include <ntsecapi.h>
  27. #include <lm.h>
  28. NTSTATUS
  29. OpenPolicy(
  30. LPTSTR ServerName, // machine to open policy on (Unicode)
  31. DWORD DesiredAccess, // desired access to policy
  32. PLSA_HANDLE PolicyHandle // resultant policy handle
  33. );
  34. BOOL
  35. GetAccountSid(
  36. LPTSTR SystemName, // where to lookup account
  37. LPTSTR AccountName, // account of interest
  38. PSID *Sid // resultant buffer containing SID
  39. );
  40. NTSTATUS
  41. SetPrivilegeOnAccount(
  42. LSA_HANDLE PolicyHandle, // open policy handle
  43. PSID AccountSid, // SID to grant privilege to
  44. LPTSTR PrivilegeName, // privilege to grant (Unicode)
  45. BOOL bEnable // enable or disable
  46. );
  47. void
  48. InitLsaString(
  49. PLSA_UNICODE_STRING LsaString, // destination
  50. LPTSTR String // source (Unicode)
  51. );
  52. #define RTN_OK 0
  53. #define RTN_USAGE 1
  54. #define RTN_ERROR 13
  55. //
  56. // If you have the ddk, include ntstatus.h.
  57. //
  58. #ifndef STATUS_SUCCESS
  59. #define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
  60. #endif
  61. BOOL
  62. GetDefaultDomainName(
  63. LPTSTR DomainName
  64. )
  65. {
  66. OBJECT_ATTRIBUTES ObjectAttributes;
  67. NTSTATUS NtStatus;
  68. DWORD err = 0;
  69. LSA_HANDLE LsaPolicyHandle = NULL;
  70. PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo = NULL;
  71. //
  72. // Open a handle to the local machine's LSA policy object.
  73. //
  74. InitializeObjectAttributes( &ObjectAttributes, // object attributes
  75. NULL, // name
  76. 0L, // attributes
  77. NULL, // root directory
  78. NULL ); // security descriptor
  79. NtStatus = LsaOpenPolicy( NULL, // system name
  80. &ObjectAttributes, // object attributes
  81. POLICY_EXECUTE, // access mask
  82. &LsaPolicyHandle ); // policy handle
  83. if( !NT_SUCCESS( NtStatus ) )
  84. {
  85. return FALSE;
  86. }
  87. //
  88. // Query the domain information from the policy object.
  89. //
  90. NtStatus = LsaQueryInformationPolicy( LsaPolicyHandle,
  91. PolicyAccountDomainInformation,
  92. (PVOID *) &DomainInfo );
  93. if (!NT_SUCCESS(NtStatus))
  94. {
  95. LsaClose(LsaPolicyHandle);
  96. return FALSE;
  97. }
  98. (void) LsaClose(LsaPolicyHandle);
  99. //
  100. // Copy the domain name into our cache, and
  101. //
  102. CopyMemory( DomainName,
  103. DomainInfo->DomainName.Buffer,
  104. DomainInfo->DomainName.Length );
  105. //
  106. // Null terminate it appropriately
  107. //
  108. DomainName[DomainInfo->DomainName.Length / sizeof(WCHAR)] = L'\0';
  109. //
  110. // Clean up
  111. //
  112. LsaFreeMemory( (PVOID)DomainInfo );
  113. return TRUE;
  114. }
  115. LPTSTR
  116. GetMachineName(
  117. LPWSTR AccountName
  118. )
  119. {
  120. LSA_HANDLE PolicyHandle = NULL;
  121. WCHAR DomainName[128];
  122. WCHAR LocalComputerName[128];
  123. LPTSTR MachineName = NULL;
  124. LPTSTR p;
  125. LPTSTR DCName = NULL;
  126. NET_API_STATUS NetStatus;
  127. UNICODE_STRING NameStrings;
  128. PLSA_REFERENCED_DOMAIN_LIST ReferencedDomains = NULL;
  129. PLSA_TRANSLATED_SID LsaSids = NULL;
  130. PUSER_MODALS_INFO_1 Modals = NULL;
  131. DWORD Size;
  132. NTSTATUS Status;
  133. //
  134. // Get the domain name
  135. //
  136. p = wcschr( wszAccountName, L'\\' );
  137. if (p) {
  138. *p = 0;
  139. wcscpy( DomainName, wszAccountName );
  140. *p = L'\\';
  141. } else {
  142. wcscpy( DomainName, wszAccountName );
  143. }
  144. //
  145. // Open the policy on the target machine.
  146. //
  147. Status = OpenPolicy(
  148. NULL,
  149. POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES,
  150. &PolicyHandle
  151. );
  152. if (Status != STATUS_SUCCESS) {
  153. goto exit;
  154. }
  155. //
  156. // lookup the domain name for the account
  157. //
  158. InitLsaString( &NameStrings, AccountName );
  159. Status = LsaLookupNames(
  160. PolicyHandle,
  161. 1,
  162. &NameStrings,
  163. &ReferencedDomains,
  164. &LsaSids
  165. );
  166. if (Status != STATUS_SUCCESS) {
  167. goto exit;
  168. }
  169. //
  170. // get the local computer name
  171. //
  172. Size = sizeof(LocalComputerName);
  173. if (!GetComputerNameW( LocalComputerName, &Size )) {
  174. goto exit;
  175. }
  176. //
  177. // see if we are tring to set a local account
  178. //
  179. if (wcscmp( LocalComputerName, ReferencedDomains->Domains->Name.Buffer ) != 0) {
  180. //
  181. // see what part of the domain we are attempting to set
  182. //
  183. NetStatus = NetUserModalsGet( NULL, 1, (LPBYTE*) &Modals );
  184. if (NetStatus != NERR_Success) {
  185. goto exit;
  186. }
  187. if (Modals->usrmod1_role != UAS_ROLE_PRIMARY) {
  188. //
  189. // we know we are remote, so get the real dc name
  190. //
  191. NetStatus = NetGetDCName( NULL, DomainName, (LPBYTE*) &DCName );
  192. if (NetStatus != NERR_Success) {
  193. goto exit;
  194. }
  195. MachineName = StringDup( DCName );
  196. }
  197. }
  198. exit:
  199. if (Modals) {
  200. NetApiBufferFree( Modals );
  201. }
  202. if (DCName) {
  203. NetApiBufferFree( DCName );
  204. }
  205. if (ReferencedDomains) {
  206. LsaFreeMemory( ReferencedDomains );
  207. }
  208. if (LsaSids) {
  209. LsaFreeMemory( LsaSids );
  210. }
  211. if (PolicyHandle) {
  212. LsaClose( PolicyHandle );
  213. }
  214. return MachineName;
  215. }
  216. DWORD
  217. SetServiceSecurity(
  218. LPTSTR AccountName
  219. )
  220. {
  221. LSA_HANDLE PolicyHandle;
  222. PSID pSid;
  223. NTSTATUS Status;
  224. int iRetVal=RTN_ERROR;
  225. LPWSTR MachineName;
  226. WCHAR NewAccountName[512];
  227. WCHAR wszAccountName[256];
  228. *wszAccountName = L'\0';
  229. #ifdef UNICODE
  230. wcscpy(wszAccountName,AccountName);
  231. #else
  232. // MultiByteToWideChar(CP_ACP,
  233. // 0,
  234. // AccountName, -1,
  235. // wszAccountName, sizeof(wszAccountName));
  236. #endif
  237. if (AccountName[0] == L'.') {
  238. if (GetDefaultDomainName( NewAccountName )) {
  239. wcscat( NewAccountName, &AccountName[1] );
  240. AccountName = NewAccountName;
  241. }
  242. }
  243. //
  244. // try to get the correct machine name
  245. //
  246. MachineName = GetMachineName( wszAccountName );
  247. //
  248. // Open the policy on the target machine.
  249. //
  250. Status = OpenPolicy(
  251. MachineName,
  252. POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES,
  253. &PolicyHandle
  254. );
  255. if (Status != STATUS_SUCCESS) {
  256. return RTN_ERROR;
  257. }
  258. //
  259. // Obtain the SID of the user/group.
  260. // Note that we could target a specific machine, but we don't.
  261. // Specifying NULL for target machine searches for the SID in the
  262. // following order: well-known, Built-in and local, primary domain,
  263. // trusted domains.
  264. //
  265. if(GetAccountSid(
  266. MachineName, // target machine
  267. AccountName,// account to obtain SID
  268. &pSid // buffer to allocate to contain resultant SID
  269. )) {
  270. //
  271. // We only grant the privilege if we succeeded in obtaining the
  272. // SID. We can actually add SIDs which cannot be looked up, but
  273. // looking up the SID is a good sanity check which is suitable for
  274. // most cases.
  275. //
  276. // Grant the SeServiceLogonRight to users represented by pSid.
  277. //
  278. if((Status=SetPrivilegeOnAccount(
  279. PolicyHandle, // policy handle
  280. pSid, // SID to grant privilege
  281. L"SeServiceLogonRight", // Unicode privilege
  282. TRUE // enable the privilege
  283. )) == STATUS_SUCCESS) {
  284. iRetVal=RTN_OK;
  285. }
  286. }
  287. //
  288. // Close the policy handle.
  289. //
  290. LsaClose(PolicyHandle);
  291. //
  292. // Free memory allocated for SID.
  293. //
  294. if(pSid != NULL) MemFree(pSid);
  295. return iRetVal;
  296. }
  297. void
  298. InitLsaString(
  299. PLSA_UNICODE_STRING LsaString,
  300. LPTSTR String
  301. )
  302. {
  303. DWORD StringLength;
  304. if (String == NULL) {
  305. LsaString->Buffer = NULL;
  306. LsaString->Length = 0;
  307. LsaString->MaximumLength = 0;
  308. return;
  309. }
  310. StringLength = wcslen(String);
  311. LsaString->Buffer = String;
  312. LsaString->Length = (USHORT) StringLength * sizeof(WCHAR);
  313. LsaString->MaximumLength=(USHORT)(StringLength+1) * sizeof(WCHAR);
  314. }
  315. NTSTATUS
  316. OpenPolicy(
  317. LPTSTR ServerName,
  318. DWORD DesiredAccess,
  319. PLSA_HANDLE PolicyHandle
  320. )
  321. {
  322. LSA_OBJECT_ATTRIBUTES ObjectAttributes;
  323. LSA_UNICODE_STRING ServerString;
  324. PLSA_UNICODE_STRING Server = NULL;
  325. //
  326. // Always initialize the object attributes to all zeroes.
  327. //
  328. ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
  329. if (ServerName != NULL) {
  330. //
  331. // Make a LSA_UNICODE_STRING out of the LPTSTR passed in
  332. //
  333. InitLsaString(&ServerString, ServerName);
  334. Server = &ServerString;
  335. }
  336. //
  337. // Attempt to open the policy.
  338. //
  339. return LsaOpenPolicy(
  340. Server,
  341. &ObjectAttributes,
  342. DesiredAccess,
  343. PolicyHandle
  344. );
  345. }
  346. /*++
  347. This function attempts to obtain a SID representing the supplied
  348. account on the supplied system.
  349. If the function succeeds, the return value is TRUE. A buffer is
  350. allocated which contains the SID representing the supplied account.
  351. This buffer should be freed when it is no longer needed by calling
  352. HeapFree(GetProcessHeap(), 0, buffer)
  353. If the function fails, the return value is FALSE. Call GetLastError()
  354. to obtain extended error information.
  355. --*/
  356. BOOL
  357. GetAccountSid(
  358. LPTSTR SystemName,
  359. LPTSTR AccountName,
  360. PSID *Sid
  361. )
  362. {
  363. LPTSTR ReferencedDomain=NULL;
  364. DWORD cbSid=128; // initial allocation attempt
  365. DWORD cbReferencedDomain=32; // initial allocation size
  366. SID_NAME_USE peUse;
  367. BOOL bSuccess=FALSE; // assume this function will fail
  368. __try {
  369. //
  370. // initial memory allocations
  371. //
  372. if((*Sid=LocalAlloc(cbSid)) == NULL) {
  373. __leave;
  374. }
  375. if((ReferencedDomain=LocalAlloc(cbReferencedDomain)) == NULL) {
  376. __leave;
  377. }
  378. //
  379. // Obtain the SID of the specified account on the specified system.
  380. //
  381. while(!LookupAccountName(
  382. SystemName, // machine to lookup account on
  383. AccountName, // account to lookup
  384. *Sid, // SID of interest
  385. &cbSid, // size of SID
  386. ReferencedDomain, // domain account was found on
  387. &cbReferencedDomain,
  388. &peUse
  389. )) {
  390. if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
  391. //
  392. // reallocate memory
  393. //
  394. if((*Sid=HeapReAlloc(
  395. GetProcessHeap(),
  396. 0,
  397. *Sid,
  398. cbSid
  399. )) == NULL) __leave;
  400. if((ReferencedDomain=HeapReAlloc(
  401. GetProcessHeap(),
  402. 0,
  403. ReferencedDomain,
  404. cbReferencedDomain
  405. )) == NULL) __leave;
  406. }
  407. else __leave;
  408. }
  409. //
  410. // Indicate success.
  411. //
  412. bSuccess=TRUE;
  413. } // finally
  414. __finally {
  415. //
  416. // Cleanup and indicate failure, if appropriate.
  417. //
  418. LocalFree(ReferencedDomain);
  419. if(!bSuccess) {
  420. if(*Sid != NULL) {
  421. LocalFree(*Sid);
  422. *Sid = NULL;
  423. }
  424. }
  425. } // finally
  426. return bSuccess;
  427. }
  428. NTSTATUS
  429. SetPrivilegeOnAccount(
  430. LSA_HANDLE PolicyHandle, // open policy handle
  431. PSID AccountSid, // SID to grant privilege to
  432. LPTSTR PrivilegeName, // privilege to grant (Unicode)
  433. BOOL bEnable // enable or disable
  434. )
  435. {
  436. LSA_UNICODE_STRING PrivilegeString;
  437. //
  438. // Create a LSA_UNICODE_STRING for the privilege name.
  439. //
  440. InitLsaString(&PrivilegeString, PrivilegeName);
  441. //
  442. // grant or revoke the privilege, accordingly
  443. //
  444. if(bEnable) {
  445. return LsaAddAccountRights(
  446. PolicyHandle, // open policy handle
  447. AccountSid, // target SID
  448. &PrivilegeString, // privileges
  449. 1 // privilege count
  450. );
  451. }
  452. else {
  453. return LsaRemoveAccountRights(
  454. PolicyHandle, // open policy handle
  455. AccountSid, // target SID
  456. FALSE, // do not disable all rights
  457. &PrivilegeString, // privileges
  458. 1 // privilege count
  459. );
  460. }
  461. }