Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package pop3srvr;
- public class App {
- public static void main(String[] args) {
- new POP3Server().run();
- }
- }
- ///////////////////////////////////////////////////////////////////////////
- package pop3srvr;
- import sun.misc.BASE64Decoder;
- import sun.misc.BASE64Encoder;
- import java.io.BufferedOutputStream;
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStreamReader;
- import java.net.ServerSocket;
- import java.net.Socket;
- public class POP3Server implements Runnable {
- // pop3 port number
- public static final int PORT = 11000;
- private ServerSocket fServerSocket = null;
- private Socket clientSocket = null;
- private BASE64Decoder decoder = new BASE64Decoder();
- private BASE64Encoder encoder = new BASE64Encoder();
- //Open server socket
- public POP3Server() {
- try {
- fServerSocket = new ServerSocket(PORT);
- System.out.println("Server started.");
- } catch (IOException e) {
- System.err.println("error:");
- e.printStackTrace();
- System.exit(1);
- }
- }
- public void run() {
- BufferedOutputStream pop3out;
- BufferedReader pop3in;
- while (true) {
- try {
- //waiting for incoming connections
- clientSocket = fServerSocket.accept();
- //assigning socket streams
- pop3out = new BufferedOutputStream(clientSocket.getOutputStream());
- pop3in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
- //do initial response
- pop3out.write("+OK\n".getBytes());
- pop3out.flush();
- //request mwssage
- String message;
- //while input stream not closed
- while ((message = pop3in.readLine()) != null) {
- // parsing is here
- System.out.println("Request: " + message);
- if (message.equals("CAPA")) {
- pop3out.write("+OK Capability list follows\nSASL CRAM-MD5 PLAIN\n.\n".getBytes());
- } else if (message.startsWith("AUTH")) {
- pop3out.write("+OK\n".getBytes());
- pop3out.flush();
- String authdata = pop3in.readLine();
- System.out.println(new String(decode(authdata.getBytes())));
- pop3out.write("+OK\n".getBytes());
- // todo: authenticate
- /*
- byte[] response = authenticate(message.getBytes());
- System.out.println("Response:" + new String(response));
- pop3out.write(response);*/
- } else {
- pop3out.write("+OK\n".getBytes());
- }
- pop3out.flush();
- }
- } catch (IOException e) {
- System.err.println("error:");
- e.printStackTrace();
- }
- }
- }
- //make response-bytes depending on a request string
- public byte[] authenticate(byte[] request) {
- if (request == null) {
- return "+OK\n".getBytes();
- }
- return SaslAuthenticator.auth(request);
- }
- public byte[] encode(byte[] data) {
- return encoder.encode(data).getBytes();
- }
- public byte[] decode(byte[] data) {
- try {
- return decoder.decodeBuffer(new String(data));
- } catch (IOException e) {
- return null;
- }
- }
- //close session
- public void quit() {
- try {
- clientSocket.close();
- } catch (IOException e) {
- System.err.println("error:");
- e.printStackTrace();
- }
- }
- }
- ///////////////////////////////////////////////////////////////////////////
- package pop3srvr;
- import pop3srvr.provider.ExternalValidationCallback;
- import pop3srvr.provider.MySecurityProvider;
- import javax.security.auth.callback.*;
- import javax.security.sasl.*;
- import java.io.IOException;
- import java.security.Security;
- import java.util.HashMap;
- import java.util.Map;
- public class SaslAuthenticator {
- private static final SaslAuthenticator instance = new SaslAuthenticator();
- public static final String PLAIN = "PLAIN";
- public static final String MD5 = "CRAM-MD5";
- static {
- // register provider
- Security.addProvider(new MySecurityProvider());
- }
- private Map<String, SaslServer> saslServers;
- private SaslAuthenticator() {
- saslServers = new HashMap<String, SaslServer>() {{
- final Map<String,String> authorizedUsers = new HashMap<String,String>();
- authorizedUsers.put("energy", "mypass");
- authorizedUsers.put("user", "userpass");
- CallbackHandler md5CallbackHandler = new CallbackHandler() {
- public void handle(Callback[] cbs) throws IOException, UnsupportedCallbackException {
- String user = null;
- for (Callback cb : cbs) {
- if (cb instanceof AuthorizeCallback) {
- System.out.println("Server - AuthorizeCallback");
- AuthorizeCallback ac = (AuthorizeCallback) cb;
- ac.setAuthorized(true);
- } else if (cb instanceof NameCallback) {
- System.out.println("Server - NameCallback");
- NameCallback nc = (NameCallback) cb;
- if (authorizedUsers.containsKey(nc.getDefaultName())) {
- user = nc.getDefaultName();
- nc.setName(nc.getDefaultName());
- }
- } else if (cb instanceof PasswordCallback) {
- System.out.println("Server - PasswordCallback");
- PasswordCallback pc = (PasswordCallback) cb;
- if (user != null) {
- pc.setPassword(authorizedUsers.get(user).toCharArray());
- }
- }
- }
- }
- };
- CallbackHandler plainCallbackHandler = new CallbackHandler() {
- public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
- for (Callback cb : callbacks) {
- if (cb instanceof ExternalValidationCallback) {
- ExternalValidationCallback evc = (ExternalValidationCallback) cb;
- if (authorizedUsers.containsKey(evc.getUsername()) && authorizedUsers.get(evc.getUsername()).equals(evc.getPassword())) {
- evc.setValidated(true);
- } else {
- evc.setValidated(false);
- }
- } else if (cb instanceof AuthorizeCallback) {
- AuthorizeCallback ac = (AuthorizeCallback) cb;
- ac.setAuthorized(true);
- } else {
- throw new UnsupportedCallbackException(cb, "Unrecognized Callback");
- }
- }
- }
- };
- try {
- put(PLAIN, Sasl.createSaslServer(PLAIN, "myProtocol", "local", null, plainCallbackHandler));
- put(MD5, Sasl.createSaslServer(MD5, "myProtocol", "local", null, md5CallbackHandler));
- } catch (SaslException e) {
- e.printStackTrace();
- }
- }};
- }
- private byte[] auth(byte[] data, final String method) {
- byte[] challenge = null;
- //byte[] response;
- try {
- final String mechanism = method;
- if (mechanism == PLAIN) {
- challenge = saslServers.get(PLAIN).evaluateResponse(data);
- } else if (mechanism == MD5) {
- challenge = saslServers.get(MD5).evaluateResponse(new byte[0]);
- return challenge;
- }
- //"energy\u00005e8edd851d2fdfbd7415232c67367cc3".getBytes()
- //response = sc.evaluateChallenge(challenge);
- System.out.println("Server: " + new String(challenge));
- //System.out.println("Client: " + new String(response));
- //saslServers.get(mechanism).evaluateResponse(response);
- if (saslServers.get(mechanism).isComplete()) {
- System.out.println("Authentication successful.");
- }
- } catch (SaslException e) {
- e.printStackTrace();
- }
- return new byte[0];
- }
- public static byte[] auth(byte[] request) {
- return instance.auth(request, MD5);
- }
- }
- ///////////////////////////////////////////////////////////////////////////
- package pop3srvr.provider;
- import java.security.Provider;
- public final class MySecurityProvider extends Provider {
- public MySecurityProvider() {
- super("My Provider", 1.0, "Simple sasl plain provider");
- put("SaslServerFactory.PLAIN", "pop3srvr.provider.PlainSaslServerFactory");
- }
- }
- ///////////////////////////////////////////////////////////////////////////
- package pop3srvr.provider;
- import javax.security.auth.callback.Callback;
- public class ExternalValidationCallback implements Callback {
- private String username;
- private String password;
- private boolean validated = false;
- public ExternalValidationCallback(String username, String password) {
- this.username = username;
- this.password = password;
- }
- public String getPassword() {
- return password;
- }
- public String getUsername() {
- return username;
- }
- public boolean isValidated() {
- return validated;
- }
- public void setValidated(boolean validated) {
- this.validated = validated;
- }
- }
- ///////////////////////////////////////////////////////////////////////////
- package pop3srvr.provider;
- import javax.security.auth.callback.CallbackHandler;
- import javax.security.sasl.Sasl;
- import javax.security.sasl.SaslException;
- import javax.security.sasl.SaslServer;
- import javax.security.sasl.SaslServerFactory;
- import java.util.Map;
- public class PlainSaslServerFactory implements SaslServerFactory {
- private static String[] mechanisms = {"PLAIN".intern()};
- public SaslServer createSaslServer(String mechanism, String protocol,
- String serverName,
- Map props, CallbackHandler cbh) throws SaslException {
- if (!mechanisms[0].equals(mechanism) || cbh == null)
- return null;
- return new PlainSaslServer(cbh);
- }
- public String[] getMechanismNames(Map props) {
- if ("true".equals(props.get(Sasl.POLICY_NOPLAINTEXT)))
- return new String[0];
- return mechanisms;
- }
- }
- ///////////////////////////////////////////////////////////////////////////
- package pop3srvr.provider;
- import java.io.IOException;
- import java.io.UnsupportedEncodingException;
- import javax.security.auth.callback.Callback;
- import javax.security.auth.callback.CallbackHandler;
- import javax.security.auth.callback.UnsupportedCallbackException;
- import javax.security.sasl.AuthorizeCallback;
- import javax.security.sasl.SaslException;
- import javax.security.sasl.SaslServer;
- /**
- * Simple sasl server to decode a
- *
- * @author toaster
- */
- public class PlainSaslServer implements SaslServer {
- public boolean complete = false;
- private String authID = null;
- private CallbackHandler cbh;
- PlainSaslServer(CallbackHandler cbh) {
- this.cbh = cbh;
- }
- public String getMechanismName() {
- return "PLAIN".intern(); //SaslConstants.SASL_SERVICE;
- }
- public byte[] evaluateResponse(byte[] response) throws SaslException {
- String authnID = null;
- String authzID = null;
- String password = null;
- // Decode response as per rfc4616.txt
- // The formal grammar for the client message using Augmented BNF [ABNF]
- // follows.
- //
- // message = [authzid] UTF8NUL authcid UTF8NUL passwd
- // authcid = 1*SAFE ; MUST accept up to 255 octets
- // authzid = 1*SAFE ; MUST accept up to 255 octets
- // passwd = 1*SAFE ; MUST accept up to 255 octets
- // UTF8NUL = %x00 ; UTF-8 encoded NUL character
- //
- // SAFE = UTF1 / UTF2 / UTF3 / UTF4
- // ;; any UTF-8 encoded Unicode character except NUL
- //
- // UTF1 = %x01-7F ;; except NUL
- // UTF2 = %xC2-DF UTF0
- // UTF3 = %xE0 %xA0-BF UTF0 / %xE1-EC 2(UTF0) /
- // %xED %x80-9F UTF0 / %xEE-EF 2(UTF0)
- // UTF4 = %xF0 %x90-BF 2(UTF0) / %xF1-F3 3(UTF0) /
- // %xF4 %x80-8F 2(UTF0)
- // UTF0 = %x80-BF
- int start = 0;
- int end = 0;
- int elementIdx = 0;
- try {
- for (byte b : response) {
- if (b == '\u0000') {
- // empty string, only authzid allows this
- if (end - start == 0) {
- if (elementIdx != 0) {
- throw new SaslException("null auth data");
- }
- } // data, wa-hoo
- else {
- String element = new String(response, start, end - start, "UTF-8");
- start = end + 1;
- switch (elementIdx) {
- case 0:
- authzID = element;
- break;
- case 1:
- authnID = element;
- break;
- default:
- throw new SaslException("Unexpected data in packet");
- }
- }
- elementIdx++;
- }
- end++;
- }
- if (start == end) {
- throw new SaslException("null auth data");
- }
- password = new String(response, start, end - start, "UTF-8");
- } catch (UnsupportedEncodingException e) {
- throw new SaslException("utf-8 encoding");
- }
- ExternalValidationCallback evc = new ExternalValidationCallback(authnID, password);
- AuthorizeCallback ac = new AuthorizeCallback(authnID, authzID);
- Callback[] cbList = new Callback[2];
- cbList[0] = evc;
- cbList[1] = ac;
- try {
- if (password == null || authnID == null) {
- throw new SaslException("null auth data");
- }
- cbh.handle(cbList);
- if (!evc.isValidated()) {
- throw new SaslException("cannot validate password");
- }
- if (!ac.isAuthorized()) {
- throw new SaslException("user not authorized");
- }
- complete = true;
- return null;
- } catch (UnsupportedCallbackException ex) {
- throw new SaslException("unsupported callback", ex);
- } catch (IOException e) {
- if (e instanceof SaslException) {
- throw (SaslException) e;
- }
- throw new SaslException("Callback error", e);
- }
- }
- public boolean isComplete() {
- return complete;
- }
- public String getAuthorizationID() {
- if (!complete) {
- throw new IllegalStateException("not complete");
- }
- return authID;
- }
- public byte[] unwrap(byte[] incoming, int offset, int len) {
- if (!complete) {
- throw new IllegalStateException("not complete");
- }
- final byte[] result = new byte[len];
- System.arraycopy(incoming, offset, result, 0, len);
- return result;
- }
- public byte[] wrap(byte[] outgoing, int offset, int len) {
- if (!complete) {
- throw new IllegalStateException("not complete");
- }
- final byte[] result = new byte[len];
- System.arraycopy(outgoing, offset, result, 0, len);
- return result;
- }
- public Object getNegotiatedProperty(String propName) {
- return null;
- }
- public void dispose() throws SaslException {
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement