001: package com.xoetrope.editor.lm;
002:
003: import com.xoetrope.carousel.build.BuildProperties;
004: import java.io.BufferedReader;
005: import java.io.ByteArrayInputStream;
006: import java.io.ByteArrayOutputStream;
007: import java.io.File;
008: import java.io.FileOutputStream;
009: import java.io.FileReader;
010: import java.io.ObjectInputStream;
011: import java.io.ObjectOutput;
012: import java.io.ObjectOutputStream;
013: import java.io.OutputStreamWriter;
014: import java.io.Writer;
015: import java.nio.charset.Charset;
016: import java.security.KeyFactory;
017: import java.security.PublicKey;
018: import java.security.Signature;
019: import java.security.spec.AlgorithmParameterSpec;
020: import java.security.spec.EncodedKeySpec;
021: import java.security.spec.KeySpec;
022: import java.security.spec.X509EncodedKeySpec;
023: import java.util.Date;
024: import java.util.prefs.Preferences;
025: import javax.crypto.Cipher;
026: import javax.crypto.SealedObject;
027: import javax.crypto.SecretKey;
028: import javax.crypto.SecretKeyFactory;
029: import javax.crypto.spec.PBEKeySpec;
030: import javax.crypto.spec.PBEParameterSpec;
031: import net.xoetrope.debug.DebugLogger;
032: import net.xoetrope.editor.lm.LicenseManager;
033:
034: /**
035: * A License Manager interface
036: * @since 3.2
037: * <p> Copyright (c) Xoetrope Ltd., 2002-2008</p>
038: * <p> License: see License.txt</p>
039: */
040: public class XuiProLicenseManager implements LicenseManager {
041: private static long ONE_YEAR = 31536000000L;
042: private static long ONE_MONTH = 2592000000L; // 30 days
043: private static long ONE_DAY = 86400000L;
044: private static long lastRegAttempt;
045: private static long endRegDate;
046:
047: // 8-byte Salt
048: private byte[] salt = { (byte) 0xA9, (byte) 0x9B, (byte) 0xC8,
049: (byte) 0x32, (byte) 0x56, (byte) 0x35, (byte) 0xE3,
050: (byte) 0x03 };
051:
052: // Iteration count
053: private int iterationCount = 19;
054: private String passPhrase = "sdfsadf098psjdf09sl;dff";
055: private PublicKey publicKey;
056:
057: private License license;
058:
059: private File storageDir;
060: private Preferences prefs;
061: private int checkCount;
062:
063: public XuiProLicenseManager() {
064: prefs = Preferences
065: .userNodeForPackage(XuiProLicenseManager.class);
066: loadLicense();
067: }
068:
069: public boolean isUserRegistered(String moduleName) {
070: /*
071: * This check is not intended as a license enforcement technique, instead it
072: * is intended to remind users to register those components that require
073: * registration as a license condition of their use.
074: *
075: * Under NO circumstances should this code be removed from the source code
076: * or modified or by-passed in any way.
077: */
078: if (isRegistrationValid(moduleName))
079: return true;
080:
081: return false;
082: }
083:
084: private boolean isRegistrationValid(String module) {
085: /*
086: * This check is not intended as a license enforcement technique, instead it
087: * is intended to remind users to register those components that require
088: * registration as a license condition of their use.
089: *
090: * Under NO circumstances should this code be removed from the source code
091: * or modified or by-passed in any way.
092: */
093: String userName = System.getProperty("user.name");
094:
095: long lastUse = prefs.getLong("regTime", Long.MAX_VALUE);
096: long now = new Date().getTime();
097: prefs.putLong("regTime", now);
098: if (now < lastUse)
099: return false;
100:
101: if (license != null) {
102: if (!isEvaluationValid())
103: return false;
104:
105: for (LicenseEntry le : license.licenseEntries) {
106: if (le.module.equals(module)) {
107: if (le.expiry > now) {
108: if (le.userName.equals(userName)) {
109: if ((checkCount++ % 83) == 0)
110: return checkSignature();
111: else
112: return true;
113: }
114: }
115: }
116: }
117: }
118:
119: return false;
120: }
121:
122: private boolean isEvaluationValid() {
123: String xoetropeUserName = prefs.get("user", null);
124: for (LicenseEntry le : license.licenseEntries) {
125: if (xoetropeUserName == null) {
126: prefs.put("user", le.xoetropeUserName);
127: return true;
128: } else if (le.module.equals("XUI Pro")) {
129: return le.xoetropeUserName.equals(xoetropeUserName);
130: }
131: }
132:
133: return false;
134: }
135:
136: public void processRegistration(String regFile) {
137: if (decrypt(regFile))
138: storeLicense(regFile);
139: else
140: license = null;
141: }
142:
143: private void storeLicense(String regFile) {
144: try {
145: String userName = System.getProperty("user.name");
146: File licenseFile = new File(getStorageDirectory(), userName
147: + ".reg");
148: FileOutputStream fos = new FileOutputStream(licenseFile);
149: Writer wr = new OutputStreamWriter(fos, Charset
150: .forName("UTF-8"));
151: wr.write(regFile);
152: wr.flush();
153: fos.flush();
154: fos.close();
155: } catch (Exception e) {
156: e.printStackTrace();
157: }
158: }
159:
160: private void loadLicense() {
161: try {
162: String userName = System.getProperty("user.name");
163: File licenseFile = new File(getStorageDirectory(), userName
164: + ".reg");
165: String regFile = "";
166:
167: if (licenseFile.exists()) {
168: BufferedReader in = new BufferedReader(new FileReader(
169: licenseFile));
170: String str;
171: while ((str = in.readLine()) != null) {
172: regFile += str;
173: }
174: in.close();
175:
176: if (!decrypt(regFile)) {
177: license = null;
178: }
179: }
180: } catch (Exception e) {
181: license = null;
182: e.printStackTrace();
183: }
184: }
185:
186: private boolean decrypt(String str) {
187: try {
188: // Strip the padding
189: String prefix = "-----BEGIN LICENSE-----";
190: String suffix = "-----END LICENSE-----";
191: if (str.indexOf(prefix) < 0)
192: return false;
193: if (str.indexOf(suffix) < 0)
194: return false;
195:
196: KeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(),
197: salt, iterationCount);
198: SecretKey key = SecretKeyFactory.getInstance(
199: "PBEWithMD5AndDES").generateSecret(keySpec);
200: Cipher dcipher = Cipher.getInstance(key.getAlgorithm());
201:
202: // Prepare the parameter to the ciphers
203: AlgorithmParameterSpec paramSpec = new PBEParameterSpec(
204: salt, iterationCount);
205:
206: dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
207:
208: str = str.substring(prefix.length());
209: if (str.startsWith("\r"))
210: str = str.substring(1);
211: if (str.startsWith("\n"))
212: str = str.substring(1);
213: str = str.substring(0, str.indexOf(suffix));
214: if (str.endsWith("\r"))
215: str = str.substring(0, str.length() - 1);
216: if (str.endsWith("\n"))
217: str = str.substring(0, str.length() - 1);
218:
219: // Decode base64 to get bytes
220: byte[] bytes = new sun.misc.BASE64Decoder()
221: .decodeBuffer(str);
222:
223: ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
224: ObjectInputStream ois = new ObjectInputStream(bis);
225: SealedObject so = (SealedObject) ois.readObject();
226: license = (License) so.getObject(dcipher);
227:
228: return checkSignature();
229: } catch (Exception e) {
230: e.printStackTrace();
231: }
232:
233: return false;
234: }
235:
236: private boolean checkSignature() {
237: if (license == null)
238: return false;
239:
240: try {
241: ByteArrayOutputStream b = new ByteArrayOutputStream();
242: ObjectOutput a = new ObjectOutputStream(b);
243:
244: a.writeObject(license.licenseEntries);
245: a.flush();
246: a.close();
247: byte[] buffer = b.toByteArray();
248: b.close();
249:
250: if (publicKey == null) {
251: String publicKeyString = "MIIBtzCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZp"
252: + "RV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fn"
253: + "xqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmCouuE"
254: + "C/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJ"
255: + "FnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImo"
256: + "g9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoDgYQAAoGAM5l8cMV9jvKjUiAMNaCRhm8c7yhx7r56928d"
257: + "o9O0Mktvqb4F1b6EWe0tIN6KiQ+Yd6X9/aeH087i0xMlB6yS5cFX1RXWlHMH7KNS4ycrY+0H/kAG"
258: + "CPZUvhIT64Jm5jGVUMtGfUJpjakMHIBlrzxBf3jxfAYCkgErwb7Gc6qDDas=";
259:
260: byte[] publicKeyBytes = new sun.misc.BASE64Decoder()
261: .decodeBuffer(publicKeyString);
262:
263: KeyFactory keyFactory = KeyFactory.getInstance("DSA");
264: EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(
265: publicKeyBytes);
266: publicKey = keyFactory.generatePublic(publicKeySpec);
267: }
268:
269: byte[] soBytes = new sun.misc.BASE64Decoder()
270: .decodeBuffer(license.signature);
271:
272: Signature sig = Signature.getInstance(publicKey
273: .getAlgorithm());
274: sig.initVerify(publicKey);
275: sig.update(buffer);
276: return sig.verify(soBytes);
277: } catch (Exception ex) {
278: ex.printStackTrace();
279: }
280:
281: license = null;
282: return false;
283: }
284:
285: /**
286: * Get the directory name to which the library will be extracted.
287: * @return the path
288: */
289: public File getStorageDirectory() {
290: if (storageDir == null) {
291: try {
292: String home = System.getProperty("user.home");
293: if (BuildProperties.DEBUG)
294: DebugLogger.trace("user.home: " + home);
295:
296: storageDir = new File(home, "XuiPro");
297: if (!storageDir.exists())
298: storageDir.mkdir();
299: } catch (Exception ex) {
300: }
301: }
302:
303: return storageDir;
304: }
305:
306: /**
307: * Get the license entry for a module
308: * @param module
309: * @return
310: */
311: public LicenseEntry getLicenseDetails(String moduleName) {
312: String userName = System.getProperty("user.name");
313:
314: long lastUse = prefs.getLong("regTime", Long.MAX_VALUE);
315: long now = new Date().getTime();
316: prefs.putLong("regTime", now);
317:
318: if (license != null) {
319: for (LicenseEntry le : license.licenseEntries) {
320: if (le.module.equals(moduleName)) {
321: if (le.expiry > now) {
322: if (le.userName.equals(userName)) {
323: return new LicenseEntry(le);
324: }
325: }
326: }
327: }
328: }
329: return null;
330: }
331: }
|