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.

2378 lines
62 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 == rc)
  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. BOOL bFindIt=FALSE;
  315. SysLen = 0;
  316. rc = ScepGetNTDirectory( &SysRoot, &SysLen, SCE_FLAG_WINDOWS_DIR );
  317. if ( rc == NO_ERROR && SysRoot != NULL ) {
  318. swprintf(TempFileName, L"%s\\Security\\tmp.edb", SysRoot);
  319. TempFileName[MAX_PATH-1] = L'\0';
  320. if ( 0xFFFFFFFF != GetFileAttributes(TempFileName) ) {
  321. bFindIt = TRUE;
  322. }
  323. ScepFree(SysRoot);
  324. }
  325. return bFindIt;
  326. }
  327. SCESTATUS
  328. ScepSaveAndOffAuditing(
  329. OUT PPOLICY_AUDIT_EVENTS_INFO *ppAuditEvent,
  330. IN BOOL bTurnOffAuditing,
  331. IN LSA_HANDLE PolicyHandle OPTIONAL
  332. )
  333. {
  334. LSA_HANDLE lsaHandle=NULL;
  335. NTSTATUS status;
  336. SCESTATUS rc;
  337. POLICY_AUDIT_EVENT_OPTIONS lSaveAudit;
  338. //
  339. // open Lsa policy for read/write
  340. //
  341. if ( PolicyHandle == NULL ) {
  342. ACCESS_MASK access=0;
  343. if ( bTurnOffAuditing ) {
  344. access = POLICY_SET_AUDIT_REQUIREMENTS | POLICY_AUDIT_LOG_ADMIN;
  345. }
  346. status = ScepOpenLsaPolicy(
  347. POLICY_VIEW_AUDIT_INFORMATION | access,
  348. &lsaHandle,
  349. TRUE
  350. );
  351. if (status != ERROR_SUCCESS) {
  352. lsaHandle = NULL;
  353. rc = RtlNtStatusToDosError( status );
  354. ScepLogOutput3( 1, rc, SCEDLL_LSA_POLICY);
  355. return(ScepDosErrorToSceStatus(rc));
  356. }
  357. } else {
  358. lsaHandle = PolicyHandle;
  359. }
  360. //
  361. // Query audit event information
  362. //
  363. status = LsaQueryInformationPolicy( lsaHandle,
  364. PolicyAuditEventsInformation,
  365. (PVOID *)ppAuditEvent
  366. );
  367. rc = RtlNtStatusToDosError( status );
  368. if ( NT_SUCCESS( status ) && bTurnOffAuditing && (*ppAuditEvent)->AuditingMode ) {
  369. //
  370. // turn off object access auditing
  371. //
  372. if ( AuditCategoryObjectAccess < (*ppAuditEvent)->MaximumAuditEventCount ) {
  373. lSaveAudit = (*ppAuditEvent)->EventAuditingOptions[AuditCategoryObjectAccess];
  374. (*ppAuditEvent)->EventAuditingOptions[AuditCategoryObjectAccess] = POLICY_AUDIT_EVENT_NONE;
  375. status = LsaSetInformationPolicy( lsaHandle,
  376. PolicyAuditEventsInformation,
  377. (PVOID)(*ppAuditEvent)
  378. );
  379. //
  380. // restore the object access auditing mode
  381. //
  382. (*ppAuditEvent)->EventAuditingOptions[AuditCategoryObjectAccess] = lSaveAudit;
  383. }
  384. rc = RtlNtStatusToDosError( status );
  385. if ( rc == NO_ERROR )
  386. ScepLogOutput3( 2, 0, SCEDLL_EVENT_IS_OFF);
  387. else
  388. ScepLogOutput3( 1, rc, SCEDLL_SCP_ERROR_EVENT_AUDITING);
  389. } else if ( rc != NO_ERROR)
  390. ScepLogOutput3( 1, rc, SCEDLL_ERROR_QUERY_EVENT_AUDITING);
  391. //
  392. // free LSA handle if it's opened in this function
  393. //
  394. if ( lsaHandle && (PolicyHandle == NULL) )
  395. LsaClose( lsaHandle );
  396. return(ScepDosErrorToSceStatus(rc));
  397. }
  398. NTSTATUS
  399. ScepGetAccountExplicitRight(
  400. IN LSA_HANDLE PolicyHandle,
  401. IN PSID AccountSid,
  402. OUT PDWORD PrivilegeLowRights,
  403. OUT PDWORD PrivilegeHighRights
  404. )
  405. /* ++
  406. Routine Description:
  407. This routine queries the explicitly assigned privilege/rights to a account
  408. (referenced by AccountSid) and stores in a DWORD type variable PrivilegeRights,
  409. in which each bit represents a privilege/right.
  410. Arguments:
  411. PolicyHandle - Lsa Policy Domain handle
  412. AccountSid - The SID for the account
  413. PrivilegeRights - Privilege/Rights of this account
  414. Return value:
  415. NTSTATUS
  416. -- */
  417. {
  418. NTSTATUS NtStatus;
  419. DWORD CurrentPrivLowRights=0, CurrentPrivHighRights=0;
  420. LONG index;
  421. PUNICODE_STRING UserRightEnum=NULL;
  422. ULONG i, cnt=0;
  423. LUID LuidValue;
  424. //
  425. // Enumerate user privilege/rights
  426. //
  427. NtStatus = LsaEnumerateAccountRights(
  428. PolicyHandle,
  429. AccountSid,
  430. &UserRightEnum,
  431. &cnt
  432. );
  433. if ( NtStatus == STATUS_NO_SUCH_PRIVILEGE ||
  434. NtStatus == STATUS_OBJECT_NAME_NOT_FOUND ) {
  435. NtStatus = ERROR_SUCCESS;
  436. goto Done;
  437. }
  438. if ( !NT_SUCCESS( NtStatus) ) {
  439. ScepLogOutput3(1,
  440. RtlNtStatusToDosError(NtStatus),
  441. SCEDLL_SAP_ERROR_ENUMERATE,
  442. L"LsaEnumerateAccountRights");
  443. goto Done;
  444. }
  445. if (UserRightEnum != NULL)
  446. for ( i=0; i < cnt; i++) {
  447. if ( UserRightEnum[i].Length == 0 )
  448. continue;
  449. NtStatus = LsaLookupPrivilegeValue(
  450. PolicyHandle,
  451. &UserRightEnum[i],
  452. &LuidValue
  453. );
  454. if ( NtStatus == STATUS_NO_SUCH_PRIVILEGE ) {
  455. index = ScepLookupPrivByName( UserRightEnum[i].Buffer );
  456. NtStatus = ERROR_SUCCESS;
  457. } else if ( NT_SUCCESS(NtStatus) ) {
  458. index = ScepLookupPrivByValue( LuidValue.LowPart );
  459. } else
  460. index = -1;
  461. if ( index == -1 ) {
  462. //
  463. // not found
  464. //
  465. NtStatus = STATUS_NOT_FOUND;
  466. ScepLogOutput3(1,
  467. RtlNtStatusToDosError(NtStatus),
  468. SCEDLL_USERRIGHT_NOT_DEFINED);
  469. goto Done;
  470. } else {
  471. if ( index < 32 ) {
  472. CurrentPrivLowRights |= (1 << index);
  473. } else {
  474. CurrentPrivHighRights |= (1 << (index-32) );
  475. }
  476. }
  477. }
  478. Done:
  479. *PrivilegeLowRights = CurrentPrivLowRights;
  480. *PrivilegeHighRights = CurrentPrivHighRights;
  481. if (UserRightEnum != NULL)
  482. LsaFreeMemory(UserRightEnum);
  483. return (NtStatus);
  484. }
  485. NTSTATUS
  486. ScepGetMemberListSids(
  487. IN PSID DomainSid,
  488. IN LSA_HANDLE PolicyHandle,
  489. IN PSCE_NAME_LIST pMembers,
  490. OUT PUNICODE_STRING *MemberNames,
  491. OUT PSID** Sids,
  492. OUT PULONG MemberCount
  493. )
  494. /*
  495. Routine Description:
  496. Lookup each account in the name list pMembers and return the lookup information
  497. in the output buffer - MemberNames, Sids, MemberCount.
  498. if an account can't be resolved, the corresponding SID will be empty.
  499. */
  500. {
  501. NTSTATUS NtStatus=STATUS_SUCCESS;
  502. PSCE_NAME_LIST pUser;
  503. PLSA_REFERENCED_DOMAIN_LIST ReferencedDomains=NULL;
  504. PLSA_TRANSLATED_SID2 MemberSids=NULL;
  505. DWORD i;
  506. PSID DomainSidToUse=NULL;
  507. ULONG Cnt=0;
  508. //
  509. // build a UNICODE_STRING for the member list to look up
  510. //
  511. for (pUser=pMembers;
  512. pUser != NULL;
  513. pUser = pUser->Next) {
  514. if ( pUser->Name == NULL ) {
  515. continue;
  516. }
  517. Cnt++;
  518. }
  519. if ( Cnt > 0 ) {
  520. *MemberNames = (PUNICODE_STRING)RtlAllocateHeap(
  521. RtlProcessHeap(),
  522. 0,
  523. Cnt * sizeof (UNICODE_STRING)
  524. );
  525. if ( *MemberNames == NULL )
  526. return(STATUS_NO_MEMORY);
  527. *Sids = (PSID *)ScepAlloc( LMEM_ZEROINIT, Cnt*sizeof(PSID));
  528. if ( *Sids == NULL ) {
  529. NtStatus = STATUS_NO_MEMORY;
  530. goto Done;
  531. }
  532. //
  533. // Lookup each UNICODE_STRING
  534. //
  535. for (pUser=pMembers, Cnt=0;
  536. pUser != NULL;
  537. pUser = pUser->Next) {
  538. if ( pUser->Name == NULL ) {
  539. continue;
  540. }
  541. RtlInitUnicodeString(&((*MemberNames)[Cnt]), pUser->Name);
  542. NtStatus = ScepLsaLookupNames2(
  543. PolicyHandle,
  544. LSA_LOOKUP_ISOLATED_AS_LOCAL,
  545. pUser->Name,
  546. &ReferencedDomains,
  547. &MemberSids
  548. );
  549. if ( !NT_SUCCESS(NtStatus) ) {
  550. ScepLogOutput3(1, RtlNtStatusToDosError(NtStatus),
  551. SCEDLL_ERROR_LOOKUP);
  552. goto Done;
  553. }
  554. DWORD SidLength=0;
  555. //
  556. // translate the LSA_TRANSLATED_SID into PSID
  557. //
  558. if ( MemberSids &&
  559. MemberSids[0].Use != SidTypeInvalid &&
  560. MemberSids[0].Use != SidTypeUnknown &&
  561. MemberSids[0].Sid != NULL ) {
  562. SidLength = RtlLengthSid(MemberSids[0].Sid);
  563. if ( ((*Sids)[Cnt] = (PSID) ScepAlloc( (UINT)0, SidLength)) == NULL ) {
  564. NtStatus = STATUS_NO_MEMORY;
  565. } else {
  566. //
  567. // copy the SID
  568. // if failed, memory will be freed at cleanup
  569. //
  570. NtStatus = RtlCopySid( SidLength, (*Sids)[Cnt], MemberSids[0].Sid );
  571. }
  572. if ( !NT_SUCCESS(NtStatus) ) {
  573. goto Done;
  574. }
  575. }
  576. if ( ReferencedDomains != NULL ){
  577. LsaFreeMemory(ReferencedDomains);
  578. ReferencedDomains = NULL;
  579. }
  580. if ( MemberSids != NULL ){
  581. LsaFreeMemory(MemberSids);
  582. MemberSids = NULL;
  583. }
  584. Cnt++;
  585. }
  586. }
  587. *MemberCount = Cnt;
  588. Done:
  589. if (!NT_SUCCESS(NtStatus) ) {
  590. if ( *Sids != NULL ) {
  591. for ( i=0; i<Cnt; i++ )
  592. if ( (*Sids)[i] != NULL )
  593. ScepFree( (*Sids)[i] );
  594. ScepFree( *Sids );
  595. *Sids = NULL;
  596. }
  597. if ( *MemberNames != NULL )
  598. RtlFreeHeap(RtlProcessHeap(), 0, *MemberNames);
  599. *MemberNames = NULL;
  600. }
  601. if ( ReferencedDomains != NULL )
  602. LsaFreeMemory(ReferencedDomains);
  603. if ( MemberSids != NULL )
  604. LsaFreeMemory(MemberSids);
  605. return(NtStatus);
  606. }
  607. DWORD
  608. ScepOpenFileObject(
  609. IN LPWSTR pObjectName,
  610. IN ACCESS_MASK AccessMask,
  611. OUT PHANDLE Handle
  612. )
  613. /*++
  614. Routine Description:
  615. opens the specified file (or directory) object
  616. Arguments:
  617. pObjectName - the name of the file object
  618. AccessMask - Desired Access
  619. Handle - the just opened handle to the object
  620. Return value:
  621. Win32 errro code
  622. */
  623. {
  624. NTSTATUS NtStatus;
  625. DWORD Status = ERROR_SUCCESS;
  626. OBJECT_ATTRIBUTES Attributes;
  627. IO_STATUS_BLOCK Isb;
  628. UNICODE_STRING FileName;
  629. PVOID FreeBuffer;
  630. //
  631. // cut and paste code from windows\base\advapi\security.c SetFileSecurityW
  632. //
  633. if (RtlDosPathNameToNtPathName_U(
  634. pObjectName,
  635. &FileName,
  636. NULL,
  637. NULL
  638. ))
  639. {
  640. FreeBuffer = FileName.Buffer;
  641. InitializeObjectAttributes(
  642. &Attributes,
  643. &FileName,
  644. OBJ_CASE_INSENSITIVE,
  645. NULL,
  646. NULL
  647. );
  648. NtStatus = NtOpenFile( Handle,
  649. AccessMask,
  650. &Attributes,
  651. &Isb,
  652. FILE_SHARE_READ |
  653. FILE_SHARE_WRITE |
  654. FILE_SHARE_DELETE,
  655. FILE_OPEN_REPARSE_POINT); // bug 635098: set permissions on junction point,
  656. // not on target directory
  657. if (!NT_SUCCESS(NtStatus))
  658. {
  659. Status = RtlNtStatusToDosError(NtStatus);
  660. }
  661. RtlFreeHeap(RtlProcessHeap(), 0,FreeBuffer);
  662. } else
  663. {
  664. Status = ERROR_INVALID_NAME;
  665. }
  666. return(Status);
  667. }
  668. DWORD
  669. ScepOpenRegistryObject(
  670. IN SE_OBJECT_TYPE ObjectType,
  671. IN LPWSTR pObjectName,
  672. IN ACCESS_MASK AccessMask,
  673. OUT PHKEY Handle
  674. )
  675. /*++
  676. Routine Description:
  677. opens the specified registry key object
  678. Arguments:
  679. pObjectName - the name of the object
  680. AccessMask - Desired access
  681. Handle - the just opened handle to the object
  682. Return value:
  683. Win32 error code
  684. Note:
  685. The code is cut/pasted from windows\base\accctrl\src\registry.cxx and modified
  686. --*/
  687. {
  688. DWORD status=NO_ERROR;
  689. HKEY basekey;
  690. LPWSTR usename, basekeyname, keyname;
  691. if (pObjectName) {
  692. //
  693. // save a copy of the name since we must crack it.
  694. //
  695. if (NULL != (usename = (LPWSTR)ScepAlloc( LMEM_ZEROINIT,
  696. (wcslen(pObjectName) + 1) * sizeof(WCHAR)))) {
  697. wcscpy(usename,pObjectName);
  698. basekeyname = usename;
  699. keyname = wcschr(usename, L'\\');
  700. if (keyname != NULL) {
  701. *keyname = L'\0';
  702. keyname++;
  703. }
  704. if (0 == _wcsicmp(basekeyname, L"MACHINE")) {
  705. basekey = HKEY_LOCAL_MACHINE;
  706. } else if (0 == _wcsicmp(basekeyname, L"USERS")) {
  707. basekey = HKEY_USERS;
  708. } else if ( 0 == _wcsicmp(basekeyname, L"CLASSES_ROOT")) {
  709. basekey = HKEY_CLASSES_ROOT;
  710. } else {
  711. status = ERROR_INVALID_PARAMETER;
  712. }
  713. if (NO_ERROR == status) {
  714. if ( keyname == NULL ) {
  715. *Handle = basekey;
  716. } else {
  717. //
  718. // open the key
  719. //
  720. #ifdef _WIN64
  721. if (ObjectType == SE_REGISTRY_WOW64_32KEY) {
  722. AccessMask |= KEY_WOW64_32KEY;
  723. }
  724. #endif
  725. status = RegOpenKeyEx(
  726. basekey,
  727. keyname,
  728. 0 ,
  729. AccessMask,
  730. Handle
  731. );
  732. }
  733. }
  734. ScepFree(usename);
  735. } else {
  736. status = ERROR_NOT_ENOUGH_MEMORY;
  737. }
  738. } else {
  739. status = ERROR_INVALID_NAME;
  740. }
  741. return(status);
  742. }
  743. SCESTATUS
  744. ScepGetNameInLevel(
  745. IN PCWSTR ObjectFullName,
  746. IN DWORD Level,
  747. IN WCHAR Delim,
  748. OUT PWSTR Buffer,
  749. OUT PBOOL LastOne
  750. )
  751. /* ++
  752. Routine Description:
  753. This routine parses a full path name and returns the component for the
  754. level. For example, a object name "c:\winnt\system32" will return c: for
  755. level 1, winnt for level 2, and system32 for level 3. This routine is
  756. used when add a object to the security tree.
  757. Arguments:
  758. ObjectFullName - The full path name of the object
  759. Level - the level of component to return
  760. Delim - the deliminator to look for
  761. Buffer - The address of buffer for the component name
  762. LastOne - Flag to indicate if the component is the last one
  763. Return value:
  764. SCESTATUS
  765. -- */
  766. {
  767. PWSTR pTemp, pStart;
  768. DWORD i;
  769. if ( ObjectFullName == NULL )
  770. return(SCESTATUS_INVALID_PARAMETER);
  771. //
  772. // loop through the object name to find the level
  773. // if there is no such level, return INVALID_PARAMETER
  774. //
  775. pStart = (PWSTR)ObjectFullName;
  776. for ( i=0; i<Level; i++) {
  777. pTemp = wcschr(pStart, Delim);
  778. if ( pTemp == pStart ) {
  779. return(SCESTATUS_INVALID_PARAMETER);
  780. }
  781. if ( i == Level-1 ) {
  782. //
  783. // find the right level
  784. //
  785. if ( pTemp == NULL ) {
  786. wcscpy(Buffer, pStart);
  787. *LastOne = TRUE;
  788. } else {
  789. wcsncpy(Buffer, pStart, (size_t)(pTemp - pStart));
  790. if ( *(pTemp+1) == L'\0' )
  791. *LastOne = TRUE;
  792. else
  793. *LastOne = FALSE;
  794. }
  795. } else {
  796. if ( pTemp == NULL )
  797. return(SCESTATUS_INVALID_PARAMETER);
  798. else
  799. pStart = pTemp + 1;
  800. }
  801. }
  802. return(SCESTATUS_SUCCESS);
  803. }
  804. SCESTATUS
  805. ScepTranslateFileDirName(
  806. IN PWSTR oldFileName,
  807. OUT PWSTR *newFileName
  808. )
  809. /* ++
  810. Routine Description:
  811. This routine converts a generic file/directory name to a real used name
  812. for the current system. The following generic file/directory names are handled:
  813. %systemroot% - Windows NT root directory (e.g., c:\winnt)
  814. %systemDirectory% - Windows NT system32 directory (e.g., c:\winnt\system32)
  815. Arguments:
  816. oldFileName - the file name to convert, which includes "%" to represent
  817. some directory names
  818. newFileName - the real file name, in which the "%" name is replaced with
  819. the real directory name
  820. Return values:
  821. Win32 error code
  822. -- */
  823. {
  824. PWSTR pTemp=NULL, pStart, TmpBuf, szVar;
  825. DWORD rc=NO_ERROR;
  826. DWORD newFileSize, cSize;
  827. BOOL bContinue;
  828. //
  829. // match for %systemroot%
  830. //
  831. rc = ScepExpandEnvironmentVariable(oldFileName,
  832. L"%SYSTEMROOT%",
  833. SCE_FLAG_WINDOWS_DIR,
  834. newFileName);
  835. if ( rc != ERROR_FILE_NOT_FOUND ) {
  836. return rc;
  837. }
  838. //
  839. // match for %systemdirectory%
  840. //
  841. rc = ScepExpandEnvironmentVariable(oldFileName,
  842. L"%SYSTEMDIRECTORY%",
  843. SCE_FLAG_SYSTEM_DIR,
  844. newFileName);
  845. if ( rc != ERROR_FILE_NOT_FOUND ) {
  846. return rc;
  847. }
  848. //
  849. // match for systemdrive
  850. //
  851. rc = ScepExpandEnvironmentVariable(oldFileName,
  852. L"%SYSTEMDRIVE%",
  853. SCE_FLAG_WINDOWS_DIR,
  854. newFileName);
  855. if ( rc != ERROR_FILE_NOT_FOUND ) {
  856. return rc;
  857. }
  858. //
  859. // match for boot drive
  860. //
  861. rc = ScepExpandEnvironmentVariable(oldFileName,
  862. L"%BOOTDRIVE%",
  863. SCE_FLAG_BOOT_DRIVE,
  864. newFileName);
  865. if ( rc != ERROR_FILE_NOT_FOUND ) {
  866. return rc;
  867. }
  868. rc = ERROR_SUCCESS;
  869. //
  870. // search for environment variable in the current process
  871. //
  872. pStart = wcschr(oldFileName, L'%');
  873. if ( pStart ) {
  874. pTemp = wcschr(pStart+1, L'%');
  875. if ( pTemp ) {
  876. bContinue = TRUE;
  877. //
  878. // find a environment variable to translate
  879. //
  880. TmpBuf = (PWSTR)ScepAlloc(0, ((UINT)(pTemp-pStart))*sizeof(WCHAR));
  881. if ( TmpBuf ) {
  882. wcsncpy(TmpBuf, pStart+1, (size_t)(pTemp-pStart-1));
  883. TmpBuf[pTemp-pStart-1] = L'\0';
  884. //
  885. // try search in the client environment block
  886. //
  887. szVar = ScepSearchClientEnv(TmpBuf, (DWORD)(pTemp-pStart-1));
  888. if ( szVar ) {
  889. // ScepLogOutput2(3,0,L"\tFind client env %s=%s", TmpBuf, szVar);
  890. //
  891. // find it in the client's environment block, use it
  892. // get info in szVar
  893. //
  894. bContinue = FALSE;
  895. newFileSize = ((DWORD)(pStart-oldFileName))+wcslen(szVar)+wcslen(pTemp+1)+1;
  896. *newFileName = (PWSTR)ScepAlloc(0, newFileSize*sizeof(TCHAR));
  897. if (*newFileName ) {
  898. if ( pStart != oldFileName ) {
  899. wcsncpy(*newFileName, oldFileName, (size_t)(pStart-oldFileName));
  900. }
  901. swprintf((PWSTR)(*newFileName+(pStart-oldFileName)), L"%s%s", szVar, pTemp+1);
  902. } else {
  903. rc = ERROR_NOT_ENOUGH_MEMORY;
  904. }
  905. //
  906. // DO NOT free szVar because it's a ref pointer to the env block
  907. //
  908. } else {
  909. cSize = GetEnvironmentVariable( TmpBuf,
  910. NULL,
  911. 0 );
  912. if ( cSize > 0 ) {
  913. //
  914. // does not find it in the client environment block,
  915. // find it in the current server process environment, use it
  916. //
  917. szVar = (PWSTR)ScepAlloc(0, (cSize+1)*sizeof(WCHAR));
  918. if ( szVar ) {
  919. cSize = GetEnvironmentVariable(TmpBuf,
  920. szVar,
  921. cSize);
  922. if ( cSize > 0 ) {
  923. //
  924. // get info in szVar
  925. //
  926. bContinue = FALSE;
  927. newFileSize = ((DWORD)(pStart-oldFileName))+cSize+wcslen(pTemp+1)+1;
  928. *newFileName = (PWSTR)ScepAlloc(0, newFileSize*sizeof(TCHAR));
  929. if (*newFileName ) {
  930. if ( pStart != oldFileName )
  931. wcsncpy(*newFileName, oldFileName, (size_t)(pStart-oldFileName));
  932. swprintf((PWSTR)(*newFileName+(pStart-oldFileName)), L"%s%s", szVar, pTemp+1);
  933. } else
  934. rc = ERROR_NOT_ENOUGH_MEMORY;
  935. }
  936. ScepFree(szVar);
  937. } else
  938. rc = ERROR_NOT_ENOUGH_MEMORY;
  939. }
  940. }
  941. ScepFree(TmpBuf);
  942. } else
  943. rc = ERROR_NOT_ENOUGH_MEMORY;
  944. if ( NO_ERROR != rc || !bContinue ) {
  945. //
  946. // if errored, or do not continue
  947. //
  948. return(rc);
  949. }
  950. //
  951. // not found in environment blob,
  952. // continue to search for DSDIT/DSLOG/SYSVOL in registry
  953. //
  954. if ( ProductType == NtProductLanManNt ) {
  955. //
  956. // search for DSDIT
  957. //
  958. rc = ScepExpandEnvironmentVariable(oldFileName,
  959. L"%DSDIT%",
  960. SCE_FLAG_DSDIT_DIR,
  961. newFileName);
  962. if ( rc != ERROR_FILE_NOT_FOUND ) {
  963. return rc;
  964. }
  965. //
  966. // search for DSLOG
  967. //
  968. rc = ScepExpandEnvironmentVariable(oldFileName,
  969. L"%DSLOG%",
  970. SCE_FLAG_DSLOG_DIR,
  971. newFileName);
  972. if ( rc != ERROR_FILE_NOT_FOUND ) {
  973. return rc;
  974. }
  975. //
  976. // search for SYSVOL
  977. //
  978. rc = ScepExpandEnvironmentVariable(oldFileName,
  979. L"%SYSVOL%",
  980. SCE_FLAG_SYSVOL_DIR,
  981. newFileName);
  982. if ( rc != ERROR_FILE_NOT_FOUND ) {
  983. return rc;
  984. }
  985. }
  986. //
  987. // search for PROFILES
  988. //
  989. rc = ScepExpandEnvironmentVariable(oldFileName,
  990. L"%PROFILES%",
  991. SCE_FLAG_PROFILES_DIR,
  992. newFileName);
  993. if ( rc != ERROR_FILE_NOT_FOUND ) {
  994. return rc;
  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, TRUE);
  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 = NULL, hNewToken = NULL;
  1554. DWORD Win32rc = NO_ERROR;
  1555. //
  1556. // get current client token
  1557. //
  1558. if (!OpenThreadToken( GetCurrentThread(),
  1559. TOKEN_IMPERSONATE | TOKEN_READ | TOKEN_DUPLICATE,
  1560. TRUE,
  1561. &hToken)) {
  1562. if(ERROR_NO_TOKEN == GetLastError()){
  1563. if(!OpenProcessToken( GetCurrentProcess(),
  1564. TOKEN_IMPERSONATE | TOKEN_READ | TOKEN_DUPLICATE,
  1565. &hToken )){
  1566. return ( GetLastError() );
  1567. }
  1568. } else {
  1569. return( GetLastError() );
  1570. }
  1571. }
  1572. //
  1573. // Duplicate it so it can be used for impersonation
  1574. //
  1575. if (!DuplicateTokenEx(hToken, TOKEN_IMPERSONATE | TOKEN_QUERY,
  1576. NULL, SecurityImpersonation, TokenImpersonation,
  1577. &hNewToken))
  1578. {
  1579. CloseHandle (hToken);
  1580. return ( GetLastError() );
  1581. }
  1582. CloseHandle (hToken);
  1583. PSECURITY_DESCRIPTOR pCurrentSD=NULL;
  1584. PRIVILEGE_SET PrivSet;
  1585. DWORD PrivSetLength = sizeof(PRIVILEGE_SET);
  1586. DWORD dwGrantedAccess;
  1587. BOOL bAccessStatus = TRUE;
  1588. if ( !bCreate ) {
  1589. Win32rc = ScepGetNamedSecurityInfo(
  1590. DatabaseName,
  1591. SE_FILE_OBJECT,
  1592. OWNER_SECURITY_INFORMATION |
  1593. GROUP_SECURITY_INFORMATION |
  1594. DACL_SECURITY_INFORMATION,
  1595. &pCurrentSD
  1596. );
  1597. if ( Win32rc == ERROR_PATH_NOT_FOUND ||
  1598. Win32rc == ERROR_FILE_NOT_FOUND ) {
  1599. pCurrentSD = NULL;
  1600. Win32rc = NO_ERROR;
  1601. }
  1602. }
  1603. if ( Win32rc == NO_ERROR ) {
  1604. if ( pCurrentSD == NULL ) {
  1605. //
  1606. // either this database is to be overwritten (re-created)
  1607. // or it doesn't exist. In both cases, hand the call over to Jet
  1608. // which will do the right access checking.
  1609. //
  1610. } else {
  1611. if ( !AccessCheck (
  1612. pCurrentSD,
  1613. hNewToken,
  1614. DesiredAccess,
  1615. &FileGenericMapping,
  1616. &PrivSet,
  1617. &PrivSetLength,
  1618. &dwGrantedAccess,
  1619. &bAccessStatus
  1620. ) ) {
  1621. Win32rc = GetLastError();
  1622. } else {
  1623. if ( bAccessStatus &&
  1624. (dwGrantedAccess == DesiredAccess ) ) {
  1625. Win32rc = NO_ERROR;
  1626. } else {
  1627. Win32rc = ERROR_ACCESS_DENIED;
  1628. }
  1629. }
  1630. }
  1631. }
  1632. if ( pCurrentSD ) {
  1633. LocalFree(pCurrentSD);
  1634. }
  1635. CloseHandle (hNewToken);
  1636. return( Win32rc );
  1637. }
  1638. DWORD
  1639. ScepAddSidToNameList(
  1640. OUT PSCE_NAME_LIST *pNameList,
  1641. IN PSID pSid,
  1642. IN BOOL bReuseBuffer,
  1643. OUT BOOL *pbBufferUsed
  1644. )
  1645. /* ++
  1646. Routine Description:
  1647. This routine adds a SID to the name list. The new added
  1648. node is always placed as the head of the list for performance reason.
  1649. Arguments:
  1650. pNameList - The address of the name list to add to.
  1651. pSid - the Sid to add
  1652. Return value:
  1653. Win32 error code
  1654. -- */
  1655. {
  1656. PSCE_NAME_LIST pList=NULL;
  1657. ULONG Length;
  1658. //
  1659. // check arguments
  1660. //
  1661. if ( pNameList == NULL ||
  1662. pbBufferUsed == NULL )
  1663. return(ERROR_INVALID_PARAMETER);
  1664. *pbBufferUsed = FALSE;
  1665. if ( pSid == NULL )
  1666. return(NO_ERROR);
  1667. if ( !RtlValidSid(pSid) ) {
  1668. return(ERROR_INVALID_PARAMETER);
  1669. }
  1670. //
  1671. // check if the SID is already in the name list
  1672. //
  1673. for ( pList=*pNameList; pList!=NULL; pList=pList->Next ) {
  1674. if ( pList->Name == NULL ) {
  1675. continue;
  1676. }
  1677. if ( ScepValidSid( (PSID)(pList->Name) ) &&
  1678. RtlEqualSid( (PSID)(pList->Name), pSid ) ) {
  1679. break;
  1680. }
  1681. }
  1682. if ( pList ) {
  1683. //
  1684. // the SID is already in the list
  1685. //
  1686. return(NO_ERROR);
  1687. }
  1688. //
  1689. // allocate a new node
  1690. //
  1691. pList = (PSCE_NAME_LIST)ScepAlloc( (UINT)0, sizeof(SCE_NAME_LIST));
  1692. if ( pList == NULL )
  1693. return(ERROR_NOT_ENOUGH_MEMORY);
  1694. if ( bReuseBuffer ) {
  1695. pList->Name = (PWSTR)pSid;
  1696. *pbBufferUsed = TRUE;
  1697. } else {
  1698. Length = RtlLengthSid ( pSid );
  1699. pList->Name = (PWSTR)ScepAlloc( LMEM_ZEROINIT, Length);
  1700. if ( pList->Name == NULL ) {
  1701. ScepFree(pList);
  1702. return(ERROR_NOT_ENOUGH_MEMORY);
  1703. }
  1704. //
  1705. // add the node to the front of the list and link its next to the old list
  1706. //
  1707. RtlCopySid( Length, (PSID)(pList->Name), pSid );
  1708. }
  1709. pList->Next = *pNameList;
  1710. *pNameList = pList;
  1711. return(NO_ERROR);
  1712. }
  1713. BOOL
  1714. ScepValidSid(
  1715. PSID Sid
  1716. )
  1717. {
  1718. if ( RtlValidSid(Sid) ) {
  1719. PISID Isid = (PISID) Sid;
  1720. if ( Isid->Revision == SID_REVISION ) {
  1721. return(TRUE);
  1722. } else {
  1723. return(FALSE);
  1724. }
  1725. }
  1726. return(FALSE);
  1727. }
  1728. BOOL
  1729. ScepBinarySearch(
  1730. IN PWSTR *aPszPtrs,
  1731. IN DWORD dwSize_aPszPtrs,
  1732. IN PWSTR pszNameToFind
  1733. )
  1734. /* ++
  1735. Routine Description:
  1736. This routine determines if a string is found in a sorted array of strings.
  1737. The complexity of this search is logarithmic (log(n)) in the size of the
  1738. input array.
  1739. Arguments:
  1740. aPszPtrs - the array of string pointers to search in
  1741. dwSize_aPszPtrs - the size of the above array
  1742. pszNameToFind - the string to search for
  1743. Return value:
  1744. TRUE if string is found
  1745. FALSE if string is not found
  1746. -- */
  1747. {
  1748. if ( aPszPtrs == NULL || dwSize_aPszPtrs == 0 || pszNameToFind == NULL ) {
  1749. return FALSE;
  1750. }
  1751. int iLow = 0;
  1752. int iHigh = dwSize_aPszPtrs - 1;
  1753. int iMid;
  1754. int iCmp;
  1755. while (iLow <= iHigh ) {
  1756. iMid = (iLow + iHigh ) / 2;
  1757. iCmp = _wcsicmp( aPszPtrs[iMid], pszNameToFind );
  1758. if ( iCmp == 0 )
  1759. return TRUE;
  1760. else if ( iCmp < 0 )
  1761. iLow = iMid + 1;
  1762. else
  1763. iHigh = iMid - 1;
  1764. }
  1765. return FALSE;
  1766. }
  1767. /* ++
  1768. Routine Description:
  1769. This routine adds a relative SID to the SID list in the format "#-RSID", eg "#-512"
  1770. for Domain Admins. Upon membership restore the groups stores as relative SIDs will be
  1771. from the tattoo table, the full SID will be restored based on current domain.
  1772. Arguments:
  1773. aPszPtrs - the array of string pointers to search in
  1774. dwSize_aPszPtrs - the size of the above array
  1775. pszNameToFind - the string to search for
  1776. Return value:
  1777. TRUE if string is found
  1778. FALSE if string is not found
  1779. -- */
  1780. DWORD
  1781. ScepAddRelativeSidToNameList(
  1782. IN OUT PSCE_NAME_LIST *pNameList,
  1783. IN PSID pSid)
  1784. {
  1785. DWORD rc;
  1786. PWSTR pwszSid = NULL;
  1787. WCHAR *pchRelativeSid;
  1788. rc = ScepConvertSidToPrefixStringSid(pSid, &pwszSid);
  1789. if(ERROR_SUCCESS == rc)
  1790. {
  1791. //
  1792. // find the relative SID suffix
  1793. //
  1794. pchRelativeSid = wcsrchr(pwszSid, STRING_SID_SUBAUTH_SEPARATOR);
  1795. if(!pchRelativeSid || L'\0'==*(pchRelativeSid+1))
  1796. {
  1797. rc = SCESTATUS_INVALID_DATA;
  1798. }
  1799. else
  1800. {
  1801. //
  1802. // Add the relative SID to list in format "#-RSID"
  1803. //
  1804. rc = ScepAddTwoNamesToNameList(
  1805. pNameList,
  1806. FALSE,
  1807. RELATIVE_SID_PREFIX_SZ,
  1808. 1,
  1809. pchRelativeSid,
  1810. wcslen(pchRelativeSid));
  1811. }
  1812. }
  1813. if(pwszSid)
  1814. {
  1815. ScepFree(pwszSid);
  1816. }
  1817. return rc;
  1818. }