Back to home page

OSCL-LXR

 
 

    


0001 /**
0002  * Licensed to the Apache Software Foundation (ASF) under one
0003  * or more contributor license agreements.  See the NOTICE file
0004  * distributed with this work for additional information
0005  * regarding copyright ownership.  The ASF licenses this file
0006  * to you under the Apache License, Version 2.0 (the
0007  * "License"); you may not use this file except in compliance
0008  * with the License.  You may obtain a copy of the License at
0009  *
0010  *     http://www.apache.org/licenses/LICENSE-2.0
0011  *
0012  * Unless required by applicable law or agreed to in writing, software
0013  * distributed under the License is distributed on an "AS IS" BASIS,
0014  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0015  * See the License for the specific language governing permissions and
0016  * limitations under the License.
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  * Sun JDK only provides a PLAIN client and no server. This class implements the Plain SASL server
0039  * conforming to RFC #4616 (http://www.ietf.org/rfc/rfc4616.txt).
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       // parse the response
0061       // message   = [authzid] UTF8NUL authcid UTF8NUL passwd'
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       // validate response
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       // optional authzid
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           /* This is to fulfill the contract of the interface which states that an exception shall
0154              be thrown when a SaslServer cannot be created due to an error but null should be
0155              returned when a Server can't be created due to the parameters supplied. And the only
0156              thing PlainSaslServer can fail on is a non-supported authentication mechanism.
0157              That's why we return null instead of throwing the Exception */
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 }