WS-Management is a new web services-based management protocol. It's SOAP-based of course, and it is compatible with the rest of the specifications in the WS-* Web Service stack, like WS-Transfer, WS-Enumeration, WS-Addressing.

WS-Management is enabled in Vista (and Longhorn Server) in several ways.

  • On the client side, you have a standard library (called WinRM) which can "consume" other WS-Management enabled interfaces. You could also use Indigo, or other web service frameworks to access the same services as well. Finally, there is a command-line tool also named WINRM which can be used to communicate with WS-Management enabled servers.
  • On the server side, any WMI class can be made remotely accessible through WS-Management.

Security

WS-Management is securely enabled on Vista machines. To find out the security configuration of your machine (both for client and server) you can use WS-Management itself like in the command below:

C:\>winrm get winrm/config
Config
    MaxEnvelopeSizekb = 150
    MaxTimeoutms = 60000
    MaxBatchItems = 20
    MaxProviderRequests = 25
    Client
        NetworkDelayms = 5000
        URLPrefix = wsman
        AllowUnencrypted = false
        Auth
            Basic = false
            Digest = true
            Kerberos = true
            Negotiate = true

        DefaultPorts
            HTTP = 80
            HTTPS = 443
        TrustedHosts
    Service
        RootSDDL = O:NSG:BAD:P(A;;GA;;;BA)(A;;GR;;;ER)S:P(AU;FA;GA;;;WD)(AU;SA;GWGX;;;WD)
        MaxConcurrentOperations = 100
        EnumerationTimeoutms = 60000
        MaxConnections = 5
        AllowUnencrypted = false
        Auth
            Basic = false
            Kerberos = true
            Negotiate = true

        DefaultPorts
            HTTP = 80
            HTTPS = 443
        IPv4Filter = *
        IPv6Filter = *
    Winrs
        AllowRemoteShellAccess = true
        IdleTimeout = 900000
        MaxConcurrentUsers = 5
        MaxShellRunTime = 28800000
        MaxProcessesPerShell = 5
        MaxMemoryPerShellMB = 80
        MaxShellsPerUser = 2

By default, WS-Management is not enabled for remote access, Windows authentication is used by default on local acceess, and encryption is turned on.

You can enable remote access by typing:

C:\>winrm quickconfig
WinRM is not set up to allow remote access to this machine for management.
The following changes must be made:

Set the WinRM service type to delayed auto start.
Start the WinRM service.
Create a WinRM listener on HTTP://* to accept WS-Man requests to any IP on this machine.
Enable the WinRM firewall exception.

Make these changes [y/n]? y

WinRM has been updated for remote management.

WinRM service type changed successfully.
WinRM service started.
Created a WinRM listener on HTTP://* to accept WS-Man requests to any IP on this machine.
WinRM firewall exception enabled.

The output above already illustrates one main advantages of web services - their flexibility with respect to firewall access. Say that you want to enable your current machine to accept incoming WS-Management SOAP requests through the port 80 (as HTTP requests). Then, all you need to do is opening port 80 and that's it! Also, NAT is not a problem, of course.

Try this type of exercise when enabling DCOM through the firewall, and you'll have nightmares. This can get really complicated. Furthermore, DCOM doesn't really work in NAT environments.

A simple example

At this point, you have a secure web service enabled on your machine, that you can then use to perform regular management queries, in WMI style. Let's get some information about a Windows service, like the status of the Spooler service.  

Note that I am doing a remote query - basically contacting the machine AOLTEAN-D2, through an internal, WS-Management web service interface:

C:\>winrm get wmicimv2/Win32_Service?Name=spooler -r:aoltean-d2
Win32_Service
    AcceptPause = false
    AcceptStop = true
    Caption = Print Spooler
    CheckPoint = 0
    CreationClassName = Win32_Service
    Description = Loads files to memory for later printing
    DesktopInteract = true
    DisplayName = Print Spooler
    ErrorControl = Normal
    ExitCode = 0
    InstallDate = null
    Name = spooler
    PathName = C:\Windows\System32\spoolsv.exe
    ProcessId = 1472
    ServiceSpecificExitCode = 0
    ServiceType = Own Process
    Started = true
    StartMode = Auto
    StartName = LocalSystem
    State = Running
    Status = OK
    SystemCreationClassName = Win32_ComputerSystem
    SystemName = AOLTEAN-D2
    TagId = 0
    WaitHint = 0

Well, it looks like the spooler service is started. We can perform even more complicated queries, such as this one, to find the list of stopped services which are supposed to be started:

C:\trace>winrm enumerate wmicimv2/* -filter:"select * from win32_service where StartMode=\"Auto\" and State = \"Stopped\" " -r:aoltean-d2

XmlFragment
    Win32_Service
        AcceptPause = false
        AcceptStop = false
        Caption = Media Center Service Launcher
        CheckPoint = 0
        CreationClassName = Win32_Service
        Description = Starts Media Center Scheduler and Media Center Receiver services at startup if TV is enabled within Media Center.
        DesktopInteract = false
        DisplayName = Media Center Service Launcher
        ErrorControl = Ignore
        ExitCode = 0
        InstallDate = null
        Name = ehstart
        PathName = C:\Windows\system32\svchost.exe -k LocalServiceNoNetwork
        ProcessId = 0
        ServiceSpecificExitCode = 0
        ServiceType = Share Process
        Started = false
        StartMode = Auto
        StartName = NT AUTHORITY\LocalService
        State = Stopped
        Status = OK
        SystemCreationClassName = Win32_ComputerSystem
        SystemName = AOLTEAN-D2
        TagId = 0
        WaitHint = 0

So, where does WS-Management comes into play? At its roots, WS-Management is a simple management protocol that allows us to operate with resources. WS-Management defines a few operations on these resources:

  1. Get resource properties - this is used by the "winrm get ..." command above. We can see that we interrogate here a resoure (the "spooler" Windows service) and we obtain various properties like PathName, Started, etc.
  2. Enumerate resources - this is a more complex command that allows us to enumerate several resources at once
  3. Set properties on a resource
  4. Create or delete resources
  5. Execute methods on a resource, just like WMI methods.

In some sense, resources can be viewed as "objects" in OOP point of view, and WS-Management defines a simple protocol to manipulate these "objects".

Under the hood

So where do web services come into play? Can we peek into the actual management protocol?

With web services, it is actually easy - all we need to do is to use a network protocol analyzer to sniff the HTTP packets between client and the server. Ultimately, web service interactions are nothing more than exchanging XML packets using HTTP/HTTPS, so analyzing these interactions is no more difficult than analyzing HTTP request/response commands between a browser and a web server.

Let's take the GET command above (winrm get wmicimv2/Win32_Service?Name=spooler -r:aoltean-d2). In our case, the client program attempts to get the properties of a given resource of type "wmicimv2/Win32_Service", identified by the selector "Name=spooler".

Let's dive in. With the network sniffer we obtain the following SOAP request message:

<s:Envelope
 xmlns:s="http://www.w3.org/2003/05/soap-envelope"
 xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing"
 xmlns:w="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd">
  <s:Header>
    <a:To>http://aoltean-d2:80/wsman</a:To>
    <w:ResourceURI s:mustUnderstand="true">http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/Win32_Service</w:ResourceURI>
    <a:ReplyTo>
      <a:Address s:mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address>
    </a:ReplyTo>
    <a:Action s:mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/09/transfer/Get</a:Action>
    <w:MaxEnvelopeSize s:mustUnderstand="true">153600</w:MaxEnvelopeSize>
    <a:MessageID>uuid:2A553640-AA45-4BE1-8CE8-C3F20BD3C74E</a:MessageID>
    <w:Locale xml:lang="en-US" s:mustUnderstand="false" />
    <w:SelectorSet>
      <w:Selector Name="Name">spooler</w:Selector>
    </w:SelectorSet>
    <w:OperationTimeout>PT60.000S</w:OperationTimeout>
  </s:Header>
  <s:Body></s:Body>
</s:Envelope>

Correspondingly, the WS-Man response packet looks like this:

<s:Envelope xml:lang="en-US" xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:w="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd">
  <s:Header>
    <a:Action  >http://schemas.xmlsoap.org/ws/2004/09/transfer/GetResponse</a:Action>
    <a:MessageID  >uuid:3E0BE062-2615-497E-BE6A-2FC7D5B7C9C3</a:MessageID>
    <a:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:To>
    <a:RelatesTo  >uuid:2A553640-AA45-4BE1-8CE8-C3F20BD3C74E</a:RelatesTo>
  </s:Header>
  <s:Body>
    <p:Win32_Service xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/Win32_Service" xmlns:cim="http://schemas.dmtf.org/wbem/wsman/1/base" xsi:type="Win32_Service">
      <p:AcceptPause>false</p:AcceptPause>
      <p:AcceptStop>true</p:AcceptStop>
      <p:Caption>Print Spooler</p:Caption>
      <p:CheckPoint>0</p:CheckPoint>
      <p:CreationClassName>Win32_Service</p:CreationClassName>
      <p:Description>Loads files to memory for later printing</p:Description>
      <p:DesktopInteract>true</p:DesktopInteract>
      <p:DisplayName>Print Spooler</p:DisplayName>
      <p:ErrorControl>Normal</p:ErrorControl>
      <p:ExitCode>0</p:ExitCode>
      <p:InstallDate xsi:nil="true"/>
      <p:Name>spooler</p:Name>
      <p:PathName>C:\Windows\System32\spoolsv.exe</p:PathName>
      <p:ProcessId>1596</p:ProcessId>
      <p:ServiceSpecificExitCode>0</p:ServiceSpecificExitCode>
      <p:ServiceType>Own Process</p:ServiceType>
      <p:Started>true</p:Started>
      <p:StartMode>Auto</p:StartMode>
      <p:StartName>LocalSystem</p:StartName>
      <p:State>Running</p:State>
      <p:Status>OK</p:Status>
      <p:SystemCreationClassName>Win32_ComputerSystem</p:SystemCreationClassName>
      <p:SystemName>AOLTEAN-D2</p:SystemName>
      <p:TagId>0</p:TagId>
      <p:WaitHint>0</p:WaitHint>
    </p:Win32_Service>
  </s:Body>
</s:Envelope>

That's it for now. I hope that in a future post I will cover the actual structure of WS-Management messages.