Service network restrictions are implemented with per-service SIDS. The mechanism is similar to that used to restrict a service's file or registry key access, as discussed in "Service Isolation," earlier in this paper. The Windows Vista and Windows Server Longhorn firewall API has been enhanced to provide the necessary support. The INetFwServiceRestriction interface includes the methods that are used to restrict a service's network access. For further information, see Internet Connection Sharing and Internet Connection Firewall, which is listed in "Resources" at the end of this paper. The following Microsoft Visual Basic® script example uses the firewall API to restrict the 6to4 service to only inbound TCP 500 traffic. 'require variable declarations option explicit 'handle errors on error resume next 'direction Const NET_FW_DIRECTION_IN = 1 ' Create the FwPolicy2 object. Dim fwPolicy2 Set fwPolicy2 = CreateObject("HNetCfg.FwPolicy2") Dim FwSvcRestr Set FwSvcRestr = fwPolicy2.ServiceRestriction 'restrict service FwSvcRestr.RestrictService "6to4", "c:\windows\system32\svchost.exe", TRUE, TRUE 'Create a new restriction rule Dim NewRule set NewRule = CreateObject("HNetCfg.FwRule") NewRule.Name = "6to4 500" NewRule.Description = "Allow 6to4 to receive TCP traffic on port 500" NewRule.ApplicationName = "c:\windows\system32\svchost.exe" NewRule.ServiceName = "6to4" NewRule.Protocol = 6 NewRule.LocalPorts = "500" NewRule.Direction = NET_FW_DIRECTION_IN NewRule.Enabled = TRUE 'Add the behavior rule to the WSH store. fwPolicy2.ServiceRestriction.Rules.Add NewRule Session 0 IsolationWindows accommodates multiple logged-on users by putting each user in a separate session. Session 0 is created during startup, with additional sessions added as required. Services have always run in Session 0. Earlier than Windows Vista, user applications have also been able to run in Session 0. For example, for Windows XP with Fast User Switching (FUS) enabled, the first user to log on is assigned to Session 0 and that user's applications run in that session. Session 1 is assigned to the second user to log on, and so on. Running services and user applications in the same session creates a number of security issues. To address those issues, Windows Vista makes two significant changes to Session 0: · Session 0 is reserved exclusively for services and other applications that are not associated with an interactive user session. User applications must run in Session 1 or higher. · Session 0 does not support user interfaces. In particular, processes that are running in Session 0 do not have access to the graphics hardware and cannot directly display any UI on the monitor. Session 0 isolation has a number of implications for services, including the following: · Services cannot use PostMessage or SendMessage to send messages to user applications. All applications are running in Session 1 or higher and have a different message queue. Applications cannot send Windows messages to a service for the same reason. Services that send messages to applications must use mechanisms such as remote procedure calls (RPCs) or named pipes. · Services that have a UI, such as a dialog box, cannot display it directly in Windows Vista. Services that require user interaction must handle it indirectly. For simple interactions, services can display a message box in the user's session by calling WTSSendMessage. For more complex interactions, services must use an approach such as calling CreateProcessAsUser to create a UI process in the user's session. That process handles user interaction and communicates with the service through RPC or named pipes. For further information about Session 0 in Windows Vista and guidelines for writing Windows Vista services, see the white paper titled Impact of Session 0 Isolation on Services and Drivers in Windows Vista, which is listed in "Resources" at the end of this paper. Performance EnhancementsThe long-running nature of services means that they can have a significant impact on performance. This section discusses several enhancements to Windows Vista that reduce the impact of services on system performance. Delayed Auto-StartEarlier than Windows Vista, there were two ways to start a service: auto-start and demand-start. Auto-start services start automatically during the system's boot process. Demand-start services can be started in several ways, but they all require a client to manually restart the service. There are two primary reasons for defining a service as auto-start. · The service must be started early in the boot process because other services depend on it. · Administrators often want an unattended start for their service that does not require the presence of an interactive user. That ensures that the service is available when needed. The problem with auto-start services is that their growing numbers are having an increasing impact on the time it takes to boot the system. However, many auto-start services fall into the second of the two categories listed above. They do not have to be part of the boot sequence; they just need an unattended start so that they are available reasonably soon after the system is ready for use. Windows Vista addresses the impact of services on boot performance by providing a variant of auto-start services called delayed auto-start. Services that are designated as delayed auto-start still start automatically when the system is started up. However, they are not started during the boot sequence. Instead, they are started shortly after the system has booted. This improves boot performance while still providing these services with an unattended start. Service developers and administrators should consider the following issues before designating a service as delayed auto-start: · Understand the service's dependencies. If another service that must be started during bootup depends on the service in question, then there is no reason to set its delayed auto-start flag. The SCM will start the service during bootup, regardless of the flag setting · There is no specific time guarantee for when a delayed auto-start service starts. If a client application attempts to use a delayed auto-start service before it has been started, the attempt fails. Clients that depend on delayed auto-start services must handle the failure gracefully and either retry the attempt later or call StartService to demand-start the service. If such failures happen frequently, the service is probably not a good candidate for delayed auto-start. · Delayed auto-start services cannot belong to a load-order group. They can belong to a stand-alone group. How to Designate a Service as Delayed Auto-StartTo create a delayed auto-start service, set the delayed auto-start flag. The flag can be set for any start type, but takes effect only for auto-start services. If it is set for an auto-start service, startup is delayed until the boot sequence has finished. With the other start types, the flag is simply ignored. Sc.exe has two new commands that support delayed auto-start. · delayflag. This command changes the setting of the delayed auto-start flag. The syntax for the delayflag command is: sc server delayflag [service name] [flag] · qdelayflag. This command retrieves the setting for the delayed auto-start flag. The syntax for the qdelayflag command is: sc server qdelayflag [service name] To set the delayed auto-start flag programmatically, call ChangeServiceConfig2 with the following parameter values. The change takes effect the next time the system is booted. · Set the dwInfo parameter to SERVICE_CONFIG_DELAYED_AUTO_START_INFO. · Set the lpInfo buffer to point to a SERVICE_DELAYED_AUTO_START_INFO structure. This structure contains a single BOOL member that sets or clears the delayed auto-start flag. Note: The delayed auto-start flag can be modified only by callers with the SERVICE_CHANGE_CONFIG access right. By default, only local administrators, power users, and server operators on a domain controller get this right remotely. Services and interactive users can get the SERVICE_CHANGE_CONFIG access right locally. Service State Change NotificationsEarlier than Windows Vista, the only way for a client to determine whether a service had changed its status or been created or deleted was to use the service query API-such as the QueryServiceStatusEx function-and poll the status of the service. This was not the best approach because these polling loops reduced system performance. In addition, polling loops have historically been a significant source of bugs. Windows Vista introduces a new function, NotifyServiceStatusChange, which allows the SCM to notify a client when a specified service is created, is deleted, or changes its status. How to Have a Client Notified When a Service's State ChangesTo register for state change notifications, a client calls NotifyServiceStatusChange to specify the service and change that they want to be notified of. They also provide the SCM with a pointer to a callback function. When the specified change takes place, the SCM calls the callback function to notify the caller. The following list contains several notes on the use of NotifyServiceStatusChange. For more information, see the function's reference page, which is listed in "Resources" at the end of this paper. · NotifyServiceStatusChange can be used by local or remote clients. · The callback function is called only once. If the client wants a subsequent notification for this change, the client must call NotifyServiceStatusChange again and reregister the callback function. · The callback function is normally called after a transition to the specified state has occurred. There is an exception to this rule for the first time that the caller invokes NotifyServiceStatusChange. In that case, if the service is already in the specified state, SCM calls the callback function. · Clients can cancel the notification by calling CloseServiceHandle to close the service handle. · Clients should not exit the thread that they used to call NotifyServiceStatusChange unless the callback function has been called or they have canceled the notification. Otherwise, they will create a memory leak. · If one or more services hold open handles to a service, the service is not deleted until the next time the system is booted. If this is the case, no delete notification is sent. Note: A caller must have the SERVICE_QUERY_STATUS access right to call NotifyServiceStatusChange. By default, only administrators, power users, and server operators on a domain controller can get this right remotely. Services and interactive users can get this right locally. Other EnhancementsWindows Vista includes a number of other services enhancements, most of which improve reliability or ease of administration. Preshutdown Notifications and Shutdown OrderingEarlier than Windows Vista, the system notifies the SCM that the computer is shutting down. The SCM than has a default time of approximately 20 seconds to shut down all running services before the system terminates the SCM process (services.exe). This procedure does not always allow services to gracefully shut themselves down. When the SCM receives the shutdown notification, it in turn sends shutdown requests to every service serially, in random order. Each service has a wait hint, that specifies how long the SCM should wait before it simply shuts down the service. In practice, the SCM waits for the longest wait hint to expire and then returns to its control handler, which shuts the services down. This shutdown model creates two types of problems for services: · The shutdown order is essentially random. If a service expects other services to shut down in a particular order, it may fail to shut itself down gracefully. · Some services might not get sufficient time to clean up adequately before shutdown. This cleanup often needs to be dealt with when the service is started again, which often results in long service startup times or data inconsistencies. Windows Vista addresses these service shutdown issues in two ways: · The SCM delivers a preshutdown notification before the actual shutdown notification. The preshutdown notification gives services that have a potentially lengthy shutdown procedure more time to shut down gracefully. · Service owners that depend on the order in which other services shut down can specify any dependencies in a global dependency list. Preshutdown notifications work much like shutdown notifications. The SCM sends preshutdown notifications to the registered services in an essentially random order. After sending a notification, the SCM waits a specified amount of time for the service to stop before assuming that the service will not respond. By default, the wait time is 3 minutes, but services can configure their wait time to match their particular requirements. For more information, see Service Control Handler Function in "Resources" at the end of this paper. Services can specify shutdown dependencies in a global dependency list. Before shutting down a service, the SCM attempts to first shut down the dependent services. To take advantage of this feature, a service must be registered for a preshutdown notification. If a service specifies dependencies, the shutdown process takes place synchronously. Suppose, for example, a service specifies a shutdown dependency on services "A," "B," and "C," in that order. The SCM sends the notification to "A" first and waits for it to either stop or timeout. Then the SCM sends a notification to "B," and so on. If any of the specified services fail to stop correctly or are not registered for preshutdown notifications, the SCM simply proceeds to the next service. How to Register for a Preshutdown NotificationA service registers for preshutdown notifications by setting SERVICE_ACCEPT_PRESHUTDOWN in their status block. Preshutdown notifications are sent only to running services that have registered for the notification. They are not sent to services that are in the SERVICE_STOPPED or SERVICE_STOP_PENDING states. To set the timeout value, services call ChangeServiceConfig2 with the following parameter settings: · dwInfoLevel. Set this parameter to SERVICE_CONFIG_PRESHUTDOWN_INFO. · lpInfo. Set this buffer to point to a SERVICE_PRESHUTDOWN_INFO structure with its dwPreshutdownTimeout member set to the timeout value, in milliseconds. How to Specify Shutdown DependenciesTo specify shutdown dependencies, create a multistring value that contains the service names in the order that they should be shut down and assign it to the Control key's PreshutdownOrder value, as follows: HKEY_LOCAL_MACHINE System CurrentControlSet Control PreshutdownOrder="Shutdown Order" Failure Detection and RecoveryIf a service fails, the SCM can perform a failure action, such as restarting the service in an attempt to recover from that failure. Earlier than Windows Vista, the definition of service failure was limited to the process crashing in any state other than SERVICE_STOPPED. With Windows Vista, a service doesn't have to crash to have the SCM initiate a failure action. Services can notify the SCM to initiate a failure action if they discover a nonfatal error condition such as a serious memory leak. How to Configure a Failure ActionThe SCM initiates failure actions only for those service that have explicitly specified them. The most common failure action is "restart the service." This action requires two values: · The recovery interval is the time in milliseconds that the SCM waits before starting the recovery action. · The reset period is the time in seconds after the last failure that the SCM waits before resetting the failure count to 0. One way to configure failure actions is with sc.exe. The following example shows typical syntax: sc.exe "failure" option, reset=300, actions=restart/60000/restart/120000/restart/none This command notifies the SCM to: · Wait 60 seconds following the first failure before restarting the service. · Wait 120 seconds following the second failure before restarting the service. · Not restart the service after the third failure. Another common action at this point would be to reboot the system. In that case, replace "restart/none" with "reboot/reboot_interval", where reboot_interval specifies how long the SCM should wait before rebooting. 60000 is a typical value for reboot_interval. · Reset the failure count to 0 after 300 seconds of successful operation. If reset is set to INFINITE, the failure count is never reset. To configure a failure action programmatically, call ChangeServiceConfig2 with the following parameter values. The change takes effect the next time the system is booted: · Set the dwInfo parameter to SERVICE_CONFIG_FAILURE_ACTIONS. · Set the lpInfo buffer to point to a SERVICE_FAILURE_ACTIONS structure. This structure contains several members that are used specify the failure action. How to Notify the SCM to Initiate a Failure ActionWindows Vista introduces a new flag, FailureActionsOnNonCrashFailures, which services set if they want to be able to notify the SCM to initiate a failure action. · Set FailureActionsOnNonCrashFailures to the default value of 0 to use the model that is earlier than Windows Vista. The SCM queues a failure action for the service only if the service's process crashes when the service is not in the SERVICE_STOPPED state. · Set FailureActionsOnNonCrashFailures to 1 to enable a service to notify the SCM to initiate failure actions: · A service notifies the SCM to queue a failure action by entering the SERVICE_STOPPED state and setting SetServiceExitCode function's dwWin32ExitCode parameter to anything other than ERROR_SUCCESS. · If the service's process crashes when the service is not in the SERVICE_STOPPED state, the SCM follows the pre-Windows Vista failure model and queues a failure action for the service. Note: For the FailureActionsOnNonCrashFailures flag to have any effect, the service must have failure actions configured. Sc.exe has two new commands to enable configuration of the FailureActionsOnNonCrashFailures setting: · failureflag. This command changes the setting of the FailureActionsOnNonCrashFailures flag. The syntax for the failureflag command is: sc server failureflag [service name] [flag] · qfailureflag. This command retrieves the setting for the FailureActionsOnNonCrashFailures flag. The syntax for the qfailureflag command is: sc server -qfailureflag [service name] To set the FailureActionsOnNonCrashFailures flag programmatically, call ChangeServiceConfig2 with the following parameter values. The change takes effect the next time the system is booted: · Set the dwInfo parameter to SERVICE_CONFIG_FAILURE_ACTIONS_FLAG. · Set the lpInfo buffer to point to a SERVICE_FAILURE_ACTIONS_FLAG structure. This structure contains a single BOOL member, fFailureActionsOnNonCrashFailures that sets or clears the failure-actions flag. Note: The FailureActionsOnNonCrashFailures flag can be modified only by callers with the SERVICE_CHANGE_CONFIG access right. By default, only local administrators, power users, and server operators on a domain controller can get this right remotely. Services and interactive users can get the SERVICE_CHANGE_CONFIG access right locally. The following links provide further information about Windows services and related topics. MSDN Windows Services Documentation http://go.microsoft.com/fwlink/?LinkId=71274 Impact of Session 0 Isolation on Services and Drivers in Windows Vista http://go.microsoft.com/fwlink/?LinkId=71275 Internet Connection Sharing and Internet Connection Firewall http://go.microsoft.com/fwlink/?LinkId=71277 NotifyServiceStatusChange http://go.microsoft.com/fwlink/?LinkId=71279 Service Control Handler Function
| ||||||||||||||||||||||||||||||||||||||||