Repository: cxf Updated Branches: refs/heads/3.0.x-fixes fe97922c9 -> 0a90b65a2
[CXF-6903]add a NameDigestPasswordCallbackHandler for JAASLoginInterceptor Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/0a90b65a Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/0a90b65a Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/0a90b65a Branch: refs/heads/3.0.x-fixes Commit: 0a90b65a2774694da7c738b08ab5fe253fb91a70 Parents: fe97922 Author: Freeman Fang <[email protected]> Authored: Tue May 17 14:10:17 2016 +0800 Committer: Freeman Fang <[email protected]> Committed: Tue May 17 14:10:17 2016 +0800 ---------------------------------------------------------------------- .../security/JAASLoginInterceptor.java | 16 ++- .../NameDigestPasswordCallbackHandler.java | 122 +++++++++++++++++++ 2 files changed, 135 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/0a90b65a/core/src/main/java/org/apache/cxf/interceptor/security/JAASLoginInterceptor.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/cxf/interceptor/security/JAASLoginInterceptor.java b/core/src/main/java/org/apache/cxf/interceptor/security/JAASLoginInterceptor.java index a48ead9..7c0549a 100644 --- a/core/src/main/java/org/apache/cxf/interceptor/security/JAASLoginInterceptor.java +++ b/core/src/main/java/org/apache/cxf/interceptor/security/JAASLoginInterceptor.java @@ -113,6 +113,8 @@ public class JAASLoginInterceptor extends AbstractPhaseInterceptor<Message> { String name = null; String password = null; + String nonce = null; + String createdTime = null; AuthorizationPolicy policy = message.get(AuthorizationPolicy.class); if (policy != null) { @@ -125,6 +127,10 @@ public class JAASLoginInterceptor extends AbstractPhaseInterceptor<Message> { UsernameToken ut = (UsernameToken)token; name = ut.getName(); password = ut.getPassword(); + if (ut.getPasswordType().endsWith("PasswordDigest")) { + nonce = ut.getNonce(); + createdTime = ut.getCreatedTime(); + } } } @@ -133,7 +139,7 @@ public class JAASLoginInterceptor extends AbstractPhaseInterceptor<Message> { } try { - CallbackHandler handler = getCallbackHandler(name, password); + CallbackHandler handler = getCallbackHandler(name, password, nonce, createdTime); LoginContext ctx = new LoginContext(getContextName(), null, handler, loginConfig); ctx.login(); @@ -168,8 +174,12 @@ public class JAASLoginInterceptor extends AbstractPhaseInterceptor<Message> { } } - protected CallbackHandler getCallbackHandler(String name, String password) { - return new NamePasswordCallbackHandler(name, password); + protected CallbackHandler getCallbackHandler(String name, String password, String nonce, String createdTime) { + if (nonce != null && createdTime != null) { + return new NameDigestPasswordCallbackHandler(name, password, nonce, createdTime); + } else { + return new NamePasswordCallbackHandler(name, password); + } } protected SecurityContext createSecurityContext(String name, Subject subject) { http://git-wip-us.apache.org/repos/asf/cxf/blob/0a90b65a/core/src/main/java/org/apache/cxf/interceptor/security/NameDigestPasswordCallbackHandler.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/cxf/interceptor/security/NameDigestPasswordCallbackHandler.java b/core/src/main/java/org/apache/cxf/interceptor/security/NameDigestPasswordCallbackHandler.java new file mode 100644 index 0000000..8b61574 --- /dev/null +++ b/core/src/main/java/org/apache/cxf/interceptor/security/NameDigestPasswordCallbackHandler.java @@ -0,0 +1,122 @@ +/** + * 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.cxf.interceptor.security; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.ResourceBundle; +import java.util.logging.Logger; + +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 org.apache.cxf.common.i18n.BundleUtils; +import org.apache.cxf.common.logging.LogUtils; + +public class NameDigestPasswordCallbackHandler implements CallbackHandler { + + private static final ResourceBundle BUNDLE = BundleUtils.getBundle(NameDigestPasswordCallbackHandler.class); + private static final Logger LOG = LogUtils.getL7dLogger(NameDigestPasswordCallbackHandler.class); + private static final String PASSWORD_CALLBACK_NAME = "setObject"; + private static final Class<?>[] PASSWORD_CALLBACK_TYPES = + new Class[]{Object.class, char[].class, String.class}; + + private String username; + private String password; + private String nonce; + private String createdTime; + + private String passwordCallbackName; + + public NameDigestPasswordCallbackHandler(String username, String password, String nonce, String createdTime) { + this(username, password, nonce, createdTime, null); + } + + public NameDigestPasswordCallbackHandler(String username, + String password, + String nonce, + String createdTime, + String passwordCallbackName) { + this.username = username; + this.password = password; + this.nonce = nonce; + this.createdTime = createdTime; + this.passwordCallbackName = passwordCallbackName; + } + + public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { + for (int i = 0; i < callbacks.length; i++) { + Callback callback = callbacks[i]; + if (handleCallback(callback)) { + continue; + } else if (callback instanceof NameCallback) { + ((NameCallback) callback).setName(username); + } else if (callback instanceof PasswordCallback) { + PasswordCallback pwCallback = (PasswordCallback) callback; + pwCallback.setPassword(password.toCharArray()); + } else if (!invokePasswordCallback(callback)) { + org.apache.cxf.common.i18n.Message errorMsg = + new org.apache.cxf.common.i18n.Message("UNSUPPORTED_CALLBACK_TYPE", + BUNDLE, + callbacks[i].getClass().getName()); + LOG.info(errorMsg.toString()); + throw new UnsupportedCallbackException(callbacks[i], errorMsg.toString()); + } + } + } + + protected boolean handleCallback(Callback callback) { + return false; + } + + /* + * This method is called from the handle(Callback[]) method when the specified callback + * did not match any of the known callback classes. It looks for the callback method + * having the specified method name with one of the suppported parameter types. + * If found, it invokes the callback method on the object and returns true. + * If not, it returns false. + */ + private boolean invokePasswordCallback(Callback callback) { + String cbname = passwordCallbackName == null + ? PASSWORD_CALLBACK_NAME : passwordCallbackName; + for (Class<?> arg : PASSWORD_CALLBACK_TYPES) { + try { + Method method = callback.getClass().getMethod(cbname, arg); + method.invoke(callback, arg == String.class ? password : password.toCharArray()); + return true; + } catch (Exception e) { + // ignore and continue + LOG.fine(e.toString()); + } + } + return false; + } + + public String getNonce() { + return this.nonce; + } + + public String getCreatedTime() { + return this.createdTime; + } + +}
