View Javadoc
1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements. See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership. The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License. You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied. See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.wss4j.common;
20  
21  import java.io.IOException;
22  import java.lang.reflect.Method;
23  
24  import javax.security.auth.callback.Callback;
25  import javax.security.auth.callback.CallbackHandler;
26  import javax.security.auth.callback.NameCallback;
27  import javax.security.auth.callback.PasswordCallback;
28  import javax.security.auth.callback.UnsupportedCallbackException;
29  
30  public class NamePasswordCallbackHandler implements CallbackHandler {
31  
32      private static final org.slf4j.Logger LOG =
33          org.slf4j.LoggerFactory.getLogger(NamePasswordCallbackHandler.class);
34  
35      private static final String PASSWORD_CALLBACK_NAME = "setObject";
36      private static final Class<?>[] PASSWORD_CALLBACK_TYPES =
37          new Class<?>[]{Object.class, char[].class, String.class};
38  
39      private String username;
40      private String password;
41  
42      private String passwordCallbackName;
43  
44      public NamePasswordCallbackHandler(String username, String password) {
45          this(username, password, null);
46      }
47  
48      public NamePasswordCallbackHandler(String username, String password, String passwordCallbackName) {
49          this.username = username;
50          this.password = password;
51          this.passwordCallbackName = passwordCallbackName;
52      }
53  
54      public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
55          for (Callback callback : callbacks) {
56              if (handleCallback(callback)) {
57                  continue;
58              } else if (callback instanceof NameCallback) {
59                  ((NameCallback) callback).setName(username);
60              } else if (callback instanceof PasswordCallback) {
61                  PasswordCallback pwCallback = (PasswordCallback) callback;
62                  pwCallback.setPassword(password.toCharArray());
63              } else if (!invokePasswordCallback(callback)) {
64                  LOG.info("Unsupported callback type " + callback.getClass().getName());
65                  throw new UnsupportedCallbackException(callback, "Unsupported callback type "
66                      + callback.getClass().getName());
67              }
68          }
69      }
70  
71      protected boolean handleCallback(Callback callback) {
72          return false;
73      }
74  
75      /*
76       * This method is called from the handle(Callback[]) method when the specified callback
77       * did not match any of the known callback classes. It looks for the callback method
78       * having the specified method name with one of the supported parameter types.
79       * If found, it invokes the callback method on the object and returns true.
80       * If not, it returns false.
81       */
82      @SuppressWarnings("InexactVarargsConditional")
83      private boolean invokePasswordCallback(Callback callback) {
84          String cbname = passwordCallbackName == null
85                          ? PASSWORD_CALLBACK_NAME : passwordCallbackName;
86          for (Class<?> arg : PASSWORD_CALLBACK_TYPES) {
87              try {
88                  Method method = callback.getClass().getMethod(cbname, arg);
89                  method.invoke(callback, arg == String.class ? password : password.toCharArray());
90                  return true;
91              } catch (Exception e) {
92                  // ignore and continue
93                  LOG.warn(e.toString());
94              }
95          }
96          return false;
97      }
98  
99  }
100