Accessing shared resources is a challenge for many ASP.NET developers. This challenge is encountered when attempting to develop Web forms and Web services. Microsoft .NET has a new approach to user authentication and authorization, which is generally a subject covered under security in most programming books and magazines. Most security articles and books dedicate a large portion of their resources explaining forms authentication. However, understanding the ASP.NET security architecture in conjunction with IIS, Network, and Operating System security is the key to providing the best solution.
Figure 1 depicts basic security representation provided by IIS and ASP.NET. This is fundamentally different from ASP security. The above figure has been borrowed from MSDN's Web site. The following sequence of events occurs when a Web request is issued.
HTTP request is issued by the user(s).
When a Web request is issued, it is picked up by IIS which runs under a SYSTEM account. The SYSTEM account is a very powerful account and has all kinds of privileges. IIS authenticates based on selected authentication type and creates an access token for each authenticated user. If anonymous authentication is selected, it creates an access token for the anonymous user, which is by default IUSR_MACHINE.
Also, IIS performs authorization based on configured authorization type. For example IIS can be configured such that it will accept a request only from certain IP addresses.
IIS passes the request and the authenticated caller's Windows access token to aspnet_isepi.dll, which is an ISAPI extension registered to handle .aspx URLs. Aspnet_isepi.dll is an IIS module and represents a bridge between IIS and ASP.NET runtime environment. The Aspnet_isapi forwards the request through named pipes to a worker process.
This worker process is aspnet_wp.exe which hosts the CLR. By default the worker process runs under an ASPNET account. This local account is created when the ASP.NET framework is installed. Unlike the SYSTEM account, which is very powerful, the ASPNET account has very limited privileges. ASP.NET authenticates the caller based on its own authentication configuration. Authentication is configured in an XML format in the project's web.config file. If ASP.NET is configured for Windows authentication, ASP.NET accepts any tokens it receives from IIS and no additional authentication occurs. In addition, the ASP.NET authorizes access to the requested resources and/or files. For example, the FileAuthorizationModel can be used to check if the user has the necessary authorization to access the requested resources. For Windows authentication, the user's access token is compared to the ACL.
If everything goes well up to this point, the application accesses the resources using a particular identity. By default the ASPNET process account provides the identity. However, if impersonation is enabled, the original user's identity can be used or impersonation can be configured such that the application can run under a specific identity.
Now that the security steps have been clarified, data can be accessed, assuming that NTFS permissions are set on network resources. Before proceeding any further, there are two important steps that must be addressed. One is to specify and define the task which will access files and folders on a Universal Naming Convention (UNC) share using ASP.NET, in other words, accessing shared files and folders on the network. The second step is deciding which identity will be used to accomplish resource access. In order to perform the first task, the second task needs to be completed.
There are several methods that can be utilized to access network resources.
Using the ASP.NET process identity
Using the anonymous user account
Using the LogonUser API
Using a serviced component (Enterprise Services)
Using the ASP.NET process identity seems to have clear drawbacks. By default, the ASP.NET process identity provides an identity (ASPNET) when the application tries to access the resources. The simplest solution is to create a local account with a matching username and password on the remote computer. Most companies consist of a large intranet environment, so this method is not practical. Also it is important to know who is accessing the resources. Although this method is sufficient to obtain access to network resources, it is inefficient.
The second method is to use the anonymous user account, for example IUSR_MACHINE. For the same reasons that are described above, it seems clear that this method would not be effective either.
The third method is using the LogonUser API. This method requires that a specific identity be impersonated by calling Win32 LogonUser API. Impersonation can also be obtained by configuring the <identity> element in the web.config file of the ASP.NET project. According to MSDN's article (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/SecNetch08.asp) "these approaches are not recommended. You should avoid them both on Windows 2000 servers, because it forces you to grant the 'Act as part of the operating system' privilege to the ASP.NET process account. This significantly reduces the security of the web application." Therefore this approach is not ideal.
The last and only option is to solve this problem using a serviced component configured to run as a fixed identity to access network resources. This approach sounds intimidating but it is by far the best solution. The architecture of this method is charted out below.
According to the security article published by J.D. Meier, et al. (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/SecNetch08.asp) using an out of process-serviced component (in an Enterprise Services server application) has the following advantages:
Flexibility in terms of the identity used. You don't just rely on the ASP.NET identity.
Trusted or higher-privileged code can be isolated from the main web application.
An additional process hop raises the bar from a security perspective. It makes it much tougher for an attacker to cross the process boundary to a process with raised privileges.
If you need to hand-craft impersonation with LogonUser API calls, you can do so in a process that is separated from your main Web application.
Assemblies receiving services from COM+ are considered Serviced Components. In order to a build a serviced component, one must have sufficient experience with COM+ technology. COM+ applications are not applications in the traditional sense in that they do not contain a user interface. COM+ applications are actually containers of components that form an application, and the COM and .NET assembly DLLs serve as the business logic portion of the application. COM+ is not a new version of COM, nor is it the combination of COM and DCOM. It is the technology that inherited MTS (Microsoft Transaction Services). The COM+ services are available in .NET components, which are referred to as Enterprise Services. They are implemented just like any middle-tier .NET component with a few more additions.
Below are the steps to create serviced components:
1. Create a new class library project to build middle-tier components that will serve initially as class libraries to the Web application.
2. Add appropriate classes, methods and properties. Since files and folders need to be accessed, System.IO namespace needs to be imported.
Figure 3: Class Library.
3. Create a Web form application.
Figure 4: Web Form Application.
Now the component, which is not yet a serviced component, can be tested. To enable meaningful security within the enterprise services application, Windows authentication must be used to enable impersonation. This is done in the web.config file of the Web application. This ensures that the serviced components are able to authenticate the original callers and make authorization decisions based on the original caller's identity. During development, while the component is not yet a serviced component, this will provide sufficient security to access shared files and folders.
In order to test, first the class needs to be compiled, then reference to this object is added to the Web application. The class is then initialized as follows:
Dim objEnterprise As New AccessingSharedResources.dal_AccessNetwork()
4. Create the strongly named assembly.
Run the Visual Studio .NET Command Prompt by selecting Start Menu --> Programs --> Microsoft Visual Studio .NET --> Visual Studio .NET Tools --> finally Visual Studio .NET Command Prompt.
Navigate to the projects directory and type the following command: sn -k KeyPair.snk
This creates a public/private key pair that will be used by the Visual Studio .NET IDE to give your component a strong name. Also, note that a KeyPair.snk file is created in the projects directory.
Open up the AssemblyInfo.vb files code window and add the following Assembly attribute. <Assembly: AssemblyKeyFile("KeyPair.snk")>
Compile the project. This will create the strongly named assembly.
5. Add the object to the GAC (Global Assembly Cache)
Open the .NET Framework Configuration Tool by selecting Start Menu --> Programs --> Administrative Tools --> Microsoft .NET Framework Configuration.
Select Assembly Cache --> Select View List of Assemblies in the Assembly Cache to view all assemblies in the GAC.
Right-click on the Assembly Cache icon and select Add.
Navigate to the AccessingSharedResources.dll file in the bin directory of the project and double click on AccessingSharedResources.dll
Note: While the command prompt is still running, type gacutil /i AccessingSharedResources.dll, this would also add the object to the GAC. This is known as the second method.
6. Add a reference to the System.EnterpiseServices.dll
7. Import the appropriate Enterprise Services namespaces:
Imports System.EnterpriseServices
Imports System.Runtime.CompilerServices
Imports System.Reflection
8. Inherit the ServicedComponent class into each class:
Public Class dal_AccessNetwork
Inherits ServicedComponent
9. Add Serviced Components related assembly attributes to the AssemblyInfo.vb file supporting Serviced Components
Import System.EnterpriseServices namespace
Add following:
'COM+ Application Name
< Assembly: ApplicationName("AccessingSharedResources")>
'COM+ Activation Type (Server which is out-of-process)
<Assembly: ApplicationActivation(ActivationOption.Server)>
10. Set AssemblyVersion:
The default AssemblyVersion attribute that is generated by Microsoft Visual Studio(r) .NET development system when a new project is created is <Assembly: AssemblyVersion("1.0.*")>. According to msdn's article (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/SecNetch09.asp) each time the project is rebuilt, a new assembly version is generated. This also results in the generation of a new class identifier (CLSID) to identify the serviced component classes. If you repeatedly register the assembly with component services using Regsvcs.exe, you will see duplicated components (strictly classes) with different CLSIDs listed beneath the Components folder.
While this complies with strict COM versioning semantics and will prevent existing managed and unmanaged clients from breaking, it can be an annoyance during development. During test and development, consider setting an explicit version by using the assembly level AssemblyVersion attribute shown below.
<Assembly: AssemblyVersion("1.0.0.1")>
This setting will prevent a new CLSID from being generated with each successive project build.
At this point; rebuild (compile) the project. The component is still in-process; it needs to be out-of-process. Execute the following steps.
11. Generate a new COM+ application and register the assembly in the new COM+ application.
Run the Visual Studio .NET Command Prompt (see step 4)
Navigate to the location of the dll which is under bin directory
Type regsvcs /c AccessingSharedResources.dll and press Enter
12. Revise the Web Application
Add a reference to the System.EnterrpiseServices.dll
Add the Imports System.EnterpriseServices statement to the web client
Now the Enterprise Service Component, otherwise known as Serviced Component, has been successfully completed. View the component as a COM+ application.
Run Component Services Manager by selecting Start --> Programs --> Administrative Tools --> Component Services
Advantages of using serviced components are as follows:
Flexibility in terms of the identity used. You don't just rely on the ASP.NET identity.
Trusted or higher-privileged code can be isolated from the main Web application.
An additional process hop raises the bar from a security perspective. It makes it much tougher for an attacker to cross the process boundary to a process with raised privileges.
If you need to hand-craft impersonation with LogonUser API calls, you can do so in a process that is separated from your main Web application.
Disadvantages are as follows:
Calling serviced components is not as fast as calling native .NET objects, so performance of the application is negatively effected.
Requires extra steps and extra code.
Harder to manage than native .NET components
DLLs need to be installed in COM+ applications
Conclusion
While we have not utilized the fundamental features of COM+ such as object pooling, transactional support, synchronization, just-in-time activation (JITA) and Event Tracking; we have accomplished our objectives. All of the COM+ features are advanced subjects and should be well understood before they are implemented. However, just installing native .NET class in COM+ applications and adding several lines of COM+-specific code is sufficient for accessing shared resources on the network.
Anthony Arslan is currently working as a developer for a large financial institution in Lincoln, Nebraska. He also teaches Microsoft Applications at a local college. Anthony holds a Master's degree in Computer Science. He can be reached at arslan@nefel.com.
Tool Parts provide an interface for Web Part properties well beyond the capabilities of the default property pane. In this article Gayan Peiris shows how to customize Web Parts with custom Tool Parts. [Read This Article][Top]
This article demonstrates how to create a reusable component in ASP.NET 2.0 and then consume it from an ASP.NET page. Also learn how the ObjectDataSource control can be used to directly bind the output of an object to the controls in an ASP.NET page and how precompilation can be used to increase the performance of the Web application and catch compilation errors. [Read This Article][Top]
Browser Helper Objects (BHOs) are COM components that communicate with Internet Explorer to enrich the browsing experience. Michele Leroux Bustamante returns to the world of COM to show you how to build a managed BHO with the help of the .NET Framework's COM interoperability features. [Read This Article][Top]
In addition to creating custom Web Parts for SharePoint Portal Server, developers can actually create their own custom properties to further enhance Web Part appearance and behavior. Gayan Peiris explains the process and provides all the necessary code. [Read This Article][Top]
Using callbacks and function pointers in VB can be risky and complicated. Ben Garcia explains his work-around for the function pointer issue he encountered while creating the VB version of his SNMP component. [Read This Article][Top]
In part two of this intriguing article series, Ben Garcia shows how to build an updated and improved SNMP component in VC++ AND VB, and he briefly explains why limitations in VB make VC++ a better language for developing this type of application. [Read This Article][Top]
Ben Garcia sheds some light on the Simple Network Management Protocol
(SNMP). First he provides a history of SNMP, then he dives right into its
architecture. Finally, he shows how to build a COM component that
communicates with SNMP-enabled devices. [Read This Article][Top]
Paul Apostolos begins his series on using Web services and the MSComm32.OCX
component to access caller id information from a Web page. In part 1, learn how to write the Visual Basic program that runs on the server and updates a database with incoming callers.
[Read This Article][Top]
Doug Dean explains different methods of retrieving and manipulating data from a database in a VB DLL so that it is ready to be rendered in a browser. [Read This Article][Top]
In this article, S.S. Ahmed shows you how to create VB add-ins. Programmers always feel that they are short of several features while working with development tools. Since Microsoft made Visual Basic an extensible product, VB developers can create their own features in VB. [Read This Article][Top]
Mailing List
Want to receive email when the next article is published? Just Click Here to sign up.