Hide Forgot
Description of problem: Sometimes, in Domain mode, an "autostart" server would not manage to connect the HostController at startup, failing with "javax.security.sasl.SaslException: Authentication failed: all available authentication mechanisms failed". This happens randomly (estimated frequency: around 1/20), and occurs in both of EAP 6.0.1 and EAP 6.1.0. Version-Release number of selected component (if applicable): How reproducible: Steps to Reproduce: 1. in the file host.xml delivered with the EAP, just replace <properties path="mgmt-users.properties" relative-to="jboss.domain.config.dir"/> by <jaas name="dummy_may_even_not_exist" /> 2. then configure a server in auto-start="true" 3. /path/to/eap6/bin/domain.sh 4. stop and restart domain.sh several times until you get the exception in the boot.log of the "auto-started" server1. Actual results: Expected results: Additional info:
In org.jboss.remoting3.remote.ClientConnectionOpenListener, a server instance sends 'response' which consists of authrization ID, "0x00", authentication ID, "0x00", and password.:- 427 if (response != null) { 428 sendBuffer.put(response); 429 } Sometimes, the password contains "0x00". In the host controller side, the received 'response' is splitted in org.jboss.sasl.plain.PlainSaslServer:- The 'split' method expects that the password does not contain "0x00". If it contains "0x00", it throws an exception. 137 // Find the password 138 nextNul = nextNul(message, startPos, false); 139 // Verify there is no nul after the password. 140 if (nextNul > -1) { 141 throw new SaslException("PLAIN: Invalid message format. (Too many delimiters)"); 142 }
The generated authkey should avoid 0x00 byte when it is randomly generated.
I found that password.equals(vpc.getPassword()) in line 579 of ServerInventoryImpl.java is FALSE, if authKey contains an unmapped UTF-8 char, ie, ed b0 b6. For example, When authKey={bd 1b ef 66 ed b0 b6 75 6a 85 10 12 dd 85 8f ff}, SaslException occurs.
The below works for me. diff --git a/host-controller/src/main/java/org/jboss/as/host/controller/ServerInventoryImpl.java b/host-controller/src/main/java/org/jboss/as/host/controller/ServerInventoryImpl.java index e10dc69..f1eaeb3 100644 --- a/host-controller/src/main/java/org/jboss/as/host/controller/ServerInventoryImpl.java +++ b/host-controller/src/main/java/org/jboss/as/host/controller/ServerInventoryImpl.java @@ -83,6 +83,8 @@ import org.jboss.sasl.util.UsernamePasswordHashUtil; public class ServerInventoryImpl implements ServerInventory { private static final Charset UTF_8 = Charset.forName("UTF-8"); + private static final int SPC = 0x20; + private static final int TILDE = 0x7e; /** The managed servers. */ private final ConcurrentMap<String, ManagedServer> servers = new ConcurrentHashMap<String, ManagedServer>(); @@ -177,7 +179,7 @@ public class ServerInventoryImpl implements ServerInventory { if(server == null) { // Create a new authKey final byte[] authKey = new byte[16]; - new Random(new SecureRandom().nextLong()).nextBytes(authKey); + storeRandomAsciiChar(authKey); // Create the managed server final ManagedServer newServer = createManagedServer(serverName, domainModel, authKey); server = servers.putIfAbsent(serverName, newServer); @@ -595,4 +597,10 @@ public class ServerInventoryImpl implements ServerInventory { }; } + static void storeRandomAsciiChar(byte[] authKey) { + Random rand = new Random(new SecureRandom().nextLong()); + for(int i =0; i < authKey.length; i++) { + authKey[i] = (byte)(SPC + rand.nextInt(TILDE-SPC+1)); + } + } } diff --git a/host-controller/src/test/java/org/jboss/as/host/controller/ServerInventoryImplTestCase.java b/host-controller/src/test/java/org/jboss/as/host/controller/ServerInventoryImplTestCase.java new file mode 100644 index 0000000..feb3c1d --- /dev/null +++ b/host-controller/src/test/java/org/jboss/as/host/controller/ServerInventoryImplTestCase.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2013 Red Hat, Inc., and individual contributors + * as indicated by the @author tags. See the copyright.txt file + * in the distribution for a full listing of individual contributors. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package org.jboss.as.host.controller; + +import java.io.UnsupportedEncodingException; +import java.util.Arrays; +import static org.hamcrest.CoreMatchers.is; +import org.junit.Assert; +import org.junit.Test; + +/** + * + * @author <a href="ehugonne">Emmanuel Hugonnet</a> (c) 2013 Red Hat, inc. + */ +public class ServerInventoryImplTestCase { + private static final String HEX_DIGITS = "0123456789abcdef"; + @Test + public void testStoreRandomeAsciiChar() throws Exception { + byte[] array = new byte[1000]; + boolean isok = true; + + ServerInventoryImpl.storeRandomAsciiChar(array); + for (byte b:array) { + if( b<0x20 || b>0x7e ) { + isok = false; + } + } + Assert.assertThat(isok, is(true)); + } +}
Emmanuel Hugonnet <ehugonne> updated the status of jira WFLY-1988 to Reopened
Emmanuel Hugonnet <ehugonne> made a comment on jira WFLY-1988 The problem is more global than just null char, but it happens with non ASCII chars in authKey.
":^A�����%?�R�","xuk�^[^L�~^T^N?'a^Y","^X�$?�~^?^_%w^R5@^S" are such 'failing' password. I don't understand how I got Strings that provide more than 16 bytes which is the authkey required length.
Using byte arrays to check for password equality instead of String fixes the bug
Verified on EAP 6.2.0.ER3