Documente online.
Zona de administrare documente. Fisierele tale
Am uitat parola x Creaza cont nou
 HomeExploreaza
upload
Upload




Best Practices for Layered Service Provider (LSP) Development in Windows

windows en



Best Practices for Layered Service Provider (LSP) Development in Windows



Microsoft Confidential. © 2004 Microsoft Corporation. All rights reserved. These materials are confidential to and maintained as a trade secret by Microsoft Corporation. Information in these materials is restricted to Microsoft authorized recipients only. Any use, distribution or public discussion of, and any feedback to, these materials is subject to the terms of the attached license. By providing any feedback on these materials to Microsoft, you agree to the terms of that license.

Microsoft Corporation Technical Documentation License Agreement (Standard)
READ THIS! THIS IS A LEGAL AGREEMENT BETWEEN MICROSOFT CORPORATION ("MICROSOFT") AND THE RECIPIENT OF THESE MATERIALS, WHETHER AN INDIVIDUAL OR AN ENTITY ("YOU"). IF YOU HAVE ACCESSED THIS AGREEMENT IN THE PROCESS OF DOWNLOADING MATERIALS ("MATERIALS") FROM A MICROSOFT WEB SITE, BY CLICKING "I ACCEPT", DOWNLOADING, USING OR PROVIDING FEEDBACK ON THE MATERIALS, YOU AGREE TO THESE TERMS. IF THIS AGREEMENT IS ATTACHED TO MATERIALS, BY ACCESSING, USING OR PROVIDING FEEDBACK ON THE ATTACHED MATERIALS, YOU AGREE TO THESE TERMS.

1. For good and valuable consideration, the receipt and sufficiency of which are acknowledged, You and Microsoft agree as follows:

(a) If You are an authorized representative of the corporation or other entity designated below ("Company"), and such Company has executed a Microsoft Corporation Non-Disclosure Agreement that is not limited to a specific subject matter or event ("Microsoft NDA"), You represent that You have authority to act on behalf of Company and agree that the Confidential Information, as defined in the Microsoft NDA, is subject to the terms and conditions of the Microsoft NDA and that Company will treat the Confidential Information accordingly;

(b) If You are an individual, and have executed a Microsoft NDA, You agree that the Confidential Information, as defined in the Microsoft NDA, is subject to the terms and conditions of the Microsoft NDA and that You will treat the Confidential Information accordingly; or

(c)If a Microsoft NDA has not been executed, You (if You are an individual), or Company (if You are an authorized representative of Company), as applicable, agrees: (a) to refrain from disclosing or distributing the Confidential Information to any third party for five (5) years from the date of disclosure of the Confidential Information by Microsoft to Company/You; (b) to refrain from reproducing or summarizing the Confidential Information; and (c) to take reasonable security precautions, at least as great as the precautions it takes to protect its own confidential information, but no less than reasonable care, to keep confidential the Confidential Information. You/Company, however, may disclose Confidential Information in accordance with a judicial or other governmental order, provided You/Company either (i) gives Microsoft reasonable notice prior to such disclosure and to allow Microsoft a reasonable opportunity to seek a protective order or equivalent, or (ii) obtains written assurance from the applicable judicial or governmental entity that it will afford the Confidential Information the highest level of protection afforded under applicable law or regulation. Confidential Information shall not include any information, however designated, that: (i) is or subsequently becomes publicly available without Your/Company's breach of any obligation owed to Microsoft; (ii) became known to You/Company prior to Microsoft's disclosure of such information to You/Company pursuant to the terms of this Agreement; (iii) became known to You/Company from a source other than Microsoft other than by the breach of an obligation of confidentiality owed to Microsoft; or (iv) is independently developed by You/Company. For purposes of this paragraph, "Confidential Information" means nonpublic information that Microsoft designates as being confidential or which, under the circumstances surrounding disclosure ought to be treated as confidential by Recipient. "Confidential Information" includes, without limitation, information in tangible or intangible form relating to and/or including released or unreleased Microsoft software or hardware products, the marketing or promotion of any Microsoft product, Microsoft's business policies or practices, and information received from others that Microsoft is obligated to treat as confidential. 

2. You may review these Materials only (a) as a reference to assist You in planning and designing Your product, service or technology ("Product") to interface with a Microsoft Product as described in these Materials; and (b) to provide feedback on these Materials to Microsoft. All other rights are retained by Microsoft; this agreement does not give You rights under any Microsoft patents. You may not (i) duplicate any part of these Materials, (ii) remove this agreement or any notices from these Materials, or (iii) give any part of these Materials, or assign or otherwise provide Your rights under this agreement, to anyone else.

3. These Materials may contain preliminary information or inaccuracies, and may not correctly represent any associated Microsoft Product as commercially released. All Materials are provided entirely "AS IS." To the extent permitted by law, MICROSOFT MAKES NO WARRANTY OF ANY KIND, DISCLAIMS ALL EXPRESS, IMPLIED AND STATUTORY WARRANTIES, AND ASSUMES NO LIABILITY TO YOU FOR ANY DAMAGES OF ANY TYPE IN CONNECTION WITH THESE MATERIALS OR ANY INTELLECTUAL PROPERTY IN THEM.

4. If You are an entity and (a) merge into another entity or (b) a controlling ownership interest in You changes, Your right to use these Materials automatically terminates and You must destroy them.

5. You have no obligation to give Microsoft any suggestions, comments or other feedback ("Feedback") relating to these Materials. However, any Feedback you voluntarily provide may be used in Microsoft Products and related specifications or other documentation (collectively, "Microsoft Offerings") which in turn may be relied upon by other third parties to develop their own Products. Accordingly, if You do give Microsoft Feedback on any version of these Materials or the Microsoft Offerings to which they apply, You agree: (a) Microsoft may freely use, reproduce, license, distribute, and otherwise commercialize Your Feedback in any Micro 22322d318w soft Offering; (b) You also grant third parties, without charge, only those patent rights necessary to enable other Products to use or interface with any specific parts of a Microsoft Product that incorporate Your Feedback; and (c) You will not give Microsoft any Feedback (i) that You have reason to believe is subject to any patent, copyright or other intellectual property claim or right of any third party; or (ii) subject to license terms which seek to require any Microsoft Offering incorporating or derived from such Feedback, or other Microsoft intellectual property, to be licensed to or otherwise shared with any third party.

6. Microsoft has no obligation to maintain confidentiality of any Microsoft Offering, but otherwise the confidentiality of Your Feedback, including Your identity as the source of such Feedback, is governed by Your NDA.

7. This agreement is governed by the laws of the State of Washington. Any dispute involving it must be brought in the federal or state superior courts located in King County, Washington, and You waive any defenses allowing the dispute to be litigated elsewhere. If there is litigation, the losing party must pay the other party's reasonable attorneys' fees, costs and other expenses. If any part of this agreement is unenforceable, it will be considered modified to the extent necessary to make it enforceable, and the remainder shall continue in effect. This agreement is the entire agreement between You and Microsoft concerning these Materials; it may be changed only by a written document signed by both You and Microsoft.


Abstract

This document describes the best practices for developing LSPs for Windows. These best practices describe the recommended model, API usage and development tools for LSP development; functionality and other requirements that a good LSP must meet as well as general dos and donts for LSPs. By following the guidelines in this document, it is expected that LSP ISVs will be able to reduce the time for their LSP development while improving the code quality. The quality improvements will result in increased revenue as a result of increased sales as well as a reduction in support costs.

The intended audience for this document is developers and project managers.

Contents

Introduction

Goal and scope of document

Write an IFS based LSP

What are IFS and non-IFS LSPs?

How to write an IFS based LSP?   

Benefits and Limitations of an IFS based LSP   

When is a non-IFS based LSP needed?   

LSP install & uninstall

Use New Install Atomic API

User Account Control (UAC) Considerations   

Support all extension functions

Supporting functions which accept multiple socket handles   

Potential Problems

LSP Bypass Mode

Intercepting Select Function Calls

Properly layer in Winsock catalog

LSP Interoperability

Selecting Base Service Providers to Layer Over   

LSP Categorization

Overview

LSP Types

Categorizing an LSP

Categorizing an Application

Determining Which LSPs Are Loaded

Sample LSP Implementation

Summary

Resources

Figures

Introduction

Windows provides a standard Application Programming Interface (API) called Winsock that allows two or more applications (or processes) to communicate with each other on the same machine or across a network. Winsock 2 in addition, also provides a Service Provider Interface (SPI) that allows inspection of all Winsock calls by third-party service providers thereby, enabling them to offer services to Winsock applications. Service providers do not require application developers to rewrite their code or to replace the Winsock 2 DLL (ws2_32.dll) to provide service to Winsock applications.

There are two types of service providers that can be implemented using SPI: transport service providers and name space service providers. Transport providers provide data communication services, such as setting up connections, transferring data, error control, and so on. Namespace providers provide naming services that enable association of the protocol addresses with one or more human-friendly names and enable protocol-independent name resolution. The SPI allows two types of transport service providers-base and layered service providers. While base providers implement the actual details of a transport protocol like TCP/IPv4, Layered Service Providers (LSPs) implement only higher-level custom communication functions and rely on an existing underlying base provider for the actual data exchange with a remote endpoint. Further, Winsock 2 SPI is very flexible, in that, it allows these LSPs to be layered on top of each other (and hence the name). This is done by having an LSP mimic or extends an existing provider. LSPs are layered on top of BSPs. Winsock maintains a catalog of all the installed LSPs and BSPs and how they are layered on top of each other. A Winsock application obtains the services of installed service providers on a host without necessarily being aware of the underlying service providers. These service providers may provide services like encryption, proxy or content filtering.

When a Winsock application makes a Winsock call, the system routes that call into the topmost LSP installed on the system. At that point, the LSP can perform its necessary tasks. It then, passes the request to the provider below itself. Ultimately the call reaches the base provider and gets handed over to the protocol drivers available on the host. Figure 1 shows a very simple architecture diagram for Winsock.

Goal and scope of document

The goal of this document is to share common knowledge in developing LSPs and provide best practices followed LSP development. The motivation being, by following these best practices, common pitfalls in LSP development will be avoided and a higher quality code will be developed. This will not only help reduce the time for development but also reduce the support costs associated with supporting a poorly written LSP. This document describes the recommended model, API usage and tools for LSP development; functionality and other requirements that a good LSP must meet as well as general dos and donts for LSPs.

This document only describes the best practices that apply to LSPs specifically. General best practices for software development on Windows are not captured in this document. Also, the best practices described in this document capture the common and useful practices that we have observed across a number a LSPs. There may be other best practices specifically targeted towards a particular scenario for LSPs that are not captured here. The decision to write an LSP or use alternative mechanisms available in Windows such as filter drivers is also outside the scope of this document. Further, the best practices suggested in this document may not be applicable in all environments and an LSP author may have to deviate from these for their specific scenario.

Write an IFS based LSP

Winsock SPI enables two different models of LSPs: Installable File System LSPs (or IFS LSP) and the non Installable File System LSPs (or non-IFS LSP). These two models for LSP development have been available since Windows 2000 and before. However, Microsoft has only provided sample code for a non-IFS based LSP and this has resulted in proliferation of non-IFS LSPs. As we discuss in sections below, a non-IFS based LSP is more complex and not the recommended model for LSP development. An IFS based LSP is much easier to develop and much smaller and is the recommended model for LSP development. Below we discuss this further.

What are IFS and non-IFS LSPs?

To understand what are IFS and non-IFS LSPs, one needs to understand about socket handles. Windows implements a file system known as Installable File System (IFS). An IFS handle is a file handle returned by IFS and can be used in file I/O operations. Socket handles can be either IFS handles or not. When a socket has an IFS handle, it can be used in file I/O functions to perform Winsock recv and send calls. On Windows NT and above, IFS handles can be added to I/O completion ports (IOCP) to achieve scalability.

Whenever an application creates a socket to a transport service, a socket handle gets created by the BSP providing that transport service and is passed through the various LSPs layered on that BSP. The LSP can either directly pass the socket handle back to the application or instead create a new socket handle and pass this new socket handle up to the LSP layered on top of it (or ws2_32.dll if it is the topmost LSP). If an LSP creates a new socket handle, it has to maintain an association list of the socket handles retrieved from the LSP below (or base provider if the LSP is the bottommost LSP) and the socket handles returned to the LSP above (or ws2_32.dll if the LSP is the topmost LSP). This allows an LSP to find the corresponding lower layer socket given a socket handle for this layer and ensures proper closure of all base socket handles when an LSP is unloaded. The ws2_32.dll in turn, keeps an association list of socket handles retrieved from an LSP and the socket handles returned to user applications.

All Microsoft base providers implement sockets as IFS handles (providers with IFS handles indicate this via the XP1_IFS_HANDLES attribute bit in the dwServiceFlags1 field of the WSAPROTOCOL_INFOW structure). An LSP cannot create socket handles that are true IFS handles since LSP will have to implement IFS for that (which would require a kernel mode driver). An IFS LSP is one that uses IFS handles. Since an LSP cannot create a true IFS handle by itself, an IFS LSP relies on the lower layer to provider the IFS socket handle. Once the IFS LSP obtains the lower provider's socket handle it can modify that handle (Winsock 2 provides an API call WPUModifyIFSHandle to do this) before returning the socket to the upper LSP (or ws2_32.dll). The modified handle is indistinguishable from the proposed handle as far as the operating system is concerned and is in fact, an IFS handle. The IFS LSP can simply choose to use only the modified handle in all of its internal processing.

Non IFS LSPs on the other hand, do not use true IFS handles. Non-IFS LSPs use WPUCreateSocketHandle to generate socket handles that are then returned to either the LSP above them or for the topmost LSP to the ws2_32.dll. These socket handles are also indistinguishable from true file system handles, but are not true IFS handles.

How to write an IFS based LSP?

Writing an IFS based LSP involves writing considerably less code than a non-IFS LSP. There are two reasons for this. First, an IFS LSP does not need to handle the various complicated I/O models associated with WSPAsyncSelect and overlapped I/O since an IFS LSP cannot be on the completion path of I/O operations. Secondly, an IFS LSP only needs to implement those Winsock SPI functions that it is interested in capturing. For example, a proxy type LSP would most likely only need to intercept WSPConnect, WSPSocket, WSPSendTo, WSPGetPeerName, and ConnectEx. For the remaining SPI functions, the IFS LSP can return the lower provider's function pointers. The next sections will cover installing an IFS provider, handling the WSPStartup, and discussing which Winsock SPI functions need special handling.

An IFS LSP must also follow a few rules on how it is installed into the Winsock catalog. First, an IFS LSP cannot be added to a protocol chain where there are non-IFS providers beneath it. This is a requirement since the LSP cannot advertise itself as an IFS provider if the lower provider returns a non-IFS handle which the IFS LSP is returning to the upper layer. Therefore if an IFS LSP is to be installed into an existing protocol chain, it should always insert itself into the chain after all the IFS LSPs but before any non-IFS LSPs.

The second requirement for installing an IFS LSP is each layered protocol chain belonging to the IFS LSP must be installed under its own GUID. By installing each layered protocol chain entry with its own GUID, the IFS LSP's WSPStartup will be invoked once each type the first socket is created from each of its layered protocol entries. The next section on WSPStartup will discuss WSPStartup in more detail.

Because an IFS LSP must install each of its layered protocol chains under its own GUID, an IFS LSP's WSPStartup must be written accordingly. To better understand this lets look at how an LSP is loaded. When an application creates a socket, Winsock will determine which provider should be loaded to handle the request. If this is the first time that provider has been invoked, then Winsock will call its WSPStartup. This means if an LSP is installed such that each layered protocol entry has its own GUID, the LSP's WSPStartup will be invoked once each time a socket is created from each of the providers. One requirement of WSPStartup is it must return a function pointer table containing all the Winsock SPI functions. Every function pointer in this table must be initialized with a valid function address. This becomes important for IFS LSPs since it will usually return some of the lower provider's SPI functions it this function table (since the IFS LSP is implementing only a subset of the Winsock SPI and letting the lower layer handle the remaining functions directly).

When an IFS LSP's WSPStartup is invoked it must perform the following actions:

  1. Enumerate the Winsock catalog
  2. From the WSAPROTOCOL_INFOW passed into WSPStartup, determine the next provider in the chain to load
  3. Load the next provider (if not already loaded)
  4. Initialize the WSPPROC_TABLE with its own function pointers as well as the remaining Winsock SPI functions from the next provider (loaded in step #3)

The trickiest step is #2 since the catalog ID of the provider following the IFS entry can either reference an exact entry or another LSP's hidden protocol entry. It is the latter case that can cause confusion. If the next provider is another LSP's hidden entry then it doesn't correspond to an actual layered protocol chain and the IFS LSP must guess which of the layered protocol entries associated with that hidden entry should be the next provider. This is where having each layered protocol entry installed under its own GUID comes into play. Since the WSAPROTOCOL_INFOW of the topmost entry is passed into WSPStartup, the WSPStartup logic can use the address family, socket type and protocol to find the correct next provider to load in the event the protocol chain references a hidden entry.

Consider the case where an IFS LSP's layered protocol entries are installed under the same GUID for TCP/IPv4 and UDP/IPv4 entries. When the application creates a TCP/IPv4 socket, the IFS LSP's WSPStartup is invoked, the IFS LSP loads the next provider which is a TCP/IPv4 provider, builds the WSPPROC_TABLE, and returns. Now when the application creates a UDP/IPv4 socket, the IFS LSP has already been loaded (since the GUID for the IFS LSP's UDP/IPv4 entry has already been loaded) and the WSPPROC_TABLE returned by the TCP/IPv4 load is used for the UDP/IPv4 socket. This approach works most of the time; however, if the TCP/IPv4 and UDP/IPv4 providers layered beneath the IFS LSPs are from two different LSPs, then when the application creates the second socket, the wrong provider is invoked to handle the request which may or may not succeed.

As mentioned earlier, one major benefit to writing an IFS LSP is that only a subset of the Winsock SPI functions need to be implemented depending on the function of the LSP. For those functions the IFS LSP doesn't implement itself, the lower provider's function pointer must be used. One special case is if the IFS LSP needs to intercept a Winsock extension function (such as ConnectEx, AcceptEx, etc.), it must intercept the WSPIoctl function in order to process requests by the upper layer to load an extension function with the SIO_GET_EXTENSION_FUNCTION_POINTER ioctl request. Only this particular ioctl is intercepted for the desired extension functions and all other requests (included this ioctl with extension functions the IFS LSP isn't interested in) should be passed to the lower provider.

Additionally, an IFS LSP may want to intercept WSPSocket and WSPClosesocket in order to maintain state information for each socket created. In this case the IFS LSP would implement its own WSPSocket which is invoked whenever a socket is created at which point the IFS LSP can create some state information which may be used in other SPI calls being intercepted. If WSPSocket is intercepted and state is kept then WSPCloseSocket should also be intercepted so that the IFS LSP can clean up state associated with a socket when it is closed by the application.

Benefits and Limitations of an IFS based LSP

There are many benefits of implementing an IFS based LSP such as:

Doesn't need to create own handles. It uses lower layer's handle.

Can pick-and-choose which Winsock SPI functions to handle. It does not have to implement all the SPI functions.

Doesn't have to handle the I/O completion or WSPAsyncSelect model

As a result, an IFS based LSP is much easier to implement and requires lesser code.

However, there are limitations of an IFS LSP:

An IFS based LSP cannot post-process overlapped I/O using WSPSend (WriteFile), WSPSendTo, WSPRecv (ReadFile), WSPRecvFrom, or WSPIoctl (or any of the Microsoft specific extension functions which may be called using ovelappedI/O). To allow additional processing in the LSP after an overlapped I/O completes in any of the above calls, an LSP must be non-IFS LSP.

Also, if the base provider handle is not an IFS handle (this is not the case for Microsoft's base providers), the LSP must be non-IFS. Additionally, all layers beneath an IFS provider must return IFS socket handles.

When is a non-IFS based LSP needed?

Non-IFS LSPs can intercept data during call completion as well as initiation. However, non-IFS LSPs

must handle *all* SPI calls themselves

must understand complex Windows I/O completion models

must create their own handle and map to the lower layer

As a result, writing a non-IFS LSP is much more complex than writing an IFS based LSP. Only in the cases where an LSP must intercept data during call completion or initiation should a non-IFS based LSP be implemented. Otherwise, an IFS based LSP is preferred. Unfortunately, the sample code provided by Microsoft has traditionally been for a non-IFS based LSP that has encouraged proliferation of non-IFS based LSPs. With an IFS based LSP sample that will be made available shortly, it is expected that most new LSPs will be IFS. In addition, even for the existing LSPs that are based on non-IFS sample, it is useful to migrate them to IFS.

LSP install & uninstall

Use New Install Atomic API

Installation and un-installation of an LSP requires several operations to be done by the LSP to maintain the consistency of Winsock catalog. These operations involve parsing the entries in the Winsock catalog, removing/adding entries, and re-ordering the resulting entries. While there are APIs available that can be used to perform each of these operations, the sequence of these operations that need to be performed for an LSP install/uninstall is complex and error prone. The number of cases that need to be considered for the various sets of LSPs that may have been installed/un-installed on a system can be huge. In some cases the code needed to do an LSP install/uninstall can reach 5000 lines of code. Further, even with a correctly written code, there is not any guarantee that the LSP will be installed/uninstalled correctly due to errors in install/uninstall code for another LSP installed/uninstalled on the system. Additional code may need to be written to get the catalog to a consistent state.

To reduce the code development effort and minimize errors in install/uninstall of LSPs, Microsoft has provided a new install API that does all the operations needed for installation of an LSP. This API is atomic and creates appropriate LSP entries and properly orders them in the Winsock Catalog. Further, new functionality has been added to the uninstall API to make sure that whenever this API is invoked, the Winsock catalog is left in a consistent state. This is done atomically and no change is needed to the LSP to make use of this additional functionality.

The new install API will be available in Longhorn and above and will be included as part of the SDK. Using it will require no more effort than the use of the current Install API. The additional functionality for the Uninstall API is available from XP SP2 and above as well as Server SP1 and above.

User Account Control (UAC) Considerations

User Account Control (UAC) is a new security feature of Microsoft Windows Vista that enables users to perform common tasks as non-Administrators. Additionally, user accounts that are members of the Administrators group will run most applications with reduced privileges.

Running with least privilege helps protect the system because applications run by Administrators no longer have full administrator privileges. Programs that do require (and request) administrator privileges, such as applications to administer the system or install an LSP, are started with full privileges after the user consents. Applications that require full administrator privileges to run correctly can run elevated, with full administrator privileges. The ability to run elevated with full privilege supports application compatibility for applications that do not otherwise run as a Standard User.

UAC affects LSP writers because the Winsock functions used to install and remove LSP entries can only be called from a user account which is a member of the Administrators group. On Windows Vista, due to the privilege difference between the built in local Administrator account and users that are a member of the Administrators group, the LSP install functions will return an access denied error unless the user is the built-in Administrator. Alternatively, when not run as the local Administrator, an installer application could be modified to prompt the user whether the installation should be allowed. The sample LSP has been updated to prompt the user in such a case when run on Windows Vista.

In order for an LSP installer to prompt a limited user whether to continue with the installation, an application manifest file needs to be created. An application manifest is an XML file named the same as the installing executable with '.manifest' appended to the end (e.g. instlsp.exe.manifest). The manifest describes the application and indicates that the application requires administrative privileges to install correctly:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">

<assemblyIdentity version="1.0.0.0" name="instlsp.exe" type="win32"/>

<description>instlsp - Sample LSP installer</description>

<!-- Identify the application security requirements. -->

<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">

<security>

<requestedPrivileges>

<requestedExecutionLevel

level="requireAdministrator"    

uiAccess="false"/>

</requestedPrivileges>

</security>

</trustInfo>

</assembly>

Once the manifest is created, it must be referenced in the application's resource file with the following directive:

#define MANIFEST_RESOURCE_ID 1

MANIFEST_RESOURCE_ID RT_MANIFEST "instlsp.exe.manifest"

Support all extension functions

Below are all the extension functions that have been provided by the Microsoft's BSP in Windows XP or before. All LSPs must support these extension functions so that an application that uses one of these extension functions does not lose that functionality as a result of a given LSP not supporting it.

AcceptEX

GetAcceptExSockaddrs

TransmitFile

TransmitPackets

ConnectEx

DisconnectEx

WSARecvMsg

In addition, in Windows Vista, non-IFS LSPs no longer have to implement each added extension function. Instead, applications intercept these new calls by watching for specific WSAIoctl ioctl values. See the latest SDK for new Ioctl definitions. Therefore, as long as an LSP has implemented WSPIoctl it will not break when new extension functions are added in this manner.

Supporting functions which accept multiple socket handles

Potential Problems

Processing function calls which provide multiple socket handles as arguments can be problematic for LSPs. To illustrate potential problems, the select function, which is used to determine the status of one or more sockets, is described. In most cases, problems stem for the fact that applications pass sockets created from different providers (ex. a UDP/IPv4 and a TCP/IPv4 socket) as arguments to a select call. This works fine unless a non-IFS LSP is installed over only the UDP/IPv4 or TCP/IPv4 base providers. In such a case, the application calling select may lose network connectivity. This problem occurs with the select function because the order of the socket handles in the provided FD_SETs matter: Winsock will find the first socket in the first non-empty FD_SET and call the provider which owns that handle to process the select call. If the first handle is a UDP/IPv4 socket from a base provider and the second handle is the TCP/IPv4 from an LSP provider, the base provider (BSP) will attempt to lookup the LSP handle, which will fail with WSAENOTSOCK. Because of this, it is recommended (see the section "Properly layer in Winsock Catalog" in this document) that non-IFS LSPs layer over all entries for a particular address family. Additionally, on Windows Vista it is recommended that non-IFS LSPs layer over both IPv4 and IPv6 entries.

Note: The problem described above also occurs if your LSP layers only over IPv4 entries, but not over the IPv6 ones.

LSP Bypass Mode

To prevent errors, Winsock in Windows Vista detects when a non-IFS LSP is installed that does not follow the guidelines of this document (ex. an IPv4 only LSP). When such an LSP is detected, functions accepting multiple socket handles as a parameter bypass LSPs entirely. The bypass mechanism has the follow characteristics:

  • Only the functions that accept multiple socket handles will bypass LSPs, all other calls will still be routed through the LSP in all cases.
  • Winsock will only enter "bypass mode" if it detects there is a non-IFS LSP installed over only one of the two required protocols (IPv4 or IPv6). If all non-IFS LSPs are installed over both IPv4 and IPv6, then Winsock will not switch to the "bypass mode"

For an LSP to intercept calls to functions which accept multiple socket handles, it will need to trap a WSAIoctl call and an ioctl associated with the function. For example, the SIO_BSP_HANDLE_SELECT IOCTL would be trapped in the LSP's WSPIoctl function if the LSP wanted to intercept select function calls ("Intercepting Select Function Calls" for further details).

Intercepting Select Function Calls

In general, LSPs do not need to intercept select unless they are injecting data into the application's stream in which case they would need to notify select-based applications that data is present. For LSPs that need to intercept select calls, they must be modified when run on Windows Vista to do so. The method by which an LSP's WSPSelect is bypassed is as follows:

  • Winsock translates each application socket to a base provider (BSP) handle, by calling the ioctl SIO_BSP_HANDLE_SELECT (described below) for each socket handle
  • Once all FD_SETs have been translated, select routes the call to the first socket handle in the first non-empty FD_SET which will be a BSP
  • Once the BSP provider returns, the handles returned are mapped back to the application handles

For an LSP to intercept select calls, on Windows Vista, it must:

  • Follow the guidelines in the "Properly layer in Winsock catalog - Selecting Base Service Providers to Layer Over" section of this document
  • Intercept the SIO_BSP_HANDLE_SELECT ioctl call and return the same socket handle value that was passed as the socket parameter (i.e. the LSP's socket handle that it returned to the caller)

The following code snippet illustrates the above rules:

int WSPAPI

WSPIoctl(

    SOCKET          s,

    DWORD           dwIoControlCode,

    LPVOID          lpvInBuffer,

    DWORD           cbInBuffer,

    LPVOID          lpvOutBuffer,

    DWORD           cbOutBuffer,

    LPDWORD         lpcbBytesReturned,

    LPWSAOVERLAPPED lpOverlapped,

    LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,

    LPWSATHREADID   lpThreadId,

    LPINT           lpErrno

        *lpvOutBuffer = s;

        *lpcbBytesReturned = sizeof(s);

        return NO_ERROR;

    // . Rest of your WSPIoctl

NOTE: If your LSP chooses to intercept select it does not guarantee that the problems described above will not be encountered. Under certain LSP layering configurations it's possible that the first handle belongs to a BSP or an LSP positioned lower in the LSP stack such that it will be unable to translate a given higher layer LSP handle. Unless you must intercept select calls, don't.

Properly layer in Winsock catalog

LSP Interoperability

Many issues surrounding interoperability with other LSPs deal with how the LSPs are layered in the Winsock catalog. If LSP writers follow a few simple rules, then interoperability issues will be greatly diminished:

An IFS LSP must not have non-IFS LSPs layered beneath it

LSPs which modify application data should install themselves at the end of the chain (but above IFS LSPs since these type of LSPs typically are non-IFS LSPs)

LSPs which inspect (filter) application data should install themselves at the head of the protocol chain

Additionally, a LSP should never register for Winsock catalog change notifications and attempt to re-order the catalog after another LSP is installed. This can lead to loss of network connectivity if two LSPs exist on the system which fights over the catalog order.

Selecting Base Service Providers to Layer Over

When determining the Base Service Providers to install your LSP over, the following guidelines should be followed:

Non-IFS LSPs should install either over all BSP entries or be installed over IPv4 and IPv6 entries

For each address family, Non-IFS LSPs should install over all protocol types. For example, if the LSP is layering over IPv4 and IPv6, it should be installed over the TCP/IPv4, UDP/IPv4, RAW/IPv4, TCP/IPv6, UDP/IPv6 and RAW/IPv6 providers

Note: The above guidance applies to Non-IFS LSPs. IFS LSPs may deviate may these guidelines as needed.

LSP Categorization

Overview

In Windows Vista, a feature called LSP Categorization has been added. LSP Categorization defines a method to state the type(s) of a Winsock Layered Service Providers (LSP) and allows applications to define what types of LSPs can be loaded into an application's process.

The core concept is that individual LSPs implement well-defined behaviors (LSP types), and these behaviors determine the ways in which the LSP manipulates the parameters and/or completions of the 30+ Winsock Service Provider Interface (SPI) functions. Application developers can determine which LSP behaviors are acceptable within an application by specifying a set of permitted LSP categories. This way an application can permit only those LSPs which implement acceptable behaviors, enabling the Winsock infrastructure to selectively include an LSP in the application's process at runtime.

This functionality was added for the following reasons:

  • 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 significant percentage of the system failures experienced by Windows users is due to an LSP malfunctioning when operating in the context of a system critical service. A side affect of these system processes loading LSPs is that such processes never exit, so when an LSP is installed or removed, a reboot is required.
  • There are cases where applications may not want to load certain LSPs. For example, some applications may not want to load cryptography LSPs so they can communicate with other machines that do not have the cryptography LSP installed.
  • 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. This method does rely on 3rd party LSPs to categorize themselves appropriately, but, the security enhancements in Vista will help prevent users from unintentionally installing malicious LSPs.

LSP Types

Winsock defines nine different LSP types (defined in ws2spi.h):

  1. LSP_SYSTEM - an LSP that should be loaded into system critical processes
  2. LSP_INSPECTOR - an LSP that simply monitors the inbound and outbound traffic but does not the data. An HTTP content filterer is an example of an inspector (as it will deny the request).
  3. LSP_REDIRECTOR - this type of LSP simply modifies the addresses used in Winsock calls.
  4. LSP_PROXY - this LSP redirects Winsock calls to a proxy server as well as instruct the proxy via a control channel to establish outbound connections.
  5. LSP_FIREWALL - an LSP that monitors incoming and outbound connection requests. A firewall LSP should only inspect data and deny request but not actually modify the data.
  6. LSP_INBOUND_MODIFY - filters inbound data
  7. LSP_OUTBOUT_MODIFY - filter outbound data
  8. LSP_CRYPTO_COMPRESS - a crypto or compression LSP can modify both inbound and outbound traffic but also includes and out of band signing/negotiation phase.
  9. LSP_LOCAL_CACHE - an LSP that inspects the contents of a Winsock request and satisfying the request by generating the expected response without the request actually hitting the intended destination.

It is possible and expected some LSPs will be categorized 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 Windows Vista, many system critical processes and system services are already registered with the appropriate categories depending on their functionality.

Categorizing an LSP

Two APIs are added in Windows Vista 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

int WSPAPI

WSCGetProviderInfo(

LPGUID lpProviderId,

WSC_PROVIDER_INFO_TYPE InfoType,

PBYTE Info,

size_t *InfoSize,

DWORD Flags,

LPINT lpErrno

To categorize an LSP:

WSCSetProviderInfo is called with the GUID of the hidden LSP entry that is associated with the LSP being categorized. (i.e. the LSP entry installed whose ProtocolChain.ChainLen is zero). WSC_PROVIDER_INFO_TYPE is an enumeration and ProviderInfoLspCategories should be passed. A DWORD with the appropriate LSP_* flags (noted above in the 'LSP Types' section) is passed in 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 the WSCGetProviderInfo function is used instead.

Categorizing an Application

The recommendation is to leave your application uncategorized - the default behavior. Leaving an application uncategorized ensures better application compatibility and results in the same behavior as on operating systems prior to Windows Vista (ie. allow all LSPs to be loaded). The only applications or services which should be categorized are those which are critical to the execution of the operating system. For example, critical system services used by Windows are categorized to ensure malfunctioning LSPs cannot disrupt the stability of the operating system as a whole.

An application specifies a set of permitted LSP categories which defines the LSPs that will be loaded into its process. Defining the permitted LSP categories for an application is done using the following two functions (defined in ws2spi.h):

int WSPAPI

WSCSetApplicationCategory(

LPCWSTR Path,

DWORD PathLength,

LPCWSTR Extra,

DWORD ExtraLength,

DWORD PermittedLspCategories,

DWORD * pPrevPermLspCat,

LPINT lpErrno

);

int WSPAPI

WSCGetApplicationCategory(

LPCWSTR Path,

DWORD PathLength,

LPCWSTR Extra,

DWORD ExtraLength,

DWORD * pPermittedLspCategories,

LPINT lpErrno

);

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. An application is defined as the full path and executable name as well as any arguments. Thus, if the application "c:\foo.exe" has a permitted LSP category set of LSP_PROXY, the application "c:\foo.exe -x 12" is different and would not be considered as allowing LSP_PROXY LSPs. The pPrevPermLspCat parameter is optional and simply returns the previous permitted category set for this application if it existed.

The following code sets the permitted LSP category set for "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

Determining Which LSPs Are Loaded

The final element of LSP categorization is determining the LSPs that are permitted in process. When a process loads Winsock, the application's permitted LSP category set and the LSP categories for all installed LSPs are loaded and the following comparisons made:

  1. If the application is not categorized (has not defined a permitted LSP category set), allow all LSPs. This is the default behavior on operating systems prior to Windows Vista where categorization is not available.
  2. If both the application and the LSP have assigned categories, all of the following must be true:
    1. AT LEAST ONE OF the LSP categories is present in the application's specified permitted categories
    2. ONLY categories specified in the application's specified permitted categories are specified in the LSPs categories (i.e. In general, the LSP's categories must be a subset of the applications permitted category set)
    3. If LSP_SYSTEM is present in the application's permitted category set, it MUST be present in the LSP's categories

NOTE: If an LSP is not categorized its category is effectively 0 and will only be included in applications that have not defined a permitted set of LSP categories.

Consider the following example:

Application Foo.exe has a permitted LSP category set equal to:

LSP_SYSTEM + LSP_FIREWALL + LSP_CRYPTO_COMPRESS

Application Bar.exe has a permitted LSP category set equal to:

LSP_FIREWALL + LSP_CRYPTO_COMPRESS

There are four LSPs installed on the system with the following categorizations:

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.

Sample LSP Implementation

The LSP sample can be obtained from the latest Windows SDK or the Windows Network Developer Platform Connect Website: https://connect.microsoft.com

Once at the site:

Select 'Available Programs' from the navigation bar on the left side of the screen.

Join the 'WNDP' (Windows Network Developer Platform) group and navigate to the group main page

The sample is available in the 'Downloads' section. See the navigation bar on the left side of the screen

Summary

In this document, we have described the best practices for LSP development. These include writing LSPs based on the simpler IFS model, using atomic install and uninstall APIs, supporting all the extension functions, properly layering the LSPs and where to find a sample LSP implementation. By following these best practices, LSP authors will be able to develop better LSP code.

Questions / Comments: [email protected]

Resources

  1. "Network Programming For Microsoft Windows", 2nd Edition, Anthony Jones and Jim Ohlund, Microsoft Press
  2. Winsock Newsgroup: public.win32.programmer.networks
  3. MSDN, https://msdn.microsoft.com
  4. Windows Network Developer Platform Team Blog: https://blogs.msdn.com/wndp
  5. Getting Started with User Account Control (UAC), https://www.microsoft.com
  6. User Account Control (UAC) Developer Guidelines, https://msdn.microsoft.com

Figures

Figure : Winsock Architecture


Document Info


Accesari: 6835
Apreciat: hand-up

Comenteaza documentul:

Nu esti inregistrat
Trebuie sa fii utilizator inregistrat pentru a putea comenta


Creaza cont nou

A fost util?

Daca documentul a fost util si crezi ca merita
sa adaugi un link catre el la tine in site


in pagina web a site-ului tau.




eCoduri.com - coduri postale, contabile, CAEN sau bancare

Politica de confidentialitate | Termenii si conditii de utilizare




Copyright © Contact (SCRIGROUP Int. 2024 )