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.

1606 lines
40 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. misc.cpp
  5. Abstract:
  6. SCE Engine miscellaneous APIs
  7. Author:
  8. Jin Huang (jinhuang) 23-Jun-1997 created
  9. --*/
  10. #include "headers.h"
  11. #include "serverp.h"
  12. #include <ntregapi.h>
  13. #include <userenv.h>
  14. #include <ntlsa.h>
  15. #include <io.h>
  16. #pragma hdrstop
  17. extern "C" {
  18. #include "dumpnt.h"
  19. }
  20. //#define SCE_DBG 1
  21. NTSTATUS
  22. ScepGetLsaDomainInfo(
  23. PPOLICY_ACCOUNT_DOMAIN_INFO *PolicyAccountDomainInfo,
  24. PPOLICY_PRIMARY_DOMAIN_INFO *PolicyPrimaryDomainInfo
  25. );
  26. DWORD
  27. ScepGetEnvVarsFromProfile(
  28. IN PWSTR UserProfileName,
  29. IN PCWSTR VarName1,
  30. IN PCWSTR VarName2 OPTIONAL,
  31. OUT PWSTR *StrValue
  32. );
  33. NTSTATUS
  34. ScepOpenSamDomain(
  35. IN ACCESS_MASK ServerAccess,
  36. IN ACCESS_MASK DomainAccess,
  37. OUT PSAM_HANDLE pServerHandle,
  38. OUT PSAM_HANDLE pDomainHandle,
  39. OUT PSID *DomainSid,
  40. OUT PSAM_HANDLE pBuiltinDomainHandle OPTIONAL,
  41. OUT PSID *BuiltinDomainSid OPTIONAL
  42. )
  43. /*
  44. Routine Description
  45. This routine opens the local SAM server for account domain and builtin
  46. domain. The domain handles and their SIDs are returned.
  47. */
  48. {
  49. NTSTATUS NtStatus;
  50. PPOLICY_ACCOUNT_DOMAIN_INFO PolicyAccountDomainInfo=NULL;
  51. PPOLICY_PRIMARY_DOMAIN_INFO PolicyPrimaryDomainInfo=NULL;
  52. OBJECT_ATTRIBUTES ObjectAttributes;
  53. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  54. if ( !pServerHandle || !pDomainHandle || !DomainSid ) {
  55. return(SCESTATUS_INVALID_PARAMETER);
  56. }
  57. //
  58. // initialize output buffers
  59. //
  60. *pServerHandle = NULL;
  61. *pDomainHandle = NULL;
  62. *DomainSid = NULL;
  63. if ( pBuiltinDomainHandle ) {
  64. *pBuiltinDomainHandle = NULL;
  65. }
  66. if ( BuiltinDomainSid ) {
  67. *BuiltinDomainSid = NULL;
  68. }
  69. //
  70. // Get information for the account domain
  71. //
  72. NtStatus = ScepGetLsaDomainInfo(
  73. &PolicyAccountDomainInfo,
  74. &PolicyPrimaryDomainInfo
  75. );
  76. if (!NT_SUCCESS(NtStatus)) {
  77. return( NtStatus );
  78. }
  79. //
  80. // Connect to the local SAM server
  81. //
  82. InitializeObjectAttributes( &ObjectAttributes, NULL, 0, 0, NULL );
  83. NtStatus = SamConnect(
  84. NULL, // ServerName (Local machine)
  85. pServerHandle,
  86. ServerAccess,
  87. &ObjectAttributes
  88. );
  89. if ( NT_SUCCESS(NtStatus) ) {
  90. //
  91. // copy the SID to output buffer
  92. //
  93. DWORD SidLen = RtlLengthSid(PolicyAccountDomainInfo->DomainSid);
  94. *DomainSid = (PSID)ScepAlloc(0, SidLen);
  95. if ( *DomainSid != NULL ) {
  96. NtStatus = RtlCopySid(SidLen, *DomainSid, PolicyAccountDomainInfo->DomainSid);
  97. } else {
  98. NtStatus = STATUS_NO_MEMORY;
  99. }
  100. }
  101. if ( NT_SUCCESS(NtStatus) ) {
  102. //
  103. // open the account domain
  104. //
  105. NtStatus = SamOpenDomain(
  106. *pServerHandle,
  107. DomainAccess,
  108. PolicyAccountDomainInfo->DomainSid,
  109. pDomainHandle
  110. );
  111. if ( NT_SUCCESS(NtStatus) && BuiltinDomainSid != NULL ) {
  112. //
  113. // build the builtin domain sid
  114. //
  115. NtStatus = RtlAllocateAndInitializeSid(
  116. &NtAuthority,
  117. 1,
  118. SECURITY_BUILTIN_DOMAIN_RID,
  119. 0, 0, 0, 0, 0, 0, 0,
  120. BuiltinDomainSid
  121. );
  122. if ( NT_SUCCESS(NtStatus) && pBuiltinDomainHandle != NULL ) {
  123. //
  124. // open the builtin domain
  125. //
  126. NtStatus = SamOpenDomain(
  127. *pServerHandle,
  128. DomainAccess,
  129. *BuiltinDomainSid,
  130. pBuiltinDomainHandle
  131. );
  132. }
  133. }
  134. }
  135. //
  136. // free memory and clean up
  137. //
  138. if ( PolicyAccountDomainInfo != NULL ) {
  139. LsaFreeMemory( PolicyAccountDomainInfo );
  140. }
  141. if ( PolicyPrimaryDomainInfo != NULL ) {
  142. LsaFreeMemory( PolicyPrimaryDomainInfo );
  143. }
  144. if ( !NT_SUCCESS(NtStatus)) {
  145. SamCloseHandle( *pDomainHandle );
  146. *pDomainHandle = NULL;
  147. if ( pBuiltinDomainHandle ) {
  148. SamCloseHandle( *pBuiltinDomainHandle );
  149. *pBuiltinDomainHandle = NULL;
  150. }
  151. SamCloseHandle( *pServerHandle );
  152. *pServerHandle = NULL;
  153. ScepFree(*DomainSid);
  154. *DomainSid = NULL;
  155. if ( BuiltinDomainSid ) {
  156. SamFreeMemory(*BuiltinDomainSid);
  157. *BuiltinDomainSid = NULL;
  158. }
  159. }
  160. return(NtStatus);
  161. }
  162. NTSTATUS
  163. ScepLookupNamesInDomain(
  164. IN SAM_HANDLE DomainHandle,
  165. IN PSCE_NAME_LIST NameList,
  166. OUT PUNICODE_STRING *Names,
  167. OUT PULONG *RIDs,
  168. OUT PSID_NAME_USE *Use,
  169. OUT PULONG CountOfName
  170. )
  171. /* ++
  172. Routine Description:
  173. This routine looks up one or more names in the SAM account domain and
  174. returns the relative IDs for each name in the list. The name list may
  175. be user list, group list, or alias list.
  176. Arguments:
  177. DomainHandle - SAM handle to the account domain
  178. NameList -- The list of names
  179. Names - Translated UNICODE_STRING names. The name list must be freed by
  180. RIDs -- List of relative IDs for each name
  181. Use -- List of type for each name
  182. CoutnOfName - The number of names in the list
  183. Return value:
  184. NTSTATUS
  185. -- */
  186. {
  187. PSCE_NAME_LIST pUser;
  188. ULONG cnt;
  189. NTSTATUS NtStatus=ERROR_SUCCESS;
  190. PUNICODE_STRING pUnicodeName=NULL;
  191. UNICODE_STRING uName;
  192. LPTSTR pTemp;
  193. //
  194. // Count how many names in the list
  195. //
  196. for (pUser=NameList, cnt=0;
  197. pUser != NULL;
  198. pUser = pUser->Next) {
  199. if ( pUser->Name == NULL ) {
  200. continue;
  201. }
  202. //
  203. // note, this may be bigger than supposed to
  204. //
  205. cnt++;
  206. }
  207. if ( cnt > 0 ) {
  208. //
  209. // Allocate memory for UNICODE_STRING names
  210. //
  211. pUnicodeName = (PUNICODE_STRING)RtlAllocateHeap(
  212. RtlProcessHeap(),
  213. 0,
  214. cnt * sizeof (UNICODE_STRING)
  215. );
  216. if ( pUnicodeName == NULL ) {
  217. NtStatus = STATUS_NO_MEMORY;
  218. cnt = 0;
  219. goto Done;
  220. }
  221. //
  222. // Initialize each UNICODE_STRING
  223. //
  224. for (pUser=NameList, cnt=0;
  225. pUser != NULL;
  226. pUser = pUser->Next) {
  227. if ( pUser->Name == NULL ) {
  228. continue;
  229. }
  230. pTemp = wcschr(pUser->Name, L'\\');
  231. if ( pTemp ) {
  232. uName.Buffer = pUser->Name;
  233. uName.Length = ((USHORT)(pTemp-pUser->Name))*sizeof(TCHAR);
  234. if ( !ScepIsDomainLocal(&uName) ) {
  235. ScepLogOutput3(1, 0, SCEDLL_NO_MAPPINGS, pUser->Name);
  236. continue;
  237. }
  238. pTemp++;
  239. } else {
  240. pTemp = pUser->Name;
  241. }
  242. RtlInitUnicodeString(&(pUnicodeName[cnt]), pTemp);
  243. cnt++;
  244. }
  245. // lookup
  246. NtStatus = SamLookupNamesInDomain(
  247. DomainHandle,
  248. cnt,
  249. pUnicodeName,
  250. RIDs,
  251. Use
  252. );
  253. if ( !NT_SUCCESS(NtStatus) ) {
  254. RtlFreeHeap(RtlProcessHeap(), 0, pUnicodeName);
  255. pUnicodeName = NULL;
  256. }
  257. }
  258. Done:
  259. *CountOfName = cnt;
  260. *Names = pUnicodeName;
  261. return(NtStatus);
  262. }
  263. NTSTATUS
  264. ScepGetLsaDomainInfo(
  265. PPOLICY_ACCOUNT_DOMAIN_INFO *PolicyAccountDomainInfo,
  266. PPOLICY_PRIMARY_DOMAIN_INFO *PolicyPrimaryDomainInfo
  267. )
  268. /*++
  269. Routine Description:
  270. This routine retrieves ACCOUNT domain information from the LSA
  271. policy database.
  272. Arguments:
  273. PolicyAccountDomainInfo - Receives a pointer to a
  274. POLICY_ACCOUNT_DOMAIN_INFO structure containing the account
  275. domain info.
  276. PolicyPrimaryDomainInfo - Receives a pointer to a
  277. POLICY_PRIMARY_DOMAIN_INFO structure containing the Primary
  278. domain info.
  279. Return Value:
  280. STATUS_SUCCESS - Succeeded.
  281. Other status values that may be returned from:
  282. LsaOpenPolicy()
  283. LsaQueryInformationPolicy()
  284. --*/
  285. {
  286. NTSTATUS Status, IgnoreStatus;
  287. LSA_HANDLE PolicyHandle;
  288. OBJECT_ATTRIBUTES PolicyObjectAttributes;
  289. //
  290. // Open the policy database
  291. //
  292. InitializeObjectAttributes( &PolicyObjectAttributes,
  293. NULL, // Name
  294. 0, // Attributes
  295. NULL, // Root
  296. NULL ); // Security Descriptor
  297. Status = LsaOpenPolicy( NULL,
  298. &PolicyObjectAttributes,
  299. POLICY_VIEW_LOCAL_INFORMATION,
  300. &PolicyHandle );
  301. if ( NT_SUCCESS(Status) ) {
  302. //
  303. // Query the account domain information
  304. //
  305. Status = LsaQueryInformationPolicy( PolicyHandle,
  306. PolicyAccountDomainInformation,
  307. (PVOID *)PolicyAccountDomainInfo );
  308. if ( NT_SUCCESS(Status) ) {
  309. //
  310. // Query the Primary domain information
  311. //
  312. Status = LsaQueryInformationPolicy( PolicyHandle,
  313. PolicyPrimaryDomainInformation,
  314. (PVOID *)PolicyPrimaryDomainInfo );
  315. }
  316. IgnoreStatus = LsaClose( PolicyHandle );
  317. ASSERT(NT_SUCCESS(IgnoreStatus));
  318. }
  319. return(Status);
  320. }
  321. VOID
  322. ScepConvertLogonHours(
  323. IN PSCE_LOGON_HOUR pLogonHours,
  324. OUT PUCHAR LogonHourBitMask
  325. )
  326. /* ++
  327. Routine Description:
  328. This routine converted the logon hour range in hours (for example, 7-20)
  329. to logon hour bit mask (for example, 0001 1111 1111 1111 1000 0000,
  330. for one day).
  331. Arguments:
  332. pLogonHours - The logon hour range (in hours)
  333. LogonHourBitMask - The converted logon hour bit mask. Each bit represents
  334. an hour. There are total 21 bytes (21*8 bits in this
  335. argument, which represents a week (7 * 24 = 21 * 8).
  336. Return value:
  337. None
  338. -- */
  339. { PSCE_LOGON_HOUR pTemp;
  340. CHAR BitMask[3]={0,0,0};
  341. ULONG j;
  342. for ( pTemp=pLogonHours; pTemp != NULL; pTemp=pTemp->Next ) {
  343. for (j=pTemp->Start; j<pTemp->End; j++)
  344. BitMask[j / 8] |= 1 << (j % 8);
  345. }
  346. for ( j=0; j<7; j++ )
  347. strncpy((CHAR *)&(LogonHourBitMask[j*3]), BitMask,3);
  348. }
  349. DWORD
  350. ScepConvertToSceLogonHour(
  351. IN PUCHAR LogonHourBitMask,
  352. OUT PSCE_LOGON_HOUR *pLogonHours
  353. )
  354. /* ++
  355. Routine Description:
  356. This routine converted the logon hour bit mask (for example,
  357. 0001 1111 1111 1111 1000 0000 for one day) to SCE_LOGON_HOUR type,
  358. which stores the logon hour range (start, end).
  359. Arguments:
  360. LogonHourBitMask - The logon hour bit mask to convert. Each bit represents
  361. an hour. There are total 21 bytes (21*8 bits in this
  362. argument, which represents a week (7 * 24 = 21 * 8).
  363. pLogonHours - The logon hour range (in hours)
  364. Return value:
  365. None
  366. -- */
  367. {
  368. BOOL findStart = TRUE;
  369. DWORD i, j, rc=NO_ERROR;
  370. DWORD start=0,
  371. end=0;
  372. LONG value;
  373. PSCE_LOGON_HOUR pLogon=NULL;
  374. if (pLogonHours == NULL )
  375. return(ERROR_INVALID_PARAMETER);
  376. for ( i=3; i<6; i++)
  377. for ( j=0; j<8; j++) {
  378. if ( findStart )
  379. value = 1;
  380. else
  381. value = 0;
  382. if ( (LogonHourBitMask[i] & (1 << j)) == value ) {
  383. if ( findStart ) {
  384. start = (i-3)*8 + j;
  385. findStart = FALSE;
  386. } else {
  387. end = (i-3)*8 + j;
  388. findStart = TRUE;
  389. }
  390. if ( findStart ) {
  391. //
  392. // find a pair
  393. //
  394. pLogon = (PSCE_LOGON_HOUR)ScepAlloc( (UINT)0, sizeof(SCE_LOGON_HOUR));
  395. if ( pLogon == NULL ) {
  396. rc = ERROR_NOT_ENOUGH_MEMORY;
  397. return(rc);
  398. }
  399. pLogon->Start = start;
  400. pLogon->End = end;
  401. pLogon->Next = *pLogonHours;
  402. *pLogonHours = pLogon;
  403. pLogon = NULL;
  404. }
  405. }
  406. }
  407. if ( findStart == FALSE ) {
  408. // find start but not end, which means end=24
  409. end = 24;
  410. pLogon = (PSCE_LOGON_HOUR)ScepAlloc( (UINT)0, sizeof(SCE_LOGON_HOUR));
  411. if ( pLogon == NULL ) {
  412. rc = ERROR_NOT_ENOUGH_MEMORY;
  413. return(rc);
  414. }
  415. pLogon->Start = start;
  416. pLogon->End = end;
  417. pLogon->Next = *pLogonHours;
  418. *pLogonHours = pLogon;
  419. pLogon = NULL;
  420. }
  421. return(rc);
  422. }
  423. NTSTATUS
  424. ScepGetGroupsForAccount(
  425. IN SAM_HANDLE DomainHandle,
  426. IN SAM_HANDLE BuiltinDomainHandle,
  427. IN SAM_HANDLE UserHandle,
  428. IN PSID AccountSid,
  429. OUT PSCE_NAME_LIST *GroupList
  430. )
  431. /* ++
  432. Routine Description:
  433. This routine queries the user's group membership.
  434. Arguments:
  435. DomainHandle - The SAM handle of the SAM account domain
  436. BuiltindomainHandle - The SAM builtin domain handle
  437. UserHandle - The SAM account handle for the user
  438. AccountSid - The SID for the user
  439. GroupList - The list of groups the user belongs to
  440. Return value:
  441. NTSTATUS
  442. -- */
  443. {
  444. NTSTATUS NtStatus=ERROR_SUCCESS;
  445. ULONG GroupCount=0,
  446. AliasCount=0;
  447. PULONG Aliases=NULL;
  448. PGROUP_MEMBERSHIP GroupAttributes=NULL;
  449. PULONG GroupIds=NULL;
  450. PUNICODE_STRING Names=NULL;
  451. PSID_NAME_USE Use=NULL;
  452. DWORD i;
  453. NtStatus = SamGetGroupsForUser(
  454. UserHandle,
  455. &GroupAttributes,
  456. &GroupCount
  457. );
  458. if ( GroupCount == 0 )
  459. NtStatus = ERROR_SUCCESS;
  460. if ( !NT_SUCCESS(NtStatus) )
  461. goto Done;
  462. //
  463. // See what local groups the account belongs to.
  464. // account domain
  465. //
  466. NtStatus = SamGetAliasMembership(
  467. DomainHandle,
  468. 1,
  469. &AccountSid,
  470. &AliasCount,
  471. &Aliases );
  472. if ( !NT_SUCCESS(NtStatus) )
  473. goto Done;
  474. if ( AliasCount != 0 || GroupCount != 0 ) {
  475. //
  476. // process each group's name in account domain
  477. //
  478. GroupIds = (PULONG)ScepAlloc((UINT)0,
  479. (GroupCount+AliasCount)*sizeof(ULONG));
  480. if ( GroupIds == NULL ) {
  481. NtStatus = STATUS_NO_MEMORY;
  482. goto Done;
  483. }
  484. for ( i=0; i<GroupCount; i++)
  485. GroupIds[i] = GroupAttributes[i].RelativeId;
  486. for ( i=0; i<AliasCount; i++)
  487. GroupIds[i+GroupCount] = Aliases[i];
  488. }
  489. SamFreeMemory(GroupAttributes);
  490. GroupAttributes = NULL;
  491. SamFreeMemory(Aliases);
  492. Aliases = NULL;
  493. if ( AliasCount != 0 || GroupCount != 0 ) {
  494. // lookup names
  495. NtStatus = SamLookupIdsInDomain(
  496. DomainHandle,
  497. GroupCount+AliasCount,
  498. GroupIds,
  499. &Names,
  500. &Use
  501. );
  502. if ( !NT_SUCCESS(NtStatus) )
  503. goto Done;
  504. }
  505. for ( i=0; i<GroupCount+AliasCount; i++) {
  506. if ( GroupIds[i] == DOMAIN_GROUP_RID_USERS )
  507. continue;
  508. switch (Use[i]) {
  509. case SidTypeGroup:
  510. case SidTypeAlias:
  511. case SidTypeWellKnownGroup:
  512. if ( ScepAddToNameList(GroupList, Names[i].Buffer, Names[i].Length/2) != NO_ERROR) {
  513. NtStatus = STATUS_NO_MEMORY;
  514. goto Done;
  515. }
  516. break;
  517. default:
  518. break;
  519. }
  520. }
  521. if ( GroupIds ) {
  522. ScepFree(GroupIds);
  523. GroupIds = NULL;
  524. }
  525. if ( Names ) {
  526. SamFreeMemory(Names);
  527. Names = NULL;
  528. }
  529. if ( Use ) {
  530. SamFreeMemory(Use);
  531. Use = NULL;
  532. }
  533. //
  534. // check the builtin domain for alias membership
  535. //
  536. AliasCount=0;
  537. NtStatus = SamGetAliasMembership(
  538. BuiltinDomainHandle,
  539. 1,
  540. &AccountSid,
  541. &AliasCount,
  542. &Aliases );
  543. if ( !NT_SUCCESS(NtStatus) )
  544. goto Done;
  545. if ( AliasCount > 0 ) {
  546. NtStatus = SamLookupIdsInDomain(
  547. BuiltinDomainHandle,
  548. AliasCount,
  549. Aliases,
  550. &Names,
  551. &Use
  552. );
  553. if ( !NT_SUCCESS(NtStatus) )
  554. goto Done;
  555. }
  556. for ( i=0; i<AliasCount; i++) {
  557. if ( Aliases[i] == DOMAIN_GROUP_RID_USERS )
  558. continue;
  559. switch (Use[i]) {
  560. case SidTypeGroup:
  561. case SidTypeAlias:
  562. case SidTypeWellKnownGroup:
  563. if ( ScepAddToNameList(GroupList, Names[i].Buffer, Names[i].Length/2) != NO_ERROR) {
  564. NtStatus = STATUS_NO_MEMORY;
  565. goto Done;
  566. }
  567. break;
  568. default:
  569. break;
  570. }
  571. }
  572. Done:
  573. if ( GroupAttributes != NULL )
  574. SamFreeMemory(GroupAttributes);
  575. if ( Aliases != NULL )
  576. SamFreeMemory(Aliases);
  577. if ( GroupIds != NULL )
  578. ScepFree(GroupIds);
  579. if ( Names != NULL )
  580. SamFreeMemory(Names);
  581. if ( Use != NULL )
  582. SamFreeMemory(Use);
  583. return(NtStatus);
  584. }
  585. ACCESS_MASK
  586. ScepGetDesiredAccess(
  587. IN SECURITY_OPEN_TYPE OpenType,
  588. IN SECURITY_INFORMATION SecurityInfo
  589. )
  590. /*++
  591. Routine Description:
  592. Gets the access required to open object to be able to set or get the
  593. specified security info.
  594. Arguments:
  595. OpenType - Flag indicating if the object is to be opened to read or
  596. write the DACL
  597. SecurityInfo - The Security information to read/write.
  598. Return value:
  599. Access mask
  600. -- */
  601. {
  602. ACCESS_MASK DesiredAccess = 0;
  603. if ( (SecurityInfo & OWNER_SECURITY_INFORMATION) ||
  604. (SecurityInfo & GROUP_SECURITY_INFORMATION) )
  605. {
  606. switch (OpenType)
  607. {
  608. case READ_ACCESS_RIGHTS:
  609. DesiredAccess |= READ_CONTROL;
  610. break;
  611. case WRITE_ACCESS_RIGHTS:
  612. DesiredAccess |= WRITE_OWNER;
  613. break;
  614. case MODIFY_ACCESS_RIGHTS:
  615. DesiredAccess |= READ_CONTROL | WRITE_OWNER;
  616. break;
  617. }
  618. }
  619. if (SecurityInfo & DACL_SECURITY_INFORMATION)
  620. {
  621. switch (OpenType)
  622. {
  623. case READ_ACCESS_RIGHTS:
  624. DesiredAccess |= READ_CONTROL;
  625. break;
  626. case WRITE_ACCESS_RIGHTS:
  627. DesiredAccess |= WRITE_DAC;
  628. break;
  629. case MODIFY_ACCESS_RIGHTS:
  630. DesiredAccess |= READ_CONTROL | WRITE_DAC;
  631. break;
  632. }
  633. }
  634. if (SecurityInfo & SACL_SECURITY_INFORMATION)
  635. {
  636. DesiredAccess |= ACCESS_SYSTEM_SECURITY;
  637. }
  638. return (DesiredAccess);
  639. }
  640. SCESTATUS
  641. ScepGetProfileOneArea(
  642. IN PSCECONTEXT hProfile,
  643. IN SCETYPE ProfileType,
  644. IN AREA_INFORMATION Area,
  645. IN DWORD dwAccountFormat,
  646. OUT PSCE_PROFILE_INFO *ppInfoBuffer
  647. )
  648. /* ++
  649. Routine Description:
  650. A wrapper routine for GetDatabaseInfo except it get information
  651. for one area at a call. This routine also logs the errors occur inside
  652. GetSecrityProfileInfo
  653. Arguments:
  654. hProfile - Handle to a profile
  655. ProfileType - The type of the profile
  656. Area - The security area to read info from
  657. ppInfoBuffer - output buffer for the info
  658. Return value:
  659. SCESTATUS returned from GetDatabaseInfo
  660. -- */
  661. {
  662. SCESTATUS rc;
  663. PSCE_ERROR_LOG_INFO pErrlog=NULL;
  664. rc = ScepGetDatabaseInfo(
  665. hProfile,
  666. ProfileType,
  667. Area,
  668. dwAccountFormat,
  669. ppInfoBuffer,
  670. &pErrlog
  671. );
  672. ScepLogWriteError( pErrlog, 1 );
  673. ScepFreeErrorLog( pErrlog );
  674. return(rc);
  675. }
  676. SCESTATUS
  677. ScepGetOneSection(
  678. IN PSCECONTEXT hProfile,
  679. IN AREA_INFORMATION Area,
  680. IN PWSTR Name,
  681. IN SCETYPE ProfileType,
  682. OUT PVOID *ppInfo
  683. )
  684. /* ++
  685. Routine Description:
  686. This routine reads information for one or more Area and logs errors to
  687. the log file. This routine should be only used by the SCP engine and
  688. the SAP engine.
  689. Arguments:
  690. hProfile - Handle to a profile
  691. ProfileType - The type of the profile
  692. Area - The security area to read info from
  693. Subarea - The subarea to read info from
  694. ppInfo - output buffer for the info
  695. Return value:
  696. SCESTATUS
  697. -- */
  698. {
  699. SCESTATUS rc;
  700. PSCE_ERROR_LOG_INFO pErrlog=NULL;
  701. if ( Name == NULL )
  702. return(SCESTATUS_INVALID_PARAMETER);
  703. if ( Area == AREA_REGISTRY_SECURITY ||
  704. Area == AREA_FILE_SECURITY ||
  705. Area == AREA_DS_OBJECTS ) {
  706. rc = ScepGetObjectChildren(
  707. hProfile,
  708. ProfileType,
  709. Area,
  710. Name,
  711. SCE_ALL_CHILDREN,
  712. ppInfo,
  713. &pErrlog
  714. );
  715. } else {
  716. rc = ScepGetUserSection(
  717. hProfile,
  718. ProfileType,
  719. Name,
  720. ppInfo,
  721. &pErrlog
  722. );
  723. }
  724. ScepLogWriteError( pErrlog, 1 );
  725. ScepFreeErrorLog( pErrlog );
  726. return(rc);
  727. }
  728. NTSTATUS
  729. ScepGetUserAccessAddress(
  730. IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
  731. IN PSID AccountSid,
  732. OUT PACCESS_MASK *pUserAccess,
  733. OUT PACCESS_MASK *pEveryone
  734. )
  735. {
  736. NTSTATUS NtStatus;
  737. PACL pAcl;
  738. BOOLEAN aclPresent, tFlag;
  739. DWORD i;
  740. PVOID pAce;
  741. PSID pSid;
  742. ACCESS_MASK access;
  743. SID_IDENTIFIER_AUTHORITY WorldAuth = SECURITY_WORLD_SID_AUTHORITY;
  744. PSID EveryoneSid=NULL;
  745. if ( AccountSid == NULL || pUserAccess == NULL || pEveryone == NULL )
  746. return(STATUS_INVALID_PARAMETER);
  747. *pUserAccess = NULL;
  748. *pEveryone = NULL;
  749. if ( pSecurityDescriptor == NULL )
  750. return(STATUS_SUCCESS);
  751. NtStatus = RtlGetDaclSecurityDescriptor(
  752. pSecurityDescriptor,
  753. &aclPresent,
  754. &pAcl,
  755. &tFlag);
  756. if ( NT_SUCCESS(NtStatus) )
  757. NtStatus = RtlAllocateAndInitializeSid(
  758. &WorldAuth,
  759. 1,
  760. SECURITY_CREATOR_OWNER_RID,
  761. 0,
  762. 0,
  763. 0,
  764. 0,
  765. 0,
  766. 0,
  767. 0,
  768. &EveryoneSid );
  769. if ( NT_SUCCESS(NtStatus) ) {
  770. if ( pAcl != NULL && aclPresent ) {
  771. for ( i=0; i < pAcl->AceCount; i++) {
  772. NtStatus = RtlGetAce( pAcl, i, &pAce );
  773. if ( !NT_SUCCESS( NtStatus ) )
  774. break;
  775. access = 0;
  776. pSid = NULL;
  777. switch ( ((PACE_HEADER)pAce)->AceType ) {
  778. case ACCESS_ALLOWED_ACE_TYPE:
  779. pSid = (PSID)&((PACCESS_ALLOWED_ACE)pAce)->SidStart;
  780. access = ((PACCESS_ALLOWED_ACE)pAce)->Mask;
  781. if ( EqualSid( AccountSid, pSid ) )
  782. *pUserAccess = &(((PACCESS_ALLOWED_ACE)pAce)->Mask);
  783. else if ( EqualSid( EveryoneSid, pSid) )
  784. *pEveryone = &(((PACCESS_ALLOWED_ACE)pAce)->Mask);
  785. break;
  786. case ACCESS_DENIED_ACE_TYPE:
  787. // do not look for denied ace type because it is not used here
  788. // pSid = (PSID)&((PACCESS_DENIED_ACE)pAce)->SidStart;
  789. // access = ((PACCESS_DENIED_ACE)pAce)->Mask;
  790. break;
  791. default:
  792. break;
  793. }
  794. if ( *pUserAccess != NULL && *pEveryone != NULL )
  795. // stop the loop because both are found
  796. break;
  797. }
  798. }
  799. }
  800. //
  801. // free EveryoneSid
  802. //
  803. if (EveryoneSid) {
  804. RtlFreeSid(EveryoneSid);
  805. EveryoneSid = NULL;
  806. }
  807. return(NtStatus);
  808. }
  809. BOOL
  810. ScepLastBackSlash(
  811. IN PWSTR Name
  812. )
  813. {
  814. if (Name == NULL )
  815. return(FALSE);
  816. if ( Name[wcslen(Name)-1] == L'\\')
  817. return(TRUE);
  818. else
  819. return(FALSE);
  820. }
  821. DWORD
  822. ScepGetUsersHomeDirectory(
  823. IN UNICODE_STRING AssignedHomeDir,
  824. IN PWSTR UserProfileName,
  825. OUT PWSTR *UserHomeDir
  826. )
  827. /*++
  828. Routine Description:
  829. This routine gets user's default home directory. The home directory is
  830. determined 1) if it is assigned in the user's object (user profile), 2)
  831. if there is a HomePath environment variable defined for the user, and
  832. 3). Harcoded.
  833. Arguments:
  834. AssignedHomeDir - The home directory explicitly assigned in the user's
  835. object.
  836. UserProfileName - The user's environment profile name
  837. UserHomeDir - The returned home directory for the user
  838. Return Value:
  839. Win32 error code.
  840. --*/
  841. {
  842. DWORD Win32rc=NO_ERROR;
  843. PWSTR StrValue=NULL;
  844. PWSTR SystemRoot=NULL;
  845. DWORD DirSize=0;
  846. *UserHomeDir = NULL;
  847. //
  848. // if there is a home directory assigned in the user profile, use it.
  849. //
  850. if ( AssignedHomeDir.Length > 0 && AssignedHomeDir.Buffer != NULL ) {
  851. *UserHomeDir = (PWSTR)ScepAlloc( LMEM_ZEROINIT, AssignedHomeDir.Length+2);
  852. if ( *UserHomeDir == NULL )
  853. return(ERROR_NOT_ENOUGH_MEMORY);
  854. wcsncpy(*UserHomeDir, AssignedHomeDir.Buffer, AssignedHomeDir.Length/2);
  855. return(NO_ERROR);
  856. }
  857. //
  858. // Home directory is NULL in user profile, the HomePath environment
  859. // is searched.
  860. //
  861. Win32rc = ScepGetNTDirectory( &SystemRoot, &DirSize, SCE_FLAG_WINDOWS_DIR );
  862. if ( Win32rc != NO_ERROR ) {
  863. ScepLogOutput3(1, Win32rc, SCEDLL_ERROR_QUERY_INFO, L"%WinDir%");
  864. return(Win32rc);
  865. }
  866. Win32rc = ScepGetEnvVarsFromProfile(
  867. UserProfileName,
  868. L"HomePath",
  869. NULL,
  870. &StrValue
  871. );
  872. if ( Win32rc == NO_ERROR && StrValue != NULL ) {
  873. *UserHomeDir = (PWSTR)ScepAlloc( LMEM_ZEROINIT, (wcslen(StrValue)+3)*sizeof(WCHAR));
  874. if ( *UserHomeDir == NULL )
  875. Win32rc = ERROR_NOT_ENOUGH_MEMORY;
  876. else {
  877. swprintf(*UserHomeDir+1, L":%s", StrValue);
  878. **UserHomeDir = SystemRoot[0];
  879. }
  880. } else
  881. Win32rc = NO_ERROR; // do not care if can't get environment variable's value
  882. if ( SystemRoot != NULL )
  883. ScepFree(SystemRoot);
  884. if ( StrValue != NULL )
  885. ScepFree( StrValue );
  886. return(Win32rc);
  887. }
  888. DWORD
  889. ScepGetEnvVarsFromProfile(
  890. IN PWSTR UserProfileName,
  891. IN PCWSTR VarName1,
  892. IN PCWSTR VarName2 OPTIONAL,
  893. OUT PWSTR *StrValue
  894. )
  895. {
  896. DWORD rc;
  897. DWORD RegType;
  898. rc = SceAdjustPrivilege(SE_RESTORE_PRIVILEGE, TRUE, NULL);
  899. if ( rc == ERROR_SUCCESS ) {
  900. rc = RegLoadKey(HKEY_USERS, L"TEMP", UserProfileName);
  901. if ( rc == ERROR_SUCCESS ) {
  902. rc = ScepRegQueryValue(
  903. HKEY_USERS,
  904. L"TEMP\\Environment",
  905. VarName1,
  906. (PVOID *)StrValue,
  907. &RegType,
  908. NULL
  909. );
  910. if ( rc != ERROR_SUCCESS && VarName2 != NULL ) {
  911. rc = ScepRegQueryValue(
  912. HKEY_USERS,
  913. L"TEMP\\Environment",
  914. VarName2,
  915. (PVOID *)StrValue,
  916. &RegType,
  917. NULL
  918. );
  919. }
  920. RegUnLoadKey(HKEY_USERS, L"TEMP");
  921. } else { //if ( rc == ERROR_ALREADY_IN_USE) {
  922. //
  923. // this profile already in use. Open the one in HKEY_CURRENT_USER
  924. //
  925. rc = ScepRegQueryValue(
  926. HKEY_CURRENT_USER,
  927. L"Environment",
  928. VarName1,
  929. (PVOID *)StrValue,
  930. &RegType,
  931. NULL
  932. );
  933. if ( rc != ERROR_SUCCESS && VarName2 != NULL ) {
  934. rc = ScepRegQueryValue(
  935. HKEY_CURRENT_USER,
  936. L"Environment",
  937. VarName2,
  938. (PVOID *)StrValue,
  939. &RegType,
  940. NULL
  941. );
  942. }
  943. }
  944. SceAdjustPrivilege(SE_RESTORE_PRIVILEGE, FALSE, NULL);
  945. }
  946. return(rc);
  947. }
  948. DWORD
  949. ScepGetUsersTempDirectory(
  950. IN PWSTR UserProfileName,
  951. OUT PWSTR *UserTempDir
  952. )
  953. /*++
  954. Routine Description:
  955. This routine returns the user's temp directory. Temp directory for a
  956. user is determined 1) environment variable "TEMP" or "TMP" defined
  957. in the user's environment profile, or 2) Harcoded to %systemDrive%\TEMP
  958. Arguments:
  959. UserProfileName - The user's environment profile name
  960. UserTempDir - The returned temp directory for the user
  961. Return Value:
  962. Win32 error code
  963. --*/
  964. {
  965. DWORD rc=NO_ERROR;
  966. PWSTR StrValue=NULL;
  967. PWSTR SystemRoot=NULL;
  968. DWORD DirSize=0;
  969. //
  970. // query the TEMP/TMP environment variable(s)
  971. //
  972. if ( UserProfileName != NULL ) {
  973. ScepGetEnvVarsFromProfile(
  974. UserProfileName,
  975. L"TEMP",
  976. L"TMP",
  977. &StrValue
  978. );
  979. }
  980. if ( StrValue != NULL ) {
  981. //
  982. // find the setting for temp dir
  983. //
  984. if ( wcsstr(_wcsupr(StrValue), L"%") != NULL ) {
  985. rc = ScepTranslateFileDirName( StrValue, UserTempDir );
  986. }
  987. if ( rc == NO_ERROR ) {
  988. ScepFree(StrValue);
  989. } else
  990. *UserTempDir = StrValue;
  991. StrValue = NULL;
  992. } else {
  993. //
  994. // hardcoded to %SystemDrive%\TEMP
  995. //
  996. rc = ScepGetNTDirectory( &SystemRoot, &DirSize, SCE_FLAG_WINDOWS_DIR );
  997. if ( rc != NO_ERROR ) {
  998. ScepLogOutput3(1, rc, SCEDLL_ERROR_QUERY_INFO, L"%WinDir%");
  999. return(rc);
  1000. }
  1001. *UserTempDir = (PWSTR)ScepAlloc( 0, 8*sizeof(WCHAR));
  1002. if ( *UserTempDir == NULL )
  1003. rc = ERROR_NOT_ENOUGH_MEMORY;
  1004. else {
  1005. swprintf(*UserTempDir+1, L":\\TEMP");
  1006. **UserTempDir = SystemRoot[0];
  1007. }
  1008. }
  1009. if (SystemRoot != NULL )
  1010. ScepFree(SystemRoot);
  1011. return(rc);
  1012. }
  1013. SCESTATUS
  1014. ScepGetRegKeyCase(
  1015. IN PWSTR ObjName,
  1016. IN DWORD BufOffset,
  1017. IN DWORD BufLen
  1018. )
  1019. {
  1020. DWORD Win32rc;
  1021. HKEY hKey=NULL;
  1022. PWSTR Buffer=NULL;
  1023. TCHAR Buffer1[MAX_PATH];
  1024. DWORD BufSize, index;
  1025. FILETIME LastWriteTime;
  1026. if ( BufOffset <= 0 || BufLen <= 0 ) {
  1027. _wcsupr(ObjName);
  1028. return(SCESTATUS_SUCCESS);
  1029. }
  1030. Buffer = (PWSTR)ScepAlloc(LMEM_ZEROINIT, BufOffset*sizeof(WCHAR));
  1031. if ( Buffer != NULL ) {
  1032. wcsncpy(Buffer, ObjName, BufOffset-1);
  1033. Win32rc = ScepOpenRegistryObject(
  1034. SE_REGISTRY_KEY,
  1035. Buffer,
  1036. KEY_READ,
  1037. &hKey
  1038. );
  1039. if ( Win32rc == NO_ERROR ) {
  1040. index = 0;
  1041. //
  1042. // enumerate all subkeys of the key
  1043. //
  1044. do {
  1045. memset(Buffer1, '\0', MAX_PATH*sizeof(WCHAR));
  1046. BufSize = MAX_PATH;
  1047. Win32rc = RegEnumKeyEx(hKey,
  1048. index,
  1049. Buffer1,
  1050. &BufSize,
  1051. NULL,
  1052. NULL,
  1053. NULL,
  1054. &LastWriteTime);
  1055. if ( Win32rc == ERROR_SUCCESS ) {
  1056. index++;
  1057. //
  1058. // find if the subkey matches the object name
  1059. //
  1060. if ( _wcsicmp(ObjName+BufOffset, Buffer1) == 0 )
  1061. break;
  1062. }
  1063. } while ( Win32rc != ERROR_NO_MORE_ITEMS );
  1064. RegCloseKey(hKey);
  1065. if ( Win32rc == ERROR_SUCCESS ) {
  1066. //
  1067. // find it
  1068. //
  1069. if ( BufSize > BufLen )
  1070. BufSize = BufLen;
  1071. wcsncpy(ObjName+BufOffset, Buffer1, BufSize);
  1072. *(ObjName+BufOffset+BufSize) = L'\0';
  1073. } else if ( Win32rc == ERROR_NO_MORE_ITEMS) {
  1074. //
  1075. // does not find it
  1076. //
  1077. Win32rc = ERROR_FILE_NOT_FOUND;
  1078. }
  1079. }
  1080. ScepFree(Buffer);
  1081. } else
  1082. Win32rc = ERROR_NOT_ENOUGH_MEMORY;
  1083. if ( Win32rc != NO_ERROR ) {
  1084. //
  1085. // convert everything to uppercase
  1086. //
  1087. _wcsupr(ObjName+BufOffset);
  1088. }
  1089. return(ScepDosErrorToSceStatus(Win32rc));
  1090. }
  1091. SCESTATUS
  1092. ScepGetFileCase(
  1093. IN PWSTR ObjName,
  1094. IN DWORD BufOffset,
  1095. IN DWORD BufLen
  1096. )
  1097. {
  1098. intptr_t hFile;
  1099. struct _wfinddata_t FileInfo;
  1100. hFile = _wfindfirst(ObjName, &FileInfo);
  1101. if ( hFile != -1 ) {
  1102. wcsncpy(ObjName+BufOffset, FileInfo.name, BufLen);
  1103. _findclose(hFile);
  1104. } else
  1105. return(ScepDosErrorToSceStatus(GetLastError()));
  1106. return(SCESTATUS_SUCCESS);
  1107. }
  1108. SCESTATUS
  1109. ScepGetGroupCase(
  1110. IN OUT PWSTR GroupName,
  1111. IN DWORD Length
  1112. )
  1113. {
  1114. NTSTATUS NtStatus;
  1115. SAM_HANDLE ServerHandle=NULL,
  1116. DomainHandle=NULL,
  1117. BuiltinDomainHandle=NULL,
  1118. ThisDomain=NULL,
  1119. GroupHandle=NULL;
  1120. PSID DomainSid=NULL,
  1121. BuiltinDomainSid=NULL;
  1122. UNICODE_STRING Name;
  1123. PULONG GrpId=NULL;
  1124. PSID_NAME_USE GrpUse=NULL;
  1125. PVOID pNameInfo=NULL;
  1126. NtStatus = ScepOpenSamDomain(
  1127. SAM_SERVER_READ | SAM_SERVER_EXECUTE,
  1128. DOMAIN_READ | DOMAIN_EXECUTE,
  1129. &ServerHandle,
  1130. &DomainHandle,
  1131. &DomainSid,
  1132. &BuiltinDomainHandle,
  1133. &BuiltinDomainSid
  1134. );
  1135. if ( NT_SUCCESS(NtStatus) ) {
  1136. RtlInitUnicodeString(&Name, GroupName);
  1137. NtStatus = SamLookupNamesInDomain(
  1138. DomainHandle,
  1139. 1,
  1140. &Name,
  1141. &GrpId,
  1142. &GrpUse
  1143. );
  1144. ThisDomain = DomainHandle;
  1145. if ( NtStatus == STATUS_NONE_MAPPED ) {
  1146. //
  1147. // not found in account domain. Lookup in the builtin domain
  1148. //
  1149. NtStatus = SamLookupNamesInDomain(
  1150. BuiltinDomainHandle,
  1151. 1,
  1152. &Name,
  1153. &GrpId,
  1154. &GrpUse
  1155. );
  1156. ThisDomain=BuiltinDomainHandle;
  1157. }
  1158. if ( NT_SUCCESS(NtStatus) ) {
  1159. switch ( GrpUse[0] ) {
  1160. case SidTypeGroup:
  1161. NtStatus = SamOpenGroup(
  1162. ThisDomain,
  1163. GROUP_READ | GROUP_EXECUTE,
  1164. GrpId[0],
  1165. &GroupHandle
  1166. );
  1167. if ( NT_SUCCESS(NtStatus) ) {
  1168. NtStatus = SamQueryInformationGroup(
  1169. GroupHandle,
  1170. GroupNameInformation,
  1171. &pNameInfo
  1172. );
  1173. }
  1174. break;
  1175. case SidTypeAlias:
  1176. NtStatus = SamOpenAlias(
  1177. ThisDomain,
  1178. ALIAS_READ | ALIAS_EXECUTE,
  1179. GrpId[0],
  1180. &GroupHandle
  1181. );
  1182. if ( NT_SUCCESS(NtStatus) ) {
  1183. NtStatus = SamQueryInformationAlias(
  1184. GroupHandle,
  1185. AliasNameInformation,
  1186. &pNameInfo
  1187. );
  1188. }
  1189. break;
  1190. default:
  1191. NtStatus = STATUS_NONE_MAPPED;
  1192. break;
  1193. }
  1194. if ( NT_SUCCESS(NtStatus) ) {
  1195. //
  1196. // get name information
  1197. //
  1198. if ( ((PGROUP_NAME_INFORMATION)pNameInfo)->Name.Buffer != NULL &&
  1199. ((PGROUP_NAME_INFORMATION)pNameInfo)->Name.Length > 0 ) {
  1200. if ( Length > (DWORD)(((PGROUP_NAME_INFORMATION)pNameInfo)->Name.Length/2) ) {
  1201. wcsncpy(GroupName, ((PGROUP_NAME_INFORMATION)pNameInfo)->Name.Buffer,
  1202. ((PGROUP_NAME_INFORMATION)pNameInfo)->Name.Length/2);
  1203. } else {
  1204. wcsncpy(GroupName, ((PGROUP_NAME_INFORMATION)pNameInfo)->Name.Buffer,
  1205. Length);
  1206. }
  1207. } else
  1208. NtStatus = STATUS_NONE_MAPPED;
  1209. SamFreeMemory(pNameInfo);
  1210. }
  1211. if (GroupHandle)
  1212. SamCloseHandle(GroupHandle);
  1213. SamFreeMemory(GrpId);
  1214. SamFreeMemory(GrpUse);
  1215. }
  1216. SamCloseHandle( DomainHandle );
  1217. SamCloseHandle( BuiltinDomainHandle );
  1218. SamCloseHandle( ServerHandle );
  1219. SamFreeMemory(DomainSid);
  1220. RtlFreeSid(BuiltinDomainSid);
  1221. }
  1222. return(ScepDosErrorToSceStatus( RtlNtStatusToDosError(NtStatus) ));
  1223. }
  1224. VOID
  1225. ScepPrintSecurityDescriptor(
  1226. IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
  1227. IN BOOL ToDumpSD
  1228. )
  1229. {
  1230. if (pSecurityDescriptor != NULL) {
  1231. if ( ToDumpSD )
  1232. DumpSECURITY_DESCRIPTOR(pSecurityDescriptor);
  1233. else
  1234. printf("Security Descriptor\n");
  1235. }
  1236. }