0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 package org.apache.hive.service.auth;
0019
0020 import java.io.IOException;
0021 import java.security.Provider;
0022 import java.util.ArrayDeque;
0023 import java.util.Deque;
0024 import java.util.Map;
0025 import javax.security.auth.callback.Callback;
0026 import javax.security.auth.callback.CallbackHandler;
0027 import javax.security.auth.callback.NameCallback;
0028 import javax.security.auth.callback.PasswordCallback;
0029 import javax.security.auth.callback.UnsupportedCallbackException;
0030 import javax.security.sasl.AuthorizeCallback;
0031 import javax.security.sasl.SaslException;
0032 import javax.security.sasl.SaslServer;
0033 import javax.security.sasl.SaslServerFactory;
0034
0035 import org.apache.hive.service.auth.AuthenticationProviderFactory.AuthMethods;
0036
0037
0038
0039
0040
0041 public class PlainSaslServer implements SaslServer {
0042
0043 public static final String PLAIN_METHOD = "PLAIN";
0044 private String user;
0045 private final CallbackHandler handler;
0046
0047 PlainSaslServer(CallbackHandler handler, String authMethodStr) throws SaslException {
0048 this.handler = handler;
0049 AuthMethods.getValidAuthMethod(authMethodStr);
0050 }
0051
0052 @Override
0053 public String getMechanismName() {
0054 return PLAIN_METHOD;
0055 }
0056
0057 @Override
0058 public byte[] evaluateResponse(byte[] response) throws SaslException {
0059 try {
0060
0061
0062
0063 Deque<String> tokenList = new ArrayDeque<String>();
0064 StringBuilder messageToken = new StringBuilder();
0065 for (byte b : response) {
0066 if (b == 0) {
0067 tokenList.addLast(messageToken.toString());
0068 messageToken = new StringBuilder();
0069 } else {
0070 messageToken.append((char) b);
0071 }
0072 }
0073 tokenList.addLast(messageToken.toString());
0074
0075
0076 if (tokenList.size() < 2 || tokenList.size() > 3) {
0077 throw new SaslException("Invalid message format");
0078 }
0079 String passwd = tokenList.removeLast();
0080 user = tokenList.removeLast();
0081
0082 String authzId;
0083 if (tokenList.isEmpty()) {
0084 authzId = user;
0085 } else {
0086 authzId = tokenList.removeLast();
0087 }
0088 if (user == null || user.isEmpty()) {
0089 throw new SaslException("No user name provided");
0090 }
0091 if (passwd == null || passwd.isEmpty()) {
0092 throw new SaslException("No password name provided");
0093 }
0094
0095 NameCallback nameCallback = new NameCallback("User");
0096 nameCallback.setName(user);
0097 PasswordCallback pcCallback = new PasswordCallback("Password", false);
0098 pcCallback.setPassword(passwd.toCharArray());
0099 AuthorizeCallback acCallback = new AuthorizeCallback(user, authzId);
0100
0101 Callback[] cbList = {nameCallback, pcCallback, acCallback};
0102 handler.handle(cbList);
0103 if (!acCallback.isAuthorized()) {
0104 throw new SaslException("Authentication failed");
0105 }
0106 } catch (IllegalStateException eL) {
0107 throw new SaslException("Invalid message format", eL);
0108 } catch (IOException eI) {
0109 throw new SaslException("Error validating the login", eI);
0110 } catch (UnsupportedCallbackException eU) {
0111 throw new SaslException("Error validating the login", eU);
0112 }
0113 return null;
0114 }
0115
0116 @Override
0117 public boolean isComplete() {
0118 return user != null;
0119 }
0120
0121 @Override
0122 public String getAuthorizationID() {
0123 return user;
0124 }
0125
0126 @Override
0127 public byte[] unwrap(byte[] incoming, int offset, int len) {
0128 throw new UnsupportedOperationException();
0129 }
0130
0131 @Override
0132 public byte[] wrap(byte[] outgoing, int offset, int len) {
0133 throw new UnsupportedOperationException();
0134 }
0135
0136 @Override
0137 public Object getNegotiatedProperty(String propName) {
0138 return null;
0139 }
0140
0141 @Override
0142 public void dispose() {}
0143
0144 public static class SaslPlainServerFactory implements SaslServerFactory {
0145
0146 @Override
0147 public SaslServer createSaslServer(String mechanism, String protocol, String serverName,
0148 Map<String, ?> props, CallbackHandler cbh) {
0149 if (PLAIN_METHOD.equals(mechanism)) {
0150 try {
0151 return new PlainSaslServer(cbh, protocol);
0152 } catch (SaslException e) {
0153
0154
0155
0156
0157
0158 return null;
0159 }
0160 }
0161 return null;
0162 }
0163
0164 @Override
0165 public String[] getMechanismNames(Map<String, ?> props) {
0166 return new String[] {PLAIN_METHOD};
0167 }
0168 }
0169
0170 public static class SaslPlainProvider extends Provider {
0171
0172 public SaslPlainProvider() {
0173 super("HiveSaslPlain", 1.0, "Hive Plain SASL provider");
0174 put("SaslServerFactory.PLAIN", SaslPlainServerFactory.class.getName());
0175 }
0176 }
0177 }