Skip to content

Commit

Permalink
Committing Particular.Licensing so we know what we ship
Browse files Browse the repository at this point in the history
  • Loading branch information
John Simons committed Sep 9, 2014
1 parent 0e3d7d4 commit fa4a929
Show file tree
Hide file tree
Showing 10 changed files with 436 additions and 1 deletion.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,3 @@ _NCrunch_NServiceBus/*
logs
run-git.cmd
src/Chocolatey/Build/*
App_Packages
51 changes: 51 additions & 0 deletions src/NServiceBus.Core/App_Packages/Particular.Licensing/License.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
namespace Particular.Licensing
{
using System;
using System.Collections.Generic;

class License
{
public static License TrialLicense(DateTime trialStartDate)
{
return new License
{
LicenseType = "Trial",
ExpirationDate = trialStartDate.AddDays(14),
IsExtendedTrial = false,
ValidApplications = new List<string> { "All"}
};
}

public License()
{
ValidApplications = new List<string>();
}

public DateTime? ExpirationDate { get; set; }

public bool IsTrialLicense
{
get { return !IsCommercialLicense; }
}

public bool IsExtendedTrial { get; set; }

public bool IsCommercialLicense
{
get { return LicenseType.ToLower() != "trial"; }
}

public string LicenseType { get; set; }

public string RegisteredTo { get; set; }

public DateTime? UpgradeProtectionExpiration { get; internal set; }

public List<string> ValidApplications{ get; internal set; }

public bool ValidForApplication(string applicationName)
{
return ValidApplications.Contains(applicationName) || ValidApplications.Contains("All");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
namespace Particular.Licensing
{
using System;
using System.Linq;
using System.Xml;

static class LicenseDeserializer
{
public static License Deserialize(string licenseText)
{
var license = new License();
var doc = new XmlDocument();
doc.LoadXml(licenseText);


var applications = doc.SelectSingleNode("/license/@Applications");


if (applications != null)
{
license.ValidApplications.AddRange(applications.Value.Split(';'));
}

var upgradeProtectionExpiration = doc.SelectSingleNode("/license/@UpgradeProtectionExpiration");

if (upgradeProtectionExpiration != null)
{
license.UpgradeProtectionExpiration = Parse(upgradeProtectionExpiration.Value);
}
else
{
var expirationDate = doc.SelectSingleNode("/license/@expiration");

if (expirationDate != null)
{
license.ExpirationDate = Parse(expirationDate.Value);

}
}

var licenseType = doc.SelectSingleNode("/license/@LicenseType");

if (licenseType == null)
{
licenseType = doc.SelectSingleNode("/license/@type");
}

if (licenseType != null)
{
license.LicenseType = licenseType.Value;
}

var name = doc.SelectSingleNode("/license/name");

if (name != null)
{
license.RegisteredTo = name.InnerText;
}

return license;
}

static DateTime Parse(string dateStringFromLicense)
{
if (string.IsNullOrEmpty(dateStringFromLicense))
{
throw new Exception("Invalid datestring found in xml");
}

return UniversalDateParser.Parse(dateStringFromLicense.Split('T').First());
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
namespace Particular.Licensing
{
using System;

static class LicenseExpirationChecker
{
public static bool HasLicenseExpired(License license)
{
if (license.ExpirationDate.HasValue && HasLicenseDateExpired(license.ExpirationDate.Value))
{
return true;
}


if (license.UpgradeProtectionExpiration != null)
{
var buildTimeStamp = ReleaseDateReader.GetReleaseDate();
if (buildTimeStamp > license.UpgradeProtectionExpiration)
{
return true;
}
}
return false;
}

static bool HasLicenseDateExpired(DateTime licenseDate)
{
var oneDayGrace = licenseDate;

if (licenseDate < DateTime.MaxValue.AddDays(-1))
{
oneDayGrace = licenseDate.AddDays(1);
}

return oneDayGrace < DateTime.UtcNow.Date;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
namespace Particular.Licensing
{
using System;
using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
using System.Xml;

class LicenseVerifier
{
public static bool TryVerify(string licenseText, out Exception failure)
{
try
{
Verify(licenseText);

failure = null;

return true;
}
catch (Exception ex)
{
failure = ex;
return false;
}

}

public static void Verify(string licenseText)
{
if (string.IsNullOrEmpty(licenseText))
{
throw new Exception("Empty license string");
}

var xmlVerifier = new SignedXmlVerifier(PublicKey);

xmlVerifier.VerifyXml(licenseText);
}

public const string PublicKey = @"<RSAKeyValue><Modulus>5M9/p7N+JczIN/e5eObahxeCIe//2xRLA9YTam7zBrcUGt1UlnXqL0l/8uO8rsO5tl+tjjIV9bOTpDLfx0H03VJyxsE8BEpSVu48xujvI25+0mWRnk4V50bDZykCTS3Du0c8XvYj5jIKOHPtU//mKXVULhagT8GkAnNnMj9CvTc=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";

class SignedXmlVerifier
{
readonly string publicKey;

public SignedXmlVerifier(string publicKey)
{
this.publicKey = publicKey;
}

public void VerifyXml(string xml)
{
var doc = LoadXmlDoc(xml);

using (var rsa = new RSACryptoServiceProvider())
{
rsa.FromXmlString(publicKey);

var nsMgr = new XmlNamespaceManager(doc.NameTable);
nsMgr.AddNamespace("sig", "http://www.w3.org/2000/09/xmldsig#");

var signedXml = new SignedXml(doc);
var signature = (XmlElement)doc.SelectSingleNode("//sig:Signature", nsMgr);
if (signature == null)
{
throw new Exception("Xml is invalid as it has no XML signature");
}
signedXml.LoadXml(signature);

if (!signedXml.CheckSignature(rsa))
{
throw new Exception("Xml is invalid as it failed signature check.");
}
}
}

static XmlDocument LoadXmlDoc(string xml)
{
try
{
var doc = new XmlDocument();
doc.LoadXml(xml);
return doc;
}
catch (XmlException exception)
{
throw new Exception("The text provided could not be parsed as XML.", exception);
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
namespace Particular.Licensing
{
using System;
using System.Security;
using Microsoft.Win32;

class RegistryLicenseStore
{
public RegistryLicenseStore()
{
keyPath = DefaultKeyPath;
keyName = DefaultKeyName;
regKey = Registry.CurrentUser;

}

public RegistryLicenseStore(RegistryKey regKey, string keyPath = DefaultKeyPath, string keyName = DefaultKeyName)
{
this.keyPath = keyPath;
this.keyName = keyName;
this.regKey = regKey;
}

public bool TryReadLicense(out string license)
{
try
{
using (var registryKey = regKey.OpenSubKey(keyPath))
{
if (registryKey == null)
{
license = null;
return false;
}

var licenseValue = registryKey.GetValue("License", null);

if (licenseValue is string[])
{
license = string.Join(" ", (string[]) licenseValue);
}
else
{
license = (string)licenseValue;
}

return !string.IsNullOrEmpty(license);
}
}
catch (SecurityException exception)
{
throw new Exception(string.Format("Failed to access '{0}'. Do you have permission to read this key?", FullPath), exception);
}
}


public void StoreLicense(string license)
{
try
{
using (var registryKey = regKey.CreateSubKey(keyPath))
{
if (registryKey == null)
{
throw new Exception(string.Format("CreateSubKey for '{0}' returned null. Do you have permission to write to this key", keyPath));
}

registryKey.SetValue(keyName, license, RegistryValueKind.String);
}
}
catch (UnauthorizedAccessException exception)
{
throw new Exception(string.Format("Failed to access '{0}'. Do you have permission to write to this key?", FullPath), exception);
}
}

string FullPath
{
get { return string.Format("{0} : {1} : {2}", regKey.Name, keyPath, keyName); }
}

string keyPath;
string keyName;
RegistryKey regKey;


const string DefaultKeyPath = @"SOFTWARE\ParticularSoftware";
const string DefaultKeyName = "License";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
namespace Particular.Licensing
{
using System;
using System.Linq;
using System.Reflection;

static class ReleaseDateReader
{
public static DateTime GetReleaseDate()
{
var attribute = (dynamic)Assembly.GetExecutingAssembly()
.GetCustomAttributes(false)
.FirstOrDefault(x => x.GetType().Name == "ReleaseDateAttribute");

if (attribute == null)
{
throw new Exception("No ReleaseDateAttribute could be found in assembly, please make sure GitVersion is enabled");
}

return UniversalDateParser.Parse((string)attribute.OriginalDate);
}
}
}
Loading

0 comments on commit fa4a929

Please sign in to comment.