Allow non cert files to be enterprise (#3346)

# Description of Changes

Please provide a summary of the changes, including:

- What was changed
- Why the change was made
- Any challenges encountered

Closes #(issue_number)

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing)
for more details.
This commit is contained in:
Anthony Stirling 2025-04-14 10:41:11 +01:00 committed by GitHub
parent 1c655f0ba0
commit f0ed60a933
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 50 additions and 35 deletions

View File

@ -29,7 +29,7 @@ ext {
} }
group = "stirling.software" group = "stirling.software"
version = "0.45.4" version = "0.45.5"
java { java {
// 17 is lowest but we support and recommend 21 // 17 is lowest but we support and recommend 21

View File

@ -53,24 +53,37 @@ public class KeygenLicenseVerifier {
} }
public License verifyLicense(String licenseKeyOrCert) { public License verifyLicense(String licenseKeyOrCert) {
if (isCertificateLicense(licenseKeyOrCert)) { License license;
log.info("Detected certificate-based license. Processing...");
return resultToEnum(verifyCertificateLicense(licenseKeyOrCert), License.ENTERPRISE); if (isCertificateLicense(licenseKeyOrCert)) {
} else if (isJWTLicense(licenseKeyOrCert)) { log.info("Detected certificate-based license. Processing...");
log.info("Detected JWT-style license key. Processing..."); boolean isValid = verifyCertificateLicense(licenseKeyOrCert);
return resultToEnum(verifyJWTLicense(licenseKeyOrCert), License.ENTERPRISE); if (isValid) {
} else { license = isEnterpriseLicense ? License.ENTERPRISE : License.PRO;
log.info("Detected standard license key. Processing..."); } else {
return resultToEnum(verifyStandardLicense(licenseKeyOrCert), License.PRO); license = License.NORMAL;
} }
} else if (isJWTLicense(licenseKeyOrCert)) {
log.info("Detected JWT-style license key. Processing...");
boolean isValid = verifyJWTLicense(licenseKeyOrCert);
if (isValid) {
license = isEnterpriseLicense ? License.ENTERPRISE : License.PRO;
} else {
license = License.NORMAL;
}
} else {
log.info("Detected standard license key. Processing...");
boolean isValid = verifyStandardLicense(licenseKeyOrCert);
if (isValid) {
license = isEnterpriseLicense ? License.ENTERPRISE : License.PRO;
} else {
license = License.NORMAL;
}
}
return license;
} }
private License resultToEnum(boolean result, License option) { private boolean isEnterpriseLicense = false;
if (result) {
return option;
}
return License.NORMAL;
}
private boolean isCertificateLicense(String license) { private boolean isCertificateLicense(String license) {
return license != null && license.trim().startsWith(CERT_PREFIX); return license != null && license.trim().startsWith(CERT_PREFIX);
@ -82,8 +95,6 @@ public class KeygenLicenseVerifier {
private boolean verifyCertificateLicense(String licenseFile) { private boolean verifyCertificateLicense(String licenseFile) {
try { try {
log.info("Verifying certificate-based license");
String encodedPayload = licenseFile; String encodedPayload = licenseFile;
// Remove the header // Remove the header
encodedPayload = encodedPayload.replace(CERT_PREFIX, ""); encodedPayload = encodedPayload.replace(CERT_PREFIX, "");
@ -106,8 +117,6 @@ public class KeygenLicenseVerifier {
encryptedData = (String) attrs.get("enc"); encryptedData = (String) attrs.get("enc");
encodedSignature = (String) attrs.get("sig"); encodedSignature = (String) attrs.get("sig");
algorithm = (String) attrs.get("alg"); algorithm = (String) attrs.get("alg");
log.info("Certificate algorithm: {}", algorithm);
} catch (JSONException e) { } catch (JSONException e) {
log.error("Failed to parse license file: {}", e.getMessage()); log.error("Failed to parse license file: {}", e.getMessage());
return false; return false;
@ -151,7 +160,6 @@ public class KeygenLicenseVerifier {
private boolean verifyEd25519Signature(String encryptedData, String encodedSignature) { private boolean verifyEd25519Signature(String encryptedData, String encodedSignature) {
try { try {
log.info("Signature to verify: {}", encodedSignature); log.info("Signature to verify: {}", encodedSignature);
log.info("Public key being used: {}", PUBLIC_KEY);
byte[] signatureBytes = Base64.getDecoder().decode(encodedSignature); byte[] signatureBytes = Base64.getDecoder().decode(encodedSignature);
@ -185,7 +193,7 @@ public class KeygenLicenseVerifier {
private boolean processCertificateData(String certData) { private boolean processCertificateData(String certData) {
try { try {
log.info("Processing certificate data: {}", certData);
JSONObject licenseData = new JSONObject(certData); JSONObject licenseData = new JSONObject(certData);
JSONObject metaObj = licenseData.optJSONObject("meta"); JSONObject metaObj = licenseData.optJSONObject("meta");
@ -234,18 +242,9 @@ public class KeygenLicenseVerifier {
applicationProperties.getPremium().setMaxUsers(users); applicationProperties.getPremium().setMaxUsers(users);
log.info("License allows for {} users", users); log.info("License allows for {} users", users);
} }
isEnterpriseLicense = metadataObj.optBoolean("isEnterprise", false);
} }
// Check maxUsers directly in attributes if present from policy definition
// if (attributesObj.has("maxUsers")) {
// int maxUsers = attributesObj.optInt("maxUsers", 0);
// if (maxUsers > 0) {
// applicationProperties.getPremium().setMaxUsers(maxUsers);
// log.info("License directly specifies {} max users",
// maxUsers);
// }
// }
// Check license status if available // Check license status if available
String status = attributesObj.optString("status", null); String status = attributesObj.optString("status", null);
if (status != null if (status != null
@ -388,9 +387,10 @@ public class KeygenLicenseVerifier {
String policyId = policyObj.optString("id", "unknown"); String policyId = policyObj.optString("id", "unknown");
log.info("License uses policy: {}", policyId); log.info("License uses policy: {}", policyId);
// Extract max users from policy if available (customize based on your policy // Extract max users and isEnterprise from policy or metadata
// structure)
int users = policyObj.optInt("users", 0); int users = policyObj.optInt("users", 0);
isEnterpriseLicense = policyObj.optBoolean("isEnterprise", false);
if (users > 0) { if (users > 0) {
applicationProperties.getPremium().setMaxUsers(users); applicationProperties.getPremium().setMaxUsers(users);
log.info("License allows for {} users", users); log.info("License allows for {} users", users);
@ -402,12 +402,16 @@ public class KeygenLicenseVerifier {
users = metadata.optInt("users", 1); users = metadata.optInt("users", 1);
applicationProperties.getPremium().setMaxUsers(users); applicationProperties.getPremium().setMaxUsers(users);
log.info("License allows for {} users (from metadata)", users); log.info("License allows for {} users (from metadata)", users);
// Check for isEnterprise flag in metadata
isEnterpriseLicense = metadata.optBoolean("isEnterprise", false);
} else { } else {
// Default value // Default value
applicationProperties.getPremium().setMaxUsers(1); applicationProperties.getPremium().setMaxUsers(1);
log.info("Using default of 1 user for license"); log.info("Using default of 1 user for license");
} }
} }
} }
return true; return true;
@ -494,6 +498,7 @@ public class KeygenLicenseVerifier {
log.info("Validation detail: " + detail); log.info("Validation detail: " + detail);
log.info("Validation code: " + code); log.info("Validation code: " + code);
// Extract user count
int users = int users =
jsonResponse jsonResponse
.path("data") .path("data")
@ -502,6 +507,16 @@ public class KeygenLicenseVerifier {
.path("users") .path("users")
.asInt(0); .asInt(0);
applicationProperties.getPremium().setMaxUsers(users); applicationProperties.getPremium().setMaxUsers(users);
// Extract isEnterprise flag
isEnterpriseLicense =
jsonResponse
.path("data")
.path("attributes")
.path("metadata")
.path("isEnterprise")
.asBoolean(false);
log.info(applicationProperties.toString()); log.info(applicationProperties.toString());
} else { } else {