Advertisement
Guest User

Untitled

a guest
Jun 4th, 2017
110
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 16.70 KB | None | 0 0
  1. package pop3srvr;
  2.  
  3. public class App {
  4.  
  5.     public static void main(String[] args) {
  6.         new POP3Server().run();
  7.     }
  8.  
  9. }
  10.  
  11. ///////////////////////////////////////////////////////////////////////////
  12.  
  13. package pop3srvr;
  14.  
  15. import sun.misc.BASE64Decoder;
  16. import sun.misc.BASE64Encoder;
  17.  
  18. import java.io.BufferedOutputStream;
  19. import java.io.BufferedReader;
  20. import java.io.IOException;
  21. import java.io.InputStreamReader;
  22. import java.net.ServerSocket;
  23. import java.net.Socket;
  24.  
  25. public class POP3Server implements Runnable {
  26.     // pop3 port number
  27.     public static final int PORT = 11000;
  28.  
  29.     private ServerSocket fServerSocket = null;
  30.     private Socket clientSocket = null;
  31.  
  32.     private BASE64Decoder decoder = new BASE64Decoder();
  33.     private BASE64Encoder encoder = new BASE64Encoder();
  34.  
  35.     //Open server socket
  36.     public POP3Server() {
  37.         try {
  38.             fServerSocket = new ServerSocket(PORT);
  39.             System.out.println("Server started.");
  40.         } catch (IOException e) {
  41.             System.err.println("error:");
  42.             e.printStackTrace();
  43.             System.exit(1);
  44.         }
  45.     }
  46.  
  47.     public void run() {
  48.  
  49.         BufferedOutputStream pop3out;
  50.         BufferedReader pop3in;
  51.         while (true) {
  52.             try {
  53.                 //waiting for incoming connections
  54.                 clientSocket = fServerSocket.accept();
  55.  
  56.                 //assigning socket streams
  57.                 pop3out = new BufferedOutputStream(clientSocket.getOutputStream());
  58.                 pop3in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
  59.  
  60.                 //do initial response
  61.                 pop3out.write("+OK\n".getBytes());
  62.                 pop3out.flush();
  63.  
  64.                 //request mwssage
  65.                 String message;
  66.  
  67.                 //while input stream not closed
  68.                 while ((message = pop3in.readLine()) != null) {
  69.  
  70.                     // parsing is here
  71.                     System.out.println("Request: " + message);
  72.                     if (message.equals("CAPA")) {
  73.                         pop3out.write("+OK Capability list follows\nSASL CRAM-MD5 PLAIN\n.\n".getBytes());
  74.                     } else if (message.startsWith("AUTH")) {
  75.                         pop3out.write("+OK\n".getBytes());
  76.                         pop3out.flush();
  77.                         String authdata = pop3in.readLine();
  78.                         System.out.println(new String(decode(authdata.getBytes())));
  79.                         pop3out.write("+OK\n".getBytes());
  80.  
  81.                         // todo: authenticate
  82.  
  83.                         /*
  84.                         byte[] response = authenticate(message.getBytes());
  85.                         System.out.println("Response:" + new String(response));
  86.                         pop3out.write(response);*/
  87.                     } else {
  88.                         pop3out.write("+OK\n".getBytes());
  89.                     }
  90.                     pop3out.flush();
  91.                 }
  92.  
  93.             } catch (IOException e) {
  94.                 System.err.println("error:");
  95.                 e.printStackTrace();
  96.             }
  97.         }
  98.     }
  99.  
  100.     //make response-bytes depending on a request string
  101.     public byte[] authenticate(byte[] request) {
  102.         if (request == null) {
  103.             return "+OK\n".getBytes();
  104.         }
  105.  
  106.         return SaslAuthenticator.auth(request);
  107.     }
  108.  
  109.     public byte[] encode(byte[] data) {
  110.         return encoder.encode(data).getBytes();
  111.     }
  112.  
  113.     public byte[] decode(byte[] data) {
  114.         try {
  115.             return decoder.decodeBuffer(new String(data));
  116.         } catch (IOException e) {
  117.             return null;
  118.         }
  119.     }
  120.  
  121.  
  122.     //close session
  123.     public void quit() {
  124.         try {
  125.             clientSocket.close();
  126.         } catch (IOException e) {
  127.             System.err.println("error:");
  128.             e.printStackTrace();
  129.         }
  130.     }
  131. }
  132.  
  133. ///////////////////////////////////////////////////////////////////////////
  134.  
  135. package pop3srvr;
  136.  
  137. import pop3srvr.provider.ExternalValidationCallback;
  138. import pop3srvr.provider.MySecurityProvider;
  139.  
  140. import javax.security.auth.callback.*;
  141. import javax.security.sasl.*;
  142. import java.io.IOException;
  143. import java.security.Security;
  144. import java.util.HashMap;
  145. import java.util.Map;
  146.  
  147. public class SaslAuthenticator {
  148.  
  149.     private static final SaslAuthenticator instance = new SaslAuthenticator();
  150.  
  151.     public static final String PLAIN = "PLAIN";
  152.     public static final String MD5 = "CRAM-MD5";
  153.  
  154.     static {
  155.         // register provider
  156.         Security.addProvider(new MySecurityProvider());
  157.     }
  158.  
  159.     private Map<String, SaslServer> saslServers;
  160.  
  161.     private SaslAuthenticator() {
  162.         saslServers = new HashMap<String, SaslServer>() {{
  163.  
  164.             final Map<String,String> authorizedUsers = new HashMap<String,String>();
  165.  
  166.             authorizedUsers.put("energy", "mypass");
  167.             authorizedUsers.put("user", "userpass");
  168.  
  169.             CallbackHandler md5CallbackHandler = new CallbackHandler() {
  170.  
  171.                 public void handle(Callback[] cbs) throws IOException, UnsupportedCallbackException {
  172.                     String user = null;
  173.                     for (Callback cb : cbs) {
  174.                         if (cb instanceof AuthorizeCallback) {
  175.  
  176.                             System.out.println("Server - AuthorizeCallback");
  177.  
  178.                             AuthorizeCallback ac = (AuthorizeCallback) cb;
  179.                             ac.setAuthorized(true);
  180.  
  181.                         } else if (cb instanceof NameCallback) {
  182.  
  183.                             System.out.println("Server - NameCallback");
  184.  
  185.                             NameCallback nc = (NameCallback) cb;
  186.                             if (authorizedUsers.containsKey(nc.getDefaultName())) {
  187.                                 user = nc.getDefaultName();
  188.                                 nc.setName(nc.getDefaultName());
  189.                             }
  190.                         } else if (cb instanceof PasswordCallback) {
  191.                             System.out.println("Server - PasswordCallback");
  192.  
  193.                             PasswordCallback pc = (PasswordCallback) cb;
  194.                             if (user != null) {
  195.                                 pc.setPassword(authorizedUsers.get(user).toCharArray());
  196.                             }
  197.                         }
  198.                     }
  199.                 }
  200.             };
  201.  
  202.             CallbackHandler plainCallbackHandler = new CallbackHandler() {
  203.                 public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
  204.                     for (Callback cb : callbacks) {
  205.                         if (cb instanceof ExternalValidationCallback) {
  206.                             ExternalValidationCallback evc = (ExternalValidationCallback) cb;
  207.  
  208.                             if (authorizedUsers.containsKey(evc.getUsername()) && authorizedUsers.get(evc.getUsername()).equals(evc.getPassword())) {
  209.                                 evc.setValidated(true);
  210.                             } else {
  211.                                 evc.setValidated(false);
  212.                             }
  213.                         } else if (cb instanceof AuthorizeCallback) {
  214.                             AuthorizeCallback ac = (AuthorizeCallback) cb;
  215.  
  216.                             ac.setAuthorized(true);
  217.                         } else {
  218.                             throw new UnsupportedCallbackException(cb, "Unrecognized Callback");
  219.                         }
  220.                     }
  221.                 }
  222.             };
  223.  
  224.             try {
  225.                 put(PLAIN, Sasl.createSaslServer(PLAIN, "myProtocol", "local", null, plainCallbackHandler));
  226.                 put(MD5, Sasl.createSaslServer(MD5, "myProtocol", "local", null, md5CallbackHandler));
  227.             } catch (SaslException e) {
  228.                 e.printStackTrace();
  229.             }
  230.         }};
  231.  
  232.     }
  233.  
  234.     private byte[] auth(byte[] data, final String method) {
  235.  
  236.         byte[] challenge = null;
  237.         //byte[] response;
  238.  
  239.         try {
  240.             final String mechanism = method;
  241.  
  242.             if (mechanism == PLAIN) {
  243.                 challenge = saslServers.get(PLAIN).evaluateResponse(data);
  244.             } else if (mechanism == MD5) {
  245.                 challenge = saslServers.get(MD5).evaluateResponse(new byte[0]);
  246.                 return challenge;
  247.             }
  248.  
  249.  
  250.             //"energy\u00005e8edd851d2fdfbd7415232c67367cc3".getBytes()
  251.             //response = sc.evaluateChallenge(challenge);
  252.  
  253.             System.out.println("Server: " + new String(challenge));
  254.             //System.out.println("Client: " + new String(response));
  255.  
  256.             //saslServers.get(mechanism).evaluateResponse(response);
  257.             if (saslServers.get(mechanism).isComplete()) {
  258.                 System.out.println("Authentication successful.");
  259.             }
  260.         } catch (SaslException e) {
  261.             e.printStackTrace();
  262.         }
  263.         return new byte[0];
  264.     }
  265.  
  266.     public static byte[] auth(byte[] request) {
  267.         return instance.auth(request, MD5);
  268.     }
  269.  
  270. }
  271.  
  272. ///////////////////////////////////////////////////////////////////////////
  273.  
  274. package pop3srvr.provider;
  275.  
  276. import java.security.Provider;
  277.  
  278. public final class MySecurityProvider extends Provider {
  279.  
  280.     public MySecurityProvider() {
  281.         super("My Provider", 1.0, "Simple sasl plain provider");
  282.         put("SaslServerFactory.PLAIN", "pop3srvr.provider.PlainSaslServerFactory");
  283.     }
  284.  
  285. }
  286.  
  287. ///////////////////////////////////////////////////////////////////////////
  288.  
  289. package pop3srvr.provider;
  290.  
  291. import javax.security.auth.callback.Callback;
  292.  
  293. public class ExternalValidationCallback implements Callback {
  294.  
  295.     private String username;
  296.     private String password;
  297.     private boolean validated = false;
  298.  
  299.     public ExternalValidationCallback(String username, String password) {
  300.         this.username = username;
  301.         this.password = password;
  302.     }
  303.  
  304.     public String getPassword() {
  305.         return password;
  306.     }
  307.  
  308.     public String getUsername() {
  309.         return username;
  310.     }
  311.  
  312.     public boolean isValidated() {
  313.         return validated;
  314.     }
  315.  
  316.     public void setValidated(boolean validated) {
  317.         this.validated = validated;
  318.     }
  319. }
  320.  
  321. ///////////////////////////////////////////////////////////////////////////
  322.  
  323. package pop3srvr.provider;
  324.  
  325. import javax.security.auth.callback.CallbackHandler;
  326. import javax.security.sasl.Sasl;
  327. import javax.security.sasl.SaslException;
  328. import javax.security.sasl.SaslServer;
  329. import javax.security.sasl.SaslServerFactory;
  330. import java.util.Map;
  331.  
  332. public class PlainSaslServerFactory implements SaslServerFactory {
  333.  
  334.     private static String[] mechanisms = {"PLAIN".intern()};
  335.  
  336.     public SaslServer createSaslServer(String mechanism, String protocol,
  337.                                        String serverName,
  338.                                        Map props, CallbackHandler cbh) throws SaslException {
  339.  
  340.         if (!mechanisms[0].equals(mechanism) || cbh == null)
  341.             return null;
  342.         return new PlainSaslServer(cbh);
  343.  
  344.     }
  345.  
  346.     public String[] getMechanismNames(Map props) {
  347.         if ("true".equals(props.get(Sasl.POLICY_NOPLAINTEXT)))
  348.             return new String[0];
  349.         return mechanisms;
  350.     }
  351. }
  352.  
  353.  
  354. ///////////////////////////////////////////////////////////////////////////
  355.  
  356. package pop3srvr.provider;
  357.  
  358. import java.io.IOException;
  359. import java.io.UnsupportedEncodingException;
  360. import javax.security.auth.callback.Callback;
  361. import javax.security.auth.callback.CallbackHandler;
  362. import javax.security.auth.callback.UnsupportedCallbackException;
  363. import javax.security.sasl.AuthorizeCallback;
  364. import javax.security.sasl.SaslException;
  365. import javax.security.sasl.SaslServer;
  366.  
  367. /**
  368.  * Simple sasl server to decode a
  369.  *
  370.  * @author toaster
  371.  */
  372. public class PlainSaslServer implements SaslServer {
  373.  
  374.     public boolean complete = false;
  375.     private String authID = null;
  376.     private CallbackHandler cbh;
  377.  
  378.     PlainSaslServer(CallbackHandler cbh) {
  379.         this.cbh = cbh;
  380.     }
  381.  
  382.     public String getMechanismName() {
  383.         return "PLAIN".intern(); //SaslConstants.SASL_SERVICE;
  384.     }
  385.  
  386.     public byte[] evaluateResponse(byte[] response) throws SaslException {
  387.         String authnID = null;
  388.         String authzID = null;
  389.         String password = null;
  390.  
  391.         // Decode response as per rfc4616.txt
  392. //       The formal grammar for the client message using Augmented BNF [ABNF]
  393. //       follows.
  394. //
  395. //       message   = [authzid] UTF8NUL authcid UTF8NUL passwd
  396. //       authcid   = 1*SAFE ; MUST accept up to 255 octets
  397. //       authzid   = 1*SAFE ; MUST accept up to 255 octets
  398. //       passwd    = 1*SAFE ; MUST accept up to 255 octets
  399. //       UTF8NUL   = %x00 ; UTF-8 encoded NUL character
  400. //
  401. //       SAFE      = UTF1 / UTF2 / UTF3 / UTF4
  402. //                   ;; any UTF-8 encoded Unicode character except NUL
  403. //
  404. //       UTF1      = %x01-7F ;; except NUL
  405. //       UTF2      = %xC2-DF UTF0
  406. //       UTF3      = %xE0 %xA0-BF UTF0 / %xE1-EC 2(UTF0) /
  407. //                   %xED %x80-9F UTF0 / %xEE-EF 2(UTF0)
  408. //       UTF4      = %xF0 %x90-BF 2(UTF0) / %xF1-F3 3(UTF0) /
  409. //                   %xF4 %x80-8F 2(UTF0)
  410. //       UTF0      = %x80-BF
  411.  
  412.         int start = 0;
  413.         int end = 0;
  414.         int elementIdx = 0;
  415.  
  416.         try {
  417.             for (byte b : response) {
  418.                 if (b == '\u0000') {
  419.                     // empty string, only authzid allows this
  420.                     if (end - start == 0) {
  421.                         if (elementIdx != 0) {
  422.                             throw new SaslException("null auth data");
  423.                         }
  424.  
  425.                     } // data, wa-hoo
  426.                     else {
  427.                         String element = new String(response, start, end - start, "UTF-8");
  428.                         start = end + 1;
  429.  
  430.                         switch (elementIdx) {
  431.                             case 0:
  432.                                 authzID = element;
  433.                                 break;
  434.                             case 1:
  435.                                 authnID = element;
  436.                                 break;
  437.                             default:
  438.                                 throw new SaslException("Unexpected data in packet");
  439.                         }
  440.                     }
  441.                     elementIdx++;
  442.  
  443.                 }
  444.                 end++;
  445.             }
  446.  
  447.             if (start == end) {
  448.                 throw new SaslException("null auth data");
  449.             }
  450.  
  451.             password = new String(response, start, end - start, "UTF-8");
  452.  
  453.  
  454.         } catch (UnsupportedEncodingException e) {
  455.             throw new SaslException("utf-8 encoding");
  456.         }
  457.  
  458.  
  459.         ExternalValidationCallback evc = new ExternalValidationCallback(authnID, password);
  460.         AuthorizeCallback ac = new AuthorizeCallback(authnID, authzID);
  461.  
  462.         Callback[] cbList = new Callback[2];
  463.  
  464.         cbList[0] = evc;
  465.         cbList[1] = ac;
  466.  
  467.         try {
  468.             if (password == null || authnID == null) {
  469.                 throw new SaslException("null auth data");
  470.             }
  471.  
  472.             cbh.handle(cbList);
  473.             if (!evc.isValidated()) {
  474.                 throw new SaslException("cannot validate password");
  475.             }
  476.  
  477.             if (!ac.isAuthorized()) {
  478.                 throw new SaslException("user not authorized");
  479.             }
  480.  
  481.             complete = true;
  482.             return null;
  483.  
  484.         } catch (UnsupportedCallbackException ex) {
  485.             throw new SaslException("unsupported callback", ex);
  486.  
  487.         } catch (IOException e) {
  488.             if (e instanceof SaslException) {
  489.                 throw (SaslException) e;
  490.             }
  491.             throw new SaslException("Callback error", e);
  492.         }
  493.  
  494.     }
  495.  
  496.     public boolean isComplete() {
  497.         return complete;
  498.     }
  499.  
  500.     public String getAuthorizationID() {
  501.         if (!complete) {
  502.             throw new IllegalStateException("not complete");
  503.         }
  504.         return authID;
  505.     }
  506.  
  507.     public byte[] unwrap(byte[] incoming, int offset, int len) {
  508.         if (!complete) {
  509.             throw new IllegalStateException("not complete");
  510.         }
  511.         final byte[] result = new byte[len];
  512.         System.arraycopy(incoming, offset, result, 0, len);
  513.         return result;
  514.  
  515.     }
  516.  
  517.     public byte[] wrap(byte[] outgoing, int offset, int len) {
  518.         if (!complete) {
  519.             throw new IllegalStateException("not complete");
  520.         }
  521.  
  522.         final byte[] result = new byte[len];
  523.         System.arraycopy(outgoing, offset, result, 0, len);
  524.         return result;
  525.  
  526.     }
  527.  
  528.     public Object getNegotiatedProperty(String propName) {
  529.         return null;
  530.     }
  531.  
  532.     public void dispose() throws SaslException {
  533.     }
  534. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement