Skip to content
This repository was archived by the owner on Dec 24, 2022. It is now read-only.

Commit 52f7907

Browse files
committed
Add new options
1 parent 52082ae commit 52f7907

File tree

2 files changed

+170
-2
lines changed

2 files changed

+170
-2
lines changed

src/ServiceStack.Text/Env.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,8 @@ static Env()
109109
+ (IsMono ? "/Mono" : "")
110110
+ (IsLinux ? "/Linux" : IsOSX ? "/OSX" : IsUnix ? "/Unix" : IsWindows ? "/Windows" : "/UnknownOS")
111111
+ (IsIOS ? "/iOS" : IsAndroid ? "/Android" : IsUWP ? "/UWP" : "")
112-
+ (IsNet6 ? "/net6" : IsNetStandard20 ? "/std2.0" : IsNetFramework ? "netfx" : "");
112+
+ (IsNet6 ? "/net6" : IsNetStandard20 ? "/std2.0" : IsNetFramework ? "netfx" : "")
113+
+ ($"/{LicenseUtils.Info}");
113114

114115
__releaseDate = new DateTime(2001,01,01);
115116
}

src/ServiceStack.Text/LicenseUtils.cs

Lines changed: 168 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System;
55
using System.Collections.Generic;
6+
using System.ComponentModel;
67
using System.Globalization;
78
using System.IO;
89
using System.Linq;
@@ -22,6 +23,8 @@ public LicenseException(string message, Exception innerException) : base(message
2223
public enum LicenseType
2324
{
2425
Free,
26+
FreeIndividual,
27+
FreeOpenSource,
2528
Indie,
2629
Business,
2730
Enterprise,
@@ -210,6 +213,12 @@ public static void RegisterLicense(string licenseKeyText)
210213
Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
211214
try
212215
{
216+
if (IsFreeLicenseKey(licenseKeyText))
217+
{
218+
ValidateFreeLicenseKey(licenseKeyText);
219+
return;
220+
}
221+
213222
var parts = licenseKeyText.SplitOnFirst('-');
214223
subId = parts[0];
215224

@@ -227,7 +236,7 @@ public static void RegisterLicense(string licenseKeyText)
227236
catch (Exception ex)
228237
{
229238
//bubble unrelated project Exceptions
230-
if (ex is FileNotFoundException || ex is FileLoadException || ex is BadImageFormatException)
239+
if (ex is FileNotFoundException || ex is FileLoadException || ex is BadImageFormatException || ex is NotSupportedException)
231240
throw;
232241

233242
if (ex is LicenseException)
@@ -277,6 +286,162 @@ private static void ValidateLicenseKey(LicenseKey key)
277286
if (LicenseWarningMessage != null)
278287
Console.WriteLine(LicenseWarningMessage);
279288
}
289+
290+
private const string IndividualPrefix = "Individual (c) ";
291+
private const string OpenSourcePrefix = "OSS ";
292+
293+
private static bool IsFreeLicenseKey(string licenseText) =>
294+
licenseText.StartsWith(IndividualPrefix) || licenseText.StartsWith(OpenSourcePrefix);
295+
296+
private static void ValidateFreeLicenseKey(string licenseText)
297+
{
298+
if (!IsFreeLicenseKey(licenseText))
299+
throw new NotSupportedException("Not a free License Key");
300+
301+
var envKey = Environment.GetEnvironmentVariable("SERVICESTACK_LICENSE");
302+
if (envKey == licenseText)
303+
throw new LicenseException("Cannot use SERVICESTACK_LICENSE Environment variable with free License Keys, " +
304+
"please use Licensing.RegisterLicense() in source code.");
305+
306+
LicenseKey key = null;
307+
if (licenseText.StartsWith(IndividualPrefix))
308+
{
309+
key = VerifyIndividualLicense(licenseText);
310+
if (key == null)
311+
throw new LicenseException("Individual License Key is invalid.");
312+
}
313+
else if (licenseText.StartsWith(OpenSourcePrefix))
314+
{
315+
key = VerifyOpenSourceLicense(licenseText);
316+
if (key == null)
317+
throw new LicenseException("Open Source License Key is invalid.");
318+
}
319+
else throw new NotSupportedException("Not a free License Key");
320+
321+
var releaseDate = Env.GetReleaseDate();
322+
if (releaseDate > key.Expiry)
323+
throw new LicenseException($"This license has expired on {key.Expiry:d} and is not valid for use with this release.\n"
324+
+ "Check https://servicestack.net/free for eligible renewals.").Trace();
325+
326+
__activatedLicense = new __ActivatedLicense(key);
327+
}
328+
329+
internal static string Info => __activatedLicense?.LicenseKey == null
330+
? "NO"
331+
: __activatedLicense.LicenseKey.Type switch {
332+
LicenseType.Free => "FR",
333+
LicenseType.FreeIndividual => "FI",
334+
LicenseType.FreeOpenSource => "FO",
335+
LicenseType.Indie => "IN",
336+
LicenseType.Business => "BU",
337+
LicenseType.Enterprise => "EN",
338+
LicenseType.TextIndie => "TI",
339+
LicenseType.TextBusiness => "TB",
340+
LicenseType.OrmLiteIndie => "OI",
341+
LicenseType.OrmLiteBusiness => "OB",
342+
LicenseType.RedisIndie => "RI",
343+
LicenseType.RedisBusiness => "RB",
344+
LicenseType.AwsIndie => "AI",
345+
LicenseType.AwsBusiness => "AB",
346+
LicenseType.Trial => "TR",
347+
LicenseType.Site => "SI",
348+
LicenseType.TextSite => "TS",
349+
LicenseType.RedisSite => "RS",
350+
LicenseType.OrmLiteSite => "OS",
351+
_ => "UN",
352+
};
353+
354+
private static LicenseKey VerifyIndividualLicense(string licenseKey)
355+
{
356+
if (licenseKey == null)
357+
return null;
358+
if (licenseKey.Length < 100)
359+
return null;
360+
if (!licenseKey.StartsWith(IndividualPrefix))
361+
return null;
362+
var keyText = licenseKey.LastLeftPart(' ');
363+
var keySign = licenseKey.LastRightPart(' ');
364+
if (keySign.Length < 48)
365+
return null;
366+
367+
try
368+
{
369+
var rsa = System.Security.Cryptography.RSA.Create();
370+
rsa.FromXml(LicensePublicKey);
371+
372+
#if !NETCORE
373+
var verified = ((System.Security.Cryptography.RSACryptoServiceProvider)rsa)
374+
.VerifyData(keyText.ToUtf8Bytes(), "SHA256", Convert.FromBase64String(keySign));
375+
#else
376+
var verified = rsa.VerifyData(keyText.ToUtf8Bytes(),
377+
Convert.FromBase64String(keySign),
378+
System.Security.Cryptography.HashAlgorithmName.SHA256,
379+
System.Security.Cryptography.RSASignaturePadding.Pkcs1);
380+
#endif
381+
if (verified)
382+
{
383+
var yearStr = keyText.Substring(IndividualPrefix.Length).LeftPart(' ');
384+
if (yearStr.Length == 4 && int.TryParse(yearStr, out var year))
385+
{
386+
return new LicenseKey {
387+
Expiry = new DateTime(year + 1, 1, 1, 0, 0, 0, DateTimeKind.Utc),
388+
Hash = keySign,
389+
Name = keyText,
390+
Type = LicenseType.FreeIndividual,
391+
};
392+
}
393+
}
394+
}
395+
catch { }
396+
397+
return null;
398+
}
399+
400+
private static LicenseKey VerifyOpenSourceLicense(string licenseKey)
401+
{
402+
if (licenseKey == null)
403+
return null;
404+
if (licenseKey.Length < 100)
405+
return null;
406+
if (!licenseKey.StartsWith(OpenSourcePrefix))
407+
return null;
408+
var keyText = licenseKey.LastLeftPart(' ');
409+
var keySign = licenseKey.LastRightPart(' ');
410+
if (keySign.Length < 48)
411+
return null;
412+
413+
try
414+
{
415+
var rsa = System.Security.Cryptography.RSA.Create();
416+
rsa.FromXml(LicensePublicKey);
417+
418+
#if !NETCORE
419+
var verified = ((System.Security.Cryptography.RSACryptoServiceProvider)rsa)
420+
.VerifyData(keyText.ToUtf8Bytes(), "SHA256", Convert.FromBase64String(keySign));
421+
#else
422+
var verified = rsa.VerifyData(keyText.ToUtf8Bytes(),
423+
Convert.FromBase64String(keySign),
424+
System.Security.Cryptography.HashAlgorithmName.SHA256,
425+
System.Security.Cryptography.RSASignaturePadding.Pkcs1);
426+
#endif
427+
if (verified)
428+
{
429+
var yearStr = keyText.Substring(OpenSourcePrefix.Length).RightPart(' ').LeftPart(' ');
430+
if (yearStr.Length == 4 && int.TryParse(yearStr, out var year))
431+
{
432+
return new LicenseKey {
433+
Expiry = new DateTime(year + 1, 1, 1, 0, 0, 0, DateTimeKind.Utc),
434+
Hash = keySign,
435+
Name = keyText,
436+
Type = LicenseType.FreeOpenSource,
437+
};
438+
}
439+
}
440+
}
441+
catch { }
442+
443+
return null;
444+
}
280445

281446
public static void RemoveLicense()
282447
{
@@ -382,6 +547,8 @@ public static LicenseFeature GetLicensedFeatures(this LicenseKey key)
382547
case LicenseType.Free:
383548
return LicenseFeature.Free;
384549

550+
case LicenseType.FreeIndividual:
551+
case LicenseType.FreeOpenSource:
385552
case LicenseType.Indie:
386553
case LicenseType.Business:
387554
case LicenseType.Enterprise:

0 commit comments

Comments
 (0)