In Windows Vista there is a new method for categorizing both Winsock Layered Service Providers (LSP) and applications themselves such that only certain LSPs will be loaded. There are a couple reasons for adding this functionality. One of the main reasons is certain system critical processes such as WinLogon and LSASS create sockets but do not send any traffic on the network so most LSPs should not be loaded. A large percentage of the crashes we see are due to buggy LSPs that cause LSASS.EXE to crash and if it crashes the system forces a shutdown. A side affect of these system processes loading LSPs is that these processes never exit so when an LSP is installed or removed, a reboot is required.
Secondly, there are some cases where applications may not want to load certain LSPs. For example, some apps may not want to load crypto LSPs so they can communicate with other machines that do not have the cypto LSP installed.
Finally, the LSP categories can be used by other LSPs to determine where in the Winsock protocol chain they should install themselves. For years, various LSP developers have wanted a way of knowing how an LSP will behave. For example, an LSP that inspects the data stream would want to be above an LSP that encrypts the data. Of course, this method isn’t fool proof since it relies on 3rd party LSPs to categorize themselves appropriately, but hopefully, the security enhancements in Vista will help prevent users from unintentionally installing malicious LSPs.
Winsock has defined nine different types of LSPs:
Note that it is possible to categorize an LSP as more than one type. In fact an LSP categorized as LSP_SYSTEM should also be categorized with the type(s) that best describe how it inspects or modifies the Winsock calls.
On Vista , the majority of the system critical processes and system services are already registered with the appropriate categories depending on their functionality.
Categorizing LSPs
There are two new APIs for categorizing an LSP which are defined in ws2spi.h:
int
WSPAPI
WSCSetProviderInfo(
LPGUID lpProviderId,
WSC_PROVIDER_INFO_TYPE InfoType,
PBYTE Info,
size_t InfoSize,
DWORD Flags,
LPINT lpErrno
);
WSCGetProviderInfo(
size_t *InfoSize,
In order to categorize an LSP, WSCSetProviderInfo is called that specifies the GUID of the hidden LSP entry (i.e. the LSP entry installed whose ProtocolChain.ChainLen is zero). The WSC_PROVIDER_INFO_TYPE is an enumeration and ProviderInfoLspCategories should be passed. Then a simple DWORD with the appropriate LSP_* flags above is passed as the Info parameter. For example:
DWORD lspCategory = LSP_INBOUND_MODIFY | LSP_OUTBOUND_MODIFY;
GUID lspGuid = &YOUR_LSP_GUID;
int rc, err;
rc = WSCSetProviderInfo( &lspGuid, ProviderInfoLspCategories,
(PBYTE) &lspCategory, sizeof(lspCategory), 0, &err);
Retrieving the LSP category is similar to setting it but using the WSCGetProviderInfo call.
Categorizing Applications
The other part of the equation is categorizing applications themselves to specify those LSPs that should be loaded in its process. This is done via the following two functions also defined in ws2spi.h:
WSCSetApplicationCategory(
LPCWSTR Path,
DWORD PathLength,
LPCWSTR Extra,
DWORD ExtraLength,
DWORD PermittedLspCategories,
DWORD * pPrevPermLspCat,
WSCGetApplicationCategory(
DWORD * pPermittedLspCategories,
In the functions above Path is the full path and executable name while Extra is the arguments passed to that application. The Path argument can contain environment variables as the function calls will expand them as necessary. Note that an application is defined as the full path and executable name as well as any arguments. Thus if the application “c:\foo.exe” is categorized as LSP_PROXY, the application “c:\foo.exe –x 12” is different and would not be considered as allowing LSP_PROXY LSPs.
The following code categorizes “foo.exe –x 12”:
rc = WSCSetApplicationCategory(
L”%windir%\\foo.exe”,
lstrlenW(L”%windir%\\foo.exe”),
L”-x 12”,
lstrlenW(L”-x 12”),
LSP_SYSTEM | LSP_FIREWALL | LSP_CRYPTO_COMPRESS,
NULL,
&err
The pPrevPermLspCat parameter is optional and simply returns the previous categories set for this application if it existed.
Determining Which LSPs Get Loaded
The final part of LSP categorization is determining which LSPs will be loaded into which processes. When a process loads Winsock, both the application category and the LSP categories for all installed LSPs and the following comparisons made:
NOTE: If an LSP is not categorized its category is effectively 0. Basically, for a match to occur all the LSP’s specified categories must be present in the application’s categories (i.e. the app must be a superset of the LSP) – with the caveat that if LSP_SYSTEM is present in the app’s category is must also be present in the LSP’s category.
Consider the following example:
Foo.exe is categorized as LSP_SYSTEM + LSP_FIREWALL + LSP_CRYPTO_COMPRESS
Bar.exe is categorized as LSP_FIREWALL + LSP_CRYPTO_COMPRESS
There are four LSPs installed on the system:
LSP1: LSP_SYSTEM
LSP2: 0 (no category set)
LSP3: LSP_FIREWALL
LSP4: LSP_SYSTEM + LSP_FIREWALL + LSP_CRYPTO_COMPRESS + LSP_INSPECTOR
In this example, Foo.exe would only load LSP1 while Bar.exe would load LSP3.
--Anthony Jones (AJones)