Bug 1003464

Summary: SaslException at startup in domain mode using JAAS for ManagementRealm
Product: [JBoss] JBoss Enterprise Application Platform 6 Reporter: Hisanobu Okuda <hokuda>
Component: Domain ManagementAssignee: Emmanuel Hugonnet (ehsavoie) <ehugonne>
Status: CLOSED CURRENTRELEASE QA Contact: Ondrej Lukas <olukas>
Severity: unspecified Docs Contact: Russell Dickenson <rdickens>
Priority: unspecified    
Version: 6.0.1CC: brian.stansberry, ehugonne, emuckenh
Target Milestone: ER1   
Target Release: EAP 6.2.0   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
: 1005004 1005670 1020568 (view as bug list) Environment:
Last Closed: 2013-12-15 16:20:23 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Bug Depends On:    
Bug Blocks: 1005004, 1005670, 1020568    

Description Hisanobu Okuda 2013-09-02 06:31:29 UTC
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:

Comment 1 Hisanobu Okuda 2013-09-02 06:43:25 UTC
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            }

Comment 3 Emmanuel Hugonnet (ehsavoie) 2013-09-03 09:52:59 UTC
The generated authkey should avoid 0x00 byte when it is randomly generated.

Comment 5 Hisanobu Okuda 2013-09-12 05:55:05 UTC
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.

Comment 6 Hisanobu Okuda 2013-09-12 06:50:05 UTC
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));
+    }
+}

Comment 7 JBoss JIRA Server 2013-09-12 11:21:53 UTC
Emmanuel Hugonnet <ehugonne> updated the status of jira WFLY-1988 to Reopened

Comment 8 JBoss JIRA Server 2013-09-12 11:21:53 UTC
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.

Comment 9 Emmanuel Hugonnet (ehsavoie) 2013-09-16 06:22:11 UTC
":^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.

Comment 10 Emmanuel Hugonnet (ehsavoie) 2013-09-16 14:15:01 UTC
Using byte arrays to check for password equality instead of String fixes the bug

Comment 12 Ondrej Lukas 2013-09-30 07:14:08 UTC
Verified on EAP 6.2.0.ER3