Controlling Network Access


In the new firewalling API we covered in Chapter 4, there are some additional capabilities we can apply to services. One of the drawbacks of the previous firewall capabilities is that permissions can be set either globally or on a per-application basis. If your service binary is uniquely named, that may not be a problem, but if your base application is svchost.exe, then this can lead to excessive permissions–on my system there are 11 svchost.exe processes running, and some of them are hosting as many as 20 services.

If you’re familiar with COM, the firewalling API is relatively easy to use. There are only three methods exposed by the INetFwServiceRestriction interface, defined in NetFw.h. There are a few differences that are worth pointing out, especially considering that all of the examples in the SDK are in VB script. First of all, in the older firewalling API, you first create a NetFwMgr object, and call get_LocalPolicy to obtain a INetFwPolicy interface. One might (erroneously) think that you could obtain an INetFwPolicy2 interface from the NetFwMgr object, or perhaps call QueryInterface on an INetFwPolicy object to get the interface pointer. Because the SDK doesn’t currently document just how you might get an INetFwPolicy2 pointer, you could try a number of approaches–this author did. As it turns out, the critical clue is in the header, where you’ll find a CLSID defined for INetFwPolicy2. Here’s what the code looks like:

 INetFwPolicy2* pFwPolicy2 = NULL; hr = CoCreateInstance( __uuidof(NetFwPolicy2),                        NULL, CLSCTX_INPROC_SERVER,                        IID_INetFwPolicy2,                        (void**)&pFwPolicy2 );

Once you have an INetFwPolicy2 pointer, the next step is to get an INetFwServiceRestriction pointer that will give access to the following methods:

  • RestrictService–enable or disable service networking restrictions

  • ServiceRestricted–queries if the service is restricted or not

  • get_Rules–obtains the rule set that applies to the service

Here’s how you can use these methods:

 INetFwServiceRestriction* pSvcRestrict = NULL; if( SUCCEEDED( pFwPolicy2->get_ServiceRestriction( &pSvcRestrict ) ) ) {    // Call methods here    pSvcRestrict->Release(); }

The first two methods are fairly easy to manage:

 hr = pSvcRestrict->RestrictService( SvcName, AppPath,                                     VARIANT_TRUE, VARIANT_TRUE ); if( SUCCEEDED( hr ) )      printf( "RestrictService succeeded\n" ); VARIANT_BOOL fRestricted; hr = pSvcRestrict->ServiceRestricted( SvcName, AppPath, &fRestricted ); if( SUCCEEDED( hr ) )      printf( "Service is %srestricted\n", fRestricted ? "" : "not" ); else      printf( "ServiceRestricted failed - err = %x\n", hr );

Remember that both SvcName and AppPath are BSTR types and will need to be initialized with SysAllocString and freed with SysFreeString. If your application isn’t running with the administrator group enabled, RestrictService will fail with access denied, but the system does nicely allow you read access when running as an ordinary user.

If you happen to already be familiar with the IEnumVARIANT type, dealing with the firewall rules is no problem, but if you aren’t, here’s how it works:

 INetFwRules* pFwRules = NULL; hr = pSvcRestrict->get_Rules( &pFwRules ); if( SUCCEEDED( hr ) ) {      long iCount = 0;      hr = pFwRules->get_Count( &iCount );      if( SUCCEEDED( hr ) )         printf( "There are %d rules\n", iCount );      IEnumVARIANT* pEnum = NULL;      hr = pFwRules->get__NewEnum( ((IUnknown**)&pEnum) );      if( SUCCEEDED( hr ) )      {         VARIANT Var;         long i;         for( i = 0; i < iCount; i++ )         {             hr = pEnum->Next( 1, &Var, NULL );             if( SUCCEEDED( hr ) )             {                INetFwRule* pRule = NULL;                // Some error checking omitted for clarity                IUnknown* pIu = (IUnknown*)Var.ppunkVal;                hr = pIu->QueryInterface( __uuidof( INetFwRule ),                                            (void**)&pRule );                BSTR desc;                hr = pRule->get_Description( &desc );                printf("Rule %d: %S\n", i, (WCHAR*)desc );                pRule->Release();             }        }     } pEnum->Release(); }

This starts out simply: you just call get_Rules to get an INetFwRules interface, and we can then straightforwardly get the number of rules. Once you have the count, you can then acquire your IEnumVARIANT pointer. The tricky bit is remembering that you have to use the ppunkVal member of the VARIANT structure and then call QueryInterface to get access to the firewall rule itself. Here’s what some sample output looks like:

 Service is restricted There are 2 rules Rule 0: Block all outbound traffic from service VistaService Rule 1: Block all inbound traffic to service VistaService

Our sample service has no business wandering around opening random sockets and doing silly things, so the default rule set works quite nicely. If your service needs to do something more complex, we covered managing rule sets in Chapter 4.



Writing Secure Code for Windows Vista
Writing Secure Code for Windows Vista (Best Practices (Microsoft))
ISBN: 0735623937
EAN: 2147483647
Year: 2004
Pages: 122

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net