Wednesday, March 10, 2010

Checking the Advantage Serial Number

Advantage includes many system procedures which allow you to obtain management information from the Advantage Database Server. One of these functions sp_mgGetInstallInfo can be used to retrieve the serial number of the server itself. This can be used to ensure that your application is connecting to the correct Advantage server.

For example you can store a Serial Number in the registry or configuration file. Then on startup your application makes a connection to the Advantage server and retrieves the serial number. You can then compare the two serial numbers to verify that you are connecting to the correct server. Perhaps the one that they have purchased from you as part of your software.

The following C# example demonstrates obtaining the serial number and comparing it to a serial number that is stored in the application configuration file. It uses a connection component that should already be connected prior to calling the function. The serial number is stored in the second field returned by sp_mgGetInstallInfo.

private bool CheckSN()
{    
    string SerialNumber;  
   
    if ( cn.State != System.Data.ConnectionState.Open )
        return false;

    // Create a command
    AdsCommand cmd = cn.CreateCommand();
    cmd.CommandText = "EXECUTE PROCEDURE sp_MgGetInstallInfo()";

    AdsDataReader rdr = cmd.ExecuteReader();
    if ( rdr.Read() )
        SerialNumber = rdr.GetString( 1 );
    else
        SerialNumber = "";
    
    rdr.Close();

    if ( SerialNumber.CompareTo( Properties.Settings.Default.ValidSN ) != 0 )
        return false;
    else
        return true;
}

Although this approach is very effective it is relatively simple to get around. A smart user could find a way to modify the configuration file or registry setting. Therefore you could use encryption to protect the serial number and reduce the chance that a user could change the "valid" serial number.

Visual Studio includes several built in cryptography libraries which make this process quite simple. First you need to add some functions to convert a string into a hash. The two functions below demonstrate using the MD5CryptoServiceProvider.

private string ComputeHash( string sValue )
{
    byte[] tmpSource;
    byte[] tmpHash;

    //Create a byte array from source data
    tmpSource = ASCIIEncoding.ASCII.GetBytes( sValue );

    //Compute hash based on source data
    tmpHash = new MD5CryptoServiceProvider().ComputeHash( tmpSource );

    return ByteArrayToString( tmpHash );
}

After that you simply read the serial number from the server, run it through the same hashing function and then compare the hashed values. The valid serial number would need to be stored in a hashed form when the application was installed. Or perhaps it could be done when the application first connects to Advantage.

private bool CheckSN( String SN )
{
    string SerialNumber;

    if ( cn.State != System.Data.ConnectionState.Open )
        return false;
    // Create a command
    AdsCommand cmd = cn.CreateCommand();
    cmd.CommandText = "EXECUTE PROCEDURE sp_MgGetInstallInfo()";

    AdsDataReader rdr = cmd.ExecuteReader();

    if ( rdr.Read() )
        SerialNumber = rdr.GetString( 1 );
    else
        return false;

    rdr.Close();

    SerialNumber = ComputeHash( SerialNumber );

    if  ( SerialNumber.CompareTo( Properties.Settings.Default.HashedSN ) != 0 )
        return false;
    else
        return true;
}

I created a simple C# application that demonstrates these techniques which you can download from CodeCentral.

No comments: