Advertisement
Guest User

Untitled

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