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.

2302 lines
58 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. srvutil.cpp
  5. Abstract:
  6. Server Service attachment APIs
  7. Author:
  8. Jin Huang (jinhuang) 23-Jun-1997
  9. Revision History:
  10. jinhuang 23-Jan-1998 splitted to client-server
  11. --*/
  12. #include "serverp.h"
  13. #include "srvutil.h"
  14. #include "infp.h"
  15. #include "pfp.h"
  16. #include <io.h>
  17. #pragma hdrstop
  18. DWORD Thread gMaxRegTicks=0;
  19. DWORD Thread gMaxFileTicks=0;
  20. DWORD Thread gMaxDsTicks=0;
  21. WCHAR Thread theAcctDomName[MAX_PATH+1];
  22. WCHAR Thread ComputerName[MAX_COMPUTERNAME_LENGTH+1];
  23. CHAR Thread sidAuthBuf[32];
  24. CHAR Thread sidBuiltinBuf[32];
  25. DWORD Thread t_pebSize=0;
  26. LPVOID Thread t_pebClient=NULL;
  27. SCESTATUS
  28. ScepQueryInfTicks(
  29. IN PWSTR TemplateName,
  30. IN AREA_INFORMATION Area,
  31. OUT PDWORD pTotalTicks
  32. );
  33. SCESTATUS
  34. ScepGetObjectCount(
  35. IN PSCECONTEXT Context,
  36. IN PCWSTR SectionName,
  37. IN BOOL bPolicyProp,
  38. OUT PDWORD pTotalTicks
  39. );
  40. LPTSTR
  41. ScepSearchClientEnv(
  42. IN LPTSTR varName,
  43. IN DWORD dwSize
  44. );
  45. //
  46. // implementations
  47. //
  48. SCESTATUS
  49. ScepGetTotalTicks(
  50. IN PCWSTR TemplateName,
  51. IN PSCECONTEXT Context,
  52. IN AREA_INFORMATION Area,
  53. IN SCEFLAGTYPE nFlag,
  54. OUT PDWORD pTotalTicks
  55. )
  56. /*
  57. Routine Description:
  58. Retrieve the total count of objects from the inf template and/or the
  59. database for the area specified.
  60. Arguments:
  61. TemplateName - the INF template Name
  62. Context - the database context
  63. Area - the security area
  64. nFlag - the flag to indicate operation which determines where the count is
  65. retrieved:
  66. SCE_FLAG_CONFIG
  67. SCE_FLAG_CONFIG_APPEND
  68. SCE_FLAG_ANALYZE
  69. SCE_FLAG_ANALYZE_APPEND
  70. pTotalTicks - the output count
  71. Return Value:
  72. SCE Status
  73. */
  74. {
  75. if ( pTotalTicks == NULL ||
  76. ( NULL == TemplateName && NULL == Context) ) {
  77. return(SCESTATUS_INVALID_PARAMETER);
  78. }
  79. SCESTATUS rc=SCESTATUS_SUCCESS;
  80. DWORD nTicks=0;
  81. *pTotalTicks = 0;
  82. gMaxRegTicks=0;
  83. gMaxFileTicks=0;
  84. gMaxDsTicks=0;
  85. if ( Area & (AREA_FILE_SECURITY |
  86. AREA_REGISTRY_SECURITY) ) { // |
  87. // AREA_DS_OBJECTS) ) {
  88. switch ( nFlag ) {
  89. case SCE_FLAG_CONFIG:
  90. case SCE_FLAG_CONFIG_APPEND:
  91. case SCE_FLAG_CONFIG_SCP:
  92. case SCE_FLAG_CONFIG_SCP_APPEND:
  93. if ( TemplateName != NULL ) {
  94. //
  95. // use the template if there is any
  96. //
  97. rc = ScepQueryInfTicks(
  98. (LPTSTR)TemplateName,
  99. Area & (AREA_FILE_SECURITY |
  100. AREA_REGISTRY_SECURITY), // |
  101. // AREA_DS_OBJECTS),
  102. pTotalTicks
  103. );
  104. }
  105. if ( Context != NULL &&
  106. (nFlag == SCE_FLAG_CONFIG_APPEND ||
  107. nFlag == SCE_FLAG_CONFIG_SCP_APPEND ||
  108. TemplateName == NULL) ) {
  109. //
  110. // use the existing database
  111. //
  112. if ( Area & AREA_REGISTRY_SECURITY ) {
  113. nTicks = 0;
  114. rc = ScepGetObjectCount(Context,
  115. szRegistryKeys,
  116. (nFlag >= SCE_FLAG_CONFIG_SCP) ? TRUE : FALSE,
  117. &nTicks);
  118. if ( SCESTATUS_SUCCESS == rc ) {
  119. gMaxRegTicks += nTicks;
  120. *pTotalTicks += nTicks;
  121. }
  122. }
  123. if ( rc == SCESTATUS_SUCCESS && (Area & AREA_FILE_SECURITY) ) {
  124. nTicks = 0;
  125. rc = ScepGetObjectCount(Context,
  126. szFileSecurity,
  127. (nFlag >= SCE_FLAG_CONFIG_SCP) ? TRUE : FALSE,
  128. &nTicks);
  129. if ( SCESTATUS_SUCCESS == rc ) {
  130. gMaxFileTicks += nTicks;
  131. *pTotalTicks += nTicks;
  132. }
  133. }
  134. #if 0
  135. if ( rc == SCESTATUS_SUCCESS && (Area & AREA_DS_OBJECTS) ) {
  136. nTicks = 0;
  137. rc = ScepGetObjectCount(Context,
  138. szDSSecurity,
  139. (nFlag >= SCE_FLAG_CONFIG_SCP) ? TRUE : FALSE,
  140. &nTicks);
  141. if ( SCESTATUS_SUCCESS == rc ) {
  142. gMaxDsTicks += nTicks;
  143. *pTotalTicks += nTicks;
  144. }
  145. }
  146. #endif
  147. }
  148. break;
  149. case SCE_FLAG_ANALYZE:
  150. case SCE_FLAG_ANALYZE_APPEND:
  151. if ( Context != NULL ) {
  152. //
  153. // use the existing database
  154. //
  155. if ( Area & AREA_REGISTRY_SECURITY ) {
  156. nTicks = 0;
  157. rc = ScepGetObjectCount(Context,
  158. szRegistryKeys,
  159. (nFlag >= SCE_FLAG_CONFIG_SCP) ? TRUE : FALSE,
  160. &nTicks);
  161. if ( SCESTATUS_SUCCESS == rc ) {
  162. gMaxRegTicks += nTicks;
  163. *pTotalTicks += nTicks;
  164. }
  165. }
  166. if ( rc == SCESTATUS_SUCCESS &&
  167. Area & AREA_FILE_SECURITY ) {
  168. nTicks = 0;
  169. rc = ScepGetObjectCount(Context,
  170. szFileSecurity,
  171. (nFlag >= SCE_FLAG_CONFIG_SCP) ? TRUE : FALSE,
  172. &nTicks);
  173. if ( SCESTATUS_SUCCESS == rc ) {
  174. gMaxFileTicks += nTicks;
  175. *pTotalTicks += nTicks;
  176. }
  177. }
  178. #if 0
  179. if ( rc == SCESTATUS_SUCCESS &&
  180. Area & AREA_DS_OBJECTS ) {
  181. nTicks = 0;
  182. rc = ScepGetObjectCount(Context,
  183. szDSSecurity,
  184. (nFlag >= SCE_FLAG_CONFIG_SCP) ? TRUE : FALSE,
  185. &nTicks);
  186. if ( SCESTATUS_SUCCESS == rc ) {
  187. gMaxDsTicks += nTicks;
  188. *pTotalTicks += nTicks;
  189. }
  190. }
  191. #endif
  192. }
  193. if ( rc == SCESTATUS_SUCCESS && TemplateName != NULL &&
  194. (nFlag == SCE_FLAG_ANALYZE_APPEND || Context == NULL) ) {
  195. //
  196. // get handle in template
  197. //
  198. DWORD nTempTicks=0;
  199. rc = ScepQueryInfTicks(
  200. (LPTSTR)TemplateName,
  201. Area & (AREA_FILE_SECURITY |
  202. AREA_REGISTRY_SECURITY), // |
  203. // AREA_DS_OBJECTS),
  204. &nTempTicks
  205. );
  206. if ( rc == SCESTATUS_SUCCESS ) {
  207. *pTotalTicks += nTempTicks;
  208. }
  209. }
  210. break;
  211. default:
  212. return SCESTATUS_INVALID_PARAMETER;
  213. }
  214. }
  215. if ( rc == SCESTATUS_SUCCESS ) {
  216. if ( Area & AREA_SECURITY_POLICY )
  217. *pTotalTicks += TICKS_SECURITY_POLICY_DS + TICKS_SPECIFIC_POLICIES;
  218. if ( Area & AREA_GROUP_MEMBERSHIP )
  219. *pTotalTicks += TICKS_GROUPS;
  220. if ( Area & AREA_PRIVILEGES )
  221. *pTotalTicks += TICKS_PRIVILEGE;
  222. if ( Area & AREA_SYSTEM_SERVICE )
  223. *pTotalTicks += TICKS_GENERAL_SERVICES + TICKS_SPECIFIC_SERVICES;
  224. /*
  225. if ( *pTotalTicks ) {
  226. *pTotalTicks += 10; // for jet engine initialization
  227. }
  228. */
  229. }
  230. return(rc);
  231. }
  232. SCESTATUS
  233. ScepQueryInfTicks(
  234. IN PWSTR TemplateName,
  235. IN AREA_INFORMATION Area,
  236. OUT PDWORD pTotalTicks
  237. )
  238. /*
  239. Routine Description:
  240. Query total number of objects in the inf template for the specified area.
  241. Arguments:
  242. Return:
  243. */
  244. {
  245. LONG Count=0;
  246. HINF InfHandle;
  247. SCESTATUS rc = SceInfpOpenProfile(
  248. TemplateName,
  249. &InfHandle
  250. );
  251. if ( rc == SCESTATUS_SUCCESS ) {
  252. if ( Area & AREA_REGISTRY_SECURITY ) {
  253. Count = SetupGetLineCount(InfHandle, szRegistryKeys);
  254. gMaxRegTicks += Count;
  255. }
  256. if ( Area & AREA_FILE_SECURITY ) {
  257. Count += SetupGetLineCount(InfHandle, szFileSecurity);
  258. gMaxFileTicks += Count;
  259. }
  260. #if 0
  261. if ( Area & AREA_DS_OBJECTS ) {
  262. Count += SetupGetLineCount(InfHandle, szDSSecurity);
  263. gMaxDsTicks += Count;
  264. }
  265. #endif
  266. SceInfpCloseProfile(InfHandle);
  267. }
  268. *pTotalTicks = Count;
  269. return(rc);
  270. }
  271. SCESTATUS
  272. ScepGetObjectCount(
  273. IN PSCECONTEXT Context,
  274. IN PCWSTR SectionName,
  275. IN BOOL bPolicyProp,
  276. OUT PDWORD pTotalTicks
  277. )
  278. {
  279. if ( Context == NULL || SectionName == NULL ||
  280. pTotalTicks == NULL ) {
  281. return(SCESTATUS_INVALID_PARAMETER);
  282. }
  283. PSCESECTION hSection=NULL;
  284. SCESTATUS rc;
  285. DWORD count=0;
  286. rc = ScepOpenSectionForName(
  287. Context,
  288. bPolicyProp ? SCE_ENGINE_SCP : SCE_ENGINE_SMP,
  289. SectionName,
  290. &hSection
  291. );
  292. if ( rc == SCESTATUS_SUCCESS ) {
  293. rc = SceJetGetLineCount(
  294. hSection,
  295. NULL,
  296. FALSE,
  297. &count
  298. );
  299. if ( rc == SCESTATUS_SUCCESS )
  300. *pTotalTicks += count;
  301. SceJetCloseSection( &hSection, TRUE);
  302. }
  303. if ( SCESTATUS_RECORD_NOT_FOUND )
  304. rc = SCESTATUS_SUCCESS;
  305. return(rc);
  306. }
  307. BOOL
  308. ScepIsEngineRecovering()
  309. {
  310. TCHAR TempFileName[MAX_PATH];
  311. PWSTR SysRoot=NULL;
  312. DWORD SysLen;
  313. DWORD rc;
  314. intptr_t hFile;
  315. struct _wfinddata_t FileInfo;
  316. BOOL bFindIt=FALSE;
  317. SysLen = 0;
  318. rc = ScepGetNTDirectory( &SysRoot, &SysLen, SCE_FLAG_WINDOWS_DIR );
  319. if ( rc == NO_ERROR && SysRoot != NULL ) {
  320. swprintf(TempFileName, L"%s\\Security\\tmp.edb", SysRoot);
  321. TempFileName[MAX_PATH-1] = L'\0';
  322. hFile = _wfindfirst(TempFileName, &FileInfo);
  323. if ( hFile != -1 ) {
  324. bFindIt = TRUE;
  325. _findclose(hFile);
  326. }
  327. ScepFree(SysRoot);
  328. }
  329. return bFindIt;
  330. }
  331. SCESTATUS
  332. ScepSaveAndOffAuditing(
  333. OUT PPOLICY_AUDIT_EVENTS_INFO *ppAuditEvent,
  334. IN BOOL bTurnOffAuditing,
  335. IN LSA_HANDLE PolicyHandle OPTIONAL
  336. )
  337. {
  338. LSA_HANDLE lsaHandle=NULL;
  339. NTSTATUS status;
  340. SCESTATUS rc;
  341. POLICY_AUDIT_EVENT_OPTIONS lSaveAudit;
  342. //
  343. // open Lsa policy for read/write
  344. //
  345. if ( PolicyHandle == NULL ) {
  346. ACCESS_MASK access=0;
  347. if ( bTurnOffAuditing ) {
  348. access = POLICY_SET_AUDIT_REQUIREMENTS | POLICY_AUDIT_LOG_ADMIN;
  349. }
  350. status = ScepOpenLsaPolicy(
  351. POLICY_VIEW_AUDIT_INFORMATION | access,
  352. &lsaHandle,
  353. TRUE
  354. );
  355. if (status != ERROR_SUCCESS) {
  356. lsaHandle = NULL;
  357. rc = RtlNtStatusToDosError( status );
  358. ScepLogOutput3( 1, rc, SCEDLL_LSA_POLICY);
  359. return(ScepDosErrorToSceStatus(rc));
  360. }
  361. } else {
  362. lsaHandle = PolicyHandle;
  363. }
  364. //
  365. // Query audit event information
  366. //
  367. status = LsaQueryInformationPolicy( lsaHandle,
  368. PolicyAuditEventsInformation,
  369. (PVOID *)ppAuditEvent
  370. );
  371. rc = RtlNtStatusToDosError( status );
  372. if ( NT_SUCCESS( status ) && bTurnOffAuditing && (*ppAuditEvent)->AuditingMode ) {
  373. //
  374. // turn off object access auditing
  375. //
  376. if ( AuditCategoryObjectAccess < (*ppAuditEvent)->MaximumAuditEventCount ) {
  377. lSaveAudit = (*ppAuditEvent)->EventAuditingOptions[AuditCategoryObjectAccess];
  378. (*ppAuditEvent)->EventAuditingOptions[AuditCategoryObjectAccess] = POLICY_AUDIT_EVENT_NONE;
  379. status = LsaSetInformationPolicy( lsaHandle,
  380. PolicyAuditEventsInformation,
  381. (PVOID)(*ppAuditEvent)
  382. );
  383. //
  384. // restore the object access auditing mode
  385. //
  386. (*ppAuditEvent)->EventAuditingOptions[AuditCategoryObjectAccess] = lSaveAudit;
  387. }
  388. rc = RtlNtStatusToDosError( status );
  389. if ( rc == NO_ERROR )
  390. ScepLogOutput3( 2, 0, SCEDLL_EVENT_IS_OFF);
  391. else
  392. ScepLogOutput3( 1, rc, SCEDLL_SCP_ERROR_EVENT_AUDITING);
  393. } else if ( rc != NO_ERROR)
  394. ScepLogOutput3( 1, rc, SCEDLL_ERROR_QUERY_EVENT_AUDITING);
  395. //
  396. // free LSA handle if it's opened in this function
  397. //
  398. if ( lsaHandle && (PolicyHandle == NULL) )
  399. LsaClose( lsaHandle );
  400. return(ScepDosErrorToSceStatus(rc));
  401. }
  402. NTSTATUS
  403. ScepGetAccountExplicitRight(
  404. IN LSA_HANDLE PolicyHandle,
  405. IN PSID AccountSid,
  406. OUT PDWORD PrivilegeLowRights,
  407. OUT PDWORD PrivilegeHighRights
  408. )
  409. /* ++
  410. Routine Description:
  411. This routine queries the explicitly assigned privilege/rights to a account
  412. (referenced by AccountSid) and stores in a DWORD type variable PrivilegeRights,
  413. in which each bit represents a privilege/right.
  414. Arguments:
  415. PolicyHandle - Lsa Policy Domain handle
  416. AccountSid - The SID for the account
  417. PrivilegeRights - Privilege/Rights of this account
  418. Return value:
  419. NTSTATUS
  420. -- */
  421. {
  422. NTSTATUS NtStatus;
  423. DWORD CurrentPrivLowRights=0, CurrentPrivHighRights=0;
  424. LONG index;
  425. PUNICODE_STRING UserRightEnum=NULL;
  426. ULONG i, cnt=0;
  427. LUID LuidValue;
  428. //
  429. // Enumerate user privilege/rights
  430. //
  431. NtStatus = LsaEnumerateAccountRights(
  432. PolicyHandle,
  433. AccountSid,
  434. &UserRightEnum,
  435. &cnt
  436. );
  437. if ( NtStatus == STATUS_NO_SUCH_PRIVILEGE ||
  438. NtStatus == STATUS_OBJECT_NAME_NOT_FOUND ) {
  439. NtStatus = ERROR_SUCCESS;
  440. goto Done;
  441. }
  442. if ( !NT_SUCCESS( NtStatus) ) {
  443. ScepLogOutput3(1,
  444. RtlNtStatusToDosError(NtStatus),
  445. SCEDLL_SAP_ERROR_ENUMERATE,
  446. L"LsaEnumerateAccountRights");
  447. goto Done;
  448. }
  449. if (UserRightEnum != NULL)
  450. for ( i=0; i < cnt; i++) {
  451. if ( UserRightEnum[i].Length == 0 )
  452. continue;
  453. NtStatus = LsaLookupPrivilegeValue(
  454. PolicyHandle,
  455. &UserRightEnum[i],
  456. &LuidValue
  457. );
  458. if ( NtStatus == STATUS_NO_SUCH_PRIVILEGE ) {
  459. index = ScepLookupPrivByName( UserRightEnum[i].Buffer );
  460. NtStatus = ERROR_SUCCESS;
  461. } else if ( NT_SUCCESS(NtStatus) ) {
  462. index = ScepLookupPrivByValue( LuidValue.LowPart );
  463. } else
  464. index = -1;
  465. if ( index == -1 ) {
  466. //
  467. // not found
  468. //
  469. NtStatus = STATUS_NOT_FOUND;
  470. ScepLogOutput3(1,
  471. RtlNtStatusToDosError(NtStatus),
  472. SCEDLL_USERRIGHT_NOT_DEFINED);
  473. goto Done;
  474. } else {
  475. if ( index < 32 ) {
  476. CurrentPrivLowRights |= (1 << index);
  477. } else {
  478. CurrentPrivHighRights |= (1 << (index-32) );
  479. }
  480. }
  481. }
  482. Done:
  483. *PrivilegeLowRights = CurrentPrivLowRights;
  484. *PrivilegeHighRights = CurrentPrivHighRights;
  485. if (UserRightEnum != NULL)
  486. LsaFreeMemory(UserRightEnum);
  487. return (NtStatus);
  488. }
  489. NTSTATUS
  490. ScepGetMemberListSids(
  491. IN PSID DomainSid,
  492. IN LSA_HANDLE PolicyHandle,
  493. IN PSCE_NAME_LIST pMembers,
  494. OUT PUNICODE_STRING *MemberNames,
  495. OUT PSID** Sids,
  496. OUT PULONG MemberCount
  497. )
  498. /*
  499. Routine Description:
  500. Lookup each account in the name list pMembers and return the lookup information
  501. in the output buffer - MemberNames, Sids, MemberCount.
  502. if an account can't be resolved, the corresponding SID will be empty.
  503. */
  504. {
  505. NTSTATUS NtStatus=STATUS_SUCCESS;
  506. PSCE_NAME_LIST pUser;
  507. PLSA_REFERENCED_DOMAIN_LIST ReferencedDomains=NULL;
  508. PLSA_TRANSLATED_SID2 MemberSids=NULL;
  509. DWORD i;
  510. PSID DomainSidToUse=NULL;
  511. ULONG Cnt=0;
  512. //
  513. // build a UNICODE_STRING for the member list to look up
  514. //
  515. for (pUser=pMembers;
  516. pUser != NULL;
  517. pUser = pUser->Next) {
  518. if ( pUser->Name == NULL ) {
  519. continue;
  520. }
  521. Cnt++;
  522. }
  523. if ( Cnt > 0 ) {
  524. *MemberNames = (PUNICODE_STRING)RtlAllocateHeap(
  525. RtlProcessHeap(),
  526. 0,
  527. Cnt * sizeof (UNICODE_STRING)
  528. );
  529. if ( *MemberNames == NULL )
  530. return(STATUS_NO_MEMORY);
  531. *Sids = (PSID *)ScepAlloc( LMEM_ZEROINIT, Cnt*sizeof(PSID));
  532. if ( *Sids == NULL ) {
  533. NtStatus = STATUS_NO_MEMORY;
  534. goto Done;
  535. }
  536. //
  537. // Lookup each UNICODE_STRING
  538. //
  539. for (pUser=pMembers, Cnt=0;
  540. pUser != NULL;
  541. pUser = pUser->Next) {
  542. if ( pUser->Name == NULL ) {
  543. continue;
  544. }
  545. RtlInitUnicodeString(&((*MemberNames)[Cnt]), pUser->Name);
  546. NtStatus = ScepLsaLookupNames2(
  547. PolicyHandle,
  548. LSA_LOOKUP_ISOLATED_AS_LOCAL,
  549. pUser->Name,
  550. &ReferencedDomains,
  551. &MemberSids
  552. );
  553. if ( !NT_SUCCESS(NtStatus) ) {
  554. ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
  555. SCEDLL_ERROR_LOOKUP);
  556. goto NextMember;
  557. }
  558. DWORD SidLength=0;
  559. //
  560. // translate the LSA_TRANSLATED_SID into PSID
  561. //
  562. if ( MemberSids[0].Use != SidTypeInvalid &&
  563. MemberSids[0].Use != SidTypeUnknown &&
  564. MemberSids[0].Sid != NULL ) {
  565. SidLength = RtlLengthSid(MemberSids[0].Sid);
  566. if ( ((*Sids)[Cnt] = (PSID) ScepAlloc( (UINT)0, SidLength)) == NULL ) {
  567. NtStatus = STATUS_NO_MEMORY;
  568. } else {
  569. //
  570. // copy the SID
  571. // if failed, memory will be freed at cleanup
  572. //
  573. NtStatus = RtlCopySid( SidLength, (*Sids)[Cnt], MemberSids[0].Sid );
  574. }
  575. if ( !NT_SUCCESS(NtStatus) ) {
  576. goto Done;
  577. }
  578. }
  579. NextMember:
  580. if ( ReferencedDomains != NULL ){
  581. LsaFreeMemory(ReferencedDomains);
  582. ReferencedDomains = NULL;
  583. }
  584. if ( MemberSids != NULL ){
  585. LsaFreeMemory(MemberSids);
  586. MemberSids = NULL;
  587. }
  588. Cnt++;
  589. }
  590. }
  591. *MemberCount = Cnt;
  592. Done:
  593. if (!NT_SUCCESS(NtStatus) ) {
  594. if ( *Sids != NULL ) {
  595. for ( i=0; i<Cnt; i++ )
  596. if ( (*Sids)[i] != NULL )
  597. ScepFree( (*Sids)[i] );
  598. ScepFree( *Sids );
  599. *Sids = NULL;
  600. }
  601. if ( *MemberNames != NULL )
  602. RtlFreeHeap(RtlProcessHeap(), 0, *MemberNames);
  603. *MemberNames = NULL;
  604. }
  605. if ( ReferencedDomains != NULL )
  606. LsaFreeMemory(ReferencedDomains);
  607. if ( MemberSids != NULL )
  608. LsaFreeMemory(MemberSids);
  609. return(NtStatus);
  610. }
  611. DWORD
  612. ScepOpenFileObject(
  613. IN LPWSTR pObjectName,
  614. IN ACCESS_MASK AccessMask,
  615. OUT PHANDLE Handle
  616. )
  617. /*++
  618. Routine Description:
  619. opens the specified file (or directory) object
  620. Arguments:
  621. pObjectName - the name of the file object
  622. AccessMask - Desired Access
  623. Handle - the just opened handle to the object
  624. Return value:
  625. Win32 errro code
  626. */
  627. {
  628. NTSTATUS NtStatus;
  629. DWORD Status = ERROR_SUCCESS;
  630. OBJECT_ATTRIBUTES Attributes;
  631. IO_STATUS_BLOCK Isb;
  632. UNICODE_STRING FileName;
  633. RTL_RELATIVE_NAME RelativeName;
  634. PVOID FreeBuffer;
  635. //
  636. // cut and paste code from windows\base\advapi\security.c SetFileSecurityW
  637. //
  638. if (RtlDosPathNameToNtPathName_U(
  639. pObjectName,
  640. &FileName,
  641. NULL,
  642. &RelativeName
  643. ))
  644. {
  645. FreeBuffer = FileName.Buffer;
  646. if ( RelativeName.RelativeName.Length ) {
  647. FileName = *(PUNICODE_STRING)&RelativeName.RelativeName;
  648. }
  649. else {
  650. RelativeName.ContainingDirectory = NULL;
  651. }
  652. InitializeObjectAttributes(
  653. &Attributes,
  654. &FileName,
  655. OBJ_CASE_INSENSITIVE,
  656. RelativeName.ContainingDirectory,
  657. NULL
  658. );
  659. NtStatus = NtOpenFile( Handle,
  660. AccessMask,
  661. &Attributes,
  662. &Isb,
  663. FILE_SHARE_READ |
  664. FILE_SHARE_WRITE |
  665. FILE_SHARE_DELETE,
  666. 0);
  667. if (!NT_SUCCESS(NtStatus))
  668. {
  669. Status = RtlNtStatusToDosError(NtStatus);
  670. }
  671. RtlFreeHeap(RtlProcessHeap(), 0,FreeBuffer);
  672. } else
  673. {
  674. Status = ERROR_INVALID_NAME;
  675. }
  676. return(Status);
  677. }
  678. DWORD
  679. ScepOpenRegistryObject(
  680. IN SE_OBJECT_TYPE ObjectType,
  681. IN LPWSTR pObjectName,
  682. IN ACCESS_MASK AccessMask,
  683. OUT PHKEY Handle
  684. )
  685. /*++
  686. Routine Description:
  687. opens the specified registry key object
  688. Arguments:
  689. pObjectName - the name of the object
  690. AccessMask - Desired access
  691. Handle - the just opened handle to the object
  692. Return value:
  693. Win32 error code
  694. Note:
  695. The code is cut/pasted from windows\base\accctrl\src\registry.cxx and modified
  696. --*/
  697. {
  698. DWORD status=NO_ERROR;
  699. HKEY basekey;
  700. LPWSTR usename, basekeyname, keyname;
  701. if (pObjectName) {
  702. //
  703. // save a copy of the name since we must crack it.
  704. //
  705. if (NULL != (usename = (LPWSTR)ScepAlloc( LMEM_ZEROINIT,
  706. (wcslen(pObjectName) + 1) * sizeof(WCHAR)))) {
  707. wcscpy(usename,pObjectName);
  708. basekeyname = usename;
  709. keyname = wcschr(usename, L'\\');
  710. if (keyname != NULL) {
  711. *keyname = L'\0';
  712. keyname++;
  713. }
  714. if (0 == _wcsicmp(basekeyname, L"MACHINE")) {
  715. basekey = HKEY_LOCAL_MACHINE;
  716. } else if (0 == _wcsicmp(basekeyname, L"USERS")) {
  717. basekey = HKEY_USERS;
  718. } else if ( 0 == _wcsicmp(basekeyname, L"CLASSES_ROOT")) {
  719. basekey = HKEY_CLASSES_ROOT;
  720. } else {
  721. status = ERROR_INVALID_PARAMETER;
  722. }
  723. if (NO_ERROR == status) {
  724. if ( keyname == NULL ) {
  725. *Handle = basekey;
  726. } else {
  727. //
  728. // open the key
  729. //
  730. #ifdef _WIN64
  731. if (ObjectType == SE_REGISTRY_WOW64_32KEY) {
  732. AccessMask |= KEY_WOW64_32KEY;
  733. }
  734. #endif
  735. status = RegOpenKeyEx(
  736. basekey,
  737. keyname,
  738. 0 ,
  739. AccessMask,
  740. Handle
  741. );
  742. }
  743. }
  744. ScepFree(usename);
  745. } else {
  746. status = ERROR_NOT_ENOUGH_MEMORY;
  747. }
  748. } else {
  749. status = ERROR_INVALID_NAME;
  750. }
  751. return(status);
  752. }
  753. SCESTATUS
  754. ScepGetNameInLevel(
  755. IN PCWSTR ObjectFullName,
  756. IN DWORD Level,
  757. IN WCHAR Delim,
  758. OUT PWSTR Buffer,
  759. OUT PBOOL LastOne
  760. )
  761. /* ++
  762. Routine Description:
  763. This routine parses a full path name and returns the component for the
  764. level. For example, a object name "c:\winnt\system32" will return c: for
  765. level 1, winnt for level 2, and system32 for level 3. This routine is
  766. used when add a object to the security tree.
  767. Arguments:
  768. ObjectFullName - The full path name of the object
  769. Level - the level of component to return
  770. Delim - the deliminator to look for
  771. Buffer - The address of buffer for the component name
  772. LastOne - Flag to indicate if the component is the last one
  773. Return value:
  774. SCESTATUS
  775. -- */
  776. {
  777. PWSTR pTemp, pStart;
  778. DWORD i;
  779. if ( ObjectFullName == NULL )
  780. return(SCESTATUS_INVALID_PARAMETER);
  781. //
  782. // loop through the object name to find the level
  783. // if there is no such level, return INVALID_PARAMETER
  784. //
  785. pStart = (PWSTR)ObjectFullName;
  786. for ( i=0; i<Level; i++) {
  787. pTemp = wcschr(pStart, Delim);
  788. if ( pTemp == pStart ) {
  789. return(SCESTATUS_INVALID_PARAMETER);
  790. }
  791. if ( i == Level-1 ) {
  792. //
  793. // find the right level
  794. //
  795. if ( pTemp == NULL ) {
  796. wcscpy(Buffer, pStart);
  797. *LastOne = TRUE;
  798. } else {
  799. wcsncpy(Buffer, pStart, (size_t)(pTemp - pStart));
  800. if ( *(pTemp+1) == L'\0' )
  801. *LastOne = TRUE;
  802. else
  803. *LastOne = FALSE;
  804. }
  805. } else {
  806. if ( pTemp == NULL )
  807. return(SCESTATUS_INVALID_PARAMETER);
  808. else
  809. pStart = pTemp + 1;
  810. }
  811. }
  812. return(SCESTATUS_SUCCESS);
  813. }
  814. SCESTATUS
  815. ScepTranslateFileDirName(
  816. IN PWSTR oldFileName,
  817. OUT PWSTR *newFileName
  818. )
  819. /* ++
  820. Routine Description:
  821. This routine converts a generic file/directory name to a real used name
  822. for the current system. The following generic file/directory names are handled:
  823. %systemroot% - Windows NT root directory (e.g., c:\winnt)
  824. %systemDirectory% - Windows NT system32 directory (e.g., c:\winnt\system32)
  825. Arguments:
  826. oldFileName - the file name to convert, which includes "%" to represent
  827. some directory names
  828. newFileName - the real file name, in which the "%" name is replaced with
  829. the real directory name
  830. Return values:
  831. Win32 error code
  832. -- */
  833. {
  834. PWSTR pTemp=NULL, pStart, TmpBuf, szVar;
  835. DWORD rc=NO_ERROR;
  836. DWORD newFileSize, cSize;
  837. BOOL bContinue;
  838. //
  839. // match for %systemroot%
  840. //
  841. rc = ScepExpandEnvironmentVariable(oldFileName,
  842. L"%SYSTEMROOT%",
  843. SCE_FLAG_WINDOWS_DIR,
  844. newFileName);
  845. if ( rc != ERROR_FILE_NOT_FOUND ) {
  846. return rc;
  847. }
  848. //
  849. // match for %systemdirectory%
  850. //
  851. rc = ScepExpandEnvironmentVariable(oldFileName,
  852. L"%SYSTEMDIRECTORY%",
  853. SCE_FLAG_SYSTEM_DIR,
  854. newFileName);
  855. if ( rc != ERROR_FILE_NOT_FOUND ) {
  856. return rc;
  857. }
  858. //
  859. // match for systemdrive
  860. //
  861. rc = ScepExpandEnvironmentVariable(oldFileName,
  862. L"%SYSTEMDRIVE%",
  863. SCE_FLAG_WINDOWS_DIR,
  864. newFileName);
  865. if ( rc != ERROR_FILE_NOT_FOUND ) {
  866. return rc;
  867. }
  868. //
  869. // match for boot drive
  870. //
  871. rc = ScepExpandEnvironmentVariable(oldFileName,
  872. L"%BOOTDRIVE%",
  873. SCE_FLAG_BOOT_DRIVE,
  874. newFileName);
  875. if ( rc != ERROR_FILE_NOT_FOUND ) {
  876. return rc;
  877. }
  878. rc = ERROR_SUCCESS;
  879. //
  880. // search for environment variable in the current process
  881. //
  882. pStart = wcschr(oldFileName, L'%');
  883. if ( pStart ) {
  884. pTemp = wcschr(pStart+1, L'%');
  885. if ( pTemp ) {
  886. bContinue = TRUE;
  887. //
  888. // find a environment variable to translate
  889. //
  890. TmpBuf = (PWSTR)ScepAlloc(0, ((UINT)(pTemp-pStart))*sizeof(WCHAR));
  891. if ( TmpBuf ) {
  892. wcsncpy(TmpBuf, pStart+1, (size_t)(pTemp-pStart-1));
  893. TmpBuf[pTemp-pStart-1] = L'\0';
  894. //
  895. // try search in the client environment block
  896. //
  897. szVar = ScepSearchClientEnv(TmpBuf, (DWORD)(pTemp-pStart-1));
  898. if ( szVar ) {
  899. // ScepLogOutput2(3,0,L"\tFind client env %s=%s", TmpBuf, szVar);
  900. //
  901. // find it in the client's environment block, use it
  902. // get info in szVar
  903. //
  904. bContinue = FALSE;
  905. newFileSize = ((DWORD)(pStart-oldFileName))+wcslen(szVar)+wcslen(pTemp+1)+1;
  906. *newFileName = (PWSTR)ScepAlloc(0, newFileSize*sizeof(TCHAR));
  907. if (*newFileName ) {
  908. if ( pStart != oldFileName ) {
  909. wcsncpy(*newFileName, oldFileName, (size_t)(pStart-oldFileName));
  910. }
  911. swprintf((PWSTR)(*newFileName+(pStart-oldFileName)), L"%s%s", szVar, pTemp+1);
  912. } else {
  913. rc = ERROR_NOT_ENOUGH_MEMORY;
  914. }
  915. //
  916. // DO NOT free szVar because it's a ref pointer to the env block
  917. //
  918. } else {
  919. cSize = GetEnvironmentVariable( TmpBuf,
  920. NULL,
  921. 0 );
  922. if ( cSize > 0 ) {
  923. //
  924. // does not find it in the client environment block,
  925. // find it in the current server process environment, use it
  926. //
  927. szVar = (PWSTR)ScepAlloc(0, (cSize+1)*sizeof(WCHAR));
  928. if ( szVar ) {
  929. cSize = GetEnvironmentVariable(TmpBuf,
  930. szVar,
  931. cSize);
  932. if ( cSize > 0 ) {
  933. //
  934. // get info in szVar
  935. //
  936. bContinue = FALSE;
  937. newFileSize = ((DWORD)(pStart-oldFileName))+cSize+wcslen(pTemp+1)+1;
  938. *newFileName = (PWSTR)ScepAlloc(0, newFileSize*sizeof(TCHAR));
  939. if (*newFileName ) {
  940. if ( pStart != oldFileName )
  941. wcsncpy(*newFileName, oldFileName, (size_t)(pStart-oldFileName));
  942. swprintf((PWSTR)(*newFileName+(pStart-oldFileName)), L"%s%s", szVar, pTemp+1);
  943. } else
  944. rc = ERROR_NOT_ENOUGH_MEMORY;
  945. }
  946. ScepFree(szVar);
  947. } else
  948. rc = ERROR_NOT_ENOUGH_MEMORY;
  949. }
  950. }
  951. ScepFree(TmpBuf);
  952. } else
  953. rc = ERROR_NOT_ENOUGH_MEMORY;
  954. if ( NO_ERROR != rc || !bContinue ) {
  955. //
  956. // if errored, or do not continue
  957. //
  958. return(rc);
  959. }
  960. //
  961. // not found in environment blob,
  962. // continue to search for DSDIT/DSLOG/SYSVOL in registry
  963. //
  964. if ( ProductType == NtProductLanManNt ) {
  965. //
  966. // search for DSDIT
  967. //
  968. rc = ScepExpandEnvironmentVariable(oldFileName,
  969. L"%DSDIT%",
  970. SCE_FLAG_DSDIT_DIR,
  971. newFileName);
  972. if ( rc != ERROR_FILE_NOT_FOUND ) {
  973. return rc;
  974. }
  975. //
  976. // search for DSLOG
  977. //
  978. rc = ScepExpandEnvironmentVariable(oldFileName,
  979. L"%DSLOG%",
  980. SCE_FLAG_DSLOG_DIR,
  981. newFileName);
  982. if ( rc != ERROR_FILE_NOT_FOUND ) {
  983. return rc;
  984. }
  985. //
  986. // search for SYSVOL
  987. //
  988. rc = ScepExpandEnvironmentVariable(oldFileName,
  989. L"%SYSVOL%",
  990. SCE_FLAG_SYSVOL_DIR,
  991. newFileName);
  992. if ( rc != ERROR_FILE_NOT_FOUND ) {
  993. return rc;
  994. }
  995. }
  996. }
  997. }
  998. //
  999. // Otherwise, just copy the old name to a new buffer and return ERROR_PATH_NOT_FOUND
  1000. //
  1001. *newFileName = (PWSTR)ScepAlloc(0, (wcslen(oldFileName)+1)*sizeof(TCHAR));
  1002. if (*newFileName != NULL) {
  1003. wcscpy(*newFileName, _wcsupr(oldFileName) );
  1004. rc = ERROR_PATH_NOT_FOUND;
  1005. } else
  1006. rc = ERROR_NOT_ENOUGH_MEMORY;
  1007. return(rc);
  1008. }
  1009. LPTSTR
  1010. ScepSearchClientEnv(
  1011. IN LPTSTR varName,
  1012. IN DWORD dwSize
  1013. )
  1014. {
  1015. if ( !varName || dwSize == 0 ||
  1016. !t_pebClient || t_pebSize == 0 ) {
  1017. return NULL;
  1018. }
  1019. LPTSTR pTemp = (LPTSTR)t_pebClient;
  1020. while ( pTemp && *pTemp != L'\0' ) {
  1021. if ( _wcsnicmp(varName, pTemp, dwSize) == 0 &&
  1022. L'=' == *(pTemp+dwSize) ) {
  1023. //
  1024. // find the variable
  1025. //
  1026. return pTemp+dwSize+1;
  1027. break;
  1028. }
  1029. DWORD Len = wcslen(pTemp);
  1030. pTemp += Len+1;
  1031. }
  1032. return NULL;
  1033. }
  1034. SCESTATUS
  1035. ScepConvertLdapToJetIndexName(
  1036. IN PWSTR TempName,
  1037. OUT PWSTR *OutName
  1038. )
  1039. {
  1040. PWSTR pTemp1;
  1041. PWSTR pTemp2;
  1042. INT i,j;
  1043. DWORD Len;
  1044. //
  1045. // Ldap name are in the format of CN=,DC=,...O=
  1046. // Jet Index requires names in the O=,...DC=,CN= format
  1047. //
  1048. // semicolon is converted to , and spaces are stripped out
  1049. //
  1050. if ( TempName == NULL || OutName == NULL ) {
  1051. return(SCESTATUS_INVALID_PARAMETER);
  1052. }
  1053. Len = wcslen(TempName);
  1054. pTemp1 = TempName + Len - 1;
  1055. //
  1056. // skip the trailing spaces, commas, or semicolons
  1057. //
  1058. while ( pTemp1 >= TempName &&
  1059. (*pTemp1 == L' ' || *pTemp1 == L';' || *pTemp1 == L',') ) {
  1060. pTemp1--;
  1061. }
  1062. if ( pTemp1 < TempName ) {
  1063. //
  1064. // all spaces or ; in the name
  1065. //
  1066. return(SCESTATUS_INVALID_PARAMETER);
  1067. }
  1068. //
  1069. // allocate output buffer
  1070. //
  1071. *OutName = (PWSTR)ScepAlloc(0, ((UINT)(pTemp1-TempName+2))*sizeof(WCHAR));
  1072. if ( *OutName != NULL ) {
  1073. pTemp2 = *OutName;
  1074. while ( pTemp1 >= TempName ) {
  1075. //
  1076. // find the previous ; or ,
  1077. //
  1078. i = 0;
  1079. while ( pTemp1-i >= TempName && *(pTemp1-i) != L',' &&
  1080. *(pTemp1-i) != L';' ) {
  1081. i++;
  1082. }
  1083. //
  1084. // either reach the head, or a ; or , is encountered
  1085. //
  1086. i--; // i must be >= 0
  1087. //
  1088. // skip the leading spaces
  1089. //
  1090. j = 0;
  1091. while ( *(pTemp1-i+j) == L' ' && j <= i ) {
  1092. j++;
  1093. }
  1094. //
  1095. // copy the component
  1096. //
  1097. if ( i >= j ) {
  1098. if ( pTemp2 != *OutName ) {
  1099. *pTemp2++ = L',';
  1100. }
  1101. wcsncpy(pTemp2, pTemp1-i+j, i-j+1);
  1102. pTemp2 += (i-j+1);
  1103. } else {
  1104. //
  1105. // all spaces
  1106. //
  1107. }
  1108. pTemp1 -= (i+1);
  1109. //
  1110. // skip the trailing spaces, commas, or semicolons
  1111. //
  1112. while ( pTemp1 >= TempName &&
  1113. (*pTemp1 == L' ' || *pTemp1 == L';' || *pTemp1 == L',') ) {
  1114. pTemp1--;
  1115. }
  1116. }
  1117. if ( pTemp2 == *OutName ) {
  1118. //
  1119. // nothing got copied to the output buffer, WRONG!!!
  1120. //
  1121. ScepFree(*OutName);
  1122. *OutName = NULL;
  1123. return(SCESTATUS_INVALID_PARAMETER);
  1124. } else {
  1125. //
  1126. // teminate the string
  1127. //
  1128. *pTemp2 = L'\0';
  1129. _wcslwr(*OutName);
  1130. return(SCESTATUS_SUCCESS);
  1131. }
  1132. } else
  1133. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  1134. }
  1135. SCESTATUS
  1136. ScepRestoreAuditing(
  1137. IN PPOLICY_AUDIT_EVENTS_INFO auditEvent,
  1138. IN LSA_HANDLE PolicyHandle OPTIONAL
  1139. )
  1140. {
  1141. LSA_HANDLE lsaHandle=NULL;
  1142. NTSTATUS status;
  1143. SCESTATUS rc;
  1144. if ( auditEvent == NULL )
  1145. return(SCESTATUS_INVALID_PARAMETER);
  1146. if ( PolicyHandle == NULL ) {
  1147. // open Lsa policy for read/write
  1148. status = ScepOpenLsaPolicy(
  1149. POLICY_VIEW_AUDIT_INFORMATION |
  1150. POLICY_SET_AUDIT_REQUIREMENTS |
  1151. POLICY_AUDIT_LOG_ADMIN,
  1152. &lsaHandle,
  1153. TRUE
  1154. );
  1155. if (status != ERROR_SUCCESS) {
  1156. lsaHandle = NULL;
  1157. rc = RtlNtStatusToDosError( status );
  1158. ScepLogOutput3( 1, rc, SCEDLL_LSA_POLICY);
  1159. return(ScepDosErrorToSceStatus(rc));
  1160. }
  1161. } else {
  1162. lsaHandle = PolicyHandle;
  1163. }
  1164. // restore
  1165. status = LsaSetInformationPolicy( lsaHandle,
  1166. PolicyAuditEventsInformation,
  1167. (PVOID)(auditEvent)
  1168. );
  1169. rc = RtlNtStatusToDosError( status );
  1170. if ( rc == NO_ERROR )
  1171. ScepLogOutput3( 2, 0, SCEDLL_EVENT_RESTORED);
  1172. else
  1173. ScepLogOutput3( 1, rc, SCEDLL_SCP_ERROR_EVENT_AUDITING);
  1174. if ( lsaHandle && (lsaHandle != PolicyHandle) )
  1175. LsaClose( lsaHandle );
  1176. return(ScepDosErrorToSceStatus(rc));
  1177. }
  1178. DWORD
  1179. ScepGetDefaultDatabase(
  1180. IN LPCTSTR JetDbName OPTIONAL,
  1181. IN DWORD LogOptions,
  1182. IN LPCTSTR LogFileName OPTIONAL,
  1183. OUT PBOOL pAdminLogon OPTIONAL,
  1184. OUT PWSTR *ppDefDatabase
  1185. )
  1186. /*
  1187. Routine Description:
  1188. Get the default SCE database for the current logged on user.
  1189. Arguments:
  1190. JetDbName - optional jet database name
  1191. LogOptions - options for the log, if there is any
  1192. LogFileName - the log file
  1193. pAdminLogon - output flag to indicate if administrative privileged user logged on
  1194. ppDefDatabase - the default database name
  1195. Return Value:
  1196. SCESTATUS
  1197. */
  1198. {
  1199. if ( !ppDefDatabase ) {
  1200. return(ERROR_INVALID_PARAMETER);
  1201. }
  1202. if ( LogOptions & SCE_DISABLE_LOG) {
  1203. ScepEnableDisableLog(FALSE);
  1204. } else {
  1205. ScepEnableDisableLog(TRUE);
  1206. }
  1207. if ( LogOptions & SCE_DEBUG_LOG ) {
  1208. ScepSetVerboseLog(3);
  1209. } else if ( LogOptions & SCE_VERBOSE_LOG ) {
  1210. //
  1211. // by default it's not verbose
  1212. //
  1213. ScepSetVerboseLog(2);
  1214. } else {
  1215. ScepSetVerboseLog(-1);
  1216. }
  1217. if ( ScepLogInitialize( LogFileName ) == ERROR_INVALID_NAME ) {
  1218. ScepLogOutput3(1,0, SCEDLL_LOGFILE_INVALID, LogFileName );
  1219. }
  1220. DWORD rc=ERROR_SUCCESS;
  1221. BOOL bAdminLogon=FALSE;
  1222. //
  1223. // determine if admin logs on
  1224. //
  1225. if ( pAdminLogon || !JetDbName || wcslen(JetDbName) < 1) {
  1226. rc = ScepIsAdminLoggedOn(&bAdminLogon);
  1227. if ( rc != NO_ERROR ) {
  1228. ScepLogOutput3(1, rc, SCEDLL_UNKNOWN_LOGON_USER);
  1229. }
  1230. if ( bAdminLogon ) {
  1231. ScepLogOutput3(3, 0, SCEDLL_ADMIN_LOGON);
  1232. }
  1233. }
  1234. //
  1235. // find the databae name
  1236. //
  1237. if ( JetDbName && wcslen(JetDbName) > 0 ) {
  1238. *ppDefDatabase = (LPTSTR)JetDbName;
  1239. } else {
  1240. //
  1241. // query if the profile name (or the default ) in registry
  1242. //
  1243. rc = ScepGetProfileSetting(
  1244. L"DefaultProfile",
  1245. bAdminLogon,
  1246. ppDefDatabase
  1247. );
  1248. if ( rc != NO_ERROR || *ppDefDatabase == NULL ) { // return is Win32 error code
  1249. ScepLogOutput3(1,rc, SCEDLL_UNKNOWN_DBLOCATION);
  1250. }
  1251. }
  1252. if ( pAdminLogon ) {
  1253. *pAdminLogon = bAdminLogon;
  1254. }
  1255. return(rc);
  1256. }
  1257. BOOL
  1258. ScepIsDomainLocal(
  1259. IN PUNICODE_STRING pDomainName OPTIONAL
  1260. )
  1261. /* ++
  1262. Routine Description:
  1263. This routine checks if the domain is on the local machine by comparing
  1264. the domain name with the local machine's computer name.
  1265. Arguments:
  1266. pDomainName - the domain's name to check
  1267. Return Value:
  1268. TRUE if it is local
  1269. -- */
  1270. {
  1271. NTSTATUS NtStatus;
  1272. OBJECT_ATTRIBUTES ObjectAttributes;
  1273. LSA_HANDLE PolicyHandle;
  1274. DWORD NameLen=MAX_COMPUTERNAME_LENGTH;
  1275. if ( pDomainName == NULL ) {
  1276. //
  1277. // reset the buffer
  1278. //
  1279. ComputerName[0] = L'\0';
  1280. theAcctDomName[0] = L'\0';
  1281. sidBuiltinBuf[0] = '\0';
  1282. sidAuthBuf[0] = '\0';
  1283. return(TRUE);
  1284. }
  1285. if ( pDomainName->Length <= 0 ||
  1286. pDomainName->Buffer == NULL )
  1287. return(TRUE);
  1288. if ( ComputerName[0] == L'\0' ) {
  1289. memset(ComputerName, '\0', (MAX_COMPUTERNAME_LENGTH+1)*sizeof(WCHAR));
  1290. GetComputerName(ComputerName, &NameLen);
  1291. }
  1292. NameLen = wcslen(ComputerName);
  1293. if ( _wcsnicmp(ComputerName, pDomainName->Buffer, pDomainName->Length/2 ) == 0 &&
  1294. (LONG)NameLen == pDomainName->Length/2 )
  1295. return(TRUE);
  1296. if ( theAcctDomName[0] == L'\0' ) {
  1297. //
  1298. // query the current account domain name (for DC case)
  1299. //
  1300. PPOLICY_ACCOUNT_DOMAIN_INFO PolicyAccountDomainInfo=NULL;
  1301. //
  1302. // Open the policy database
  1303. //
  1304. InitializeObjectAttributes( &ObjectAttributes,
  1305. NULL, // Name
  1306. 0, // Attributes
  1307. NULL, // Root
  1308. NULL ); // Security Descriptor
  1309. NtStatus = LsaOpenPolicy( NULL,
  1310. &ObjectAttributes,
  1311. POLICY_VIEW_LOCAL_INFORMATION,
  1312. &PolicyHandle );
  1313. if ( NT_SUCCESS(NtStatus) ) {
  1314. //
  1315. // Query the account domain information
  1316. //
  1317. NtStatus = LsaQueryInformationPolicy( PolicyHandle,
  1318. PolicyAccountDomainInformation,
  1319. (PVOID *)&PolicyAccountDomainInfo );
  1320. LsaClose( PolicyHandle );
  1321. }
  1322. if ( NT_SUCCESS(NtStatus) ) {
  1323. if ( PolicyAccountDomainInfo->DomainName.Buffer ) {
  1324. wcsncpy(theAcctDomName,
  1325. PolicyAccountDomainInfo->DomainName.Buffer,
  1326. PolicyAccountDomainInfo->DomainName.Length/2);
  1327. theAcctDomName[PolicyAccountDomainInfo->DomainName.Length/2] = L'\0';
  1328. }
  1329. LsaFreeMemory(PolicyAccountDomainInfo);
  1330. }
  1331. }
  1332. NameLen = wcslen(theAcctDomName);
  1333. if ( _wcsnicmp(theAcctDomName, pDomainName->Buffer, pDomainName->Length/2) == 0 &&
  1334. (LONG)NameLen == pDomainName->Length/2 )
  1335. return(TRUE);
  1336. else
  1337. return(FALSE);
  1338. }
  1339. BOOL
  1340. ScepIsDomainLocalBySid(
  1341. PSID pSidLookup
  1342. )
  1343. {
  1344. if ( pSidLookup == NULL ) {
  1345. return FALSE;
  1346. }
  1347. NTSTATUS NtStatus;
  1348. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  1349. //
  1350. // search for "NT Authority" name
  1351. //
  1352. if ( sidAuthBuf[0] == '\0' ) { // sid revision can't be 0
  1353. //
  1354. // build the NT authority sid
  1355. //
  1356. NtStatus = RtlInitializeSid(
  1357. (PSID)sidAuthBuf,
  1358. &NtAuthority,
  1359. 0
  1360. );
  1361. if ( !NT_SUCCESS(NtStatus) ) {
  1362. sidAuthBuf[0] = '\0';
  1363. }
  1364. }
  1365. if ( sidAuthBuf[0] != '\0' &&
  1366. RtlEqualSid((PSID)sidAuthBuf, pSidLookup) ) {
  1367. return(TRUE);
  1368. }
  1369. if ( sidBuiltinBuf[0] == '\0' ) {
  1370. //
  1371. // build the builtin domain sid
  1372. //
  1373. NtStatus = RtlInitializeSid(
  1374. (PSID)sidBuiltinBuf,
  1375. &NtAuthority,
  1376. 1
  1377. );
  1378. if ( NT_SUCCESS(NtStatus) ) {
  1379. *(RtlSubAuthoritySid((PSID)sidBuiltinBuf, 0)) = SECURITY_BUILTIN_DOMAIN_RID;
  1380. } else {
  1381. sidBuiltinBuf[0] = '\0';
  1382. }
  1383. }
  1384. if ( sidBuiltinBuf[0] != '\0' &&
  1385. RtlEqualSid((PSID)sidBuiltinBuf, pSidLookup) ) {
  1386. return(TRUE);
  1387. } else {
  1388. return(FALSE);
  1389. }
  1390. }
  1391. NTSTATUS
  1392. ScepAddAdministratorToThisList(
  1393. IN SAM_HANDLE DomainHandle OPTIONAL,
  1394. IN OUT PSCE_NAME_LIST *ppList
  1395. )
  1396. {
  1397. NTSTATUS NtStatus;
  1398. SAM_HANDLE AccountDomain=NULL;
  1399. SAM_HANDLE UserHandle=NULL;
  1400. SAM_HANDLE ServerHandle=NULL;
  1401. PSID DomainSid=NULL;
  1402. USER_NAME_INFORMATION *BufName=NULL;
  1403. DOMAIN_NAME_INFORMATION *DomainName=NULL;
  1404. PSCE_NAME_LIST pName=NULL;
  1405. if (!ppList ) {
  1406. return(STATUS_INVALID_PARAMETER);
  1407. }
  1408. if ( !DomainHandle ) {
  1409. //
  1410. // open the sam account domain
  1411. //
  1412. NtStatus = ScepOpenSamDomain(
  1413. SAM_SERVER_ALL_ACCESS,
  1414. MAXIMUM_ALLOWED,
  1415. &ServerHandle,
  1416. &AccountDomain,
  1417. &DomainSid,
  1418. NULL,
  1419. NULL
  1420. );
  1421. if ( !NT_SUCCESS(NtStatus) ) {
  1422. ScepLogOutput3(1,RtlNtStatusToDosError(NtStatus),
  1423. SCEDLL_ERROR_OPEN, L"SAM");
  1424. return(NtStatus);
  1425. }
  1426. } else {
  1427. AccountDomain = DomainHandle;
  1428. }
  1429. //
  1430. // query account domain name
  1431. //
  1432. NtStatus = SamQueryInformationDomain(
  1433. AccountDomain,
  1434. DomainNameInformation,
  1435. (PVOID *)&DomainName
  1436. );
  1437. if ( NT_SUCCESS( NtStatus ) && DomainName &&
  1438. DomainName->DomainName.Length > 0 && DomainName->DomainName.Buffer ) {
  1439. NtStatus = SamOpenUser(
  1440. AccountDomain,
  1441. MAXIMUM_ALLOWED,
  1442. DOMAIN_USER_RID_ADMIN,
  1443. &UserHandle
  1444. );
  1445. if ( NT_SUCCESS( NtStatus ) ) {
  1446. NtStatus = SamQueryInformationUser(
  1447. UserHandle,
  1448. UserNameInformation,
  1449. (PVOID *)&BufName
  1450. );
  1451. if ( NT_SUCCESS( NtStatus ) && BufName &&
  1452. BufName->UserName.Length > 0 && BufName->UserName.Buffer ) {
  1453. //
  1454. // add it to the members list, check duplicate
  1455. //
  1456. LONG NameLen;
  1457. PWSTR pTemp;
  1458. for ( pName = *ppList; pName; pName=pName->Next ) {
  1459. if ( !pName->Name ) {
  1460. continue;
  1461. }
  1462. pTemp = wcschr( pName->Name, L'\\');
  1463. if ( pTemp ) {
  1464. //
  1465. // has a domain prefix
  1466. //
  1467. pTemp++;
  1468. } else {
  1469. pTemp = pName->Name;
  1470. }
  1471. NameLen = wcslen(pTemp);
  1472. if ( NameLen == BufName->UserName.Length/2 &&
  1473. _wcsnicmp(pTemp,
  1474. BufName->UserName.Buffer,
  1475. BufName->UserName.Length/2) == 0 ) {
  1476. //
  1477. // now, match the domain prefix
  1478. //
  1479. if ( pTemp != pName->Name ) {
  1480. if ( (pTemp-pName->Name-1) == DomainName->DomainName.Length/2 &&
  1481. _wcsnicmp(pName->Name,
  1482. DomainName->DomainName.Buffer,
  1483. DomainName->DomainName.Length/2) == 0 ) {
  1484. break;
  1485. }
  1486. } else {
  1487. break;
  1488. }
  1489. }
  1490. }
  1491. if ( !pName ) {
  1492. //
  1493. // allocate a new node, if no resource, ignore the addition
  1494. //
  1495. pName = (PSCE_NAME_LIST)ScepAlloc( (UINT)0, sizeof(SCE_NAME_LIST));
  1496. if ( pName ) {
  1497. pName->Name = (PWSTR)ScepAlloc( LMEM_ZEROINIT, BufName->UserName.Length+DomainName->DomainName.Length+4);
  1498. if ( pName->Name == NULL ) {
  1499. ScepFree(pName);
  1500. } else {
  1501. //
  1502. // add the node to the front of the members list
  1503. //
  1504. NameLen = DomainName->DomainName.Length/2;
  1505. wcsncpy(pName->Name, DomainName->DomainName.Buffer,
  1506. NameLen);
  1507. pName->Name[NameLen] = L'\\';
  1508. wcsncpy(pName->Name+NameLen+1, BufName->UserName.Buffer,
  1509. BufName->UserName.Length/2);
  1510. pName->Name[NameLen+1+BufName->UserName.Length/2] = L'\0';
  1511. pName->Next = *ppList;
  1512. *ppList = pName;
  1513. }
  1514. }
  1515. } else {
  1516. // else find it in the member list already, do nothing
  1517. }
  1518. }
  1519. //
  1520. // close the user handle
  1521. //
  1522. SamCloseHandle(UserHandle);
  1523. UserHandle = NULL;
  1524. }
  1525. }
  1526. if ( AccountDomain != DomainHandle ) {
  1527. //
  1528. // domain is opened
  1529. //
  1530. SamCloseHandle(AccountDomain);
  1531. SamCloseHandle( ServerHandle );
  1532. if ( DomainSid != NULL )
  1533. SamFreeMemory(DomainSid);
  1534. }
  1535. if ( BufName ) {
  1536. SamFreeMemory(BufName);
  1537. }
  1538. if ( DomainName ) {
  1539. SamFreeMemory(DomainName);
  1540. }
  1541. return(NtStatus);
  1542. }
  1543. DWORD
  1544. ScepDatabaseAccessGranted(
  1545. IN LPTSTR DatabaseName,
  1546. IN DWORD DesiredAccess,
  1547. IN BOOL bCreate
  1548. )
  1549. {
  1550. if ( DatabaseName == NULL || DesiredAccess == 0 ) {
  1551. return(SCESTATUS_INVALID_PARAMETER);
  1552. }
  1553. HANDLE hToken, hNewToken;
  1554. DWORD Win32rc = NO_ERROR;
  1555. //
  1556. // get current client token
  1557. //
  1558. if (!OpenThreadToken( GetCurrentThread(),
  1559. TOKEN_IMPERSONATE | TOKEN_READ | TOKEN_DUPLICATE,
  1560. FALSE,
  1561. &hToken)) {
  1562. if (!OpenProcessToken( GetCurrentProcess(),
  1563. TOKEN_IMPERSONATE | TOKEN_READ | TOKEN_DUPLICATE,
  1564. &hToken)) {
  1565. return( GetLastError() );
  1566. }
  1567. }
  1568. //
  1569. // Duplicate it so it can be used for impersonation
  1570. //
  1571. if (!DuplicateTokenEx(hToken, TOKEN_IMPERSONATE | TOKEN_QUERY,
  1572. NULL, SecurityImpersonation, TokenImpersonation,
  1573. &hNewToken))
  1574. {
  1575. CloseHandle (hToken);
  1576. return ( GetLastError() );
  1577. }
  1578. CloseHandle (hToken);
  1579. PSECURITY_DESCRIPTOR pCurrentSD=NULL;
  1580. PRIVILEGE_SET PrivSet;
  1581. DWORD PrivSetLength = sizeof(PRIVILEGE_SET);
  1582. DWORD dwGrantedAccess;
  1583. BOOL bAccessStatus = TRUE;
  1584. if ( !bCreate ) {
  1585. Win32rc = ScepGetNamedSecurityInfo(
  1586. DatabaseName,
  1587. SE_FILE_OBJECT,
  1588. OWNER_SECURITY_INFORMATION |
  1589. GROUP_SECURITY_INFORMATION |
  1590. DACL_SECURITY_INFORMATION,
  1591. &pCurrentSD
  1592. );
  1593. if ( Win32rc == ERROR_PATH_NOT_FOUND ||
  1594. Win32rc == ERROR_FILE_NOT_FOUND ) {
  1595. pCurrentSD = NULL;
  1596. Win32rc = NO_ERROR;
  1597. }
  1598. }
  1599. if ( Win32rc == NO_ERROR ) {
  1600. if ( pCurrentSD == NULL ) {
  1601. //
  1602. // either this database is to be overwritten (re-created)
  1603. // or it doesn't exist. In both cases, hand the call over to Jet
  1604. // which will do the right access checking.
  1605. //
  1606. } else {
  1607. if ( !AccessCheck (
  1608. pCurrentSD,
  1609. hNewToken,
  1610. DesiredAccess,
  1611. &FileGenericMapping,
  1612. &PrivSet,
  1613. &PrivSetLength,
  1614. &dwGrantedAccess,
  1615. &bAccessStatus
  1616. ) ) {
  1617. Win32rc = GetLastError();
  1618. } else {
  1619. if ( bAccessStatus &&
  1620. (dwGrantedAccess == DesiredAccess ) ) {
  1621. Win32rc = NO_ERROR;
  1622. } else {
  1623. Win32rc = ERROR_ACCESS_DENIED;
  1624. }
  1625. }
  1626. }
  1627. }
  1628. if ( pCurrentSD ) {
  1629. LocalFree(pCurrentSD);
  1630. }
  1631. CloseHandle (hNewToken);
  1632. return( Win32rc );
  1633. }
  1634. DWORD
  1635. ScepAddSidToNameList(
  1636. OUT PSCE_NAME_LIST *pNameList,
  1637. IN PSID pSid,
  1638. IN BOOL bReuseBuffer,
  1639. OUT BOOL *pbBufferUsed
  1640. )
  1641. /* ++
  1642. Routine Description:
  1643. This routine adds a SID to the name list. The new added
  1644. node is always placed as the head of the list for performance reason.
  1645. Arguments:
  1646. pNameList - The address of the name list to add to.
  1647. pSid - the Sid to add
  1648. Return value:
  1649. Win32 error code
  1650. -- */
  1651. {
  1652. PSCE_NAME_LIST pList=NULL;
  1653. ULONG Length;
  1654. //
  1655. // check arguments
  1656. //
  1657. if ( pNameList == NULL ||
  1658. pbBufferUsed == NULL )
  1659. return(ERROR_INVALID_PARAMETER);
  1660. *pbBufferUsed = FALSE;
  1661. if ( pSid == NULL )
  1662. return(NO_ERROR);
  1663. if ( !RtlValidSid(pSid) ) {
  1664. return(ERROR_INVALID_PARAMETER);
  1665. }
  1666. //
  1667. // check if the SID is already in the name list
  1668. //
  1669. for ( pList=*pNameList; pList!=NULL; pList=pList->Next ) {
  1670. if ( pList->Name == NULL ) {
  1671. continue;
  1672. }
  1673. if ( ScepValidSid( (PSID)(pList->Name) ) &&
  1674. RtlEqualSid( (PSID)(pList->Name), pSid ) ) {
  1675. break;
  1676. }
  1677. }
  1678. if ( pList ) {
  1679. //
  1680. // the SID is already in the list
  1681. //
  1682. return(NO_ERROR);
  1683. }
  1684. //
  1685. // allocate a new node
  1686. //
  1687. pList = (PSCE_NAME_LIST)ScepAlloc( (UINT)0, sizeof(SCE_NAME_LIST));
  1688. if ( pList == NULL )
  1689. return(ERROR_NOT_ENOUGH_MEMORY);
  1690. if ( bReuseBuffer ) {
  1691. pList->Name = (PWSTR)pSid;
  1692. *pbBufferUsed = TRUE;
  1693. } else {
  1694. Length = RtlLengthSid ( pSid );
  1695. pList->Name = (PWSTR)ScepAlloc( LMEM_ZEROINIT, Length);
  1696. if ( pList->Name == NULL ) {
  1697. ScepFree(pList);
  1698. return(ERROR_NOT_ENOUGH_MEMORY);
  1699. }
  1700. //
  1701. // add the node to the front of the list and link its next to the old list
  1702. //
  1703. RtlCopySid( Length, (PSID)(pList->Name), pSid );
  1704. }
  1705. pList->Next = *pNameList;
  1706. *pNameList = pList;
  1707. return(NO_ERROR);
  1708. }
  1709. BOOL
  1710. ScepValidSid(
  1711. PSID Sid
  1712. )
  1713. {
  1714. if ( RtlValidSid(Sid) ) {
  1715. PISID Isid = (PISID) Sid;
  1716. if ( Isid->Revision == SID_REVISION ) {
  1717. return(TRUE);
  1718. } else {
  1719. return(FALSE);
  1720. }
  1721. }
  1722. return(FALSE);
  1723. }
  1724. BOOL
  1725. ScepBinarySearch(
  1726. IN PWSTR *aPszPtrs,
  1727. IN DWORD dwSize_aPszPtrs,
  1728. IN PWSTR pszNameToFind
  1729. )
  1730. /* ++
  1731. Routine Description:
  1732. This routine determines if a string is found in a sorted array of strings.
  1733. The complexity of this search is logarithmic (log(n)) in the size of the
  1734. input array.
  1735. Arguments:
  1736. aPszPtrs - the array of string pointers to search in
  1737. dwSize_aPszPtrs - the size of the above array
  1738. pszNameToFind - the string to search for
  1739. Return value:
  1740. TRUE if string is found
  1741. FALSE if string is not found
  1742. -- */
  1743. {
  1744. if ( aPszPtrs == NULL || dwSize_aPszPtrs == 0 || pszNameToFind == NULL ) {
  1745. return FALSE;
  1746. }
  1747. int iLow = 0;
  1748. int iHigh = dwSize_aPszPtrs - 1;
  1749. int iMid;
  1750. int iCmp;
  1751. while (iLow <= iHigh ) {
  1752. iMid = (iLow + iHigh ) / 2;
  1753. iCmp = _wcsicmp( aPszPtrs[iMid], pszNameToFind );
  1754. if ( iCmp == 0 )
  1755. return TRUE;
  1756. else if ( iCmp < 0 )
  1757. iLow = iMid + 1;
  1758. else
  1759. iHigh = iMid - 1;
  1760. }
  1761. return FALSE;
  1762. }