Advertisement
Guest User

PowerMTA 4.5r3 MC - LAK

a guest
Jun 14th, 2016
467
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 16.80 KB | None | 0 0
  1. package com.port25.webui.security;
  2.  
  3. import com.port25.webui.util.StringParser;
  4. import com.port25.webui.util.Utility;
  5. import java.io.*;
  6. import java.security.*;
  7. import java.security.spec.X509EncodedKeySpec;
  8. import java.util.Calendar;
  9. import org.apache.commons.logging.Log;
  10. import org.apache.commons.logging.LogFactory;
  11. import org.bouncycastle.jce.provider.BouncyCastleProvider;
  12. import org.bouncycastle.util.encoders.Base64;
  13. import org.bouncycastle.util.io.pem.PemObject;
  14. import org.bouncycastle.util.io.pem.PemReader;
  15.  
  16. // Referenced classes of package com.port25.webui.security:
  17. //            Timer
  18.  
  19. public class Lak
  20.     implements Comparable
  21. {
  22.     private static final class ParseState extends Enum
  23.     {
  24.  
  25.         public static ParseState[] values()
  26.         {
  27.             return (ParseState[])$VALUES.clone();
  28.         }
  29.  
  30.         public static ParseState valueOf(String name)
  31.         {
  32.             return (ParseState)Enum.valueOf(com/port25/webui/security/Lak$ParseState, name);
  33.         }
  34.  
  35.         public static final ParseState OK;
  36.         public static final ParseState NEW_LAK;
  37.         public static final ParseState INVALID;
  38.         private static final ParseState $VALUES[];
  39.  
  40.         static
  41.         {
  42.             OK = new ParseState("OK", 0);
  43.             NEW_LAK = new ParseState("NEW_LAK", 1);
  44.             INVALID = new ParseState("INVALID", 2);
  45.             $VALUES = (new ParseState[] {
  46.                 OK, NEW_LAK, INVALID
  47.             });
  48.         }
  49.  
  50.         private ParseState(String s, int i)
  51.         {
  52.             super(s, i);
  53.         }
  54.     }
  55.  
  56.  
  57.     private static String dec(byte pubKey[])
  58.     {
  59.         String xorKey = "Ljava/lang/String;";
  60.         StringBuilder result = new StringBuilder();
  61.         for(int p = 0; p < pubKey.length; p++)
  62.             result.append((char)(pubKey[p] ^ (byte)xorKey.charAt(p % xorKey.length())));
  63.  
  64.         return result.toString();
  65.     }
  66.  
  67.     Lak(Timer timer)
  68.     {
  69.         _timer = timer;
  70.     }
  71.  
  72.     static Lak parse(String pubKey, StringParser parser, Timer timer, String needVersion)
  73.     {
  74.         Lak lak = new Lak(timer);
  75.         boolean done = false;
  76. label0:
  77.         do
  78.         {
  79.             int lakStart;
  80.             StringBuilder lineBuffer;
  81.             do
  82.             {
  83.                 if(done || !parser.hasMore())
  84.                     break label0;
  85.                 lakStart = parser.getPosition();
  86.                 lineBuffer = new StringBuilder();
  87.                 lineBuffer.append(parser.scanUntil("\r\n#"));
  88.                 if(parser.nextCharIs('#'))
  89.                     parser.skipUntil("\r\n");
  90.                 parser.skipLineEndings();
  91.             } while("".equals(lineBuffer.toString().trim()));
  92.             for(; parser.nextCharIsIn(" \t"); parser.skipLineEndings())
  93.             {
  94.                 parser.skipSpacesAndTabs();
  95.                 lineBuffer.append(parser.scanUntil("\r\n"));
  96.             }
  97.  
  98.             String line = lineBuffer.toString();
  99.             int colonPos = line.indexOf(':');
  100.             if(colonPos == -1)
  101.                 return null;
  102.             String key = line.substring(0, colonPos).trim();
  103.             String value = line.substring(colonPos + 1).trim();
  104.             static class _cls1
  105.             {
  106.  
  107.                 static final int $SwitchMap$com$port25$webui$security$Lak$ParseState[];
  108.  
  109.                 static
  110.                 {
  111.                     $SwitchMap$com$port25$webui$security$Lak$ParseState = new int[ParseState.values().length];
  112.                     try
  113.                     {
  114.                         $SwitchMap$com$port25$webui$security$Lak$ParseState[ParseState.OK.ordinal()] = 1;
  115.                     }
  116.                     catch(NoSuchFieldError ex) { }
  117.                     try
  118.                     {
  119.                         $SwitchMap$com$port25$webui$security$Lak$ParseState[ParseState.NEW_LAK.ordinal()] = 2;
  120.                     }
  121.                     catch(NoSuchFieldError ex) { }
  122.                     try
  123.                     {
  124.                         $SwitchMap$com$port25$webui$security$Lak$ParseState[ParseState.INVALID.ordinal()] = 3;
  125.                     }
  126.                     catch(NoSuchFieldError ex) { }
  127.                 }
  128.             }
  129.  
  130.             switch(_cls1..SwitchMap.com.port25.webui.security.Lak.ParseState[lak.set(key, value).ordinal()])
  131.             {
  132.             case 2: // '\002'
  133.                 parser.setPosition(lakStart);
  134.                 done = true;
  135.                 break;
  136.  
  137.             case 3: // '\003'
  138.                 log.debug((new StringBuilder()).append("Invalid LAK: Unknown field '").append(key).append("': '").append(value).append("'").toString());
  139.                 return null;
  140.             }
  141.         } while(true);
  142.         if(lak.isValid(pubKey, needVersion))
  143.             return lak;
  144.         else
  145.             return null;
  146.     }
  147.  
  148.     private ParseState set(String key, String value)
  149.     {
  150.         if("product".equalsIgnoreCase(key))
  151.         {
  152.             if(_product != null)
  153.                 return ParseState.NEW_LAK;
  154.             _product = value;
  155.         } else
  156.         {
  157.             if(_product == null)
  158.                 return ParseState.INVALID;
  159.             if("version".equalsIgnoreCase(key))
  160.                 _version = value;
  161.             else
  162.             if("platform".equalsIgnoreCase(key))
  163.                 _platform = value;
  164.             else
  165.             if("units".equalsIgnoreCase(key))
  166.                 _units = value;
  167.             else
  168.             if("instances".equalsIgnoreCase(key))
  169.                 _instances = value;
  170.             else
  171.             if("licensee".equalsIgnoreCase(key))
  172.                 _licensee = value;
  173.             else
  174.             if("comment".equalsIgnoreCase(key))
  175.                 _comment = value;
  176.             else
  177.             if("issued".equalsIgnoreCase(key))
  178.                 _issued = value;
  179.             else
  180.             if("expires".equalsIgnoreCase(key))
  181.                 _expiresMs = parseDate(value);
  182.             else
  183.             if("serial".equalsIgnoreCase(key))
  184.                 _serial = value;
  185.             else
  186.             if("options".equalsIgnoreCase(key))
  187.                 _options = value;
  188.             else
  189.             if("copyright".equalsIgnoreCase(key))
  190.                 _copyright = value;
  191.             else
  192.             if("check".equalsIgnoreCase(key))
  193.                 _check = value;
  194.             else
  195.                 return ParseState.INVALID;
  196.         }
  197.         return ParseState.OK;
  198.     }
  199.  
  200.     private long parseDate(String value)
  201.     {
  202.         if("never".equalsIgnoreCase(value))
  203.         {
  204.             return 0x7fffffffffffffffL;
  205.         } else
  206.         {
  207.             int yearStart = 0;
  208.             int yearStop = 4;
  209.             String year = value.substring(0, 4);
  210.             int monthStart = 5;
  211.             int monthStop = 7;
  212.             String month = value.substring(5, 7);
  213.             int dayStart = 8;
  214.             int dayStop = 10;
  215.             String day = value.substring(8, 10);
  216.             Calendar cal = Calendar.getInstance();
  217.             cal.setTimeZone(_timer.getTimeZone());
  218.             cal.set(1, Integer.parseInt(year));
  219.             cal.set(2, Integer.parseInt(month) - 1);
  220.             cal.set(5, Integer.parseInt(day));
  221.             cal.set(11, 0);
  222.             cal.set(12, 0);
  223.             cal.set(13, 0);
  224.             cal.set(14, 0);
  225.             return cal.getTimeInMillis();
  226.         }
  227.     }
  228.  
  229.     private boolean isValid(String pubKey, String needVersion)
  230.     {
  231.         if(_check == null)
  232.         {
  233.             log.debug("Invalid LAK: no checksum");
  234.             return false;
  235.         }
  236.         if(_check.startsWith("1-"))
  237.         {
  238.             if(!checkLak1(normalize(), _check.substring(2), pubKey))
  239.             {
  240.                 log.debug("Invalid LAK: bad checksum");
  241.                 return false;
  242.             }
  243.         } else
  244.         {
  245.             log.debug("Invalid LAK: bad algorithm");
  246.             return false;
  247.         }
  248.         if(!"PowerMTA Management Console".equals(_product))
  249.         {
  250.             log.debug((new StringBuilder()).append("Invalid LAK: product mismatch (need PowerMTA Management Console, but found ").append(_product).append(")").toString());
  251.             return false;
  252.         }
  253.         if(!Utility.isEmpty(_platform) && !"linux-intel".equals(_platform))
  254.         {
  255.             log.debug((new StringBuilder()).append("Invalid LAK: platform mismatch (need linux-intel but found ").append(_platform).append(")").toString());
  256.             return false;
  257.         }
  258.         String guiVersion = getLakCompatibleVersion(needVersion);
  259.         if(guiVersion.compareToIgnoreCase(_version) > 0)
  260.         {
  261.             log.debug("Invalid LAK: version mismatch");
  262.             return false;
  263.         } else
  264.         {
  265.             return true;
  266.         }
  267.     }
  268.  
  269.     private byte[] normalize()
  270.     {
  271.         return normalize(false).getBytes();
  272.     }
  273.  
  274.     private String normalize(boolean pretty)
  275.     {
  276.         StringBuilder normalized = new StringBuilder();
  277.         normAppend(normalized, "  product", _product, pretty);
  278.         normAppend(normalized, "  version", _version, pretty);
  279.         normAppend(normalized, " platform", _platform, pretty);
  280.         normAppend(normalized, "    units", _units, pretty);
  281.         if(_instances != null && !"1".equals(_instances))
  282.         {
  283.             String instances = "0".equals(_instances) ? "unlimited" : _instances;
  284.             normAppend(normalized, "instances", instances, pretty);
  285.         }
  286.         normAppend(normalized, " licensee", _licensee, pretty);
  287.         normAppend(normalized, "   issued", _issued, pretty);
  288.         normAppend(normalized, "  expires", getExpiration(), pretty);
  289.         normAppend(normalized, "   serial", _serial, pretty);
  290.         normAppend(normalized, "  options", _options, pretty);
  291.         normAppend(normalized, "  comment", _comment, pretty);
  292.         normAppend(normalized, "copyright", _copyright, pretty);
  293.         return normalized.toString();
  294.     }
  295.  
  296.     private void normAppend(StringBuilder normalized, String name, String value, boolean pretty)
  297.     {
  298.         if(pretty)
  299.             normAppend(normalized, NL, name, ": ", value);
  300.         else
  301.             normAppend(normalized, ";", name.trim(), "", value);
  302.     }
  303.  
  304.     private void normAppend(StringBuilder normalized, String recordSeparator, String name, String keyValueSeparator, String value)
  305.     {
  306.         if(normalized.length() > 0)
  307.             normalized.append(recordSeparator);
  308.         normalized.append(name);
  309.         normalized.append(keyValueSeparator);
  310.         if(value != null)
  311.             normalized.append(value);
  312.     }
  313.  
  314.     public static String getLakCompatibleVersion(String version)
  315.     {
  316.         int pos;
  317.         for(pos = 0; pos < version.length() && "0123456789.".contains((new StringBuilder()).append("").append(version.charAt(pos)).toString()); pos++);
  318.         return version.substring(0, pos);
  319.     }
  320.  
  321.     public String getText()
  322.     {
  323.         return (new StringBuilder()).append(normalize(true)).append(NL).toString();
  324.     }
  325.  
  326.     public String getSerial()
  327.     {
  328.         return _serial;
  329.     }
  330.  
  331.     private boolean checkLak1(byte normalizedLak[], String sigBase64, String pubKey)
  332.     {
  333.         Signature signer;
  334.         PemReader reader;
  335.         Throwable throwable;
  336.         Security.addProvider(new BouncyCastleProvider());
  337.         signer = Signature.getInstance("SHA1withRSA", "BC");
  338.         reader = new PemReader(new StringReader(pubKey));
  339.         throwable = null;
  340.         boolean flag;
  341.         try
  342.         {
  343.             PemObject obj = reader.readPemObject();
  344.             KeyFactory fact = KeyFactory.getInstance("RSA");
  345.             PublicKey key = fact.generatePublic(new X509EncodedKeySpec(obj.getContent()));
  346.             signer.initVerify(key);
  347.             signer.update(normalizedLak);
  348.             flag = signer.verify(Base64.decode(sigBase64));
  349.         }
  350.         catch(Throwable throwable1)
  351.         {
  352.             throwable = throwable1;
  353.             throw throwable1;
  354.         }
  355.         if(reader != null)
  356.             if(throwable != null)
  357.                 try
  358.                 {
  359.                     reader.close();
  360.                 }
  361.                 catch(Throwable x2)
  362.                 {
  363.                     throwable.addSuppressed(x2);
  364.                 }
  365.             else
  366.                 reader.close();
  367.         return flag;
  368.         Exception exception;
  369.         exception;
  370.         if(reader != null)
  371.             if(throwable != null)
  372.                 try
  373.                 {
  374.                     reader.close();
  375.                 }
  376.                 catch(Throwable x2)
  377.                 {
  378.                     throwable.addSuppressed(x2);
  379.                 }
  380.             else
  381.                 reader.close();
  382.         throw exception;
  383.         Exception e;
  384.         e;
  385.         throw new RuntimeException(e);
  386.     }
  387.  
  388.     public String getExpiration()
  389.     {
  390.         return _timer.formattedDate(_expiresMs);
  391.     }
  392.  
  393.     long getExpirationMs()
  394.     {
  395.         return _expiresMs + 0x5265c00L;
  396.     }
  397.  
  398.     public boolean isExpired()
  399.     {
  400.         return _expiresMs != 0x7fffffffffffffffL && msTillExpiration() <= 0L;
  401.     }
  402.  
  403.     private long msTillExpiration()
  404.     {
  405.         if(_expiresMs == 0x7fffffffffffffffL)
  406.             return 0x7fffffffffffffffL;
  407.         else
  408.             return getExpirationMs() - _timer.getTime();
  409.     }
  410.  
  411.     public String getExpirationWarning()
  412.     {
  413.         if(isExpired())
  414.             return "The license key for this PowerMTA Management Console has expired. Please contact sales@ to renew.";
  415.         long daysLeft = msTillExpiration() / 0x5265c00L - 1L;
  416.         int daysWarn = isEvaluation() ? 10 : 30;
  417.         if(daysLeft <= (long)daysWarn && daysLeft >= 0L)
  418.             return (new StringBuilder()).append("The license key for this PowerMTA Management Console expires in ").append(daysPl(daysLeft)).append(". ").append("Please contact sales@ to renew.").toString();
  419.         else
  420.             return null;
  421.     }
  422.  
  423.     private String daysPl(long days)
  424.     {
  425.         return (new StringBuilder()).append(days).append(days != 1L ? " days" : " day").toString();
  426.     }
  427.  
  428.     public boolean isEvaluation()
  429.     {
  430.         return hasOption("evaluation");
  431.     }
  432.  
  433.     public boolean hasOption(String option)
  434.     {
  435.         return _options != null && _options.contains(option);
  436.     }
  437.  
  438.     public int compareTo(Lak lak)
  439.     {
  440.         long expirationDiff = msTillExpiration() - lak.msTillExpiration();
  441.         if(expirationDiff < 0L)
  442.             return -1;
  443.         return expirationDiff <= 0L ? 0 : 1;
  444.     }
  445.  
  446.     public boolean equals(Object other)
  447.     {
  448.         return other != null && other.getClass().equals(getClass()) && other.hashCode() == hashCode();
  449.     }
  450.  
  451.     public int hashCode()
  452.     {
  453.         int prime = 17;
  454.         return _product.hashCode() + _serial.hashCode() * 17 + _options.hashCode() * 17 + _units.hashCode() * 17 + _instances.hashCode() * 17 + _version.hashCode() * 17 + _platform.hashCode() * 17 + _licensee.hashCode() * 17 + _comment.hashCode() * 17 + _issued.hashCode() * 17 + Long.valueOf(_expiresMs).hashCode() * 17 + _copyright.hashCode() * 17 + _check.hashCode() * 17;
  455.     }
  456.  
  457.     public volatile int compareTo(Object x0)
  458.     {
  459.         return compareTo((Lak)x0);
  460.     }
  461.  
  462.     static final String NL;
  463.     static final String PUB_KEY = dec(new byte[] {
  464.         97, 71, 76, 91, 76, 109, 41, 38, 39, 41,
  465.         15, 3, 33, 48, 37, 39, 36, 27, 7, 47,
  466.         56, 91, 76, 2, 65, 76, 100, 42, 105, 36,
  467.         3, 54, 56, 55, 45, 112, 35, 48, 40, 30,
  468.         23, 76, 34, 32, 63, 34, 109, 17, 37, 51,
  469.         45, 61, 16, 122, 59, 57, 32, 60, 35, 110,
  470.         33, 16, 33, 63, 28, 24, 19, 32, 5, 39,
  471.         45, 116, 11, 32, 21, 27, 57, 118, 29, 37,
  472.         15, 31, 24, 63, 91, 66, 63, 63, 51, 126,
  473.         36, 96, 87, 62, 5, 94, 32, 0, 44, 49,
  474.         100, 55, 33, 63, 7, 94, 0, 74, 35, 19,
  475.         37, 3, 22, 99, 20, 8, 7, 62, 126, 53,
  476.         60, 57, 58, 55, 40, 114, 3, 59, 41, 78,
  477.         16, 66, 24, 14, 42, 9, 78, 29, 46, 74,
  478.         19, 60, 21, 98, 46, 57, 52, 53, 32, 88,
  479.         41, 32, 47, 54, 18, 110, 126, 95, 68, 67,
  480.         74, 22, 9, 36, 37, 86, 49, 122, 46, 45,
  481.         39, 36, 15, 24, 49, 43, 68, 67, 74, 22,
  482.         97, 96
  483.     });
  484.     private static final int EVAL_LAK_GRACE = 10;
  485.     private static final int NORMAL_LAK_GRACE = 30;
  486.     private static Log log = LogFactory.getLog(com/port25/webui/security/Lak);
  487.     private Timer _timer;
  488.     private String _product;
  489.     private String _serial;
  490.     private String _options;
  491.     private String _units;
  492.     private String _instances;
  493.     private String _version;
  494.     private String _platform;
  495.     private String _licensee;
  496.     private String _comment;
  497.     private String _issued;
  498.     private long _expiresMs;
  499.     private String _copyright;
  500.     private String _check;
  501.  
  502.     static
  503.     {
  504.         NL = File.separatorChar != '/' ? "\r\n" : "\n";
  505.     }
  506. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement