1d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/* 2d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 3d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Licensed to the Apache Software Foundation (ASF) under one 4d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * or more contributor license agreements. See the NOTICE file 5d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * distributed with this work for additional information 6d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * regarding copyright ownership. The ASF licenses this file 7d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * to you under the Apache License, Version 2.0 (the 8d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * "License"); you may not use this file except in compliance 9d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * with the License. You may obtain a copy of the License at 10d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 11d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * http://www.apache.org/licenses/LICENSE-2.0 12d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 13d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Unless required by applicable law or agreed to in writing, 14d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * software distributed under the License is distributed on an 15d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * KIND, either express or implied. See the License for the 17d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * specific language governing permissions and limitations 18d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * under the License. 19d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 20d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 21d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpackage org.apache.qpid.management.common.sasl; 22d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 23d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.apache.harmony.javax.security.auth.callback.Callback; 24d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.apache.harmony.javax.security.auth.callback.CallbackHandler; 25d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.apache.harmony.javax.security.auth.callback.NameCallback; 26d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.apache.harmony.javax.security.auth.callback.PasswordCallback; 27d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.apache.harmony.javax.security.auth.callback.UnsupportedCallbackException; 28d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport de.measite.smack.Sasl; 29d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.apache.harmony.javax.security.sasl.SaslClient; 30d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.apache.harmony.javax.security.sasl.SaslException; 31d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.io.IOException; 32d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.io.UnsupportedEncodingException; 33d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 34d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic class PlainSaslClient implements SaslClient 35d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen{ 36d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 37d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private boolean completed; 38d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private CallbackHandler cbh; 39d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private String authorizationID; 40d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private String authenticationID; 41d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private byte password[]; 42d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private static byte SEPARATOR = 0; 43d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 44d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public PlainSaslClient(String authorizationID, CallbackHandler cbh) throws SaslException 45d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen { 46d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen completed = false; 47d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.cbh = cbh; 48d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Object[] userInfo = getUserInfo(); 49d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.authorizationID = authorizationID; 50d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.authenticationID = (String) userInfo[0]; 51d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.password = (byte[]) userInfo[1]; 52d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (authenticationID == null || password == null) 53d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen { 54d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new SaslException("PLAIN: authenticationID and password must be specified"); 55d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 56d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 57d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 58d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public byte[] evaluateChallenge(byte[] challenge) throws SaslException 59d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen { 60d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (completed) 61d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen { 62d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalStateException("PLAIN: authentication already " + 63d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen "completed"); 64d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 65d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen completed = true; 66d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try 67d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen { 68d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen byte authzid[] = 69d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen authorizationID == null ? null : authorizationID.getBytes("UTF8"); 70d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen byte authnid[] = authenticationID.getBytes("UTF8"); 71d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen byte response[] = 72d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen new byte[ 73d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen password.length + 74d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen authnid.length + 75d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 2 + // SEPARATOR 76d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen (authzid != null ? authzid.length : 0) 77d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ]; 78d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen int size = 0; 79d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (authzid != null) { 80d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen System.arraycopy(authzid, 0, response, 0, authzid.length); 81d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen size = authzid.length; 82d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 83d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen response[size++] = SEPARATOR; 84d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen System.arraycopy(authnid, 0, response, size, authnid.length); 85d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen size += authnid.length; 86d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen response[size++] = SEPARATOR; 87d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen System.arraycopy(password, 0, response, size, password.length); 88d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen clearPassword(); 89d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return response; 90d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } catch (UnsupportedEncodingException e) { 91d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new SaslException("PLAIN: Cannot get UTF-8 encoding of ids", 92d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen e); 93d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 94d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 95d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 96d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public String getMechanismName() 97d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen { 98d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return "PLAIN"; 99d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 100d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 101d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public boolean hasInitialResponse() 102d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen { 103d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return true; 104d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 105d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 106d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public boolean isComplete() 107d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen { 108d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return completed; 109d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 110d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 111d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public byte[] unwrap(byte[] incoming, int offset, int len) throws SaslException 112d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen { 113d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (completed) { 114d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalStateException("PLAIN: this mechanism supports " + 115d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen "neither integrity nor privacy"); 116d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } else { 117d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalStateException("PLAIN: authentication not " + 118d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen "completed"); 119d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 120d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 121d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 122d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public byte[] wrap(byte[] outgoing, int offset, int len) throws SaslException 123d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen { 124d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (completed) 125d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen { 126d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalStateException("PLAIN: this mechanism supports " + 127d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen "neither integrity nor privacy"); 128d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 129d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else 130d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen { 131d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalStateException("PLAIN: authentication not " + 132d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen "completed"); 133d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 134d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 135d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 136d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public Object getNegotiatedProperty(String propName) 137d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen { 138d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (completed) 139d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen { 140d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (propName.equals(Sasl.QOP)) 141d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen { 142d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return "auth"; 143d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 144d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else 145d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen { 146d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return null; 147d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 148d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 149d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else 150d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen { 151d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new IllegalStateException("PLAIN: authentication not " + 152d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen "completed"); 153d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 154d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 155d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 156d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private void clearPassword() 157d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen { 158d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (password != null) 159d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen { 160d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (int i = 0 ; i < password.length ; i++) 161d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen { 162d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen password[i] = 0; 163d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 164d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen password = null; 165d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 166d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 167d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 168d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void dispose() throws SaslException 169d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen { 170d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen clearPassword(); 171d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 172d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 173d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen protected void finalize() 174d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen { 175d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen clearPassword(); 176d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 177d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 178d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private Object[] getUserInfo() throws SaslException 179d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen { 180d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen try 181d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen { 182d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen final String userPrompt = "PLAIN authentication id: "; 183d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen final String pwPrompt = "PLAIN password: "; 184d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen NameCallback nameCb = new NameCallback(userPrompt); 185d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PasswordCallback passwordCb = new PasswordCallback(pwPrompt, false); 186d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen cbh.handle(new Callback[] { nameCb, passwordCb }); 187d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String userid = nameCb.getName(); 188d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen char pwchars[] = passwordCb.getPassword(); 189d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen byte pwbytes[]; 190d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (pwchars != null) 191d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen { 192d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen pwbytes = (new String(pwchars)).getBytes("UTF8"); 193d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen passwordCb.clearPassword(); 194d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 195d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen else 196d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen { 197d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen pwbytes = null; 198d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 199d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return (new Object[] { userid, pwbytes }); 200d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 201d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (IOException e) 202d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen { 203d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new SaslException("Cannot get password", e); 204d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 205d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen catch (UnsupportedCallbackException e) 206d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen { 207d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new SaslException("Cannot get userid/password", e); 208d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 209d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 210d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 211