1 /* 2 * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.jndi.ldap.sasl; 27 28 import javax.security.auth.callback.*; 29 import javax.security.sasl.RealmCallback; 30 import javax.security.sasl.RealmChoiceCallback; 31 import java.io.IOException; 32 33 /** 34 * DefaultCallbackHandler for satisfying NameCallback and 35 * PasswordCallback for an LDAP client. 36 * NameCallback is used for getting the authentication ID and is 37 * gotten from the java.naming.security.principal property. 38 * PasswordCallback is gotten from the java.naming.security.credentials 39 * property and must be of type String, char[] or byte[]. 40 * If byte[], it is assumed to have UTF-8 encoding. 41 * 42 * If the caller of getPassword() will be using the password as 43 * a byte array, then it should encode the char[] array returned by 44 * getPassword() into a byte[] using UTF-8. 45 * 46 * @author Rosanna Lee 47 */ 48 final class DefaultCallbackHandler implements CallbackHandler { 49 private char[] passwd; 50 private String authenticationID; 51 private String authRealm; 52 53 DefaultCallbackHandler(String principal, Object cred, String realm) 54 throws IOException { 55 authenticationID = principal; 56 authRealm = realm; 57 if (cred instanceof String) { 58 passwd = ((String)cred).toCharArray(); 59 } else if (cred instanceof char[]) { 60 passwd = ((char[])cred).clone(); 61 } else if (cred != null) { 62 // assume UTF-8 encoding 63 String orig = new String((byte[])cred, "UTF8"); 64 passwd = orig.toCharArray(); 65 } 66 } 67 68 public void handle(Callback[] callbacks) 69 throws IOException, UnsupportedCallbackException { 70 for (int i = 0; i < callbacks.length; i++) { 71 if (callbacks[i] instanceof NameCallback) { 72 ((NameCallback)callbacks[i]).setName(authenticationID); 73 74 } else if (callbacks[i] instanceof PasswordCallback) { 75 ((PasswordCallback)callbacks[i]).setPassword(passwd); 76 77 } else if (callbacks[i] instanceof RealmChoiceCallback) { 78 /* Deals with a choice of realms */ 79 String[] choices = 80 ((RealmChoiceCallback)callbacks[i]).getChoices(); 81 int selected = 0; 82 83 if (authRealm != null && authRealm.length() > 0) { 84 selected = -1; // no realm chosen 85 for (int j = 0; j < choices.length; j++) { 86 if (choices[j].equals(authRealm)) { 87 selected = j; 88 } 89 } 90 if (selected == -1) { 91 StringBuilder allChoices = new StringBuilder(); 92 for (int j = 0; j < choices.length; j++) { 93 allChoices.append(choices[j] + ","); 94 } 95 throw new IOException("Cannot match " + 96 "'java.naming.security.sasl.realm' property value, '" + 97 authRealm + "' with choices " + allChoices + 98 "in RealmChoiceCallback"); 99 } 100 } 101 102 ((RealmChoiceCallback)callbacks[i]).setSelectedIndex(selected); 103 104 } else if (callbacks[i] instanceof RealmCallback) { 105 /* 1 or 0 realms specified in challenge */ 106 RealmCallback rcb = (RealmCallback) callbacks[i]; 107 if (authRealm != null) { 108 rcb.setText(authRealm); // Use what user supplied 109 } else { 110 String defaultRealm = rcb.getDefaultText(); 111 if (defaultRealm != null) { 112 rcb.setText(defaultRealm); // Use what server supplied 113 } else { 114 rcb.setText(""); // Specify no realm 115 } 116 } 117 } else { 118 throw new UnsupportedCallbackException(callbacks[i]); 119 } 120 } 121 } 122 123 void clearPassword() { 124 if (passwd != null) { 125 for (int i = 0; i < passwd.length; i++) { 126 passwd[i] = '\0'; 127 } 128 passwd = null; 129 } 130 } 131 132 protected void finalize() throws Throwable { 133 clearPassword(); 134 } 135 }