Java tutorial
/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.hadoop.io.crypto.bee.key.sasl; import java.io.IOException; import java.net.URL; import java.util.Map; import java.util.TreeMap; import java.util.UUID; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.NameCallback; import javax.security.auth.callback.PasswordCallback; import javax.security.auth.callback.UnsupportedCallbackException; import javax.security.sasl.RealmCallback; import javax.security.sasl.Sasl; import javax.security.sasl.SaslClient; import javax.security.sasl.SaslException; import org.apache.commons.codec.binary.Base64; import org.apache.hadoop.io.crypto.bee.RestClient; import org.apache.hadoop.io.crypto.bee.key.sasl.common.KeyToken; import org.apache.hadoop.io.crypto.bee.key.sasl.common.SaslParam; import org.apache.hadoop.io.crypto.bee.key.sasl.common.SaslUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.gson.Gson; public class KeySaslClient { final Logger logger = LoggerFactory.getLogger(getClass()); private UUID uuid; // Each KeySaslServer has a unique ID. Server will send // back this ID to client while INIT KeyToken keyToken; SaslClient saslCli; // Each UUID map to a SaslServer SaslUtil.SaslAuthStatus saslAuthStatus; public KeySaslClient(KeyToken keyToken) throws SaslException { logger.debug("assign key token"); this.keyToken = keyToken; Map<String, String> propsClient = new TreeMap<String, String>(); propsClient.put(Sasl.QOP, "auth-conf"); saslCli = Sasl.createSaslClient(new String[] { "DIGEST-MD5" }, this.keyToken.getUser(), SaslUtil.KEY_SERVICE, SaslUtil.KEY_REALM, propsClient, new ClientCallbackHandler(this.keyToken)); saslAuthStatus = SaslUtil.SaslAuthStatus.AUTH_PROCESSING; } public UUID getUuid() { return uuid; } public void setUuid(UUID uuid) { this.uuid = uuid; } public byte[] auth(byte[] challenge) throws SaslException { byte[] response = saslCli.evaluateChallenge(challenge); if (saslCli.isComplete()) { this.saslAuthStatus = SaslUtil.SaslAuthStatus.AUTH_SUCCESS; } return response; } /** * @return the saslAuthStatus */ public SaslUtil.SaslAuthStatus getSaslAuthStatus() { return saslAuthStatus; } public byte[] dataProcess(byte[] data) throws Exception { if (saslAuthStatus.equals(SaslUtil.SaslAuthStatus.AUTH_SUCCESS)) { return saslCli.wrap(data, 0, data.length); } else { throw new Exception("Still in Auth Process"); } } public byte[] dataUnwrap(byte[] data) throws Exception { return this.saslCli.unwrap(data, 0, data.length); } public byte[] dataUnwrap(SaslParam saslParam) throws Exception { byte[] data = saslParam.getdata(); return this.saslCli.unwrap(data, 0, data.length); } public SaslParam connection(String strBaseUrl, SaslParam saslParam) throws Exception { String strParam = new Gson().toJson(saslParam); String strUrl = strBaseUrl + Base64.encodeBase64URLSafeString(strParam.getBytes()); logger.debug("prepare to connect. strBaseUrl = " + strBaseUrl + ", strParam = " + strParam); URL url = new URL(strUrl); StringBuffer sb = new RestClient(url).getResult(); return new Gson().fromJson(sb.toString(), SaslParam.class); } } class ClientCallbackHandler implements CallbackHandler { final Logger logger = LoggerFactory.getLogger(getClass()); KeyToken keyToken; public ClientCallbackHandler(KeyToken keyToken) { this.keyToken = keyToken; } public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (int i = 0; i < callbacks.length; i++) { if (callbacks[i] instanceof NameCallback) { // logger.debug("set name"); NameCallback ncb = (NameCallback) callbacks[i]; ncb.setName(keyToken.getUser()); } else if (callbacks[i] instanceof PasswordCallback) { // logger.debug("set password"); PasswordCallback pcb = (PasswordCallback) callbacks[i]; pcb.setPassword(new String(keyToken.getPassword()).toCharArray()); // logger.debug("set password:" + // Hex.encodeHexString(keyToken.getPassword())); } else if (callbacks[i] instanceof RealmCallback) { // logger.debug("set realm"); RealmCallback rcb = (RealmCallback) callbacks[i]; rcb.setText(SaslUtil.KEY_REALM); } else { throw new UnsupportedCallbackException(callbacks[i]); } } } }