Giving Your DLL a Strong Name

Summary

In this post I’m going to talk a little about strong naming a dll and some of the gotchas associated with strong naming.

About Strong Names

If you’ve written .Net programs as long as I have, you’ve run into a problem where a dll does not have a strong name (also known as a signed dll).  Most dlls produced by Microsoft or downloaded using NuGet are already strong named and you don’t have to worry about them.  If you are creating a .Net program without using COM then you probably will also not have to worry about this problem.  If, however, you are creating a COM interface in order to use .Net code for your legacy non-.Net code, then you’ll need to strong-name your COM module as well as any dll that the COM library is dependent on (that is not already strong named).

How to Strong Name or Sign a DLL

Making your project create a strong-named dll is easy.  First you’ll need to generate a snk file.  There is an sn utility that is used to create this file and you can probably use the following syntax to generate the file (I have tested this on Windows 7, 10 and 2008R2):

“C:Program Files (x86)\Microsoft SDKs\Windows\v8.1A\bin\NETFX 4.5.1 Tools\sn” -k YourProjectName.snk

Technically, you can name this file anything you want, but I like to make it the project name to keep the file naming consistent with each project.  Now you need to link this to your project.  Right-click on your project, select “Add”, “Existing Item…”.

You’ll need to change your file type filter list to show all files (All files *.*).  Click on the snk file you created (don’t double-click).  The trick at this point is to click on the little down triangle next to the “Add” button and choose “Add as Link”. Then your snk file will be added as a link.

Now you need to right-click on the project again and select properties.  In the list of tabs on the left of the properties screen, select “Signing”.

Now click on the check box labeled “Sign the assembly”.  Then select your snk file from the drop-down list box and click on the save button (the floppy icon, or ctrl-s).

Now you can re-build your library and a strong-named dll will be created.

Checking DLL Strong Name

After you add a project or dll to another project, you can look in the references to find your dll.  Click on that dll and check the properties window.  You’ll see a property named “Strong Name”.  This should be set to “True”:

As I mentioned before, most dlls that ship with Visual Studio are already strong-named, but you might run into a situation where a package from NuGet is not strong-named.  In that instance you might have to find the source (probably GitHub or BitBucket) and download the source and perform the steps above to make it strong-named.

 

 

ISessionStateItemCollection interface

Summary

In previous programming projects, I have used the ISessionStateItemCollection object to override the session state collection object built into HttpContext.Current.  In this blog post I’m going to demo a bug in Microsoft’s sample code used to show how to create a custom SessionStateItemCollection.

Where to Find the Sample Code

Microsoft provides a lot of sample code for objects that you can customize.  The session state collection is one example.  The ISessionStateItemCollection interface is detailed on this webpage:  IsessionStateItemCollection Interface.  Each property and method is described in detail to make it easy to design a custom object.  If you scroll down the page, you’ll see a sample custom interface that uses the SortedList object to contain the item collection.  If you copy the code and paste it into Visual Studio, it will run as advertised.  Here’s a sample of some code you can execute in a console application:

var sessionTest = new MySessionStateItemCollection();

sessionTest[“test“] = “test data“;

Console.WriteLine(sessionTest[“test“]);

Console.ReadKey();

 Unfortunately, there is a problem with the key collection cast.  If you attempt to run this code, you’ll see the run-time casting error:

var sessionTest = new MySessionStateItemCollection();

sessionTest[“test“] = “test data“;

Console.WriteLine(sessionTest.Keys.Count);

Console.ReadKey();


 The error message looks like this:


If you’re like me, you’ll copy the error message and paste it into Google and attempt to find a solution.  That solution normally shows up on Stack Overflow, but sometimes if it’s not on that website you’ll stumble across it someplace else.  The solution to this error, is nowhere to be found.  I suspect that very few programmers write a custom session state item collection and those who do, have found a work-around.  So I’m posting a work-around to this issue that is not fantastic, but it works.

First, remove the line of code containing the SortedList.  Then add a base class to the object like this:

public class MySessionStateItemCollection : NameObjectCollectionBase, ISessionStateItemCollection

Next, you’ll need to alter all the method calls that used the SortedList (pItems).  You can use base.BaseGet(index) and base.BaseSet(index), etc.  You can override the Keys property and it will cast correctly, or you can just remove it since the base class implements that property already.  You’ll have to perform some fancy footwork for the CopyTo() method, since it is not implemented in the base class.

A second solution to this problem is to implement your own NameObjectCollectionBase type.  You could technically, implement a custom collection that mirrors the built-in methods of the NameObjectCollectionBase class.  This object also has sample code from Microsoft and this code works as advertised (see NameObjectCollectionBase Class).

 

Mocking HttpContext – Adding Sessions

Summary

In one of my previous posts (See: Mocking HttpContext), I created a HttpContext factory and a mocked HttpContext object that can be used to simulate the HttpContext.Current object used by methods under a unit test.  In this post, I’m going to add the Session capabilities to this object so you can unit test your methods and fake or mock your session variables.

The Mock Indexer

The session indexer can be overridden by creating a class based on the HttpSessionStateBase class.  Once this is done, then it can be used the Session object of the HttpContext.  Here’s the class to override the indexer:

public class MockHttpSession : HttpSessionStateBase
{
    public SessionStateItemCollection SessionVariables = new SessionStateItemCollection();

    public override object this[string name]
    {
        get
        {
            return SessionVariables[name];
        }
        set
        {
            SessionVariables[name] = value;
        }
    }
}

You’ll have to add a “using using System.Web.SessionState;” at the top for HttpSessionStateBase to be available.

Adding to the MockHttpContext

Next, you’ll need to add another public variable to the top of the existing MockHttpContext object and then add a Setup() method to replace the Session object.  Your MockHttpContext object will look like this:

public class MockHttpContext
{
    public NameValueCollection ServerVariables = new NameValueCollection();
    public HttpCookieCollection Cookies = new HttpCookieCollection();
    public NameValueCollection HeaderVariables = new NameValueCollection();
    public MockHttpSession SessionVars = new MockHttpSession();

    public HttpContextBase Context
    {
        get
        {
            var httpRequest = new Moq.Mock<HttpRequestBase>();

            httpRequest.Setup(x => x.ServerVariables.Get(It.IsAny<string>()))
                .Returns<string>(x =>
                {
                    return ServerVariables[x];
                });

            httpRequest.SetupGet(x => x.Cookies).Returns(Cookies);

            httpRequest.Setup(x => x.Headers.Get(It.IsAny<string>()))
                .Returns<string>(x =>
                    {
                        return HeaderVariables[x];
                    }
                );

            var httpContext = (new Moq.Mock<HttpContextBase>());
            httpContext.Setup(x => x.Request).Returns(httpRequest.Object);

            httpContext.Setup(ctx => ctx.Session).Returns(SessionVars);

            return httpContext.Object;
        }
    }
}
 
You’ll need to include Moq (use NuGet to find and install), and you’ll need to include the following using statements:

using System.Collections.Specialized;
using System.Web;
using System.Web.SessionState;
using Moq;


The Unit Test

The new unit test would look roughly like this:

[TestMethod]
public void httpcontext_session()
{
    var tempContext = new MockHttpContext();
    HttpContextFactory.SetCurrentContext(tempContext.Context);

    HttpContextFactory.Current.Session[“testid“] = “test data“;

    //TODO: call http method under test

    Assert.AreEqual(“test data“, HttpContextFactory.Current.Session[“testid“]);
}

This unit test uses the same HttpContextFactory as shown in my previous blog post.  The entire working code can be found on my GitHub account.

Where to Get the Code

As usual, you can go to my GitHub account and download the entire project by clicking here.

 
 
 

 

Creating Your Own Custom Session ID (Part 2)

Summary

In my last post, I talked about how to override the id generator of the HttpContext.Current.Session.  In this post I’m going to show how to override the methods that affect the cookie itself.

The ISessionIDManager Interface

In order to get at the methods required to manipulate the cookie, you’ll need to implement the ISessionIDManager Interface.  If you’re using Visual Studio 2015, this is an opportunity to use a new feature.  If you create a new solution and add a library project, then add a using for “System.Web.SessionState” and add the “System.Web” reference.  Now you can create a class that looks like this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.SessionState;

namespace MyCustomSession
{
    public class CustomSessionIDManager : ISessionIDManager
    {

    }
}

The ISessionIDManager statement will have a red wavy line under it.  If you hover over that keyword, you’ll get the following drop-down:

 Now you can click on the “Show Potential Fixes” link, then click on “Implement Interface”.  Then all the necessary methods and properties will be auto-populated:

So you’ll end up with something like this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.SessionState;

namespace MyCustomSession
{
    public class CustomSessionIDManager: ISessionIDManager
    {
        public string CreateSessionID(HttpContext context)
        {
            throw new NotImplementedException();
        }

        public string GetSessionID(HttpContext context)
        {
            throw new NotImplementedException();
        }

        public void Initialize()
        {
            throw new NotImplementedException();
        }

        public bool InitializeRequest(HttpContext context, bool suppressAutoDetectRedirect, out bool supportSessionIDReissue)
        {
            throw new NotImplementedException();
        }

        public void RemoveSessionID(HttpContext context)
        {
            throw new NotImplementedException();
        }

        public void SaveSessionID(HttpContext context, string id, out bool redirected, out bool cookieAdded)
        {
            throw new NotImplementedException();
        }

        public bool Validate(string id)
        {
            throw new NotImplementedException();
        }
    }
}

In case you’re wondering, this is the free Visual Studio Community 2015 version.  I’m evaluating the features that are available and it appears that Microsoft has finally produced a free version of Visual Studio that can be used to produce real software.  I’m still expecting to run into a limitation at some point, but so far, I’ve been using 2015 Community as though it has the same features as my old Visual Studio 2013 Professional.

Implementing the Interface

In my last blog post, I already implemented the CreateSessionID() and Validate() methods, so I’m going to copy and paste that code over from that project.  Again, Microsoft has a sample that you can use for your template.  It can be found at this website: ISessionIDManager Interface.

The first problem that I discovered when using the code provided from Microsoft is that the GetSessionID() method give an error at the “context.Request.Cookies[pConfig.CookieName].Value;” line.  The cookie has not been created and the SaveSessionID() method does not get called before this method is called.

The second thing I noticed is that the implementation of the IHttpModule methods seems pointless.  They also never get called.  I’m betting that there are methods in IHttpModule that are handy for certain features of the Session id, but they are not needed for this demonstration.

Don’t forget to setup your web.config file to invoke your custom object:

<configuration>
    <system.web>
        <sessionState cookieName=”MySessionID” 

            sessionIDManagerType=”MyCustomSession.CustomSessionIDManager,  
            MyCustomSession” />
    </system.web>
</configuration>

To fix the issue with the cookie not being created on initial load, I did this:

public string GetSessionID(HttpContext context)
{
    string id = null;

    if (pConfig.Cookieless == HttpCookieMode.UseUri)
    {
        // Retrieve the SessionID from the URI.
    }
    else
    {
        if (context.Request.Cookies[pConfig.CookieName] == null)
        {
            bool redirected;
            bool cookieAdded;

            SaveSessionID(context, id, out redirected, out cookieAdded);
        }
        else
        {
            id = context.Request.Cookies[pConfig.CookieName].Value;
        }
    }

    // Verify that the retrieved SessionID is valid. If not, return null.

    if (!Validate(id))
    {
        id = null;
    }

    return id;
}

If anybody out there has the correct solution to this problem, please drop me a comment.  If I find a solution, I’ll post an update to this blog entry.  I’m assuming that the calling object is supposed to recognize when a cookie doesn’t exist and call the SaveSessionID() method automatically.  However, that doesn’t happen here for some reason.


Where to Get the Code


As usual, you can go to my GitHub account and download the working project by clicking here.



 


 

 

Creating Your Own Custom Session ID

Summary

In this blog post I’m going to talk about the ID manager used by the .Net HttpContext.Current.Session and how to customize the ID that is generated to create a more secure ID.

Session ID

The session ID that is created when you use the Session object is contained in a cookie named ASP.NET_SessionId by default.  You can override the cookie name in the web.config file by using the following syntax:

<configuration>
    <system.web>
        <sessionState cookieName=”MySessionID” />
    </system.web>
</configuration>
 

This will cause the cookie to be named “MySessionID”.  You can also set the session to become cookieless.  I’m not go into cookieless sessions in this blog post.  What I am going to talk about is how to override the mechanism that generates the actual session id stored inside the cookie.  In a future blog post I’ll take this further and discuss how the cookie generation code can be modified to give you more control over this process.

The default .Net algorithm that is used to generate the id uses lower case characters ‘a’ thorugh ‘z’ and the numbers ‘0’ through ‘5’.  The reason for this sequence is that they are safe to use in a URL if you switch to cookieless.  The choice of only 6 numbers is due to the fact that the total characters to choose from becomes 32, which is an even binary number.  That allows the random number generator used to choose the letter for each digit to be un-biased.  For an excellent article about random number biasing when using the mod function I’ll refer you to this blog post: How much bias is introduced by the remainder technique?

The SessionIDManager Object

The SessionIDManager object is what performs the id generation and I’m going to show how to override the CreateSessionID() and Validate() methods in order to generate your own session id.  Microsoft has sample code here: SessionIDManager.CreateSessionID Method (HttpContext) using a GUID for the id.  DON’T DO IT THIS WAY!  This is a very simple and quick way to generate a custom id, but it’s also relatively easy to hack.  The problem with the GUID is that it is unique, but it is not random.  It’s pseudo-random and predictable.  If you refer to RFC4122, section 6:

Do not assume that UUIDs are hard to guess; they should not be used as security capabilities (identifiers whose mere possession grants access), for example. A predictable random number source will exacerbate the situation.

Make sure you use a cryptographically random number generator.  For this we can use the RNGCryptoServiceProvider object.  In addition to this, I’m going to make the key length 64 characters (you can go up to 80).  Here’s the C# code in total:

using System.Web;
using System.Web.SessionState;
using System.Security.Cryptography;
using System.Linq;

namespace MyCustomSession
{
    public class CustomSessionIDManager : SessionIDManager
    {
        public const int KEY_LENGTH = 64;
        private char[] Encoding = {
            ‘a‘, ‘b‘, ‘c‘, ‘d‘, ‘e‘, ‘f‘, ‘g‘, ‘h‘, ‘i‘, ‘j‘, ‘k‘, ‘l‘, ‘m‘,
            ‘n‘, ‘o‘, ‘p‘, ‘q‘, ‘r‘, ‘s‘, ‘t‘, ‘u‘, ‘v‘, ‘w‘, ‘x‘, ‘y‘, ‘z‘,
            ‘0‘, ‘1‘, ‘2‘, ‘3‘, ‘4‘, ‘5‘ };

        public override string CreateSessionID(HttpContext context)
        {
            char[] identifier = new char[KEY_LENGTH];
            byte[] randomData = new byte[KEY_LENGTH];

            using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
            {
                rng.GetBytes(randomData);
            }

            for (int i = 0; i < identifier.Length; i++)
            {
                int pos = randomData[i] % Encoding.Length;
                identifier[i] = Encoding[pos];
            }

            return new string(identifier);
        }

        public override bool Validate(string id)
        {
            try
            {
                if (id.Length != KEY_LENGTH)
                {
                    return false;
                }

                for (int i=0; i < id.Length; i++)
                {
                    if (!Encoding.Contains(id[i]))
                    {
                        return false;
                    }
                }

                return true;
            }
            catch
            {
            }

            return false;
        }
    }
}

And you’ll need to modify your web.config to match:

<configuration>
    <system.web>
        <sessionState cookieName=”MySessionID” 

            sessionIDManagerType=”MyCustomSession.CustomSessionIDManager,  
            MyCustomSession” />
    </system.web>
</configuration>


You’ll notice that MyCustomSession is used twice in the sessionIDManagerType definition.  The first one is the namespace and the name after the comma is the name of the dll.

I used the same character encoding that Microsoft uses, but you can increase the charactors to increase your security.  Just make sure you use an even binary number like 64 characters.  Also be aware of characters that might be difficult to work with (like the period, commas, back-slash, less-than, greater-than, etc.).  If you use upper case letters, lower case letters and all numbers you’ll end up two characters short of 64 characters.  So you’re forced to use two non-number/non-letter characters.

The next thing to note about the above class is that there is a validate() method.  This opens up some possibilities for a custom sequence that you can use to prevent spoofing.  In such a case I would try and keep such information classified so an outsider has difficulty in spoofing your id.  In the sample above, I’m only checking to make sure that the length is exactly correct and that each character in the id is in the list of valid characters.


Where to Get the Code

I have posted this example on my GitHub account and you can download it by clicking here.  This was written in Visual Studio 2015, but you can use it in earlier versions of Visual Studio.