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.

1499 lines
46 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. service.cpp
  5. Abstract:
  6. Routines to configure/analyze general settings of services plus
  7. some helper APIs
  8. Author:
  9. Jin Huang (jinhuang) 25-Jun-1997
  10. Revision History:
  11. --*/
  12. #include "headers.h"
  13. #include "serverp.h"
  14. #include "service.h"
  15. #include "pfp.h"
  16. //#define SCESVC_DBG 1
  17. SCESTATUS
  18. ScepConfigureGeneralServices(
  19. IN PSCECONTEXT hProfile,
  20. IN PSCE_SERVICES pServiceList,
  21. IN DWORD ConfigOptions
  22. )
  23. /*
  24. Routine Descripton:
  25. Configure startup and security descriptor settings for the list of
  26. services passed in.
  27. Arguments:
  28. pServiceList - the list of services to configure
  29. Return Value:
  30. SCE status
  31. */
  32. {
  33. SCESTATUS SceErr=SCESTATUS_SUCCESS;
  34. PSCE_SERVICES pNode;
  35. DWORD nServices=0;
  36. BOOL bDoneSettingSaclDacl = FALSE;
  37. NTSTATUS NtStatus = 0;
  38. SID_IDENTIFIER_AUTHORITY IdAuth=SECURITY_NT_AUTHORITY;
  39. DWORD rcSaveRsop = ERROR_SUCCESS;
  40. PSCESECTION hSectionDomain=NULL;
  41. PSCESECTION hSectionTattoo=NULL;
  42. PSCE_SERVICES pServiceCurrent=NULL;
  43. DWORD ServiceLen=0;
  44. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  45. ScepIsSystemShutDown() ) {
  46. return(SCESTATUS_SERVICE_NOT_SUPPORT);
  47. }
  48. if ( pServiceList != NULL ) {
  49. SC_HANDLE hScManager;
  50. //
  51. // open the manager
  52. //
  53. hScManager = OpenSCManager(
  54. NULL,
  55. NULL,
  56. SC_MANAGER_ALL_ACCESS
  57. // SC_MANAGER_CONNECT |
  58. // SC_MANAGER_QUERY_LOCK_STATUS |
  59. // SC_MANAGER_MODIFY_BOOT_CONFIG
  60. );
  61. SC_HANDLE hService=NULL;
  62. DWORD rc=NO_ERROR;
  63. if ( NULL == hScManager ) {
  64. rc = GetLastError();
  65. ScepLogOutput3(1, rc, SCEDLL_ERROR_OPEN, L"Service Control Manager");
  66. ScepPostProgress(TICKS_GENERAL_SERVICES,
  67. AREA_SYSTEM_SERVICE,
  68. NULL);
  69. return( ScepDosErrorToSceStatus(rc) );
  70. }
  71. LPQUERY_SERVICE_CONFIG pConfig=NULL;
  72. DWORD BytesNeeded;
  73. //
  74. // Adjust privilege for setting SACL
  75. //
  76. rc = SceAdjustPrivilege( SE_SECURITY_PRIVILEGE, TRUE, NULL );
  77. //
  78. // if can't adjust privilege, ignore (will error out later if SACL is requested)
  79. //
  80. if ( rc != NO_ERROR ) {
  81. ScepLogOutput3(1, rc, SCEDLL_ERROR_ADJUST, L"SE_SECURITY_PRIVILEGE");
  82. rc = NO_ERROR;
  83. }
  84. //
  85. // Adjust privilege for setting ownership (if required)
  86. //
  87. rc = SceAdjustPrivilege( SE_TAKE_OWNERSHIP_PRIVILEGE, TRUE, NULL );
  88. //
  89. // if can't adjust privilege, ignore (will error out later if acls need to be written)
  90. //
  91. if ( rc != NO_ERROR ) {
  92. ScepLogOutput3(1, rc, SCEDLL_ERROR_ADJUST, L"SE_TAKE_OWNERSHIP_PRIVILEGE");
  93. rc = NO_ERROR;
  94. }
  95. //
  96. // get AdminsSid in case need to take ownership later
  97. //
  98. NtStatus = RtlAllocateAndInitializeSid(
  99. &IdAuth,
  100. 2,
  101. SECURITY_BUILTIN_DOMAIN_RID,
  102. DOMAIN_ALIAS_RID_ADMINS,
  103. 0,
  104. 0,
  105. 0,
  106. 0,
  107. 0,
  108. 0,
  109. &AdminsSid );
  110. //
  111. // open the policy/tattoo tables
  112. //
  113. if ( ConfigOptions & SCE_POLICY_TEMPLATE ) {
  114. ScepTattooOpenPolicySections(
  115. hProfile,
  116. szServiceGeneral,
  117. &hSectionDomain,
  118. &hSectionTattoo
  119. );
  120. }
  121. //
  122. // Loop through each service to set general setting
  123. //
  124. for ( pNode=pServiceList;
  125. pNode != NULL && rc == NO_ERROR; pNode = pNode->Next ) {
  126. //
  127. // print the service name
  128. //
  129. if ( nServices < TICKS_GENERAL_SERVICES ) {
  130. ScepPostProgress(1,
  131. AREA_SYSTEM_SERVICE,
  132. pNode->ServiceName);
  133. nServices++;
  134. }
  135. ScepLogOutput3(2,0, SCEDLL_SCP_CONFIGURE, pNode->ServiceName);
  136. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  137. ScepIsSystemShutDown() ) {
  138. rc = ERROR_NOT_SUPPORTED;
  139. break;
  140. }
  141. ServiceLen = 0;
  142. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  143. hSectionDomain && hSectionTattoo ) {
  144. //
  145. // check if we need to query current setting for the service
  146. //
  147. ServiceLen = wcslen(pNode->ServiceName);
  148. if ( ScepTattooIfQueryNeeded(hSectionDomain, hSectionTattoo,
  149. pNode->ServiceName, ServiceLen, NULL, NULL ) ) {
  150. rc = ScepQueryAndAddService(
  151. hScManager,
  152. pNode->ServiceName,
  153. NULL,
  154. &pServiceCurrent
  155. );
  156. if ( ERROR_SUCCESS != rc ) {
  157. ScepLogOutput3(1,0,SCESRV_POLICY_TATTOO_ERROR_QUERY,rc,pNode->ServiceName);
  158. rc = NO_ERROR;
  159. } else {
  160. ScepLogOutput3(3,0,SCESRV_POLICY_TATTOO_QUERY,pNode->ServiceName);
  161. }
  162. }
  163. }
  164. bDoneSettingSaclDacl = FALSE;
  165. rcSaveRsop = ERROR_SUCCESS;
  166. //
  167. // open the service
  168. //
  169. hService = OpenService(
  170. hScManager,
  171. pNode->ServiceName,
  172. SERVICE_QUERY_CONFIG |
  173. SERVICE_CHANGE_CONFIG |
  174. READ_CONTROL |
  175. WRITE_DAC |
  176. // WRITE_OWNER | owner can't be set for a service
  177. ACCESS_SYSTEM_SECURITY
  178. );
  179. // if access was denied, try to take ownership
  180. // and try to open service again
  181. if (hService == NULL &&
  182. (ERROR_ACCESS_DENIED == (rc = GetLastError())) &&
  183. pNode->General.pSecurityDescriptor) {
  184. DWORD rcTakeOwnership = NO_ERROR;
  185. if (AdminsSid) {
  186. if ( NO_ERROR == (rcTakeOwnership = SetNamedSecurityInfo(
  187. (LPWSTR)pNode->ServiceName,
  188. SE_SERVICE,
  189. OWNER_SECURITY_INFORMATION,
  190. AdminsSid,
  191. NULL,
  192. NULL,
  193. NULL
  194. ))) {
  195. //
  196. // ownership changed, open service again and set SACL and DACL
  197. // get a handle to set security
  198. //
  199. if ( hService = OpenService(
  200. hScManager,
  201. pNode->ServiceName,
  202. READ_CONTROL |
  203. WRITE_DAC |
  204. ACCESS_SYSTEM_SECURITY
  205. )) {
  206. if ( SetServiceObjectSecurity(
  207. hService,
  208. pNode->SeInfo & (DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION),
  209. pNode->General.pSecurityDescriptor
  210. ) ) {
  211. bDoneSettingSaclDacl = TRUE;
  212. CloseServiceHandle(hService);
  213. hService = NULL;
  214. //
  215. // re-open the service only if there are other config info
  216. // to set (startup type).
  217. // So when NOSTARTTYPE is set, do not need to reopen the service
  218. //
  219. if (!(ConfigOptions & SCE_SETUP_SERVICE_NOSTARTTYPE)) {
  220. if (!(hService = OpenService(
  221. hScManager,
  222. pNode->ServiceName,
  223. SERVICE_QUERY_CONFIG |
  224. SERVICE_CHANGE_CONFIG
  225. )) ) {
  226. rc = GetLastError();
  227. }
  228. else {
  229. //
  230. //clear any error we have seen so far since everything has succeeded
  231. //
  232. rc = NO_ERROR;
  233. }
  234. }
  235. } else {
  236. //
  237. // shouldn't fail here unless Service Control Manager
  238. // fails for some reason.
  239. //
  240. rc = GetLastError();
  241. }
  242. } else {
  243. //
  244. // still fail to open the service to set DACL. this should
  245. // not happen for admin logons since the current logon is
  246. // one of the owner. But for normal user logon, this could
  247. // fail (actually normal user logon should fail to set
  248. // the owner
  249. rc = GetLastError();
  250. }
  251. }
  252. } else {
  253. //
  254. // AdminSid failed to be initialized, get the error
  255. //
  256. rcTakeOwnership = RtlNtStatusToDosError(NtStatus);
  257. }
  258. if ( NO_ERROR != rcTakeOwnership || NO_ERROR != rc ) {
  259. //
  260. // log the error occurred in take ownership process
  261. // reset error back to access denied so it will also be
  262. // logged as failure to open the service
  263. //
  264. if (NO_ERROR != rcTakeOwnership)
  265. ScepLogOutput3(2,rcTakeOwnership, SCEDLL_ERROR_TAKE_OWNER, (LPWSTR)pNode->ServiceName);
  266. else
  267. ScepLogOutput3(2, rc, SCEDLL_ERROR_OPEN, (LPWSTR)pNode->ServiceName);
  268. rc = ERROR_ACCESS_DENIED;
  269. }
  270. }
  271. if ( hService != NULL ) {
  272. if (ConfigOptions & SCE_SETUP_SERVICE_NOSTARTTYPE) {
  273. //
  274. // do not configure service start type
  275. //
  276. if ( pNode->General.pSecurityDescriptor != NULL ) {
  277. if ( !SetServiceObjectSecurity(
  278. hService,
  279. pNode->SeInfo & (DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION),
  280. pNode->General.pSecurityDescriptor
  281. ) ) {
  282. rc = GetLastError();
  283. }
  284. else
  285. bDoneSettingSaclDacl = TRUE;
  286. }
  287. } else {
  288. //
  289. // query the length of config
  290. //
  291. if ( !QueryServiceConfig(
  292. hService,
  293. NULL,
  294. 0,
  295. &BytesNeeded
  296. ) ) {
  297. rc = GetLastError();
  298. if ( rc == ERROR_INSUFFICIENT_BUFFER ) {
  299. pConfig = (LPQUERY_SERVICE_CONFIG)ScepAlloc(0, BytesNeeded);
  300. if ( pConfig != NULL ) {
  301. //
  302. // the real query of config
  303. //
  304. if ( QueryServiceConfig(
  305. hService,
  306. pConfig,
  307. BytesNeeded,
  308. &BytesNeeded
  309. ) ) {
  310. rc = ERROR_SUCCESS;
  311. //
  312. // change pConfig->dwStartType to the new value
  313. //
  314. if ( pNode->Startup != (BYTE)(pConfig->dwStartType) ) {
  315. //
  316. // congigure the service startup
  317. //
  318. if ( !ChangeServiceConfig(
  319. hService,
  320. pConfig->dwServiceType,
  321. pNode->Startup,
  322. pConfig->dwErrorControl,
  323. pConfig->lpBinaryPathName,
  324. pConfig->lpLoadOrderGroup,
  325. NULL,
  326. pConfig->lpDependencies,
  327. pConfig->lpServiceStartName,
  328. NULL,
  329. pConfig->lpDisplayName
  330. ) ) {
  331. rc = GetLastError();
  332. }
  333. }
  334. if ( rc == NO_ERROR &&
  335. pNode->General.pSecurityDescriptor != NULL &&
  336. !bDoneSettingSaclDacl) {
  337. if ( !SetServiceObjectSecurity(
  338. hService,
  339. pNode->SeInfo & (DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION),
  340. pNode->General.pSecurityDescriptor
  341. ) ) {
  342. rc = GetLastError();
  343. }
  344. else
  345. bDoneSettingSaclDacl = TRUE;
  346. }
  347. } else {
  348. rc = GetLastError();
  349. ScepLogOutput3(3,rc, SCEDLL_ERROR_QUERY_INFO, pNode->ServiceName);
  350. }
  351. ScepFree(pConfig);
  352. pConfig = NULL;
  353. } else {
  354. //
  355. // cannot allocate pConfig
  356. //
  357. rc = ERROR_NOT_ENOUGH_MEMORY;
  358. }
  359. } else {
  360. ScepLogOutput3(3,rc, SCEDLL_ERROR_QUERY_INFO, pNode->ServiceName);
  361. }
  362. } else {
  363. //
  364. // should not fall in here
  365. //
  366. rc = ERROR_SUCCESS;
  367. }
  368. }
  369. CloseServiceHandle (hService);
  370. hService = NULL;
  371. if ( rc != NO_ERROR ) {
  372. ScepLogOutput3(1, rc, SCEDLL_SCP_ERROR_CONFIGURE, pNode->ServiceName);
  373. rcSaveRsop = rc;
  374. if ( ERROR_INVALID_OWNER == rc ||
  375. ERROR_INVALID_PRIMARY_GROUP == rc ||
  376. ERROR_INVALID_SECURITY_DESCR == rc ||
  377. ERROR_INVALID_ACL == rc ||
  378. ERROR_ACCESS_DENIED == rc ) {
  379. gWarningCode = rc;
  380. rc = NO_ERROR;
  381. }
  382. } else if ( !(ConfigOptions & SCE_SETUP_SERVICE_NOSTARTTYPE) &&
  383. pNode->Startup == SERVICE_DISABLED ) {
  384. //
  385. // if the service type is "disabled", we should also stop the service
  386. //
  387. if ( hService = OpenService(
  388. hScManager,
  389. pNode->ServiceName,
  390. SERVICE_STOP
  391. )) {
  392. SERVICE_STATUS ServiceStatus;
  393. if (!ControlService(hService,
  394. SERVICE_CONTROL_STOP,
  395. &ServiceStatus
  396. )) {
  397. if ( ERROR_SERVICE_NOT_ACTIVE != GetLastError() ) {
  398. ScepLogOutput3(2, GetLastError(), SCEDLL_SCP_ERROR_STOP, pNode->ServiceName);
  399. }
  400. }
  401. CloseServiceHandle (hService);
  402. hService = NULL;
  403. } else {
  404. ScepLogOutput3(2, GetLastError(), SCEDLL_SCP_ERROR_OPENFORSTOP, pNode->ServiceName);
  405. }
  406. }
  407. } else {
  408. //
  409. // cannot open the service or some error taking ownership
  410. //
  411. if (rc != NO_ERROR) {
  412. ScepLogOutput3(1, rc, SCEDLL_ERROR_OPEN, pNode->ServiceName);
  413. // either of setting security/startup type failed - save it for RSOP log
  414. rcSaveRsop = (rcSaveRsop == ERROR_SUCCESS ? rc: rcSaveRsop);
  415. if ( rc == ERROR_SERVICE_DOES_NOT_EXIST )
  416. rc = NO_ERROR;
  417. }
  418. }
  419. if (ConfigOptions & SCE_RSOP_CALLBACK)
  420. ScepRsopLog(SCE_RSOP_SERVICES_INFO,
  421. rcSaveRsop != NO_ERROR ? rcSaveRsop : rc,
  422. pNode->ServiceName,
  423. 0,
  424. 0);
  425. if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
  426. hSectionDomain && hSectionTattoo ) {
  427. //
  428. // manage the tattoo value of this one
  429. //
  430. ScepTattooManageOneServiceValue(
  431. hSectionDomain,
  432. hSectionTattoo,
  433. pNode->ServiceName,
  434. ServiceLen,
  435. pServiceCurrent,
  436. rc
  437. );
  438. }
  439. if ( pServiceCurrent ) {
  440. SceFreePSCE_SERVICES(pServiceCurrent);
  441. pServiceCurrent = NULL;
  442. }
  443. }
  444. CloseServiceHandle (hScManager);
  445. if (AdminsSid) {
  446. RtlFreeSid(AdminsSid);
  447. AdminsSid = NULL;
  448. }
  449. SceAdjustPrivilege( SE_TAKE_OWNERSHIP_PRIVILEGE, FALSE, NULL );
  450. SceAdjustPrivilege( SE_SECURITY_PRIVILEGE, FALSE, NULL );
  451. SceErr = ScepDosErrorToSceStatus(rc);
  452. }
  453. if ( nServices < TICKS_GENERAL_SERVICES ) {
  454. ScepPostProgress(TICKS_GENERAL_SERVICES-nServices,
  455. AREA_SYSTEM_SERVICE,
  456. NULL);
  457. }
  458. SceJetCloseSection(&hSectionDomain, TRUE);
  459. SceJetCloseSection(&hSectionTattoo, TRUE);
  460. return(SceErr);
  461. }
  462. SCESTATUS
  463. ScepAnalyzeGeneralServices(
  464. IN PSCECONTEXT hProfile,
  465. IN DWORD Options
  466. )
  467. /*
  468. Routine Description:
  469. Analyze all available services on the current system.
  470. The base profile (SCEP) is in hProfile
  471. Arguments:
  472. hProfile - the database context handle
  473. Return Value:
  474. SCE status
  475. */
  476. {
  477. if ( hProfile == NULL ) {
  478. ScepPostProgress(TICKS_GENERAL_SERVICES,
  479. AREA_SYSTEM_SERVICE,
  480. NULL);
  481. return(SCESTATUS_INVALID_PARAMETER);
  482. }
  483. SCESTATUS rc;
  484. PSCE_SERVICES pServiceList=NULL;
  485. DWORD nServices=0;
  486. rc = SceEnumerateServices( &pServiceList, FALSE );
  487. rc = ScepDosErrorToSceStatus(rc);
  488. if ( rc == SCESTATUS_SUCCESS ) {
  489. PSCESECTION hSectionScep=NULL, hSectionSap=NULL;
  490. //
  491. // open the sap section. If it is not there, creates it
  492. //
  493. rc = ScepStartANewSection(
  494. hProfile,
  495. &hSectionSap,
  496. (Options & SCE_GENERATE_ROLLBACK) ? SCEJET_TABLE_SMP : SCEJET_TABLE_SAP,
  497. szServiceGeneral
  498. );
  499. if ( rc == SCESTATUS_SUCCESS ) {
  500. PSCE_SERVICES pNode = pServiceList;
  501. //
  502. // open SCEP section. should be success always because the StartANewSection
  503. // creates the section if it is not there
  504. //
  505. rc = ScepOpenSectionForName(
  506. hProfile,
  507. (Options & SCE_GENERATE_ROLLBACK) ? SCE_ENGINE_SMP : SCE_ENGINE_SCP, // SCE_ENGINE_SMP,
  508. szServiceGeneral,
  509. &hSectionScep
  510. );
  511. if ( rc == SCESTATUS_SUCCESS ) {
  512. //
  513. // analyze each service
  514. //
  515. PSCE_SERVICES pOneService=NULL;
  516. BOOL IsDifferent;
  517. for ( pNode=pServiceList;
  518. pNode != NULL; pNode=pNode->Next ) {
  519. ScepLogOutput3(2, 0, SCEDLL_SAP_ANALYZE, pNode->ServiceName);
  520. if ( nServices < TICKS_SPECIFIC_SERVICES ) {
  521. ScepPostProgress(1,
  522. AREA_SYSTEM_SERVICE,
  523. NULL);
  524. nServices++;
  525. }
  526. //
  527. // get setting from the SMP profile
  528. //
  529. rc = ScepGetSingleServiceSetting(
  530. hSectionScep,
  531. pNode->ServiceName,
  532. &pOneService
  533. );
  534. if ( rc == SCESTATUS_SUCCESS ) {
  535. //
  536. // there is a SMP entry for the service, compare and save
  537. //
  538. rc = ScepCompareSingleServiceSetting(
  539. pOneService,
  540. pNode,
  541. &IsDifferent
  542. );
  543. if ( rc == SCESTATUS_SUCCESS && IsDifferent ) {
  544. //
  545. // write the service as mismatch
  546. //
  547. pNode->Status = (Options & SCE_GENERATE_ROLLBACK) ? 0 : SCE_STATUS_MISMATCH;
  548. pNode->SeInfo = pOneService->SeInfo;
  549. rc = ScepSetSingleServiceSetting(
  550. hSectionSap,
  551. pNode
  552. );
  553. }
  554. } else if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
  555. //
  556. // this service is not defined
  557. //
  558. if ( !(Options & SCE_GENERATE_ROLLBACK) ) {
  559. //
  560. // save the record with not configured status
  561. //
  562. pNode->Status = SCE_STATUS_NOT_CONFIGURED;
  563. rc = ScepSetSingleServiceSetting(
  564. hSectionSap,
  565. pNode
  566. );
  567. } else {
  568. //
  569. // ignore this one
  570. //
  571. rc = SCESTATUS_SUCCESS;
  572. }
  573. }
  574. SceFreePSCE_SERVICES(pOneService);
  575. pOneService = NULL;
  576. if ( rc != SCESTATUS_SUCCESS ) {
  577. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  578. SCEDLL_SAP_ERROR_ANALYZE, pNode->ServiceName);
  579. if ( SCESTATUS_ACCESS_DENIED == rc ) {
  580. gWarningCode = ScepSceStatusToDosError(rc);
  581. if ( !(Options & SCE_GENERATE_ROLLBACK) ) {
  582. //
  583. // raise a error status
  584. //
  585. pNode->Status = SCE_STATUS_ERROR_NOT_AVAILABLE;
  586. rc = ScepSetSingleServiceSetting(
  587. hSectionSap,
  588. pNode
  589. );
  590. }
  591. rc = SCESTATUS_SUCCESS;
  592. } else {
  593. break;
  594. }
  595. }
  596. }
  597. SceJetCloseSection(&hSectionScep, TRUE);
  598. }
  599. if ( !(Options & SCE_GENERATE_ROLLBACK ) ) {
  600. //
  601. // raise any error item
  602. //
  603. for ( PSCE_SERVICES pNodeTmp=pNode; pNodeTmp != NULL; pNodeTmp = pNodeTmp->Next ) {
  604. pNodeTmp->Status = SCE_STATUS_ERROR_NOT_AVAILABLE;
  605. ScepSetSingleServiceSetting(
  606. hSectionSap,
  607. pNode
  608. );
  609. }
  610. }
  611. SceJetCloseSection(&hSectionSap, TRUE);
  612. }
  613. if ( rc != SCESTATUS_SUCCESS )
  614. ScepLogOutput3(1, ScepSceStatusToDosError(rc), SCEDLL_SAP_ERROR_OUT);
  615. }
  616. if ( nServices < TICKS_GENERAL_SERVICES ) {
  617. ScepPostProgress(TICKS_GENERAL_SERVICES-nServices,
  618. AREA_SYSTEM_SERVICE,
  619. NULL);
  620. }
  621. return(rc);
  622. }
  623. SCESTATUS
  624. ScepGetSingleServiceSetting(
  625. IN PSCESECTION hSection,
  626. IN PWSTR ServiceName,
  627. OUT PSCE_SERVICES *pOneService
  628. )
  629. /*
  630. Routine Description:
  631. Get service settings for the service from the section
  632. Arguments:
  633. hSection - the section handle
  634. ServiceName - the service name
  635. pOneService - the service settings
  636. Return Value:
  637. SCE status
  638. */
  639. {
  640. if ( hSection == NULL || ServiceName == NULL || pOneService == NULL ) {
  641. return(SCESTATUS_INVALID_PARAMETER);
  642. }
  643. SCESTATUS rc;
  644. DWORD ValueLen;
  645. //
  646. // seek to the record and get length for name and value
  647. //
  648. rc = SceJetGetValue(
  649. hSection,
  650. SCEJET_EXACT_MATCH_NO_CASE,
  651. ServiceName,
  652. NULL,
  653. 0,
  654. NULL,
  655. NULL,
  656. 0,
  657. &ValueLen
  658. );
  659. if ( rc == SCESTATUS_SUCCESS ) {
  660. PWSTR Value=NULL;
  661. //
  662. // allocate memory for the service name and value string
  663. //
  664. Value = (PWSTR)ScepAlloc( LMEM_ZEROINIT, ValueLen+2);
  665. if ( Value != NULL ) {
  666. //
  667. // Get the service and its value
  668. //
  669. rc = SceJetGetValue(
  670. hSection,
  671. SCEJET_CURRENT,
  672. NULL,
  673. NULL,
  674. 0,
  675. NULL,
  676. Value,
  677. ValueLen,
  678. &ValueLen
  679. );
  680. if ( rc == SCESTATUS_SUCCESS ) {
  681. Value[ValueLen/2] = L'\0';
  682. DWORD Win32Rc=NO_ERROR;
  683. PSECURITY_DESCRIPTOR pTempSD=NULL;
  684. DWORD SDsize=0;
  685. SECURITY_INFORMATION SeInfo=0;
  686. if ( ValueLen >= 2 && Value[1] != L'\0' ) {
  687. //
  688. // convert to security descriptor
  689. //
  690. Win32Rc = ConvertTextSecurityDescriptor(
  691. Value+1,
  692. &pTempSD,
  693. &SDsize,
  694. &SeInfo
  695. );
  696. }
  697. if ( Win32Rc == NO_ERROR ) {
  698. ScepChangeAclRevision(pTempSD, ACL_REVISION);
  699. //
  700. // create this service node
  701. //
  702. *pOneService = (PSCE_SERVICES)ScepAlloc( LMEM_FIXED, sizeof(SCE_SERVICES) );
  703. if ( *pOneService != NULL ) {
  704. (*pOneService)->ServiceName = (PWSTR)ScepAlloc(LMEM_FIXED,
  705. (wcslen(ServiceName)+1)*sizeof(WCHAR));
  706. if ( (*pOneService)->ServiceName != NULL ) {
  707. wcscpy( (*pOneService)->ServiceName, ServiceName);
  708. (*pOneService)->DisplayName = NULL;
  709. (*pOneService)->Status = *((BYTE *)Value);
  710. (*pOneService)->Startup = *((BYTE *)Value+1);
  711. (*pOneService)->General.pSecurityDescriptor = pTempSD;
  712. (*pOneService)->SeInfo = SeInfo;
  713. (*pOneService)->Next = NULL;
  714. //
  715. // DO NOT free the following buffers
  716. //
  717. pTempSD = NULL;
  718. } else {
  719. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  720. ScepFree(*pOneService);
  721. }
  722. } else {
  723. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  724. }
  725. if ( pTempSD != NULL ) {
  726. ScepFree(pTempSD);
  727. }
  728. } else {
  729. rc = ScepDosErrorToSceStatus(Win32Rc);
  730. }
  731. }
  732. ScepFree(Value);
  733. } else
  734. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  735. }
  736. return(rc);
  737. }
  738. SCESTATUS
  739. ScepCompareSingleServiceSetting(
  740. IN PSCE_SERVICES pNode1,
  741. IN PSCE_SERVICES pNode2,
  742. OUT PBOOL pIsDifferent
  743. )
  744. /*
  745. Routine Description:
  746. Comare two service settings.
  747. Arguments:
  748. pNode1 - the first service
  749. pNode2 - the second service
  750. pIsDifferent - output TRUE if different
  751. Return Value:
  752. SCE status
  753. */
  754. {
  755. SCESTATUS rc=SCESTATUS_SUCCESS;
  756. if ( pNode1->Startup == pNode2->Startup ) {
  757. BYTE resultSD = 0;
  758. rc = ScepCompareObjectSecurity(
  759. SE_SERVICE,
  760. FALSE,
  761. pNode1->General.pSecurityDescriptor,
  762. pNode2->General.pSecurityDescriptor,
  763. pNode1->SeInfo & (DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION),
  764. &resultSD
  765. );
  766. if ( resultSD ) {
  767. *pIsDifferent = TRUE;
  768. } else
  769. *pIsDifferent = FALSE;
  770. } else
  771. *pIsDifferent = TRUE;
  772. return(rc);
  773. }
  774. SCESTATUS
  775. ScepSetSingleServiceSetting(
  776. IN PSCESECTION hSection,
  777. IN PSCE_SERVICES pOneService
  778. )
  779. /*
  780. Routine Description:
  781. Set service settings for the service from the section
  782. Arguments:
  783. hSection - the section handle
  784. pOneService - the service settings
  785. Return Value:
  786. SCE status
  787. */
  788. {
  789. if ( hSection == NULL || pOneService == NULL ) {
  790. return(SCESTATUS_INVALID_PARAMETER);
  791. }
  792. SCESTATUS rc=SCESTATUS_SUCCESS;
  793. PWSTR SDspec=NULL;
  794. DWORD SDsize=0;
  795. if ( (pOneService->Status != SCE_STATUS_NOT_ANALYZED) &&
  796. (pOneService->Status != SCE_STATUS_ERROR_NOT_AVAILABLE) &&
  797. (pOneService->General.pSecurityDescriptor != NULL) ) {
  798. DWORD Win32Rc;
  799. Win32Rc = ConvertSecurityDescriptorToText (
  800. pOneService->General.pSecurityDescriptor,
  801. pOneService->SeInfo,
  802. &SDspec,
  803. &SDsize // number of w-chars
  804. );
  805. rc = ScepDosErrorToSceStatus(Win32Rc);
  806. }
  807. if ( rc == SCESTATUS_SUCCESS ) {
  808. PWSTR Value=NULL;
  809. DWORD ValueLen;
  810. ValueLen = (SDsize+1)*sizeof(WCHAR);
  811. Value = (PWSTR)ScepAlloc( (UINT)0, ValueLen+sizeof(WCHAR) );
  812. if ( Value != NULL ) {
  813. //
  814. // The first byte is status, the second byte is startup
  815. //
  816. *((BYTE *)Value) = pOneService->Status;
  817. *((BYTE *)Value+1) = pOneService->Startup;
  818. if ( SDspec != NULL ) {
  819. swprintf(Value+1, L"%s", SDspec );
  820. }
  821. Value[SDsize+1] = L'\0'; //terminate this string
  822. //
  823. // set the value
  824. //
  825. rc = SceJetSetLine(
  826. hSection,
  827. pOneService->ServiceName,
  828. FALSE,
  829. Value,
  830. ValueLen,
  831. 0
  832. );
  833. ScepFree( Value );
  834. switch ( pOneService->Status ) {
  835. case SCE_STATUS_ERROR_NOT_AVAILABLE:
  836. ScepLogOutput3(2, 0, SCEDLL_STATUS_ERROR, pOneService->ServiceName);
  837. break;
  838. case SCE_STATUS_NOT_CONFIGURED:
  839. ScepLogOutput3(2, 0, SCEDLL_STATUS_NC, pOneService->ServiceName);
  840. break;
  841. case SCE_STATUS_NOT_ANALYZED:
  842. ScepLogOutput3(2, 0, SCEDLL_STATUS_NEW, pOneService->ServiceName);
  843. break;
  844. default:
  845. ScepLogOutput3(2, 0, SCEDLL_STATUS_MISMATCH, pOneService->ServiceName);
  846. break;
  847. }
  848. } else
  849. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  850. }
  851. if ( SDspec != NULL ) {
  852. ScepFree( SDspec );
  853. }
  854. return(rc);
  855. }
  856. SCESTATUS
  857. ScepInvokeSpecificServices(
  858. IN PSCECONTEXT hProfile,
  859. IN BOOL bConfigure,
  860. IN SCE_ATTACHMENT_TYPE aType
  861. )
  862. /*
  863. Routine Description:
  864. Call each service engine for configure or analyze
  865. Arguments:
  866. hProfile - the profile handle
  867. bConfigure - TRUE = to configure, FALSE=to analyze
  868. aType - attachment type "services" or "policy"
  869. Return Value:
  870. SCE status
  871. */
  872. {
  873. //
  874. // for posting progress
  875. //
  876. DWORD nServices=0;
  877. AREA_INFORMATION Area=0;
  878. DWORD nMaxTicks=0;
  879. switch(aType) {
  880. case SCE_ATTACHMENT_SERVICE:
  881. Area = AREA_SYSTEM_SERVICE;
  882. nMaxTicks = TICKS_SPECIFIC_SERVICES;
  883. break;
  884. case SCE_ATTACHMENT_POLICY:
  885. Area = AREA_SECURITY_POLICY;
  886. nMaxTicks = TICKS_SPECIFIC_POLICIES;
  887. break;
  888. }
  889. if ( hProfile == NULL ) {
  890. ScepPostProgress(nMaxTicks,
  891. Area,
  892. NULL);
  893. return(SCESTATUS_INVALID_PARAMETER);
  894. }
  895. //
  896. // call available service engines to configure specific setting
  897. //
  898. SCESTATUS SceErr ;
  899. PSCE_SERVICES pSvcEngineList=NULL;
  900. SCEP_HANDLE sceHandle;
  901. SCESVC_CALLBACK_INFO sceCbInfo;
  902. SceErr = ScepEnumServiceEngines(&pSvcEngineList, aType);
  903. if ( SceErr == SCESTATUS_SUCCESS) {
  904. HINSTANCE hDll;
  905. PF_ConfigAnalyzeService pfTemp;
  906. for ( PSCE_SERVICES pNode=pSvcEngineList;
  907. pNode != NULL; pNode = pNode->Next ) {
  908. ScepLogOutput3(2, 0, SCEDLL_LOAD_ATTACHMENT, pNode->ServiceName);
  909. if ( nServices < nMaxTicks ) {
  910. ScepPostProgress(1, Area, pNode->ServiceName);
  911. nServices++;
  912. }
  913. //
  914. // load the dll.
  915. //
  916. hDll = LoadLibrary(pNode->General.ServiceEngineName);
  917. if ( hDll != NULL ) {
  918. if ( bConfigure ) {
  919. //
  920. // call SceSvcAttachmentConfig from the dll
  921. //
  922. pfTemp = (PF_ConfigAnalyzeService)
  923. GetProcAddress(hDll,
  924. "SceSvcAttachmentConfig") ;
  925. } else {
  926. //
  927. // call SceSvcAttachmentAnalyze from the dll
  928. //
  929. pfTemp = (PF_ConfigAnalyzeService)
  930. GetProcAddress(hDll,
  931. "SceSvcAttachmentAnalyze") ;
  932. }
  933. if ( pfTemp != NULL ) {
  934. //
  935. // prepare the handle first
  936. //
  937. sceHandle.hProfile = (PVOID)hProfile;
  938. sceHandle.ServiceName = (PCWSTR)(pNode->ServiceName);
  939. sceCbInfo.sceHandle = &sceHandle;
  940. sceCbInfo.pfQueryInfo = &SceCbQueryInfo;
  941. sceCbInfo.pfSetInfo = &SceCbSetInfo;
  942. sceCbInfo.pfFreeInfo = &SceSvcpFreeMemory;
  943. sceCbInfo.pfLogInfo = &ScepLogOutput2;
  944. //
  945. // call the SceSvcAttachmentConfig/Analyze from the DLL
  946. //
  947. __try {
  948. SceErr = (*pfTemp)((PSCESVC_CALLBACK_INFO)&sceCbInfo);
  949. } __except (EXCEPTION_EXECUTE_HANDLER) {
  950. SceErr = SCESTATUS_SERVICE_NOT_SUPPORT;
  951. }
  952. } else {
  953. //
  954. // this API is not supported
  955. //
  956. SceErr = SCESTATUS_SERVICE_NOT_SUPPORT;
  957. }
  958. //
  959. // try to free the library handle. If it fails, just leave it
  960. // to to the process to terminate
  961. //
  962. FreeLibrary(hDll);
  963. } else
  964. SceErr = SCESTATUS_SERVICE_NOT_SUPPORT;
  965. if ( SceErr == SCESTATUS_SERVICE_NOT_SUPPORT ) {
  966. if ( bConfigure )
  967. ScepLogOutput3(1, ScepSceStatusToDosError(SceErr),
  968. SCEDLL_SCP_NOT_SUPPORT);
  969. else
  970. ScepLogOutput3(1, ScepSceStatusToDosError(SceErr),
  971. SCEDLL_SAP_NOT_SUPPORT);
  972. SceErr = SCESTATUS_SUCCESS;
  973. } else if ( SceErr != SCESTATUS_SUCCESS &&
  974. SceErr != SCESTATUS_RECORD_NOT_FOUND ) {
  975. ScepLogOutput3(1, ScepSceStatusToDosError(SceErr),
  976. SCEDLL_ERROR_LOAD, pNode->ServiceName);
  977. }
  978. if ( SceErr != SCESTATUS_SUCCESS &&
  979. SceErr != SCESTATUS_SERVICE_NOT_SUPPORT &&
  980. SceErr != SCESTATUS_RECORD_NOT_FOUND )
  981. break;
  982. }
  983. //
  984. // free the buffer
  985. //
  986. SceFreePSCE_SERVICES(pSvcEngineList);
  987. } else if ( SceErr != SCESTATUS_SUCCESS &&
  988. SceErr != SCESTATUS_PROFILE_NOT_FOUND &&
  989. SceErr != SCESTATUS_RECORD_NOT_FOUND ) {
  990. ScepLogOutput3(1, ScepSceStatusToDosError(SceErr),
  991. SCEDLL_SAP_ERROR_ENUMERATE, L"services");
  992. }
  993. if ( SceErr == SCESTATUS_PROFILE_NOT_FOUND ||
  994. SceErr == SCESTATUS_RECORD_NOT_FOUND ||
  995. SceErr == SCESTATUS_SERVICE_NOT_SUPPORT ) {
  996. //
  997. // no service engine defined
  998. //
  999. SceErr = SCESTATUS_SUCCESS;
  1000. }
  1001. if ( nServices < nMaxTicks ) {
  1002. ScepPostProgress(nMaxTicks-nServices,
  1003. Area,
  1004. NULL);
  1005. }
  1006. return(SceErr);
  1007. }
  1008. SCESTATUS
  1009. ScepEnumServiceEngines(
  1010. OUT PSCE_SERVICES *pSvcEngineList,
  1011. IN SCE_ATTACHMENT_TYPE aType
  1012. )
  1013. /*
  1014. Routine Description:
  1015. Query all services which has a service engine for security manager
  1016. The service engine information is in the registry:
  1017. MACHINE\Software\Microsoft\Windows NT\CurrentVersion\SeCEdit
  1018. Arguments:
  1019. pSvcEngineList - the service engine list
  1020. aType - attachment type (service or policy)
  1021. Return Value:
  1022. SCE status
  1023. */
  1024. {
  1025. if ( pSvcEngineList == NULL ) {
  1026. return(SCESTATUS_INVALID_PARAMETER);
  1027. }
  1028. DWORD Win32Rc;
  1029. HKEY hKey=NULL;
  1030. switch ( aType ) {
  1031. case SCE_ATTACHMENT_SERVICE:
  1032. Win32Rc = RegOpenKeyEx(
  1033. HKEY_LOCAL_MACHINE,
  1034. SCE_ROOT_SERVICE_PATH,
  1035. 0,
  1036. KEY_READ,
  1037. &hKey
  1038. );
  1039. break;
  1040. case SCE_ATTACHMENT_POLICY:
  1041. Win32Rc = RegOpenKeyEx(
  1042. HKEY_LOCAL_MACHINE,
  1043. SCE_ROOT_POLICY_PATH,
  1044. 0,
  1045. KEY_READ,
  1046. &hKey
  1047. );
  1048. break;
  1049. default:
  1050. return SCESTATUS_INVALID_PARAMETER;
  1051. }
  1052. if ( Win32Rc == ERROR_SUCCESS ) {
  1053. TCHAR Buffer[MAX_PATH];
  1054. DWORD BufSize;
  1055. DWORD index = 0;
  1056. DWORD EnumRc;
  1057. FILETIME LastWriteTime;
  1058. PWSTR BufTmp=NULL;
  1059. PWSTR EngineName=NULL;
  1060. DWORD RegType;
  1061. //
  1062. // enumerate all subkeys of the key
  1063. //
  1064. do {
  1065. memset(Buffer, '\0', MAX_PATH*sizeof(WCHAR));
  1066. BufSize = MAX_PATH;
  1067. EnumRc = RegEnumKeyEx(
  1068. hKey,
  1069. index,
  1070. Buffer,
  1071. &BufSize,
  1072. NULL,
  1073. NULL,
  1074. NULL,
  1075. &LastWriteTime);
  1076. if ( EnumRc == ERROR_SUCCESS ) {
  1077. index++;
  1078. //
  1079. // get the service name, query service engine name
  1080. //
  1081. BufSize += wcslen(SCE_ROOT_SERVICE_PATH) + 1; //62;
  1082. BufTmp = (PWSTR)ScepAlloc( 0, (BufSize+1)*sizeof(WCHAR));
  1083. if ( BufTmp != NULL ) {
  1084. switch ( aType ) {
  1085. case SCE_ATTACHMENT_SERVICE:
  1086. swprintf(BufTmp, L"%s\\%s", SCE_ROOT_SERVICE_PATH, Buffer);
  1087. Win32Rc = ScepRegQueryValue(
  1088. HKEY_LOCAL_MACHINE,
  1089. BufTmp,
  1090. L"ServiceAttachmentPath",
  1091. (PVOID *)&EngineName,
  1092. &RegType
  1093. );
  1094. break;
  1095. case SCE_ATTACHMENT_POLICY:
  1096. // policies
  1097. swprintf(BufTmp, L"%s\\%s", SCE_ROOT_POLICY_PATH, Buffer);
  1098. Win32Rc = ScepRegQueryValue(
  1099. HKEY_LOCAL_MACHINE,
  1100. BufTmp,
  1101. L"PolicyAttachmentPath",
  1102. (PVOID *)&EngineName,
  1103. &RegType
  1104. );
  1105. break;
  1106. }
  1107. if ( Win32Rc == ERROR_SUCCESS ) {
  1108. //
  1109. // get the service engine name and service name
  1110. // add them to the service node
  1111. //
  1112. Win32Rc = ScepAddOneServiceToList(
  1113. Buffer, // service name
  1114. NULL,
  1115. 0,
  1116. (PVOID)EngineName,
  1117. 0,
  1118. FALSE,
  1119. pSvcEngineList
  1120. );
  1121. //
  1122. // free the buffer if it's not added to the list
  1123. //
  1124. if ( Win32Rc != ERROR_SUCCESS && EngineName ) {
  1125. ScepFree(EngineName);
  1126. }
  1127. EngineName = NULL;
  1128. } else if ( Win32Rc == ERROR_FILE_NOT_FOUND ) {
  1129. //
  1130. // if no service engine name, ignore this service
  1131. //
  1132. Win32Rc = ERROR_SUCCESS;
  1133. }
  1134. ScepFree(BufTmp);
  1135. BufTmp = NULL;
  1136. } else {
  1137. Win32Rc = ERROR_NOT_ENOUGH_MEMORY;
  1138. }
  1139. if ( Win32Rc != ERROR_SUCCESS ) {
  1140. break;
  1141. }
  1142. }
  1143. } while ( EnumRc != ERROR_NO_MORE_ITEMS );
  1144. RegCloseKey(hKey);
  1145. //
  1146. // remember the error code from enumeration
  1147. //
  1148. if ( EnumRc != ERROR_SUCCESS && EnumRc != ERROR_NO_MORE_ITEMS ) {
  1149. if ( Win32Rc == ERROR_SUCCESS )
  1150. Win32Rc = EnumRc;
  1151. }
  1152. }
  1153. if ( Win32Rc != NO_ERROR && *pSvcEngineList != NULL ) {
  1154. //
  1155. // free memory allocated for the list
  1156. //
  1157. SceFreePSCE_SERVICES(*pSvcEngineList);
  1158. *pSvcEngineList = NULL;
  1159. }
  1160. return( ScepDosErrorToSceStatus(Win32Rc) );
  1161. }