Browse files

Merge branch 'master' of github.com:hibernating-rhinos/rhino-licensing

  • Loading branch information...
2 parents 6b78c3c + 504845f commit cc63229129598e1ed6220099c2176163af865217 @HEskandari HEskandari committed Aug 15, 2010
View
941 Rhino.Licensing/AbstractLicenseValidator.cs
@@ -1,439 +1,504 @@
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Net.NetworkInformation;
-using System.Security.Cryptography;
-using System.Security.Cryptography.Xml;
-using System.ServiceModel;
-using System.Threading;
-using System.Xml;
-using log4net;
-
-namespace Rhino.Licensing
-{
- public abstract class AbstractLicenseValidator
- {
- protected readonly ILog Log = LogManager.GetLogger(typeof(LicenseValidator));
-
- protected readonly string[] TimeServers = new[]
- {
- "time.nist.gov",
- "time-nw.nist.gov",
- "time-a.nist.gov",
- "time-b.nist.gov",
- "time-a.timefreq.bldrdoc.gov",
- "time-b.timefreq.bldrdoc.gov",
- "time-c.timefreq.bldrdoc.gov",
- "utcnist.colorado.edu",
- "nist1.datum.com",
- "nist1.dc.certifiedtime.com",
- "nist1.nyc.certifiedtime.com",
- "nist1.sjc.certifiedtime.com"
- };
-
- private readonly string licenseServerUrl;
- private readonly Guid clientId;
- private readonly string publicKey;
- private readonly Timer nextLeaseTimer;
- private bool disableFutureChecks;
- private bool currentlyValidatingSubscriptionLicense;
-
- public event Action<InvalidationType> LicenseInvalidated;
-
- public DateTime ExpirationDate
- {
- get; private set;
- }
-
- public string SubscriptionEndpoint
- {
- get; set;
- }
-
- public LicenseType LicenseType
- {
- get; private set;
- }
-
- public Guid UserId
- {
- get; private set;
- }
-
- public string Name
- {
- get; private set;
- }
-
- public bool DisableFloatingLicenses
- {
- get; set;
- }
-
- public IDictionary<string, string> LicenseAttributes
- {
- get; private set;
- }
-
- protected abstract string License
- {
- get; set;
- }
-
- private void LeaseLicenseAgain(object state)
- {
- if (HasExistingLicense())
- return;
- RaiseLicenseInvalidated();
- }
-
- private void RaiseLicenseInvalidated()
- {
- var licenseInvalidated = LicenseInvalidated;
- if (licenseInvalidated == null)
- throw new InvalidOperationException("License was invalidated, but there is no one subscribe to the LicenseInvalidated event");
- licenseInvalidated(LicenseType == LicenseType.Floating
- ? InvalidationType.CannotGetNewLicense
- : InvalidationType.TimeExpired);
- }
-
- protected AbstractLicenseValidator(string publicKey)
- {
- LicenseAttributes = new Dictionary<string, string>();
- nextLeaseTimer = new Timer(LeaseLicenseAgain);
- this.publicKey = publicKey;
- }
-
- protected AbstractLicenseValidator(string publicKey, string licenseServerUrl, Guid clientId)
- {
- LicenseAttributes = new Dictionary<string, string>();
- nextLeaseTimer = new Timer(LeaseLicenseAgain);
- this.publicKey = publicKey;
- this.licenseServerUrl = licenseServerUrl;
- this.clientId = clientId;
- }
-
-
- public virtual void AssertValidLicense()
- {
- LicenseAttributes.Clear();
- if (HasExistingLicense())
- return;
- Log.WarnFormat("Could not validate existing license\r\n{0}", License);
- throw new LicenseNotFoundException();
- }
-
- private bool HasExistingLicense()
- {
- try
- {
- if (TryLoadingLicenseValuesFromValidatedXml() == false)
- {
- Log.WarnFormat("Failed validating license:\r\n{0}", License);
- return false;
- }
- Log.InfoFormat("License expiration date is {0}", ExpirationDate);
-
- bool result;
- if (LicenseType == LicenseType.Subscription)
- result = ValidateSubscription();
- else
- result = DateTime.UtcNow < ExpirationDate;
-
- if (result)
- ValidateUsingNetworkTime();
-
- return result;
- }
- catch (RhinoLicensingException)
- {
- throw;
- }
- catch (Exception)
- {
- return false;
- }
- }
-
- private bool ValidateSubscription()
- {
- if ((ExpirationDate - DateTime.UtcNow).TotalDays > 4)
- return true;
-
- if (currentlyValidatingSubscriptionLicense)
- return DateTime.UtcNow < ExpirationDate;
-
- if (SubscriptionEndpoint == null)
- throw new InvalidOperationException("Subscription endpoints are not supported for this license validator");
-
- try
- {
- TryGettingNewLeaseSubscription();
- }
- catch (Exception e)
- {
- Log.Error("Could not re-lease subscription license", e);
- }
-
- return ValidateWithoutUsingSubscriptionLeasing();
- }
-
- private bool ValidateWithoutUsingSubscriptionLeasing()
- {
- currentlyValidatingSubscriptionLicense = true;
- try
- {
- return HasExistingLicense();
- }
- finally
- {
- currentlyValidatingSubscriptionLicense = false;
- }
- }
-
- private void TryGettingNewLeaseSubscription()
- {
- var service = ChannelFactory<ISubscriptionLicensingService>.CreateChannel(new BasicHttpBinding(), new EndpointAddress(SubscriptionEndpoint));
- try
- {
- var newLicense = service.LeaseLicense(License);
- TryOverwritingWithNewLicense(newLicense);
- }
- finally
- {
- var communicationObject = service as ICommunicationObject;
- if (communicationObject != null)
- {
- try
- {
- communicationObject.Close(TimeSpan.FromMilliseconds(200));
- }
- catch
- {
- communicationObject.Abort();
- }
- }
- }
- }
-
- protected bool TryOverwritingWithNewLicense(string newLicense)
- {
- if (string.IsNullOrEmpty(newLicense))
- return false;
- try
- {
- var xmlDocument = new XmlDocument();
- xmlDocument.LoadXml(newLicense);
- }
- catch (Exception e)
- {
- Log.Error("New license is not valid XML\r\n" + newLicense, e);
- return false;
- }
- License = newLicense;
- return true;
- }
-
- private void ValidateUsingNetworkTime()
- {
- if (!NetworkInterface.GetIsNetworkAvailable())
- return;
-
- var sntp = new SntpClient(TimeServers);
- sntp.BeginGetDate(time =>
- {
- if (time > ExpirationDate)
- RaiseLicenseInvalidated();
- }
- ,() =>
- {
- /* ignored */
- });
- }
-
- public virtual void RemoveExistingLicense()
- {
- }
-
- public bool TryLoadingLicenseValuesFromValidatedXml()
- {
- try
- {
- var doc = new XmlDocument();
- doc.LoadXml(License);
-
- if (TryGetValidDocument(publicKey, doc) == false)
- {
- Log.WarnFormat("Could not validate xml signature of:\r\n{0}", License);
- return false;
- }
-
- if (doc.FirstChild == null)
- {
- Log.WarnFormat("Could not find first child of:\r\n{0}", License);
- return false;
- }
-
- if (doc.SelectSingleNode("/floating-license") != null)
- {
- var node = doc.SelectSingleNode("/floating-license/license-server-public-key/text()");
- if (node == null)
- {
- Log.WarnFormat("Invalid license, floating license without license server public key:\r\n{0}", License);
- throw new InvalidOperationException(
- "Invalid license file format, floating license without license server public key");
- }
- return ValidateFloatingLicense(node.InnerText);
- }
-
- var result = ValidateXmlDocumentLicense(doc);
- if (result && disableFutureChecks == false)
- {
- nextLeaseTimer.Change(TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5));
- }
- return result;
- }
- catch (RhinoLicensingException)
- {
- throw;
- }
- catch (Exception e)
- {
- Log.Error("Could not validate license", e);
- return false;
- }
- }
-
- private bool ValidateFloatingLicense(string publicKeyOfFloatingLicense)
- {
- if (DisableFloatingLicenses)
- {
- Log.Warn("Floating licenses have been disabled");
- return false;
- }
- if (licenseServerUrl == null)
- {
- Log.Warn("Could not find license server url");
- throw new InvalidOperationException("Floating license encountered, but licenseServerUrl was not set");
- }
-
- var success = false;
- var licensingService = ChannelFactory<ILicensingService>.CreateChannel(new WSHttpBinding(), new EndpointAddress(licenseServerUrl));
- try
- {
- var leasedLicense = licensingService.LeaseLicense(
- Environment.MachineName,
- Environment.UserName,
- clientId);
- ((ICommunicationObject)licensingService).Close();
- success = true;
- if (leasedLicense == null)
- {
- Log.WarnFormat("Null response from license server: {0}", licenseServerUrl);
- throw new FloatingLicenseNotAvialableException();
- }
-
- var doc = new XmlDocument();
- doc.LoadXml(leasedLicense);
-
- if (TryGetValidDocument(publicKeyOfFloatingLicense, doc) == false)
- {
- Log.WarnFormat("Could not get valid license from floating license server {0}", licenseServerUrl);
- throw new FloatingLicenseNotAvialableException();
- }
-
- var validLicense = ValidateXmlDocumentLicense(doc);
- if (validLicense)
- {
- //setup next lease
- var time = (ExpirationDate.AddMinutes(-5) - DateTime.UtcNow);
- Log.DebugFormat("Will lease license again at {0}", time);
- if (disableFutureChecks == false)
- nextLeaseTimer.Change(time, time);
- }
- return validLicense;
- }
- finally
- {
- if (success == false)
- ((ICommunicationObject)licensingService).Abort();
- }
- }
-
- internal bool ValidateXmlDocumentLicense(XmlDocument doc)
- {
- XmlNode id = doc.SelectSingleNode("/license/@id");
- if (id == null)
- {
- Log.WarnFormat("Could not find id attribute in license:\r\n{0}", License);
- return false;
- }
-
- UserId = new Guid(id.Value);
-
- XmlNode date = doc.SelectSingleNode("/license/@expiration");
- if (date == null)
- {
- Log.WarnFormat("Could not find expiration in license:\r\n{0}", License);
- return false;
- }
-
- ExpirationDate = DateTime.ParseExact(date.Value, "yyyy-MM-ddTHH:mm:ss.fffffff", CultureInfo.InvariantCulture);
-
- XmlNode licenseType = doc.SelectSingleNode("/license/@type");
- if (licenseType == null)
- {
- Log.WarnFormat("Could not find license type in {0}", licenseType);
- return false;
- }
-
- LicenseType = (LicenseType)Enum.Parse(typeof(LicenseType), licenseType.Value);
-
- XmlNode name = doc.SelectSingleNode("/license/name/text()");
- if (name == null)
- {
- Log.WarnFormat("Could not find licensee's name in license:\r\n{0}", License);
- return false;
- }
-
- Name = name.Value;
-
- var license = doc.SelectSingleNode("/license");
- foreach (XmlAttribute attrib in license.Attributes)
- {
- if (attrib.Name == "type" || attrib.Name == "expiration" || attrib.Name == "id")
- continue;
-
- LicenseAttributes[attrib.Name] = attrib.Value;
- }
-
- return true;
- }
-
- private bool TryGetValidDocument(string licensePublicKey, XmlDocument doc)
- {
- var rsa = new RSACryptoServiceProvider();
- rsa.FromXmlString(licensePublicKey);
-
- var nsMgr = new XmlNamespaceManager(doc.NameTable);
- nsMgr.AddNamespace("sig", "http://www.w3.org/2000/09/xmldsig#");
-
- var signedXml = new SignedXml(doc);
- var sig = (XmlElement)doc.SelectSingleNode("//sig:Signature", nsMgr);
- if (sig == null)
- {
- Log.WarnFormat("Could not find this signature node on license:\r\n{0}", License);
- return false;
- }
- signedXml.LoadXml(sig);
-
- return signedXml.CheckSignature(rsa);
- }
-
- public void DisableFutureChecks()
- {
- disableFutureChecks = true;
- nextLeaseTimer.Dispose();
- }
- }
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Net.NetworkInformation;
+using System.Security.Cryptography;
+using System.Security.Cryptography.Xml;
+using System.ServiceModel;
+using System.Threading;
+using System.Xml;
+using log4net;
+
+namespace Rhino.Licensing
+{
+ /// <summary>
+ /// Base license validator.
+ /// </summary>
+ public abstract class AbstractLicenseValidator
+ {
+ /// <summary>
+ /// License validator logger
+ /// </summary>
+ protected readonly ILog Log = LogManager.GetLogger(typeof(LicenseValidator));
+
+ /// <summary>
+ /// Standard Time servers
+ /// </summary>
+ protected readonly string[] TimeServers = new[]
+ {
+ "time.nist.gov",
+ "time-nw.nist.gov",
+ "time-a.nist.gov",
+ "time-b.nist.gov",
+ "time-a.timefreq.bldrdoc.gov",
+ "time-b.timefreq.bldrdoc.gov",
+ "time-c.timefreq.bldrdoc.gov",
+ "utcnist.colorado.edu",
+ "nist1.datum.com",
+ "nist1.dc.certifiedtime.com",
+ "nist1.nyc.certifiedtime.com",
+ "nist1.sjc.certifiedtime.com"
+ };
+
+ private readonly string licenseServerUrl;
+ private readonly Guid clientId;
+ private readonly string publicKey;
+ private readonly Timer nextLeaseTimer;
+ private bool disableFutureChecks;
+ private bool currentlyValidatingSubscriptionLicense;
+
+
+ /// <summary>
+ /// Fired when license data is invalidated
+ /// </summary>
+ public event Action<InvalidationType> LicenseInvalidated;
+
+ /// <summary>
+ /// Gets the expiration date of the license
+ /// </summary>
+ public DateTime ExpirationDate
+ {
+ get; private set;
+ }
+
+ /// <summary>
+ /// Gets or Sets the endpoint address of the subscription service
+ /// </summary>
+ public string SubscriptionEndpoint
+ {
+ get; set;
+ }
+
+ /// <summary>
+ /// Gets the Type of the license
+ /// </summary>
+ public LicenseType LicenseType
+ {
+ get; private set;
+ }
+
+ /// <summary>
+ /// Gets the Id of the license holder
+ /// </summary>
+ public Guid UserId
+ {
+ get; private set;
+ }
+
+ /// <summary>
+ /// Gets the name of the license holder
+ /// </summary>
+ public string Name
+ {
+ get; private set;
+ }
+
+ /// <summary>
+ /// Gets or Sets Floating license support
+ /// </summary>
+ public bool DisableFloatingLicenses
+ {
+ get; set;
+ }
+
+ /// <summary>
+ /// Gets extra license information
+ /// </summary>
+ public IDictionary<string, string> LicenseAttributes
+ {
+ get; private set;
+ }
+
+ /// <summary>
+ /// Gets or Sets the license content
+ /// </summary>
+ protected abstract string License
+ {
+ get; set;
+ }
+
+ private void LeaseLicenseAgain(object state)
+ {
+ if (HasExistingLicense())
+ return;
+ RaiseLicenseInvalidated();
+ }
+
+ private void RaiseLicenseInvalidated()
+ {
+ var licenseInvalidated = LicenseInvalidated;
+ if (licenseInvalidated == null)
+ throw new InvalidOperationException("License was invalidated, but there is no one subscribe to the LicenseInvalidated event");
+ licenseInvalidated(LicenseType == LicenseType.Floating
+ ? InvalidationType.CannotGetNewLicense
+ : InvalidationType.TimeExpired);
+ }
+
+ /// <summary>
+ /// Creates a license validator with specfied public key.
+ /// </summary>
+ /// <param name="publicKey">public key</param>
+ protected AbstractLicenseValidator(string publicKey)
+ {
+ LicenseAttributes = new Dictionary<string, string>();
+ nextLeaseTimer = new Timer(LeaseLicenseAgain);
+ this.publicKey = publicKey;
+ }
+
+ /// <summary>
+ /// Creates a license validator using the client information
+ /// and a service endpoint address to validate the license.
+ /// </summary>
+ /// <param name="publicKey"></param>
+ /// <param name="licenseServerUrl"></param>
+ /// <param name="clientId"></param>
+ protected AbstractLicenseValidator(string publicKey, string licenseServerUrl, Guid clientId)
+ {
+ LicenseAttributes = new Dictionary<string, string>();
+ nextLeaseTimer = new Timer(LeaseLicenseAgain);
+ this.publicKey = publicKey;
+ this.licenseServerUrl = licenseServerUrl;
+ this.clientId = clientId;
+ }
+
+ /// <summary>
+ /// Validates loaded license
+ /// </summary>
+ public virtual void AssertValidLicense()
+ {
+ LicenseAttributes.Clear();
+ if (HasExistingLicense())
+ return;
+ Log.WarnFormat("Could not validate existing license\r\n{0}", License);
+ throw new LicenseNotFoundException();
+ }
+
+ private bool HasExistingLicense()
+ {
+ try
+ {
+ if (TryLoadingLicenseValuesFromValidatedXml() == false)
+ {
+ Log.WarnFormat("Failed validating license:\r\n{0}", License);
+ return false;
+ }
+ Log.InfoFormat("License expiration date is {0}", ExpirationDate);
+
+ bool result;
+ if (LicenseType == LicenseType.Subscription)
+ result = ValidateSubscription();
+ else
+ result = DateTime.UtcNow < ExpirationDate;
+
+ if (result)
+ ValidateUsingNetworkTime();
+
+ return result;
+ }
+ catch (RhinoLicensingException)
+ {
+ throw;
+ }
+ catch (Exception)
+ {
+ return false;
+ }
+ }
+
+ private bool ValidateSubscription()
+ {
+ if ((ExpirationDate - DateTime.UtcNow).TotalDays > 4)
+ return true;
+
+ if (currentlyValidatingSubscriptionLicense)
+ return DateTime.UtcNow < ExpirationDate;
+
+ if (SubscriptionEndpoint == null)
+ throw new InvalidOperationException("Subscription endpoints are not supported for this license validator");
+
+ try
+ {
+ TryGettingNewLeaseSubscription();
+ }
+ catch (Exception e)
+ {
+ Log.Error("Could not re-lease subscription license", e);
+ }
+
+ return ValidateWithoutUsingSubscriptionLeasing();
+ }
+
+ private bool ValidateWithoutUsingSubscriptionLeasing()
+ {
+ currentlyValidatingSubscriptionLicense = true;
+ try
+ {
+ return HasExistingLicense();
+ }
+ finally
+ {
+ currentlyValidatingSubscriptionLicense = false;
+ }
+ }
+
+ private void TryGettingNewLeaseSubscription()
+ {
+ var service = ChannelFactory<ISubscriptionLicensingService>.CreateChannel(new BasicHttpBinding(), new EndpointAddress(SubscriptionEndpoint));
+ try
+ {
+ var newLicense = service.LeaseLicense(License);
+ TryOverwritingWithNewLicense(newLicense);
+ }
+ finally
+ {
+ var communicationObject = service as ICommunicationObject;
+ if (communicationObject != null)
+ {
+ try
+ {
+ communicationObject.Close(TimeSpan.FromMilliseconds(200));
+ }
+ catch
+ {
+ communicationObject.Abort();
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Loads the license file.
+ /// </summary>
+ /// <param name="newLicense"></param>
+ /// <returns></returns>
+ protected bool TryOverwritingWithNewLicense(string newLicense)
+ {
+ if (string.IsNullOrEmpty(newLicense))
+ return false;
+ try
+ {
+ var xmlDocument = new XmlDocument();
+ xmlDocument.LoadXml(newLicense);
+ }
+ catch (Exception e)
+ {
+ Log.Error("New license is not valid XML\r\n" + newLicense, e);
+ return false;
+ }
+ License = newLicense;
+ return true;
+ }
+
+ private void ValidateUsingNetworkTime()
+ {
+ if (!NetworkInterface.GetIsNetworkAvailable())
+ return;
+
+ var sntp = new SntpClient(TimeServers);
+ sntp.BeginGetDate(time =>
+ {
+ if (time > ExpirationDate)
+ RaiseLicenseInvalidated();
+ }
+ ,() =>
+ {
+ /* ignored */
+ });
+ }
+
+ /// <summary>
+ /// Removes existing license from the machine.
+ /// </summary>
+ public virtual void RemoveExistingLicense()
+ {
+ }
+
+ /// <summary>
+ /// Loads license data from validated license file.
+ /// </summary>
+ /// <returns></returns>
+ public bool TryLoadingLicenseValuesFromValidatedXml()
+ {
+ try
+ {
+ var doc = new XmlDocument();
+ doc.LoadXml(License);
+
+ if (TryGetValidDocument(publicKey, doc) == false)
+ {
+ Log.WarnFormat("Could not validate xml signature of:\r\n{0}", License);
+ return false;
+ }
+
+ if (doc.FirstChild == null)
+ {
+ Log.WarnFormat("Could not find first child of:\r\n{0}", License);
+ return false;
+ }
+
+ if (doc.SelectSingleNode("/floating-license") != null)
+ {
+ var node = doc.SelectSingleNode("/floating-license/license-server-public-key/text()");
+ if (node == null)
+ {
+ Log.WarnFormat("Invalid license, floating license without license server public key:\r\n{0}", License);
+ throw new InvalidOperationException(
+ "Invalid license file format, floating license without license server public key");
+ }
+ return ValidateFloatingLicense(node.InnerText);
+ }
+
+ var result = ValidateXmlDocumentLicense(doc);
+ if (result && disableFutureChecks == false)
+ {
+ nextLeaseTimer.Change(TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5));
+ }
+ return result;
+ }
+ catch (RhinoLicensingException)
+ {
+ throw;
+ }
+ catch (Exception e)
+ {
+ Log.Error("Could not validate license", e);
+ return false;
+ }
+ }
+
+ private bool ValidateFloatingLicense(string publicKeyOfFloatingLicense)
+ {
+ if (DisableFloatingLicenses)
+ {
+ Log.Warn("Floating licenses have been disabled");
+ return false;
+ }
+ if (licenseServerUrl == null)
+ {
+ Log.Warn("Could not find license server url");
+ throw new InvalidOperationException("Floating license encountered, but licenseServerUrl was not set");
+ }
+
+ var success = false;
+ var licensingService = ChannelFactory<ILicensingService>.CreateChannel(new WSHttpBinding(), new EndpointAddress(licenseServerUrl));
+ try
+ {
+ var leasedLicense = licensingService.LeaseLicense(
+ Environment.MachineName,
+ Environment.UserName,
+ clientId);
+ ((ICommunicationObject)licensingService).Close();
+ success = true;
+ if (leasedLicense == null)
+ {
+ Log.WarnFormat("Null response from license server: {0}", licenseServerUrl);
+ throw new FloatingLicenseNotAvialableException();
+ }
+
+ var doc = new XmlDocument();
+ doc.LoadXml(leasedLicense);
+
+ if (TryGetValidDocument(publicKeyOfFloatingLicense, doc) == false)
+ {
+ Log.WarnFormat("Could not get valid license from floating license server {0}", licenseServerUrl);
+ throw new FloatingLicenseNotAvialableException();
+ }
+
+ var validLicense = ValidateXmlDocumentLicense(doc);
+ if (validLicense)
+ {
+ //setup next lease
+ var time = (ExpirationDate.AddMinutes(-5) - DateTime.UtcNow);
+ Log.DebugFormat("Will lease license again at {0}", time);
+ if (disableFutureChecks == false)
+ nextLeaseTimer.Change(time, time);
+ }
+ return validLicense;
+ }
+ finally
+ {
+ if (success == false)
+ ((ICommunicationObject)licensingService).Abort();
+ }
+ }
+
+ internal bool ValidateXmlDocumentLicense(XmlDocument doc)
+ {
+ XmlNode id = doc.SelectSingleNode("/license/@id");
+ if (id == null)
+ {
+ Log.WarnFormat("Could not find id attribute in license:\r\n{0}", License);
+ return false;
+ }
+
+ UserId = new Guid(id.Value);
+
+ XmlNode date = doc.SelectSingleNode("/license/@expiration");
+ if (date == null)
+ {
+ Log.WarnFormat("Could not find expiration in license:\r\n{0}", License);
+ return false;
+ }
+
+ ExpirationDate = DateTime.ParseExact(date.Value, "yyyy-MM-ddTHH:mm:ss.fffffff", CultureInfo.InvariantCulture);
+
+ XmlNode licenseType = doc.SelectSingleNode("/license/@type");
+ if (licenseType == null)
+ {
+ Log.WarnFormat("Could not find license type in {0}", licenseType);
+ return false;
+ }
+
+ LicenseType = (LicenseType)Enum.Parse(typeof(LicenseType), licenseType.Value);
+
+ XmlNode name = doc.SelectSingleNode("/license/name/text()");
+ if (name == null)
+ {
+ Log.WarnFormat("Could not find licensee's name in license:\r\n{0}", License);
+ return false;
+ }
+
+ Name = name.Value;
+
+ var license = doc.SelectSingleNode("/license");
+ foreach (XmlAttribute attrib in license.Attributes)
+ {
+ if (attrib.Name == "type" || attrib.Name == "expiration" || attrib.Name == "id")
+ continue;
+
+ LicenseAttributes[attrib.Name] = attrib.Value;
+ }
+
+ return true;
+ }
+
+ private bool TryGetValidDocument(string licensePublicKey, XmlDocument doc)
+ {
+ var rsa = new RSACryptoServiceProvider();
+ rsa.FromXmlString(licensePublicKey);
+
+ var nsMgr = new XmlNamespaceManager(doc.NameTable);
+ nsMgr.AddNamespace("sig", "http://www.w3.org/2000/09/xmldsig#");
+
+ var signedXml = new SignedXml(doc);
+ var sig = (XmlElement)doc.SelectSingleNode("//sig:Signature", nsMgr);
+ if (sig == null)
+ {
+ Log.WarnFormat("Could not find this signature node on license:\r\n{0}", License);
+ return false;
+ }
+ signedXml.LoadXml(sig);
+
+ return signedXml.CheckSignature(rsa);
+ }
+
+ /// <summary>
+ /// Disables further license checks for the session.
+ /// </summary>
+ public void DisableFutureChecks()
+ {
+ disableFutureChecks = true;
+ nextLeaseTimer.Dispose();
+ }
+ }
}
View
20 Rhino.Licensing/FloatingLicenseNotAvialableException.cs
@@ -3,22 +3,42 @@
namespace Rhino.Licensing
{
+ /// <summary>
+ ///
+ /// </summary>
public class FloatingLicenseNotAvialableException : RhinoLicensingException
{
+ /// <summary>
+ /// Creates a new instance of <seealso cref="FloatingLicenseNotAvialableException"/>.
+ /// </summary>
public FloatingLicenseNotAvialableException()
{
}
+ /// <summary>
+ /// Creates a new instance of <seealso cref="FloatingLicenseNotAvialableException"/>.
+ /// </summary>
+ /// <param name="message">error message</param>
public FloatingLicenseNotAvialableException(string message)
: base(message)
{
}
+ /// <summary>
+ /// Creates a new instance of <seealso cref="FloatingLicenseNotAvialableException"/>.
+ /// </summary>
+ /// <param name="message">error message</param>
+ /// <param name="inner">inner exception</param>
public FloatingLicenseNotAvialableException(string message, Exception inner)
: base(message, inner)
{
}
+ /// <summary>
+ /// Creates a new instance of <seealso cref="FloatingLicenseNotAvialableException"/>.
+ /// </summary>
+ /// <param name="info">serialization information</param>
+ /// <param name="context">streaming context</param>
protected FloatingLicenseNotAvialableException(
SerializationInfo info,
StreamingContext context)
View
31 Rhino.Licensing/ILicensingService.cs
@@ -1,11 +1,22 @@
-using System;
-using System.ServiceModel;
-namespace Rhino.Licensing
-{
- [ServiceContract(SessionMode = SessionMode.NotAllowed)]
- public interface ILicensingService
- {
- [OperationContract]
- string LeaseLicense(string machine, string user, Guid id);
- }
+using System;
+using System.ServiceModel;
+
+namespace Rhino.Licensing
+{
+ /// <summary>
+ /// Service contract of the licensing server.
+ /// </summary>
+ [ServiceContract(SessionMode = SessionMode.NotAllowed)]
+ public interface ILicensingService
+ {
+ /// <summary>
+ /// Issues a float license for the user.
+ /// </summary>
+ /// <param name="machine">machine name</param>
+ /// <param name="user">user name</param>
+ /// <param name="id">Id of the license holder</param>
+ /// <returns></returns>
+ [OperationContract]
+ string LeaseLicense(string machine, string user, Guid id);
+ }
}
View
28 Rhino.Licensing/ISubscriptionLicensingService.cs
@@ -1,11 +1,19 @@
-using System.ServiceModel;
-
-namespace Rhino.Licensing
-{
- [ServiceContract]
- public interface ISubscriptionLicensingService
- {
- [OperationContract]
- string LeaseLicense(string previousLicense);
- }
+using System.ServiceModel;
+
+namespace Rhino.Licensing
+{
+ /// <summary>
+ /// Service contract of subscription server.
+ /// </summary>
+ [ServiceContract]
+ public interface ISubscriptionLicensingService
+ {
+ /// <summary>
+ /// Issues a leased license
+ /// </summary>
+ /// <param name="previousLicense"></param>
+ /// <returns></returns>
+ [OperationContract]
+ string LeaseLicense(string previousLicense);
+ }
}
View
10 Rhino.Licensing/InvalidationType.cs
@@ -1,8 +1,18 @@
namespace Rhino.Licensing
{
+ /// <summary>
+ /// InvalidationType
+ /// </summary>
public enum InvalidationType
{
+ /// <summary>
+ /// Can not create a new license
+ /// </summary>
CannotGetNewLicense,
+
+ /// <summary>
+ /// License is expired
+ /// </summary>
TimeExpired
}
}
View
21 Rhino.Licensing/LicenseFileNotFoundException.cs
@@ -3,23 +3,44 @@
namespace Rhino.Licensing
{
+ /// <summary>
+ /// Thrown when a valid license file can not be
+ /// found on the client machine.
+ /// </summary>
[Serializable]
public class LicenseFileNotFoundException : RhinoLicensingException
{
+ /// <summary>
+ /// Creates a new instance of <seealso cref="LicenseFileNotFoundException"/>
+ /// </summary>
public LicenseFileNotFoundException()
{
}
+ /// <summary>
+ /// Creates a new instance of <seealso cref="LicenseFileNotFoundException"/>
+ /// </summary>
+ /// <param name="message">error message</param>
public LicenseFileNotFoundException(string message)
: base(message)
{
}
+ /// <summary>
+ /// Creates a new instance of <seealso cref="LicenseFileNotFoundException"/>
+ /// </summary>
+ /// <param name="message">error message</param>
+ /// <param name="inner">inner exception</param>
public LicenseFileNotFoundException(string message, Exception inner)
: base(message, inner)
{
}
+ /// <summary>
+ /// Creates a new instance of <seealso cref="LicenseFileNotFoundException"/>
+ /// </summary>
+ /// <param name="info">serialization information</param>
+ /// <param name="context">streaming context</param>
protected LicenseFileNotFoundException(
SerializationInfo info,
StreamingContext context) : base(info, context)
View
31 Rhino.Licensing/LicenseGenerator.cs
@@ -9,15 +9,28 @@
namespace Rhino.Licensing
{
+ /// <summary>
+ /// LicenseGenerator generates and signs license.
+ /// </summary>
public class LicenseGenerator
{
private readonly string privateKey;
+ /// <summary>
+ /// Creates a new instance of <seealso cref="LicenseGenerator"/>.
+ /// </summary>
+ /// <param name="privateKey">private key of the product</param>
public LicenseGenerator(string privateKey)
{
this.privateKey = privateKey;
}
+ /// <summary>
+ /// Generates a new floating license.
+ /// </summary>
+ /// <param name="name">Name of the license holder</param>
+ /// <param name="publicKey">public key of the license server</param>
+ /// <returns>license content</returns>
public string GenerateFloatingLicense(string name, string publicKey)
{
using (var rsa = new RSACryptoServiceProvider())
@@ -49,11 +62,29 @@ public string GenerateFloatingLicense(string name, string publicKey)
return new StreamReader(ms).ReadToEnd();
}
}
+
+ /// <summary>
+ /// Generates a new license
+ /// </summary>
+ /// <param name="name">name of the license holder</param>
+ /// <param name="id">Id of the license holder</param>
+ /// <param name="expirationDate">expiry date</param>
+ /// <param name="licenseType">type of the license</param>
+ /// <returns></returns>
public string Generate(string name, Guid id, DateTime expirationDate, LicenseType licenseType)
{
return Generate(name, id, expirationDate, new Dictionary<string, string>(), licenseType);
}
+ /// <summary>
+ /// Generates a new license
+ /// </summary>
+ /// <param name="name">name of the license holder</param>
+ /// <param name="id">Id of the license holder</param>
+ /// <param name="expirationDate">expiry date</param>
+ /// <param name="licenseType">type of the license</param>
+ /// <param name="attributes">extra information stored as key/valye in the license file</param>
+ /// <returns></returns>
public string Generate(string name, Guid id, DateTime expirationDate, IDictionary<string, string> attributes, LicenseType licenseType)
{
using (var rsa = new RSACryptoServiceProvider())
View
26 Rhino.Licensing/LicenseNotFoundException.cs
@@ -3,21 +3,43 @@
namespace Rhino.Licensing
{
+ /// <summary>
+ /// Thrown when suitable license is not found.
+ /// </summary>
[Serializable]
public class LicenseNotFoundException : RhinoLicensingException
{
+ /// <summary>
+ /// Creates a new instance of <seealso cref="LicenseNotFoundException"/>.
+ /// </summary>
public LicenseNotFoundException()
{
}
- public LicenseNotFoundException(string message) : base(message)
+ /// <summary>
+ /// Creates a new instance of <seealso cref="LicenseNotFoundException"/>.
+ /// </summary>
+ /// <param name="message">error message</param>
+ public LicenseNotFoundException(string message)
+ : base(message)
{
}
- public LicenseNotFoundException(string message, Exception inner) : base(message, inner)
+ /// <summary>
+ /// Creates a new instance of <seealso cref="LicenseNotFoundException"/>.
+ /// </summary>
+ /// <param name="message">error message</param>
+ /// <param name="inner">inner exception</param>
+ public LicenseNotFoundException(string message, Exception inner)
+ : base(message, inner)
{
}
+ /// <summary>
+ /// Creates a new instance of <seealso cref="LicenseNotFoundException"/>.
+ /// </summary>
+ /// <param name="info">serialization information</param>
+ /// <param name="context">steaming context</param>
protected LicenseNotFoundException(
SerializationInfo info,
StreamingContext context) : base(info, context)
View
26 Rhino.Licensing/LicenseType.cs
@@ -1,12 +1,38 @@
namespace Rhino.Licensing
{
+ /// <summary>
+ /// License Type
+ /// </summary>
public enum LicenseType
{
+ /// <summary>
+ /// No type specified
+ /// </summary>
None,
+
+ /// <summary>
+ /// For trial use
+ /// </summary>
Trial,
+
+ /// <summary>
+ /// Standard license
+ /// </summary>
Standard,
+
+ /// <summary>
+ /// For personal use
+ /// </summary>
Personal,
+
+ /// <summary>
+ /// Floating license
+ /// </summary>
Floating,
+
+ /// <summary>
+ /// Subscription based license
+ /// </summary>
Subscription
}
}
View
25 Rhino.Licensing/LicenseValidator.cs
@@ -3,23 +3,42 @@
namespace Rhino.Licensing
{
+ /// <summary>
+ /// License validator validates a license file
+ /// that can be located on disk.
+ /// </summary>
public class LicenseValidator : AbstractLicenseValidator
{
private readonly string licensePath;
private string inMemoryLicense;
+ /// <summary>
+ /// Creates a new instance of <seealso cref="LicenseValidator"/>.
+ /// </summary>
+ /// <param name="publicKey">public key</param>
+ /// <param name="licensePath">path to license file</param>
public LicenseValidator(string publicKey, string licensePath)
: base(publicKey)
{
this.licensePath = licensePath;
}
+ /// <summary>
+ /// Creates a new instance of <seealso cref="LicenseValidator"/>.
+ /// </summary>
+ /// <param name="publicKey">public key</param>
+ /// <param name="licensePath">path to license file</param>
+ /// <param name="licenseServerUrl">license server endpoint address</param>
+ /// <param name="clientId">Id of the license holder</param>
public LicenseValidator(string publicKey, string licensePath, string licenseServerUrl, Guid clientId)
: base(publicKey, licenseServerUrl, clientId)
{
this.licensePath = licensePath;
}
+ /// <summary>
+ /// Gets or Sets the license content
+ /// </summary>
protected override string License
{
get
@@ -40,6 +59,9 @@ protected override string License
}
}
+ /// <summary>
+ /// Validates loaded license
+ /// </summary>
public override void AssertValidLicense()
{
if (File.Exists(licensePath) == false)
@@ -51,6 +73,9 @@ public override void AssertValidLicense()
base.AssertValidLicense();
}
+ /// <summary>
+ /// Removes existing license from the machine.
+ /// </summary>
public override void RemoveExistingLicense()
{
File.Delete(licensePath);
View
25 Rhino.Licensing/LicensingService.cs
@@ -7,16 +7,22 @@ namespace Rhino.Licensing
using System.ServiceModel;
using System.Linq;
- // because we use this service behavior,
- // we don't have to worry about multi threading issues.
- // it is not something that we expect to have to deal with huge load, anyway
+ /// <summary>
+ /// Licensing server implementation.
+ /// Because we use this service behavior, we don't have to worry
+ /// about multi threading issues. it is not something that we
+ /// expect to have to deal with huge load, anyway.
+ /// </summary>
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]
public class LicensingService : ILicensingService
{
private readonly List<LicenseValidator> availableLicenses = new List<LicenseValidator>();
private readonly Dictionary<string, KeyValuePair<DateTime, LicenseValidator>> leasedLicenses = new Dictionary<string, KeyValuePair<DateTime, LicenseValidator>>();
private readonly string state;
+ /// <summary>
+ /// Creates a new instance of <seealso cref="LicensingService"/>.
+ /// </summary>
public LicensingService()
{
if (SoftwarePublicKey == null)
@@ -35,11 +41,17 @@ public LicensingService()
ReadInitialState();
}
+ /// <summary>
+ /// Gets or Sets the public key of the product
+ /// </summary>
public static string SoftwarePublicKey
{
get; set;
}
+ /// <summary>
+ /// Gets or Sets the private key of the license server
+ /// </summary>
public static string LicenseServerPrivateKey
{
get; set;
@@ -149,6 +161,13 @@ private void WriteState(Stream stream)
}
}
+ /// <summary>
+ /// Leases a new license to the client machine.
+ /// </summary>
+ /// <param name="machine">client machine name</param>
+ /// <param name="user">user name</param>
+ /// <param name="id">Id of the license holder</param>
+ /// <returns></returns>
public string LeaseLicense(string machine, string user, Guid id)
{
KeyValuePair<DateTime, LicenseValidator> value;
View
21 Rhino.Licensing/RhinoLicensingException.cs
@@ -3,22 +3,43 @@
namespace Rhino.Licensing
{
+ /// <summary>
+ /// Base class for all licensing exceptions.
+ /// </summary>
+ [Serializable]
public class RhinoLicensingException : Exception
{
+ /// <summary>
+ /// Creates a new instance of <seealso cref="RhinoLicensingException"/>.
+ /// </summary>
protected RhinoLicensingException()
{
}
+ /// <summary>
+ /// Creates a new instance of <seealso cref="RhinoLicensingException"/>.
+ /// </summary>
+ /// <param name="message">error message</param>
protected RhinoLicensingException(string message)
: base(message)
{
}
+ /// <summary>
+ /// Creates a new instance of <seealso cref="RhinoLicensingException"/>.
+ /// </summary>
+ /// <param name="message">error message</param>
+ /// <param name="inner">inner exception</param>
protected RhinoLicensingException(string message, Exception inner)
: base(message, inner)
{
}
+ /// <summary>
+ /// Creates a new instance of <seealso cref="RhinoLicensingException"/>.
+ /// </summary>
+ /// <param name="info">serialization information</param>
+ /// <param name="context">streaming context</param>
protected RhinoLicensingException(
SerializationInfo info,
StreamingContext context)
View
35 Rhino.Licensing/SntpClient.cs
@@ -4,12 +4,20 @@
namespace Rhino.Licensing
{
+ /// <summary>
+ /// A SNTP client that is used to load time with server.
+ /// For more information see http://en.wikipedia.org/wiki/SNTP />
+ /// </summary>
public class SntpClient
{
private const byte SntpDataLength = 48;
private readonly string[] hosts;
private int index = -1;
+ /// <summary>
+ /// Creates a new instance of <seealso cref="SntpClient"/>.
+ /// </summary>
+ /// <param name="hosts">addresses of internet SNTP servers</param>
public SntpClient(string[] hosts)
{
this.hosts = hosts;
@@ -47,6 +55,11 @@ private static ulong GetMilliSeconds(byte[] sntpData, byte offset)
return milliseconds;
}
+ /// <summary>
+ /// Starts to get current date/time
+ /// </summary>
+ /// <param name="getTime"></param>
+ /// <param name="failure"></param>
public void BeginGetDate(Action<DateTime> getTime, Action failure)
{
index += 1;
@@ -140,8 +153,18 @@ private bool IsResponseValid(byte[] sntpData)
#region Nested type: State
+ /// <summary>
+ /// Maintains state of the SNTP client.
+ /// </summary>
public class State
{
+ /// <summary>
+ /// Creates a new instance of <seealso cref="State"/> object.
+ /// </summary>
+ /// <param name="socket">socket</param>
+ /// <param name="endPoint">server endpoint</param>
+ /// <param name="getTime">action to get the time</param>
+ /// <param name="failure">action to handle errors</param>
public State(UdpClient socket, IPEndPoint endPoint, Action<DateTime> getTime, Action failure)
{
Socket = socket;
@@ -150,12 +173,24 @@ public State(UdpClient socket, IPEndPoint endPoint, Action<DateTime> getTime, Ac
Failure = failure;
}
+ /// <summary>
+ /// Gets the socket to the time server
+ /// </summary>
public UdpClient Socket { get; private set; }
+ /// <summary>
+ /// Gets the action to do to get the time from the server.
+ /// </summary>
public Action<DateTime> GetTime { get; private set; }
+ /// <summary>
+ /// Gets the action to perform when an error occurs.
+ /// </summary>
public Action Failure { get; private set; }
+ /// <summary>
+ /// Endpoint address of the time server.
+ /// </summary>
public IPEndPoint EndPoint { get; private set; }
}
View
11 Rhino.Licensing/StringLicenseValidator.cs
@@ -1,13 +1,24 @@
namespace Rhino.Licensing
{
+ /// <summary>
+ /// Validates content of a license file
+ /// </summary>
public class StringLicenseValidator : AbstractLicenseValidator
{
+ /// <summary>
+ /// Creates a new instance of <seealso cref="StringLicenseValidator"/>
+ /// </summary>
+ /// <param name="publicKey">public key</param>
+ /// <param name="license">license content</param>
public StringLicenseValidator(string publicKey, string license)
: base(publicKey)
{
License = license;
}
+ /// <summary>
+ /// License content
+ /// </summary>
protected override string License
{
get; set;

0 comments on commit cc63229

Please sign in to comment.